drm-misc-next for v5.6:

UAPI Changes:
 
 Cross-subsystem Changes:
 - Convert simple panel bindings to a template.
 
 Core Changes:
 - Revert drm-bridge-state changes, it causes a dependency error
   between drm and drm_kms_helper.
 - Fix when disabling crc's.
 - Assorted Kconfig fixes.
 
 Driver Changes:
 - Add ddc symlinks to more drivers.
 - Fix chained bridge handling in exynos and vc4.
 - More clock rate fixes in sun4i.
 - Add support for AUO B116XAK01, GiantPlus GPM940B0, Sony ACX424AKP,
   BOE NV140FHM-N49, Satoz SAT050AT40H12R2 and Sharp LS020B1DD01D panels.
 - Assorted small bugfixes.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEuXvWqAysSYEJGuVH/lWMcqZwE8MFAl4YZQEACgkQ/lWMcqZw
 E8OLZA/+NOx1QWnXNV/PgMc8aleGGOuqnezWRZr7yb1Ai+oaDk7cmc5sARu1/K0P
 tiMohehLOyYTu254I5xn+8jbaw1AhZcS3IGT27ayXz6MJPM3feE5uv/0pEyhd3Jc
 8AZ82Y12wGgWxEMiOH8YONoseEObTcVxiubmLz7GdNu4m+T7qa6D8Gh1B1rbZqVj
 5H00yHvuJuHMQu81fSJVNEt5VhxEqQGnAzRQ28cvVxb6VD5y6xCvY3vMz/63/+UO
 8f2irsSydqAAeKQ33obcS6nBy394YxKDwCPsMR8zo6DMIw7xp4iuR1k39J3JYV8+
 3RIxAq1aOBRrIYVxzqNTztM5A2bo5gxUV8gYw34Jkv6sHAgtOiAU8zyZUbt8A/Mx
 69FVFQ26uww+1ccgEWnrJi+8lafkublgJRsZ+u5/u+dY4aHPeEhxWCpx1O3X1dwU
 bASsRp26KLK+e4TJpg3Xk6lOZrepkJsuHdewIuwgs4kWKz5xMWi2tlXO2yGTLfor
 B8H38VvmFSkRLqthVWOKWe/Geoe3G36X3O4YiSAcT9wVZmGy77maJfppvfAP/hlO
 SItIn4Z4B4zSyrQ5T0n26LcWKenRKVMbtPcF14gxdgGx4QpMrYnIO25gL10upyXN
 eFLDZm3spUf5YPVAYmtSHqVQeA9HJ9YEfbwAdJ8LTTOVKs7OhXM=
 =P/VK
 -----END PGP SIGNATURE-----

Merge tag 'drm-misc-next-2020-01-10' of git://anongit.freedesktop.org/drm/drm-misc into drm-next

drm-misc-next for v5.6:

UAPI Changes:

Cross-subsystem Changes:
- Convert simple panel bindings to a template.

Core Changes:
- Revert drm-bridge-state changes, it causes a dependency error
  between drm and drm_kms_helper.
- Fix when disabling crc's.
- Assorted Kconfig fixes.

Driver Changes:
- Add ddc symlinks to more drivers.
- Fix chained bridge handling in exynos and vc4.
- More clock rate fixes in sun4i.
- Add support for AUO B116XAK01, GiantPlus GPM940B0, Sony ACX424AKP,
  BOE NV140FHM-N49, Satoz SAT050AT40H12R2 and Sharp LS020B1DD01D panels.
- Assorted small bugfixes.

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/1e8d4944-68d7-0df3-f39b-31f6fba22a2a@linux.intel.com
This commit is contained in:
Dave Airlie 2020-01-13 11:53:01 +10:00
commit 79f88da22b
54 changed files with 3531 additions and 1660 deletions

View File

@ -0,0 +1,291 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/allwinner,sun4i-a10-display-backend.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Allwinner A10 Display Engine Backend Device Tree Bindings
maintainers:
- Chen-Yu Tsai <wens@csie.org>
- Maxime Ripard <mripard@kernel.org>
description: |
The display engine backend exposes layers and sprites to the system.
properties:
compatible:
enum:
- allwinner,sun4i-a10-display-backend
- allwinner,sun5i-a13-display-backend
- allwinner,sun6i-a31-display-backend
- allwinner,sun7i-a20-display-backend
- allwinner,sun8i-a23-display-backend
- allwinner,sun8i-a33-display-backend
- allwinner,sun9i-a80-display-backend
reg:
minItems: 1
maxItems: 2
items:
- description: Display Backend registers
- description: SAT registers
reg-names:
minItems: 1
maxItems: 2
items:
- const: be
- const: sat
interrupts:
maxItems: 1
clocks:
minItems: 3
maxItems: 4
items:
- description: The backend interface clock
- description: The backend module clock
- description: The backend DRAM clock
- description: The SAT clock
clock-names:
minItems: 3
maxItems: 4
items:
- const: ahb
- const: mod
- const: ram
- const: sat
resets:
minItems: 1
maxItems: 2
items:
- description: The Backend reset line
- description: The SAT reset line
reset-names:
minItems: 1
maxItems: 2
items:
- const: be
- const: sat
# FIXME: This should be made required eventually once every SoC will
# have the MBUS declared.
interconnects:
maxItems: 1
# FIXME: This should be made required eventually once every SoC will
# have the MBUS declared.
interconnect-names:
const: dma-mem
ports:
type: object
description: |
A ports node with endpoint definitions as defined in
Documentation/devicetree/bindings/media/video-interfaces.txt.
properties:
"#address-cells":
const: 1
"#size-cells":
const: 0
port@0:
type: object
description: |
Input endpoints of the controller.
port@1:
type: object
description: |
Output endpoints of the controller.
required:
- "#address-cells"
- "#size-cells"
- port@0
- port@1
additionalProperties: false
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
- resets
- ports
additionalProperties: false
if:
properties:
compatible:
contains:
const: allwinner,sun8i-a33-display-backend
then:
properties:
reg:
minItems: 2
reg-names:
minItems: 2
clocks:
minItems: 4
clock-names:
minItems: 4
resets:
minItems: 2
reset-names:
minItems: 2
required:
- reg-names
- reset-names
else:
properties:
reg:
maxItems: 1
reg-names:
maxItems: 1
clocks:
maxItems: 3
clock-names:
maxItems: 3
resets:
maxItems: 1
reset-names:
maxItems: 1
examples:
- |
/*
* This comes from the clock/sun4i-a10-ccu.h and
* reset/sun4i-a10-ccu.h headers, but we can't include them since
* it would trigger a bunch of warnings for redefinitions of
* symbols with the other example.
*/
#define CLK_AHB_DE_BE0 42
#define CLK_DRAM_DE_BE0 140
#define CLK_DE_BE0 144
#define RST_DE_BE0 5
display-backend@1e60000 {
compatible = "allwinner,sun4i-a10-display-backend";
reg = <0x01e60000 0x10000>;
interrupts = <47>;
clocks = <&ccu CLK_AHB_DE_BE0>, <&ccu CLK_DE_BE0>,
<&ccu CLK_DRAM_DE_BE0>;
clock-names = "ahb", "mod",
"ram";
resets = <&ccu RST_DE_BE0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
endpoint@0 {
reg = <0>;
remote-endpoint = <&fe0_out_be0>;
};
endpoint@1 {
reg = <1>;
remote-endpoint = <&fe1_out_be0>;
};
};
port@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
endpoint@0 {
reg = <0>;
remote-endpoint = <&tcon0_in_be0>;
};
endpoint@1 {
reg = <1>;
remote-endpoint = <&tcon1_in_be0>;
};
};
};
};
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
/*
* This comes from the clock/sun8i-a23-a33-ccu.h and
* reset/sun8i-a23-a33-ccu.h headers, but we can't include them
* since it would trigger a bunch of warnings for redefinitions of
* symbols with the other example.
*/
#define CLK_BUS_DE_BE 40
#define CLK_BUS_SAT 46
#define CLK_DRAM_DE_BE 84
#define CLK_DE_BE 85
#define RST_BUS_DE_BE 21
#define RST_BUS_SAT 27
display-backend@1e60000 {
compatible = "allwinner,sun8i-a33-display-backend";
reg = <0x01e60000 0x10000>, <0x01e80000 0x1000>;
reg-names = "be", "sat";
interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_DE_BE>, <&ccu CLK_DE_BE>,
<&ccu CLK_DRAM_DE_BE>, <&ccu CLK_BUS_SAT>;
clock-names = "ahb", "mod",
"ram", "sat";
resets = <&ccu RST_BUS_DE_BE>, <&ccu RST_BUS_SAT>;
reset-names = "be", "sat";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
endpoint {
remote-endpoint = <&fe0_out_be0>;
};
};
port@1 {
reg = <1>;
endpoint {
remote-endpoint = <&drc0_in_be0>;
};
};
};
};
...

View File

@ -0,0 +1,114 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/allwinner,sun4i-a10-display-engine.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Allwinner A10 Display Engine Pipeline Device Tree Bindings
maintainers:
- Chen-Yu Tsai <wens@csie.org>
- Maxime Ripard <mripard@kernel.org>
description: |
The display engine pipeline (and its entry point, since it can be
either directly the backend or the frontend) is represented as an
extra node.
The Allwinner A10 Display pipeline is composed of several components
that are going to be documented below:
For all connections between components up to the TCONs in the
display pipeline, when there are multiple components of the same
type at the same depth, the local endpoint ID must be the same as
the remote component's index. For example, if the remote endpoint is
Frontend 1, then the local endpoint ID must be 1.
Frontend 0 [0] ------- [0] Backend 0 [0] ------- [0] TCON 0
[1] -- -- [1] [1] -- -- [1]
\ / \ /
X X
/ \ / \
[0] -- -- [0] [0] -- -- [0]
Frontend 1 [1] ------- [1] Backend 1 [1] ------- [1] TCON 1
For a two pipeline system such as the one depicted above, the lines
represent the connections between the components, while the numbers
within the square brackets corresponds to the ID of the local endpoint.
The same rule also applies to DE 2.0 mixer-TCON connections:
Mixer 0 [0] ----------- [0] TCON 0
[1] ---- ---- [1]
\ /
X
/ \
[0] ---- ---- [0]
Mixer 1 [1] ----------- [1] TCON 1
properties:
compatible:
enum:
- allwinner,sun4i-a10-display-engine
- allwinner,sun5i-a10s-display-engine
- allwinner,sun5i-a13-display-engine
- allwinner,sun6i-a31-display-engine
- allwinner,sun6i-a31s-display-engine
- allwinner,sun7i-a20-display-engine
- allwinner,sun8i-a23-display-engine
- allwinner,sun8i-a33-display-engine
- allwinner,sun8i-a83t-display-engine
- allwinner,sun8i-h3-display-engine
- allwinner,sun8i-r40-display-engine
- allwinner,sun8i-v3s-display-engine
- allwinner,sun9i-a80-display-engine
- allwinner,sun50i-a64-display-engine
- allwinner,sun50i-h6-display-engine
allwinner,pipelines:
allOf:
- $ref: /schemas/types.yaml#/definitions/phandle-array
- minItems: 1
maxItems: 2
description: |
Available display engine frontends (DE 1.0) or mixers (DE
2.0/3.0) available.
required:
- compatible
- allwinner,pipelines
additionalProperties: false
if:
properties:
compatible:
contains:
enum:
- allwinner,sun4i-a10-display-engine
- allwinner,sun6i-a31-display-engine
- allwinner,sun6i-a31s-display-engine
- allwinner,sun7i-a20-display-engine
- allwinner,sun8i-a83t-display-engine
- allwinner,sun8i-r40-display-engine
- allwinner,sun9i-a80-display-engine
- allwinner,sun50i-a64-display-engine
then:
properties:
allwinner,pipelines:
minItems: 2
else:
properties:
allwinner,pipelines:
maxItems: 1
examples:
- |
de: display-engine {
compatible = "allwinner,sun4i-a10-display-engine";
allwinner,pipelines = <&fe0>, <&fe1>;
};
...

View File

@ -0,0 +1,138 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/allwinner,sun4i-a10-display-frontend.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Allwinner A10 Display Engine Frontend Device Tree Bindings
maintainers:
- Chen-Yu Tsai <wens@csie.org>
- Maxime Ripard <mripard@kernel.org>
description: |
The display engine frontend does formats conversion, scaling,
deinterlacing and color space conversion.
properties:
compatible:
enum:
- allwinner,sun4i-a10-display-frontend
- allwinner,sun5i-a13-display-frontend
- allwinner,sun6i-a31-display-frontend
- allwinner,sun7i-a20-display-frontend
- allwinner,sun8i-a23-display-frontend
- allwinner,sun8i-a33-display-frontend
- allwinner,sun9i-a80-display-frontend
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
items:
- description: The frontend interface clock
- description: The frontend module clock
- description: The frontend DRAM clock
clock-names:
items:
- const: ahb
- const: mod
- const: ram
# FIXME: This should be made required eventually once every SoC will
# have the MBUS declared.
interconnects:
maxItems: 1
# FIXME: This should be made required eventually once every SoC will
# have the MBUS declared.
interconnect-names:
const: dma-mem
resets:
maxItems: 1
ports:
type: object
description: |
A ports node with endpoint definitions as defined in
Documentation/devicetree/bindings/media/video-interfaces.txt.
properties:
"#address-cells":
const: 1
"#size-cells":
const: 0
port@0:
type: object
description: |
Input endpoints of the controller.
port@1:
type: object
description: |
Output endpoints of the controller.
required:
- "#address-cells"
- "#size-cells"
- port@1
additionalProperties: false
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
- resets
- ports
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/sun4i-a10-ccu.h>
#include <dt-bindings/reset/sun4i-a10-ccu.h>
fe0: display-frontend@1e00000 {
compatible = "allwinner,sun4i-a10-display-frontend";
reg = <0x01e00000 0x20000>;
interrupts = <47>;
clocks = <&ccu CLK_AHB_DE_FE0>, <&ccu CLK_DE_FE0>,
<&ccu CLK_DRAM_DE_FE0>;
clock-names = "ahb", "mod",
"ram";
resets = <&ccu RST_DE_FE0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
fe0_out: port@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
fe0_out_be0: endpoint@0 {
reg = <0>;
remote-endpoint = <&be0_in_fe0>;
};
fe0_out_be1: endpoint@1 {
reg = <1>;
remote-endpoint = <&be1_in_fe0>;
};
};
};
};
...

View File

@ -0,0 +1,183 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/allwinner,sun4i-a10-hdmi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Allwinner A10 HDMI Controller Device Tree Bindings
description: |
The HDMI Encoder supports the HDMI video and audio outputs, and does
CEC. It is one end of the pipeline.
maintainers:
- Chen-Yu Tsai <wens@csie.org>
- Maxime Ripard <mripard@kernel.org>
properties:
compatible:
oneOf:
- const: allwinner,sun4i-a10-hdmi
- const: allwinner,sun5i-a10s-hdmi
- const: allwinner,sun6i-a31-hdmi
- items:
- const: allwinner,sun7i-a20-hdmi
- const: allwinner,sun5i-a10s-hdmi
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
oneOf:
- items:
- description: The HDMI interface clock
- description: The HDMI module clock
- description: The first video PLL
- description: The second video PLL
- items:
- description: The HDMI interface clock
- description: The HDMI module clock
- description: The HDMI DDC clock
- description: The first video PLL
- description: The second video PLL
clock-names:
oneOf:
- items:
- const: ahb
- const: mod
- const: pll-0
- const: pll-1
- items:
- const: ahb
- const: mod
- const: ddc
- const: pll-0
- const: pll-1
resets:
maxItems: 1
dmas:
items:
- description: DDC Transmission DMA Channel
- description: DDC Reception DMA Channel
- description: Audio Transmission DMA Channel
dma-names:
items:
- const: ddc-tx
- const: ddc-rx
- const: audio-tx
ports:
type: object
description: |
A ports node with endpoint definitions as defined in
Documentation/devicetree/bindings/media/video-interfaces.txt.
properties:
"#address-cells":
const: 1
"#size-cells":
const: 0
port@0:
type: object
description: |
Input endpoints of the controller.
port@1:
type: object
description: |
Output endpoints of the controller. Usually an HDMI
connector.
required:
- "#address-cells"
- "#size-cells"
- port@0
- port@1
additionalProperties: false
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
- dmas
- dma-names
if:
properties:
compatible:
contains:
const: allwinner,sun6i-a31-hdmi
then:
properties:
clocks:
minItems: 5
clock-names:
minItems: 5
required:
- resets
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/sun4i-a10-ccu.h>
#include <dt-bindings/dma/sun4i-a10.h>
#include <dt-bindings/reset/sun4i-a10-ccu.h>
hdmi: hdmi@1c16000 {
compatible = "allwinner,sun4i-a10-hdmi";
reg = <0x01c16000 0x1000>;
interrupts = <58>;
clocks = <&ccu CLK_AHB_HDMI0>, <&ccu CLK_HDMI>,
<&ccu CLK_PLL_VIDEO0_2X>,
<&ccu CLK_PLL_VIDEO1_2X>;
clock-names = "ahb", "mod", "pll-0", "pll-1";
dmas = <&dma SUN4I_DMA_NORMAL 16>,
<&dma SUN4I_DMA_NORMAL 16>,
<&dma SUN4I_DMA_DEDICATED 24>;
dma-names = "ddc-tx", "ddc-rx", "audio-tx";
ports {
#address-cells = <1>;
#size-cells = <0>;
hdmi_in: port@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
hdmi_in_tcon0: endpoint@0 {
reg = <0>;
remote-endpoint = <&tcon0_out_hdmi>;
};
hdmi_in_tcon1: endpoint@1 {
reg = <1>;
remote-endpoint = <&tcon1_out_hdmi>;
};
};
hdmi_out: port@1 {
reg = <1>;
};
};
};
...

View File

@ -0,0 +1,676 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/allwinner,sun4i-a10-tcon.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Allwinner A10 Timings Controller (TCON) Device Tree Bindings
maintainers:
- Chen-Yu Tsai <wens@csie.org>
- Maxime Ripard <mripard@kernel.org>
description: |
The TCON acts as a timing controller for RGB, LVDS and TV
interfaces.
properties:
"#clock-cells":
const: 0
compatible:
oneOf:
- const: allwinner,sun4i-a10-tcon
- const: allwinner,sun5i-a13-tcon
- const: allwinner,sun6i-a31-tcon
- const: allwinner,sun6i-a31s-tcon
- const: allwinner,sun7i-a20-tcon
- const: allwinner,sun8i-a23-tcon
- const: allwinner,sun8i-a33-tcon
- const: allwinner,sun8i-a83t-tcon-lcd
- const: allwinner,sun8i-a83t-tcon-tv
- const: allwinner,sun8i-r40-tcon-tv
- const: allwinner,sun8i-v3s-tcon
- const: allwinner,sun9i-a80-tcon-lcd
- const: allwinner,sun9i-a80-tcon-tv
- items:
- enum:
- allwinner,sun50i-a64-tcon-lcd
- const: allwinner,sun8i-a83t-tcon-lcd
- items:
- enum:
- allwinner,sun8i-h3-tcon-tv
- allwinner,sun50i-a64-tcon-tv
- allwinner,sun50i-h6-tcon-tv
- const: allwinner,sun8i-a83t-tcon-tv
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
minItems: 1
maxItems: 4
clock-names:
minItems: 1
maxItems: 4
clock-output-names:
allOf:
- $ref: /schemas/types.yaml#/definitions/string-array
- maxItems: 1
description:
Name of the LCD pixel clock created.
dmas:
maxItems: 1
resets:
anyOf:
- items:
- description: TCON Reset Line
- items:
- description: TCON Reset Line
- description: TCON LVDS Reset Line
- items:
- description: TCON Reset Line
- description: TCON eDP Reset Line
- items:
- description: TCON Reset Line
- description: TCON eDP Reset Line
- description: TCON LVDS Reset Line
reset-names:
oneOf:
- const: lcd
- items:
- const: lcd
- const: lvds
- items:
- const: lcd
- const: edp
- items:
- const: lcd
- const: edp
- const: lvds
ports:
type: object
description: |
A ports node with endpoint definitions as defined in
Documentation/devicetree/bindings/media/video-interfaces.txt.
properties:
"#address-cells":
const: 1
"#size-cells":
const: 0
port@0:
type: object
description: |
Input endpoints of the controller.
port@1:
type: object
description: |
Output endpoints of the controller.
patternProperties:
"^endpoint(@[0-9])$":
type: object
properties:
allwinner,tcon-channel:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
TCON can have 1 or 2 channels, usually with the
first channel being used for the panels interfaces
(RGB, LVDS, etc.), and the second being used for the
outputs that require another controller (TV Encoder,
HDMI, etc.).
If that property is present, specifies the TCON
channel the endpoint is associated to. If that
property is not present, the endpoint number will be
used as the channel number.
unevaluatedProperties: true
required:
- "#address-cells"
- "#size-cells"
- port@0
- port@1
additionalProperties: false
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
- resets
- ports
additionalProperties: false
allOf:
- if:
properties:
compatible:
contains:
enum:
- allwinner,sun4i-a10-tcon
- allwinner,sun5i-a13-tcon
- allwinner,sun7i-a20-tcon
then:
properties:
clocks:
minItems: 3
clock-names:
items:
- const: ahb
- const: tcon-ch0
- const: tcon-ch1
- if:
properties:
compatible:
contains:
enum:
- allwinner,sun6i-a31-tcon
- allwinner,sun6i-a31s-tcon
then:
properties:
clocks:
minItems: 4
clock-names:
items:
- const: ahb
- const: tcon-ch0
- const: tcon-ch1
- const: lvds-alt
- if:
properties:
compatible:
contains:
enum:
- allwinner,sun8i-a23-tcon
- allwinner,sun8i-a33-tcon
then:
properties:
clocks:
minItems: 3
clock-names:
items:
- const: ahb
- const: tcon-ch0
- const: lvds-alt
- if:
properties:
compatible:
contains:
enum:
- allwinner,sun8i-a83t-tcon-lcd
- allwinner,sun8i-v3s-tcon
- allwinner,sun9i-a80-tcon-lcd
then:
properties:
clocks:
minItems: 2
clock-names:
items:
- const: ahb
- const: tcon-ch0
- if:
properties:
compatible:
contains:
enum:
- allwinner,sun8i-a83t-tcon-tv
- allwinner,sun8i-r40-tcon-tv
- allwinner,sun9i-a80-tcon-tv
then:
properties:
clocks:
minItems: 2
clock-names:
items:
- const: ahb
- const: tcon-ch1
- if:
properties:
compatible:
contains:
enum:
- allwinner,sun5i-a13-tcon
- allwinner,sun6i-a31-tcon
- allwinner,sun6i-a31s-tcon
- allwinner,sun7i-a20-tcon
- allwinner,sun8i-a23-tcon
- allwinner,sun8i-a33-tcon
- allwinner,sun8i-v3s-tcon
- allwinner,sun9i-a80-tcon-lcd
- allwinner,sun4i-a10-tcon
- allwinner,sun8i-a83t-tcon-lcd
then:
required:
- "#clock-cells"
- clock-output-names
- if:
properties:
compatible:
contains:
enum:
- allwinner,sun6i-a31-tcon
- allwinner,sun6i-a31s-tcon
- allwinner,sun8i-a23-tcon
- allwinner,sun8i-a33-tcon
- allwinner,sun8i-a83t-tcon-lcd
then:
properties:
resets:
minItems: 2
reset-names:
items:
- const: lcd
- const: lvds
- if:
properties:
compatible:
contains:
enum:
- allwinner,sun9i-a80-tcon-lcd
then:
properties:
resets:
minItems: 3
reset-names:
items:
- const: lcd
- const: edp
- const: lvds
- if:
properties:
compatible:
contains:
enum:
- allwinner,sun9i-a80-tcon-tv
then:
properties:
resets:
minItems: 2
reset-names:
items:
- const: lcd
- const: edp
- if:
properties:
compatible:
contains:
enum:
- allwinner,sun4i-a10-tcon
- allwinner,sun5i-a13-tcon
- allwinner,sun6i-a31-tcon
- allwinner,sun6i-a31s-tcon
- allwinner,sun7i-a20-tcon
- allwinner,sun8i-a23-tcon
- allwinner,sun8i-a33-tcon
then:
required:
- dmas
examples:
- |
#include <dt-bindings/dma/sun4i-a10.h>
/*
* This comes from the clock/sun4i-a10-ccu.h and
* reset/sun4i-a10-ccu.h headers, but we can't include them since
* it would trigger a bunch of warnings for redefinitions of
* symbols with the other example.
*/
#define CLK_AHB_LCD0 56
#define CLK_TCON0_CH0 149
#define CLK_TCON0_CH1 155
#define RST_TCON0 11
lcd-controller@1c0c000 {
compatible = "allwinner,sun4i-a10-tcon";
reg = <0x01c0c000 0x1000>;
interrupts = <44>;
resets = <&ccu RST_TCON0>;
reset-names = "lcd";
clocks = <&ccu CLK_AHB_LCD0>,
<&ccu CLK_TCON0_CH0>,
<&ccu CLK_TCON0_CH1>;
clock-names = "ahb",
"tcon-ch0",
"tcon-ch1";
clock-output-names = "tcon0-pixel-clock";
#clock-cells = <0>;
dmas = <&dma SUN4I_DMA_DEDICATED 14>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
endpoint@0 {
reg = <0>;
remote-endpoint = <&be0_out_tcon0>;
};
endpoint@1 {
reg = <1>;
remote-endpoint = <&be1_out_tcon0>;
};
};
port@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
endpoint@1 {
reg = <1>;
remote-endpoint = <&hdmi_in_tcon0>;
allwinner,tcon-channel = <1>;
};
};
};
};
#undef CLK_AHB_LCD0
#undef CLK_TCON0_CH0
#undef CLK_TCON0_CH1
#undef RST_TCON0
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
/*
* This comes from the clock/sun6i-a31-ccu.h and
* reset/sun6i-a31-ccu.h headers, but we can't include them since
* it would trigger a bunch of warnings for redefinitions of
* symbols with the other example.
*/
#define CLK_PLL_MIPI 15
#define CLK_AHB1_LCD0 47
#define CLK_LCD0_CH0 127
#define CLK_LCD0_CH1 129
#define RST_AHB1_LCD0 27
#define RST_AHB1_LVDS 41
lcd-controller@1c0c000 {
compatible = "allwinner,sun6i-a31-tcon";
reg = <0x01c0c000 0x1000>;
interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&dma 11>;
resets = <&ccu RST_AHB1_LCD0>, <&ccu RST_AHB1_LVDS>;
reset-names = "lcd", "lvds";
clocks = <&ccu CLK_AHB1_LCD0>,
<&ccu CLK_LCD0_CH0>,
<&ccu CLK_LCD0_CH1>,
<&ccu CLK_PLL_MIPI>;
clock-names = "ahb",
"tcon-ch0",
"tcon-ch1",
"lvds-alt";
clock-output-names = "tcon0-pixel-clock";
#clock-cells = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
endpoint@0 {
reg = <0>;
remote-endpoint = <&drc0_out_tcon0>;
};
endpoint@1 {
reg = <1>;
remote-endpoint = <&drc1_out_tcon0>;
};
};
port@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
endpoint@1 {
reg = <1>;
remote-endpoint = <&hdmi_in_tcon0>;
allwinner,tcon-channel = <1>;
};
};
};
};
#undef CLK_PLL_MIPI
#undef CLK_AHB1_LCD0
#undef CLK_LCD0_CH0
#undef CLK_LCD0_CH1
#undef RST_AHB1_LCD0
#undef RST_AHB1_LVDS
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
/*
* This comes from the clock/sun9i-a80-ccu.h and
* reset/sun9i-a80-ccu.h headers, but we can't include them since
* it would trigger a bunch of warnings for redefinitions of
* symbols with the other example.
*/
#define CLK_BUS_LCD0 102
#define CLK_LCD0 58
#define RST_BUS_LCD0 22
#define RST_BUS_EDP 24
#define RST_BUS_LVDS 25
lcd-controller@3c00000 {
compatible = "allwinner,sun9i-a80-tcon-lcd";
reg = <0x03c00000 0x10000>;
interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_LCD0>, <&ccu CLK_LCD0>;
clock-names = "ahb", "tcon-ch0";
resets = <&ccu RST_BUS_LCD0>, <&ccu RST_BUS_EDP>, <&ccu RST_BUS_LVDS>;
reset-names = "lcd", "edp", "lvds";
clock-output-names = "tcon0-pixel-clock";
#clock-cells = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
endpoint {
remote-endpoint = <&drc0_out_tcon0>;
};
};
port@1 {
reg = <1>;
};
};
};
#undef CLK_BUS_TCON0
#undef CLK_TCON0
#undef RST_BUS_TCON0
#undef RST_BUS_EDP
#undef RST_BUS_LVDS
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
/*
* This comes from the clock/sun8i-a83t-ccu.h and
* reset/sun8i-a83t-ccu.h headers, but we can't include them since
* it would trigger a bunch of warnings for redefinitions of
* symbols with the other example.
*/
#define CLK_BUS_TCON0 36
#define CLK_TCON0 85
#define RST_BUS_TCON0 22
#define RST_BUS_LVDS 31
lcd-controller@1c0c000 {
compatible = "allwinner,sun8i-a83t-tcon-lcd";
reg = <0x01c0c000 0x1000>;
interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_TCON0>, <&ccu CLK_TCON0>;
clock-names = "ahb", "tcon-ch0";
clock-output-names = "tcon-pixel-clock";
#clock-cells = <0>;
resets = <&ccu RST_BUS_TCON0>, <&ccu RST_BUS_LVDS>;
reset-names = "lcd", "lvds";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
endpoint@0 {
reg = <0>;
remote-endpoint = <&mixer0_out_tcon0>;
};
endpoint@1 {
reg = <1>;
remote-endpoint = <&mixer1_out_tcon0>;
};
};
port@1 {
reg = <1>;
};
};
};
#undef CLK_BUS_TCON0
#undef CLK_TCON0
#undef RST_BUS_TCON0
#undef RST_BUS_LVDS
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
/*
* This comes from the clock/sun8i-r40-ccu.h and
* reset/sun8i-r40-ccu.h headers, but we can't include them since
* it would trigger a bunch of warnings for redefinitions of
* symbols with the other example.
*/
#define CLK_BUS_TCON_TV0 73
#define RST_BUS_TCON_TV0 49
tcon_tv0: lcd-controller@1c73000 {
compatible = "allwinner,sun8i-r40-tcon-tv";
reg = <0x01c73000 0x1000>;
interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_TCON_TV0>, <&tcon_top 0>;
clock-names = "ahb", "tcon-ch1";
resets = <&ccu RST_BUS_TCON_TV0>;
reset-names = "lcd";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
endpoint@0 {
reg = <0>;
remote-endpoint = <&tcon_top_mixer0_out_tcon_tv0>;
};
endpoint@1 {
reg = <1>;
remote-endpoint = <&tcon_top_mixer1_out_tcon_tv0>;
};
};
tcon_tv0_out: port@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
endpoint@1 {
reg = <1>;
remote-endpoint = <&tcon_top_hdmi_in_tcon_tv0>;
};
};
};
};
#undef CLK_BUS_TCON_TV0
#undef RST_BUS_TCON_TV0
...

View File

@ -0,0 +1,62 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/allwinner,sun4i-a10-tv-encoder.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Allwinner A10 TV Encoder Device Tree Bindings
maintainers:
- Chen-Yu Tsai <wens@csie.org>
- Maxime Ripard <mripard@kernel.org>
properties:
compatible:
const: allwinner,sun4i-a10-tv-encoder
reg:
maxItems: 1
clocks:
maxItems: 1
resets:
maxItems: 1
port:
type: object
description:
A port node with endpoint definitions as defined in
Documentation/devicetree/bindings/media/video-interfaces.txt. The
first port should be the input endpoint, usually coming from the
associated TCON.
required:
- compatible
- reg
- clocks
- resets
- port
additionalProperties: false
examples:
- |
tve0: tv-encoder@1c0a000 {
compatible = "allwinner,sun4i-a10-tv-encoder";
reg = <0x01c0a000 0x1000>;
clocks = <&ahb_gates 34>;
resets = <&tcon_ch0_clk 0>;
port {
#address-cells = <1>;
#size-cells = <0>;
tve0_in_tcon0: endpoint@0 {
reg = <0>;
remote-endpoint = <&tcon0_out_tve0>;
};
};
};
...

View File

@ -0,0 +1,138 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/allwinner,sun6i-a31-drc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Allwinner A31 Dynamic Range Controller Device Tree Bindings
maintainers:
- Chen-Yu Tsai <wens@csie.org>
- Maxime Ripard <mripard@kernel.org>
description: |
The DRC (Dynamic Range Controller) allows to dynamically adjust
pixel brightness/contrast based on histogram measurements for LCD
content adaptive backlight control.
properties:
compatible:
enum:
- allwinner,sun6i-a31-drc
- allwinner,sun6i-a31s-drc
- allwinner,sun8i-a23-drc
- allwinner,sun8i-a33-drc
- allwinner,sun9i-a80-drc
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
items:
- description: The DRC interface clock
- description: The DRC module clock
- description: The DRC DRAM clock
clock-names:
items:
- const: ahb
- const: mod
- const: ram
resets:
maxItems: 1
ports:
type: object
description: |
A ports node with endpoint definitions as defined in
Documentation/devicetree/bindings/media/video-interfaces.txt.
properties:
"#address-cells":
const: 1
"#size-cells":
const: 0
port@0:
type: object
description: |
Input endpoints of the controller.
port@1:
type: object
description: |
Output endpoints of the controller.
required:
- "#address-cells"
- "#size-cells"
- port@0
- port@1
additionalProperties: false
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
- resets
- ports
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/sun6i-a31-ccu.h>
#include <dt-bindings/reset/sun6i-a31-ccu.h>
drc0: drc@1e70000 {
compatible = "allwinner,sun6i-a31-drc";
reg = <0x01e70000 0x10000>;
interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_AHB1_DRC0>, <&ccu CLK_IEP_DRC0>,
<&ccu CLK_DRAM_DRC0>;
clock-names = "ahb", "mod",
"ram";
resets = <&ccu RST_AHB1_DRC0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
drc0_in: port@0 {
reg = <0>;
drc0_in_be0: endpoint {
remote-endpoint = <&be0_out_drc0>;
};
};
drc0_out: port@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
drc0_out_tcon0: endpoint@0 {
reg = <0>;
remote-endpoint = <&tcon0_in_drc0>;
};
drc0_out_tcon1: endpoint@1 {
reg = <1>;
remote-endpoint = <&tcon1_in_drc0>;
};
};
};
};
...

View File

@ -0,0 +1,118 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/allwinner,sun8i-a83t-de2-mixer.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Allwinner Display Engine 2.0 Mixer Device Tree Bindings
maintainers:
- Chen-Yu Tsai <wens@csie.org>
- Maxime Ripard <mripard@kernel.org>
properties:
compatible:
enum:
- allwinner,sun8i-a83t-de2-mixer-0
- allwinner,sun8i-a83t-de2-mixer-1
- allwinner,sun8i-h3-de2-mixer-0
- allwinner,sun8i-r40-de2-mixer-0
- allwinner,sun8i-r40-de2-mixer-1
- allwinner,sun8i-v3s-de2-mixer
- allwinner,sun50i-a64-de2-mixer-0
- allwinner,sun50i-a64-de2-mixer-1
- allwinner,sun50i-h6-de3-mixer-0
reg:
maxItems: 1
clocks:
items:
- description: The mixer interface clock
- description: The mixer module clock
clock-names:
items:
- const: bus
- const: mod
resets:
maxItems: 1
ports:
type: object
description: |
A ports node with endpoint definitions as defined in
Documentation/devicetree/bindings/media/video-interfaces.txt.
properties:
"#address-cells":
const: 1
"#size-cells":
const: 0
port@0:
type: object
description: |
Input endpoints of the controller.
port@1:
type: object
description: |
Output endpoints of the controller.
required:
- "#address-cells"
- "#size-cells"
- port@1
additionalProperties: false
required:
- compatible
- reg
- clocks
- clock-names
- resets
- ports
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/sun8i-de2.h>
#include <dt-bindings/reset/sun8i-de2.h>
mixer0: mixer@1100000 {
compatible = "allwinner,sun8i-a83t-de2-mixer-0";
reg = <0x01100000 0x100000>;
clocks = <&display_clocks CLK_BUS_MIXER0>,
<&display_clocks CLK_MIXER0>;
clock-names = "bus",
"mod";
resets = <&display_clocks RST_MIXER0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
mixer0_out: port@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
mixer0_out_tcon0: endpoint@0 {
reg = <0>;
remote-endpoint = <&tcon0_in_mixer0>;
};
mixer0_out_tcon1: endpoint@1 {
reg = <1>;
remote-endpoint = <&tcon1_in_mixer0>;
};
};
};
};
...

View File

@ -0,0 +1,273 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/allwinner,sun8i-a83t-dw-hdmi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Allwinner A83t DWC HDMI TX Encoder Device Tree Bindings
description: |
The HDMI transmitter is a Synopsys DesignWare HDMI 1.4 TX controller
IP with Allwinner\'s own PHY IP. It supports audio and video outputs
and CEC.
These DT bindings follow the Synopsys DWC HDMI TX bindings defined
in Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt with
the following device-specific properties.
maintainers:
- Chen-Yu Tsai <wens@csie.org>
- Maxime Ripard <mripard@kernel.org>
properties:
"#phy-cells":
const: 0
compatible:
oneOf:
- const: allwinner,sun8i-a83t-dw-hdmi
- const: allwinner,sun50i-h6-dw-hdmi
- items:
- enum:
- allwinner,sun8i-h3-dw-hdmi
- allwinner,sun8i-r40-dw-hdmi
- allwinner,sun50i-a64-dw-hdmi
- const: allwinner,sun8i-a83t-dw-hdmi
reg:
maxItems: 1
reg-io-width:
const: 1
interrupts:
maxItems: 1
clocks:
minItems: 3
maxItems: 6
items:
- description: Bus Clock
- description: Register Clock
- description: TMDS Clock
- description: HDMI CEC Clock
- description: HDCP Clock
- description: HDCP Bus Clock
clock-names:
minItems: 3
maxItems: 6
items:
- const: iahb
- const: isfr
- const: tmds
- const: cec
- const: hdcp
- const: hdcp-bus
resets:
minItems: 1
maxItems: 2
items:
- description: HDMI Controller Reset
- description: HDCP Reset
reset-names:
minItems: 1
maxItems: 2
items:
- const: ctrl
- const: hdcp
phys:
maxItems: 1
description:
Phandle to the DWC HDMI PHY.
phy-names:
const: phy
hvcc-supply:
description:
The VCC power supply of the controller
ports:
type: object
description: |
A ports node with endpoint definitions as defined in
Documentation/devicetree/bindings/media/video-interfaces.txt.
properties:
"#address-cells":
const: 1
"#size-cells":
const: 0
port@0:
type: object
description: |
Input endpoints of the controller. Usually the associated
TCON.
port@1:
type: object
description: |
Output endpoints of the controller. Usually an HDMI
connector.
required:
- "#address-cells"
- "#size-cells"
- port@0
- port@1
additionalProperties: false
required:
- compatible
- reg
- reg-io-width
- interrupts
- clocks
- clock-names
- resets
- reset-names
- phys
- phy-names
- ports
if:
properties:
compatible:
contains:
enum:
- allwinner,sun50i-h6-dw-hdmi
then:
properties:
clocks:
minItems: 6
clock-names:
minItems: 6
resets:
minItems: 2
reset-names:
minItems: 2
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
/*
* This comes from the clock/sun8i-a83t-ccu.h and
* reset/sun8i-a83t-ccu.h headers, but we can't include them since
* it would trigger a bunch of warnings for redefinitions of
* symbols with the other example.
*/
#define CLK_BUS_HDMI 39
#define CLK_HDMI 93
#define CLK_HDMI_SLOW 94
#define RST_BUS_HDMI1 26
hdmi@1ee0000 {
compatible = "allwinner,sun8i-a83t-dw-hdmi";
reg = <0x01ee0000 0x10000>;
reg-io-width = <1>;
interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_HDMI>, <&ccu CLK_HDMI_SLOW>,
<&ccu CLK_HDMI>;
clock-names = "iahb", "isfr", "tmds";
resets = <&ccu RST_BUS_HDMI1>;
reset-names = "ctrl";
phys = <&hdmi_phy>;
phy-names = "phy";
pinctrl-names = "default";
pinctrl-0 = <&hdmi_pins>;
status = "disabled";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
endpoint {
remote-endpoint = <&tcon1_out_hdmi>;
};
};
port@1 {
reg = <1>;
};
};
};
/* Cleanup after ourselves */
#undef CLK_BUS_HDMI
#undef CLK_HDMI
#undef CLK_HDMI_SLOW
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
/*
* This comes from the clock/sun50i-h6-ccu.h and
* reset/sun50i-h6-ccu.h headers, but we can't include them since
* it would trigger a bunch of warnings for redefinitions of
* symbols with the other example.
*/
#define CLK_BUS_HDMI 126
#define CLK_BUS_HDCP 137
#define CLK_HDMI 123
#define CLK_HDMI_SLOW 124
#define CLK_HDMI_CEC 125
#define CLK_HDCP 136
#define RST_BUS_HDMI_SUB 57
#define RST_BUS_HDCP 62
hdmi@6000000 {
compatible = "allwinner,sun50i-h6-dw-hdmi";
reg = <0x06000000 0x10000>;
reg-io-width = <1>;
interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_HDMI>, <&ccu CLK_HDMI_SLOW>,
<&ccu CLK_HDMI>, <&ccu CLK_HDMI_CEC>,
<&ccu CLK_HDCP>, <&ccu CLK_BUS_HDCP>;
clock-names = "iahb", "isfr", "tmds", "cec", "hdcp",
"hdcp-bus";
resets = <&ccu RST_BUS_HDMI_SUB>, <&ccu RST_BUS_HDCP>;
reset-names = "ctrl", "hdcp";
phys = <&hdmi_phy>;
phy-names = "phy";
pinctrl-names = "default";
pinctrl-0 = <&hdmi_pins>;
status = "disabled";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
endpoint {
remote-endpoint = <&tcon_top_hdmi_out_hdmi>;
};
};
port@1 {
reg = <1>;
};
};
};
...

View File

@ -0,0 +1,117 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/allwinner,sun8i-a83t-hdmi-phy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Allwinner A83t HDMI PHY Device Tree Bindings
maintainers:
- Chen-Yu Tsai <wens@csie.org>
- Maxime Ripard <mripard@kernel.org>
properties:
"#phy-cells":
const: 0
compatible:
enum:
- allwinner,sun8i-a83t-hdmi-phy
- allwinner,sun8i-h3-hdmi-phy
- allwinner,sun8i-r40-hdmi-phy
- allwinner,sun50i-a64-hdmi-phy
- allwinner,sun50i-h6-hdmi-phy
reg:
maxItems: 1
clocks:
minItems: 2
maxItems: 4
items:
- description: Bus Clock
- description: Module Clock
- description: Parent of the PHY clock
- description: Second possible parent of the PHY clock
clock-names:
minItems: 2
maxItems: 4
items:
- const: bus
- const: mod
- const: pll-0
- const: pll-1
resets:
maxItems: 1
reset-names:
const: phy
required:
- compatible
- reg
- clocks
- clock-names
- resets
- reset-names
if:
properties:
compatible:
contains:
enum:
- allwinner,sun8i-r40-hdmi-phy
then:
properties:
clocks:
minItems: 4
clock-names:
minItems: 4
else:
if:
properties:
compatible:
contains:
enum:
- allwinner,sun8i-h3-hdmi-phy
- allwinner,sun50i-a64-hdmi-phy
then:
properties:
clocks:
minItems: 3
clock-names:
minItems: 3
else:
properties:
clocks:
maxItems: 2
clock-names:
maxItems: 2
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/sun8i-a83t-ccu.h>
#include <dt-bindings/reset/sun8i-a83t-ccu.h>
hdmi_phy: hdmi-phy@1ef0000 {
compatible = "allwinner,sun8i-a83t-hdmi-phy";
reg = <0x01ef0000 0x10000>;
clocks = <&ccu CLK_BUS_HDMI>, <&ccu CLK_HDMI_SLOW>;
clock-names = "bus", "mod";
resets = <&ccu RST_BUS_HDMI0>;
reset-names = "phy";
#phy-cells = <0>;
};
...

View File

@ -0,0 +1,382 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/allwinner,sun8i-r40-tcon-top.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Allwinner R40 TCON TOP Device Tree Bindings
maintainers:
- Chen-Yu Tsai <wens@csie.org>
- Maxime Ripard <mripard@kernel.org>
description: |
TCON TOPs main purpose is to configure whole display pipeline. It
determines relationships between mixers and TCONs, selects source
TCON for HDMI, muxes LCD and TV encoder GPIO output, selects TV
encoder clock source and contains additional TV TCON and DSI gates.
It allows display pipeline to be configured in very different ways:
/ LCD0/LVDS0
/ [0] TCON-LCD0
| \ MIPI DSI
mixer0 |
\ / [1] TCON-LCD1 - LCD1/LVDS1
TCON-TOP
/ \ [2] TCON-TV0 [0] - TVE0/RGB
mixer1 | \
| TCON-TOP - HDMI
| /
\ [3] TCON-TV1 [1] - TVE1/RGB
Note that both TCON TOP references same physical unit. Both mixers
can be connected to any TCON. Not all TCON TOP variants support all
features.
properties:
"#clock-cells":
const: 1
compatible:
enum:
- allwinner,sun8i-r40-tcon-top
- allwinner,sun50i-h6-tcon-top
reg:
maxItems: 1
clocks:
minItems: 2
maxItems: 6
items:
- description: The TCON TOP interface clock
- description: The TCON TOP TV0 clock
- description: The TCON TOP TVE0 clock
- description: The TCON TOP TV1 clock
- description: The TCON TOP TVE1 clock
- description: The TCON TOP MIPI DSI clock
clock-names:
minItems: 2
maxItems: 6
items:
- const: bus
- const: tcon-tv0
- const: tve0
- const: tcon-tv1
- const: tve1
- const: dsi
clock-output-names:
minItems: 1
maxItems: 3
description: >
The first item is the name of the clock created for the TV0
channel, the second item is the name of the TCON TV1 channel
clock and the third one is the name of the DSI channel clock.
resets:
maxItems: 1
ports:
type: object
description: |
A ports node with endpoint definitions as defined in
Documentation/devicetree/bindings/media/video-interfaces.txt.
All ports should have only one endpoint connected to
remote endpoint.
properties:
"#address-cells":
const: 1
"#size-cells":
const: 0
port@0:
type: object
description: |
Input endpoint for Mixer 0 mux.
port@1:
type: object
description: |
Output endpoint for Mixer 0 mux
properties:
"#address-cells":
const: 1
"#size-cells":
const: 0
reg: true
patternProperties:
"^endpoint@[0-9]$":
type: object
properties:
reg:
description: |
ID of the target TCON
required:
- reg
required:
- "#address-cells"
- "#size-cells"
additionalProperties: false
port@2:
type: object
description: |
Input endpoint for Mixer 1 mux.
port@3:
type: object
description: |
Output endpoint for Mixer 1 mux
properties:
"#address-cells":
const: 1
"#size-cells":
const: 0
reg: true
patternProperties:
"^endpoint@[0-9]$":
type: object
properties:
reg:
description: |
ID of the target TCON
required:
- reg
required:
- "#address-cells"
- "#size-cells"
additionalProperties: false
port@4:
type: object
description: |
Input endpoint for HDMI mux.
properties:
"#address-cells":
const: 1
"#size-cells":
const: 0
reg: true
patternProperties:
"^endpoint@[0-9]$":
type: object
properties:
reg:
description: |
ID of the target TCON
required:
- reg
required:
- "#address-cells"
- "#size-cells"
additionalProperties: false
port@5:
type: object
description: |
Output endpoint for HDMI mux
required:
- "#address-cells"
- "#size-cells"
- port@0
- port@1
- port@4
- port@5
additionalProperties: false
required:
- "#clock-cells"
- compatible
- reg
- clocks
- clock-names
- clock-output-names
- resets
- ports
additionalProperties: false
if:
properties:
compatible:
contains:
const: allwinner,sun50i-h6-tcon-top
then:
properties:
clocks:
maxItems: 2
clock-output-names:
maxItems: 1
else:
properties:
clocks:
minItems: 6
clock-output-names:
minItems: 3
ports:
required:
- port@2
- port@3
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/sun8i-r40-ccu.h>
#include <dt-bindings/reset/sun8i-r40-ccu.h>
tcon_top: tcon-top@1c70000 {
compatible = "allwinner,sun8i-r40-tcon-top";
reg = <0x01c70000 0x1000>;
clocks = <&ccu CLK_BUS_TCON_TOP>,
<&ccu CLK_TCON_TV0>,
<&ccu CLK_TVE0>,
<&ccu CLK_TCON_TV1>,
<&ccu CLK_TVE1>,
<&ccu CLK_DSI_DPHY>;
clock-names = "bus",
"tcon-tv0",
"tve0",
"tcon-tv1",
"tve1",
"dsi";
clock-output-names = "tcon-top-tv0",
"tcon-top-tv1",
"tcon-top-dsi";
resets = <&ccu RST_BUS_TCON_TOP>;
#clock-cells = <1>;
ports {
#address-cells = <1>;
#size-cells = <0>;
tcon_top_mixer0_in: port@0 {
reg = <0>;
tcon_top_mixer0_in_mixer0: endpoint {
remote-endpoint = <&mixer0_out_tcon_top>;
};
};
tcon_top_mixer0_out: port@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
tcon_top_mixer0_out_tcon_lcd0: endpoint@0 {
reg = <0>;
};
tcon_top_mixer0_out_tcon_lcd1: endpoint@1 {
reg = <1>;
};
tcon_top_mixer0_out_tcon_tv0: endpoint@2 {
reg = <2>;
remote-endpoint = <&tcon_tv0_in_tcon_top_mixer0>;
};
tcon_top_mixer0_out_tcon_tv1: endpoint@3 {
reg = <3>;
remote-endpoint = <&tcon_tv1_in_tcon_top_mixer0>;
};
};
tcon_top_mixer1_in: port@2 {
#address-cells = <1>;
#size-cells = <0>;
reg = <2>;
tcon_top_mixer1_in_mixer1: endpoint@1 {
reg = <1>;
remote-endpoint = <&mixer1_out_tcon_top>;
};
};
tcon_top_mixer1_out: port@3 {
#address-cells = <1>;
#size-cells = <0>;
reg = <3>;
tcon_top_mixer1_out_tcon_lcd0: endpoint@0 {
reg = <0>;
};
tcon_top_mixer1_out_tcon_lcd1: endpoint@1 {
reg = <1>;
};
tcon_top_mixer1_out_tcon_tv0: endpoint@2 {
reg = <2>;
remote-endpoint = <&tcon_tv0_in_tcon_top_mixer1>;
};
tcon_top_mixer1_out_tcon_tv1: endpoint@3 {
reg = <3>;
remote-endpoint = <&tcon_tv1_in_tcon_top_mixer1>;
};
};
tcon_top_hdmi_in: port@4 {
#address-cells = <1>;
#size-cells = <0>;
reg = <4>;
tcon_top_hdmi_in_tcon_tv0: endpoint@0 {
reg = <0>;
remote-endpoint = <&tcon_tv0_out_tcon_top>;
};
tcon_top_hdmi_in_tcon_tv1: endpoint@1 {
reg = <1>;
remote-endpoint = <&tcon_tv1_out_tcon_top>;
};
};
tcon_top_hdmi_out: port@5 {
reg = <5>;
tcon_top_hdmi_out_hdmi: endpoint {
remote-endpoint = <&hdmi_in_tcon_top>;
};
};
};
};
...

View File

@ -0,0 +1,133 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/allwinner,sun9i-a80-deu.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Allwinner A80 Detail Enhancement Unit Device Tree Bindings
maintainers:
- Chen-Yu Tsai <wens@csie.org>
- Maxime Ripard <mripard@kernel.org>
description: |
The DEU (Detail Enhancement Unit), found in the Allwinner A80 SoC,
can sharpen the display content in both luma and chroma channels.
properties:
compatible:
const: allwinner,sun9i-a80-deu
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
items:
- description: The DEU interface clock
- description: The DEU module clock
- description: The DEU DRAM clock
clock-names:
items:
- const: ahb
- const: mod
- const: ram
resets:
maxItems: 1
ports:
type: object
description: |
A ports node with endpoint definitions as defined in
Documentation/devicetree/bindings/media/video-interfaces.txt.
properties:
"#address-cells":
const: 1
"#size-cells":
const: 0
port@0:
type: object
description: |
Input endpoints of the controller.
port@1:
type: object
description: |
Output endpoints of the controller.
required:
- "#address-cells"
- "#size-cells"
- port@0
- port@1
additionalProperties: false
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
- resets
- ports
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/sun9i-a80-de.h>
#include <dt-bindings/reset/sun9i-a80-de.h>
deu0: deu@3300000 {
compatible = "allwinner,sun9i-a80-deu";
reg = <0x03300000 0x40000>;
interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&de_clocks CLK_BUS_DEU0>,
<&de_clocks CLK_IEP_DEU0>,
<&de_clocks CLK_DRAM_DEU0>;
clock-names = "ahb",
"mod",
"ram";
resets = <&de_clocks RST_DEU0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
deu0_in: port@0 {
reg = <0>;
deu0_in_fe0: endpoint {
remote-endpoint = <&fe0_out_deu0>;
};
};
deu0_out: port@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
deu0_out_be0: endpoint@0 {
reg = <0>;
remote-endpoint = <&be0_in_deu0>;
};
deu0_out_be1: endpoint@1 {
reg = <1>;
remote-endpoint = <&be1_in_deu0>;
};
};
};
};
...

View File

@ -1,42 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/panel/ampire,am-480272h3tmqw-t01h.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Ampire AM-480272H3TMQW-T01H 4.3" WQVGA TFT LCD panel
maintainers:
- Yannick Fertre <yannick.fertre@st.com>
- Thierry Reding <treding@nvidia.com>
allOf:
- $ref: panel-common.yaml#
properties:
compatible:
const: ampire,am-480272h3tmqw-t01h
power-supply: true
enable-gpios: true
backlight: true
port: true
required:
- compatible
additionalProperties: false
examples:
- |
panel_rgb: panel {
compatible = "ampire,am-480272h3tmqw-t01h";
enable-gpios = <&gpioa 8 1>;
port {
panel_in_rgb: endpoint {
remote-endpoint = <&controller_out_rgb>;
};
};
};
...

View File

@ -1,7 +0,0 @@
Ampire AM-800480R3TMQW-A1H 7.0" WVGA TFT LCD panel
Required properties:
- compatible: should be "ampire,am800480r3tmqwa1h"
This binding is compatible with the simple-panel binding, which is specified
in simple-panel.txt in this directory.

View File

@ -1,12 +0,0 @@
GiantPlus 3.0" (320x240 pixels) 24-bit TFT LCD panel
Required properties:
- compatible: should be "giantplus,gpm940b0"
- power-supply: as specified in the base binding
Optional properties:
- backlight: as specified in the base binding
- enable-gpios: as specified in the base binding
This binding is compatible with the simple-panel binding, which is specified
in simple-panel.txt in this directory.

View File

@ -0,0 +1,69 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/panel/panel-simple.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Simple panels with one power supply
maintainers:
- Thierry Reding <thierry.reding@gmail.com>
- Sam Ravnborg <sam@ravnborg.org>
description: |
This binding file is a collection of the simple (dumb) panels that
requires only a single power-supply.
There are optionally a backlight and an enable GPIO.
The panel may use an OF graph binding for the association to the display,
or it may be a direct child node of the display.
If the panel is more advanced a dedicated binding file is required.
allOf:
- $ref: panel-common.yaml#
properties:
compatible:
enum:
# compatible must be listed in alphabetical order, ordered by compatible.
# The description in the comment is mandatory for each compatible.
# Ampire AM-480272H3TMQW-T01H 4.3" WQVGA TFT LCD panel
- ampire,am-480272h3tmqw-t01h
# Ampire AM-800480R3TMQW-A1H 7.0" WVGA TFT LCD panel
- ampire,am800480r3tmqwa1h
# AUO B116XAK01 eDP TFT LCD panel
- auo,b116xa01
# BOE NV140FHM-N49 14.0" FHD a-Si FT panel
- boe,nv140fhmn49
# GiantPlus GPM940B0 3.0" QVGA TFT LCD panel
- giantplus,gpm940b0
# Satoz SAT050AT40H12R2 5.0" WVGA TFT LCD panel
- satoz,sat050at40h12r2
# Sharp LS020B1DD01D 2.0" HQVGA TFT LCD panel
- sharp,ls020b1dd01d
backlight: true
enable-gpios: true
port: true
power-supply: true
additionalProperties: false
required:
- compatible
- power-supply
examples:
- |
panel_rgb: panel-rgb {
compatible = "ampire,am-480272h3tmqw-t01h";
power-supply = <&vcc_lcd_reg>;
port {
panel_in_rgb: endpoint {
remote-endpoint = <&ltdc_out_rgb>;
};
};
};

View File

@ -1,12 +0,0 @@
Sharp 2.0" (240x160 pixels) 16-bit TFT LCD panel
Required properties:
- compatible: should be "sharp,ls020b1dd01d"
- power-supply: as specified in the base binding
Optional properties:
- backlight: as specified in the base binding
- enable-gpios: as specified in the base binding
This binding is compatible with the simple-panel binding, which is specified
in simple-panel.txt in this directory.

View File

@ -1,637 +0,0 @@
Allwinner A10 Display Pipeline
==============================
The Allwinner A10 Display pipeline is composed of several components
that are going to be documented below:
For all connections between components up to the TCONs in the display
pipeline, when there are multiple components of the same type at the
same depth, the local endpoint ID must be the same as the remote
component's index. For example, if the remote endpoint is Frontend 1,
then the local endpoint ID must be 1.
Frontend 0 [0] ------- [0] Backend 0 [0] ------- [0] TCON 0
[1] -- -- [1] [1] -- -- [1]
\ / \ /
X X
/ \ / \
[0] -- -- [0] [0] -- -- [0]
Frontend 1 [1] ------- [1] Backend 1 [1] ------- [1] TCON 1
For a two pipeline system such as the one depicted above, the lines
represent the connections between the components, while the numbers
within the square brackets corresponds to the ID of the local endpoint.
The same rule also applies to DE 2.0 mixer-TCON connections:
Mixer 0 [0] ----------- [0] TCON 0
[1] ---- ---- [1]
\ /
X
/ \
[0] ---- ---- [0]
Mixer 1 [1] ----------- [1] TCON 1
HDMI Encoder
------------
The HDMI Encoder supports the HDMI video and audio outputs, and does
CEC. It is one end of the pipeline.
Required properties:
- compatible: value must be one of:
* allwinner,sun4i-a10-hdmi
* allwinner,sun5i-a10s-hdmi
* allwinner,sun6i-a31-hdmi
- reg: base address and size of memory-mapped region
- interrupts: interrupt associated to this IP
- clocks: phandles to the clocks feeding the HDMI encoder
* ahb: the HDMI interface clock
* mod: the HDMI module clock
* ddc: the HDMI ddc clock (A31 only)
* pll-0: the first video PLL
* pll-1: the second video PLL
- clock-names: the clock names mentioned above
- resets: phandle to the reset control for the HDMI encoder (A31 only)
- dmas: phandles to the DMA channels used by the HDMI encoder
* ddc-tx: The channel for DDC transmission
* ddc-rx: The channel for DDC reception
* audio-tx: The channel used for audio transmission
- dma-names: the channel names mentioned above
- ports: A ports node with endpoint definitions as defined in
Documentation/devicetree/bindings/media/video-interfaces.txt. The
first port should be the input endpoint. The second should be the
output, usually to an HDMI connector.
DWC HDMI TX Encoder
-------------------
The HDMI transmitter is a Synopsys DesignWare HDMI 1.4 TX controller IP
with Allwinner's own PHY IP. It supports audio and video outputs and CEC.
These DT bindings follow the Synopsys DWC HDMI TX bindings defined in
Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt with the
following device-specific properties.
Required properties:
- compatible: value must be one of:
* "allwinner,sun8i-a83t-dw-hdmi"
* "allwinner,sun50i-a64-dw-hdmi", "allwinner,sun8i-a83t-dw-hdmi"
* "allwinner,sun50i-h6-dw-hdmi"
- reg: base address and size of memory-mapped region
- reg-io-width: See dw_hdmi.txt. Shall be 1.
- interrupts: HDMI interrupt number
- clocks: phandles to the clocks feeding the HDMI encoder
* iahb: the HDMI bus clock
* isfr: the HDMI register clock
* tmds: TMDS clock
* cec: HDMI CEC clock (H6 only)
* hdcp: HDCP clock (H6 only)
* hdcp-bus: HDCP bus clock (H6 only)
- clock-names: the clock names mentioned above
- resets:
* ctrl: HDMI controller reset
* hdcp: HDCP reset (H6 only)
- reset-names: reset names mentioned above
- phys: phandle to the DWC HDMI PHY
- phy-names: must be "phy"
- ports: A ports node with endpoint definitions as defined in
Documentation/devicetree/bindings/media/video-interfaces.txt. The
first port should be the input endpoint. The second should be the
output, usually to an HDMI connector.
Optional properties:
- hvcc-supply: the VCC power supply of the controller
DWC HDMI PHY
------------
Required properties:
- compatible: value must be one of:
* allwinner,sun8i-a83t-hdmi-phy
* allwinner,sun8i-h3-hdmi-phy
* allwinner,sun8i-r40-hdmi-phy
* allwinner,sun50i-a64-hdmi-phy
* allwinner,sun50i-h6-hdmi-phy
- reg: base address and size of memory-mapped region
- clocks: phandles to the clocks feeding the HDMI PHY
* bus: the HDMI PHY interface clock
* mod: the HDMI PHY module clock
- clock-names: the clock names mentioned above
- resets: phandle to the reset controller driving the PHY
- reset-names: must be "phy"
H3, A64 and R40 HDMI PHY require additional clocks:
- pll-0: parent of phy clock
- pll-1: second possible phy clock parent (A64/R40 only)
TV Encoder
----------
The TV Encoder supports the composite and VGA output. It is one end of
the pipeline.
Required properties:
- compatible: value should be "allwinner,sun4i-a10-tv-encoder".
- reg: base address and size of memory-mapped region
- clocks: the clocks driving the TV encoder
- resets: phandle to the reset controller driving the encoder
- ports: A ports node with endpoint definitions as defined in
Documentation/devicetree/bindings/media/video-interfaces.txt. The
first port should be the input endpoint.
TCON
----
The TCON acts as a timing controller for RGB, LVDS and TV interfaces.
Required properties:
- compatible: value must be either:
* allwinner,sun4i-a10-tcon
* allwinner,sun5i-a13-tcon
* allwinner,sun6i-a31-tcon
* allwinner,sun6i-a31s-tcon
* allwinner,sun7i-a20-tcon
* allwinner,sun8i-a23-tcon
* allwinner,sun8i-a33-tcon
* allwinner,sun8i-a83t-tcon-lcd
* allwinner,sun8i-a83t-tcon-tv
* allwinner,sun8i-r40-tcon-tv
* allwinner,sun8i-v3s-tcon
* allwinner,sun9i-a80-tcon-lcd
* allwinner,sun9i-a80-tcon-tv
* "allwinner,sun50i-a64-tcon-lcd", "allwinner,sun8i-a83t-tcon-lcd"
* "allwinner,sun50i-a64-tcon-tv", "allwinner,sun8i-a83t-tcon-tv"
* allwinner,sun50i-h6-tcon-tv, allwinner,sun8i-r40-tcon-tv
- reg: base address and size of memory-mapped region
- interrupts: interrupt associated to this IP
- clocks: phandles to the clocks feeding the TCON.
- 'ahb': the interface clocks
- 'tcon-ch0': The clock driving the TCON channel 0, if supported
- resets: phandles to the reset controllers driving the encoder
- "lcd": the reset line for the TCON
- "edp": the reset line for the eDP block (A80 only)
- clock-names: the clock names mentioned above
- reset-names: the reset names mentioned above
- clock-output-names: Name of the pixel clock created, if TCON supports
channel 0.
- ports: A ports node with endpoint definitions as defined in
Documentation/devicetree/bindings/media/video-interfaces.txt. The
first port should be the input endpoint, the second one the output
The output may have multiple endpoints. TCON can have 1 or 2 channels,
usually with the first channel being used for the panels interfaces
(RGB, LVDS, etc.), and the second being used for the outputs that
require another controller (TV Encoder, HDMI, etc.). The endpoints
will take an extra property, allwinner,tcon-channel, to specify the
channel the endpoint is associated to. If that property is not
present, the endpoint number will be used as the channel number.
For TCONs with channel 0, there is one more clock required:
- 'tcon-ch0': The clock driving the TCON channel 0
For TCONs with channel 1, there is one more clock required:
- 'tcon-ch1': The clock driving the TCON channel 1
When TCON support LVDS (all TCONs except TV TCONs on A83T, R40 and those found
in A13, H3, H5 and V3s SoCs), you need one more reset line:
- 'lvds': The reset line driving the LVDS logic
And on the A23, A31, A31s and A33, you need one more clock line:
- 'lvds-alt': An alternative clock source, separate from the TCON channel 0
clock, that can be used to drive the LVDS clock
TCON TOP
--------
TCON TOPs main purpose is to configure whole display pipeline. It determines
relationships between mixers and TCONs, selects source TCON for HDMI, muxes
LCD and TV encoder GPIO output, selects TV encoder clock source and contains
additional TV TCON and DSI gates.
It allows display pipeline to be configured in very different ways:
/ LCD0/LVDS0
/ [0] TCON-LCD0
| \ MIPI DSI
mixer0 |
\ / [1] TCON-LCD1 - LCD1/LVDS1
TCON-TOP
/ \ [2] TCON-TV0 [0] - TVE0/RGB
mixer1 | \
| TCON-TOP - HDMI
| /
\ [3] TCON-TV1 [1] - TVE1/RGB
Note that both TCON TOP references same physical unit. Both mixers can be
connected to any TCON. Not all TCON TOP variants support all features.
Required properties:
- compatible: value must be one of:
* allwinner,sun8i-r40-tcon-top
* allwinner,sun50i-h6-tcon-top
- reg: base address and size of the memory-mapped region.
- clocks: phandle to the clocks feeding the TCON TOP
* bus: TCON TOP interface clock
* tcon-tv0: TCON TV0 clock
* tve0: TVE0 clock (R40 only)
* tcon-tv1: TCON TV1 clock (R40 only)
* tve1: TVE0 clock (R40 only)
* dsi: MIPI DSI clock (R40 only)
- clock-names: clock name mentioned above
- resets: phandle to the reset line driving the TCON TOP
- #clock-cells : must contain 1
- clock-output-names: Names of clocks created for TCON TV0 channel clock,
TCON TV1 channel clock (R40 only) and DSI channel clock (R40 only), in
that order.
- ports: A ports node with endpoint definitions as defined in
Documentation/devicetree/bindings/media/video-interfaces.txt. 6 ports should
be defined:
* port 0 is input for mixer0 mux
* port 1 is output for mixer0 mux
* port 2 is input for mixer1 mux
* port 3 is output for mixer1 mux
* port 4 is input for HDMI mux
* port 5 is output for HDMI mux
All output endpoints for mixer muxes and input endpoints for HDMI mux should
have reg property with the id of the target TCON, as shown in above graph
(0-3 for mixer muxes and 0-1 for HDMI mux). All ports should have only one
endpoint connected to remote endpoint.
DRC
---
The DRC (Dynamic Range Controller), found in the latest Allwinner SoCs
(A31, A23, A33, A80), allows to dynamically adjust pixel
brightness/contrast based on histogram measurements for LCD content
adaptive backlight control.
Required properties:
- compatible: value must be one of:
* allwinner,sun6i-a31-drc
* allwinner,sun6i-a31s-drc
* allwinner,sun8i-a23-drc
* allwinner,sun8i-a33-drc
* allwinner,sun9i-a80-drc
- reg: base address and size of the memory-mapped region.
- interrupts: interrupt associated to this IP
- clocks: phandles to the clocks feeding the DRC
* ahb: the DRC interface clock
* mod: the DRC module clock
* ram: the DRC DRAM clock
- clock-names: the clock names mentioned above
- resets: phandles to the reset line driving the DRC
- ports: A ports node with endpoint definitions as defined in
Documentation/devicetree/bindings/media/video-interfaces.txt. The
first port should be the input endpoints, the second one the outputs
Display Engine Backend
----------------------
The display engine backend exposes layers and sprites to the
system.
Required properties:
- compatible: value must be one of:
* allwinner,sun4i-a10-display-backend
* allwinner,sun5i-a13-display-backend
* allwinner,sun6i-a31-display-backend
* allwinner,sun7i-a20-display-backend
* allwinner,sun8i-a23-display-backend
* allwinner,sun8i-a33-display-backend
* allwinner,sun9i-a80-display-backend
- reg: base address and size of the memory-mapped region.
- interrupts: interrupt associated to this IP
- clocks: phandles to the clocks feeding the frontend and backend
* ahb: the backend interface clock
* mod: the backend module clock
* ram: the backend DRAM clock
- clock-names: the clock names mentioned above
- resets: phandles to the reset controllers driving the backend
- ports: A ports node with endpoint definitions as defined in
Documentation/devicetree/bindings/media/video-interfaces.txt. The
first port should be the input endpoints, the second one the output
On the A33, some additional properties are required:
- reg needs to have an additional region corresponding to the SAT
- reg-names need to be set, with "be" and "sat"
- clocks and clock-names need to have a phandle to the SAT bus
clocks, whose name will be "sat"
- resets and reset-names need to have a phandle to the SAT bus
resets, whose name will be "sat"
DEU
---
The DEU (Detail Enhancement Unit), found in the Allwinner A80 SoC,
can sharpen the display content in both luma and chroma channels.
Required properties:
- compatible: value must be one of:
* allwinner,sun9i-a80-deu
- reg: base address and size of the memory-mapped region.
- interrupts: interrupt associated to this IP
- clocks: phandles to the clocks feeding the DEU
* ahb: the DEU interface clock
* mod: the DEU module clock
* ram: the DEU DRAM clock
- clock-names: the clock names mentioned above
- resets: phandles to the reset line driving the DEU
- ports: A ports node with endpoint definitions as defined in
Documentation/devicetree/bindings/media/video-interfaces.txt. The
first port should be the input endpoints, the second one the outputs
Display Engine Frontend
-----------------------
The display engine frontend does formats conversion, scaling,
deinterlacing and color space conversion.
Required properties:
- compatible: value must be one of:
* allwinner,sun4i-a10-display-frontend
* allwinner,sun5i-a13-display-frontend
* allwinner,sun6i-a31-display-frontend
* allwinner,sun7i-a20-display-frontend
* allwinner,sun8i-a23-display-frontend
* allwinner,sun8i-a33-display-frontend
* allwinner,sun9i-a80-display-frontend
- reg: base address and size of the memory-mapped region.
- interrupts: interrupt associated to this IP
- clocks: phandles to the clocks feeding the frontend and backend
* ahb: the backend interface clock
* mod: the backend module clock
* ram: the backend DRAM clock
- clock-names: the clock names mentioned above
- resets: phandles to the reset controllers driving the backend
- ports: A ports node with endpoint definitions as defined in
Documentation/devicetree/bindings/media/video-interfaces.txt. The
first port should be the input endpoints, the second one the outputs
Display Engine 2.0 Mixer
------------------------
The DE2 mixer have many functionalities, currently only layer blending is
supported.
Required properties:
- compatible: value must be one of:
* allwinner,sun8i-a83t-de2-mixer-0
* allwinner,sun8i-a83t-de2-mixer-1
* allwinner,sun8i-h3-de2-mixer-0
* allwinner,sun8i-r40-de2-mixer-0
* allwinner,sun8i-r40-de2-mixer-1
* allwinner,sun8i-v3s-de2-mixer
* allwinner,sun50i-a64-de2-mixer-0
* allwinner,sun50i-a64-de2-mixer-1
* allwinner,sun50i-h6-de3-mixer-0
- reg: base address and size of the memory-mapped region.
- clocks: phandles to the clocks feeding the mixer
* bus: the mixer interface clock
* mod: the mixer module clock
- clock-names: the clock names mentioned above
- resets: phandles to the reset controllers driving the mixer
- ports: A ports node with endpoint definitions as defined in
Documentation/devicetree/bindings/media/video-interfaces.txt. The
first port should be the input endpoints, the second one the output
Display Engine Pipeline
-----------------------
The display engine pipeline (and its entry point, since it can be
either directly the backend or the frontend) is represented as an
extra node.
Required properties:
- compatible: value must be one of:
* allwinner,sun4i-a10-display-engine
* allwinner,sun5i-a10s-display-engine
* allwinner,sun5i-a13-display-engine
* allwinner,sun6i-a31-display-engine
* allwinner,sun6i-a31s-display-engine
* allwinner,sun7i-a20-display-engine
* allwinner,sun8i-a23-display-engine
* allwinner,sun8i-a33-display-engine
* allwinner,sun8i-a83t-display-engine
* allwinner,sun8i-h3-display-engine
* allwinner,sun8i-r40-display-engine
* allwinner,sun8i-v3s-display-engine
* allwinner,sun9i-a80-display-engine
* allwinner,sun50i-a64-display-engine
* allwinner,sun50i-h6-display-engine
- allwinner,pipelines: list of phandle to the display engine
frontends (DE 1.0) or mixers (DE 2.0/3.0) available.
Example:
panel: panel {
compatible = "olimex,lcd-olinuxino-43-ts";
#address-cells = <1>;
#size-cells = <0>;
port {
#address-cells = <1>;
#size-cells = <0>;
panel_input: endpoint {
remote-endpoint = <&tcon0_out_panel>;
};
};
};
connector {
compatible = "hdmi-connector";
type = "a";
port {
hdmi_con_in: endpoint {
remote-endpoint = <&hdmi_out_con>;
};
};
};
hdmi: hdmi@1c16000 {
compatible = "allwinner,sun5i-a10s-hdmi";
reg = <0x01c16000 0x1000>;
interrupts = <58>;
clocks = <&ccu CLK_AHB_HDMI>, <&ccu CLK_HDMI>,
<&ccu CLK_PLL_VIDEO0_2X>,
<&ccu CLK_PLL_VIDEO1_2X>;
clock-names = "ahb", "mod", "pll-0", "pll-1";
dmas = <&dma SUN4I_DMA_NORMAL 16>,
<&dma SUN4I_DMA_NORMAL 16>,
<&dma SUN4I_DMA_DEDICATED 24>;
dma-names = "ddc-tx", "ddc-rx", "audio-tx";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
hdmi_in_tcon0: endpoint {
remote-endpoint = <&tcon0_out_hdmi>;
};
};
port@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
hdmi_out_con: endpoint {
remote-endpoint = <&hdmi_con_in>;
};
};
};
};
tve0: tv-encoder@1c0a000 {
compatible = "allwinner,sun4i-a10-tv-encoder";
reg = <0x01c0a000 0x1000>;
clocks = <&ahb_gates 34>;
resets = <&tcon_ch0_clk 0>;
port {
#address-cells = <1>;
#size-cells = <0>;
tve0_in_tcon0: endpoint@0 {
reg = <0>;
remote-endpoint = <&tcon0_out_tve0>;
};
};
};
tcon0: lcd-controller@1c0c000 {
compatible = "allwinner,sun5i-a13-tcon";
reg = <0x01c0c000 0x1000>;
interrupts = <44>;
resets = <&tcon_ch0_clk 1>;
reset-names = "lcd";
clocks = <&ahb_gates 36>,
<&tcon_ch0_clk>,
<&tcon_ch1_clk>;
clock-names = "ahb",
"tcon-ch0",
"tcon-ch1";
clock-output-names = "tcon-pixel-clock";
ports {
#address-cells = <1>;
#size-cells = <0>;
tcon0_in: port@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
tcon0_in_be0: endpoint@0 {
reg = <0>;
remote-endpoint = <&be0_out_tcon0>;
};
};
tcon0_out: port@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
tcon0_out_panel: endpoint@0 {
reg = <0>;
remote-endpoint = <&panel_input>;
};
tcon0_out_tve0: endpoint@1 {
reg = <1>;
remote-endpoint = <&tve0_in_tcon0>;
};
};
};
};
fe0: display-frontend@1e00000 {
compatible = "allwinner,sun5i-a13-display-frontend";
reg = <0x01e00000 0x20000>;
interrupts = <47>;
clocks = <&ahb_gates 46>, <&de_fe_clk>,
<&dram_gates 25>;
clock-names = "ahb", "mod",
"ram";
resets = <&de_fe_clk>;
ports {
#address-cells = <1>;
#size-cells = <0>;
fe0_out: port@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
fe0_out_be0: endpoint {
remote-endpoint = <&be0_in_fe0>;
};
};
};
};
be0: display-backend@1e60000 {
compatible = "allwinner,sun5i-a13-display-backend";
reg = <0x01e60000 0x10000>;
interrupts = <47>;
clocks = <&ahb_gates 44>, <&de_be_clk>,
<&dram_gates 26>;
clock-names = "ahb", "mod",
"ram";
resets = <&de_be_clk>;
ports {
#address-cells = <1>;
#size-cells = <0>;
be0_in: port@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
be0_in_fe0: endpoint@0 {
reg = <0>;
remote-endpoint = <&fe0_out_be0>;
};
};
be0_out: port@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
be0_out_tcon0: endpoint@0 {
reg = <0>;
remote-endpoint = <&tcon0_in_be0>;
};
};
};
};
display-engine {
compatible = "allwinner,sun5i-a13-display-engine";
allwinner,pipelines = <&fe0>;
};

View File

@ -825,6 +825,8 @@ patternProperties:
description: Sancloud Ltd
"^sandisk,.*":
description: Sandisk Corporation
"^satoz,.*":
description: Satoz International Co., Ltd
"^sbs,.*":
description: Smart Battery System
"^schindler,.*":

View File

@ -5357,6 +5357,12 @@ S: Maintained
F: drivers/gpu/drm/tiny/st7735r.c
F: Documentation/devicetree/bindings/display/sitronix,st7735r.txt
DRM DRIVER FOR SONY ACX424AKP PANELS
M: Linus Walleij <linus.walleij@linaro.org>
T: git git://anongit.freedesktop.org/drm/drm-misc
S: Maintained
F: drivers/gpu/drm/panel/panel-sony-acx424akp.c
DRM DRIVER FOR ST-ERICSSON MCDE
M: Linus Walleij <linus.walleij@linaro.org>
T: git git://anongit.freedesktop.org/drm/drm-misc

View File

@ -168,6 +168,7 @@ config DRM_LOAD_EDID_FIRMWARE
config DRM_DP_CEC
bool "Enable DisplayPort CEC-Tunneling-over-AUX HDMI support"
depends on DRM
select CEC_CORE
help
Choose this option if you want to enable HDMI CEC support for

View File

@ -1289,21 +1289,19 @@ struct drm_crtc *analogix_dp_get_new_crtc(struct analogix_dp_device *dp,
return conn_state->crtc;
}
static void
analogix_dp_bridge_atomic_pre_enable(struct drm_bridge *bridge,
struct drm_bridge_state *old_bridge_state)
static void analogix_dp_bridge_atomic_pre_enable(struct drm_bridge *bridge,
struct drm_atomic_state *state)
{
struct drm_atomic_state *old_state = old_bridge_state->base.state;
struct analogix_dp_device *dp = bridge->driver_private;
struct drm_crtc *crtc;
struct drm_crtc_state *old_crtc_state;
int ret;
crtc = analogix_dp_get_new_crtc(dp, old_state);
crtc = analogix_dp_get_new_crtc(dp, state);
if (!crtc)
return;
old_crtc_state = drm_atomic_get_old_crtc_state(old_state, crtc);
old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
/* Don't touch the panel if we're coming back from PSR */
if (old_crtc_state && old_crtc_state->self_refresh_active)
return;
@ -1368,22 +1366,20 @@ static int analogix_dp_set_bridge(struct analogix_dp_device *dp)
return ret;
}
static void
analogix_dp_bridge_atomic_enable(struct drm_bridge *bridge,
struct drm_bridge_state *old_bridge_state)
static void analogix_dp_bridge_atomic_enable(struct drm_bridge *bridge,
struct drm_atomic_state *state)
{
struct drm_atomic_state *old_state = old_bridge_state->base.state;
struct analogix_dp_device *dp = bridge->driver_private;
struct drm_crtc *crtc;
struct drm_crtc_state *old_crtc_state;
int timeout_loop = 0;
int ret;
crtc = analogix_dp_get_new_crtc(dp, old_state);
crtc = analogix_dp_get_new_crtc(dp, state);
if (!crtc)
return;
old_crtc_state = drm_atomic_get_old_crtc_state(old_state, crtc);
old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
/* Not a full enable, just disable PSR and continue */
if (old_crtc_state && old_crtc_state->self_refresh_active) {
ret = analogix_dp_disable_psr(dp);
@ -1444,20 +1440,18 @@ static void analogix_dp_bridge_disable(struct drm_bridge *bridge)
dp->dpms_mode = DRM_MODE_DPMS_OFF;
}
static void
analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge,
struct drm_bridge_state *old_bridge_state)
static void analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge,
struct drm_atomic_state *state)
{
struct drm_atomic_state *old_state = old_bridge_state->base.state;
struct analogix_dp_device *dp = bridge->driver_private;
struct drm_crtc *crtc;
struct drm_crtc_state *new_crtc_state = NULL;
crtc = analogix_dp_get_new_crtc(dp, old_state);
crtc = analogix_dp_get_new_crtc(dp, state);
if (!crtc)
goto out;
new_crtc_state = drm_atomic_get_new_crtc_state(old_state, crtc);
new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
if (!new_crtc_state)
goto out;
@ -1469,21 +1463,20 @@ analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge,
analogix_dp_bridge_disable(bridge);
}
static void
analogix_dp_bridge_atomic_post_disable(struct drm_bridge *bridge,
struct drm_bridge_state *old_bridge_state)
static
void analogix_dp_bridge_atomic_post_disable(struct drm_bridge *bridge,
struct drm_atomic_state *state)
{
struct drm_atomic_state *old_state = old_bridge_state->base.state;
struct analogix_dp_device *dp = bridge->driver_private;
struct drm_crtc *crtc;
struct drm_crtc_state *new_crtc_state;
int ret;
crtc = analogix_dp_get_new_crtc(dp, old_state);
crtc = analogix_dp_get_new_crtc(dp, state);
if (!crtc)
return;
new_crtc_state = drm_atomic_get_new_crtc_state(old_state, crtc);
new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
if (!new_crtc_state || !new_crtc_state->self_refresh_active)
return;

View File

@ -30,7 +30,6 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_uapi.h>
#include <drm/drm_bridge.h>
#include <drm/drm_debugfs.h>
#include <drm/drm_device.h>
#include <drm/drm_drv.h>
@ -1018,44 +1017,6 @@ static void drm_atomic_connector_print_state(struct drm_printer *p,
connector->funcs->atomic_print_state(p, state);
}
/**
* drm_atomic_add_encoder_bridges - add bridges attached to an encoder
* @state: atomic state
* @encoder: DRM encoder
*
* This function adds all bridges attached to @encoder. This is needed to add
* bridge states to @state and make them available when
* &bridge_funcs.atomic_{check,pre_enable,enable,disable_post_disable}() are
* called
*
* Returns:
* 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
* then the w/w mutex code has detected a deadlock and the entire atomic
* sequence must be restarted. All other errors are fatal.
*/
int
drm_atomic_add_encoder_bridges(struct drm_atomic_state *state,
struct drm_encoder *encoder)
{
struct drm_bridge_state *bridge_state;
struct drm_bridge *bridge;
if (!encoder)
return 0;
DRM_DEBUG_ATOMIC("Adding all bridges for [encoder:%d:%s] to %p\n",
encoder->base.id, encoder->name, state);
drm_for_each_bridge_in_chain(encoder, bridge) {
bridge_state = drm_atomic_get_bridge_state(state, bridge);
if (IS_ERR(bridge_state))
return PTR_ERR(bridge_state);
}
return 0;
}
EXPORT_SYMBOL(drm_atomic_add_encoder_bridges);
/**
* drm_atomic_add_affected_connectors - add connectors for CRTC
* @state: atomic state

View File

@ -437,12 +437,12 @@ mode_fixup(struct drm_atomic_state *state)
funcs = encoder->helper_private;
bridge = drm_bridge_chain_get_first_bridge(encoder);
ret = drm_atomic_bridge_chain_check(bridge,
new_crtc_state,
new_conn_state);
if (ret) {
DRM_DEBUG_ATOMIC("Bridge atomic check failed\n");
return ret;
ret = drm_bridge_chain_mode_fixup(bridge,
&new_crtc_state->mode,
&new_crtc_state->adjusted_mode);
if (!ret) {
DRM_DEBUG_ATOMIC("Bridge fixup failed\n");
return -EINVAL;
}
if (funcs && funcs->atomic_check) {
@ -730,26 +730,6 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
return ret;
}
/*
* Iterate over all connectors again, and add all affected bridges to
* the state.
*/
for_each_oldnew_connector_in_state(state, connector,
old_connector_state,
new_connector_state, i) {
struct drm_encoder *encoder;
encoder = old_connector_state->best_encoder;
ret = drm_atomic_add_encoder_bridges(state, encoder);
if (ret)
return ret;
encoder = new_connector_state->best_encoder;
ret = drm_atomic_add_encoder_bridges(state, encoder);
if (ret)
return ret;
}
ret = mode_valid(state);
if (ret)
return ret;

View File

@ -25,7 +25,6 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_encoder.h>
@ -90,74 +89,6 @@ void drm_bridge_remove(struct drm_bridge *bridge)
}
EXPORT_SYMBOL(drm_bridge_remove);
static struct drm_bridge_state *
drm_atomic_default_bridge_duplicate_state(struct drm_bridge *bridge)
{
struct drm_bridge_state *new;
if (WARN_ON(!bridge->base.state))
return NULL;
new = kzalloc(sizeof(*new), GFP_KERNEL);
if (new)
__drm_atomic_helper_bridge_duplicate_state(bridge, new);
return new;
}
static struct drm_private_state *
drm_bridge_atomic_duplicate_priv_state(struct drm_private_obj *obj)
{
struct drm_bridge *bridge = drm_priv_to_bridge(obj);
struct drm_bridge_state *state;
if (bridge->funcs->atomic_duplicate_state)
state = bridge->funcs->atomic_duplicate_state(bridge);
else
state = drm_atomic_default_bridge_duplicate_state(bridge);
return state ? &state->base : NULL;
}
static void
drm_atomic_default_bridge_destroy_state(struct drm_bridge *bridge,
struct drm_bridge_state *state)
{
/* Just a simple kfree() for now */
kfree(state);
}
static void
drm_bridge_atomic_destroy_priv_state(struct drm_private_obj *obj,
struct drm_private_state *s)
{
struct drm_bridge_state *state = drm_priv_to_bridge_state(s);
struct drm_bridge *bridge = drm_priv_to_bridge(obj);
if (bridge->funcs->atomic_destroy_state)
bridge->funcs->atomic_destroy_state(bridge, state);
else
drm_atomic_default_bridge_destroy_state(bridge, state);
}
static const struct drm_private_state_funcs drm_bridge_priv_state_funcs = {
.atomic_duplicate_state = drm_bridge_atomic_duplicate_priv_state,
.atomic_destroy_state = drm_bridge_atomic_destroy_priv_state,
};
static struct drm_bridge_state *
drm_atomic_default_bridge_reset(struct drm_bridge *bridge)
{
struct drm_bridge_state *bridge_state;
bridge_state = kzalloc(sizeof(*bridge_state), GFP_KERNEL);
if (!bridge_state)
return ERR_PTR(-ENOMEM);
__drm_atomic_helper_bridge_reset(bridge, bridge_state);
return bridge_state;
}
/**
* drm_bridge_attach - attach the bridge to an encoder's chain
*
@ -183,7 +114,6 @@ drm_atomic_default_bridge_reset(struct drm_bridge *bridge)
int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
struct drm_bridge *previous)
{
struct drm_bridge_state *state;
int ret;
if (!encoder || !bridge)
@ -205,35 +135,15 @@ int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
if (bridge->funcs->attach) {
ret = bridge->funcs->attach(bridge);
if (ret < 0)
goto err_reset_bridge;
if (ret < 0) {
list_del(&bridge->chain_node);
bridge->dev = NULL;
bridge->encoder = NULL;
return ret;
}
}
if (bridge->funcs->atomic_reset)
state = bridge->funcs->atomic_reset(bridge);
else
state = drm_atomic_default_bridge_reset(bridge);
if (IS_ERR(state)) {
ret = PTR_ERR(state);
goto err_detach_bridge;
}
drm_atomic_private_obj_init(bridge->dev, &bridge->base,
&state->base,
&drm_bridge_priv_state_funcs);
return 0;
err_detach_bridge:
if (bridge->funcs->detach)
bridge->funcs->detach(bridge);
err_reset_bridge:
bridge->dev = NULL;
bridge->encoder = NULL;
list_del(&bridge->chain_node);
return ret;
}
EXPORT_SYMBOL(drm_bridge_attach);
@ -245,8 +155,6 @@ void drm_bridge_detach(struct drm_bridge *bridge)
if (WARN_ON(!bridge->dev))
return;
drm_atomic_private_obj_fini(&bridge->base);
if (bridge->funcs->detach)
bridge->funcs->detach(bridge);
@ -501,19 +409,10 @@ void drm_atomic_bridge_chain_disable(struct drm_bridge *bridge,
encoder = bridge->encoder;
list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) {
if (iter->funcs->atomic_disable) {
struct drm_bridge_state *old_bridge_state;
old_bridge_state =
drm_atomic_get_old_bridge_state(old_state,
iter);
if (WARN_ON(!old_bridge_state))
return;
iter->funcs->atomic_disable(iter, old_bridge_state);
} else if (iter->funcs->disable) {
if (iter->funcs->atomic_disable)
iter->funcs->atomic_disable(iter, old_state);
else if (iter->funcs->disable)
iter->funcs->disable(iter);
}
if (iter == bridge)
break;
@ -544,20 +443,10 @@ void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge,
encoder = bridge->encoder;
list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) {
if (bridge->funcs->atomic_post_disable) {
struct drm_bridge_state *old_bridge_state;
old_bridge_state =
drm_atomic_get_old_bridge_state(old_state,
bridge);
if (WARN_ON(!old_bridge_state))
return;
bridge->funcs->atomic_post_disable(bridge,
old_bridge_state);
} else if (bridge->funcs->post_disable) {
if (bridge->funcs->atomic_post_disable)
bridge->funcs->atomic_post_disable(bridge, old_state);
else if (bridge->funcs->post_disable)
bridge->funcs->post_disable(bridge);
}
}
}
EXPORT_SYMBOL(drm_atomic_bridge_chain_post_disable);
@ -586,19 +475,10 @@ void drm_atomic_bridge_chain_pre_enable(struct drm_bridge *bridge,
encoder = bridge->encoder;
list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) {
if (iter->funcs->atomic_pre_enable) {
struct drm_bridge_state *old_bridge_state;
old_bridge_state =
drm_atomic_get_old_bridge_state(old_state,
iter);
if (WARN_ON(!old_bridge_state))
return;
iter->funcs->atomic_pre_enable(iter, old_bridge_state);
} else if (iter->funcs->pre_enable) {
if (iter->funcs->atomic_pre_enable)
iter->funcs->atomic_pre_enable(iter, old_state);
else if (iter->funcs->pre_enable)
iter->funcs->pre_enable(iter);
}
if (iter == bridge)
break;
@ -628,385 +508,14 @@ void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge,
encoder = bridge->encoder;
list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) {
if (bridge->funcs->atomic_enable) {
struct drm_bridge_state *old_bridge_state;
old_bridge_state =
drm_atomic_get_old_bridge_state(old_state,
bridge);
if (WARN_ON(!old_bridge_state))
return;
bridge->funcs->atomic_enable(bridge, old_bridge_state);
} else if (bridge->funcs->enable) {
if (bridge->funcs->atomic_enable)
bridge->funcs->atomic_enable(bridge, old_state);
else if (bridge->funcs->enable)
bridge->funcs->enable(bridge);
}
}
}
EXPORT_SYMBOL(drm_atomic_bridge_chain_enable);
static int drm_atomic_bridge_check(struct drm_bridge *bridge,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
if (bridge->funcs->atomic_check) {
struct drm_bridge_state *bridge_state;
int ret;
bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state,
bridge);
if (WARN_ON(!bridge_state))
return -EINVAL;
ret = bridge->funcs->atomic_check(bridge, bridge_state,
crtc_state, conn_state);
if (ret)
return ret;
} else if (bridge->funcs->mode_fixup) {
if (!bridge->funcs->mode_fixup(bridge, &crtc_state->mode,
&crtc_state->adjusted_mode))
return -EINVAL;
}
return 0;
}
/**
* drm_atomic_helper_bridge_propagate_bus_fmt() - Propagate output format to
* the input end of a bridge
* @bridge: bridge control structure
* @bridge_state: new bridge state
* @crtc_state: new CRTC state
* @conn_state: new connector state
* @output_fmt: tested output bus format
* @num_input_fmts: will contain the size of the returned array
*
* This helper is a pluggable implementation of the
* &drm_bridge_funcs.atomic_get_input_bus_fmts operation for bridges that don't
* modify the bus configuration between their input and their output. It
* returns an array of input formats with a single element set to @output_fmt.
*
* RETURNS:
* a valid format array of size @num_input_fmts, or NULL if the allocation
* failed
*/
u32 *
drm_atomic_helper_bridge_propagate_bus_fmt(struct drm_bridge *bridge,
struct drm_bridge_state *bridge_state,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state,
u32 output_fmt,
unsigned int *num_input_fmts)
{
u32 *input_fmts;
input_fmts = kzalloc(sizeof(*input_fmts), GFP_KERNEL);
if (!input_fmts) {
*num_input_fmts = 0;
return NULL;
}
*num_input_fmts = 1;
input_fmts[0] = output_fmt;
return input_fmts;
}
EXPORT_SYMBOL(drm_atomic_helper_bridge_propagate_bus_fmt);
static int select_bus_fmt_recursive(struct drm_bridge *first_bridge,
struct drm_bridge *cur_bridge,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state,
u32 out_bus_fmt)
{
struct drm_bridge_state *cur_state;
unsigned int num_in_bus_fmts, i;
struct drm_bridge *prev_bridge;
u32 *in_bus_fmts;
int ret;
prev_bridge = drm_bridge_get_prev_bridge(cur_bridge);
cur_state = drm_atomic_get_new_bridge_state(crtc_state->state,
cur_bridge);
if (WARN_ON(!cur_state))
return -EINVAL;
/*
* If bus format negotiation is not supported by this bridge, let's
* pass MEDIA_BUS_FMT_FIXED to the previous bridge in the chain and
* hope that it can handle this situation gracefully (by providing
* appropriate default values).
*/
if (!cur_bridge->funcs->atomic_get_input_bus_fmts) {
if (cur_bridge != first_bridge) {
ret = select_bus_fmt_recursive(first_bridge,
prev_bridge, crtc_state,
conn_state,
MEDIA_BUS_FMT_FIXED);
if (ret)
return ret;
}
cur_state->input_bus_cfg.format = MEDIA_BUS_FMT_FIXED;
cur_state->output_bus_cfg.format = out_bus_fmt;
return 0;
}
in_bus_fmts = cur_bridge->funcs->atomic_get_input_bus_fmts(cur_bridge,
cur_state,
crtc_state,
conn_state,
out_bus_fmt,
&num_in_bus_fmts);
if (!num_in_bus_fmts)
return -ENOTSUPP;
else if (!in_bus_fmts)
return -ENOMEM;
if (first_bridge == cur_bridge) {
cur_state->input_bus_cfg.format = in_bus_fmts[0];
cur_state->output_bus_cfg.format = out_bus_fmt;
kfree(in_bus_fmts);
return 0;
}
for (i = 0; i < num_in_bus_fmts; i++) {
ret = select_bus_fmt_recursive(first_bridge, prev_bridge,
crtc_state, conn_state,
in_bus_fmts[i]);
if (ret != -ENOTSUPP)
break;
}
if (!ret) {
cur_state->input_bus_cfg.format = in_bus_fmts[i];
cur_state->output_bus_cfg.format = out_bus_fmt;
}
kfree(in_bus_fmts);
return ret;
}
/*
* This function is called by &drm_atomic_bridge_chain_check() just before
* calling &drm_bridge_funcs.atomic_check() on all elements of the chain.
* It performs bus format negotiation between bridge elements. The negotiation
* happens in reverse order, starting from the last element in the chain up to
* @bridge.
*
* Negotiation starts by retrieving supported output bus formats on the last
* bridge element and testing them one by one. The test is recursive, meaning
* that for each tested output format, the whole chain will be walked backward,
* and each element will have to choose an input bus format that can be
* transcoded to the requested output format. When a bridge element does not
* support transcoding into a specific output format -ENOTSUPP is returned and
* the next bridge element will have to try a different format. If none of the
* combinations worked, -ENOTSUPP is returned and the atomic modeset will fail.
*
* This implementation is relying on
* &drm_bridge_funcs.atomic_get_output_bus_fmts() and
* &drm_bridge_funcs.atomic_get_input_bus_fmts() to gather supported
* input/output formats.
*
* When &drm_bridge_funcs.atomic_get_output_bus_fmts() is not implemented by
* the last element of the chain, &drm_atomic_bridge_chain_select_bus_fmts()
* tries a single format: &drm_connector.display_info.bus_formats[0] if
* available, MEDIA_BUS_FMT_FIXED otherwise.
*
* When &drm_bridge_funcs.atomic_get_input_bus_fmts() is not implemented,
* &drm_atomic_bridge_chain_select_bus_fmts() skips the negotiation on the
* bridge element that lacks this hook and asks the previous element in the
* chain to try MEDIA_BUS_FMT_FIXED. It's up to bridge drivers to decide what
* to do in that case (fail if they want to enforce bus format negotiation, or
* provide a reasonable default if they need to support pipelines where not
* all elements support bus format negotiation).
*/
static int
drm_atomic_bridge_chain_select_bus_fmts(struct drm_bridge *bridge,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
struct drm_connector *conn = conn_state->connector;
struct drm_encoder *encoder = bridge->encoder;
struct drm_bridge_state *last_bridge_state;
unsigned int i, num_out_bus_fmts;
struct drm_bridge *last_bridge;
u32 *out_bus_fmts;
int ret = 0;
last_bridge = list_last_entry(&encoder->bridge_chain,
struct drm_bridge, chain_node);
last_bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state,
last_bridge);
if (WARN_ON(!last_bridge_state))
return -EINVAL;
if (last_bridge->funcs->atomic_get_output_bus_fmts) {
const struct drm_bridge_funcs *funcs = last_bridge->funcs;
out_bus_fmts = funcs->atomic_get_output_bus_fmts(last_bridge,
last_bridge_state,
crtc_state,
conn_state,
&num_out_bus_fmts);
if (!num_out_bus_fmts)
return -ENOTSUPP;
else if (!out_bus_fmts)
return -ENOMEM;
} else {
num_out_bus_fmts = 1;
out_bus_fmts = kmalloc(sizeof(*out_bus_fmts), GFP_KERNEL);
if (!out_bus_fmts)
return -ENOMEM;
if (conn->display_info.num_bus_formats &&
conn->display_info.bus_formats)
out_bus_fmts[0] = conn->display_info.bus_formats[0];
else
out_bus_fmts[0] = MEDIA_BUS_FMT_FIXED;
}
for (i = 0; i < num_out_bus_fmts; i++) {
ret = select_bus_fmt_recursive(bridge, last_bridge, crtc_state,
conn_state, out_bus_fmts[i]);
if (ret != -ENOTSUPP)
break;
}
kfree(out_bus_fmts);
return ret;
}
static void
drm_atomic_bridge_propagate_bus_flags(struct drm_bridge *bridge,
struct drm_connector *conn,
struct drm_atomic_state *state)
{
struct drm_bridge_state *bridge_state, *next_bridge_state;
struct drm_bridge *next_bridge;
u32 output_flags;
bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
next_bridge = drm_bridge_get_next_bridge(bridge);
/*
* Let's try to apply the most common case here, that is, propagate
* display_info flags for the last bridge, and propagate the input
* flags of the next bridge element to the output end of the current
* bridge when the bridge is not the last one.
* There are exceptions to this rule, like when signal inversion is
* happening at the board level, but that's something drivers can deal
* with from their &drm_bridge_funcs.atomic_check() implementation by
* simply overriding the flags value we've set here.
*/
if (!next_bridge) {
output_flags = conn->display_info.bus_flags;
} else {
next_bridge_state = drm_atomic_get_new_bridge_state(state,
next_bridge);
output_flags = next_bridge_state->input_bus_cfg.flags;
}
bridge_state->output_bus_cfg.flags = output_flags;
/*
* Propage the output flags to the input end of the bridge. Again, it's
* not necessarily what all bridges want, but that's what most of them
* do, and by doing that by default we avoid forcing drivers to
* duplicate the "dummy propagation" logic.
*/
bridge_state->input_bus_cfg.flags = output_flags;
}
/**
* drm_atomic_bridge_chain_check() - Do an atomic check on the bridge chain
* @bridge: bridge control structure
* @crtc_state: new CRTC state
* @conn_state: new connector state
*
* First trigger a bus format negotiation before calling
* &drm_bridge_funcs.atomic_check() (falls back on
* &drm_bridge_funcs.mode_fixup()) op for all the bridges in the encoder chain,
* starting from the last bridge to the first. These are called before calling
* &drm_encoder_helper_funcs.atomic_check()
*
* RETURNS:
* 0 on success, a negative error code on failure
*/
int drm_atomic_bridge_chain_check(struct drm_bridge *bridge,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
struct drm_connector *conn = conn_state->connector;
struct drm_encoder *encoder = bridge->encoder;
struct drm_bridge *iter;
int ret;
ret = drm_atomic_bridge_chain_select_bus_fmts(bridge, crtc_state,
conn_state);
if (ret)
return ret;
list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) {
int ret;
/*
* Bus flags are propagated by default. If a bridge needs to
* tweak the input bus flags for any reason, it should happen
* in its &drm_bridge_funcs.atomic_check() implementation such
* that preceding bridges in the chain can propagate the new
* bus flags.
*/
drm_atomic_bridge_propagate_bus_flags(iter, conn,
crtc_state->state);
ret = drm_atomic_bridge_check(iter, crtc_state, conn_state);
if (ret)
return ret;
if (iter == bridge)
break;
}
return 0;
}
EXPORT_SYMBOL(drm_atomic_bridge_chain_check);
/**
* __drm_atomic_helper_bridge_reset() - Initialize a bridge state to its
* default
* @bridge: the bridge this state is refers to
* @state: bridge state to initialize
*
* Initialize the bridge state to default values. This is meant to be* called
* by the bridge &drm_plane_funcs.reset hook for bridges that subclass the
* bridge state.
*/
void __drm_atomic_helper_bridge_reset(struct drm_bridge *bridge,
struct drm_bridge_state *state)
{
memset(state, 0, sizeof(*state));
state->bridge = bridge;
}
EXPORT_SYMBOL(__drm_atomic_helper_bridge_reset);
/**
* __drm_atomic_helper_bridge_duplicate_state() - Copy atomic bridge state
* @bridge: bridge object
* @state: atomic bridge state
*
* Copies atomic state from a bridge's current state and resets inferred values.
* This is useful for drivers that subclass the bridge state.
*/
void __drm_atomic_helper_bridge_duplicate_state(struct drm_bridge *bridge,
struct drm_bridge_state *state)
{
__drm_atomic_helper_private_obj_duplicate_state(&bridge->base,
&state->base);
state->bridge = bridge;
}
EXPORT_SYMBOL(__drm_atomic_helper_bridge_duplicate_state);
#ifdef CONFIG_OF
/**
* of_drm_find_bridge - find the bridge corresponding to the device node in

View File

@ -140,8 +140,8 @@ static ssize_t crc_control_write(struct file *file, const char __user *ubuf,
if (IS_ERR(source))
return PTR_ERR(source);
if (source[len] == '\n')
source[len] = '\0';
if (source[len - 1] == '\n')
source[len - 1] = '\0';
ret = crtc->funcs->verify_crc_source(crtc, source, &values_cnt);
if (ret)
@ -258,6 +258,11 @@ static int crtc_crc_release(struct inode *inode, struct file *filep)
struct drm_crtc *crtc = filep->f_inode->i_private;
struct drm_crtc_crc *crc = &crtc->crc;
/* terminate the infinite while loop if 'drm_dp_aux_crc_work' running */
spin_lock_irq(&crc->lock);
crc->opened = false;
spin_unlock_irq(&crc->lock);
crtc->funcs->set_crc_source(crtc, NULL);
spin_lock_irq(&crc->lock);

View File

@ -9,6 +9,7 @@
* Copyright (C) 2012 Red Hat
*/
#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_cma_helper.h>

View File

@ -360,7 +360,8 @@ void drm_legacy_lock_master_cleanup(struct drm_device *dev, struct drm_master *m
/*
* Since the master is disappearing, so is the
* possibility to lock.
*/ mutex_lock(&dev->struct_mutex);
*/
mutex_lock(&dev->struct_mutex);
if (master->lock.hw_lock) {
if (dev->sigdata.lock == master->lock.hw_lock)
dev->sigdata.lock = NULL;

View File

@ -233,7 +233,7 @@ struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay,
/* 3) Nominal HSync width (% of line period) - default 8 */
#define CVT_HSYNC_PERCENTAGE 8
unsigned int hblank_percentage;
int vsyncandback_porch, vback_porch, hblank;
int vsyncandback_porch, __maybe_unused vback_porch, hblank;
/* estimated the horizontal period */
tmp1 = HV_FACTOR * 1000000 -
@ -386,9 +386,10 @@ drm_gtf_mode_complex(struct drm_device *dev, int hdisplay, int vdisplay,
int top_margin, bottom_margin;
int interlace;
unsigned int hfreq_est;
int vsync_plus_bp, vback_porch;
unsigned int vtotal_lines, vfieldrate_est, hperiod;
unsigned int vfield_rate, vframe_rate;
int vsync_plus_bp, __maybe_unused vback_porch;
unsigned int vtotal_lines, __maybe_unused vfieldrate_est;
unsigned int __maybe_unused hperiod;
unsigned int vfield_rate, __maybe_unused vframe_rate;
int left_margin, right_margin;
unsigned int total_active_pixels, ideal_duty_cycle;
unsigned int hblank, total_pixels, pixel_freq;

View File

@ -1378,6 +1378,7 @@ static void exynos_dsi_unregister_te_irq(struct exynos_dsi *dsi)
static void exynos_dsi_enable(struct drm_encoder *encoder)
{
struct exynos_dsi *dsi = encoder_to_dsi(encoder);
struct drm_bridge *iter;
int ret;
if (dsi->state & DSIM_STATE_ENABLED)
@ -1391,7 +1392,11 @@ static void exynos_dsi_enable(struct drm_encoder *encoder)
if (ret < 0)
goto err_put_sync;
} else {
drm_bridge_chain_pre_enable(dsi->out_bridge);
list_for_each_entry_reverse(iter, &dsi->bridge_chain,
chain_node) {
if (iter->funcs->pre_enable)
iter->funcs->pre_enable(iter);
}
}
exynos_dsi_set_display_mode(dsi);
@ -1402,7 +1407,10 @@ static void exynos_dsi_enable(struct drm_encoder *encoder)
if (ret < 0)
goto err_display_disable;
} else {
drm_bridge_chain_enable(dsi->out_bridge);
list_for_each_entry(iter, &dsi->bridge_chain, chain_node) {
if (iter->funcs->enable)
iter->funcs->enable(iter);
}
}
dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE;
@ -1420,6 +1428,7 @@ static void exynos_dsi_enable(struct drm_encoder *encoder)
static void exynos_dsi_disable(struct drm_encoder *encoder)
{
struct exynos_dsi *dsi = encoder_to_dsi(encoder);
struct drm_bridge *iter;
if (!(dsi->state & DSIM_STATE_ENABLED))
return;
@ -1427,10 +1436,20 @@ static void exynos_dsi_disable(struct drm_encoder *encoder)
dsi->state &= ~DSIM_STATE_VIDOUT_AVAILABLE;
drm_panel_disable(dsi->panel);
drm_bridge_chain_disable(dsi->out_bridge);
list_for_each_entry_reverse(iter, &dsi->bridge_chain, chain_node) {
if (iter->funcs->disable)
iter->funcs->disable(iter);
}
exynos_dsi_set_display_enable(dsi, false);
drm_panel_unprepare(dsi->panel);
drm_bridge_chain_post_disable(dsi->out_bridge);
list_for_each_entry(iter, &dsi->bridge_chain, chain_node) {
if (iter->funcs->post_disable)
iter->funcs->post_disable(iter);
}
dsi->state &= ~DSIM_STATE_ENABLED;
pm_runtime_put_sync(dsi->dev);
}
@ -1523,7 +1542,7 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
if (out_bridge) {
drm_bridge_attach(encoder, out_bridge, NULL);
dsi->out_bridge = out_bridge;
list_splice(&encoder->bridge_chain, &dsi->bridge_chain);
list_splice_init(&encoder->bridge_chain, &dsi->bridge_chain);
} else {
int ret = exynos_dsi_create_connector(encoder);

View File

@ -470,12 +470,11 @@ void psb_irq_turn_off_dpst(struct drm_device *dev)
{
struct drm_psb_private *dev_priv =
(struct drm_psb_private *) dev->dev_private;
u32 hist_reg;
u32 pwm_reg;
if (gma_power_begin(dev, false)) {
PSB_WVDC32(0x00000000, HISTOGRAM_INT_CONTROL);
hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
PSB_RVDC32(HISTOGRAM_INT_CONTROL);
psb_disable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE);

View File

@ -255,13 +255,17 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job)
return task->fence;
}
static void lima_sched_handle_error_task(struct lima_sched_pipe *pipe,
struct lima_sched_task *task)
static void lima_sched_timedout_job(struct drm_sched_job *job)
{
struct lima_sched_pipe *pipe = to_lima_pipe(job->sched);
struct lima_sched_task *task = to_lima_task(job);
if (!pipe->error)
DRM_ERROR("lima job timeout\n");
drm_sched_stop(&pipe->base, &task->base);
if (task)
drm_sched_increase_karma(&task->base);
drm_sched_increase_karma(&task->base);
pipe->task_error(pipe);
@ -284,16 +288,6 @@ static void lima_sched_handle_error_task(struct lima_sched_pipe *pipe,
drm_sched_start(&pipe->base, true);
}
static void lima_sched_timedout_job(struct drm_sched_job *job)
{
struct lima_sched_pipe *pipe = to_lima_pipe(job->sched);
struct lima_sched_task *task = to_lima_task(job);
DRM_ERROR("lima job timeout\n");
lima_sched_handle_error_task(pipe, task);
}
static void lima_sched_free_job(struct drm_sched_job *job)
{
struct lima_sched_task *task = to_lima_task(job);
@ -318,15 +312,6 @@ static const struct drm_sched_backend_ops lima_sched_ops = {
.free_job = lima_sched_free_job,
};
static void lima_sched_error_work(struct work_struct *work)
{
struct lima_sched_pipe *pipe =
container_of(work, struct lima_sched_pipe, error_work);
struct lima_sched_task *task = pipe->current_task;
lima_sched_handle_error_task(pipe, task);
}
int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char *name)
{
unsigned int timeout = lima_sched_timeout_ms > 0 ?
@ -335,8 +320,6 @@ int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char *name)
pipe->fence_context = dma_fence_context_alloc(1);
spin_lock_init(&pipe->fence_lock);
INIT_WORK(&pipe->error_work, lima_sched_error_work);
return drm_sched_init(&pipe->base, &lima_sched_ops, 1, 0,
msecs_to_jiffies(timeout), name);
}
@ -349,7 +332,7 @@ void lima_sched_pipe_fini(struct lima_sched_pipe *pipe)
void lima_sched_pipe_task_done(struct lima_sched_pipe *pipe)
{
if (pipe->error)
schedule_work(&pipe->error_work);
drm_sched_fault(&pipe->base);
else {
struct lima_sched_task *task = pipe->current_task;

View File

@ -68,8 +68,6 @@ struct lima_sched_pipe {
void (*task_fini)(struct lima_sched_pipe *pipe);
void (*task_error)(struct lima_sched_pipe *pipe);
void (*task_mmu_error)(struct lima_sched_pipe *pipe);
struct work_struct error_work;
};
int lima_sched_task_init(struct lima_sched_task *task,

View File

@ -135,7 +135,7 @@ struct meson_drm {
} venc;
struct {
dma_addr_t addr_phys;
dma_addr_t addr_dma;
uint32_t *addr;
unsigned int offset;
} rdma;

View File

@ -27,7 +27,7 @@ int meson_rdma_init(struct meson_drm *priv)
/* Allocate a PAGE buffer */
priv->rdma.addr =
dma_alloc_coherent(priv->dev, SZ_4K,
&priv->rdma.addr_phys,
&priv->rdma.addr_dma,
GFP_KERNEL);
if (!priv->rdma.addr)
return -ENOMEM;
@ -47,16 +47,16 @@ int meson_rdma_init(struct meson_drm *priv)
void meson_rdma_free(struct meson_drm *priv)
{
if (!priv->rdma.addr && !priv->rdma.addr_phys)
if (!priv->rdma.addr && !priv->rdma.addr_dma)
return;
meson_rdma_stop(priv);
dma_free_coherent(priv->dev, SZ_4K,
priv->rdma.addr, priv->rdma.addr_phys);
priv->rdma.addr, priv->rdma.addr_dma);
priv->rdma.addr = NULL;
priv->rdma.addr_phys = (dma_addr_t)NULL;
priv->rdma.addr_dma = (dma_addr_t)0;
}
void meson_rdma_setup(struct meson_drm *priv)
@ -118,11 +118,11 @@ void meson_rdma_flush(struct meson_drm *priv)
meson_rdma_stop(priv);
/* Start of Channel 1 register writes buffer */
writel(priv->rdma.addr_phys,
writel(priv->rdma.addr_dma,
priv->io_base + _REG(RDMA_AHB_START_ADDR_1));
/* Last byte on Channel 1 register writes buffer */
writel(priv->rdma.addr_phys + (priv->rdma.offset * RDMA_DESC_SIZE) - 1,
writel(priv->rdma.addr_dma + (priv->rdma.offset * RDMA_DESC_SIZE) - 1,
priv->io_base + _REG(RDMA_AHB_END_ADDR_1));
/* Trigger Channel 1 on VSYNC event */

View File

@ -393,8 +393,7 @@ static void dispc_get_reg_field(struct dispc_device *dispc,
enum dispc_feat_reg_field id,
u8 *start, u8 *end)
{
if (id >= dispc->feat->num_reg_fields)
BUG();
BUG_ON(id >= dispc->feat->num_reg_fields);
*start = dispc->feat->reg_fields[id].start;
*end = dispc->feat->reg_fields[id].end;

View File

@ -338,6 +338,17 @@ config DRM_PANEL_SITRONIX_ST7789V
Say Y here if you want to enable support for the Sitronix
ST7789V controller for 240x320 LCD panels
config DRM_PANEL_SONY_ACX424AKP
tristate "Sony ACX424AKP DSI command mode panel"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
select VIDEOMODE_HELPERS
help
Say Y here if you want to enable the Sony ACX424 display
panel. This panel supports DSI in both command and video
mode.
config DRM_PANEL_SONY_ACX565AKM
tristate "Sony ACX565AKM panel"
depends on GPIOLIB && OF && SPI

View File

@ -35,6 +35,7 @@ obj-$(CONFIG_DRM_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
obj-$(CONFIG_DRM_PANEL_SHARP_LS043T1LE01) += panel-sharp-ls043t1le01.o
obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7701) += panel-sitronix-st7701.o
obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7789V) += panel-sitronix-st7789v.o
obj-$(CONFIG_DRM_PANEL_SONY_ACX424AKP) += panel-sony-acx424akp.o
obj-$(CONFIG_DRM_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o
obj-$(CONFIG_DRM_PANEL_TPO_TD028TTEC1) += panel-tpo-td028ttec1.o
obj-$(CONFIG_DRM_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o

View File

@ -629,6 +629,35 @@ static const struct panel_desc auo_b101xtn01 = {
},
};
static const struct drm_display_mode auo_b116xak01_mode = {
.clock = 69300,
.hdisplay = 1366,
.hsync_start = 1366 + 48,
.hsync_end = 1366 + 48 + 32,
.htotal = 1366 + 48 + 32 + 10,
.vdisplay = 768,
.vsync_start = 768 + 4,
.vsync_end = 768 + 4 + 6,
.vtotal = 768 + 4 + 6 + 15,
.vrefresh = 60,
.flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
};
static const struct panel_desc auo_b116xak01 = {
.modes = &auo_b116xak01_mode,
.num_modes = 1,
.bpc = 6,
.size = {
.width = 256,
.height = 144,
},
.delay = {
.hpd_absent_delay = 200,
},
.bus_format = MEDIA_BUS_FMT_RGB666_1X18,
.connector_type = DRM_MODE_CONNECTOR_eDP,
};
static const struct drm_display_mode auo_b116xw03_mode = {
.clock = 70589,
.hdisplay = 1366,
@ -1008,6 +1037,38 @@ static const struct panel_desc boe_nv101wxmn51 = {
},
};
static const struct drm_display_mode boe_nv140fhmn49_modes[] = {
{
.clock = 148500,
.hdisplay = 1920,
.hsync_start = 1920 + 48,
.hsync_end = 1920 + 48 + 32,
.htotal = 2200,
.vdisplay = 1080,
.vsync_start = 1080 + 3,
.vsync_end = 1080 + 3 + 5,
.vtotal = 1125,
.vrefresh = 60,
},
};
static const struct panel_desc boe_nv140fhmn49 = {
.modes = boe_nv140fhmn49_modes,
.num_modes = ARRAY_SIZE(boe_nv140fhmn49_modes),
.bpc = 6,
.size = {
.width = 309,
.height = 174,
},
.delay = {
.prepare = 210,
.enable = 50,
.unprepare = 160,
},
.bus_format = MEDIA_BUS_FMT_RGB666_1X18,
.connector_type = DRM_MODE_CONNECTOR_eDP,
};
static const struct drm_display_mode cdtech_s043wq26h_ct7_mode = {
.clock = 9000,
.hdisplay = 480,
@ -2553,6 +2614,30 @@ static const struct panel_desc samsung_ltn140at29_301 = {
},
};
static const struct display_timing satoz_sat050at40h12r2_timing = {
.pixelclock = {33300000, 33300000, 50000000},
.hactive = {800, 800, 800},
.hfront_porch = {16, 210, 354},
.hback_porch = {46, 46, 46},
.hsync_len = {1, 1, 40},
.vactive = {480, 480, 480},
.vfront_porch = {7, 22, 147},
.vback_porch = {23, 23, 23},
.vsync_len = {1, 1, 20},
};
static const struct panel_desc satoz_sat050at40h12r2 = {
.timings = &satoz_sat050at40h12r2_timing,
.num_timings = 1,
.bpc = 8,
.size = {
.width = 108,
.height = 65,
},
.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
.connector_type = DRM_MODE_CONNECTOR_LVDS,
};
static const struct drm_display_mode sharp_ld_d5116z01b_mode = {
.clock = 168480,
.hdisplay = 1920,
@ -3125,6 +3210,9 @@ static const struct of_device_id platform_of_match[] = {
}, {
.compatible = "auo,b101xtn01",
.data = &auo_b101xtn01,
}, {
.compatible = "auo,b116xa01",
.data = &auo_b116xak01,
}, {
.compatible = "auo,b116xw03",
.data = &auo_b116xw03,
@ -3167,6 +3255,9 @@ static const struct of_device_id platform_of_match[] = {
}, {
.compatible = "boe,nv101wxmn51",
.data = &boe_nv101wxmn51,
}, {
.compatible = "boe,nv140fhmn49",
.data = &boe_nv140fhmn49,
}, {
.compatible = "cdtech,s043wq26h-ct7",
.data = &cdtech_s043wq26h_ct7,
@ -3356,6 +3447,9 @@ static const struct of_device_id platform_of_match[] = {
}, {
.compatible = "samsung,ltn140at29-301",
.data = &samsung_ltn140at29_301,
}, {
.compatible = "satoz,sat050at40h12r2",
.data = &satoz_sat050at40h12r2,
}, {
.compatible = "sharp,ld-d5116z01b",
.data = &sharp_ld_d5116z01b,

View File

@ -0,0 +1,550 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* MIPI-DSI Sony ACX424AKP panel driver. This is a 480x864
* AMOLED panel with a command-only DSI interface.
*
* Copyright (C) Linaro Ltd. 2019
* Author: Linus Walleij
* Based on code and know-how from Marcus Lorentzon
* Copyright (C) ST-Ericsson SA 2010
*/
#include <linux/backlight.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/regulator/consumer.h>
#include <video/mipi_display.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_modes.h>
#include <drm/drm_panel.h>
#include <drm/drm_print.h>
#define ACX424_DCS_READ_ID1 0xDA
#define ACX424_DCS_READ_ID2 0xDB
#define ACX424_DCS_READ_ID3 0xDC
#define ACX424_DCS_SET_MDDI 0xAE
/*
* Sony seems to use vendor ID 0x81
*/
#define DISPLAY_SONY_ACX424AKP_ID1 0x811b
#define DISPLAY_SONY_ACX424AKP_ID2 0x811a
/*
* The third ID looks like a bug, vendor IDs begin at 0x80
* and panel 00 ... seems like default values.
*/
#define DISPLAY_SONY_ACX424AKP_ID3 0x8000
struct acx424akp {
struct drm_panel panel;
struct device *dev;
struct backlight_device *bl;
struct regulator *supply;
struct gpio_desc *reset_gpio;
bool video_mode;
};
static const struct drm_display_mode sony_acx424akp_vid_mode = {
.clock = 330000,
.hdisplay = 480,
.hsync_start = 480 + 15,
.hsync_end = 480 + 15 + 0,
.htotal = 480 + 15 + 0 + 15,
.vdisplay = 864,
.vsync_start = 864 + 14,
.vsync_end = 864 + 14 + 1,
.vtotal = 864 + 14 + 1 + 11,
.vrefresh = 60,
.width_mm = 48,
.height_mm = 84,
.flags = DRM_MODE_FLAG_PVSYNC,
};
/*
* The timings are not very helpful as the display is used in
* command mode using the maximum HS frequency.
*/
static const struct drm_display_mode sony_acx424akp_cmd_mode = {
.clock = 420160,
.hdisplay = 480,
.hsync_start = 480 + 154,
.hsync_end = 480 + 154 + 16,
.htotal = 480 + 154 + 16 + 32,
.vdisplay = 864,
.vsync_start = 864 + 1,
.vsync_end = 864 + 1 + 1,
.vtotal = 864 + 1 + 1 + 1,
/*
* Some desired refresh rate, experiments at the maximum "pixel"
* clock speed (HS clock 420 MHz) yields around 117Hz.
*/
.vrefresh = 60,
.width_mm = 48,
.height_mm = 84,
};
static inline struct acx424akp *panel_to_acx424akp(struct drm_panel *panel)
{
return container_of(panel, struct acx424akp, panel);
}
#define FOSC 20 /* 20Mhz */
#define SCALE_FACTOR_NS_DIV_MHZ 1000
static int acx424akp_set_brightness(struct backlight_device *bl)
{
struct acx424akp *acx = bl_get_data(bl);
struct mipi_dsi_device *dsi = to_mipi_dsi_device(acx->dev);
int period_ns = 1023;
int duty_ns = bl->props.brightness;
u8 pwm_ratio;
u8 pwm_div;
u8 par;
int ret;
/* Calculate the PWM duty cycle in n/256's */
pwm_ratio = max(((duty_ns * 256) / period_ns) - 1, 1);
pwm_div = max(1,
((FOSC * period_ns) / 256) /
SCALE_FACTOR_NS_DIV_MHZ);
/* Set up PWM dutycycle ONE byte (differs from the standard) */
DRM_DEV_DEBUG(acx->dev, "calculated duty cycle %02x\n", pwm_ratio);
ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
&pwm_ratio, 1);
if (ret < 0) {
DRM_DEV_ERROR(acx->dev,
"failed to set display PWM ratio (%d)\n",
ret);
return ret;
}
/*
* Sequence to write PWMDIV:
* address data
* 0xF3 0xAA CMD2 Unlock
* 0x00 0x01 Enter CMD2 page 0
* 0X7D 0x01 No reload MTP of CMD2 P1
* 0x22 PWMDIV
* 0x7F 0xAA CMD2 page 1 lock
*/
par = 0xaa;
ret = mipi_dsi_dcs_write(dsi, 0xf3, &par, 1);
if (ret < 0) {
DRM_DEV_ERROR(acx->dev,
"failed to unlock CMD 2 (%d)\n",
ret);
return ret;
}
par = 0x01;
ret = mipi_dsi_dcs_write(dsi, 0x00, &par, 1);
if (ret < 0) {
DRM_DEV_ERROR(acx->dev,
"failed to enter page 1 (%d)\n",
ret);
return ret;
}
par = 0x01;
ret = mipi_dsi_dcs_write(dsi, 0x7d, &par, 1);
if (ret < 0) {
DRM_DEV_ERROR(acx->dev,
"failed to disable MTP reload (%d)\n",
ret);
return ret;
}
ret = mipi_dsi_dcs_write(dsi, 0x22, &pwm_div, 1);
if (ret < 0) {
DRM_DEV_ERROR(acx->dev,
"failed to set PWM divisor (%d)\n",
ret);
return ret;
}
par = 0xaa;
ret = mipi_dsi_dcs_write(dsi, 0x7f, &par, 1);
if (ret < 0) {
DRM_DEV_ERROR(acx->dev,
"failed to lock CMD 2 (%d)\n",
ret);
return ret;
}
/* Enable backlight */
par = 0x24;
ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY,
&par, 1);
if (ret < 0) {
DRM_DEV_ERROR(acx->dev,
"failed to enable display backlight (%d)\n",
ret);
return ret;
}
return 0;
}
static const struct backlight_ops acx424akp_bl_ops = {
.update_status = acx424akp_set_brightness,
};
static int acx424akp_read_id(struct acx424akp *acx)
{
struct mipi_dsi_device *dsi = to_mipi_dsi_device(acx->dev);
u8 vendor, version, panel;
u16 val;
int ret;
ret = mipi_dsi_dcs_read(dsi, ACX424_DCS_READ_ID1, &vendor, 1);
if (ret < 0) {
DRM_DEV_ERROR(acx->dev, "could not vendor ID byte\n");
return ret;
}
ret = mipi_dsi_dcs_read(dsi, ACX424_DCS_READ_ID2, &version, 1);
if (ret < 0) {
DRM_DEV_ERROR(acx->dev, "could not read device version byte\n");
return ret;
}
ret = mipi_dsi_dcs_read(dsi, ACX424_DCS_READ_ID3, &panel, 1);
if (ret < 0) {
DRM_DEV_ERROR(acx->dev, "could not read panel ID byte\n");
return ret;
}
if (vendor == 0x00) {
DRM_DEV_ERROR(acx->dev, "device vendor ID is zero\n");
return -ENODEV;
}
val = (vendor << 8) | panel;
switch (val) {
case DISPLAY_SONY_ACX424AKP_ID1:
case DISPLAY_SONY_ACX424AKP_ID2:
case DISPLAY_SONY_ACX424AKP_ID3:
DRM_DEV_INFO(acx->dev,
"MTP vendor: %02x, version: %02x, panel: %02x\n",
vendor, version, panel);
break;
default:
DRM_DEV_INFO(acx->dev,
"unknown vendor: %02x, version: %02x, panel: %02x\n",
vendor, version, panel);
break;
}
return 0;
}
static int acx424akp_power_on(struct acx424akp *acx)
{
int ret;
ret = regulator_enable(acx->supply);
if (ret) {
DRM_DEV_ERROR(acx->dev, "failed to enable supply (%d)\n", ret);
return ret;
}
/* Assert RESET */
gpiod_set_value_cansleep(acx->reset_gpio, 1);
udelay(20);
/* De-assert RESET */
gpiod_set_value_cansleep(acx->reset_gpio, 0);
usleep_range(11000, 20000);
return 0;
}
static void acx424akp_power_off(struct acx424akp *acx)
{
/* Assert RESET */
gpiod_set_value_cansleep(acx->reset_gpio, 1);
usleep_range(11000, 20000);
regulator_disable(acx->supply);
}
static int acx424akp_prepare(struct drm_panel *panel)
{
struct acx424akp *acx = panel_to_acx424akp(panel);
struct mipi_dsi_device *dsi = to_mipi_dsi_device(acx->dev);
const u8 mddi = 3;
int ret;
ret = acx424akp_power_on(acx);
if (ret)
return ret;
ret = acx424akp_read_id(acx);
if (ret) {
DRM_DEV_ERROR(acx->dev, "failed to read panel ID (%d)\n", ret);
goto err_power_off;
}
/* Enabe tearing mode: send TE (tearing effect) at VBLANK */
ret = mipi_dsi_dcs_set_tear_on(dsi,
MIPI_DSI_DCS_TEAR_MODE_VBLANK);
if (ret) {
DRM_DEV_ERROR(acx->dev, "failed to enable vblank TE (%d)\n",
ret);
goto err_power_off;
}
/*
* Set MDDI
*
* This presumably deactivates the Qualcomm MDDI interface and
* selects DSI, similar code is found in other drivers such as the
* Sharp LS043T1LE01 which makes us suspect that this panel may be
* using a Novatek NT35565 or similar display driver chip that shares
* this command. Due to the lack of documentation we cannot know for
* sure.
*/
ret = mipi_dsi_dcs_write(dsi, ACX424_DCS_SET_MDDI,
&mddi, sizeof(mddi));
if (ret < 0) {
DRM_DEV_ERROR(acx->dev, "failed to set MDDI (%d)\n", ret);
goto err_power_off;
}
/* Exit sleep mode */
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
if (ret) {
DRM_DEV_ERROR(acx->dev, "failed to exit sleep mode (%d)\n",
ret);
goto err_power_off;
}
msleep(140);
ret = mipi_dsi_dcs_set_display_on(dsi);
if (ret) {
DRM_DEV_ERROR(acx->dev, "failed to turn display on (%d)\n",
ret);
goto err_power_off;
}
if (acx->video_mode) {
/* In video mode turn peripheral on */
ret = mipi_dsi_turn_on_peripheral(dsi);
if (ret) {
dev_err(acx->dev, "failed to turn on peripheral\n");
goto err_power_off;
}
}
acx->bl->props.power = FB_BLANK_NORMAL;
return 0;
err_power_off:
acx424akp_power_off(acx);
return ret;
}
static int acx424akp_unprepare(struct drm_panel *panel)
{
struct acx424akp *acx = panel_to_acx424akp(panel);
struct mipi_dsi_device *dsi = to_mipi_dsi_device(acx->dev);
u8 par;
int ret;
/* Disable backlight */
par = 0x00;
ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY,
&par, 1);
if (ret) {
DRM_DEV_ERROR(acx->dev,
"failed to disable display backlight (%d)\n",
ret);
return ret;
}
ret = mipi_dsi_dcs_set_display_off(dsi);
if (ret) {
DRM_DEV_ERROR(acx->dev, "failed to turn display off (%d)\n",
ret);
return ret;
}
/* Enter sleep mode */
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
if (ret) {
DRM_DEV_ERROR(acx->dev, "failed to enter sleep mode (%d)\n",
ret);
return ret;
}
msleep(85);
acx424akp_power_off(acx);
acx->bl->props.power = FB_BLANK_POWERDOWN;
return 0;
}
static int acx424akp_enable(struct drm_panel *panel)
{
struct acx424akp *acx = panel_to_acx424akp(panel);
/*
* The backlight is on as long as the display is on
* so no use to call backlight_enable() here.
*/
acx->bl->props.power = FB_BLANK_UNBLANK;
return 0;
}
static int acx424akp_disable(struct drm_panel *panel)
{
struct acx424akp *acx = panel_to_acx424akp(panel);
/*
* The backlight is on as long as the display is on
* so no use to call backlight_disable() here.
*/
acx->bl->props.power = FB_BLANK_NORMAL;
return 0;
}
static int acx424akp_get_modes(struct drm_panel *panel,
struct drm_connector *connector)
{
struct acx424akp *acx = panel_to_acx424akp(panel);
struct drm_display_mode *mode;
if (acx->video_mode)
mode = drm_mode_duplicate(connector->dev,
&sony_acx424akp_vid_mode);
else
mode = drm_mode_duplicate(connector->dev,
&sony_acx424akp_cmd_mode);
if (!mode) {
DRM_ERROR("bad mode or failed to add mode\n");
return -EINVAL;
}
drm_mode_set_name(mode);
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
connector->display_info.width_mm = mode->width_mm;
connector->display_info.height_mm = mode->height_mm;
drm_mode_probed_add(connector, mode);
return 1; /* Number of modes */
}
static const struct drm_panel_funcs acx424akp_drm_funcs = {
.disable = acx424akp_disable,
.unprepare = acx424akp_unprepare,
.prepare = acx424akp_prepare,
.enable = acx424akp_enable,
.get_modes = acx424akp_get_modes,
};
static int acx424akp_probe(struct mipi_dsi_device *dsi)
{
struct device *dev = &dsi->dev;
struct acx424akp *acx;
int ret;
acx = devm_kzalloc(dev, sizeof(struct acx424akp), GFP_KERNEL);
if (!acx)
return -ENOMEM;
acx->video_mode = of_property_read_bool(dev->of_node,
"enforce-video-mode");
mipi_dsi_set_drvdata(dsi, acx);
acx->dev = dev;
dsi->lanes = 2;
dsi->format = MIPI_DSI_FMT_RGB888;
/*
* FIXME: these come from the ST-Ericsson vendor driver for the
* HREF520 and seems to reflect limitations in the PLLs on that
* platform, if you have the datasheet, please cross-check the
* actual max rates.
*/
dsi->lp_rate = 19200000;
dsi->hs_rate = 420160000;
if (acx->video_mode)
/* Burst mode using event for sync */
dsi->mode_flags =
MIPI_DSI_MODE_VIDEO |
MIPI_DSI_MODE_VIDEO_BURST;
else
dsi->mode_flags =
MIPI_DSI_CLOCK_NON_CONTINUOUS |
MIPI_DSI_MODE_EOT_PACKET;
acx->supply = devm_regulator_get(dev, "vddi");
if (IS_ERR(acx->supply))
return PTR_ERR(acx->supply);
/* This asserts RESET by default */
acx->reset_gpio = devm_gpiod_get_optional(dev, "reset",
GPIOD_OUT_HIGH);
if (IS_ERR(acx->reset_gpio)) {
ret = PTR_ERR(acx->reset_gpio);
if (ret != -EPROBE_DEFER)
DRM_DEV_ERROR(dev, "failed to request GPIO (%d)\n",
ret);
return ret;
}
drm_panel_init(&acx->panel, dev, &acx424akp_drm_funcs,
DRM_MODE_CONNECTOR_DSI);
acx->bl = devm_backlight_device_register(dev, "acx424akp", dev, acx,
&acx424akp_bl_ops, NULL);
if (IS_ERR(acx->bl)) {
DRM_DEV_ERROR(dev, "failed to register backlight device\n");
return PTR_ERR(acx->bl);
}
acx->bl->props.max_brightness = 1023;
acx->bl->props.brightness = 512;
acx->bl->props.power = FB_BLANK_POWERDOWN;
ret = drm_panel_add(&acx->panel);
if (ret < 0)
return ret;
ret = mipi_dsi_attach(dsi);
if (ret < 0) {
drm_panel_remove(&acx->panel);
return ret;
}
return 0;
}
static int acx424akp_remove(struct mipi_dsi_device *dsi)
{
struct acx424akp *acx = mipi_dsi_get_drvdata(dsi);
mipi_dsi_detach(dsi);
drm_panel_remove(&acx->panel);
return 0;
}
static const struct of_device_id acx424akp_of_match[] = {
{ .compatible = "sony,acx424akp" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, acx424akp_of_match);
static struct mipi_dsi_driver acx424akp_driver = {
.probe = acx424akp_probe,
.remove = acx424akp_remove,
.driver = {
.name = "panel-sony-acx424akp",
.of_match_table = acx424akp_of_match,
},
};
module_mipi_dsi_driver(acx424akp_driver);
MODULE_AUTHOR("Linus Wallei <linus.walleij@linaro.org>");
MODULE_DESCRIPTION("MIPI-DSI Sony acx424akp Panel Driver");
MODULE_LICENSE("GPL v2");

View File

@ -590,9 +590,8 @@ static void __rcar_lvds_atomic_enable(struct drm_bridge *bridge,
}
static void rcar_lvds_atomic_enable(struct drm_bridge *bridge,
struct drm_bridge_state *old_bridge_state)
struct drm_atomic_state *state)
{
struct drm_atomic_state *state = old_bridge_state->base.state;
struct drm_connector *connector;
struct drm_crtc *crtc;
@ -604,7 +603,7 @@ static void rcar_lvds_atomic_enable(struct drm_bridge *bridge,
}
static void rcar_lvds_atomic_disable(struct drm_bridge *bridge,
struct drm_bridge_state *old_bridge_state)
struct drm_atomic_state *state)
{
struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
@ -619,8 +618,7 @@ static void rcar_lvds_atomic_disable(struct drm_bridge *bridge,
/* Disable the companion LVDS encoder in dual-link mode. */
if (lvds->link_type != RCAR_LVDS_SINGLE_LINK && lvds->companion)
lvds->companion->funcs->atomic_disable(lvds->companion,
old_bridge_state);
lvds->companion->funcs->atomic_disable(lvds->companion, state);
clk_disable_unprepare(lvds->clocks.mod);
}

View File

@ -856,6 +856,13 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
ret = PTR_ERR(backend->mod_clk);
goto err_disable_bus_clk;
}
ret = clk_set_rate_exclusive(backend->mod_clk, 300000000);
if (ret) {
dev_err(dev, "Couldn't set the module clock frequency\n");
goto err_disable_bus_clk;
}
clk_prepare_enable(backend->mod_clk);
backend->ram_clk = devm_clk_get(dev, "ram");
@ -932,6 +939,7 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
err_disable_ram_clk:
clk_disable_unprepare(backend->ram_clk);
err_disable_mod_clk:
clk_rate_exclusive_put(backend->mod_clk);
clk_disable_unprepare(backend->mod_clk);
err_disable_bus_clk:
clk_disable_unprepare(backend->bus_clk);
@ -952,6 +960,7 @@ static void sun4i_backend_unbind(struct device *dev, struct device *master,
sun4i_backend_free_sat(dev);
clk_disable_unprepare(backend->ram_clk);
clk_rate_exclusive_put(backend->mod_clk);
clk_disable_unprepare(backend->mod_clk);
clk_disable_unprepare(backend->bus_clk);
reset_control_assert(backend->reset);

View File

@ -56,6 +56,13 @@ static int sun6i_drc_bind(struct device *dev, struct device *master,
ret = PTR_ERR(drc->mod_clk);
goto err_disable_bus_clk;
}
ret = clk_set_rate_exclusive(drc->mod_clk, 300000000);
if (ret) {
dev_err(dev, "Couldn't set the module clock frequency\n");
goto err_disable_bus_clk;
}
clk_prepare_enable(drc->mod_clk);
return 0;
@ -72,6 +79,7 @@ static void sun6i_drc_unbind(struct device *dev, struct device *master,
{
struct sun6i_drc *drc = dev_get_drvdata(dev);
clk_rate_exclusive_put(drc->mod_clk);
clk_disable_unprepare(drc->mod_clk);
clk_disable_unprepare(drc->bus_clk);
reset_control_assert(drc->reset);

View File

@ -1430,9 +1430,10 @@ static int tegra_hdmi_init(struct host1x_client *client)
hdmi->output.dev = client->dev;
drm_connector_init(drm, &hdmi->output.connector,
&tegra_hdmi_connector_funcs,
DRM_MODE_CONNECTOR_HDMIA);
drm_connector_init_with_ddc(drm, &hdmi->output.connector,
&tegra_hdmi_connector_funcs,
DRM_MODE_CONNECTOR_HDMIA,
hdmi->output.ddc);
drm_connector_helper_add(&hdmi->output.connector,
&tegra_hdmi_connector_helper_funcs);
hdmi->output.connector.dpms = DRM_MODE_DPMS_OFF;

View File

@ -3086,9 +3086,10 @@ static int tegra_sor_init(struct host1x_client *client)
sor->output.dev = sor->dev;
drm_connector_init(drm, &sor->output.connector,
&tegra_sor_connector_funcs,
connector);
drm_connector_init_with_ddc(drm, &sor->output.connector,
&tegra_sor_connector_funcs,
connector,
sor->output.ddc);
drm_connector_helper_add(&sor->output.connector,
&tegra_sor_connector_helper_funcs);
sor->output.connector.dpms = DRM_MODE_DPMS_OFF;

View File

@ -2,9 +2,8 @@
config DRM_UDL
tristate "DisplayLink"
depends on DRM
depends on USB_SUPPORT
depends on USB
depends on USB_ARCH_HAS_HCD
select USB
select DRM_GEM_SHMEM_HELPER
select DRM_KMS_HELPER
help

View File

@ -753,10 +753,19 @@ static void vc4_dsi_encoder_disable(struct drm_encoder *encoder)
struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
struct vc4_dsi *dsi = vc4_encoder->dsi;
struct device *dev = &dsi->pdev->dev;
struct drm_bridge *iter;
list_for_each_entry_reverse(iter, &dsi->bridge_chain, chain_node) {
if (iter->funcs->disable)
iter->funcs->disable(iter);
}
drm_bridge_chain_disable(dsi->bridge);
vc4_dsi_ulps(dsi, true);
drm_bridge_chain_post_disable(dsi->bridge);
list_for_each_entry_from(iter, &dsi->bridge_chain, chain_node) {
if (iter->funcs->post_disable)
iter->funcs->post_disable(iter);
}
clk_disable_unprepare(dsi->pll_phy_clock);
clk_disable_unprepare(dsi->escape_clock);
@ -824,6 +833,7 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder)
struct vc4_dsi *dsi = vc4_encoder->dsi;
struct device *dev = &dsi->pdev->dev;
bool debug_dump_regs = false;
struct drm_bridge *iter;
unsigned long hs_clock;
u32 ui_ns;
/* Minimum LP state duration in escape clock cycles. */
@ -1056,7 +1066,10 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder)
vc4_dsi_ulps(dsi, false);
drm_bridge_chain_pre_enable(dsi->bridge);
list_for_each_entry_reverse(iter, &dsi->bridge_chain, chain_node) {
if (iter->funcs->pre_enable)
iter->funcs->pre_enable(iter);
}
if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
DSI_PORT_WRITE(DISP0_CTRL,
@ -1073,7 +1086,10 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder)
DSI_DISP0_ENABLE);
}
drm_bridge_chain_enable(dsi->bridge);
list_for_each_entry(iter, &dsi->bridge_chain, chain_node) {
if (iter->funcs->enable)
iter->funcs->enable(iter);
}
if (debug_dump_regs) {
struct drm_printer p = drm_info_printer(&dsi->pdev->dev);
@ -1613,7 +1629,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
* from our driver, since we need to sequence them within the
* encoder's enable/disable paths.
*/
list_splice(&dsi->encoder->bridge_chain, &dsi->bridge_chain);
list_splice_init(&dsi->encoder->bridge_chain, &dsi->bridge_chain);
if (dsi->port == 0)
vc4_debugfs_add_regset32(drm, "dsi0_regs", &dsi->regset);
@ -1639,7 +1655,7 @@ static void vc4_dsi_unbind(struct device *dev, struct device *master,
* Restore the bridge_chain so the bridge detach procedure can happen
* normally.
*/
list_splice(&dsi->bridge_chain, &dsi->encoder->bridge_chain);
list_splice_init(&dsi->bridge_chain, &dsi->encoder->bridge_chain);
vc4_dsi_encoder_destroy(dsi->encoder);
if (dsi->port == 1)

View File

@ -267,7 +267,8 @@ static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs =
};
static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
struct drm_encoder *encoder)
struct drm_encoder *encoder,
struct i2c_adapter *ddc)
{
struct drm_connector *connector;
struct vc4_hdmi_connector *hdmi_connector;
@ -281,8 +282,10 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
hdmi_connector->encoder = encoder;
drm_connector_init(dev, connector, &vc4_hdmi_connector_funcs,
DRM_MODE_CONNECTOR_HDMIA);
drm_connector_init_with_ddc(dev, connector,
&vc4_hdmi_connector_funcs,
DRM_MODE_CONNECTOR_HDMIA,
ddc);
drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs);
/* Create and attach TV margin props to this connector. */
@ -1395,7 +1398,8 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
DRM_MODE_ENCODER_TMDS, NULL);
drm_encoder_helper_add(hdmi->encoder, &vc4_hdmi_encoder_helper_funcs);
hdmi->connector = vc4_hdmi_connector_init(drm, hdmi->encoder);
hdmi->connector =
vc4_hdmi_connector_init(drm, hdmi->encoder, hdmi->ddc);
if (IS_ERR(hdmi->connector)) {
ret = PTR_ERR(hdmi->connector);
goto err_destroy_encoder;

View File

@ -319,8 +319,10 @@ static int zx_hdmi_register(struct drm_device *drm, struct zx_hdmi *hdmi)
hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
drm_connector_init(drm, &hdmi->connector, &zx_hdmi_connector_funcs,
DRM_MODE_CONNECTOR_HDMIA);
drm_connector_init_with_ddc(drm, &hdmi->connector,
&zx_hdmi_connector_funcs,
DRM_MODE_CONNECTOR_HDMIA,
&hdmi->ddc->adap);
drm_connector_helper_add(&hdmi->connector,
&zx_hdmi_connector_helper_funcs);

View File

@ -165,8 +165,10 @@ static int zx_vga_register(struct drm_device *drm, struct zx_vga *vga)
vga->connector.polled = DRM_CONNECTOR_POLL_HPD;
ret = drm_connector_init(drm, connector, &zx_vga_connector_funcs,
DRM_MODE_CONNECTOR_VGA);
ret = drm_connector_init_with_ddc(drm, connector,
&zx_vga_connector_funcs,
DRM_MODE_CONNECTOR_VGA,
&vga->ddc->adap);
if (ret) {
DRM_DEV_ERROR(dev, "failed to init connector: %d\n", ret);
goto clean_encoder;

View File

@ -456,7 +456,6 @@ static int mmphw_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "%s: no IRQ defined\n", __func__);
ret = -ENOENT;
goto failed;
}

View File

@ -669,9 +669,6 @@ __drm_atomic_get_current_plane_state(struct drm_atomic_state *state,
return plane->state;
}
int __must_check
drm_atomic_add_encoder_bridges(struct drm_atomic_state *state,
struct drm_encoder *encoder);
int __must_check
drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
struct drm_crtc *crtc);

View File

@ -25,8 +25,6 @@
#include <linux/list.h>
#include <linux/ctype.h>
#include <drm/drm_atomic.h>
#include <drm/drm_encoder.h>
#include <drm/drm_mode_object.h>
#include <drm/drm_modes.h>
@ -35,65 +33,6 @@ struct drm_bridge;
struct drm_bridge_timings;
struct drm_panel;
/**
* struct drm_bus_cfg - bus configuration
*
* This structure stores the configuration of a physical bus between two
* components in an output pipeline, usually between two bridges, an encoder
* and a bridge, or a bridge and a connector.
*
* The bus configuration is stored in &drm_bridge_state separately for the
* input and output buses, as seen from the point of view of each bridge. The
* bus configuration of a bridge output is usually identical to the
* configuration of the next bridge's input, but may differ if the signals are
* modified between the two bridges, for instance by an inverter on the board.
* The input and output configurations of a bridge may differ if the bridge
* modifies the signals internally, for instance by performing format
* conversion, or modifying signals polarities.
*/
struct drm_bus_cfg {
/**
* @format: format used on this bus (one of the MEDIA_BUS_FMT_* format)
*
* This field should not be directly modified by drivers
* (&drm_atomic_bridge_chain_select_bus_fmts() takes care of the bus
* format negotiation).
*/
u32 format;
/**
* @flags: DRM_BUS_* flags used on this bus
*/
u32 flags;
};
/**
* struct drm_bridge_state - Atomic bridge state object
* @base: inherit from &drm_private_state
* @bridge: the bridge this state refers to
*/
struct drm_bridge_state {
struct drm_private_state base;
struct drm_bridge *bridge;
/**
* @input_bus_cfg: input bus configuration
*/
struct drm_bus_cfg input_bus_cfg;
/**
* @output_bus_cfg: input bus configuration
*/
struct drm_bus_cfg output_bus_cfg;
};
static inline struct drm_bridge_state *
drm_priv_to_bridge_state(struct drm_private_state *priv)
{
return container_of(priv, struct drm_bridge_state, base);
}
/**
* struct drm_bridge_funcs - drm_bridge control functions
*/
@ -170,9 +109,7 @@ struct drm_bridge_funcs {
* this function passes all other callbacks must succeed for this
* configuration.
*
* The mode_fixup callback is optional. &drm_bridge_funcs.mode_fixup()
* is not called when &drm_bridge_funcs.atomic_check() is implemented,
* so only one of them should be provided.
* The @mode_fixup callback is optional.
*
* NOTE:
*
@ -326,7 +263,7 @@ struct drm_bridge_funcs {
* The @atomic_pre_enable callback is optional.
*/
void (*atomic_pre_enable)(struct drm_bridge *bridge,
struct drm_bridge_state *old_bridge_state);
struct drm_atomic_state *old_state);
/**
* @atomic_enable:
@ -351,7 +288,7 @@ struct drm_bridge_funcs {
* The @atomic_enable callback is optional.
*/
void (*atomic_enable)(struct drm_bridge *bridge,
struct drm_bridge_state *old_bridge_state);
struct drm_atomic_state *old_state);
/**
* @atomic_disable:
*
@ -374,7 +311,7 @@ struct drm_bridge_funcs {
* The @atomic_disable callback is optional.
*/
void (*atomic_disable)(struct drm_bridge *bridge,
struct drm_bridge_state *old_bridge_state);
struct drm_atomic_state *old_state);
/**
* @atomic_post_disable:
@ -400,146 +337,7 @@ struct drm_bridge_funcs {
* The @atomic_post_disable callback is optional.
*/
void (*atomic_post_disable)(struct drm_bridge *bridge,
struct drm_bridge_state *old_bridge_state);
/**
* @atomic_duplicate_state:
*
* Duplicate the current bridge state object (which is guaranteed to be
* non-NULL).
*
* The atomic_duplicate_state() is optional. When not implemented the
* core allocates a drm_bridge_state object and calls
* &__drm_atomic_helper_bridge_duplicate_state() to initialize it.
*
* RETURNS:
* A valid drm_bridge_state object or NULL if the allocation fails.
*/
struct drm_bridge_state *(*atomic_duplicate_state)(struct drm_bridge *bridge);
/**
* @atomic_destroy_state:
*
* Destroy a bridge state object previously allocated by
* &drm_bridge_funcs.atomic_duplicate_state().
*
* The atomic_destroy_state hook is optional. When not implemented the
* core calls kfree() on the state.
*/
void (*atomic_destroy_state)(struct drm_bridge *bridge,
struct drm_bridge_state *state);
/**
* @atomic_get_output_bus_fmts:
*
* Return the supported bus formats on the output end of a bridge.
* The returned array must be allocated with kmalloc() and will be
* freed by the caller. If the allocation fails, NULL should be
* returned. num_output_fmts must be set to the returned array size.
* Formats listed in the returned array should be listed in decreasing
* preference order (the core will try all formats until it finds one
* that works).
*
* This method is only called on the last element of the bridge chain
* as part of the bus format negotiation process that happens in
* &drm_atomic_bridge_chain_select_bus_fmts().
* This method is optional. When not implemented, the core will
* fall back to &drm_connector.display_info.bus_formats[0] if
* &drm_connector.display_info.num_bus_formats > 0,
* or to MEDIA_BUS_FMT_FIXED otherwise.
*/
u32 *(*atomic_get_output_bus_fmts)(struct drm_bridge *bridge,
struct drm_bridge_state *bridge_state,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state,
unsigned int *num_output_fmts);
/**
* @atomic_get_input_bus_fmts:
*
* Return the supported bus formats on the input end of a bridge for
* a specific output bus format.
*
* The returned array must be allocated with kmalloc() and will be
* freed by the caller. If the allocation fails, NULL should be
* returned. num_output_fmts must be set to the returned array size.
* Formats listed in the returned array should be listed in decreasing
* preference order (the core will try all formats until it finds one
* that works). When the format is not supported NULL should be
* returned and *num_output_fmts should be set to 0.
*
* This method is called on all elements of the bridge chain as part of
* the bus format negotiation process that happens in
* &drm_atomic_bridge_chain_select_bus_fmts().
* This method is optional. When not implemented, the core will bypass
* bus format negotiation on this element of the bridge without
* failing, and the previous element in the chain will be passed
* MEDIA_BUS_FMT_FIXED as its output bus format.
*
* Bridge drivers that need to support being linked to bridges that are
* not supporting bus format negotiation should handle the
* output_fmt == MEDIA_BUS_FMT_FIXED case appropriately, by selecting a
* sensible default value or extracting this information from somewhere
* else (FW property, &drm_display_mode, &drm_display_info, ...)
*
* Note: Even if input format selection on the first bridge has no
* impact on the negotiation process (bus format negotiation stops once
* we reach the first element of the chain), drivers are expected to
* return accurate input formats as the input format may be used to
* configure the CRTC output appropriately.
*/
u32 *(*atomic_get_input_bus_fmts)(struct drm_bridge *bridge,
struct drm_bridge_state *bridge_state,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state,
u32 output_fmt,
unsigned int *num_input_fmts);
/**
* @atomic_check:
*
* This method is responsible for checking bridge state correctness.
* It can also check the state of the surrounding components in chain
* to make sure the whole pipeline can work properly.
*
* &drm_bridge_funcs.atomic_check() hooks are called in reverse
* order (from the last to the first bridge).
*
* This method is optional. &drm_bridge_funcs.mode_fixup() is not
* called when &drm_bridge_funcs.atomic_check() is implemented, so only
* one of them should be provided.
*
* If drivers need to tweak &drm_bridge_state.input_bus_cfg.flags or
* &drm_bridge_state.output_bus_cfg.flags it should should happen in
* this function. By default the &drm_bridge_state.output_bus_cfg.flags
* field is set to the next bridge
* &drm_bridge_state.input_bus_cfg.flags value or
* &drm_connector.display_info.bus_flags if the bridge is the last
* element in the chain.
*
* RETURNS:
* zero if the check passed, a negative error code otherwise.
*/
int (*atomic_check)(struct drm_bridge *bridge,
struct drm_bridge_state *bridge_state,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state);
/**
* @atomic_reset:
*
* Reset the bridge to a predefined state (or retrieve its current
* state) and return a &drm_bridge_state object matching this state.
* This function is called at attach time.
*
* The atomic_reset hook is optional. When not implemented the core
* allocates a new state and calls &__drm_atomic_helper_bridge_reset().
*
* RETURNS:
* A valid drm_bridge_state object in case of success, an ERR_PTR()
* giving the reason of the failure otherwise.
*/
struct drm_bridge_state *(*atomic_reset)(struct drm_bridge *bridge);
struct drm_atomic_state *old_state);
};
/**
@ -582,8 +380,6 @@ struct drm_bridge_timings {
* struct drm_bridge - central DRM bridge control structure
*/
struct drm_bridge {
/** @base: inherit from &drm_private_object */
struct drm_private_obj base;
/** @dev: DRM device this bridge belongs to */
struct drm_device *dev;
/** @encoder: encoder to which this bridge is connected */
@ -608,12 +404,6 @@ struct drm_bridge {
void *driver_private;
};
static inline struct drm_bridge *
drm_priv_to_bridge(struct drm_private_obj *priv)
{
return container_of(priv, struct drm_bridge, base);
}
void drm_bridge_add(struct drm_bridge *bridge);
void drm_bridge_remove(struct drm_bridge *bridge);
struct drm_bridge *of_drm_find_bridge(struct device_node *np);
@ -692,9 +482,6 @@ void drm_bridge_chain_mode_set(struct drm_bridge *bridge,
void drm_bridge_chain_pre_enable(struct drm_bridge *bridge);
void drm_bridge_chain_enable(struct drm_bridge *bridge);
int drm_atomic_bridge_chain_check(struct drm_bridge *bridge,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state);
void drm_atomic_bridge_chain_disable(struct drm_bridge *bridge,
struct drm_atomic_state *state);
void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge,
@ -704,58 +491,6 @@ void drm_atomic_bridge_chain_pre_enable(struct drm_bridge *bridge,
void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge,
struct drm_atomic_state *state);
u32 *
drm_atomic_helper_bridge_propagate_bus_fmt(struct drm_bridge *bridge,
struct drm_bridge_state *bridge_state,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state,
u32 output_fmt,
unsigned int *num_input_fmts);
void __drm_atomic_helper_bridge_reset(struct drm_bridge *bridge,
struct drm_bridge_state *state);
void __drm_atomic_helper_bridge_duplicate_state(struct drm_bridge *bridge,
struct drm_bridge_state *new);
static inline struct drm_bridge_state *
drm_atomic_get_bridge_state(struct drm_atomic_state *state,
struct drm_bridge *bridge)
{
struct drm_private_state *obj_state;
obj_state = drm_atomic_get_private_obj_state(state, &bridge->base);
if (IS_ERR(obj_state))
return ERR_CAST(obj_state);
return drm_priv_to_bridge_state(obj_state);
}
static inline struct drm_bridge_state *
drm_atomic_get_old_bridge_state(struct drm_atomic_state *state,
struct drm_bridge *bridge)
{
struct drm_private_state *obj_state;
obj_state = drm_atomic_get_old_private_obj_state(state, &bridge->base);
if (!obj_state)
return NULL;
return drm_priv_to_bridge_state(obj_state);
}
static inline struct drm_bridge_state *
drm_atomic_get_new_bridge_state(struct drm_atomic_state *state,
struct drm_bridge *bridge)
{
struct drm_private_state *obj_state;
obj_state = drm_atomic_get_new_private_obj_state(state, &bridge->base);
if (!obj_state)
return NULL;
return drm_priv_to_bridge_state(obj_state);
}
#ifdef CONFIG_DRM_PANEL_BRIDGE
struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel);
struct drm_bridge *drm_panel_bridge_add_typed(struct drm_panel *panel,

View File

@ -2,6 +2,8 @@
#ifndef __DRM_FB_CMA_HELPER_H__
#define __DRM_FB_CMA_HELPER_H__
#include <linux/types.h>
struct drm_framebuffer;
struct drm_plane_state;