mirror of
https://github.com/armbian/linux-cix.git
synced 2026-01-06 12:30:45 -08:00
Merge tag 'drm-misc-next-2021-04-01' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for 5.13: UAPI Changes: Cross-subsystem Changes: Core Changes: - mst: Improve topology logging - edid: Rework and improvements for displayid Driver Changes: - anx7625: Regulators support - bridge: Support for the Chipone ICN6211, Lontium LT8912B - lt9611: Fix 4k panels handling Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20210401110552.2b3yetlgsjtlotcn@gilmour
This commit is contained in:
@@ -34,6 +34,15 @@ properties:
|
||||
description: used for reset chip control, RESET_N pin B7.
|
||||
maxItems: 1
|
||||
|
||||
vdd10-supply:
|
||||
description: Regulator that provides the supply 1.0V power.
|
||||
|
||||
vdd18-supply:
|
||||
description: Regulator that provides the supply 1.8V power.
|
||||
|
||||
vdd33-supply:
|
||||
description: Regulator that provides the supply 3.3V power.
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
@@ -55,6 +64,9 @@ properties:
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd10-supply
|
||||
- vdd18-supply
|
||||
- vdd33-supply
|
||||
- ports
|
||||
|
||||
additionalProperties: false
|
||||
@@ -72,6 +84,9 @@ examples:
|
||||
reg = <0x58>;
|
||||
enable-gpios = <&pio 45 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&pio 73 GPIO_ACTIVE_HIGH>;
|
||||
vdd10-supply = <&pp1000_mipibrdg>;
|
||||
vdd18-supply = <&pp1800_mipibrdg>;
|
||||
vdd33-supply = <&pp3300_mipibrdg>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/bridge/chipone,icn6211.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Chipone ICN6211 MIPI-DSI to RGB Converter bridge
|
||||
|
||||
maintainers:
|
||||
- Jagan Teki <jagan@amarulasolutions.com>
|
||||
|
||||
description: |
|
||||
ICN6211 is MIPI-DSI to RGB Converter bridge from chipone.
|
||||
|
||||
It has a flexible configuration of MIPI DSI signal input and
|
||||
produce RGB565, RGB666, RGB888 output format.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- chipone,icn6211
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
description: virtual channel number of a DSI peripheral
|
||||
|
||||
enable-gpios:
|
||||
description: Bridge EN pin, chip is reset when EN is low.
|
||||
|
||||
vdd1-supply:
|
||||
description: A 1.8V/2.5V/3.3V supply that power the MIPI RX.
|
||||
|
||||
vdd2-supply:
|
||||
description: A 1.8V/2.5V/3.3V supply that power the PLL.
|
||||
|
||||
vdd3-supply:
|
||||
description: A 1.8V/2.5V/3.3V supply that power the RGB output.
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
Video port for MIPI DSI input
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
Video port for MIPI DPI output (panel or connector).
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- enable-gpios
|
||||
- ports
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
dsi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
bridge@0 {
|
||||
compatible = "chipone,icn6211";
|
||||
reg = <0>;
|
||||
enable-gpios = <&r_pio 0 5 GPIO_ACTIVE_HIGH>; /* LCD-RST: PL5 */
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
bridge_in_dsi: endpoint {
|
||||
remote-endpoint = <&dsi_out_bridge>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
bridge_out_panel: endpoint {
|
||||
remote-endpoint = <&panel_out_bridge>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,102 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/bridge/lontium,lt8912b.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Lontium LT8912B MIPI to HDMI Bridge
|
||||
|
||||
maintainers:
|
||||
- Adrien Grassein <adrien.grassein@gmail.com>
|
||||
|
||||
description: |
|
||||
The LT8912B is a bridge device which convert DSI to HDMI
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- lontium,lt8912b
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
description: GPIO connected to active high RESET pin.
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
Primary MIPI port for MIPI input
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
$ref: /schemas/media/video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
data-lanes: true
|
||||
|
||||
required:
|
||||
- data-lanes
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: |
|
||||
HDMI port, should be connected to a node compatible with the
|
||||
hdmi-connector binding.
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reset-gpios
|
||||
- ports
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
i2c4 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
hdmi-bridge@48 {
|
||||
compatible = "lontium,lt8912b";
|
||||
reg = <0x48>;
|
||||
reset-gpios = <&max7323 0 GPIO_ACTIVE_LOW>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
hdmi_out_in: endpoint {
|
||||
data-lanes = <0 1 2 3>;
|
||||
remote-endpoint = <&mipi_dsi_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
endpoint {
|
||||
remote-endpoint = <&hdmi_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
@@ -161,6 +161,8 @@ properties:
|
||||
# Innolux Corporation 12.1" G121X1-L03 XGA (1024x768) TFT LCD panel
|
||||
- innolux,g121x1-l03
|
||||
# Innolux Corporation 11.6" WXGA (1366x768) TFT LCD panel
|
||||
- innolux,n116bca-ea1
|
||||
# Innolux Corporation 11.6" WXGA (1366x768) TFT LCD panel
|
||||
- innolux,n116bge
|
||||
# InnoLux 13.3" FHD (1920x1080) eDP TFT LCD panel
|
||||
- innolux,n125hce-gn1
|
||||
|
||||
@@ -257,3 +257,79 @@ fences in the kernel. This means:
|
||||
userspace is allowed to use userspace fencing or long running compute
|
||||
workloads. This also means no implicit fencing for shared buffers in these
|
||||
cases.
|
||||
|
||||
Recoverable Hardware Page Faults Implications
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Modern hardware supports recoverable page faults, which has a lot of
|
||||
implications for DMA fences.
|
||||
|
||||
First, a pending page fault obviously holds up the work that's running on the
|
||||
accelerator and a memory allocation is usually required to resolve the fault.
|
||||
But memory allocations are not allowed to gate completion of DMA fences, which
|
||||
means any workload using recoverable page faults cannot use DMA fences for
|
||||
synchronization. Synchronization fences controlled by userspace must be used
|
||||
instead.
|
||||
|
||||
On GPUs this poses a problem, because current desktop compositor protocols on
|
||||
Linux rely on DMA fences, which means without an entirely new userspace stack
|
||||
built on top of userspace fences, they cannot benefit from recoverable page
|
||||
faults. Specifically this means implicit synchronization will not be possible.
|
||||
The exception is when page faults are only used as migration hints and never to
|
||||
on-demand fill a memory request. For now this means recoverable page
|
||||
faults on GPUs are limited to pure compute workloads.
|
||||
|
||||
Furthermore GPUs usually have shared resources between the 3D rendering and
|
||||
compute side, like compute units or command submission engines. If both a 3D
|
||||
job with a DMA fence and a compute workload using recoverable page faults are
|
||||
pending they could deadlock:
|
||||
|
||||
- The 3D workload might need to wait for the compute job to finish and release
|
||||
hardware resources first.
|
||||
|
||||
- The compute workload might be stuck in a page fault, because the memory
|
||||
allocation is waiting for the DMA fence of the 3D workload to complete.
|
||||
|
||||
There are a few options to prevent this problem, one of which drivers need to
|
||||
ensure:
|
||||
|
||||
- Compute workloads can always be preempted, even when a page fault is pending
|
||||
and not yet repaired. Not all hardware supports this.
|
||||
|
||||
- DMA fence workloads and workloads which need page fault handling have
|
||||
independent hardware resources to guarantee forward progress. This could be
|
||||
achieved through e.g. through dedicated engines and minimal compute unit
|
||||
reservations for DMA fence workloads.
|
||||
|
||||
- The reservation approach could be further refined by only reserving the
|
||||
hardware resources for DMA fence workloads when they are in-flight. This must
|
||||
cover the time from when the DMA fence is visible to other threads up to
|
||||
moment when fence is completed through dma_fence_signal().
|
||||
|
||||
- As a last resort, if the hardware provides no useful reservation mechanics,
|
||||
all workloads must be flushed from the GPU when switching between jobs
|
||||
requiring DMA fences or jobs requiring page fault handling: This means all DMA
|
||||
fences must complete before a compute job with page fault handling can be
|
||||
inserted into the scheduler queue. And vice versa, before a DMA fence can be
|
||||
made visible anywhere in the system, all compute workloads must be preempted
|
||||
to guarantee all pending GPU page faults are flushed.
|
||||
|
||||
- Only a fairly theoretical option would be to untangle these dependencies when
|
||||
allocating memory to repair hardware page faults, either through separate
|
||||
memory blocks or runtime tracking of the full dependency graph of all DMA
|
||||
fences. This results very wide impact on the kernel, since resolving the page
|
||||
on the CPU side can itself involve a page fault. It is much more feasible and
|
||||
robust to limit the impact of handling hardware page faults to the specific
|
||||
driver.
|
||||
|
||||
Note that workloads that run on independent hardware like copy engines or other
|
||||
GPUs do not have any impact. This allows us to keep using DMA fences internally
|
||||
in the kernel even for resolving hardware page faults, e.g. by using copy
|
||||
engines to clear or copy memory needed to resolve the page fault.
|
||||
|
||||
In some ways this page fault problem is a special case of the `Infinite DMA
|
||||
Fences` discussions: Infinite fences from compute workloads are allowed to
|
||||
depend on DMA fences, but not the other way around. And not even the page fault
|
||||
problem is new, because some other CPU thread in userspace might
|
||||
hit a page fault which holds up a userspace fence - supporting page faults on
|
||||
GPUs doesn't anything fundamentally new.
|
||||
|
||||
@@ -677,7 +677,7 @@ Outside DRM
|
||||
Convert fbdev drivers to DRM
|
||||
----------------------------
|
||||
|
||||
There are plenty of fbdev drivers for older hardware. Some hwardware has
|
||||
There are plenty of fbdev drivers for older hardware. Some hardware has
|
||||
become obsolete, but some still provides good(-enough) framebuffers. The
|
||||
drivers that are still useful should be converted to DRM and afterwards
|
||||
removed from fbdev.
|
||||
|
||||
21
MAINTAINERS
21
MAINTAINERS
@@ -5568,6 +5568,12 @@ S: Maintained
|
||||
F: Documentation/devicetree/bindings/display/panel/boe,himax8279d.yaml
|
||||
F: drivers/gpu/drm/panel/panel-boe-himax8279d.c
|
||||
|
||||
DRM DRIVER FOR CHIPONE ICN6211 MIPI-DSI to RGB CONVERTER BRIDGE
|
||||
M: Jagan Teki <jagan@amarulasolutions.com>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/display/bridge/chipone,icn6211.yaml
|
||||
F: drivers/gpu/drm/bridge/chipone-icn6211.c
|
||||
|
||||
DRM DRIVER FOR FARADAY TVE200 TV ENCODER
|
||||
M: Linus Walleij <linus.walleij@linaro.org>
|
||||
S: Maintained
|
||||
@@ -5586,6 +5592,14 @@ S: Maintained
|
||||
F: Documentation/devicetree/bindings/display/panel/feiyang,fy07024di26a30d.yaml
|
||||
F: drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c
|
||||
|
||||
DRM DRIVER FOR GENERIC USB DISPLAY
|
||||
M: Noralf Trønnes <noralf@tronnes.org>
|
||||
S: Maintained
|
||||
W: https://github.com/notro/gud/wiki
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
F: drivers/gpu/drm/gud/
|
||||
F: include/drm/gud.h
|
||||
|
||||
DRM DRIVER FOR GRAIN MEDIA GM12U320 PROJECTORS
|
||||
M: Hans de Goede <hdegoede@redhat.com>
|
||||
S: Maintained
|
||||
@@ -5894,6 +5908,7 @@ F: drivers/gpu/drm/atmel-hlcdc/
|
||||
DRM DRIVERS FOR BRIDGE CHIPS
|
||||
M: Andrzej Hajda <a.hajda@samsung.com>
|
||||
M: Neil Armstrong <narmstrong@baylibre.com>
|
||||
M: Robert Foss <robert.foss@linaro.org>
|
||||
R: Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
|
||||
R: Jonas Karlman <jonas@kwiboo.se>
|
||||
R: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
@@ -10460,6 +10475,12 @@ S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git
|
||||
F: drivers/hid/hid-lg-g15.c
|
||||
|
||||
LONTIUM LT8912B MIPI TO HDMI BRIDGE
|
||||
M: Adrien Grassein <adrien.grassein@gmail.com>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/display/bridge/lontium,lt8912b.yaml
|
||||
F: drivers/gpu/drm/bridge/lontium-lt8912b.c
|
||||
|
||||
LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
|
||||
M: Sathya Prakash <sathya.prakash@broadcom.com>
|
||||
M: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
|
||||
|
||||
@@ -384,6 +384,8 @@ source "drivers/gpu/drm/tidss/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/xlnx/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/gud/Kconfig"
|
||||
|
||||
# Keep legacy drivers last
|
||||
|
||||
menuconfig DRM_LEGACY
|
||||
|
||||
@@ -7,7 +7,7 @@ drm-y := drm_auth.o drm_cache.o \
|
||||
drm_file.o drm_gem.o drm_ioctl.o drm_irq.o \
|
||||
drm_drv.o \
|
||||
drm_sysfs.o drm_hashtab.o drm_mm.o \
|
||||
drm_crtc.o drm_fourcc.o drm_modes.o drm_edid.o \
|
||||
drm_crtc.o drm_fourcc.o drm_modes.o drm_edid.o drm_displayid.o \
|
||||
drm_encoder_slave.o \
|
||||
drm_trace_points.o drm_prime.o \
|
||||
drm_rect.o drm_vma_manager.o drm_flip_work.o \
|
||||
@@ -125,3 +125,4 @@ obj-$(CONFIG_DRM_ASPEED_GFX) += aspeed/
|
||||
obj-$(CONFIG_DRM_MCDE) += mcde/
|
||||
obj-$(CONFIG_DRM_TIDSS) += tidss/
|
||||
obj-y += xlnx/
|
||||
obj-y += gud/
|
||||
|
||||
@@ -638,15 +638,15 @@ void amdgpu_vm_move_to_lru_tail(struct amdgpu_device *adev,
|
||||
struct amdgpu_vm_bo_base *bo_base;
|
||||
|
||||
if (vm->bulk_moveable) {
|
||||
spin_lock(&ttm_glob.lru_lock);
|
||||
spin_lock(&adev->mman.bdev.lru_lock);
|
||||
ttm_bo_bulk_move_lru_tail(&vm->lru_bulk_move);
|
||||
spin_unlock(&ttm_glob.lru_lock);
|
||||
spin_unlock(&adev->mman.bdev.lru_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&vm->lru_bulk_move, 0, sizeof(vm->lru_bulk_move));
|
||||
|
||||
spin_lock(&ttm_glob.lru_lock);
|
||||
spin_lock(&adev->mman.bdev.lru_lock);
|
||||
list_for_each_entry(bo_base, &vm->idle, vm_status) {
|
||||
struct amdgpu_bo *bo = bo_base->bo;
|
||||
|
||||
@@ -660,7 +660,7 @@ void amdgpu_vm_move_to_lru_tail(struct amdgpu_device *adev,
|
||||
&bo->shadow->tbo.mem,
|
||||
&vm->lru_bulk_move);
|
||||
}
|
||||
spin_unlock(&ttm_glob.lru_lock);
|
||||
spin_unlock(&adev->mman.bdev.lru_lock);
|
||||
|
||||
vm->bulk_moveable = true;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,19 @@ config DRM_CDNS_DSI
|
||||
Support Cadence DPI to DSI bridge. This is an internal
|
||||
bridge and is meant to be directly embedded in a SoC.
|
||||
|
||||
config DRM_CHIPONE_ICN6211
|
||||
tristate "Chipone ICN6211 MIPI-DSI/RGB Converter bridge"
|
||||
depends on OF
|
||||
select DRM_MIPI_DSI
|
||||
select DRM_PANEL_BRIDGE
|
||||
help
|
||||
ICN6211 is MIPI-DSI/RGB Converter bridge from chipone.
|
||||
|
||||
It has a flexible configuration of MIPI DSI signal input
|
||||
and produce RGB565, RGB666, RGB888 output format.
|
||||
|
||||
If in doubt, say "N".
|
||||
|
||||
config DRM_CHRONTEL_CH7033
|
||||
tristate "Chrontel CH7033 Video Encoder"
|
||||
depends on OF
|
||||
@@ -48,6 +61,20 @@ config DRM_DISPLAY_CONNECTOR
|
||||
on ARM-based platforms. Saying Y here when this driver is not needed
|
||||
will not cause any issue.
|
||||
|
||||
config DRM_LONTIUM_LT8912B
|
||||
tristate "Lontium LT8912B DSI/HDMI bridge"
|
||||
depends on OF
|
||||
select DRM_PANEL_BRIDGE
|
||||
select DRM_KMS_HELPER
|
||||
select REGMAP_I2C
|
||||
help
|
||||
Driver for Lontium LT8912B DSI to HDMI bridge
|
||||
chip driver.
|
||||
Please say Y if you have such hardware.
|
||||
|
||||
Say M here if you want to support this hardware as a module.
|
||||
The module will be named "lontium-lt8912b".
|
||||
|
||||
config DRM_LONTIUM_LT9611
|
||||
tristate "Lontium LT9611 DSI/HDMI bridge"
|
||||
select SND_SOC_HDMI_CODEC if SND_SOC
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o
|
||||
obj-$(CONFIG_DRM_CHIPONE_ICN6211) += chipone-icn6211.o
|
||||
obj-$(CONFIG_DRM_CHRONTEL_CH7033) += chrontel-ch7033.o
|
||||
obj-$(CONFIG_DRM_DISPLAY_CONNECTOR) += display-connector.o
|
||||
obj-$(CONFIG_DRM_LONTIUM_LT8912B) += lontium-lt8912b.o
|
||||
obj-$(CONFIG_DRM_LONTIUM_LT9611) += lontium-lt9611.o
|
||||
obj-$(CONFIG_DRM_LONTIUM_LT9611UXC) += lontium-lt9611uxc.o
|
||||
obj-$(CONFIG_DRM_LVDS_CODEC) += lvds-codec.o
|
||||
|
||||
@@ -550,28 +550,38 @@ static int anx6345_bridge_attach(struct drm_bridge *bridge,
|
||||
DRM_MODE_CONNECTOR_eDP);
|
||||
if (err) {
|
||||
DRM_ERROR("Failed to initialize connector: %d\n", err);
|
||||
return err;
|
||||
goto aux_unregister;
|
||||
}
|
||||
|
||||
drm_connector_helper_add(&anx6345->connector,
|
||||
&anx6345_connector_helper_funcs);
|
||||
|
||||
err = drm_connector_register(&anx6345->connector);
|
||||
if (err) {
|
||||
DRM_ERROR("Failed to register connector: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
anx6345->connector.polled = DRM_CONNECTOR_POLL_HPD;
|
||||
|
||||
err = drm_connector_attach_encoder(&anx6345->connector,
|
||||
bridge->encoder);
|
||||
if (err) {
|
||||
DRM_ERROR("Failed to link up connector to encoder: %d\n", err);
|
||||
return err;
|
||||
goto connector_cleanup;
|
||||
}
|
||||
|
||||
err = drm_connector_register(&anx6345->connector);
|
||||
if (err) {
|
||||
DRM_ERROR("Failed to register connector: %d\n", err);
|
||||
goto connector_cleanup;
|
||||
}
|
||||
|
||||
return 0;
|
||||
connector_cleanup:
|
||||
drm_connector_cleanup(&anx6345->connector);
|
||||
aux_unregister:
|
||||
drm_dp_aux_unregister(&anx6345->aux);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void anx6345_bridge_detach(struct drm_bridge *bridge)
|
||||
{
|
||||
drm_dp_aux_unregister(&bridge_to_anx6345(bridge)->aux);
|
||||
}
|
||||
|
||||
static enum drm_mode_status
|
||||
@@ -624,6 +634,7 @@ static void anx6345_bridge_enable(struct drm_bridge *bridge)
|
||||
|
||||
static const struct drm_bridge_funcs anx6345_bridge_funcs = {
|
||||
.attach = anx6345_bridge_attach,
|
||||
.detach = anx6345_bridge_detach,
|
||||
.mode_valid = anx6345_bridge_mode_valid,
|
||||
.disable = anx6345_bridge_disable,
|
||||
.enable = anx6345_bridge_enable,
|
||||
|
||||
@@ -918,28 +918,38 @@ static int anx78xx_bridge_attach(struct drm_bridge *bridge,
|
||||
DRM_MODE_CONNECTOR_DisplayPort);
|
||||
if (err) {
|
||||
DRM_ERROR("Failed to initialize connector: %d\n", err);
|
||||
return err;
|
||||
goto aux_unregister;
|
||||
}
|
||||
|
||||
drm_connector_helper_add(&anx78xx->connector,
|
||||
&anx78xx_connector_helper_funcs);
|
||||
|
||||
err = drm_connector_register(&anx78xx->connector);
|
||||
if (err) {
|
||||
DRM_ERROR("Failed to register connector: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
anx78xx->connector.polled = DRM_CONNECTOR_POLL_HPD;
|
||||
|
||||
err = drm_connector_attach_encoder(&anx78xx->connector,
|
||||
bridge->encoder);
|
||||
if (err) {
|
||||
DRM_ERROR("Failed to link up connector to encoder: %d\n", err);
|
||||
return err;
|
||||
goto connector_cleanup;
|
||||
}
|
||||
|
||||
err = drm_connector_register(&anx78xx->connector);
|
||||
if (err) {
|
||||
DRM_ERROR("Failed to register connector: %d\n", err);
|
||||
goto connector_cleanup;
|
||||
}
|
||||
|
||||
return 0;
|
||||
connector_cleanup:
|
||||
drm_connector_cleanup(&anx78xx->connector);
|
||||
aux_unregister:
|
||||
drm_dp_aux_unregister(&anx78xx->aux);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void anx78xx_bridge_detach(struct drm_bridge *bridge)
|
||||
{
|
||||
drm_dp_aux_unregister(&bridge_to_anx78xx(bridge)->aux);
|
||||
}
|
||||
|
||||
static enum drm_mode_status
|
||||
@@ -1013,6 +1023,7 @@ static void anx78xx_bridge_enable(struct drm_bridge *bridge)
|
||||
|
||||
static const struct drm_bridge_funcs anx78xx_bridge_funcs = {
|
||||
.attach = anx78xx_bridge_attach,
|
||||
.detach = anx78xx_bridge_detach,
|
||||
.mode_valid = anx78xx_bridge_mode_valid,
|
||||
.disable = anx78xx_bridge_disable,
|
||||
.mode_set = anx78xx_bridge_mode_set,
|
||||
|
||||
@@ -1782,6 +1782,7 @@ int analogix_dp_bind(struct analogix_dp_device *dp, struct drm_device *drm_dev)
|
||||
|
||||
err_disable_pm_runtime:
|
||||
pm_runtime_disable(dp->dev);
|
||||
drm_dp_aux_unregister(&dp->aux);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/workqueue.h>
|
||||
@@ -875,12 +876,25 @@ static int sp_tx_edid_read(struct anx7625_data *ctx,
|
||||
static void anx7625_power_on(struct anx7625_data *ctx)
|
||||
{
|
||||
struct device *dev = &ctx->client->dev;
|
||||
int ret, i;
|
||||
|
||||
if (!ctx->pdata.low_power_mode) {
|
||||
DRM_DEV_DEBUG_DRIVER(dev, "not low power mode!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ctx->pdata.supplies); i++) {
|
||||
ret = regulator_enable(ctx->pdata.supplies[i].consumer);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_DEBUG_DRIVER(dev, "cannot enable supply %d: %d\n",
|
||||
i, ret);
|
||||
goto reg_err;
|
||||
}
|
||||
usleep_range(2000, 2100);
|
||||
}
|
||||
|
||||
usleep_range(4000, 4100);
|
||||
|
||||
/* Power on pin enable */
|
||||
gpiod_set_value(ctx->pdata.gpio_p_on, 1);
|
||||
usleep_range(10000, 11000);
|
||||
@@ -889,11 +903,16 @@ static void anx7625_power_on(struct anx7625_data *ctx)
|
||||
usleep_range(10000, 11000);
|
||||
|
||||
DRM_DEV_DEBUG_DRIVER(dev, "power on !\n");
|
||||
return;
|
||||
reg_err:
|
||||
for (--i; i >= 0; i--)
|
||||
regulator_disable(ctx->pdata.supplies[i].consumer);
|
||||
}
|
||||
|
||||
static void anx7625_power_standby(struct anx7625_data *ctx)
|
||||
{
|
||||
struct device *dev = &ctx->client->dev;
|
||||
int ret;
|
||||
|
||||
if (!ctx->pdata.low_power_mode) {
|
||||
DRM_DEV_DEBUG_DRIVER(dev, "not low power mode!\n");
|
||||
@@ -904,6 +923,12 @@ static void anx7625_power_standby(struct anx7625_data *ctx)
|
||||
usleep_range(1000, 1100);
|
||||
gpiod_set_value(ctx->pdata.gpio_p_on, 0);
|
||||
usleep_range(1000, 1100);
|
||||
|
||||
ret = regulator_bulk_disable(ARRAY_SIZE(ctx->pdata.supplies),
|
||||
ctx->pdata.supplies);
|
||||
if (ret < 0)
|
||||
DRM_DEV_DEBUG_DRIVER(dev, "cannot disable supplies %d\n", ret);
|
||||
|
||||
DRM_DEV_DEBUG_DRIVER(dev, "power down\n");
|
||||
}
|
||||
|
||||
@@ -1742,6 +1767,15 @@ static int anx7625_i2c_probe(struct i2c_client *client,
|
||||
platform->client = client;
|
||||
i2c_set_clientdata(client, platform);
|
||||
|
||||
pdata->supplies[0].supply = "vdd10";
|
||||
pdata->supplies[1].supply = "vdd18";
|
||||
pdata->supplies[2].supply = "vdd33";
|
||||
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(pdata->supplies),
|
||||
pdata->supplies);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dev, "fail to get power supplies: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
anx7625_init_gpio(platform);
|
||||
|
||||
atomic_set(&platform->power_status, 0);
|
||||
|
||||
@@ -350,6 +350,7 @@ struct s_edid_data {
|
||||
struct anx7625_platform_data {
|
||||
struct gpio_desc *gpio_p_on;
|
||||
struct gpio_desc *gpio_reset;
|
||||
struct regulator_bulk_data supplies[3];
|
||||
struct drm_bridge *panel_bridge;
|
||||
int intp_irq;
|
||||
u32 low_power_mode;
|
||||
|
||||
293
drivers/gpu/drm/bridge/chipone-icn6211.c
Normal file
293
drivers/gpu/drm/bridge/chipone-icn6211.c
Normal file
@@ -0,0 +1,293 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2020 Amarula Solutions(India)
|
||||
* Author: Jagan Teki <jagan@amarulasolutions.com>
|
||||
*/
|
||||
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
#define HACTIVE_LI 0x20
|
||||
#define VACTIVE_LI 0x21
|
||||
#define VACTIVE_HACTIVE_HI 0x22
|
||||
#define HFP_LI 0x23
|
||||
#define HSYNC_LI 0x24
|
||||
#define HBP_LI 0x25
|
||||
#define HFP_HSW_HBP_HI 0x26
|
||||
#define VFP 0x27
|
||||
#define VSYNC 0x28
|
||||
#define VBP 0x29
|
||||
|
||||
struct chipone {
|
||||
struct device *dev;
|
||||
struct drm_bridge bridge;
|
||||
struct drm_bridge *panel_bridge;
|
||||
struct gpio_desc *enable_gpio;
|
||||
struct regulator *vdd1;
|
||||
struct regulator *vdd2;
|
||||
struct regulator *vdd3;
|
||||
};
|
||||
|
||||
static inline struct chipone *bridge_to_chipone(struct drm_bridge *bridge)
|
||||
{
|
||||
return container_of(bridge, struct chipone, bridge);
|
||||
}
|
||||
|
||||
static struct drm_display_mode *bridge_to_mode(struct drm_bridge *bridge)
|
||||
{
|
||||
return &bridge->encoder->crtc->state->adjusted_mode;
|
||||
}
|
||||
|
||||
static inline int chipone_dsi_write(struct chipone *icn, const void *seq,
|
||||
size_t len)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(icn->dev);
|
||||
|
||||
return mipi_dsi_generic_write(dsi, seq, len);
|
||||
}
|
||||
|
||||
#define ICN6211_DSI(icn, seq...) \
|
||||
{ \
|
||||
const u8 d[] = { seq }; \
|
||||
chipone_dsi_write(icn, d, ARRAY_SIZE(d)); \
|
||||
}
|
||||
|
||||
static void chipone_enable(struct drm_bridge *bridge)
|
||||
{
|
||||
struct chipone *icn = bridge_to_chipone(bridge);
|
||||
struct drm_display_mode *mode = bridge_to_mode(bridge);
|
||||
|
||||
ICN6211_DSI(icn, 0x7a, 0xc1);
|
||||
|
||||
ICN6211_DSI(icn, HACTIVE_LI, mode->hdisplay & 0xff);
|
||||
|
||||
ICN6211_DSI(icn, VACTIVE_LI, mode->vdisplay & 0xff);
|
||||
|
||||
/**
|
||||
* lsb nibble: 2nd nibble of hdisplay
|
||||
* msb nibble: 2nd nibble of vdisplay
|
||||
*/
|
||||
ICN6211_DSI(icn, VACTIVE_HACTIVE_HI,
|
||||
((mode->hdisplay >> 8) & 0xf) |
|
||||
(((mode->vdisplay >> 8) & 0xf) << 4));
|
||||
|
||||
ICN6211_DSI(icn, HFP_LI, mode->hsync_start - mode->hdisplay);
|
||||
|
||||
ICN6211_DSI(icn, HSYNC_LI, mode->hsync_end - mode->hsync_start);
|
||||
|
||||
ICN6211_DSI(icn, HBP_LI, mode->htotal - mode->hsync_end);
|
||||
|
||||
ICN6211_DSI(icn, HFP_HSW_HBP_HI, 0x00);
|
||||
|
||||
ICN6211_DSI(icn, VFP, mode->vsync_start - mode->vdisplay);
|
||||
|
||||
ICN6211_DSI(icn, VSYNC, mode->vsync_end - mode->vsync_start);
|
||||
|
||||
ICN6211_DSI(icn, VBP, mode->vtotal - mode->vsync_end);
|
||||
|
||||
/* dsi specific sequence */
|
||||
ICN6211_DSI(icn, MIPI_DCS_SET_TEAR_OFF, 0x80);
|
||||
ICN6211_DSI(icn, MIPI_DCS_SET_ADDRESS_MODE, 0x28);
|
||||
ICN6211_DSI(icn, 0xb5, 0xa0);
|
||||
ICN6211_DSI(icn, 0x5c, 0xff);
|
||||
ICN6211_DSI(icn, MIPI_DCS_SET_COLUMN_ADDRESS, 0x01);
|
||||
ICN6211_DSI(icn, MIPI_DCS_GET_POWER_SAVE, 0x92);
|
||||
ICN6211_DSI(icn, 0x6b, 0x71);
|
||||
ICN6211_DSI(icn, 0x69, 0x2b);
|
||||
ICN6211_DSI(icn, MIPI_DCS_ENTER_SLEEP_MODE, 0x40);
|
||||
ICN6211_DSI(icn, MIPI_DCS_EXIT_SLEEP_MODE, 0x98);
|
||||
|
||||
/* icn6211 specific sequence */
|
||||
ICN6211_DSI(icn, 0xb6, 0x20);
|
||||
ICN6211_DSI(icn, 0x51, 0x20);
|
||||
ICN6211_DSI(icn, 0x09, 0x10);
|
||||
|
||||
usleep_range(10000, 11000);
|
||||
}
|
||||
|
||||
static void chipone_pre_enable(struct drm_bridge *bridge)
|
||||
{
|
||||
struct chipone *icn = bridge_to_chipone(bridge);
|
||||
int ret;
|
||||
|
||||
if (icn->vdd1) {
|
||||
ret = regulator_enable(icn->vdd1);
|
||||
if (ret)
|
||||
DRM_DEV_ERROR(icn->dev,
|
||||
"failed to enable VDD1 regulator: %d\n", ret);
|
||||
}
|
||||
|
||||
if (icn->vdd2) {
|
||||
ret = regulator_enable(icn->vdd2);
|
||||
if (ret)
|
||||
DRM_DEV_ERROR(icn->dev,
|
||||
"failed to enable VDD2 regulator: %d\n", ret);
|
||||
}
|
||||
|
||||
if (icn->vdd3) {
|
||||
ret = regulator_enable(icn->vdd3);
|
||||
if (ret)
|
||||
DRM_DEV_ERROR(icn->dev,
|
||||
"failed to enable VDD3 regulator: %d\n", ret);
|
||||
}
|
||||
|
||||
gpiod_set_value(icn->enable_gpio, 1);
|
||||
|
||||
usleep_range(10000, 11000);
|
||||
}
|
||||
|
||||
static void chipone_post_disable(struct drm_bridge *bridge)
|
||||
{
|
||||
struct chipone *icn = bridge_to_chipone(bridge);
|
||||
|
||||
if (icn->vdd1)
|
||||
regulator_disable(icn->vdd1);
|
||||
|
||||
if (icn->vdd2)
|
||||
regulator_disable(icn->vdd2);
|
||||
|
||||
if (icn->vdd3)
|
||||
regulator_disable(icn->vdd3);
|
||||
|
||||
gpiod_set_value(icn->enable_gpio, 0);
|
||||
}
|
||||
|
||||
static int chipone_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags)
|
||||
{
|
||||
struct chipone *icn = bridge_to_chipone(bridge);
|
||||
|
||||
return drm_bridge_attach(bridge->encoder, icn->panel_bridge, bridge, flags);
|
||||
}
|
||||
|
||||
static const struct drm_bridge_funcs chipone_bridge_funcs = {
|
||||
.attach = chipone_attach,
|
||||
.post_disable = chipone_post_disable,
|
||||
.pre_enable = chipone_pre_enable,
|
||||
.enable = chipone_enable,
|
||||
};
|
||||
|
||||
static int chipone_parse_dt(struct chipone *icn)
|
||||
{
|
||||
struct device *dev = icn->dev;
|
||||
struct drm_panel *panel;
|
||||
int ret;
|
||||
|
||||
icn->vdd1 = devm_regulator_get_optional(dev, "vdd1");
|
||||
if (IS_ERR(icn->vdd1)) {
|
||||
ret = PTR_ERR(icn->vdd1);
|
||||
if (ret == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
icn->vdd1 = NULL;
|
||||
DRM_DEV_DEBUG(dev, "failed to get VDD1 regulator: %d\n", ret);
|
||||
}
|
||||
|
||||
icn->vdd2 = devm_regulator_get_optional(dev, "vdd2");
|
||||
if (IS_ERR(icn->vdd2)) {
|
||||
ret = PTR_ERR(icn->vdd2);
|
||||
if (ret == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
icn->vdd2 = NULL;
|
||||
DRM_DEV_DEBUG(dev, "failed to get VDD2 regulator: %d\n", ret);
|
||||
}
|
||||
|
||||
icn->vdd3 = devm_regulator_get_optional(dev, "vdd3");
|
||||
if (IS_ERR(icn->vdd3)) {
|
||||
ret = PTR_ERR(icn->vdd3);
|
||||
if (ret == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
icn->vdd3 = NULL;
|
||||
DRM_DEV_DEBUG(dev, "failed to get VDD3 regulator: %d\n", ret);
|
||||
}
|
||||
|
||||
icn->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(icn->enable_gpio)) {
|
||||
DRM_DEV_ERROR(dev, "failed to get enable GPIO\n");
|
||||
return PTR_ERR(icn->enable_gpio);
|
||||
}
|
||||
|
||||
ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
icn->panel_bridge = devm_drm_panel_bridge_add(dev, panel);
|
||||
if (IS_ERR(icn->panel_bridge))
|
||||
return PTR_ERR(icn->panel_bridge);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int chipone_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
struct chipone *icn;
|
||||
int ret;
|
||||
|
||||
icn = devm_kzalloc(dev, sizeof(struct chipone), GFP_KERNEL);
|
||||
if (!icn)
|
||||
return -ENOMEM;
|
||||
|
||||
mipi_dsi_set_drvdata(dsi, icn);
|
||||
icn->dev = dev;
|
||||
|
||||
ret = chipone_parse_dt(icn);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
icn->bridge.funcs = &chipone_bridge_funcs;
|
||||
icn->bridge.type = DRM_MODE_CONNECTOR_DPI;
|
||||
icn->bridge.of_node = dev->of_node;
|
||||
|
||||
drm_bridge_add(&icn->bridge);
|
||||
|
||||
dsi->lanes = 4;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
|
||||
|
||||
ret = mipi_dsi_attach(dsi);
|
||||
if (ret < 0) {
|
||||
drm_bridge_remove(&icn->bridge);
|
||||
dev_err(dev, "failed to attach dsi\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int chipone_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct chipone *icn = mipi_dsi_get_drvdata(dsi);
|
||||
|
||||
mipi_dsi_detach(dsi);
|
||||
drm_bridge_remove(&icn->bridge);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id chipone_of_match[] = {
|
||||
{ .compatible = "chipone,icn6211", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, chipone_of_match);
|
||||
|
||||
static struct mipi_dsi_driver chipone_driver = {
|
||||
.probe = chipone_probe,
|
||||
.remove = chipone_remove,
|
||||
.driver = {
|
||||
.name = "chipone-icn6211",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = chipone_of_match,
|
||||
},
|
||||
};
|
||||
module_mipi_dsi_driver(chipone_driver);
|
||||
|
||||
MODULE_AUTHOR("Jagan Teki <jagan@amarulasolutions.com>");
|
||||
MODULE_DESCRIPTION("Chipone ICN6211 MIPI-DSI to RGB Converter Bridge");
|
||||
MODULE_LICENSE("GPL");
|
||||
765
drivers/gpu/drm/bridge/lontium-lt8912b.c
Normal file
765
drivers/gpu/drm/bridge/lontium-lt8912b.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -867,8 +867,14 @@ static enum drm_mode_status lt9611_bridge_mode_valid(struct drm_bridge *bridge,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
struct lt9611_mode *lt9611_mode = lt9611_find_mode(mode);
|
||||
struct lt9611 *lt9611 = bridge_to_lt9611(bridge);
|
||||
|
||||
return lt9611_mode ? MODE_OK : MODE_BAD;
|
||||
if (!lt9611_mode)
|
||||
return MODE_BAD;
|
||||
else if (lt9611_mode->intfs > 1 && !lt9611->dsi1)
|
||||
return MODE_PANEL;
|
||||
else
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static void lt9611_bridge_pre_enable(struct drm_bridge *bridge)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user