Merge tag 'drm-misc-next-2022-01-27' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
[airlied: add two missing Kconfig] drm-misc-next for v5.18: UAPI Changes: - Fix invalid IN_FORMATS blob when plane->format_mod_supported is NULL. Cross-subsystem Changes: - Assorted dt bindings updates. - Fix vga16fb vga checking on x86. - Fix extra semicolon in rwsem.h's _down_write_nest_lock. - Assorted small fixes to agp and fbdev drivers. - Fix oops in creating a udmabuf with 0 pages. - Hot-unplug firmware fb devices on forced removal - Reqquest memory region in simplefb and simpledrm, and don't make the ioresource as busy. Core Changes: - Mock a drm_plane in drm-plane-helper selftest. - Assorted bug fixes to device logging, dbi. - Use DP helper for sink count in mst. - Assorted documentation fixes. - Assorted small fixes. - Move DP headers to drm/dp, and add a drm dp helper module. - Move the buddy allocator from i915 to common drm. - Add simple pci and platform module init macros to remove a lot of boilerplate from some drivers. - Support microsoft extension for HMDs and specialized monitors. - Improve edid parser's deep color handling. - Add type 7 timing support to edid parser. - Add a weak backpointer to the ttm_bo from ttm_resource - Add 3 eDP panels. Driver Changes: - Add support for HDMI and JZ4780 to ingenic. - Add support for higher DP/eDP bitrates to nouveau. - Assorted driver fixes to tilcdc, vmwgfx, sn65dsi83, meson, stm, panfrost, v3d, gma500, vc4, virtio, mgag200, ast, radeon, amdgpu, nouveau, various bridge drivers. - Convert and revert exynos dsi support to bridge driver. - Add vcc supply regulator support for sn65dsi83. - More conversion of bridge/chipone-icn6211 to atomic. - Remove conflicting fb's from stm, and add support for new hw version. - Add device link in parade-ps8640 to fix suspend/resume. - Update Boe-tv110c9m init sequence. - Add wide screen support to AST2600. - Fix omapdrm implicit dma_buf fencing. - Add support for multiple overlay planes to vkms. - Convert bridge/anx7625 to atomic, add HDCP support, add eld support for audio, and fix HPD. - Add driver for ChromeOS privacy screen. - Handover display from firmware to vc4 more gracefully, and support nomodeset. - Add flexible and ycbcr pixel formats to stm/ltdc. - Convert exynos mipi dsi to atomic. - Add initial dual core group GPUs support to panfrost. - No longer add exclusive fence in amdgpu as shared fence. - Add CSC and full range supoprt to vc4. - Shutdown the display on system shutdown and unbind. - Add Multi-Inno Technology MI0700S4T-6 simple panel. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/456a23c6-7324-7543-0c45-751f30ef83f7@linux.intel.com
This commit is contained in:
@@ -39,6 +39,7 @@ properties:
|
|||||||
- const: lvds-encoder # Generic LVDS encoder compatible fallback
|
- const: lvds-encoder # Generic LVDS encoder compatible fallback
|
||||||
- items:
|
- items:
|
||||||
- enum:
|
- enum:
|
||||||
|
- ti,ds90cf364a # For the DS90CF364A FPD-Link LVDS Receiver
|
||||||
- ti,ds90cf384a # For the DS90CF384A FPD-Link LVDS Receiver
|
- ti,ds90cf384a # For the DS90CF384A FPD-Link LVDS Receiver
|
||||||
- const: lvds-decoder # Generic LVDS decoders compatible fallback
|
- const: lvds-decoder # Generic LVDS decoders compatible fallback
|
||||||
- enum:
|
- enum:
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ properties:
|
|||||||
maxItems: 1
|
maxItems: 1
|
||||||
description: GPIO specifier for bridge_en pin (active high).
|
description: GPIO specifier for bridge_en pin (active high).
|
||||||
|
|
||||||
|
vcc-supply:
|
||||||
|
description: A 1.8V power supply (see regulator/regulator.yaml).
|
||||||
|
|
||||||
ports:
|
ports:
|
||||||
$ref: /schemas/graph.yaml#/properties/ports
|
$ref: /schemas/graph.yaml#/properties/ports
|
||||||
|
|
||||||
@@ -91,7 +94,6 @@ properties:
|
|||||||
required:
|
required:
|
||||||
- compatible
|
- compatible
|
||||||
- reg
|
- reg
|
||||||
- enable-gpios
|
|
||||||
- ports
|
- ports
|
||||||
|
|
||||||
allOf:
|
allOf:
|
||||||
@@ -133,6 +135,7 @@ examples:
|
|||||||
reg = <0x2d>;
|
reg = <0x2d>;
|
||||||
|
|
||||||
enable-gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>;
|
enable-gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>;
|
||||||
|
vcc-supply = <®_sn65dsi83_1v8>;
|
||||||
|
|
||||||
ports {
|
ports {
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
|
|||||||
@@ -222,6 +222,8 @@ properties:
|
|||||||
- logictechno,lttd800480070-l6wh-rt
|
- logictechno,lttd800480070-l6wh-rt
|
||||||
# Mitsubishi "AA070MC01 7.0" WVGA TFT LCD panel
|
# Mitsubishi "AA070MC01 7.0" WVGA TFT LCD panel
|
||||||
- mitsubishi,aa070mc01-ca1
|
- 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 Technology Co.,Ltd MI1010AIT-1CP 10.1" 1280x800 LVDS IPS Cap Touch Mod.
|
||||||
- multi-inno,mi1010ait-1cp
|
- multi-inno,mi1010ait-1cp
|
||||||
# NEC LCD Technologies, Ltd. 12.1" WXGA (1280x800) LVDS TFT LCD panel
|
# 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#
|
$id: http://devicetree.org/schemas/display/panel/sony,acx424akp.yaml#
|
||||||
$schema: http://devicetree.org/meta-schemas/core.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:
|
maintainers:
|
||||||
- Linus Walleij <linus.walleij@linaro.org>
|
- Linus Walleij <linus.walleij@linaro.org>
|
||||||
@@ -14,7 +19,9 @@ allOf:
|
|||||||
|
|
||||||
properties:
|
properties:
|
||||||
compatible:
|
compatible:
|
||||||
const: sony,acx424akp
|
enum:
|
||||||
|
- sony,acx424akp
|
||||||
|
- sony,acx424akm
|
||||||
reg: true
|
reg: true
|
||||||
reset-gpios: true
|
reset-gpios: true
|
||||||
vddi-supply:
|
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
|
kernel log at initialization time and passes it to userspace through the
|
||||||
DRM_IOCTL_VERSION ioctl.
|
DRM_IOCTL_VERSION ioctl.
|
||||||
|
|
||||||
|
Module Initialization
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
.. kernel-doc:: include/drm/drm_module.h
|
||||||
|
:doc: overview
|
||||||
|
|
||||||
Managing Ownership of the Framebuffer Aperture
|
Managing Ownership of the Framebuffer Aperture
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -232,34 +232,34 @@ HDCP Helper Functions Reference
|
|||||||
Display Port 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
|
:doc: dp helpers
|
||||||
|
|
||||||
.. kernel-doc:: include/drm/drm_dp_helper.h
|
.. kernel-doc:: include/drm/dp/drm_dp_helper.h
|
||||||
:internal:
|
:internal:
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/drm_dp_helper.c
|
.. kernel-doc:: drivers/gpu/drm/dp/drm_dp.c
|
||||||
:export:
|
:export:
|
||||||
|
|
||||||
Display Port CEC Helper Functions Reference
|
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
|
:doc: dp cec helpers
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/drm_dp_cec.c
|
.. kernel-doc:: drivers/gpu/drm/dp/drm_dp_cec.c
|
||||||
:export:
|
:export:
|
||||||
|
|
||||||
Display Port Dual Mode Adaptor Helper Functions Reference
|
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
|
: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:
|
: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:
|
:export:
|
||||||
|
|
||||||
Display Port MST Helpers
|
Display Port MST Helpers
|
||||||
@@ -268,19 +268,19 @@ Display Port MST Helpers
|
|||||||
Overview
|
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
|
: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
|
:doc: Branch device and port refcounting
|
||||||
|
|
||||||
Functions Reference
|
Functions Reference
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
.. kernel-doc:: include/drm/drm_dp_mst_helper.h
|
.. kernel-doc:: include/drm/dp/drm_dp_mst_helper.h
|
||||||
:internal:
|
:internal:
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/drm_dp_mst_topology.c
|
.. kernel-doc:: drivers/gpu/drm/dp/drm_dp_mst_topology.c
|
||||||
:export:
|
:export:
|
||||||
|
|
||||||
Topology Lifetime Internals
|
Topology Lifetime Internals
|
||||||
@@ -289,7 +289,7 @@ Topology Lifetime Internals
|
|||||||
These functions aren't exported to drivers, but are documented here to help make
|
These functions aren't exported to drivers, but are documented here to help make
|
||||||
the MST topology helpers easier to understand
|
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
|
:functions: drm_dp_mst_topology_try_get_mstb drm_dp_mst_topology_get_mstb
|
||||||
drm_dp_mst_topology_put_mstb
|
drm_dp_mst_topology_put_mstb
|
||||||
drm_dp_mst_topology_try_get_port drm_dp_mst_topology_get_port
|
drm_dp_mst_topology_try_get_port drm_dp_mst_topology_get_port
|
||||||
|
|||||||
@@ -423,12 +423,12 @@ Connector Functions Reference
|
|||||||
Writeback Connectors
|
Writeback Connectors
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
.. kernel-doc:: include/drm/drm_writeback.h
|
|
||||||
:internal:
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/drm_writeback.c
|
.. kernel-doc:: drivers/gpu/drm/drm_writeback.c
|
||||||
:doc: overview
|
:doc: overview
|
||||||
|
|
||||||
|
.. kernel-doc:: include/drm/drm_writeback.h
|
||||||
|
:internal:
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/drm_writeback.c
|
.. kernel-doc:: drivers/gpu/drm/drm_writeback.c
|
||||||
:export:
|
: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
|
efficiently is thus crucial for the graphics stack and plays a central
|
||||||
role in the DRM infrastructure.
|
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
|
(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
|
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
|
solution. It provides a single userspace API to accommodate the need of
|
||||||
|
|||||||
@@ -467,6 +467,21 @@ Contact: Thomas Zimmermann <tzimmermann@suse.de>
|
|||||||
|
|
||||||
Level: Intermediate
|
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
|
Core refactorings
|
||||||
=================
|
=================
|
||||||
|
|||||||
@@ -124,8 +124,6 @@ Add Plane Features
|
|||||||
|
|
||||||
There's lots of plane features we could add support for:
|
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
|
- Clearing primary plane: clear primary plane before plane composition (at the
|
||||||
start) for correctness of pixel blend ops. It also guarantees alpha channel
|
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]
|
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)
|
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);
|
page_map->real = (unsigned long *) __get_free_page(GFP_KERNEL);
|
||||||
if (page_map->real == NULL)
|
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);
|
set_memory_uc((unsigned long)page_map->real, 1);
|
||||||
err = map_page_into_agp(virt_to_page(page_map->real));
|
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;
|
page_map->remapped = page_map->real;
|
||||||
|
|
||||||
for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) {
|
for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) {
|
||||||
@@ -303,7 +307,7 @@ static int ati_insert_memory(struct agp_memory * mem,
|
|||||||
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
|
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
|
||||||
addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
|
addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
|
||||||
cur_gatt = GET_GATT(addr);
|
cur_gatt = GET_GATT(addr);
|
||||||
writel(agp_bridge->driver->mask_memory(agp_bridge,
|
writel(agp_bridge->driver->mask_memory(agp_bridge,
|
||||||
page_to_phys(mem->pages[i]),
|
page_to_phys(mem->pages[i]),
|
||||||
mem->type),
|
mem->type),
|
||||||
cur_gatt+GET_GATT_OFF(addr));
|
cur_gatt+GET_GATT_OFF(addr));
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ EXPORT_SYMBOL(agp_find_bridge);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* agp_backend_acquire - attempt to acquire an agp backend.
|
* agp_backend_acquire - attempt to acquire an agp backend.
|
||||||
|
* @pdev: the PCI device
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct agp_bridge_data *agp_backend_acquire(struct pci_dev *pdev)
|
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.
|
* 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
|
* The caller must insure that the graphics aperture translation table
|
||||||
* is read for use by another entity.
|
* is read for use by another entity.
|
||||||
|
|||||||
@@ -39,7 +39,9 @@
|
|||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
#include "agp.h"
|
#include "agp.h"
|
||||||
|
#include "compat_ioctl.h"
|
||||||
|
|
||||||
struct agp_front_data agp_fe;
|
struct agp_front_data agp_fe;
|
||||||
|
|
||||||
@@ -1017,7 +1019,7 @@ static long agp_ioctl(struct file *file,
|
|||||||
case AGPIOC_UNBIND:
|
case AGPIOC_UNBIND:
|
||||||
ret_val = agpioc_unbind_wrap(curr_priv, (void __user *) arg);
|
ret_val = agpioc_unbind_wrap(curr_priv, (void __user *) arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AGPIOC_CHIPSET_FLUSH:
|
case AGPIOC_CHIPSET_FLUSH:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
static void nvidia_tlbflush(struct agp_memory *mem)
|
||||||
{
|
{
|
||||||
unsigned long end;
|
unsigned long end;
|
||||||
u32 wbc_reg, temp;
|
u32 wbc_reg;
|
||||||
|
u32 __maybe_unused temp;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* flush chipset */
|
/* flush chipset */
|
||||||
|
|||||||
@@ -262,13 +262,10 @@ static void serverworks_tlbflush(struct agp_memory *temp)
|
|||||||
|
|
||||||
static int serverworks_configure(void)
|
static int serverworks_configure(void)
|
||||||
{
|
{
|
||||||
struct aper_size_info_lvl2 *current_size;
|
|
||||||
u32 temp;
|
u32 temp;
|
||||||
u8 enable_reg;
|
u8 enable_reg;
|
||||||
u16 cap_reg;
|
u16 cap_reg;
|
||||||
|
|
||||||
current_size = A_SIZE_LVL2(agp_bridge->current_size);
|
|
||||||
|
|
||||||
/* Get the memory mapped registers */
|
/* Get the memory mapped registers */
|
||||||
pci_read_config_dword(agp_bridge->dev, serverworks_private.mm_addr_ofs, &temp);
|
pci_read_config_dword(agp_bridge->dev, serverworks_private.mm_addr_ofs, &temp);
|
||||||
temp = (temp & PCI_BASE_ADDRESS_MEM_MASK);
|
temp = (temp & PCI_BASE_ADDRESS_MEM_MASK);
|
||||||
@@ -350,7 +347,7 @@ static int serverworks_insert_memory(struct agp_memory *mem,
|
|||||||
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
|
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
|
||||||
addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
|
addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
|
||||||
cur_gatt = SVRWRKS_GET_GATT(addr);
|
cur_gatt = SVRWRKS_GET_GATT(addr);
|
||||||
writel(agp_bridge->driver->mask_memory(agp_bridge,
|
writel(agp_bridge->driver->mask_memory(agp_bridge,
|
||||||
page_to_phys(mem->pages[i]), mem->type),
|
page_to_phys(mem->pages[i]), mem->type),
|
||||||
cur_gatt+GET_GATT_OFF(addr));
|
cur_gatt+GET_GATT_OFF(addr));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,9 +128,6 @@ static int via_fetch_size_agp3(void)
|
|||||||
static int via_configure_agp3(void)
|
static int via_configure_agp3(void)
|
||||||
{
|
{
|
||||||
u32 temp;
|
u32 temp;
|
||||||
struct aper_size_info_16 *current_size;
|
|
||||||
|
|
||||||
current_size = A_SIZE_16(agp_bridge->current_size);
|
|
||||||
|
|
||||||
/* address to map to */
|
/* address to map to */
|
||||||
agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
|
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
|
* dma_resv_get_fences - Get an object's shared and exclusive
|
||||||
* fences without update side lock held
|
* fences without update side lock held
|
||||||
* @obj: the reservation object
|
* @obj: the reservation object
|
||||||
* @fence_excl: the returned exclusive fence (or NULL)
|
* @write: true if we should return all fences
|
||||||
* @shared_count: the number of shared fences returned
|
* @num_fences: the number of fences returned
|
||||||
* @shared: the array of shared fence ptrs returned (array is krealloc'd to
|
* @fences: the array of fence ptrs returned (array is krealloc'd to the
|
||||||
* the required size, and must be freed by caller)
|
* required size, and must be freed by caller)
|
||||||
*
|
*
|
||||||
* Retrieve all fences from the reservation object. If the pointer for the
|
* Retrieve all fences from the reservation object.
|
||||||
* exclusive fence is not specified the fence is put into the array of the
|
* Returns either zero or -ENOMEM.
|
||||||
* shared fences as well. Returns either zero or -ENOMEM.
|
|
||||||
*/
|
*/
|
||||||
int dma_resv_get_fences(struct dma_resv *obj, struct dma_fence **fence_excl,
|
int dma_resv_get_fences(struct dma_resv *obj, bool write,
|
||||||
unsigned int *shared_count, struct dma_fence ***shared)
|
unsigned int *num_fences, struct dma_fence ***fences)
|
||||||
{
|
{
|
||||||
struct dma_resv_iter cursor;
|
struct dma_resv_iter cursor;
|
||||||
struct dma_fence *fence;
|
struct dma_fence *fence;
|
||||||
|
|
||||||
*shared_count = 0;
|
*num_fences = 0;
|
||||||
*shared = NULL;
|
*fences = NULL;
|
||||||
|
|
||||||
if (fence_excl)
|
dma_resv_iter_begin(&cursor, obj, write);
|
||||||
*fence_excl = NULL;
|
|
||||||
|
|
||||||
dma_resv_iter_begin(&cursor, obj, true);
|
|
||||||
dma_resv_for_each_fence_unlocked(&cursor, fence) {
|
dma_resv_for_each_fence_unlocked(&cursor, fence) {
|
||||||
|
|
||||||
if (dma_resv_iter_is_restarted(&cursor)) {
|
if (dma_resv_iter_is_restarted(&cursor)) {
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
|
|
||||||
while (*shared_count)
|
while (*num_fences)
|
||||||
dma_fence_put((*shared)[--(*shared_count)]);
|
dma_fence_put((*fences)[--(*num_fences)]);
|
||||||
|
|
||||||
if (fence_excl)
|
count = cursor.shared_count + 1;
|
||||||
dma_fence_put(*fence_excl);
|
|
||||||
|
|
||||||
count = cursor.shared_count;
|
|
||||||
count += fence_excl ? 0 : 1;
|
|
||||||
|
|
||||||
/* Eventually re-allocate the array */
|
/* Eventually re-allocate the array */
|
||||||
*shared = krealloc_array(*shared, count,
|
*fences = krealloc_array(*fences, count,
|
||||||
sizeof(void *),
|
sizeof(void *),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (count && !*shared) {
|
if (count && !*fences) {
|
||||||
dma_resv_iter_end(&cursor);
|
dma_resv_iter_end(&cursor);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dma_fence_get(fence);
|
(*fences)[(*num_fences)++] = dma_fence_get(fence);
|
||||||
if (dma_resv_iter_is_exclusive(&cursor) && fence_excl)
|
|
||||||
*fence_excl = fence;
|
|
||||||
else
|
|
||||||
(*shared)[(*shared_count)++] = fence;
|
|
||||||
}
|
}
|
||||||
dma_resv_iter_end(&cursor);
|
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)
|
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;
|
struct dma_resv resv;
|
||||||
int r, i;
|
int r, i;
|
||||||
|
|
||||||
@@ -304,35 +304,19 @@ static int test_get_fences(void *arg, bool shared)
|
|||||||
}
|
}
|
||||||
dma_resv_unlock(&resv);
|
dma_resv_unlock(&resv);
|
||||||
|
|
||||||
r = dma_resv_get_fences(&resv, &excl, &i, &fences);
|
r = dma_resv_get_fences(&resv, shared, &i, &fences);
|
||||||
if (r) {
|
if (r) {
|
||||||
pr_err("get_fences failed\n");
|
pr_err("get_fences failed\n");
|
||||||
goto err_free;
|
goto err_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shared) {
|
if (i != 1 || fences[0] != f) {
|
||||||
if (excl != NULL) {
|
pr_err("get_fences returned unexpected fence\n");
|
||||||
pr_err("get_fences returned unexpected excl fence\n");
|
goto err_free;
|
||||||
goto err_free;
|
|
||||||
}
|
|
||||||
if (i != 1 || fences[0] != f) {
|
|
||||||
pr_err("get_fences returned unexpected shared 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);
|
dma_fence_signal(f);
|
||||||
err_free:
|
err_free:
|
||||||
dma_fence_put(excl);
|
|
||||||
while (i--)
|
while (i--)
|
||||||
dma_fence_put(fences[i]);
|
dma_fence_put(fences[i]);
|
||||||
kfree(fences);
|
kfree(fences);
|
||||||
|
|||||||
@@ -190,6 +190,10 @@ static long udmabuf_create(struct miscdevice *device,
|
|||||||
if (ubuf->pagecount > pglimit)
|
if (ubuf->pagecount > pglimit)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ubuf->pagecount)
|
||||||
|
goto err;
|
||||||
|
|
||||||
ubuf->pages = kmalloc_array(ubuf->pagecount, sizeof(*ubuf->pages),
|
ubuf->pages = kmalloc_array(ubuf->pagecount, sizeof(*ubuf->pages),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!ubuf->pages) {
|
if (!ubuf->pages) {
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ __init int sysfb_create_simplefb(const struct screen_info *si,
|
|||||||
|
|
||||||
/* setup IORESOURCE_MEM as framebuffer memory */
|
/* setup IORESOURCE_MEM as framebuffer memory */
|
||||||
memset(&res, 0, sizeof(res));
|
memset(&res, 0, sizeof(res));
|
||||||
res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
|
res.flags = IORESOURCE_MEM;
|
||||||
res.name = simplefb_resname;
|
res.name = simplefb_resname;
|
||||||
res.start = base;
|
res.start = base;
|
||||||
res.end = res.start + length - 1;
|
res.end = res.start + length - 1;
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ config DRM_DEBUG_SELFTEST
|
|||||||
depends on DRM
|
depends on DRM
|
||||||
depends on DEBUG_KERNEL
|
depends on DEBUG_KERNEL
|
||||||
select PRIME_NUMBERS
|
select PRIME_NUMBERS
|
||||||
|
select DRM_DP_HELPER
|
||||||
select DRM_LIB_RANDOM
|
select DRM_LIB_RANDOM
|
||||||
select DRM_KMS_HELPER
|
select DRM_KMS_HELPER
|
||||||
select DRM_EXPORT_FOR_TESTS if m
|
select DRM_EXPORT_FOR_TESTS if m
|
||||||
@@ -80,6 +81,12 @@ config DRM_DEBUG_SELFTEST
|
|||||||
|
|
||||||
If in doubt, say "N".
|
If in doubt, say "N".
|
||||||
|
|
||||||
|
config DRM_DP_HELPER
|
||||||
|
tristate
|
||||||
|
depends on DRM
|
||||||
|
help
|
||||||
|
DRM helpers for DisplayPort.
|
||||||
|
|
||||||
config DRM_KMS_HELPER
|
config DRM_KMS_HELPER
|
||||||
tristate
|
tristate
|
||||||
depends on DRM
|
depends on DRM
|
||||||
@@ -198,6 +205,12 @@ config DRM_TTM
|
|||||||
GPU memory types. Will be enabled automatically if a device driver
|
GPU memory types. Will be enabled automatically if a device driver
|
||||||
uses it.
|
uses it.
|
||||||
|
|
||||||
|
config DRM_BUDDY
|
||||||
|
tristate
|
||||||
|
depends on DRM
|
||||||
|
help
|
||||||
|
A page based buddy allocator
|
||||||
|
|
||||||
config DRM_VRAM_HELPER
|
config DRM_VRAM_HELPER
|
||||||
tristate
|
tristate
|
||||||
depends on DRM
|
depends on DRM
|
||||||
@@ -236,6 +249,7 @@ config DRM_RADEON
|
|||||||
depends on DRM && PCI && MMU
|
depends on DRM && PCI && MMU
|
||||||
depends on AGP || !AGP
|
depends on AGP || !AGP
|
||||||
select FW_LOADER
|
select FW_LOADER
|
||||||
|
select DRM_DP_HELPER
|
||||||
select DRM_KMS_HELPER
|
select DRM_KMS_HELPER
|
||||||
select DRM_TTM
|
select DRM_TTM
|
||||||
select DRM_TTM_HELPER
|
select DRM_TTM_HELPER
|
||||||
@@ -256,6 +270,7 @@ config DRM_AMDGPU
|
|||||||
tristate "AMD GPU"
|
tristate "AMD GPU"
|
||||||
depends on DRM && PCI && MMU
|
depends on DRM && PCI && MMU
|
||||||
select FW_LOADER
|
select FW_LOADER
|
||||||
|
select DRM_DP_HELPER
|
||||||
select DRM_KMS_HELPER
|
select DRM_KMS_HELPER
|
||||||
select DRM_SCHED
|
select DRM_SCHED
|
||||||
select DRM_TTM
|
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_LOAD_EDID_FIRMWARE) += drm_edid_load.o
|
||||||
drm-$(CONFIG_DRM_PRIVACY_SCREEN) += drm_privacy_screen.o drm_privacy_screen_x86.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
|
obj-$(CONFIG_DRM_NOMODESET) += drm_nomodeset.o
|
||||||
|
|
||||||
drm_cma_helper-y := drm_gem_cma_helper.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
|
drm_shmem_helper-y := drm_gem_shmem_helper.o
|
||||||
obj-$(CONFIG_DRM_GEM_SHMEM_HELPER) += drm_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
|
drm_vram_helper-y := drm_gem_vram_helper.o
|
||||||
obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o
|
obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o
|
||||||
|
|
||||||
drm_ttm_helper-y := drm_gem_ttm_helper.o
|
drm_ttm_helper-y := drm_gem_ttm_helper.o
|
||||||
obj-$(CONFIG_DRM_TTM_HELPER) += drm_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_dsc.o drm_encoder_slave.o drm_flip_work.o drm_hdcp.o \
|
||||||
drm_probe_helper.o \
|
drm_probe_helper.o \
|
||||||
drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
|
drm_plane_helper.o drm_atomic_helper.o \
|
||||||
drm_kms_helper_common.o drm_dp_dual_mode_helper.o \
|
drm_kms_helper_common.o \
|
||||||
drm_simple_kms_helper.o drm_modeset_helper.o \
|
drm_simple_kms_helper.o drm_modeset_helper.o \
|
||||||
drm_scdc_helper.o drm_gem_atomic_helper.o \
|
drm_scdc_helper.o drm_gem_atomic_helper.o \
|
||||||
drm_gem_framebuffer_helper.o \
|
drm_gem_framebuffer_helper.o \
|
||||||
drm_atomic_state_helper.o drm_damage_helper.o \
|
drm_atomic_state_helper.o drm_damage_helper.o \
|
||||||
drm_format_helper.o drm_self_refresh_helper.o drm_rect.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_PANEL_BRIDGE) += bridge/panel.o
|
||||||
drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.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_KMS_HELPER) += drm_kms_helper.o
|
||||||
obj-$(CONFIG_DRM_DEBUG_SELFTEST) += selftests/
|
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_MIPI_DSI) += drm_mipi_dsi.o
|
||||||
obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o
|
obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o
|
||||||
obj-y += arm/
|
obj-y += arm/
|
||||||
|
obj-y += dp/
|
||||||
obj-$(CONFIG_DRM_TTM) += ttm/
|
obj-$(CONFIG_DRM_TTM) += ttm/
|
||||||
obj-$(CONFIG_DRM_SCHED) += scheduler/
|
obj-$(CONFIG_DRM_SCHED) += scheduler/
|
||||||
obj-$(CONFIG_DRM_TDFX) += tdfx/
|
obj-$(CONFIG_DRM_TDFX) += tdfx/
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
#include <drm/drm_edid.h>
|
#include <drm/drm_edid.h>
|
||||||
#include <drm/drm_fb_helper.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/drm_probe_helper.h>
|
||||||
#include <drm/amdgpu_drm.h>
|
#include <drm/amdgpu_drm.h>
|
||||||
#include "amdgpu.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 */
|
/* Check if bpc is within clock limit. Try to degrade gracefully otherwise */
|
||||||
if ((bpc == 12) && (mode_clock * 3/2 > max_tmds_clock)) {
|
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))
|
(mode_clock * 5/4 <= max_tmds_clock))
|
||||||
bpc = 10;
|
bpc = 10;
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1274,14 +1274,11 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
|
|||||||
/*
|
/*
|
||||||
* Work around dma_resv shortcommings by wrapping up the
|
* Work around dma_resv shortcommings by wrapping up the
|
||||||
* submission in a dma_fence_chain and add it as exclusive
|
* submission in a dma_fence_chain and add it as exclusive
|
||||||
* fence, but first add the submission as shared fence to make
|
* fence.
|
||||||
* sure that shared fences never signal before the exclusive
|
|
||||||
* one.
|
|
||||||
*/
|
*/
|
||||||
dma_fence_chain_init(chain, dma_resv_excl_fence(resv),
|
dma_fence_chain_init(chain, dma_resv_excl_fence(resv),
|
||||||
dma_fence_get(p->fence), 1);
|
dma_fence_get(p->fence), 1);
|
||||||
|
|
||||||
dma_resv_add_shared_fence(resv, p->fence);
|
|
||||||
rcu_assign_pointer(resv->fence_excl, &chain->base);
|
rcu_assign_pointer(resv->fence_excl, &chain->base);
|
||||||
e->chain = NULL;
|
e->chain = NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,8 +200,10 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc,
|
|||||||
goto unpin;
|
goto unpin;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = dma_resv_get_fences(new_abo->tbo.base.resv, NULL,
|
/* TODO: Unify this with other drivers */
|
||||||
&work->shared_count, &work->shared);
|
r = dma_resv_get_fences(new_abo->tbo.base.resv, true,
|
||||||
|
&work->shared_count,
|
||||||
|
&work->shared);
|
||||||
if (unlikely(r != 0)) {
|
if (unlikely(r != 0)) {
|
||||||
DRM_ERROR("failed to get fences for buffer\n");
|
DRM_ERROR("failed to get fences for buffer\n");
|
||||||
goto unpin;
|
goto unpin;
|
||||||
|
|||||||
@@ -226,12 +226,6 @@ static void amdgpu_gem_object_close(struct drm_gem_object *obj,
|
|||||||
if (!amdgpu_vm_ready(vm))
|
if (!amdgpu_vm_ready(vm))
|
||||||
goto out_unlock;
|
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);
|
r = amdgpu_vm_clear_freed(adev, vm, &fence);
|
||||||
if (r || !fence)
|
if (r || !fence)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|||||||
@@ -167,6 +167,7 @@ static int amdgpu_gtt_mgr_new(struct ttm_resource_manager *man,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_free:
|
err_free:
|
||||||
|
ttm_resource_fini(man, &node->base.base);
|
||||||
kfree(node);
|
kfree(node);
|
||||||
|
|
||||||
err_out:
|
err_out:
|
||||||
@@ -198,6 +199,7 @@ static void amdgpu_gtt_mgr_del(struct ttm_resource_manager *man,
|
|||||||
if (!(res->placement & TTM_PL_FLAG_TEMPORARY))
|
if (!(res->placement & TTM_PL_FLAG_TEMPORARY))
|
||||||
atomic64_sub(res->num_pages, &mgr->used);
|
atomic64_sub(res->num_pages, &mgr->used);
|
||||||
|
|
||||||
|
ttm_resource_fini(man, res);
|
||||||
kfree(node);
|
kfree(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,7 +288,8 @@ int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size)
|
|||||||
man->use_tt = true;
|
man->use_tt = true;
|
||||||
man->func = &amdgpu_gtt_mgr_func;
|
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;
|
start = AMDGPU_GTT_MAX_TRANSFER_SIZE * AMDGPU_GTT_NUM_TRANSFER_WINDOWS;
|
||||||
size = (adev->gmc.gart_size >> PAGE_SHIFT) - start;
|
size = (adev->gmc.gart_size >> PAGE_SHIFT) - start;
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ void amdgpu_pasid_free_delayed(struct dma_resv *resv,
|
|||||||
unsigned count;
|
unsigned count;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = dma_resv_get_fences(resv, NULL, &count, &fences);
|
r = dma_resv_get_fences(resv, true, &count, &fences);
|
||||||
if (r)
|
if (r)
|
||||||
goto fallback;
|
goto fallback;
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
#include <drm/drm_crtc.h>
|
#include <drm/drm_crtc.h>
|
||||||
#include <drm/drm_edid.h>
|
#include <drm/drm_edid.h>
|
||||||
#include <drm/drm_encoder.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_fixed.h>
|
||||||
#include <drm/drm_crtc_helper.h>
|
#include <drm/drm_crtc_helper.h>
|
||||||
#include <drm/drm_fb_helper.h>
|
#include <drm/drm_fb_helper.h>
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
#include <linux/hrtimer.h>
|
#include <linux/hrtimer.h>
|
||||||
#include "amdgpu_irq.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 "modules/inc/mod_freesync.h"
|
||||||
#include "amdgpu_dm_irq_params.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);
|
struct amdgpu_preempt_mgr *mgr = to_preempt_mgr(man);
|
||||||
|
|
||||||
atomic64_sub(res->num_pages, &mgr->used);
|
atomic64_sub(res->num_pages, &mgr->used);
|
||||||
|
ttm_resource_fini(man, res);
|
||||||
kfree(res);
|
kfree(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,7 +153,7 @@ int amdgpu_preempt_mgr_init(struct amdgpu_device *adev)
|
|||||||
man->use_tt = true;
|
man->use_tt = true;
|
||||||
man->func = &amdgpu_preempt_mgr_func;
|
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);
|
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);
|
TTM_PL_VRAM);
|
||||||
struct drm_printer p = drm_seq_file_printer(m);
|
struct drm_printer p = drm_seq_file_printer(m);
|
||||||
|
|
||||||
man->func->debug(man, &p);
|
ttm_resource_manager_debug(man, &p);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2105,7 +2105,7 @@ static int amdgpu_mm_tt_table_show(struct seq_file *m, void *unused)
|
|||||||
TTM_PL_TT);
|
TTM_PL_TT);
|
||||||
struct drm_printer p = drm_seq_file_printer(m);
|
struct drm_printer p = drm_seq_file_printer(m);
|
||||||
|
|
||||||
man->func->debug(man, &p);
|
ttm_resource_manager_debug(man, &p);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2116,7 +2116,7 @@ static int amdgpu_mm_gds_table_show(struct seq_file *m, void *unused)
|
|||||||
AMDGPU_PL_GDS);
|
AMDGPU_PL_GDS);
|
||||||
struct drm_printer p = drm_seq_file_printer(m);
|
struct drm_printer p = drm_seq_file_printer(m);
|
||||||
|
|
||||||
man->func->debug(man, &p);
|
ttm_resource_manager_debug(man, &p);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2127,7 +2127,7 @@ static int amdgpu_mm_gws_table_show(struct seq_file *m, void *unused)
|
|||||||
AMDGPU_PL_GWS);
|
AMDGPU_PL_GWS);
|
||||||
struct drm_printer p = drm_seq_file_printer(m);
|
struct drm_printer p = drm_seq_file_printer(m);
|
||||||
|
|
||||||
man->func->debug(man, &p);
|
ttm_resource_manager_debug(man, &p);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2138,7 +2138,7 @@ static int amdgpu_mm_oa_table_show(struct seq_file *m, void *unused)
|
|||||||
AMDGPU_PL_OA);
|
AMDGPU_PL_OA);
|
||||||
struct drm_printer p = drm_seq_file_printer(m);
|
struct drm_printer p = drm_seq_file_printer(m);
|
||||||
|
|
||||||
man->func->debug(man, &p);
|
ttm_resource_manager_debug(man, &p);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -472,6 +472,7 @@ error_free:
|
|||||||
while (i--)
|
while (i--)
|
||||||
drm_mm_remove_node(&node->mm_nodes[i]);
|
drm_mm_remove_node(&node->mm_nodes[i]);
|
||||||
spin_unlock(&mgr->lock);
|
spin_unlock(&mgr->lock);
|
||||||
|
ttm_resource_fini(man, &node->base);
|
||||||
kvfree(node);
|
kvfree(node);
|
||||||
|
|
||||||
error_sub:
|
error_sub:
|
||||||
@@ -511,6 +512,7 @@ static void amdgpu_vram_mgr_del(struct ttm_resource_manager *man,
|
|||||||
atomic64_sub(usage, &mgr->usage);
|
atomic64_sub(usage, &mgr->usage);
|
||||||
atomic64_sub(vis_usage, &mgr->vis_usage);
|
atomic64_sub(vis_usage, &mgr->vis_usage);
|
||||||
|
|
||||||
|
ttm_resource_fini(man, res);
|
||||||
kvfree(node);
|
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 amdgpu_vram_mgr *mgr = &adev->mman.vram_mgr;
|
||||||
struct ttm_resource_manager *man = &mgr->manager;
|
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;
|
man->func = &amdgpu_vram_mgr_func;
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
#include "atombios_dp.h"
|
#include "atombios_dp.h"
|
||||||
#include "amdgpu_connectors.h"
|
#include "amdgpu_connectors.h"
|
||||||
#include "amdgpu_atombios.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 */
|
/* move these to drm_dp_helper.c/h */
|
||||||
#define DP_LINK_CONFIGURATION_SIZE 9
|
#define DP_LINK_CONFIGURATION_SIZE 9
|
||||||
|
|||||||
@@ -76,7 +76,7 @@
|
|||||||
#include <drm/drm_atomic.h>
|
#include <drm/drm_atomic.h>
|
||||||
#include <drm/drm_atomic_uapi.h>
|
#include <drm/drm_atomic_uapi.h>
|
||||||
#include <drm/drm_atomic_helper.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_fb_helper.h>
|
||||||
#include <drm/drm_fourcc.h>
|
#include <drm/drm_fourcc.h>
|
||||||
#include <drm/drm_edid.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)
|
else if (drm_mode_is_420_also(info, mode_in)
|
||||||
&& aconnector->force_yuv420_output)
|
&& aconnector->force_yuv420_output)
|
||||||
timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
|
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)
|
&& stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
|
||||||
timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444;
|
timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444;
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
#include <drm/drm_atomic.h>
|
#include <drm/drm_atomic.h>
|
||||||
#include <drm/drm_connector.h>
|
#include <drm/drm_connector.h>
|
||||||
#include <drm/drm_crtc.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>
|
#include <drm/drm_plane.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -25,8 +25,8 @@
|
|||||||
|
|
||||||
#include <drm/drm_atomic.h>
|
#include <drm/drm_atomic.h>
|
||||||
#include <drm/drm_atomic_helper.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_dp_helper.h>
|
#include <drm/dp/drm_dp_helper.h>
|
||||||
#include "dm_services.h"
|
#include "dm_services.h"
|
||||||
#include "amdgpu.h"
|
#include "amdgpu.h"
|
||||||
#include "amdgpu_dm.h"
|
#include "amdgpu_dm.h"
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
#include <dc_link.h>
|
#include <dc_link.h>
|
||||||
#include <inc/link_hwss.h>
|
#include <inc/link_hwss.h>
|
||||||
#include <inc/link_dpcd.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 <dc_dp_types.h>
|
||||||
#include "dm_helpers.h"
|
#include "dm_helpers.h"
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
#include <drm/drm_dsc.h>
|
#include <drm/drm_dsc.h>
|
||||||
#include "dc_hw_types.h"
|
#include "dc_hw_types.h"
|
||||||
#include "dsc.h"
|
#include "dsc.h"
|
||||||
#include <drm/drm_dp_helper.h>
|
#include <drm/dp/drm_dp_helper.h>
|
||||||
#include "dc.h"
|
#include "dc.h"
|
||||||
#include "rc_calc.h"
|
#include "rc_calc.h"
|
||||||
#include "fixed31_32.h"
|
#include "fixed31_32.h"
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
#include <asm/byteorder.h>
|
#include <asm/byteorder.h>
|
||||||
|
|
||||||
#include <drm/drm_print.h>
|
#include <drm/drm_print.h>
|
||||||
#include <drm/drm_dp_helper.h>
|
#include <drm/dp/drm_dp_helper.h>
|
||||||
|
|
||||||
#include "cgs_common.h"
|
#include "cgs_common.h"
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#ifndef __DAL_DPCD_DEFS_H__
|
#ifndef __DAL_DPCD_DEFS_H__
|
||||||
#define __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
|
#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
|
#define DP_SINK_HW_REVISION_START 0x409
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
#include "hdcp_log.h"
|
#include "hdcp_log.h"
|
||||||
|
|
||||||
#include <drm/drm_hdcp.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 {
|
enum mod_hdcp_trans_input_result {
|
||||||
UNKNOWN = 0,
|
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;
|
mask |= IPS_CTRL_YUV | IPS_CTRL_CHD422 | IPS_CTRL_CHD420;
|
||||||
|
|
||||||
/* config color format */
|
/* 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;
|
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;
|
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;
|
ctrl |= IPS_CTRL_YUV;
|
||||||
|
|
||||||
malidp_write32_mask(reg, BLK_CONTROL, mask, ctrl);
|
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 = to_improc(c);
|
||||||
improc->supported_color_depths = BIT(8) | BIT(10);
|
improc->supported_color_depths = BIT(8) | BIT(10);
|
||||||
improc->supported_color_formats = DRM_COLOR_FORMAT_RGB444 |
|
improc->supported_color_formats = DRM_COLOR_FORMAT_RGB444 |
|
||||||
DRM_COLOR_FORMAT_YCRCB444 |
|
DRM_COLOR_FORMAT_YCBCR444 |
|
||||||
DRM_COLOR_FORMAT_YCRCB422;
|
DRM_COLOR_FORMAT_YCBCR422;
|
||||||
value = malidp_read32(reg, BLK_INFO);
|
value = malidp_read32(reg, BLK_INFO);
|
||||||
if (value & IPS_INFO_CHD420)
|
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_csc = true;
|
||||||
improc->supports_gamma = true;
|
improc->supports_gamma = true;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/component.h>
|
#include <linux/component.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <drm/drm_module.h>
|
||||||
#include <drm/drm_of.h>
|
#include <drm/drm_of.h>
|
||||||
#include "komeda_dev.h"
|
#include "komeda_dev.h"
|
||||||
#include "komeda_kms.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_AUTHOR("James.Qian.Wang <james.qian.wang@arm.com>");
|
||||||
MODULE_DESCRIPTION("Komeda KMS driver");
|
MODULE_DESCRIPTION("Komeda KMS driver");
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include <drm/drm_gem_cma_helper.h>
|
#include <drm/drm_gem_cma_helper.h>
|
||||||
#include <drm/drm_gem_framebuffer_helper.h>
|
#include <drm/drm_gem_framebuffer_helper.h>
|
||||||
#include <drm/drm_modeset_helper.h>
|
#include <drm/drm_modeset_helper.h>
|
||||||
|
#include <drm/drm_module.h>
|
||||||
#include <drm/drm_of.h>
|
#include <drm/drm_of.h>
|
||||||
#include <drm/drm_probe_helper.h>
|
#include <drm/drm_probe_helper.h>
|
||||||
#include <drm/drm_vblank.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_AUTHOR("Liviu Dudau");
|
||||||
MODULE_DESCRIPTION("ARM HDLCD DRM driver");
|
MODULE_DESCRIPTION("ARM HDLCD DRM driver");
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include <drm/drm_gem_cma_helper.h>
|
#include <drm/drm_gem_cma_helper.h>
|
||||||
#include <drm/drm_gem_framebuffer_helper.h>
|
#include <drm/drm_gem_framebuffer_helper.h>
|
||||||
#include <drm/drm_modeset_helper.h>
|
#include <drm/drm_modeset_helper.h>
|
||||||
|
#include <drm/drm_module.h>
|
||||||
#include <drm/drm_of.h>
|
#include <drm/drm_of.h>
|
||||||
#include <drm/drm_probe_helper.h>
|
#include <drm/drm_probe_helper.h>
|
||||||
#include <drm/drm_vblank.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_AUTHOR("Liviu Dudau <Liviu.Dudau@arm.com>");
|
||||||
MODULE_DESCRIPTION("ARM Mali DP DRM driver");
|
MODULE_DESCRIPTION("ARM Mali DP DRM driver");
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#include <drm/drm_crtc_helper.h>
|
#include <drm/drm_crtc_helper.h>
|
||||||
#include <drm/drm_drv.h>
|
#include <drm/drm_drv.h>
|
||||||
#include <drm/drm_gem_vram_helper.h>
|
#include <drm/drm_gem_vram_helper.h>
|
||||||
|
#include <drm/drm_module.h>
|
||||||
#include <drm/drm_probe_helper.h>
|
#include <drm/drm_probe_helper.h>
|
||||||
|
|
||||||
#include "ast_drv.h"
|
#include "ast_drv.h"
|
||||||
@@ -230,22 +231,7 @@ static struct pci_driver ast_pci_driver = {
|
|||||||
.driver.pm = &ast_pm_ops,
|
.driver.pm = &ast_pm_ops,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init ast_init(void)
|
drm_module_pci_driver_if_modeset(ast_pci_driver, ast_modeset);
|
||||||
{
|
|
||||||
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);
|
|
||||||
|
|
||||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||||
|
|||||||
@@ -209,6 +209,8 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
|
|||||||
if (ast->chip == AST2500 &&
|
if (ast->chip == AST2500 &&
|
||||||
scu_rev == 0x100) /* ast2510 */
|
scu_rev == 0x100) /* ast2510 */
|
||||||
ast->support_wide_screen = true;
|
ast->support_wide_screen = true;
|
||||||
|
if (ast->chip == AST2600) /* ast2600 */
|
||||||
|
ast->support_wide_screen = true;
|
||||||
}
|
}
|
||||||
break;
|
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)
|
static void ast_set_crtthd_reg(struct ast_private *ast)
|
||||||
{
|
{
|
||||||
/* Set Threshold */
|
/* 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->chip == AST2500) {
|
||||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x78);
|
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x78);
|
||||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x60);
|
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x60);
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ config DRM_CDNS_DSI
|
|||||||
config DRM_CHIPONE_ICN6211
|
config DRM_CHIPONE_ICN6211
|
||||||
tristate "Chipone ICN6211 MIPI-DSI/RGB Converter bridge"
|
tristate "Chipone ICN6211 MIPI-DSI/RGB Converter bridge"
|
||||||
depends on OF
|
depends on OF
|
||||||
|
depends on DRM_KMS_HELPER
|
||||||
select DRM_MIPI_DSI
|
select DRM_MIPI_DSI
|
||||||
select DRM_PANEL_BRIDGE
|
select DRM_PANEL_BRIDGE
|
||||||
help
|
help
|
||||||
@@ -183,6 +184,7 @@ config DRM_PARADE_PS8640
|
|||||||
tristate "Parade PS8640 MIPI DSI to eDP Converter"
|
tristate "Parade PS8640 MIPI DSI to eDP Converter"
|
||||||
depends on OF
|
depends on OF
|
||||||
select DRM_DP_AUX_BUS
|
select DRM_DP_AUX_BUS
|
||||||
|
select DRM_DP_HELPER
|
||||||
select DRM_KMS_HELPER
|
select DRM_KMS_HELPER
|
||||||
select DRM_MIPI_DSI
|
select DRM_MIPI_DSI
|
||||||
select DRM_PANEL
|
select DRM_PANEL
|
||||||
@@ -253,6 +255,7 @@ config DRM_TOSHIBA_TC358764
|
|||||||
config DRM_TOSHIBA_TC358767
|
config DRM_TOSHIBA_TC358767
|
||||||
tristate "Toshiba TC358767 eDP bridge"
|
tristate "Toshiba TC358767 eDP bridge"
|
||||||
depends on OF
|
depends on OF
|
||||||
|
select DRM_DP_HELPER
|
||||||
select DRM_KMS_HELPER
|
select DRM_KMS_HELPER
|
||||||
select REGMAP_I2C
|
select REGMAP_I2C
|
||||||
select DRM_PANEL
|
select DRM_PANEL
|
||||||
@@ -272,6 +275,7 @@ config DRM_TOSHIBA_TC358768
|
|||||||
config DRM_TOSHIBA_TC358775
|
config DRM_TOSHIBA_TC358775
|
||||||
tristate "Toshiba TC358775 DSI/LVDS bridge"
|
tristate "Toshiba TC358775 DSI/LVDS bridge"
|
||||||
depends on OF
|
depends on OF
|
||||||
|
select DRM_DP_HELPER
|
||||||
select DRM_KMS_HELPER
|
select DRM_KMS_HELPER
|
||||||
select REGMAP_I2C
|
select REGMAP_I2C
|
||||||
select DRM_PANEL
|
select DRM_PANEL
|
||||||
@@ -299,6 +303,7 @@ config DRM_TI_SN65DSI83
|
|||||||
config DRM_TI_SN65DSI86
|
config DRM_TI_SN65DSI86
|
||||||
tristate "TI SN65DSI86 DSI to eDP bridge"
|
tristate "TI SN65DSI86 DSI to eDP bridge"
|
||||||
depends on OF
|
depends on OF
|
||||||
|
select DRM_DP_HELPER
|
||||||
select DRM_KMS_HELPER
|
select DRM_KMS_HELPER
|
||||||
select REGMAP_I2C
|
select REGMAP_I2C
|
||||||
select DRM_PANEL
|
select DRM_PANEL
|
||||||
|
|||||||
@@ -169,6 +169,7 @@
|
|||||||
#define ADV7511_PACKET_ENABLE_SPARE2 BIT(1)
|
#define ADV7511_PACKET_ENABLE_SPARE2 BIT(1)
|
||||||
#define ADV7511_PACKET_ENABLE_SPARE1 BIT(0)
|
#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_MASK 0xc0
|
||||||
#define ADV7511_REG_POWER2_HPD_SRC_BOTH 0x00
|
#define ADV7511_REG_POWER2_HPD_SRC_BOTH 0x00
|
||||||
#define ADV7511_REG_POWER2_HPD_SRC_HPD 0x40
|
#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;
|
config.csc_coefficents = adv7511_csc_ycbcr_to_rgb;
|
||||||
|
|
||||||
if ((connector->display_info.color_formats &
|
if ((connector->display_info.color_formats &
|
||||||
DRM_COLOR_FORMAT_YCRCB422) &&
|
DRM_COLOR_FORMAT_YCBCR422) &&
|
||||||
config.hdmi_mode) {
|
config.hdmi_mode) {
|
||||||
config.csc_enable = false;
|
config.csc_enable = false;
|
||||||
config.avi_infoframe.colorspace =
|
config.avi_infoframe.colorspace =
|
||||||
@@ -351,11 +351,17 @@ static void __adv7511_power_on(struct adv7511 *adv7511)
|
|||||||
* from standby or are enabled. When the HPD goes low the adv7511 is
|
* 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
|
* 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
|
* 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.
|
||||||
*/
|
*/
|
||||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
|
if (adv7511->type == ADV7535)
|
||||||
ADV7511_REG_POWER2_HPD_SRC_MASK,
|
regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
|
||||||
ADV7511_REG_POWER2_HPD_SRC_NONE);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void adv7511_power_on(struct adv7511 *adv7511)
|
static void adv7511_power_on(struct adv7511 *adv7511)
|
||||||
@@ -375,6 +381,10 @@ static void adv7511_power_on(struct adv7511 *adv7511)
|
|||||||
static void __adv7511_power_off(struct adv7511 *adv7511)
|
static void __adv7511_power_off(struct adv7511 *adv7511)
|
||||||
{
|
{
|
||||||
/* TODO: setup additional power down modes */
|
/* 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,
|
regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
|
||||||
ADV7511_POWER_POWER_DOWN,
|
ADV7511_POWER_POWER_DOWN,
|
||||||
ADV7511_POWER_POWER_DOWN);
|
ADV7511_POWER_POWER_DOWN);
|
||||||
@@ -672,9 +682,14 @@ adv7511_detect(struct adv7511 *adv7511, struct drm_connector *connector)
|
|||||||
status = connector_status_disconnected;
|
status = connector_status_disconnected;
|
||||||
} else {
|
} else {
|
||||||
/* Renable HPD sensing */
|
/* Renable HPD sensing */
|
||||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
|
if (adv7511->type == ADV7535)
|
||||||
ADV7511_REG_POWER2_HPD_SRC_MASK,
|
regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
|
||||||
ADV7511_REG_POWER2_HPD_SRC_BOTH);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
adv7511->status = status;
|
adv7511->status = status;
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ static void adv7511_dsi_config_timing_gen(struct adv7511 *adv)
|
|||||||
struct mipi_dsi_device *dsi = adv->dsi;
|
struct mipi_dsi_device *dsi = adv->dsi;
|
||||||
struct drm_display_mode *mode = &adv->curr_mode;
|
struct drm_display_mode *mode = &adv->curr_mode;
|
||||||
unsigned int hsw, hfp, hbp, vsw, vfp, vbp;
|
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;
|
hsw = mode->hsync_end - mode->hsync_start;
|
||||||
hfp = mode->hsync_start - mode->hdisplay;
|
hfp = mode->hsync_start - mode->hdisplay;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ config DRM_ANALOGIX_ANX6345
|
|||||||
tristate "Analogix ANX6345 bridge"
|
tristate "Analogix ANX6345 bridge"
|
||||||
depends on OF
|
depends on OF
|
||||||
select DRM_ANALOGIX_DP
|
select DRM_ANALOGIX_DP
|
||||||
|
select DRM_DP_HELPER
|
||||||
select DRM_KMS_HELPER
|
select DRM_KMS_HELPER
|
||||||
select REGMAP_I2C
|
select REGMAP_I2C
|
||||||
help
|
help
|
||||||
@@ -14,6 +15,7 @@ config DRM_ANALOGIX_ANX6345
|
|||||||
config DRM_ANALOGIX_ANX78XX
|
config DRM_ANALOGIX_ANX78XX
|
||||||
tristate "Analogix ANX78XX bridge"
|
tristate "Analogix ANX78XX bridge"
|
||||||
select DRM_ANALOGIX_DP
|
select DRM_ANALOGIX_DP
|
||||||
|
select DRM_DP_HELPER
|
||||||
select DRM_KMS_HELPER
|
select DRM_KMS_HELPER
|
||||||
select REGMAP_I2C
|
select REGMAP_I2C
|
||||||
help
|
help
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
#include <drm/drm_bridge.h>
|
#include <drm/drm_bridge.h>
|
||||||
#include <drm/drm_crtc.h>
|
#include <drm/drm_crtc.h>
|
||||||
#include <drm/drm_crtc_helper.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_edid.h>
|
||||||
#include <drm/drm_of.h>
|
#include <drm/drm_of.h>
|
||||||
#include <drm/drm_panel.h>
|
#include <drm/drm_panel.h>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
#include <drm/drm_atomic_helper.h>
|
#include <drm/drm_atomic_helper.h>
|
||||||
#include <drm/drm_bridge.h>
|
#include <drm/drm_bridge.h>
|
||||||
#include <drm/drm_crtc.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_edid.h>
|
||||||
#include <drm/drm_print.h>
|
#include <drm/drm_print.h>
|
||||||
#include <drm/drm_probe_helper.h>
|
#include <drm/drm_probe_helper.h>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#include <linux/regmap.h>
|
#include <linux/regmap.h>
|
||||||
|
|
||||||
#include <drm/drm.h>
|
#include <drm/drm.h>
|
||||||
#include <drm/drm_dp_helper.h>
|
#include <drm/dp/drm_dp_helper.h>
|
||||||
#include <drm/drm_print.h>
|
#include <drm/drm_print.h>
|
||||||
|
|
||||||
#include "analogix-i2c-dptx.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;
|
video->color_depth = COLOR_8;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (display_info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
|
if (display_info->color_formats & DRM_COLOR_FORMAT_YCBCR444)
|
||||||
video->color_space = COLOR_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;
|
video->color_space = COLOR_YCBCR422;
|
||||||
else
|
else
|
||||||
video->color_space = COLOR_RGB;
|
video->color_space = COLOR_RGB;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
#define _ANALOGIX_DP_CORE_H
|
#define _ANALOGIX_DP_CORE_H
|
||||||
|
|
||||||
#include <drm/drm_crtc.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 DP_TIMEOUT_LOOP_COUNT 100
|
||||||
#define MAX_CR_LOOP 5
|
#define MAX_CR_LOOP 5
|
||||||
|
|||||||
@@ -24,8 +24,9 @@
|
|||||||
#include <drm/drm_atomic_helper.h>
|
#include <drm/drm_atomic_helper.h>
|
||||||
#include <drm/drm_bridge.h>
|
#include <drm/drm_bridge.h>
|
||||||
#include <drm/drm_crtc_helper.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_edid.h>
|
||||||
|
#include <drm/drm_hdcp.h>
|
||||||
#include <drm/drm_mipi_dsi.h>
|
#include <drm/drm_mipi_dsi.h>
|
||||||
#include <drm/drm_of.h>
|
#include <drm/drm_of.h>
|
||||||
#include <drm/drm_panel.h>
|
#include <drm/drm_panel.h>
|
||||||
@@ -213,6 +214,65 @@ static int wait_aux_op_finish(struct anx7625_data *ctx)
|
|||||||
return 0;
|
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,
|
static int anx7625_video_mute_control(struct anx7625_data *ctx,
|
||||||
u8 status)
|
u8 status)
|
||||||
{
|
{
|
||||||
@@ -669,6 +729,165 @@ static int anx7625_dpi_config(struct anx7625_data *ctx)
|
|||||||
return ret;
|
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)
|
static void anx7625_dp_start(struct anx7625_data *ctx)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@@ -679,6 +898,9 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Disable HDCP */
|
||||||
|
anx7625_write_and(ctx, ctx->i2c.rx_p1_client, 0xee, 0x9f);
|
||||||
|
|
||||||
if (ctx->pdata.is_dpi)
|
if (ctx->pdata.is_dpi)
|
||||||
ret = anx7625_dpi_config(ctx);
|
ret = anx7625_dpi_config(ctx);
|
||||||
else
|
else
|
||||||
@@ -686,6 +908,10 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
|
|||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
DRM_DEV_ERROR(dev, "MIPI phy setup error.\n");
|
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)
|
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);
|
ret |= anx7625_video_mute_control(ctx, 1);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
DRM_DEV_ERROR(dev, "IO error : mute video fail\n");
|
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)
|
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 */
|
/* Gpio for chip power enable */
|
||||||
platform->pdata.gpio_p_on =
|
platform->pdata.gpio_p_on =
|
||||||
devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW);
|
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 */
|
/* Gpio for chip reset */
|
||||||
platform->pdata.gpio_reset =
|
platform->pdata.gpio_reset =
|
||||||
devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
|
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) {
|
if (platform->pdata.gpio_p_on && platform->pdata.gpio_reset) {
|
||||||
platform->pdata.low_power_mode = 1;
|
platform->pdata.low_power_mode = 1;
|
||||||
@@ -1601,9 +1840,27 @@ static int anx7625_audio_hook_plugged_cb(struct device *dev, void *data,
|
|||||||
return 0;
|
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 = {
|
static const struct hdmi_codec_ops anx7625_codec_ops = {
|
||||||
.hw_params = anx7625_audio_hw_params,
|
.hw_params = anx7625_audio_hw_params,
|
||||||
.audio_shutdown = anx7625_audio_shutdown,
|
.audio_shutdown = anx7625_audio_shutdown,
|
||||||
|
.get_eld = anx7625_audio_get_eld,
|
||||||
.get_dai_id = anx7625_hdmi_i2s_get_dai_id,
|
.get_dai_id = anx7625_hdmi_i2s_get_dai_id,
|
||||||
.hook_plugged_cb = anx7625_audio_hook_plugged_cb,
|
.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);
|
host = of_find_mipi_dsi_host_by_node(ctx->pdata.mipi_host_node);
|
||||||
if (!host) {
|
if (!host) {
|
||||||
DRM_DEV_ERROR(dev, "fail to find dsi host.\n");
|
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);
|
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;
|
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,
|
static int anx7625_bridge_attach(struct drm_bridge *bridge,
|
||||||
enum drm_bridge_attach_flags flags)
|
enum drm_bridge_attach_flags flags)
|
||||||
{
|
{
|
||||||
@@ -1902,25 +2236,57 @@ static bool anx7625_bridge_mode_fixup(struct drm_bridge *bridge,
|
|||||||
return true;
|
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 anx7625_data *ctx = bridge_to_anx7625(bridge);
|
||||||
struct device *dev = &ctx->client->dev;
|
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);
|
pm_runtime_get_sync(dev);
|
||||||
|
|
||||||
anx7625_dp_start(ctx);
|
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 anx7625_data *ctx = bridge_to_anx7625(bridge);
|
||||||
struct device *dev = &ctx->client->dev;
|
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);
|
anx7625_dp_stop(ctx);
|
||||||
|
|
||||||
pm_runtime_put_sync(dev);
|
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 = {
|
static const struct drm_bridge_funcs anx7625_bridge_funcs = {
|
||||||
.attach = anx7625_bridge_attach,
|
.attach = anx7625_bridge_attach,
|
||||||
.disable = anx7625_bridge_disable,
|
|
||||||
.mode_valid = anx7625_bridge_mode_valid,
|
.mode_valid = anx7625_bridge_mode_valid,
|
||||||
.mode_set = anx7625_bridge_mode_set,
|
.mode_set = anx7625_bridge_mode_set,
|
||||||
.mode_fixup = anx7625_bridge_mode_fixup,
|
.atomic_check = anx7625_bridge_atomic_check,
|
||||||
.enable = anx7625_bridge_enable,
|
.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,
|
.detect = anx7625_bridge_detect,
|
||||||
.get_edid = anx7625_bridge_get_edid,
|
.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,
|
static int anx7625_register_i2c_dummy_clients(struct anx7625_data *ctx,
|
||||||
struct i2c_client *client)
|
struct i2c_client *client)
|
||||||
{
|
{
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
ctx->i2c.tx_p0_client = i2c_new_dummy_device(client->adapter,
|
ctx->i2c.tx_p0_client = i2c_new_dummy_device(client->adapter,
|
||||||
TX_P0_ADDR >> 1);
|
TX_P0_ADDR >> 1);
|
||||||
if (!ctx->i2c.tx_p0_client)
|
if (IS_ERR(ctx->i2c.tx_p0_client))
|
||||||
return -ENOMEM;
|
return PTR_ERR(ctx->i2c.tx_p0_client);
|
||||||
|
|
||||||
ctx->i2c.tx_p1_client = i2c_new_dummy_device(client->adapter,
|
ctx->i2c.tx_p1_client = i2c_new_dummy_device(client->adapter,
|
||||||
TX_P1_ADDR >> 1);
|
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;
|
goto free_tx_p0;
|
||||||
|
}
|
||||||
|
|
||||||
ctx->i2c.tx_p2_client = i2c_new_dummy_device(client->adapter,
|
ctx->i2c.tx_p2_client = i2c_new_dummy_device(client->adapter,
|
||||||
TX_P2_ADDR >> 1);
|
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;
|
goto free_tx_p1;
|
||||||
|
}
|
||||||
|
|
||||||
ctx->i2c.rx_p0_client = i2c_new_dummy_device(client->adapter,
|
ctx->i2c.rx_p0_client = i2c_new_dummy_device(client->adapter,
|
||||||
RX_P0_ADDR >> 1);
|
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;
|
goto free_tx_p2;
|
||||||
|
}
|
||||||
|
|
||||||
ctx->i2c.rx_p1_client = i2c_new_dummy_device(client->adapter,
|
ctx->i2c.rx_p1_client = i2c_new_dummy_device(client->adapter,
|
||||||
RX_P1_ADDR >> 1);
|
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;
|
goto free_rx_p0;
|
||||||
|
}
|
||||||
|
|
||||||
ctx->i2c.rx_p2_client = i2c_new_dummy_device(client->adapter,
|
ctx->i2c.rx_p2_client = i2c_new_dummy_device(client->adapter,
|
||||||
RX_P2_ADDR >> 1);
|
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;
|
goto free_rx_p1;
|
||||||
|
}
|
||||||
|
|
||||||
ctx->i2c.tcpc_client = i2c_new_dummy_device(client->adapter,
|
ctx->i2c.tcpc_client = i2c_new_dummy_device(client->adapter,
|
||||||
TCPC_INTERFACE_ADDR >> 1);
|
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;
|
goto free_rx_p2;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -2012,7 +2395,7 @@ free_tx_p1:
|
|||||||
free_tx_p0:
|
free_tx_p0:
|
||||||
i2c_unregister_device(ctx->i2c.tx_p0_client);
|
i2c_unregister_device(ctx->i2c.tx_p0_client);
|
||||||
|
|
||||||
return -ENOMEM;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void anx7625_unregister_i2c_dummy_clients(struct anx7625_data *ctx)
|
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);
|
anx7625_init_gpio(platform);
|
||||||
|
|
||||||
mutex_init(&platform->lock);
|
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;
|
platform->pdata.intp_irq = client->irq;
|
||||||
if (platform->pdata.intp_irq) {
|
if (platform->pdata.intp_irq) {
|
||||||
@@ -2143,7 +2535,7 @@ static int anx7625_i2c_probe(struct i2c_client *client,
|
|||||||
if (!platform->workqueue) {
|
if (!platform->workqueue) {
|
||||||
DRM_DEV_ERROR(dev, "fail to create work queue\n");
|
DRM_DEV_ERROR(dev, "fail to create work queue\n");
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto free_platform;
|
goto free_hdcp_wq;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = devm_request_threaded_irq(dev, platform->pdata.intp_irq,
|
ret = devm_request_threaded_irq(dev, platform->pdata.intp_irq,
|
||||||
@@ -2213,6 +2605,10 @@ free_wq:
|
|||||||
if (platform->workqueue)
|
if (platform->workqueue)
|
||||||
destroy_workqueue(platform->workqueue);
|
destroy_workqueue(platform->workqueue);
|
||||||
|
|
||||||
|
free_hdcp_wq:
|
||||||
|
if (platform->hdcp_workqueue)
|
||||||
|
destroy_workqueue(platform->hdcp_workqueue);
|
||||||
|
|
||||||
free_platform:
|
free_platform:
|
||||||
kfree(platform);
|
kfree(platform);
|
||||||
|
|
||||||
@@ -2228,6 +2624,12 @@ static int anx7625_i2c_remove(struct i2c_client *client)
|
|||||||
if (platform->pdata.intp_irq)
|
if (platform->pdata.intp_irq)
|
||||||
destroy_workqueue(platform->workqueue);
|
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)
|
if (!platform->pdata.low_power_mode)
|
||||||
pm_runtime_put_sync_suspend(&client->dev);
|
pm_runtime_put_sync_suspend(&client->dev);
|
||||||
|
|
||||||
|
|||||||
@@ -59,10 +59,23 @@
|
|||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* Register definition of device address 0x70 */
|
/* 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_LINK_BW_SET_REG 0xA0
|
#define SP_TX_WAIT_R0_TIME 0x40
|
||||||
#define SP_TX_LANE_COUNT_SET_REG 0xA1
|
#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
|
||||||
|
|
||||||
#define M_VID_0 0xC0
|
#define M_VID_0 0xC0
|
||||||
#define M_VID_1 0xC1
|
#define M_VID_1 0xC1
|
||||||
@@ -71,6 +84,12 @@
|
|||||||
#define N_VID_1 0xC4
|
#define N_VID_1 0xC4
|
||||||
#define N_VID_2 0xC5
|
#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 */
|
/* Register definition of device address 0x72 */
|
||||||
#define AUX_RST 0x04
|
#define AUX_RST 0x04
|
||||||
@@ -155,9 +174,43 @@
|
|||||||
|
|
||||||
#define I2C_ADDR_7E_FLASH_CONTROLLER 0x7E
|
#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 0x05
|
||||||
#define FLASH_LOAD_STA_CHK BIT(7)
|
#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
|
#define XTAL_FRQ_SEL 0x3F
|
||||||
/* bit field positions */
|
/* bit field positions */
|
||||||
#define XTAL_FRQ_SEL_POS 5
|
#define XTAL_FRQ_SEL_POS 5
|
||||||
@@ -184,10 +237,15 @@
|
|||||||
#define AP_AUX_CTRL_ADDRONLY 0x20
|
#define AP_AUX_CTRL_ADDRONLY 0x20
|
||||||
|
|
||||||
#define AP_AUX_BUFF_START 0x15
|
#define AP_AUX_BUFF_START 0x15
|
||||||
#define PIXEL_CLOCK_L 0x25
|
#define PIXEL_CLOCK_L 0x25
|
||||||
#define PIXEL_CLOCK_H 0x26
|
#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))
|
||||||
|
|
||||||
#define AP_AUX_COMMAND 0x27 /* com+len */
|
|
||||||
/* Bit 0&1: 3D video structure */
|
/* Bit 0&1: 3D video structure */
|
||||||
/* 0x01: frame packing, 0x02:Line alternative, 0x03:Side-by-side(full) */
|
/* 0x01: frame packing, 0x02:Line alternative, 0x03:Side-by-side(full) */
|
||||||
#define AP_AV_STATUS 0x28
|
#define AP_AV_STATUS 0x28
|
||||||
@@ -392,21 +450,29 @@ struct anx7625_data {
|
|||||||
struct platform_device *audio_pdev;
|
struct platform_device *audio_pdev;
|
||||||
int hpd_status;
|
int hpd_status;
|
||||||
int hpd_high_cnt;
|
int hpd_high_cnt;
|
||||||
|
int dp_en;
|
||||||
|
int hdcp_cp;
|
||||||
/* Lock for work queue */
|
/* Lock for work queue */
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
struct i2c_client *client;
|
struct i2c_client *client;
|
||||||
struct anx7625_i2c_client i2c;
|
struct anx7625_i2c_client i2c;
|
||||||
struct i2c_client *last_client;
|
struct i2c_client *last_client;
|
||||||
|
struct timer_list hdcp_timer;
|
||||||
struct s_edid_data slimport_edid_p;
|
struct s_edid_data slimport_edid_p;
|
||||||
struct device *codec_dev;
|
struct device *codec_dev;
|
||||||
hdmi_codec_plugged_cb plugged_cb;
|
hdmi_codec_plugged_cb plugged_cb;
|
||||||
struct work_struct work;
|
struct work_struct work;
|
||||||
struct workqueue_struct *workqueue;
|
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;
|
char edid_block;
|
||||||
struct display_timing dt;
|
struct display_timing dt;
|
||||||
u8 display_timing_valid;
|
u8 display_timing_valid;
|
||||||
struct drm_bridge bridge;
|
struct drm_bridge bridge;
|
||||||
u8 bridge_attached;
|
u8 bridge_attached;
|
||||||
|
struct drm_connector *connector;
|
||||||
struct mipi_dsi_device *dsi;
|
struct mipi_dsi_device *dsi;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0-only
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
config DRM_CDNS_MHDP8546
|
config DRM_CDNS_MHDP8546
|
||||||
tristate "Cadence DPI/DP bridge"
|
tristate "Cadence DPI/DP bridge"
|
||||||
|
select DRM_DP_HELPER
|
||||||
select DRM_KMS_HELPER
|
select DRM_KMS_HELPER
|
||||||
select DRM_PANEL_BRIDGE
|
select DRM_PANEL_BRIDGE
|
||||||
depends on OF
|
depends on OF
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
#include <drm/drm_bridge.h>
|
#include <drm/drm_bridge.h>
|
||||||
#include <drm/drm_connector.h>
|
#include <drm/drm_connector.h>
|
||||||
#include <drm/drm_crtc_helper.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_hdcp.h>
|
||||||
#include <drm/drm_modeset_helper_vtables.h>
|
#include <drm/drm_modeset_helper_vtables.h>
|
||||||
#include <drm/drm_print.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) {
|
switch (fmt->color_format) {
|
||||||
case DRM_COLOR_FORMAT_RGB444:
|
case DRM_COLOR_FORMAT_RGB444:
|
||||||
case DRM_COLOR_FORMAT_YCRCB444:
|
case DRM_COLOR_FORMAT_YCBCR444:
|
||||||
bpp = fmt->bpc * 3;
|
bpp = fmt->bpc * 3;
|
||||||
break;
|
break;
|
||||||
case DRM_COLOR_FORMAT_YCRCB422:
|
case DRM_COLOR_FORMAT_YCBCR422:
|
||||||
bpp = fmt->bpc * 2;
|
bpp = fmt->bpc * 2;
|
||||||
break;
|
break;
|
||||||
case DRM_COLOR_FORMAT_YCRCB420:
|
case DRM_COLOR_FORMAT_YCBCR420:
|
||||||
bpp = fmt->bpc * 3 / 2;
|
bpp = fmt->bpc * 3 / 2;
|
||||||
break;
|
break;
|
||||||
default:
|
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
|
* If YCBCR supported and stream not SD, use ITU709
|
||||||
* Need to handle ITU version with YCBCR420 when supported
|
* Need to handle ITU version with YCBCR420 when supported
|
||||||
*/
|
*/
|
||||||
if ((pxlfmt == DRM_COLOR_FORMAT_YCRCB444 ||
|
if ((pxlfmt == DRM_COLOR_FORMAT_YCBCR444 ||
|
||||||
pxlfmt == DRM_COLOR_FORMAT_YCRCB422) && mode->crtc_vdisplay >= 720)
|
pxlfmt == DRM_COLOR_FORMAT_YCBCR422) && mode->crtc_vdisplay >= 720)
|
||||||
misc0 = DP_YCBCR_COEFFICIENTS_ITU709;
|
misc0 = DP_YCBCR_COEFFICIENTS_ITU709;
|
||||||
|
|
||||||
bpp = cdns_mhdp_get_bpp(&mhdp->display_fmt);
|
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;
|
pxl_repr = CDNS_DP_FRAMER_RGB << CDNS_DP_FRAMER_PXL_FORMAT;
|
||||||
misc0 |= DP_COLOR_FORMAT_RGB;
|
misc0 |= DP_COLOR_FORMAT_RGB;
|
||||||
break;
|
break;
|
||||||
case DRM_COLOR_FORMAT_YCRCB444:
|
case DRM_COLOR_FORMAT_YCBCR444:
|
||||||
pxl_repr = CDNS_DP_FRAMER_YCBCR444 << CDNS_DP_FRAMER_PXL_FORMAT;
|
pxl_repr = CDNS_DP_FRAMER_YCBCR444 << CDNS_DP_FRAMER_PXL_FORMAT;
|
||||||
misc0 |= DP_COLOR_FORMAT_YCbCr444 | DP_TEST_DYNAMIC_RANGE_CEA;
|
misc0 |= DP_COLOR_FORMAT_YCbCr444 | DP_TEST_DYNAMIC_RANGE_CEA;
|
||||||
break;
|
break;
|
||||||
case DRM_COLOR_FORMAT_YCRCB422:
|
case DRM_COLOR_FORMAT_YCBCR422:
|
||||||
pxl_repr = CDNS_DP_FRAMER_YCBCR422 << CDNS_DP_FRAMER_PXL_FORMAT;
|
pxl_repr = CDNS_DP_FRAMER_YCBCR422 << CDNS_DP_FRAMER_PXL_FORMAT;
|
||||||
misc0 |= DP_COLOR_FORMAT_YCbCr422 | DP_TEST_DYNAMIC_RANGE_CEA;
|
misc0 |= DP_COLOR_FORMAT_YCbCr422 | DP_TEST_DYNAMIC_RANGE_CEA;
|
||||||
break;
|
break;
|
||||||
case DRM_COLOR_FORMAT_YCRCB420:
|
case DRM_COLOR_FORMAT_YCBCR420:
|
||||||
pxl_repr = CDNS_DP_FRAMER_YCBCR420 << CDNS_DP_FRAMER_PXL_FORMAT;
|
pxl_repr = CDNS_DP_FRAMER_YCBCR420 << CDNS_DP_FRAMER_PXL_FORMAT;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -1882,7 +1882,7 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
|
|||||||
if (mhdp->display_fmt.y_only)
|
if (mhdp->display_fmt.y_only)
|
||||||
misc1 |= CDNS_DP_TEST_COLOR_FORMAT_RAW_Y_ONLY;
|
misc1 |= CDNS_DP_TEST_COLOR_FORMAT_RAW_Y_ONLY;
|
||||||
/* Use VSC SDP for Y420 */
|
/* Use VSC SDP for Y420 */
|
||||||
if (pxlfmt == DRM_COLOR_FORMAT_YCRCB420)
|
if (pxlfmt == DRM_COLOR_FORMAT_YCBCR420)
|
||||||
misc1 = CDNS_DP_TEST_VSC_SDP;
|
misc1 = CDNS_DP_TEST_VSC_SDP;
|
||||||
|
|
||||||
cdns_mhdp_reg_write(mhdp, CDNS_DP_MSA_MISC(stream_id),
|
cdns_mhdp_reg_write(mhdp, CDNS_DP_MSA_MISC(stream_id),
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
#include <drm/drm_bridge.h>
|
#include <drm/drm_bridge.h>
|
||||||
#include <drm/drm_connector.h>
|
#include <drm/drm_connector.h>
|
||||||
#include <drm/drm_dp_helper.h>
|
#include <drm/dp/drm_dp_helper.h>
|
||||||
|
|
||||||
struct clk;
|
struct clk;
|
||||||
struct device;
|
struct device;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
* Author: Jagan Teki <jagan@amarulasolutions.com>
|
* Author: Jagan Teki <jagan@amarulasolutions.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <drm/drm_atomic_helper.h>
|
||||||
#include <drm/drm_of.h>
|
#include <drm/drm_of.h>
|
||||||
#include <drm/drm_print.h>
|
#include <drm/drm_print.h>
|
||||||
#include <drm/drm_mipi_dsi.h>
|
#include <drm/drm_mipi_dsi.h>
|
||||||
@@ -30,6 +31,7 @@
|
|||||||
struct chipone {
|
struct chipone {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct drm_bridge bridge;
|
struct drm_bridge bridge;
|
||||||
|
struct drm_display_mode mode;
|
||||||
struct drm_bridge *panel_bridge;
|
struct drm_bridge *panel_bridge;
|
||||||
struct gpio_desc *enable_gpio;
|
struct gpio_desc *enable_gpio;
|
||||||
struct regulator *vdd1;
|
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);
|
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,
|
static inline int chipone_dsi_write(struct chipone *icn, const void *seq,
|
||||||
size_t len)
|
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)); \
|
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 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);
|
ICN6211_DSI(icn, 0x7a, 0xc1);
|
||||||
|
|
||||||
@@ -114,7 +112,8 @@ static void chipone_enable(struct drm_bridge *bridge)
|
|||||||
usleep_range(10000, 11000);
|
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);
|
struct chipone *icn = bridge_to_chipone(bridge);
|
||||||
int ret;
|
int ret;
|
||||||
@@ -145,7 +144,8 @@ static void chipone_pre_enable(struct drm_bridge *bridge)
|
|||||||
usleep_range(10000, 11000);
|
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);
|
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);
|
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)
|
static int chipone_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags)
|
||||||
{
|
{
|
||||||
struct chipone *icn = bridge_to_chipone(bridge);
|
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 = {
|
static const struct drm_bridge_funcs chipone_bridge_funcs = {
|
||||||
.attach = chipone_attach,
|
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
|
||||||
.post_disable = chipone_post_disable,
|
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
|
||||||
.pre_enable = chipone_pre_enable,
|
.atomic_reset = drm_atomic_helper_bridge_reset,
|
||||||
.enable = chipone_enable,
|
.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,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int chipone_parse_dt(struct chipone *icn)
|
static int chipone_parse_dt(struct chipone *icn)
|
||||||
|
|||||||
@@ -936,9 +936,6 @@ static int it66121_probe(struct i2c_client *client,
|
|||||||
return -EPROBE_DEFER;
|
return -EPROBE_DEFER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ctx->next_bridge)
|
|
||||||
return -EPROBE_DEFER;
|
|
||||||
|
|
||||||
i2c_set_clientdata(client, ctx);
|
i2c_set_clientdata(client, ctx);
|
||||||
mutex_init(&ctx->lock);
|
mutex_init(&ctx->lock);
|
||||||
|
|
||||||
|
|||||||
@@ -1090,7 +1090,7 @@ static int lt9611_probe(struct i2c_client *client,
|
|||||||
if (!lt9611)
|
if (!lt9611)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
lt9611->dev = &client->dev;
|
lt9611->dev = dev;
|
||||||
lt9611->client = client;
|
lt9611->client = client;
|
||||||
lt9611->sleep = false;
|
lt9611->sleep = false;
|
||||||
|
|
||||||
@@ -1100,7 +1100,7 @@ static int lt9611_probe(struct i2c_client *client,
|
|||||||
return PTR_ERR(lt9611->regmap);
|
return PTR_ERR(lt9611->regmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = lt9611_parse_dt(&client->dev, lt9611);
|
ret = lt9611_parse_dt(dev, lt9611);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "failed to parse device tree\n");
|
dev_err(dev, "failed to parse device tree\n");
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@@ -860,7 +860,7 @@ static int lt9611uxc_probe(struct i2c_client *client,
|
|||||||
if (!lt9611uxc)
|
if (!lt9611uxc)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
lt9611uxc->dev = &client->dev;
|
lt9611uxc->dev = dev;
|
||||||
lt9611uxc->client = client;
|
lt9611uxc->client = client;
|
||||||
mutex_init(<9611uxc->ocm_lock);
|
mutex_init(<9611uxc->ocm_lock);
|
||||||
|
|
||||||
@@ -870,7 +870,7 @@ static int lt9611uxc_probe(struct i2c_client *client,
|
|||||||
return PTR_ERR(lt9611uxc->regmap);
|
return PTR_ERR(lt9611uxc->regmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = lt9611uxc_parse_dt(&client->dev, lt9611uxc);
|
ret = lt9611uxc_parse_dt(dev, lt9611uxc);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "failed to parse device tree\n");
|
dev_err(dev, "failed to parse device tree\n");
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ struct nwl_dsi_transfer {
|
|||||||
struct nwl_dsi {
|
struct nwl_dsi {
|
||||||
struct drm_bridge bridge;
|
struct drm_bridge bridge;
|
||||||
struct mipi_dsi_host dsi_host;
|
struct mipi_dsi_host dsi_host;
|
||||||
struct drm_bridge *panel_bridge;
|
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct phy *phy;
|
struct phy *phy;
|
||||||
union phy_configure_opts phy_cfg;
|
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))
|
if (IS_ERR(panel_bridge))
|
||||||
return PTR_ERR(panel_bridge);
|
return PTR_ERR(panel_bridge);
|
||||||
}
|
}
|
||||||
dsi->panel_bridge = panel_bridge;
|
|
||||||
|
|
||||||
if (!dsi->panel_bridge)
|
if (!panel_bridge)
|
||||||
return -EPROBE_DEFER;
|
return -EPROBE_DEFER;
|
||||||
|
|
||||||
return drm_bridge_attach(bridge->encoder, dsi->panel_bridge, bridge,
|
return drm_bridge_attach(bridge->encoder, panel_bridge, bridge, flags);
|
||||||
flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nwl_dsi_bridge_detach(struct drm_bridge *bridge)
|
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);
|
ret = nwl_dsi_select_input(dsi);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
pm_runtime_disable(dev);
|
||||||
mipi_dsi_host_unregister(&dsi->dsi_host);
|
mipi_dsi_host_unregister(&dsi->dsi_host);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
#include <linux/regulator/consumer.h>
|
#include <linux/regulator/consumer.h>
|
||||||
|
|
||||||
#include <drm/drm_bridge.h>
|
#include <drm/drm_bridge.h>
|
||||||
#include <drm/drm_dp_aux_bus.h>
|
#include <drm/dp/drm_dp_aux_bus.h>
|
||||||
#include <drm/drm_dp_helper.h>
|
#include <drm/dp/drm_dp_helper.h>
|
||||||
#include <drm/drm_mipi_dsi.h>
|
#include <drm/drm_mipi_dsi.h>
|
||||||
#include <drm/drm_of.h>
|
#include <drm/drm_of.h>
|
||||||
#include <drm/drm_panel.h>
|
#include <drm/drm_panel.h>
|
||||||
@@ -102,6 +102,7 @@ struct ps8640 {
|
|||||||
struct regulator_bulk_data supplies[2];
|
struct regulator_bulk_data supplies[2];
|
||||||
struct gpio_desc *gpio_reset;
|
struct gpio_desc *gpio_reset;
|
||||||
struct gpio_desc *gpio_powerdown;
|
struct gpio_desc *gpio_powerdown;
|
||||||
|
struct device_link *link;
|
||||||
bool pre_enabled;
|
bool pre_enabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -456,14 +457,36 @@ static int ps8640_bridge_attach(struct drm_bridge *bridge,
|
|||||||
return ret;
|
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 */
|
/* 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);
|
&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)
|
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,
|
static struct edid *ps8640_bridge_get_edid(struct drm_bridge *bridge,
|
||||||
|
|||||||
@@ -166,10 +166,12 @@ struct sii902x {
|
|||||||
struct i2c_client *i2c;
|
struct i2c_client *i2c;
|
||||||
struct regmap *regmap;
|
struct regmap *regmap;
|
||||||
struct drm_bridge bridge;
|
struct drm_bridge bridge;
|
||||||
|
struct drm_bridge *next_bridge;
|
||||||
struct drm_connector connector;
|
struct drm_connector connector;
|
||||||
struct gpio_desc *reset_gpio;
|
struct gpio_desc *reset_gpio;
|
||||||
struct i2c_mux_core *i2cmux;
|
struct i2c_mux_core *i2cmux;
|
||||||
struct regulator_bulk_data supplies[2];
|
struct regulator_bulk_data supplies[2];
|
||||||
|
bool sink_is_hdmi;
|
||||||
/*
|
/*
|
||||||
* Mutex protects audio and video functions from interfering
|
* Mutex protects audio and video functions from interfering
|
||||||
* each other, by keeping their i2c command sequences atomic.
|
* 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);
|
gpiod_set_value(sii902x->reset_gpio, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum drm_connector_status
|
static enum drm_connector_status sii902x_detect(struct sii902x *sii902x)
|
||||||
sii902x_connector_detect(struct drm_connector *connector, bool force)
|
|
||||||
{
|
{
|
||||||
struct sii902x *sii902x = connector_to_sii902x(connector);
|
|
||||||
unsigned int status;
|
unsigned int status;
|
||||||
|
|
||||||
mutex_lock(&sii902x->mutex);
|
mutex_lock(&sii902x->mutex);
|
||||||
@@ -261,6 +261,14 @@ sii902x_connector_detect(struct drm_connector *connector, bool force)
|
|||||||
connector_status_connected : connector_status_disconnected;
|
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 = {
|
static const struct drm_connector_funcs sii902x_connector_funcs = {
|
||||||
.detect = sii902x_connector_detect,
|
.detect = sii902x_connector_detect,
|
||||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
.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,
|
.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;
|
struct edid *edid;
|
||||||
int num = 0, ret;
|
|
||||||
|
|
||||||
mutex_lock(&sii902x->mutex);
|
mutex_lock(&sii902x->mutex);
|
||||||
|
|
||||||
edid = drm_get_edid(connector, sii902x->i2cmux->adapter[0]);
|
edid = drm_get_edid(connector, sii902x->i2cmux->adapter[0]);
|
||||||
drm_connector_update_edid_property(connector, edid);
|
|
||||||
if (edid) {
|
if (edid) {
|
||||||
if (drm_detect_hdmi_monitor(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);
|
num = drm_add_edid_modes(connector, edid);
|
||||||
kfree(edid);
|
kfree(edid);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = drm_display_info_set_bus_formats(&connector->display_info,
|
return num;
|
||||||
&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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum drm_mode_status sii902x_mode_valid(struct drm_connector *connector,
|
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)
|
const struct drm_display_mode *adj)
|
||||||
{
|
{
|
||||||
struct sii902x *sii902x = bridge_to_sii902x(bridge);
|
struct sii902x *sii902x = bridge_to_sii902x(bridge);
|
||||||
|
u8 output_mode = SII902X_SYS_CTRL_OUTPUT_DVI;
|
||||||
struct regmap *regmap = sii902x->regmap;
|
struct regmap *regmap = sii902x->regmap;
|
||||||
u8 buf[HDMI_INFOFRAME_SIZE(AVI)];
|
u8 buf[HDMI_INFOFRAME_SIZE(AVI)];
|
||||||
struct hdmi_avi_infoframe frame;
|
struct hdmi_avi_infoframe frame;
|
||||||
u16 pixel_clock_10kHz = adj->clock / 10;
|
u16 pixel_clock_10kHz = adj->clock / 10;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (sii902x->sink_is_hdmi)
|
||||||
|
output_mode = SII902X_SYS_CTRL_OUTPUT_HDMI;
|
||||||
|
|
||||||
buf[0] = pixel_clock_10kHz & 0xff;
|
buf[0] = pixel_clock_10kHz & 0xff;
|
||||||
buf[1] = pixel_clock_10kHz >> 8;
|
buf[1] = pixel_clock_10kHz >> 8;
|
||||||
buf[2] = drm_mode_vrefresh(adj);
|
buf[2] = drm_mode_vrefresh(adj);
|
||||||
@@ -375,6 +385,11 @@ static void sii902x_bridge_mode_set(struct drm_bridge *bridge,
|
|||||||
|
|
||||||
mutex_lock(&sii902x->mutex);
|
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);
|
ret = regmap_bulk_write(regmap, SII902X_TPI_VIDEO_DATA, buf, 10);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
@@ -405,13 +420,13 @@ static int sii902x_bridge_attach(struct drm_bridge *bridge,
|
|||||||
enum drm_bridge_attach_flags flags)
|
enum drm_bridge_attach_flags flags)
|
||||||
{
|
{
|
||||||
struct sii902x *sii902x = bridge_to_sii902x(bridge);
|
struct sii902x *sii902x = bridge_to_sii902x(bridge);
|
||||||
|
u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
|
||||||
struct drm_device *drm = bridge->dev;
|
struct drm_device *drm = bridge->dev;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
|
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
|
||||||
DRM_ERROR("Fix bridge driver to make connector optional!");
|
return drm_bridge_attach(bridge->encoder, sii902x->next_bridge,
|
||||||
return -EINVAL;
|
bridge, flags);
|
||||||
}
|
|
||||||
|
|
||||||
drm_connector_helper_add(&sii902x->connector,
|
drm_connector_helper_add(&sii902x->connector,
|
||||||
&sii902x_connector_helper_funcs);
|
&sii902x_connector_helper_funcs);
|
||||||
@@ -433,16 +448,38 @@ static int sii902x_bridge_attach(struct drm_bridge *bridge,
|
|||||||
else
|
else
|
||||||
sii902x->connector.polled = DRM_CONNECTOR_POLL_CONNECT;
|
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);
|
drm_connector_attach_encoder(&sii902x->connector, bridge->encoder);
|
||||||
|
|
||||||
return 0;
|
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 = {
|
static const struct drm_bridge_funcs sii902x_bridge_funcs = {
|
||||||
.attach = sii902x_bridge_attach,
|
.attach = sii902x_bridge_attach,
|
||||||
.mode_set = sii902x_bridge_mode_set,
|
.mode_set = sii902x_bridge_mode_set,
|
||||||
.disable = sii902x_bridge_disable,
|
.disable = sii902x_bridge_disable,
|
||||||
.enable = sii902x_bridge_enable,
|
.enable = sii902x_bridge_enable,
|
||||||
|
.detect = sii902x_bridge_detect,
|
||||||
|
.get_edid = sii902x_bridge_get_edid,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int sii902x_mute(struct sii902x *sii902x, bool mute)
|
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);
|
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_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;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
@@ -1001,6 +1042,11 @@ static int sii902x_init(struct sii902x *sii902x)
|
|||||||
sii902x->bridge.funcs = &sii902x_bridge_funcs;
|
sii902x->bridge.funcs = &sii902x_bridge_funcs;
|
||||||
sii902x->bridge.of_node = dev->of_node;
|
sii902x->bridge.of_node = dev->of_node;
|
||||||
sii902x->bridge.timings = &default_sii902x_timings;
|
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);
|
drm_bridge_add(&sii902x->bridge);
|
||||||
|
|
||||||
sii902x_audio_codec_init(sii902x, dev);
|
sii902x_audio_codec_init(sii902x, dev);
|
||||||
@@ -1022,6 +1068,7 @@ static int sii902x_probe(struct i2c_client *client,
|
|||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
struct device *dev = &client->dev;
|
struct device *dev = &client->dev;
|
||||||
|
struct device_node *endpoint;
|
||||||
struct sii902x *sii902x;
|
struct sii902x *sii902x;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@@ -1049,6 +1096,28 @@ static int sii902x_probe(struct i2c_client *client,
|
|||||||
return PTR_ERR(sii902x->reset_gpio);
|
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);
|
mutex_init(&sii902x->mutex);
|
||||||
|
|
||||||
sii902x->supplies[0].supply = "iovcc";
|
sii902x->supplies[0].supply = "iovcc";
|
||||||
|
|||||||
@@ -2120,7 +2120,7 @@ static void sii8620_init_rcp_input_dev(struct sii8620 *ctx)
|
|||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(ctx->dev, "Failed to register RC device\n");
|
dev_err(ctx->dev, "Failed to register RC device\n");
|
||||||
ctx->error = ret;
|
ctx->error = ret;
|
||||||
rc_free_device(ctx->rc_dev);
|
rc_free_device(rc_dev);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ctx->rc_dev = rc_dev;
|
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;
|
struct drm_display_mode *mode = &crtc_state->mode;
|
||||||
u8 max_bpc = conn_state->max_requested_bpc;
|
u8 max_bpc = conn_state->max_requested_bpc;
|
||||||
bool is_hdmi2_sink = info->hdmi.scdc.supported ||
|
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;
|
u32 *output_fmts;
|
||||||
unsigned int i = 0;
|
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 (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_YUV16_1X48;
|
||||||
|
|
||||||
output_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48;
|
output_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (max_bpc >= 12 && info->bpc >= 12) {
|
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;
|
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_YUV12_1X36;
|
||||||
|
|
||||||
output_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36;
|
output_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (max_bpc >= 10 && info->bpc >= 10) {
|
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;
|
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_YUV10_1X30;
|
||||||
|
|
||||||
output_fmts[i++] = MEDIA_BUS_FMT_RGB101010_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;
|
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;
|
output_fmts[i++] = MEDIA_BUS_FMT_YUV8_1X24;
|
||||||
|
|
||||||
/* Default 8bit RGB fallback */
|
/* 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);
|
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);
|
struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
|
||||||
const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops;
|
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);
|
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);
|
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;
|
enum drm_mode_status mode_status = MODE_OK;
|
||||||
|
|
||||||
if (pdata->mode_valid)
|
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;
|
return mode_status;
|
||||||
}
|
}
|
||||||
@@ -1032,11 +1037,14 @@ static int dw_mipi_dsi_bridge_attach(struct drm_bridge *bridge,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct drm_bridge_funcs dw_mipi_dsi_bridge_funcs = {
|
static const struct drm_bridge_funcs dw_mipi_dsi_bridge_funcs = {
|
||||||
.mode_set = dw_mipi_dsi_bridge_mode_set,
|
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
|
||||||
.enable = dw_mipi_dsi_bridge_enable,
|
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
|
||||||
.post_disable = dw_mipi_dsi_bridge_post_disable,
|
.atomic_reset = drm_atomic_helper_bridge_reset,
|
||||||
.mode_valid = dw_mipi_dsi_bridge_mode_valid,
|
.atomic_enable = dw_mipi_dsi_bridge_atomic_enable,
|
||||||
.attach = dw_mipi_dsi_bridge_attach,
|
.atomic_post_disable = dw_mipi_dsi_bridge_post_atomic_disable,
|
||||||
|
.mode_set = dw_mipi_dsi_bridge_mode_set,
|
||||||
|
.mode_valid = dw_mipi_dsi_bridge_mode_valid,
|
||||||
|
.attach = dw_mipi_dsi_bridge_attach,
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
@@ -1199,6 +1207,7 @@ __dw_mipi_dsi_probe(struct platform_device *pdev,
|
|||||||
ret = mipi_dsi_host_register(&dsi->dsi_host);
|
ret = mipi_dsi_host_register(&dsi->dsi_host);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "Failed to register MIPI host: %d\n", ret);
|
dev_err(dev, "Failed to register MIPI host: %d\n", ret);
|
||||||
|
pm_runtime_disable(dev);
|
||||||
dw_mipi_dsi_debugfs_remove(dsi);
|
dw_mipi_dsi_debugfs_remove(dsi);
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
#include <drm/drm_atomic_helper.h>
|
#include <drm/drm_atomic_helper.h>
|
||||||
#include <drm/drm_bridge.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_edid.h>
|
||||||
#include <drm/drm_of.h>
|
#include <drm/drm_of.h>
|
||||||
#include <drm/drm_panel.h>
|
#include <drm/drm_panel.h>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
#include <drm/drm_atomic_helper.h>
|
#include <drm/drm_atomic_helper.h>
|
||||||
#include <drm/drm_bridge.h>
|
#include <drm/drm_bridge.h>
|
||||||
#include <drm/drm_crtc_helper.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_mipi_dsi.h>
|
||||||
#include <drm/drm_of.h>
|
#include <drm/drm_of.h>
|
||||||
#include <drm/drm_panel.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__MASK 0x00000002
|
||||||
#define TC358775_LVCFG_LVDLINK__SHIFT 0
|
#define TC358775_LVCFG_LVDLINK__SHIFT 1
|
||||||
static inline u32 TC358775_LVCFG_LVDLINK(uint32_t val)
|
static inline u32 TC358775_LVCFG_LVDLINK(uint32_t val)
|
||||||
{
|
{
|
||||||
return ((val) << TC358775_LVCFG_LVDLINK__SHIFT) &
|
return ((val) << TC358775_LVCFG_LVDLINK__SHIFT) &
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
#include <linux/of_graph.h>
|
#include <linux/of_graph.h>
|
||||||
#include <linux/regmap.h>
|
#include <linux/regmap.h>
|
||||||
|
#include <linux/regulator/consumer.h>
|
||||||
|
|
||||||
#include <drm/drm_atomic_helper.h>
|
#include <drm/drm_atomic_helper.h>
|
||||||
#include <drm/drm_bridge.h>
|
#include <drm/drm_bridge.h>
|
||||||
@@ -143,6 +144,7 @@ struct sn65dsi83 {
|
|||||||
struct mipi_dsi_device *dsi;
|
struct mipi_dsi_device *dsi;
|
||||||
struct drm_bridge *panel_bridge;
|
struct drm_bridge *panel_bridge;
|
||||||
struct gpio_desc *enable_gpio;
|
struct gpio_desc *enable_gpio;
|
||||||
|
struct regulator *vcc;
|
||||||
int dsi_lanes;
|
int dsi_lanes;
|
||||||
bool lvds_dual_link;
|
bool lvds_dual_link;
|
||||||
bool lvds_dual_link_even_odd_swap;
|
bool lvds_dual_link_even_odd_swap;
|
||||||
@@ -337,6 +339,12 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
|
|||||||
u16 val;
|
u16 val;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
ret = regulator_enable(ctx->vcc);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(ctx->dev, "Failed to enable vcc: %d\n", ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Deassert reset */
|
/* Deassert reset */
|
||||||
gpiod_set_value(ctx->enable_gpio, 1);
|
gpiod_set_value(ctx->enable_gpio, 1);
|
||||||
usleep_range(1000, 1100);
|
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 drm_bridge_state *old_bridge_state)
|
||||||
{
|
{
|
||||||
struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
|
struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* Put the chip in reset, pull EN line low, and assure 10ms reset low timing. */
|
/* Put the chip in reset, pull EN line low, and assure 10ms reset low timing. */
|
||||||
gpiod_set_value(ctx->enable_gpio, 0);
|
gpiod_set_value(ctx->enable_gpio, 0);
|
||||||
usleep_range(10000, 11000);
|
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);
|
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);
|
ctx->host_node = of_graph_get_remote_port_parent(endpoint);
|
||||||
of_node_put(endpoint);
|
of_node_put(endpoint);
|
||||||
|
|
||||||
if (ctx->dsi_lanes < 0 || ctx->dsi_lanes > 4)
|
if (ctx->dsi_lanes < 0 || ctx->dsi_lanes > 4) {
|
||||||
return -EINVAL;
|
ret = -EINVAL;
|
||||||
if (!ctx->host_node)
|
goto err_put_node;
|
||||||
return -ENODEV;
|
}
|
||||||
|
if (!ctx->host_node) {
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto err_put_node;
|
||||||
|
}
|
||||||
|
|
||||||
ctx->lvds_dual_link = false;
|
ctx->lvds_dual_link = false;
|
||||||
ctx->lvds_dual_link_even_odd_swap = 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);
|
ret = drm_of_find_panel_or_bridge(dev->of_node, 2, 0, &panel, &panel_bridge);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
goto err_put_node;
|
||||||
if (panel) {
|
if (panel) {
|
||||||
panel_bridge = devm_drm_panel_bridge_add(dev, panel);
|
panel_bridge = devm_drm_panel_bridge_add(dev, panel);
|
||||||
if (IS_ERR(panel_bridge))
|
if (IS_ERR(panel_bridge)) {
|
||||||
return PTR_ERR(panel_bridge);
|
ret = PTR_ERR(panel_bridge);
|
||||||
|
goto err_put_node;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->panel_bridge = panel_bridge;
|
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;
|
return 0;
|
||||||
|
|
||||||
|
err_put_node:
|
||||||
|
of_node_put(ctx->host_node);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sn65dsi83_host_attach(struct sn65dsi83 *ctx)
|
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. */
|
/* 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))
|
if (IS_ERR(ctx->enable_gpio))
|
||||||
return PTR_ERR(ctx->enable_gpio);
|
return PTR_ERR(ctx->enable_gpio);
|
||||||
|
|
||||||
@@ -673,8 +702,10 @@ static int sn65dsi83_probe(struct i2c_client *client,
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ctx->regmap = devm_regmap_init_i2c(client, &sn65dsi83_regmap_config);
|
ctx->regmap = devm_regmap_init_i2c(client, &sn65dsi83_regmap_config);
|
||||||
if (IS_ERR(ctx->regmap))
|
if (IS_ERR(ctx->regmap)) {
|
||||||
return PTR_ERR(ctx->regmap);
|
ret = PTR_ERR(ctx->regmap);
|
||||||
|
goto err_put_node;
|
||||||
|
}
|
||||||
|
|
||||||
dev_set_drvdata(dev, ctx);
|
dev_set_drvdata(dev, ctx);
|
||||||
i2c_set_clientdata(client, ctx);
|
i2c_set_clientdata(client, ctx);
|
||||||
@@ -691,6 +722,8 @@ static int sn65dsi83_probe(struct i2c_client *client,
|
|||||||
|
|
||||||
err_remove_bridge:
|
err_remove_bridge:
|
||||||
drm_bridge_remove(&ctx->bridge);
|
drm_bridge_remove(&ctx->bridge);
|
||||||
|
err_put_node:
|
||||||
|
of_node_put(ctx->host_node);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,8 +26,8 @@
|
|||||||
#include <drm/drm_atomic.h>
|
#include <drm/drm_atomic.h>
|
||||||
#include <drm/drm_atomic_helper.h>
|
#include <drm/drm_atomic_helper.h>
|
||||||
#include <drm/drm_bridge.h>
|
#include <drm/drm_bridge.h>
|
||||||
#include <drm/drm_dp_aux_bus.h>
|
#include <drm/dp/drm_dp_aux_bus.h>
|
||||||
#include <drm/drm_dp_helper.h>
|
#include <drm/dp/drm_dp_helper.h>
|
||||||
#include <drm/drm_mipi_dsi.h>
|
#include <drm/drm_mipi_dsi.h>
|
||||||
#include <drm/drm_of.h>
|
#include <drm/drm_of.h>
|
||||||
#include <drm/drm_panel.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/sched.h>
|
||||||
#include <linux/seq_file.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_print.h>
|
||||||
#include <drm/drm_vblank.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/drm_panel.h>
|
||||||
|
|
||||||
#include "drm_crtc_helper_internal.h"
|
#include "drm_dp_helper_internal.h"
|
||||||
|
|
||||||
struct dp_aux_backlight {
|
struct dp_aux_backlight {
|
||||||
struct backlight_device *base;
|
struct backlight_device *base;
|
||||||
@@ -19,8 +19,8 @@
|
|||||||
#include <linux/pm_domain.h>
|
#include <linux/pm_domain.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
|
||||||
#include <drm/drm_dp_aux_bus.h>
|
#include <drm/dp/drm_dp_aux_bus.h>
|
||||||
#include <drm/drm_dp_helper.h>
|
#include <drm/dp/drm_dp_helper.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dp_aux_ep_match() - The match function for the dp_aux_bus.
|
* dp_aux_ep_match() - The match function for the dp_aux_bus.
|
||||||
@@ -36,11 +36,11 @@
|
|||||||
#include <linux/uio.h>
|
#include <linux/uio.h>
|
||||||
|
|
||||||
#include <drm/drm_crtc.h>
|
#include <drm/drm_crtc.h>
|
||||||
#include <drm/drm_dp_helper.h>
|
#include <drm/dp/drm_dp_helper.h>
|
||||||
#include <drm/drm_dp_mst_helper.h>
|
#include <drm/dp/drm_dp_mst_helper.h>
|
||||||
#include <drm/drm_print.h>
|
#include <drm/drm_print.h>
|
||||||
|
|
||||||
#include "drm_crtc_helper_internal.h"
|
#include "drm_dp_helper_internal.h"
|
||||||
|
|
||||||
struct drm_dp_aux_dev {
|
struct drm_dp_aux_dev {
|
||||||
unsigned index;
|
unsigned index;
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
#include <drm/drm_connector.h>
|
#include <drm/drm_connector.h>
|
||||||
#include <drm/drm_device.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
|
* Unfortunately it turns out that we have a chicken-and-egg situation
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
|
|
||||||
#include <drm/drm_device.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>
|
#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>
|
#include <linux/math64.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <drm/dp/drm_dp_mst_helper.h>
|
||||||
#include <drm/drm_atomic.h>
|
#include <drm/drm_atomic.h>
|
||||||
#include <drm/drm_atomic_helper.h>
|
#include <drm/drm_atomic_helper.h>
|
||||||
#include <drm/drm_dp_mst_helper.h>
|
|
||||||
#include <drm/drm_drv.h>
|
#include <drm/drm_drv.h>
|
||||||
#include <drm/drm_print.h>
|
#include <drm/drm_print.h>
|
||||||
#include <drm/drm_probe_helper.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"
|
#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 ret = 0;
|
||||||
int sc;
|
int sc;
|
||||||
*handled = false;
|
*handled = false;
|
||||||
sc = esi[0] & 0x3f;
|
sc = DP_GET_SINK_COUNT(esi[0]);
|
||||||
|
|
||||||
if (sc != mgr->sink_count) {
|
if (sc != mgr->sink_count) {
|
||||||
mgr->sink_count = sc;
|
mgr->sink_count = sc;
|
||||||
@@ -4811,7 +4811,7 @@ static void drm_dp_mst_dump_mstb(struct seq_file *m,
|
|||||||
|
|
||||||
seq_printf(m, "%smstb - [%p]: num_ports: %d\n", prefix, mstb, mstb->num_ports);
|
seq_printf(m, "%smstb - [%p]: num_ports: %d\n", prefix, mstb, mstb->num_ports);
|
||||||
list_for_each_entry(port, &mstb->ports, next) {
|
list_for_each_entry(port, &mstb->ports, next) {
|
||||||
seq_printf(m, "%sport %d - [%p] (%s - %s): ddps: %d, ldps: %d, sdp: %d/%d, fec: %s, conn: %p\n",
|
seq_printf(m, "%sport %d - [%p] (%s - %s): ddps: %d, ldps: %d, sdp: %d/%d, fec: %s, conn: %p\n",
|
||||||
prefix,
|
prefix,
|
||||||
port->port_num,
|
port->port_num,
|
||||||
port,
|
port,
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
#ifndef _DRM_DP_MST_HELPER_INTERNAL_H_
|
#ifndef _DRM_DP_MST_HELPER_INTERNAL_H_
|
||||||
#define _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
|
void
|
||||||
drm_dp_encode_sideband_req(const struct drm_dp_sideband_msg_req_body *req,
|
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
|
* driver boot-up state too. Drivers can access this blob through
|
||||||
* &drm_crtc_state.gamma_lut.
|
* &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”:
|
* “GAMMA_LUT_SIZE”:
|
||||||
* Unsigned range property to give the size of the lookup table to be set
|
* 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).
|
* on the GAMMA_LUT property (the size depends on the underlying hardware).
|
||||||
|
|||||||
@@ -28,36 +28,9 @@
|
|||||||
|
|
||||||
#include <drm/drm_connector.h>
|
#include <drm/drm_connector.h>
|
||||||
#include <drm/drm_crtc.h>
|
#include <drm/drm_crtc.h>
|
||||||
#include <drm/drm_dp_helper.h>
|
|
||||||
#include <drm/drm_encoder.h>
|
#include <drm/drm_encoder.h>
|
||||||
#include <drm/drm_modes.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 */
|
/* drm_probe_helper.c */
|
||||||
enum drm_mode_status drm_crtc_mode_valid(struct drm_crtc *crtc,
|
enum drm_mode_status drm_crtc_mode_valid(struct drm_crtc *crtc,
|
||||||
const struct drm_display_mode *mode);
|
const struct drm_display_mode *mode);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/byteorder/generic.h>
|
#include <linux/byteorder/generic.h>
|
||||||
#include <drm/drm_print.h>
|
#include <drm/drm_print.h>
|
||||||
#include <drm/drm_dp_helper.h>
|
#include <drm/dp/drm_dp_helper.h>
|
||||||
#include <drm/drm_dsc.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) */
|
/* Non desktop display (i.e. HMD) */
|
||||||
#define EDID_QUIRK_NON_DESKTOP (1 << 12)
|
#define EDID_QUIRK_NON_DESKTOP (1 << 12)
|
||||||
|
|
||||||
|
#define MICROSOFT_IEEE_OUI 0xca125c
|
||||||
|
|
||||||
struct detailed_mode_closure {
|
struct detailed_mode_closure {
|
||||||
struct drm_connector *connector;
|
struct drm_connector *connector;
|
||||||
struct edid *edid;
|
struct edid *edid;
|
||||||
@@ -212,9 +214,7 @@ static const struct edid_quirk {
|
|||||||
|
|
||||||
/* Windows Mixed Reality Headsets */
|
/* Windows Mixed Reality Headsets */
|
||||||
EDID_QUIRK('A', 'C', 'R', 0x7fce, EDID_QUIRK_NON_DESKTOP),
|
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', 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('F', 'U', 'J', 0x1970, EDID_QUIRK_NON_DESKTOP),
|
||||||
EDID_QUIRK('D', 'E', 'L', 0x7fce, EDID_QUIRK_NON_DESKTOP),
|
EDID_QUIRK('D', 'E', 'L', 0x7fce, EDID_QUIRK_NON_DESKTOP),
|
||||||
EDID_QUIRK('S', 'E', 'C', 0x144a, 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)
|
if (modes > 0)
|
||||||
info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;
|
info->color_formats |= DRM_COLOR_FORMAT_YCBCR420;
|
||||||
return modes;
|
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;
|
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)
|
static bool cea_db_is_vcdb(const u8 *db)
|
||||||
{
|
{
|
||||||
if (cea_db_tag(db) != USE_EXTENDED_TAG)
|
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) {
|
if (map_len == 0) {
|
||||||
/* All CEA modes support ycbcr420 sampling also.*/
|
/* All CEA modes support ycbcr420 sampling also.*/
|
||||||
hdmi->y420_cmdb_map = U64_MAX;
|
hdmi->y420_cmdb_map = U64_MAX;
|
||||||
info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;
|
info->color_formats |= DRM_COLOR_FORMAT_YCBCR420;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4302,7 +4313,7 @@ static void drm_parse_y420cmdb_bitmap(struct drm_connector *connector,
|
|||||||
map |= (u64)db[2 + count] << (8 * count);
|
map |= (u64)db[2 + count] << (8 * count);
|
||||||
|
|
||||||
if (map)
|
if (map)
|
||||||
info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;
|
info->color_formats |= DRM_COLOR_FORMAT_YCBCR420;
|
||||||
|
|
||||||
hdmi->y420_cmdb_map = map;
|
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) {
|
if (hdmi[6] & DRM_EDID_HDMI_DC_30) {
|
||||||
dc_bpc = 10;
|
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",
|
DRM_DEBUG("%s: HDMI sink does deep color 30.\n",
|
||||||
connector->name);
|
connector->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hdmi[6] & DRM_EDID_HDMI_DC_36) {
|
if (hdmi[6] & DRM_EDID_HDMI_DC_36) {
|
||||||
dc_bpc = 12;
|
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",
|
DRM_DEBUG("%s: HDMI sink does deep color 36.\n",
|
||||||
connector->name);
|
connector->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hdmi[6] & DRM_EDID_HDMI_DC_48) {
|
if (hdmi[6] & DRM_EDID_HDMI_DC_48) {
|
||||||
dc_bpc = 16;
|
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",
|
DRM_DEBUG("%s: HDMI sink does deep color 48.\n",
|
||||||
connector->name);
|
connector->name);
|
||||||
}
|
}
|
||||||
@@ -5104,16 +5115,9 @@ static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector,
|
|||||||
connector->name, dc_bpc);
|
connector->name, dc_bpc);
|
||||||
info->bpc = 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. */
|
/* YCRCB444 is optional according to spec. */
|
||||||
if (hdmi[6] & DRM_EDID_HDMI_DC_Y444) {
|
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",
|
DRM_DEBUG("%s: HDMI sink does YCRCB444 in deep color.\n",
|
||||||
connector->name);
|
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);
|
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,
|
static void drm_parse_cea_ext(struct drm_connector *connector,
|
||||||
const struct edid *edid)
|
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 */
|
/* The existence of a CEA block should imply RGB support */
|
||||||
info->color_formats = DRM_COLOR_FORMAT_RGB444;
|
info->color_formats = DRM_COLOR_FORMAT_RGB444;
|
||||||
if (edid_ext[3] & EDID_CEA_YCRCB444)
|
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)
|
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))
|
if (cea_db_offsets(edid_ext, &start, &end))
|
||||||
return;
|
return;
|
||||||
@@ -5179,6 +5202,8 @@ static void drm_parse_cea_ext(struct drm_connector *connector,
|
|||||||
drm_parse_hdmi_vsdb_video(connector, db);
|
drm_parse_hdmi_vsdb_video(connector, db);
|
||||||
if (cea_db_is_hdmi_forum_vsdb(db))
|
if (cea_db_is_hdmi_forum_vsdb(db))
|
||||||
drm_parse_hdmi_forum_vsdb(connector, 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))
|
if (cea_db_is_y420cmdb(db))
|
||||||
drm_parse_y420cmdb_bitmap(connector, db);
|
drm_parse_y420cmdb_bitmap(connector, db);
|
||||||
if (cea_db_is_vcdb(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->width_mm = edid->width_cm * 10;
|
||||||
info->height_mm = edid->height_cm * 10;
|
info->height_mm = edid->height_cm * 10;
|
||||||
|
|
||||||
info->non_desktop = !!(quirks & EDID_QUIRK_NON_DESKTOP);
|
|
||||||
|
|
||||||
drm_get_monitor_range(connector, edid);
|
drm_get_monitor_range(connector, edid);
|
||||||
|
|
||||||
DRM_DEBUG_KMS("non_desktop set to %d\n", info->non_desktop);
|
|
||||||
|
|
||||||
if (edid->revision < 3)
|
if (edid->revision < 3)
|
||||||
return quirks;
|
goto out;
|
||||||
|
|
||||||
if (!(edid->input & DRM_EDID_INPUT_DIGITAL))
|
if (!(edid->input & DRM_EDID_INPUT_DIGITAL))
|
||||||
return quirks;
|
goto out;
|
||||||
|
|
||||||
drm_parse_cea_ext(connector, edid);
|
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 */
|
/* Only defined for 1.4 with digital displays */
|
||||||
if (edid->revision < 4)
|
if (edid->revision < 4)
|
||||||
return quirks;
|
goto out;
|
||||||
|
|
||||||
switch (edid->input & DRM_EDID_DIGITAL_DEPTH_MASK) {
|
switch (edid->input & DRM_EDID_DIGITAL_DEPTH_MASK) {
|
||||||
case DRM_EDID_DIGITAL_DEPTH_6:
|
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;
|
info->color_formats |= DRM_COLOR_FORMAT_RGB444;
|
||||||
if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB444)
|
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)
|
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);
|
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;
|
return quirks;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct drm_display_mode *drm_mode_displayid_detailed(struct drm_device *dev,
|
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;
|
struct drm_display_mode *mode;
|
||||||
unsigned pixel_clock = (timings->pixel_clock[0] |
|
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)
|
if (!mode)
|
||||||
return NULL;
|
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->hdisplay = hactive;
|
||||||
mode->hsync_start = mode->hdisplay + hsync;
|
mode->hsync_start = mode->hdisplay + hsync;
|
||||||
mode->hsync_end = mode->hsync_start + hsync_width;
|
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;
|
int num_timings;
|
||||||
struct drm_display_mode *newmode;
|
struct drm_display_mode *newmode;
|
||||||
int num_modes = 0;
|
int num_modes = 0;
|
||||||
|
bool type_7 = block->tag == DATA_BLOCK_2_TYPE_7_DETAILED_TIMING;
|
||||||
/* blocks must be multiple of 20 bytes length */
|
/* blocks must be multiple of 20 bytes length */
|
||||||
if (block->num_bytes % 20)
|
if (block->num_bytes % 20)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -5465,7 +5496,7 @@ static int add_displayid_detailed_1_modes(struct drm_connector *connector,
|
|||||||
for (i = 0; i < num_timings; i++) {
|
for (i = 0; i < num_timings; i++) {
|
||||||
struct displayid_detailed_timings_1 *timings = &det->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)
|
if (!newmode)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -5484,7 +5515,8 @@ static int add_displayid_detailed_modes(struct drm_connector *connector,
|
|||||||
|
|
||||||
displayid_iter_edid_begin(edid, &iter);
|
displayid_iter_edid_begin(edid, &iter);
|
||||||
displayid_iter_for_each(block, &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);
|
num_modes += add_displayid_detailed_1_modes(connector, block);
|
||||||
}
|
}
|
||||||
displayid_iter_end(&iter);
|
displayid_iter_end(&iter);
|
||||||
@@ -5652,7 +5684,7 @@ static bool is_hdmi2_sink(const struct drm_connector *connector)
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
return connector->display_info.hdmi.scdc.supported ||
|
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)
|
static inline bool is_eotf_supported(u8 output_eotf, u8 sink_eotf)
|
||||||
@@ -5891,13 +5923,13 @@ static const u32 hdmi_colorimetry_val[] = {
|
|||||||
#undef ACE
|
#undef ACE
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* drm_hdmi_avi_infoframe_colorspace() - fill the HDMI AVI infoframe
|
* drm_hdmi_avi_infoframe_colorimetry() - fill the HDMI AVI infoframe
|
||||||
* colorspace information
|
* colorimetry information
|
||||||
* @frame: HDMI AVI infoframe
|
* @frame: HDMI AVI infoframe
|
||||||
* @conn_state: connector state
|
* @conn_state: connector state
|
||||||
*/
|
*/
|
||||||
void
|
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)
|
const struct drm_connector_state *conn_state)
|
||||||
{
|
{
|
||||||
u32 colorimetry_val;
|
u32 colorimetry_val;
|
||||||
@@ -5916,7 +5948,7 @@ drm_hdmi_avi_infoframe_colorspace(struct hdmi_avi_infoframe *frame,
|
|||||||
frame->extended_colorimetry = (colorimetry_val >> 2) &
|
frame->extended_colorimetry = (colorimetry_val >> 2) &
|
||||||
EXTENDED_COLORIMETRY_MASK;
|
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
|
* 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.");
|
"DEPRECATED. Use drm.edid_firmware module parameter instead.");
|
||||||
|
|
||||||
#endif
|
#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);
|
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);
|
mod = modifiers_ptr(blob_data);
|
||||||
for (i = 0; i < plane->modifier_count; i++) {
|
for (i = 0; i < plane->modifier_count; i++) {
|
||||||
for (j = 0; j < plane->format_count; j++) {
|
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->format_types[j],
|
||||||
plane->modifiers[i])) {
|
plane->modifiers[i])) {
|
||||||
|
|
||||||
mod->formats |= 1ULL << j;
|
mod->formats |= 1ULL << j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -223,7 +219,6 @@ static int create_in_format_blob(struct drm_device *dev, struct drm_plane *plane
|
|||||||
mod++;
|
mod++;
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
|
||||||
drm_object_attach_property(&plane->base, config->modifiers_property,
|
drm_object_attach_property(&plane->base, config->modifiers_property,
|
||||||
blob->base.id);
|
blob->base.id);
|
||||||
|
|
||||||
|
|||||||
@@ -387,7 +387,8 @@ static void drm_privacy_screen_device_release(struct device *dev)
|
|||||||
* * An ERR_PTR(errno) on failure.
|
* * An ERR_PTR(errno) on failure.
|
||||||
*/
|
*/
|
||||||
struct drm_privacy_screen *drm_privacy_screen_register(
|
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;
|
struct drm_privacy_screen *priv;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -404,6 +405,7 @@ struct drm_privacy_screen *drm_privacy_screen_register(
|
|||||||
priv->dev.parent = parent;
|
priv->dev.parent = parent;
|
||||||
priv->dev.release = drm_privacy_screen_device_release;
|
priv->dev.release = drm_privacy_screen_device_release;
|
||||||
dev_set_name(&priv->dev, "privacy_screen-%s", dev_name(parent));
|
dev_set_name(&priv->dev, "privacy_screen-%s", dev_name(parent));
|
||||||
|
priv->drvdata = data;
|
||||||
priv->ops = ops;
|
priv->ops = ops;
|
||||||
|
|
||||||
priv->ops->get_hw_state(priv);
|
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_unlock(&drm_privacy_screen_devs_lock);
|
||||||
|
|
||||||
mutex_lock(&priv->lock);
|
mutex_lock(&priv->lock);
|
||||||
|
priv->drvdata = NULL;
|
||||||
priv->ops = NULL;
|
priv->ops = NULL;
|
||||||
mutex_unlock(&priv->lock);
|
mutex_unlock(&priv->lock);
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,13 @@ static bool __init detect_thinkpad_privacy_screen(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#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 = {
|
static const struct arch_init_data arch_init_data[] __initconst = {
|
||||||
#if IS_ENABLED(CONFIG_THINKPAD_ACPI)
|
#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,
|
.detect = detect_thinkpad_privacy_screen,
|
||||||
},
|
},
|
||||||
#endif
|
#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)
|
void __init drm_privacy_screen_lookup_init(void)
|
||||||
|
|||||||
@@ -189,8 +189,7 @@ static int submit_fence_sync(struct etnaviv_gem_submit *submit)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (bo->flags & ETNA_SUBMIT_BO_WRITE) {
|
if (bo->flags & ETNA_SUBMIT_BO_WRITE) {
|
||||||
ret = dma_resv_get_fences(robj, NULL,
|
ret = dma_resv_get_fences(robj, true, &bo->nr_shared,
|
||||||
&bo->nr_shared,
|
|
||||||
&bo->shared);
|
&bo->shared);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ config DRM_EXYNOS_DP
|
|||||||
bool "Exynos specific extensions for Analogix DP driver"
|
bool "Exynos specific extensions for Analogix DP driver"
|
||||||
depends on DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON
|
depends on DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON
|
||||||
select DRM_ANALOGIX_DP
|
select DRM_ANALOGIX_DP
|
||||||
|
select DRM_DP_HELPER
|
||||||
default DRM_EXYNOS
|
default DRM_EXYNOS
|
||||||
select DRM_PANEL
|
select DRM_PANEL
|
||||||
help
|
help
|
||||||
|
|||||||
@@ -258,6 +258,7 @@ struct exynos_dsi {
|
|||||||
struct list_head bridge_chain;
|
struct list_head bridge_chain;
|
||||||
struct drm_bridge *out_bridge;
|
struct drm_bridge *out_bridge;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
|
struct drm_display_mode mode;
|
||||||
|
|
||||||
void __iomem *reg_base;
|
void __iomem *reg_base;
|
||||||
struct phy *phy;
|
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)
|
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;
|
unsigned int num_bits_resol = dsi->driver_data->num_bits_resol;
|
||||||
u32 reg;
|
u32 reg;
|
||||||
|
|
||||||
@@ -1446,6 +1447,15 @@ static void exynos_dsi_disable(struct drm_encoder *encoder)
|
|||||||
pm_runtime_put_sync(dsi->dev);
|
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
|
static enum drm_connector_status
|
||||||
exynos_dsi_detect(struct drm_connector *connector, bool force)
|
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 = {
|
static const struct drm_encoder_helper_funcs exynos_dsi_encoder_helper_funcs = {
|
||||||
.enable = exynos_dsi_enable,
|
.enable = exynos_dsi_enable,
|
||||||
.disable = exynos_dsi_disable,
|
.disable = exynos_dsi_disable,
|
||||||
|
.mode_set = exynos_dsi_mode_set,
|
||||||
};
|
};
|
||||||
|
|
||||||
MODULE_DEVICE_TABLE(of, exynos_dsi_of_match);
|
MODULE_DEVICE_TABLE(of, exynos_dsi_of_match);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
#include <drm/drm_crtc.h>
|
#include <drm/drm_crtc.h>
|
||||||
#include <drm/drm_crtc_helper.h>
|
#include <drm/drm_crtc_helper.h>
|
||||||
#include <drm/drm_dp_helper.h>
|
#include <drm/dp/drm_dp_helper.h>
|
||||||
#include <drm/drm_simple_kms_helper.h>
|
#include <drm/drm_simple_kms_helper.h>
|
||||||
|
|
||||||
#include "gma_display.h"
|
#include "gma_display.h"
|
||||||
@@ -82,7 +82,6 @@ i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading)
|
|||||||
{
|
{
|
||||||
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
||||||
int mode = MODE_I2C_START;
|
int mode = MODE_I2C_START;
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (reading)
|
if (reading)
|
||||||
mode |= MODE_I2C_READ;
|
mode |= MODE_I2C_READ;
|
||||||
@@ -90,8 +89,7 @@ i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading)
|
|||||||
mode |= MODE_I2C_WRITE;
|
mode |= MODE_I2C_WRITE;
|
||||||
algo_data->address = address;
|
algo_data->address = address;
|
||||||
algo_data->running = true;
|
algo_data->running = true;
|
||||||
ret = i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
|
return i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -122,13 +120,11 @@ static int
|
|||||||
i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte)
|
i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte)
|
||||||
{
|
{
|
||||||
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (!algo_data->running)
|
if (!algo_data->running)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL);
|
return i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL);
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -139,13 +135,11 @@ static int
|
|||||||
i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret)
|
i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret)
|
||||||
{
|
{
|
||||||
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (!algo_data->running)
|
if (!algo_data->running)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret);
|
return i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret);
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user