mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-01 10:43:43 +00:00
Merge tag 'drm-misc-next-2024-11-08' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next
drm-misc-next for v6.13: UAPI Changes: - Add 1X7X5 media-bus formats. Cross-subsystem Changes: - Maintainer updates for VKMS and IT6263. - Add media-bus-fmt for MEDIA_BUS_FMT_RGB101010_1X7X5_*. - Add IT6263 DT bindings and driver. Core Changes: - Add ABGR210101010 support to panic handler. - Use ATOMIC64_INIT in drm_file.c - Improve scheduler teardown documentation. Driver Changes: - Make mediatek compile on ARM again. - Add missing drm/drm_bridge.h header include, already in drm-next. - Small fixes and cleanups to vkms, bridge/it6505, panfrost, panthor. - Add panic support to nouveau for nv50+. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/344afe41-d27b-408a-8542-bfecfd3555f6@linux.intel.com
This commit is contained in:
commit
56b70bf9ec
250
Documentation/devicetree/bindings/display/bridge/ite,it6263.yaml
Normal file
250
Documentation/devicetree/bindings/display/bridge/ite,it6263.yaml
Normal file
@ -0,0 +1,250 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/bridge/ite,it6263.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ITE IT6263 LVDS to HDMI converter
|
||||
|
||||
maintainers:
|
||||
- Liu Ying <victor.liu@nxp.com>
|
||||
|
||||
description: |
|
||||
The IT6263 is a high-performance single-chip De-SSC(De-Spread Spectrum) LVDS
|
||||
to HDMI converter. Combined with LVDS receiver and HDMI 1.4a transmitter,
|
||||
the IT6263 supports LVDS input and HDMI 1.4 output by conversion function.
|
||||
The built-in LVDS receiver can support single-link and dual-link LVDS inputs,
|
||||
and the built-in HDMI transmitter is fully compliant with HDMI 1.4a/3D, HDCP
|
||||
1.2 and backward compatible with DVI 1.0 specification.
|
||||
|
||||
The IT6263 also encodes and transmits up to 8 channels of I2S digital audio,
|
||||
with sampling rate up to 192KHz and sample size up to 24 bits. In addition,
|
||||
an S/PDIF input port takes in compressed audio of up to 192KHz frame rate.
|
||||
|
||||
The newly supported High-Bit Rate(HBR) audio by HDMI specifications v1.3 is
|
||||
provided by the IT6263 in two interfaces: the four I2S input ports or the
|
||||
S/PDIF input port. With both interfaces the highest possible HBR frame rate
|
||||
is supported at up to 768KHz.
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/display/lvds-dual-ports.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: ite,it6263
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
description: audio master clock
|
||||
|
||||
clock-names:
|
||||
const: mclk
|
||||
|
||||
data-mapping:
|
||||
enum:
|
||||
- jeida-18
|
||||
- jeida-24
|
||||
- jeida-30
|
||||
- vesa-24
|
||||
- vesa-30
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
|
||||
ivdd-supply:
|
||||
description: 1.8V digital logic power
|
||||
|
||||
ovdd-supply:
|
||||
description: 3.3V I/O pin power
|
||||
|
||||
txavcc18-supply:
|
||||
description: 1.8V HDMI analog frontend power
|
||||
|
||||
txavcc33-supply:
|
||||
description: 3.3V HDMI analog frontend power
|
||||
|
||||
pvcc1-supply:
|
||||
description: 1.8V HDMI frontend core PLL power
|
||||
|
||||
pvcc2-supply:
|
||||
description: 1.8V HDMI frontend filter PLL power
|
||||
|
||||
avcc-supply:
|
||||
description: 3.3V LVDS frontend power
|
||||
|
||||
anvdd-supply:
|
||||
description: 1.8V LVDS frontend analog power
|
||||
|
||||
apvdd-supply:
|
||||
description: 1.8V LVDS frontend PLL power
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 0
|
||||
|
||||
ite,i2s-audio-fifo-sources:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
items:
|
||||
enum: [0, 1, 2, 3]
|
||||
description:
|
||||
Each array element indicates the pin number of an I2S serial data input
|
||||
line which is connected to an audio FIFO, from audio FIFO0 to FIFO3.
|
||||
|
||||
ite,rl-channel-swap-audio-sources:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
uniqueItems: true
|
||||
items:
|
||||
enum: [0, 1, 2, 3]
|
||||
description:
|
||||
Each array element indicates an audio source whose right channel and left
|
||||
channel are swapped by this converter. For I2S, the element is the pin
|
||||
number of an I2S serial data input line. For S/PDIF, the element is always
|
||||
0.
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
properties:
|
||||
port@0: true
|
||||
|
||||
port@1:
|
||||
oneOf:
|
||||
- required: [dual-lvds-odd-pixels]
|
||||
- required: [dual-lvds-even-pixels]
|
||||
|
||||
port@2:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: video port for the HDMI output
|
||||
|
||||
port@3:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: sound input port
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@2
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- data-mapping
|
||||
- ivdd-supply
|
||||
- ovdd-supply
|
||||
- txavcc18-supply
|
||||
- txavcc33-supply
|
||||
- pvcc1-supply
|
||||
- pvcc2-supply
|
||||
- avcc-supply
|
||||
- anvdd-supply
|
||||
- apvdd-supply
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
/* single-link LVDS input */
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
hdmi@4c {
|
||||
compatible = "ite,it6263";
|
||||
reg = <0x4c>;
|
||||
data-mapping = "jeida-24";
|
||||
reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
|
||||
ivdd-supply = <®_buck5>;
|
||||
ovdd-supply = <®_vext_3v3>;
|
||||
txavcc18-supply = <®_buck5>;
|
||||
txavcc33-supply = <®_vext_3v3>;
|
||||
pvcc1-supply = <®_buck5>;
|
||||
pvcc2-supply = <®_buck5>;
|
||||
avcc-supply = <®_vext_3v3>;
|
||||
anvdd-supply = <®_buck5>;
|
||||
apvdd-supply = <®_buck5>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
it6263_lvds_link1: endpoint {
|
||||
remote-endpoint = <&ldb_lvds_ch0>;
|
||||
};
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
|
||||
it6263_out: endpoint {
|
||||
remote-endpoint = <&hdmi_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
- |
|
||||
/* dual-link LVDS input */
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
hdmi@4c {
|
||||
compatible = "ite,it6263";
|
||||
reg = <0x4c>;
|
||||
data-mapping = "jeida-24";
|
||||
reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
|
||||
ivdd-supply = <®_buck5>;
|
||||
ovdd-supply = <®_vext_3v3>;
|
||||
txavcc18-supply = <®_buck5>;
|
||||
txavcc33-supply = <®_vext_3v3>;
|
||||
pvcc1-supply = <®_buck5>;
|
||||
pvcc2-supply = <®_buck5>;
|
||||
avcc-supply = <®_vext_3v3>;
|
||||
anvdd-supply = <®_buck5>;
|
||||
apvdd-supply = <®_buck5>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
dual-lvds-odd-pixels;
|
||||
|
||||
it6263_lvds_link1_dual: endpoint {
|
||||
remote-endpoint = <&ldb_lvds_ch0>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
dual-lvds-even-pixels;
|
||||
|
||||
it6263_lvds_link2_dual: endpoint {
|
||||
remote-endpoint = <&ldb_lvds_ch1>;
|
||||
};
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
|
||||
it6263_out_dual: endpoint {
|
||||
remote-endpoint = <&hdmi_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -26,12 +26,17 @@ description: |
|
||||
Device compatible with those specifications have been marketed under the
|
||||
FPD-Link and FlatLink brands.
|
||||
|
||||
This bindings also supports 30-bit data mapping compatible with JEIDA and
|
||||
VESA.
|
||||
|
||||
properties:
|
||||
data-mapping:
|
||||
enum:
|
||||
- jeida-18
|
||||
- jeida-24
|
||||
- jeida-30
|
||||
- vesa-24
|
||||
- vesa-30
|
||||
description: |
|
||||
The color signals mapping order.
|
||||
|
||||
@ -60,6 +65,19 @@ properties:
|
||||
DATA2 ><_CTL2_><_CTL1_><_CTL0_><__B7__><__B6__><__B5__><__B4__><
|
||||
DATA3 ><_CTL3_><__B1__><__B0__><__G1__><__G0__><__R1__><__R0__><
|
||||
|
||||
- "jeida-30" - 30-bit data mapping compatible with JEIDA and VESA. Data
|
||||
are transferred as follows on 5 LVDS lanes.
|
||||
|
||||
Slot 0 1 2 3 4 5 6
|
||||
________________ _________________
|
||||
Clock \_______________________/
|
||||
______ ______ ______ ______ ______ ______ ______
|
||||
DATA0 ><__G4__><__R9__><__R8__><__R7__><__R6__><__R5__><__R4__><
|
||||
DATA1 ><__B5__><__B4__><__G9__><__G8__><__G7__><__G6__><__G5__><
|
||||
DATA2 ><_CTL2_><_CTL1_><_CTL0_><__B9__><__B8__><__B7__><__B6__><
|
||||
DATA3 ><_CTL3_><__B3__><__B2__><__G3__><__G2__><__R3__><__R2__><
|
||||
DATA4 ><_CTL3_><__B1__><__B0__><__G1__><__G0__><__R1__><__R0__><
|
||||
|
||||
- "vesa-24" - 24-bit data mapping compatible with the [VESA] specification.
|
||||
Data are transferred as follows on 4 LVDS lanes.
|
||||
|
||||
@ -72,6 +90,19 @@ properties:
|
||||
DATA2 ><_CTL2_><_CTL1_><_CTL0_><__B5__><__B4__><__B3__><__B2__><
|
||||
DATA3 ><_CTL3_><__B7__><__B6__><__G7__><__G6__><__R7__><__R6__><
|
||||
|
||||
- "vesa-30" - 30-bit data mapping compatible with VESA. Data are
|
||||
transferred as follows on 5 LVDS lanes.
|
||||
|
||||
Slot 0 1 2 3 4 5 6
|
||||
________________ _________________
|
||||
Clock \_______________________/
|
||||
______ ______ ______ ______ ______ ______ ______
|
||||
DATA0 ><__G0__><__R5__><__R4__><__R3__><__R2__><__R1__><__R0__><
|
||||
DATA1 ><__B1__><__B0__><__G5__><__G4__><__G3__><__G2__><__G1__><
|
||||
DATA2 ><_CTL2_><_CTL1_><_CTL0_><__B5__><__B4__><__B3__><__B2__><
|
||||
DATA3 ><_CTL3_><__B7__><__B6__><__G7__><__G6__><__R7__><__R6__><
|
||||
DATA4 ><_CTL3_><__B9__><__B8__><__G9__><__G8__><__R9__><__R8__><
|
||||
|
||||
Control signals are mapped as follows.
|
||||
|
||||
CTL0: HSync
|
||||
|
@ -0,0 +1,63 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/lvds-dual-ports.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Dual-link LVDS Display Common Properties
|
||||
|
||||
maintainers:
|
||||
- Liu Ying <victor.liu@nxp.com>
|
||||
|
||||
description: |
|
||||
Common properties for LVDS displays with dual LVDS links. Extend LVDS display
|
||||
common properties defined in lvds.yaml.
|
||||
|
||||
Dual-link LVDS displays receive odd pixels and even pixels separately from
|
||||
the dual LVDS links. One link receives odd pixels and the other receives
|
||||
even pixels. Some of those displays may also use only one LVDS link to
|
||||
receive all pixels, being odd and even agnostic.
|
||||
|
||||
allOf:
|
||||
- $ref: lvds.yaml#
|
||||
|
||||
properties:
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
patternProperties:
|
||||
'^port@[01]$':
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
unevaluatedProperties: false
|
||||
description: |
|
||||
port@0 represents the first LVDS input link.
|
||||
port@1 represents the second LVDS input link.
|
||||
|
||||
properties:
|
||||
dual-lvds-odd-pixels:
|
||||
type: boolean
|
||||
description: LVDS input link for odd pixels
|
||||
|
||||
dual-lvds-even-pixels:
|
||||
type: boolean
|
||||
description: LVDS input link for even pixels
|
||||
|
||||
oneOf:
|
||||
- required: [dual-lvds-odd-pixels]
|
||||
- required: [dual-lvds-even-pixels]
|
||||
- properties:
|
||||
dual-lvds-odd-pixels: false
|
||||
dual-lvds-even-pixels: false
|
||||
|
||||
anyOf:
|
||||
- required:
|
||||
- port@0
|
||||
- required:
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- ports
|
||||
|
||||
additionalProperties: true
|
||||
|
||||
...
|
@ -20,6 +20,7 @@ description: |
|
||||
dual-lvds-odd-pixels or dual-lvds-even-pixels).
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/display/lvds-dual-ports.yaml#
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
@ -44,22 +45,10 @@ properties:
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
unevaluatedProperties: false
|
||||
description: The sink for odd pixels.
|
||||
properties:
|
||||
dual-lvds-odd-pixels: true
|
||||
|
||||
required:
|
||||
- dual-lvds-odd-pixels
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
unevaluatedProperties: false
|
||||
description: The sink for even pixels.
|
||||
properties:
|
||||
dual-lvds-even-pixels: true
|
||||
|
||||
required:
|
||||
- dual-lvds-even-pixels
|
||||
|
||||
@ -75,7 +64,6 @@ required:
|
||||
- height-mm
|
||||
- data-mapping
|
||||
- panel-timing
|
||||
- ports
|
||||
|
||||
examples:
|
||||
- |+
|
||||
|
@ -22,6 +22,7 @@ description: |
|
||||
If the panel is more advanced a dedicated binding file is required.
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/display/lvds-dual-ports.yaml#
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
@ -55,28 +56,10 @@ properties:
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
unevaluatedProperties: false
|
||||
description: The first sink port.
|
||||
|
||||
properties:
|
||||
dual-lvds-odd-pixels:
|
||||
type: boolean
|
||||
description: The first sink port for odd pixels.
|
||||
|
||||
required:
|
||||
- dual-lvds-odd-pixels
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
unevaluatedProperties: false
|
||||
description: The second sink port.
|
||||
|
||||
properties:
|
||||
dual-lvds-even-pixels:
|
||||
type: boolean
|
||||
description: The second sink port for even pixels.
|
||||
|
||||
required:
|
||||
- dual-lvds-even-pixels
|
||||
|
||||
@ -88,7 +71,6 @@ unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- ports
|
||||
- power-supply
|
||||
|
||||
examples:
|
||||
|
@ -2225,7 +2225,7 @@ The following table list existing packed 48bit wide RGB formats.
|
||||
\endgroup
|
||||
|
||||
On LVDS buses, usually each sample is transferred serialized in seven
|
||||
time slots per pixel clock, on three (18-bit) or four (24-bit)
|
||||
time slots per pixel clock, on three (18-bit) or four (24-bit) or five (30-bit)
|
||||
differential data pairs at the same time. The remaining bits are used
|
||||
for control signals as defined by SPWG/PSWG/VESA or JEIDA standards. The
|
||||
24-bit RGB format serialized in seven time slots on four lanes using
|
||||
@ -2246,11 +2246,12 @@ JEIDA defined bit mapping will be named
|
||||
- Code
|
||||
-
|
||||
-
|
||||
- :cspan:`3` Data organization
|
||||
- :cspan:`4` Data organization
|
||||
* -
|
||||
-
|
||||
- Timeslot
|
||||
- Lane
|
||||
- 4
|
||||
- 3
|
||||
- 2
|
||||
- 1
|
||||
@ -2262,6 +2263,7 @@ JEIDA defined bit mapping will be named
|
||||
- 0
|
||||
-
|
||||
-
|
||||
-
|
||||
- d
|
||||
- b\ :sub:`1`
|
||||
- g\ :sub:`0`
|
||||
@ -2270,6 +2272,7 @@ JEIDA defined bit mapping will be named
|
||||
- 1
|
||||
-
|
||||
-
|
||||
-
|
||||
- d
|
||||
- b\ :sub:`0`
|
||||
- r\ :sub:`5`
|
||||
@ -2278,6 +2281,7 @@ JEIDA defined bit mapping will be named
|
||||
- 2
|
||||
-
|
||||
-
|
||||
-
|
||||
- d
|
||||
- g\ :sub:`5`
|
||||
- r\ :sub:`4`
|
||||
@ -2286,6 +2290,7 @@ JEIDA defined bit mapping will be named
|
||||
- 3
|
||||
-
|
||||
-
|
||||
-
|
||||
- b\ :sub:`5`
|
||||
- g\ :sub:`4`
|
||||
- r\ :sub:`3`
|
||||
@ -2294,6 +2299,7 @@ JEIDA defined bit mapping will be named
|
||||
- 4
|
||||
-
|
||||
-
|
||||
-
|
||||
- b\ :sub:`4`
|
||||
- g\ :sub:`3`
|
||||
- r\ :sub:`2`
|
||||
@ -2302,6 +2308,7 @@ JEIDA defined bit mapping will be named
|
||||
- 5
|
||||
-
|
||||
-
|
||||
-
|
||||
- b\ :sub:`3`
|
||||
- g\ :sub:`2`
|
||||
- r\ :sub:`1`
|
||||
@ -2310,6 +2317,7 @@ JEIDA defined bit mapping will be named
|
||||
- 6
|
||||
-
|
||||
-
|
||||
-
|
||||
- b\ :sub:`2`
|
||||
- g\ :sub:`1`
|
||||
- r\ :sub:`0`
|
||||
@ -2319,6 +2327,7 @@ JEIDA defined bit mapping will be named
|
||||
- 0x1011
|
||||
- 0
|
||||
-
|
||||
-
|
||||
- d
|
||||
- d
|
||||
- b\ :sub:`1`
|
||||
@ -2327,6 +2336,7 @@ JEIDA defined bit mapping will be named
|
||||
-
|
||||
- 1
|
||||
-
|
||||
-
|
||||
- b\ :sub:`7`
|
||||
- d
|
||||
- b\ :sub:`0`
|
||||
@ -2335,6 +2345,7 @@ JEIDA defined bit mapping will be named
|
||||
-
|
||||
- 2
|
||||
-
|
||||
-
|
||||
- b\ :sub:`6`
|
||||
- d
|
||||
- g\ :sub:`5`
|
||||
@ -2343,6 +2354,7 @@ JEIDA defined bit mapping will be named
|
||||
-
|
||||
- 3
|
||||
-
|
||||
-
|
||||
- g\ :sub:`7`
|
||||
- b\ :sub:`5`
|
||||
- g\ :sub:`4`
|
||||
@ -2351,6 +2363,7 @@ JEIDA defined bit mapping will be named
|
||||
-
|
||||
- 4
|
||||
-
|
||||
-
|
||||
- g\ :sub:`6`
|
||||
- b\ :sub:`4`
|
||||
- g\ :sub:`3`
|
||||
@ -2359,6 +2372,7 @@ JEIDA defined bit mapping will be named
|
||||
-
|
||||
- 5
|
||||
-
|
||||
-
|
||||
- r\ :sub:`7`
|
||||
- b\ :sub:`3`
|
||||
- g\ :sub:`2`
|
||||
@ -2367,6 +2381,7 @@ JEIDA defined bit mapping will be named
|
||||
-
|
||||
- 6
|
||||
-
|
||||
-
|
||||
- r\ :sub:`6`
|
||||
- b\ :sub:`2`
|
||||
- g\ :sub:`1`
|
||||
@ -2377,6 +2392,7 @@ JEIDA defined bit mapping will be named
|
||||
- 0x1012
|
||||
- 0
|
||||
-
|
||||
-
|
||||
- d
|
||||
- d
|
||||
- b\ :sub:`3`
|
||||
@ -2385,6 +2401,7 @@ JEIDA defined bit mapping will be named
|
||||
-
|
||||
- 1
|
||||
-
|
||||
-
|
||||
- b\ :sub:`1`
|
||||
- d
|
||||
- b\ :sub:`2`
|
||||
@ -2393,6 +2410,7 @@ JEIDA defined bit mapping will be named
|
||||
-
|
||||
- 2
|
||||
-
|
||||
-
|
||||
- b\ :sub:`0`
|
||||
- d
|
||||
- g\ :sub:`7`
|
||||
@ -2401,6 +2419,7 @@ JEIDA defined bit mapping will be named
|
||||
-
|
||||
- 3
|
||||
-
|
||||
-
|
||||
- g\ :sub:`1`
|
||||
- b\ :sub:`7`
|
||||
- g\ :sub:`6`
|
||||
@ -2409,6 +2428,7 @@ JEIDA defined bit mapping will be named
|
||||
-
|
||||
- 4
|
||||
-
|
||||
-
|
||||
- g\ :sub:`0`
|
||||
- b\ :sub:`6`
|
||||
- g\ :sub:`5`
|
||||
@ -2417,6 +2437,7 @@ JEIDA defined bit mapping will be named
|
||||
-
|
||||
- 5
|
||||
-
|
||||
-
|
||||
- r\ :sub:`1`
|
||||
- b\ :sub:`5`
|
||||
- g\ :sub:`4`
|
||||
@ -2425,10 +2446,141 @@ JEIDA defined bit mapping will be named
|
||||
-
|
||||
- 6
|
||||
-
|
||||
-
|
||||
- r\ :sub:`0`
|
||||
- b\ :sub:`4`
|
||||
- g\ :sub:`3`
|
||||
- r\ :sub:`2`
|
||||
* .. _MEDIA-BUS-FMT-RGB101010-1X7X5-SPWG:
|
||||
|
||||
- MEDIA_BUS_FMT_RGB101010_1X7X5_SPWG
|
||||
- 0x1026
|
||||
- 0
|
||||
-
|
||||
- d
|
||||
- d
|
||||
- d
|
||||
- b\ :sub:`1`
|
||||
- g\ :sub:`0`
|
||||
* -
|
||||
-
|
||||
- 1
|
||||
-
|
||||
- b\ :sub:`9`
|
||||
- b\ :sub:`7`
|
||||
- d
|
||||
- b\ :sub:`0`
|
||||
- r\ :sub:`5`
|
||||
* -
|
||||
-
|
||||
- 2
|
||||
-
|
||||
- b\ :sub:`8`
|
||||
- b\ :sub:`6`
|
||||
- d
|
||||
- g\ :sub:`5`
|
||||
- r\ :sub:`4`
|
||||
* -
|
||||
-
|
||||
- 3
|
||||
-
|
||||
- g\ :sub:`9`
|
||||
- g\ :sub:`7`
|
||||
- b\ :sub:`5`
|
||||
- g\ :sub:`4`
|
||||
- r\ :sub:`3`
|
||||
* -
|
||||
-
|
||||
- 4
|
||||
-
|
||||
- g\ :sub:`8`
|
||||
- g\ :sub:`6`
|
||||
- b\ :sub:`4`
|
||||
- g\ :sub:`3`
|
||||
- r\ :sub:`2`
|
||||
* -
|
||||
-
|
||||
- 5
|
||||
-
|
||||
- r\ :sub:`9`
|
||||
- r\ :sub:`7`
|
||||
- b\ :sub:`3`
|
||||
- g\ :sub:`2`
|
||||
- r\ :sub:`1`
|
||||
* -
|
||||
-
|
||||
- 6
|
||||
-
|
||||
- r\ :sub:`8`
|
||||
- r\ :sub:`6`
|
||||
- b\ :sub:`2`
|
||||
- g\ :sub:`1`
|
||||
- r\ :sub:`0`
|
||||
* .. _MEDIA-BUS-FMT-RGB101010-1X7X5-JEIDA:
|
||||
|
||||
- MEDIA_BUS_FMT_RGB101010_1X7X5_JEIDA
|
||||
- 0x1027
|
||||
- 0
|
||||
-
|
||||
- d
|
||||
- d
|
||||
- d
|
||||
- b\ :sub:`5`
|
||||
- g\ :sub:`4`
|
||||
* -
|
||||
-
|
||||
- 1
|
||||
-
|
||||
- b\ :sub:`1`
|
||||
- b\ :sub:`3`
|
||||
- d
|
||||
- b\ :sub:`4`
|
||||
- r\ :sub:`9`
|
||||
* -
|
||||
-
|
||||
- 2
|
||||
-
|
||||
- b\ :sub:`0`
|
||||
- b\ :sub:`2`
|
||||
- d
|
||||
- g\ :sub:`9`
|
||||
- r\ :sub:`8`
|
||||
* -
|
||||
-
|
||||
- 3
|
||||
-
|
||||
- g\ :sub:`1`
|
||||
- g\ :sub:`3`
|
||||
- b\ :sub:`9`
|
||||
- g\ :sub:`8`
|
||||
- r\ :sub:`7`
|
||||
* -
|
||||
-
|
||||
- 4
|
||||
-
|
||||
- g\ :sub:`0`
|
||||
- g\ :sub:`2`
|
||||
- b\ :sub:`8`
|
||||
- g\ :sub:`7`
|
||||
- r\ :sub:`6`
|
||||
* -
|
||||
-
|
||||
- 5
|
||||
-
|
||||
- r\ :sub:`1`
|
||||
- r\ :sub:`3`
|
||||
- b\ :sub:`7`
|
||||
- g\ :sub:`6`
|
||||
- r\ :sub:`5`
|
||||
* -
|
||||
-
|
||||
- 6
|
||||
-
|
||||
- r\ :sub:`0`
|
||||
- r\ :sub:`2`
|
||||
- b\ :sub:`6`
|
||||
- g\ :sub:`5`
|
||||
- r\ :sub:`4`
|
||||
|
||||
.. raw:: latex
|
||||
|
||||
|
@ -7448,7 +7448,6 @@ T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/udl/
|
||||
|
||||
DRM DRIVER FOR VIRTUAL KERNEL MODESETTING (VKMS)
|
||||
M: Maíra Canal <mairacanal@riseup.net>
|
||||
M: Louis Chauvet <louis.chauvet@bootlin.com>
|
||||
R: Haneen Mohammed <hamohammed.sa@gmail.com>
|
||||
R: Simona Vetter <simona@ffwll.ch>
|
||||
@ -12135,6 +12134,14 @@ W: https://linuxtv.org
|
||||
Q: http://patchwork.linuxtv.org/project/linux-media/list/
|
||||
F: drivers/media/tuners/it913x*
|
||||
|
||||
ITE IT6263 LVDS TO HDMI BRIDGE DRIVER
|
||||
M: Liu Ying <victor.liu@nxp.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/bridge/ite,it6263.yaml
|
||||
F: drivers/gpu/drm/bridge/ite-it6263.c
|
||||
|
||||
ITE IT66121 HDMI BRIDGE DRIVER
|
||||
M: Phong LE <ple@baylibre.com>
|
||||
M: Neil Armstrong <neil.armstrong@linaro.org>
|
||||
|
@ -90,6 +90,17 @@ config DRM_FSL_LDB
|
||||
help
|
||||
Support for i.MX8MP DPI-to-LVDS on-SoC encoder.
|
||||
|
||||
config DRM_ITE_IT6263
|
||||
tristate "ITE IT6263 LVDS/HDMI bridge"
|
||||
depends on OF
|
||||
select DRM_DISPLAY_HDMI_STATE_HELPER
|
||||
select DRM_DISPLAY_HELPER
|
||||
select DRM_BRIDGE_CONNECTOR
|
||||
select DRM_KMS_HELPER
|
||||
select REGMAP_I2C
|
||||
help
|
||||
ITE IT6263 LVDS to HDMI bridge chip driver.
|
||||
|
||||
config DRM_ITE_IT6505
|
||||
tristate "ITE IT6505 DisplayPort bridge"
|
||||
depends on OF
|
||||
|
@ -6,6 +6,7 @@ obj-$(CONFIG_DRM_CHRONTEL_CH7033) += chrontel-ch7033.o
|
||||
obj-$(CONFIG_DRM_CROS_EC_ANX7688) += cros-ec-anx7688.o
|
||||
obj-$(CONFIG_DRM_DISPLAY_CONNECTOR) += display-connector.o
|
||||
obj-$(CONFIG_DRM_FSL_LDB) += fsl-ldb.o
|
||||
obj-$(CONFIG_DRM_ITE_IT6263) += ite-it6263.o
|
||||
obj-$(CONFIG_DRM_ITE_IT6505) += ite-it6505.o
|
||||
obj-$(CONFIG_DRM_LONTIUM_LT8912B) += lontium-lt8912b.o
|
||||
obj-$(CONFIG_DRM_LONTIUM_LT9211) += lontium-lt9211.o
|
||||
|
898
drivers/gpu/drm/bridge/ite-it6263.c
Normal file
898
drivers/gpu/drm/bridge/ite-it6263.c
Normal file
@ -0,0 +1,898 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright 2024 NXP
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/hdmi.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/media-bus-format.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <drm/display/drm_hdmi_helper.h>
|
||||
#include <drm/display/drm_hdmi_state_helper.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_atomic_state_helper.h>
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_bridge_connector.h>
|
||||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* LVDS registers
|
||||
*/
|
||||
|
||||
/* LVDS software reset registers */
|
||||
#define LVDS_REG_05 0x05
|
||||
#define REG_SOFT_P_RST BIT(1)
|
||||
|
||||
/* LVDS system configuration registers */
|
||||
/* 0x0b */
|
||||
#define LVDS_REG_0B 0x0b
|
||||
#define REG_SSC_PCLK_RF BIT(0)
|
||||
#define REG_LVDS_IN_SWAP BIT(1)
|
||||
|
||||
/* LVDS test pattern gen control registers */
|
||||
/* 0x2c */
|
||||
#define LVDS_REG_2C 0x2c
|
||||
#define REG_COL_DEP GENMASK(1, 0)
|
||||
#define BIT8 FIELD_PREP(REG_COL_DEP, 1)
|
||||
#define OUT_MAP BIT(4)
|
||||
#define JEIDA 0
|
||||
#define REG_DESSC_ENB BIT(6)
|
||||
#define DMODE BIT(7)
|
||||
#define DISO BIT(7)
|
||||
#define SISO 0
|
||||
|
||||
#define LVDS_REG_3C 0x3c
|
||||
#define LVDS_REG_3F 0x3f
|
||||
#define LVDS_REG_47 0x47
|
||||
#define LVDS_REG_48 0x48
|
||||
#define LVDS_REG_4F 0x4f
|
||||
#define LVDS_REG_52 0x52
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* HDMI registers are separated into three banks:
|
||||
* 1) HDMI register common bank: 0x00 ~ 0x2f
|
||||
*/
|
||||
|
||||
/* HDMI genernal registers */
|
||||
#define HDMI_REG_SW_RST 0x04
|
||||
#define SOFTREF_RST BIT(5)
|
||||
#define SOFTA_RST BIT(4)
|
||||
#define SOFTV_RST BIT(3)
|
||||
#define AUD_RST BIT(2)
|
||||
#define HDCP_RST BIT(0)
|
||||
#define HDMI_RST_ALL (SOFTREF_RST | SOFTA_RST | SOFTV_RST | \
|
||||
AUD_RST | HDCP_RST)
|
||||
|
||||
#define HDMI_REG_SYS_STATUS 0x0e
|
||||
#define HPDETECT BIT(6)
|
||||
#define TXVIDSTABLE BIT(4)
|
||||
|
||||
#define HDMI_REG_BANK_CTRL 0x0f
|
||||
#define REG_BANK_SEL BIT(0)
|
||||
|
||||
/* HDMI System DDC control registers */
|
||||
#define HDMI_REG_DDC_MASTER_CTRL 0x10
|
||||
#define MASTER_SEL_HOST BIT(0)
|
||||
|
||||
#define HDMI_REG_DDC_HEADER 0x11
|
||||
|
||||
#define HDMI_REG_DDC_REQOFF 0x12
|
||||
#define HDMI_REG_DDC_REQCOUNT 0x13
|
||||
#define HDMI_REG_DDC_EDIDSEG 0x14
|
||||
|
||||
#define HDMI_REG_DDC_CMD 0x15
|
||||
#define DDC_CMD_EDID_READ 0x3
|
||||
#define DDC_CMD_FIFO_CLR 0x9
|
||||
|
||||
#define HDMI_REG_DDC_STATUS 0x16
|
||||
#define DDC_DONE BIT(7)
|
||||
#define DDC_NOACK BIT(5)
|
||||
#define DDC_WAITBUS BIT(4)
|
||||
#define DDC_ARBILOSE BIT(3)
|
||||
#define DDC_ERROR (DDC_NOACK | DDC_WAITBUS | DDC_ARBILOSE)
|
||||
|
||||
#define HDMI_DDC_FIFO_BYTES 32
|
||||
#define HDMI_REG_DDC_READFIFO 0x17
|
||||
#define HDMI_REG_LVDS_PORT 0x1d /* LVDS input control I2C addr */
|
||||
#define HDMI_REG_LVDS_PORT_EN 0x1e
|
||||
#define LVDS_INPUT_CTRL_I2C_ADDR 0x33
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* 2) HDMI register bank0: 0x30 ~ 0xff
|
||||
*/
|
||||
|
||||
/* HDMI AFE registers */
|
||||
#define HDMI_REG_AFE_DRV_CTRL 0x61
|
||||
#define AFE_DRV_PWD BIT(5)
|
||||
#define AFE_DRV_RST BIT(4)
|
||||
|
||||
#define HDMI_REG_AFE_XP_CTRL 0x62
|
||||
#define AFE_XP_GAINBIT BIT(7)
|
||||
#define AFE_XP_ER0 BIT(4)
|
||||
#define AFE_XP_RESETB BIT(3)
|
||||
|
||||
#define HDMI_REG_AFE_ISW_CTRL 0x63
|
||||
|
||||
#define HDMI_REG_AFE_IP_CTRL 0x64
|
||||
#define AFE_IP_GAINBIT BIT(7)
|
||||
#define AFE_IP_ER0 BIT(3)
|
||||
#define AFE_IP_RESETB BIT(2)
|
||||
|
||||
/* HDMI input data format registers */
|
||||
#define HDMI_REG_INPUT_MODE 0x70
|
||||
#define IN_RGB 0x00
|
||||
|
||||
/* HDMI general control registers */
|
||||
#define HDMI_REG_HDMI_MODE 0xc0
|
||||
#define TX_HDMI_MODE BIT(0)
|
||||
|
||||
#define HDMI_REG_GCP 0xc1
|
||||
#define AVMUTE BIT(0)
|
||||
#define HDMI_COLOR_DEPTH GENMASK(6, 4)
|
||||
#define HDMI_COLOR_DEPTH_24 FIELD_PREP(HDMI_COLOR_DEPTH, 4)
|
||||
|
||||
#define HDMI_REG_PKT_GENERAL_CTRL 0xc6
|
||||
#define HDMI_REG_AVI_INFOFRM_CTRL 0xcd
|
||||
#define ENABLE_PKT BIT(0)
|
||||
#define REPEAT_PKT BIT(1)
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* 3) HDMI register bank1: 0x130 ~ 0x1ff (HDMI packet registers)
|
||||
*/
|
||||
|
||||
/* AVI packet registers */
|
||||
#define HDMI_REG_AVI_DB1 0x158
|
||||
#define HDMI_REG_AVI_DB2 0x159
|
||||
#define HDMI_REG_AVI_DB3 0x15a
|
||||
#define HDMI_REG_AVI_DB4 0x15b
|
||||
#define HDMI_REG_AVI_DB5 0x15c
|
||||
#define HDMI_REG_AVI_CSUM 0x15d
|
||||
#define HDMI_REG_AVI_DB6 0x15e
|
||||
#define HDMI_REG_AVI_DB7 0x15f
|
||||
#define HDMI_REG_AVI_DB8 0x160
|
||||
#define HDMI_REG_AVI_DB9 0x161
|
||||
#define HDMI_REG_AVI_DB10 0x162
|
||||
#define HDMI_REG_AVI_DB11 0x163
|
||||
#define HDMI_REG_AVI_DB12 0x164
|
||||
#define HDMI_REG_AVI_DB13 0x165
|
||||
|
||||
#define HDMI_AVI_DB_CHUNK1_SIZE (HDMI_REG_AVI_DB5 - HDMI_REG_AVI_DB1 + 1)
|
||||
#define HDMI_AVI_DB_CHUNK2_SIZE (HDMI_REG_AVI_DB13 - HDMI_REG_AVI_DB6 + 1)
|
||||
|
||||
/* IT6263 data sheet Rev0.8: LVDS RX supports input clock rate up to 150MHz. */
|
||||
#define MAX_PIXEL_CLOCK_KHZ 150000
|
||||
|
||||
/* IT6263 programming guide Ver0.90: PCLK_HIGH for TMDS clock over 80MHz. */
|
||||
#define HIGH_PIXEL_CLOCK_KHZ 80000
|
||||
|
||||
/*
|
||||
* IT6263 data sheet Rev0.8: HDMI TX supports link speeds of up to 2.25Gbps
|
||||
* (link clock rate of 225MHz).
|
||||
*/
|
||||
#define MAX_HDMI_TMDS_CHAR_RATE_HZ 225000000
|
||||
|
||||
struct it6263 {
|
||||
struct device *dev;
|
||||
struct i2c_client *hdmi_i2c;
|
||||
struct i2c_client *lvds_i2c;
|
||||
struct regmap *hdmi_regmap;
|
||||
struct regmap *lvds_regmap;
|
||||
struct drm_bridge bridge;
|
||||
struct drm_bridge *next_bridge;
|
||||
int lvds_data_mapping;
|
||||
bool lvds_dual_link;
|
||||
bool lvds_link12_swap;
|
||||
};
|
||||
|
||||
static inline struct it6263 *bridge_to_it6263(struct drm_bridge *bridge)
|
||||
{
|
||||
return container_of(bridge, struct it6263, bridge);
|
||||
}
|
||||
|
||||
static bool it6263_hdmi_writeable_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case HDMI_REG_SW_RST:
|
||||
case HDMI_REG_BANK_CTRL:
|
||||
case HDMI_REG_DDC_MASTER_CTRL:
|
||||
case HDMI_REG_DDC_HEADER:
|
||||
case HDMI_REG_DDC_REQOFF:
|
||||
case HDMI_REG_DDC_REQCOUNT:
|
||||
case HDMI_REG_DDC_EDIDSEG:
|
||||
case HDMI_REG_DDC_CMD:
|
||||
case HDMI_REG_LVDS_PORT:
|
||||
case HDMI_REG_LVDS_PORT_EN:
|
||||
case HDMI_REG_AFE_DRV_CTRL:
|
||||
case HDMI_REG_AFE_XP_CTRL:
|
||||
case HDMI_REG_AFE_ISW_CTRL:
|
||||
case HDMI_REG_AFE_IP_CTRL:
|
||||
case HDMI_REG_INPUT_MODE:
|
||||
case HDMI_REG_HDMI_MODE:
|
||||
case HDMI_REG_GCP:
|
||||
case HDMI_REG_PKT_GENERAL_CTRL:
|
||||
case HDMI_REG_AVI_INFOFRM_CTRL:
|
||||
case HDMI_REG_AVI_DB1:
|
||||
case HDMI_REG_AVI_DB2:
|
||||
case HDMI_REG_AVI_DB3:
|
||||
case HDMI_REG_AVI_DB4:
|
||||
case HDMI_REG_AVI_DB5:
|
||||
case HDMI_REG_AVI_CSUM:
|
||||
case HDMI_REG_AVI_DB6:
|
||||
case HDMI_REG_AVI_DB7:
|
||||
case HDMI_REG_AVI_DB8:
|
||||
case HDMI_REG_AVI_DB9:
|
||||
case HDMI_REG_AVI_DB10:
|
||||
case HDMI_REG_AVI_DB11:
|
||||
case HDMI_REG_AVI_DB12:
|
||||
case HDMI_REG_AVI_DB13:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool it6263_hdmi_readable_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
if (it6263_hdmi_writeable_reg(dev, reg))
|
||||
return true;
|
||||
|
||||
switch (reg) {
|
||||
case HDMI_REG_SYS_STATUS:
|
||||
case HDMI_REG_DDC_STATUS:
|
||||
case HDMI_REG_DDC_READFIFO:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool it6263_hdmi_volatile_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case HDMI_REG_SW_RST:
|
||||
case HDMI_REG_SYS_STATUS:
|
||||
case HDMI_REG_DDC_STATUS:
|
||||
case HDMI_REG_DDC_READFIFO:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct regmap_range_cfg it6263_hdmi_range_cfg = {
|
||||
.range_min = 0x00,
|
||||
.range_max = HDMI_REG_AVI_DB13,
|
||||
.selector_reg = HDMI_REG_BANK_CTRL,
|
||||
.selector_mask = REG_BANK_SEL,
|
||||
.selector_shift = 0,
|
||||
.window_start = 0x00,
|
||||
.window_len = 0x100,
|
||||
};
|
||||
|
||||
static const struct regmap_config it6263_hdmi_regmap_config = {
|
||||
.name = "it6263-hdmi",
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.writeable_reg = it6263_hdmi_writeable_reg,
|
||||
.readable_reg = it6263_hdmi_readable_reg,
|
||||
.volatile_reg = it6263_hdmi_volatile_reg,
|
||||
.max_register = HDMI_REG_AVI_DB13,
|
||||
.ranges = &it6263_hdmi_range_cfg,
|
||||
.num_ranges = 1,
|
||||
.cache_type = REGCACHE_MAPLE,
|
||||
};
|
||||
|
||||
static bool it6263_lvds_writeable_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case LVDS_REG_05:
|
||||
case LVDS_REG_0B:
|
||||
case LVDS_REG_2C:
|
||||
case LVDS_REG_3C:
|
||||
case LVDS_REG_3F:
|
||||
case LVDS_REG_47:
|
||||
case LVDS_REG_48:
|
||||
case LVDS_REG_4F:
|
||||
case LVDS_REG_52:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool it6263_lvds_readable_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
return it6263_lvds_writeable_reg(dev, reg);
|
||||
}
|
||||
|
||||
static bool it6263_lvds_volatile_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
return reg == LVDS_REG_05;
|
||||
}
|
||||
|
||||
static const struct regmap_config it6263_lvds_regmap_config = {
|
||||
.name = "it6263-lvds",
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.writeable_reg = it6263_lvds_writeable_reg,
|
||||
.readable_reg = it6263_lvds_readable_reg,
|
||||
.volatile_reg = it6263_lvds_volatile_reg,
|
||||
.max_register = LVDS_REG_52,
|
||||
.cache_type = REGCACHE_MAPLE,
|
||||
};
|
||||
|
||||
static const char * const it6263_supplies[] = {
|
||||
"ivdd", "ovdd", "txavcc18", "txavcc33", "pvcc1", "pvcc2",
|
||||
"avcc", "anvdd", "apvdd"
|
||||
};
|
||||
|
||||
static int it6263_parse_dt(struct it6263 *it)
|
||||
{
|
||||
struct device *dev = it->dev;
|
||||
struct device_node *port0, *port1;
|
||||
int ret = 0;
|
||||
|
||||
it->lvds_data_mapping = drm_of_lvds_get_data_mapping(dev->of_node);
|
||||
if (it->lvds_data_mapping < 0) {
|
||||
dev_err(dev, "%pOF: invalid or missing %s DT property: %d\n",
|
||||
dev->of_node, "data-mapping", it->lvds_data_mapping);
|
||||
return it->lvds_data_mapping;
|
||||
}
|
||||
|
||||
it->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 2, 0);
|
||||
if (IS_ERR(it->next_bridge))
|
||||
return dev_err_probe(dev, PTR_ERR(it->next_bridge),
|
||||
"failed to get next bridge\n");
|
||||
|
||||
port0 = of_graph_get_port_by_id(dev->of_node, 0);
|
||||
port1 = of_graph_get_port_by_id(dev->of_node, 1);
|
||||
if (port0 && port1) {
|
||||
int order;
|
||||
|
||||
it->lvds_dual_link = true;
|
||||
order = drm_of_lvds_get_dual_link_pixel_order_sink(port0, port1);
|
||||
if (order < 0) {
|
||||
dev_err(dev,
|
||||
"failed to get dual link pixel order: %d\n",
|
||||
order);
|
||||
ret = order;
|
||||
} else if (order == DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS) {
|
||||
it->lvds_link12_swap = true;
|
||||
}
|
||||
} else if (port1) {
|
||||
ret = -EINVAL;
|
||||
dev_err(dev, "single input LVDS port1 is not supported\n");
|
||||
} else if (!port0) {
|
||||
ret = -EINVAL;
|
||||
dev_err(dev, "no input LVDS port\n");
|
||||
}
|
||||
|
||||
of_node_put(port0);
|
||||
of_node_put(port1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void it6263_hw_reset(struct gpio_desc *reset_gpio)
|
||||
{
|
||||
if (!reset_gpio)
|
||||
return;
|
||||
|
||||
gpiod_set_value_cansleep(reset_gpio, 0);
|
||||
fsleep(1000);
|
||||
gpiod_set_value_cansleep(reset_gpio, 1);
|
||||
/* The chip maker says the low pulse should be at least 40ms. */
|
||||
fsleep(40000);
|
||||
gpiod_set_value_cansleep(reset_gpio, 0);
|
||||
/* addtional time to wait the high voltage to be stable */
|
||||
fsleep(5000);
|
||||
}
|
||||
|
||||
static inline int it6263_lvds_set_i2c_addr(struct it6263 *it)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = regmap_write(it->hdmi_regmap, HDMI_REG_LVDS_PORT,
|
||||
LVDS_INPUT_CTRL_I2C_ADDR << 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return regmap_write(it->hdmi_regmap, HDMI_REG_LVDS_PORT_EN, BIT(0));
|
||||
}
|
||||
|
||||
static inline void it6263_lvds_reset(struct it6263 *it)
|
||||
{
|
||||
/* AFE PLL reset */
|
||||
regmap_write_bits(it->lvds_regmap, LVDS_REG_3C, BIT(0), 0x0);
|
||||
fsleep(1000);
|
||||
regmap_write_bits(it->lvds_regmap, LVDS_REG_3C, BIT(0), BIT(0));
|
||||
|
||||
/* software pixel clock domain reset */
|
||||
regmap_write_bits(it->lvds_regmap, LVDS_REG_05, REG_SOFT_P_RST,
|
||||
REG_SOFT_P_RST);
|
||||
fsleep(1000);
|
||||
regmap_write_bits(it->lvds_regmap, LVDS_REG_05, REG_SOFT_P_RST, 0x0);
|
||||
fsleep(10000);
|
||||
}
|
||||
|
||||
static inline void it6263_lvds_set_interface(struct it6263 *it)
|
||||
{
|
||||
/* color depth */
|
||||
regmap_write_bits(it->lvds_regmap, LVDS_REG_2C, REG_COL_DEP, BIT8);
|
||||
/* output mapping */
|
||||
regmap_write_bits(it->lvds_regmap, LVDS_REG_2C, OUT_MAP, JEIDA);
|
||||
|
||||
if (it->lvds_dual_link) {
|
||||
regmap_write_bits(it->lvds_regmap, LVDS_REG_2C, DMODE, DISO);
|
||||
regmap_write_bits(it->lvds_regmap, LVDS_REG_52, BIT(1), BIT(1));
|
||||
} else {
|
||||
regmap_write_bits(it->lvds_regmap, LVDS_REG_2C, DMODE, SISO);
|
||||
regmap_write_bits(it->lvds_regmap, LVDS_REG_52, BIT(1), 0);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void it6263_lvds_set_afe(struct it6263 *it)
|
||||
{
|
||||
regmap_write(it->lvds_regmap, LVDS_REG_3C, 0xaa);
|
||||
regmap_write(it->lvds_regmap, LVDS_REG_3F, 0x02);
|
||||
regmap_write(it->lvds_regmap, LVDS_REG_47, 0xaa);
|
||||
regmap_write(it->lvds_regmap, LVDS_REG_48, 0x02);
|
||||
regmap_write(it->lvds_regmap, LVDS_REG_4F, 0x11);
|
||||
|
||||
regmap_write_bits(it->lvds_regmap, LVDS_REG_0B, REG_SSC_PCLK_RF,
|
||||
REG_SSC_PCLK_RF);
|
||||
regmap_write_bits(it->lvds_regmap, LVDS_REG_3C, 0x07, 0);
|
||||
regmap_write_bits(it->lvds_regmap, LVDS_REG_2C, REG_DESSC_ENB,
|
||||
REG_DESSC_ENB);
|
||||
}
|
||||
|
||||
static inline void it6263_lvds_sys_cfg(struct it6263 *it)
|
||||
{
|
||||
regmap_write_bits(it->lvds_regmap, LVDS_REG_0B, REG_LVDS_IN_SWAP,
|
||||
it->lvds_link12_swap ? REG_LVDS_IN_SWAP : 0);
|
||||
}
|
||||
|
||||
static inline void it6263_lvds_config(struct it6263 *it)
|
||||
{
|
||||
it6263_lvds_reset(it);
|
||||
it6263_lvds_set_interface(it);
|
||||
it6263_lvds_set_afe(it);
|
||||
it6263_lvds_sys_cfg(it);
|
||||
}
|
||||
|
||||
static inline void it6263_hdmi_config(struct it6263 *it)
|
||||
{
|
||||
regmap_write(it->hdmi_regmap, HDMI_REG_SW_RST, HDMI_RST_ALL);
|
||||
regmap_write(it->hdmi_regmap, HDMI_REG_INPUT_MODE, IN_RGB);
|
||||
regmap_write_bits(it->hdmi_regmap, HDMI_REG_GCP, HDMI_COLOR_DEPTH,
|
||||
HDMI_COLOR_DEPTH_24);
|
||||
}
|
||||
|
||||
static enum drm_connector_status it6263_detect(struct it6263 *it)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
regmap_read(it->hdmi_regmap, HDMI_REG_SYS_STATUS, &val);
|
||||
if (val & HPDETECT)
|
||||
return connector_status_connected;
|
||||
else
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
static int it6263_read_edid(void *data, u8 *buf, unsigned int block, size_t len)
|
||||
{
|
||||
struct it6263 *it = data;
|
||||
struct regmap *regmap = it->hdmi_regmap;
|
||||
unsigned int start = (block % 2) * EDID_LENGTH;
|
||||
unsigned int segment = block >> 1;
|
||||
unsigned int count, val;
|
||||
int ret;
|
||||
|
||||
regmap_write(regmap, HDMI_REG_DDC_MASTER_CTRL, MASTER_SEL_HOST);
|
||||
regmap_write(regmap, HDMI_REG_DDC_HEADER, DDC_ADDR << 1);
|
||||
regmap_write(regmap, HDMI_REG_DDC_EDIDSEG, segment);
|
||||
|
||||
while (len) {
|
||||
/* clear DDC FIFO */
|
||||
regmap_write(regmap, HDMI_REG_DDC_CMD, DDC_CMD_FIFO_CLR);
|
||||
|
||||
ret = regmap_read_poll_timeout(regmap, HDMI_REG_DDC_STATUS,
|
||||
val, val & DDC_DONE,
|
||||
2000, 10000);
|
||||
if (ret) {
|
||||
dev_err(it->dev, "failed to clear DDC FIFO:%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
count = len > HDMI_DDC_FIFO_BYTES ? HDMI_DDC_FIFO_BYTES : len;
|
||||
|
||||
/* fire the read command */
|
||||
regmap_write(regmap, HDMI_REG_DDC_REQOFF, start);
|
||||
regmap_write(regmap, HDMI_REG_DDC_REQCOUNT, count);
|
||||
regmap_write(regmap, HDMI_REG_DDC_CMD, DDC_CMD_EDID_READ);
|
||||
|
||||
start += count;
|
||||
len -= count;
|
||||
|
||||
ret = regmap_read_poll_timeout(regmap, HDMI_REG_DDC_STATUS, val,
|
||||
val & (DDC_DONE | DDC_ERROR),
|
||||
20000, 250000);
|
||||
if (ret && !(val & DDC_ERROR)) {
|
||||
dev_err(it->dev, "failed to read EDID:%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (val & DDC_ERROR) {
|
||||
dev_err(it->dev, "DDC error\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* cache to buffer */
|
||||
for (; count > 0; count--) {
|
||||
regmap_read(regmap, HDMI_REG_DDC_READFIFO, &val);
|
||||
*(buf++) = val;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int it6263_bridge_atomic_check(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *bridge_state,
|
||||
struct drm_crtc_state *crtc_state,
|
||||
struct drm_connector_state *conn_state)
|
||||
{
|
||||
return drm_atomic_helper_connector_hdmi_check(conn_state->connector,
|
||||
conn_state->state);
|
||||
}
|
||||
|
||||
static void
|
||||
it6263_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
{
|
||||
struct it6263 *it = bridge_to_it6263(bridge);
|
||||
|
||||
regmap_write_bits(it->hdmi_regmap, HDMI_REG_GCP, AVMUTE, AVMUTE);
|
||||
regmap_write(it->hdmi_regmap, HDMI_REG_PKT_GENERAL_CTRL, 0);
|
||||
regmap_write(it->hdmi_regmap, HDMI_REG_AFE_DRV_CTRL,
|
||||
AFE_DRV_RST | AFE_DRV_PWD);
|
||||
}
|
||||
|
||||
static void
|
||||
it6263_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
{
|
||||
struct drm_atomic_state *state = old_bridge_state->base.state;
|
||||
struct it6263 *it = bridge_to_it6263(bridge);
|
||||
const struct drm_crtc_state *crtc_state;
|
||||
struct regmap *regmap = it->hdmi_regmap;
|
||||
const struct drm_display_mode *mode;
|
||||
struct drm_connector *connector;
|
||||
bool is_stable = false;
|
||||
struct drm_crtc *crtc;
|
||||
unsigned int val;
|
||||
bool pclk_high;
|
||||
int i, ret;
|
||||
|
||||
connector = drm_atomic_get_new_connector_for_encoder(state,
|
||||
bridge->encoder);
|
||||
crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;
|
||||
crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
|
||||
mode = &crtc_state->adjusted_mode;
|
||||
|
||||
regmap_write(regmap, HDMI_REG_HDMI_MODE, TX_HDMI_MODE);
|
||||
|
||||
drm_atomic_helper_connector_hdmi_update_infoframes(connector, state);
|
||||
|
||||
/* HDMI AFE setup */
|
||||
pclk_high = mode->clock > HIGH_PIXEL_CLOCK_KHZ;
|
||||
regmap_write(regmap, HDMI_REG_AFE_DRV_CTRL, AFE_DRV_RST);
|
||||
if (pclk_high)
|
||||
regmap_write(regmap, HDMI_REG_AFE_XP_CTRL,
|
||||
AFE_XP_GAINBIT | AFE_XP_RESETB);
|
||||
else
|
||||
regmap_write(regmap, HDMI_REG_AFE_XP_CTRL,
|
||||
AFE_XP_ER0 | AFE_XP_RESETB);
|
||||
regmap_write(regmap, HDMI_REG_AFE_ISW_CTRL, 0x10);
|
||||
if (pclk_high)
|
||||
regmap_write(regmap, HDMI_REG_AFE_IP_CTRL,
|
||||
AFE_IP_GAINBIT | AFE_IP_RESETB);
|
||||
else
|
||||
regmap_write(regmap, HDMI_REG_AFE_IP_CTRL,
|
||||
AFE_IP_ER0 | AFE_IP_RESETB);
|
||||
|
||||
/* HDMI software video reset */
|
||||
regmap_write_bits(regmap, HDMI_REG_SW_RST, SOFTV_RST, SOFTV_RST);
|
||||
fsleep(1000);
|
||||
regmap_write_bits(regmap, HDMI_REG_SW_RST, SOFTV_RST, 0);
|
||||
|
||||
/* reconfigure LVDS and retry several times in case video is instable */
|
||||
for (i = 0; i < 3; i++) {
|
||||
ret = regmap_read_poll_timeout(regmap, HDMI_REG_SYS_STATUS, val,
|
||||
val & TXVIDSTABLE,
|
||||
20000, 500000);
|
||||
if (!ret) {
|
||||
is_stable = true;
|
||||
break;
|
||||
}
|
||||
|
||||
it6263_lvds_config(it);
|
||||
}
|
||||
|
||||
if (!is_stable)
|
||||
dev_warn(it->dev, "failed to wait for video stable\n");
|
||||
|
||||
/* HDMI AFE reset release and power up */
|
||||
regmap_write(regmap, HDMI_REG_AFE_DRV_CTRL, 0);
|
||||
|
||||
regmap_write_bits(regmap, HDMI_REG_GCP, AVMUTE, 0);
|
||||
|
||||
regmap_write(regmap, HDMI_REG_PKT_GENERAL_CTRL, ENABLE_PKT | REPEAT_PKT);
|
||||
}
|
||||
|
||||
static enum drm_mode_status
|
||||
it6263_bridge_mode_valid(struct drm_bridge *bridge,
|
||||
const struct drm_display_info *info,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
unsigned long long rate;
|
||||
|
||||
rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB);
|
||||
if (rate == 0)
|
||||
return MODE_NOCLOCK;
|
||||
|
||||
return bridge->funcs->hdmi_tmds_char_rate_valid(bridge, mode, rate);
|
||||
}
|
||||
|
||||
static int it6263_bridge_attach(struct drm_bridge *bridge,
|
||||
enum drm_bridge_attach_flags flags)
|
||||
{
|
||||
struct it6263 *it = bridge_to_it6263(bridge);
|
||||
struct drm_connector *connector;
|
||||
int ret;
|
||||
|
||||
ret = drm_bridge_attach(bridge->encoder, it->next_bridge, bridge,
|
||||
flags | DRM_BRIDGE_ATTACH_NO_CONNECTOR);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
|
||||
return 0;
|
||||
|
||||
connector = drm_bridge_connector_init(bridge->dev, bridge->encoder);
|
||||
if (IS_ERR(connector)) {
|
||||
ret = PTR_ERR(connector);
|
||||
dev_err(it->dev, "failed to initialize bridge connector: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
drm_connector_attach_encoder(connector, bridge->encoder);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum drm_connector_status it6263_bridge_detect(struct drm_bridge *bridge)
|
||||
{
|
||||
struct it6263 *it = bridge_to_it6263(bridge);
|
||||
|
||||
return it6263_detect(it);
|
||||
}
|
||||
|
||||
static const struct drm_edid *
|
||||
it6263_bridge_edid_read(struct drm_bridge *bridge,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct it6263 *it = bridge_to_it6263(bridge);
|
||||
|
||||
return drm_edid_read_custom(connector, it6263_read_edid, it);
|
||||
}
|
||||
|
||||
static u32 *
|
||||
it6263_bridge_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)
|
||||
{
|
||||
struct it6263 *it = bridge_to_it6263(bridge);
|
||||
u32 *input_fmts;
|
||||
|
||||
*num_input_fmts = 0;
|
||||
|
||||
if (it->lvds_data_mapping != MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA)
|
||||
return NULL;
|
||||
|
||||
input_fmts = kmalloc(sizeof(*input_fmts), GFP_KERNEL);
|
||||
if (!input_fmts)
|
||||
return NULL;
|
||||
|
||||
input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA;
|
||||
*num_input_fmts = 1;
|
||||
|
||||
return input_fmts;
|
||||
}
|
||||
|
||||
static enum drm_mode_status
|
||||
it6263_hdmi_tmds_char_rate_valid(const struct drm_bridge *bridge,
|
||||
const struct drm_display_mode *mode,
|
||||
unsigned long long tmds_rate)
|
||||
{
|
||||
if (mode->clock > MAX_PIXEL_CLOCK_KHZ)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
if (tmds_rate > MAX_HDMI_TMDS_CHAR_RATE_HZ)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static int it6263_hdmi_clear_infoframe(struct drm_bridge *bridge,
|
||||
enum hdmi_infoframe_type type)
|
||||
{
|
||||
struct it6263 *it = bridge_to_it6263(bridge);
|
||||
|
||||
if (type == HDMI_INFOFRAME_TYPE_AVI)
|
||||
regmap_write(it->hdmi_regmap, HDMI_REG_AVI_INFOFRM_CTRL, 0);
|
||||
else
|
||||
dev_dbg(it->dev, "unsupported HDMI infoframe 0x%x\n", type);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int it6263_hdmi_write_infoframe(struct drm_bridge *bridge,
|
||||
enum hdmi_infoframe_type type,
|
||||
const u8 *buffer, size_t len)
|
||||
{
|
||||
struct it6263 *it = bridge_to_it6263(bridge);
|
||||
struct regmap *regmap = it->hdmi_regmap;
|
||||
|
||||
if (type != HDMI_INFOFRAME_TYPE_AVI) {
|
||||
dev_dbg(it->dev, "unsupported HDMI infoframe 0x%x\n", type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* write the first AVI infoframe data byte chunk(DB1-DB5) */
|
||||
regmap_bulk_write(regmap, HDMI_REG_AVI_DB1,
|
||||
&buffer[HDMI_INFOFRAME_HEADER_SIZE],
|
||||
HDMI_AVI_DB_CHUNK1_SIZE);
|
||||
|
||||
/* write the second AVI infoframe data byte chunk(DB6-DB13) */
|
||||
regmap_bulk_write(regmap, HDMI_REG_AVI_DB6,
|
||||
&buffer[HDMI_INFOFRAME_HEADER_SIZE +
|
||||
HDMI_AVI_DB_CHUNK1_SIZE],
|
||||
HDMI_AVI_DB_CHUNK2_SIZE);
|
||||
|
||||
/* write checksum */
|
||||
regmap_write(regmap, HDMI_REG_AVI_CSUM, buffer[3]);
|
||||
|
||||
regmap_write(regmap, HDMI_REG_AVI_INFOFRM_CTRL, ENABLE_PKT | REPEAT_PKT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_bridge_funcs it6263_bridge_funcs = {
|
||||
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
|
||||
.atomic_reset = drm_atomic_helper_bridge_reset,
|
||||
.attach = it6263_bridge_attach,
|
||||
.mode_valid = it6263_bridge_mode_valid,
|
||||
.atomic_disable = it6263_bridge_atomic_disable,
|
||||
.atomic_enable = it6263_bridge_atomic_enable,
|
||||
.atomic_check = it6263_bridge_atomic_check,
|
||||
.detect = it6263_bridge_detect,
|
||||
.edid_read = it6263_bridge_edid_read,
|
||||
.atomic_get_input_bus_fmts = it6263_bridge_atomic_get_input_bus_fmts,
|
||||
.hdmi_tmds_char_rate_valid = it6263_hdmi_tmds_char_rate_valid,
|
||||
.hdmi_clear_infoframe = it6263_hdmi_clear_infoframe,
|
||||
.hdmi_write_infoframe = it6263_hdmi_write_infoframe,
|
||||
};
|
||||
|
||||
static int it6263_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct gpio_desc *reset_gpio;
|
||||
struct it6263 *it;
|
||||
int ret;
|
||||
|
||||
it = devm_kzalloc(dev, sizeof(*it), GFP_KERNEL);
|
||||
if (!it)
|
||||
return -ENOMEM;
|
||||
|
||||
it->dev = dev;
|
||||
it->hdmi_i2c = client;
|
||||
|
||||
it->hdmi_regmap = devm_regmap_init_i2c(client,
|
||||
&it6263_hdmi_regmap_config);
|
||||
if (IS_ERR(it->hdmi_regmap))
|
||||
return dev_err_probe(dev, PTR_ERR(it->hdmi_regmap),
|
||||
"failed to init I2C regmap for HDMI\n");
|
||||
|
||||
reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(reset_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(reset_gpio),
|
||||
"failed to get reset gpio\n");
|
||||
|
||||
ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(it6263_supplies),
|
||||
it6263_supplies);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "failed to get power supplies\n");
|
||||
|
||||
ret = it6263_parse_dt(it);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
it6263_hw_reset(reset_gpio);
|
||||
|
||||
ret = it6263_lvds_set_i2c_addr(it);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "failed to set I2C addr\n");
|
||||
|
||||
it->lvds_i2c = devm_i2c_new_dummy_device(dev, client->adapter,
|
||||
LVDS_INPUT_CTRL_I2C_ADDR);
|
||||
if (IS_ERR(it->lvds_i2c))
|
||||
dev_err_probe(it->dev, PTR_ERR(it->lvds_i2c),
|
||||
"failed to allocate I2C device for LVDS\n");
|
||||
|
||||
it->lvds_regmap = devm_regmap_init_i2c(it->lvds_i2c,
|
||||
&it6263_lvds_regmap_config);
|
||||
if (IS_ERR(it->lvds_regmap))
|
||||
return dev_err_probe(dev, PTR_ERR(it->lvds_regmap),
|
||||
"failed to init I2C regmap for LVDS\n");
|
||||
|
||||
it6263_lvds_config(it);
|
||||
it6263_hdmi_config(it);
|
||||
|
||||
i2c_set_clientdata(client, it);
|
||||
|
||||
it->bridge.funcs = &it6263_bridge_funcs;
|
||||
it->bridge.of_node = dev->of_node;
|
||||
/* IT6263 chip doesn't support HPD interrupt. */
|
||||
it->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID |
|
||||
DRM_BRIDGE_OP_HDMI;
|
||||
it->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
|
||||
it->bridge.vendor = "ITE";
|
||||
it->bridge.product = "IT6263";
|
||||
|
||||
return devm_drm_bridge_add(dev, &it->bridge);
|
||||
}
|
||||
|
||||
static const struct of_device_id it6263_of_match[] = {
|
||||
{ .compatible = "ite,it6263", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, it6263_of_match);
|
||||
|
||||
static const struct i2c_device_id it6263_i2c_ids[] = {
|
||||
{ "it6263", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, it6263_i2c_ids);
|
||||
|
||||
static struct i2c_driver it6263_driver = {
|
||||
.probe = it6263_probe,
|
||||
.driver = {
|
||||
.name = "it6263",
|
||||
.of_match_table = it6263_of_match,
|
||||
},
|
||||
.id_table = it6263_i2c_ids,
|
||||
};
|
||||
module_i2c_driver(it6263_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ITE Tech. Inc. IT6263 LVDS/HDMI bridge");
|
||||
MODULE_AUTHOR("Liu Ying <victor.liu@nxp.com>");
|
||||
MODULE_LICENSE("GPL");
|
@ -2614,9 +2614,9 @@ static int it6505_poweron(struct it6505 *it6505)
|
||||
/* time interval between OVDD and SYSRSTN at least be 10ms */
|
||||
if (pdata->gpiod_reset) {
|
||||
usleep_range(10000, 20000);
|
||||
gpiod_set_value_cansleep(pdata->gpiod_reset, 0);
|
||||
usleep_range(1000, 2000);
|
||||
gpiod_set_value_cansleep(pdata->gpiod_reset, 1);
|
||||
usleep_range(1000, 2000);
|
||||
gpiod_set_value_cansleep(pdata->gpiod_reset, 0);
|
||||
usleep_range(25000, 35000);
|
||||
}
|
||||
|
||||
@ -2647,7 +2647,7 @@ static int it6505_poweroff(struct it6505 *it6505)
|
||||
disable_irq_nosync(it6505->irq);
|
||||
|
||||
if (pdata->gpiod_reset)
|
||||
gpiod_set_value_cansleep(pdata->gpiod_reset, 0);
|
||||
gpiod_set_value_cansleep(pdata->gpiod_reset, 1);
|
||||
|
||||
if (pdata->pwr18) {
|
||||
err = regulator_disable(pdata->pwr18);
|
||||
@ -3135,7 +3135,7 @@ static int it6505_init_pdata(struct it6505 *it6505)
|
||||
return PTR_ERR(pdata->ovdd);
|
||||
}
|
||||
|
||||
pdata->gpiod_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
|
||||
pdata->gpiod_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(pdata->gpiod_reset)) {
|
||||
dev_err(dev, "gpiod_reset gpio not found");
|
||||
return PTR_ERR(pdata->gpiod_reset);
|
||||
|
@ -1,17 +0,0 @@
|
||||
git+https://gitlab.freedesktop.org/gfx-ci/ci-collate@09e7142715c16f54344ddf97013331ba063b162b
|
||||
termcolor==2.3.0
|
||||
|
||||
# ci-collate dependencies
|
||||
certifi==2023.7.22
|
||||
charset-normalizer==3.2.0
|
||||
idna==3.4
|
||||
pip==23.3
|
||||
python-gitlab==3.15.0
|
||||
requests==2.31.0
|
||||
requests-toolbelt==1.0.0
|
||||
ruamel.yaml==0.17.32
|
||||
ruamel.yaml.clib==0.2.7
|
||||
setuptools==70.0.0
|
||||
tenacity==8.2.3
|
||||
urllib3==2.0.7
|
||||
wheel==0.41.1
|
@ -1,204 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
from collections import defaultdict
|
||||
import difflib
|
||||
import os
|
||||
import re
|
||||
from glcollate import Collate
|
||||
from termcolor import colored
|
||||
from urllib.parse import urlparse
|
||||
|
||||
|
||||
def get_canonical_name(job_name):
|
||||
return re.split(r" \d+/\d+", job_name)[0]
|
||||
|
||||
|
||||
def get_xfails_file_path(job_name, suffix):
|
||||
canonical_name = get_canonical_name(job_name)
|
||||
name = canonical_name.replace(":", "-")
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
return os.path.join(script_dir, f"{name}-{suffix}.txt")
|
||||
|
||||
|
||||
def get_unit_test_name_and_results(unit_test):
|
||||
if "Artifact results/failures.csv not found" in unit_test or '' == unit_test:
|
||||
return None, None
|
||||
unit_test_name, unit_test_result = unit_test.strip().split(",")
|
||||
return unit_test_name, unit_test_result
|
||||
|
||||
|
||||
def read_file(file_path):
|
||||
try:
|
||||
with open(file_path, "r") as file:
|
||||
f = file.readlines()
|
||||
if len(f):
|
||||
f[-1] = f[-1].strip() + "\n"
|
||||
return f
|
||||
except FileNotFoundError:
|
||||
return []
|
||||
|
||||
|
||||
def save_file(content, file_path):
|
||||
# delete file is content is empty
|
||||
if not content or not any(content):
|
||||
if os.path.exists(file_path):
|
||||
os.remove(file_path)
|
||||
return
|
||||
|
||||
with open(file_path, "w") as file:
|
||||
file.writelines(content)
|
||||
|
||||
|
||||
def is_test_present_on_file(file_content, unit_test_name):
|
||||
return any(unit_test_name in line for line in file_content)
|
||||
|
||||
|
||||
def is_unit_test_present_in_other_jobs(unit_test, job_ids):
|
||||
return all(unit_test in job_ids[job_id] for job_id in job_ids)
|
||||
|
||||
|
||||
def remove_unit_test_if_present(lines, unit_test_name):
|
||||
if not is_test_present_on_file(lines, unit_test_name):
|
||||
return
|
||||
lines[:] = [line for line in lines if unit_test_name not in line]
|
||||
|
||||
|
||||
def add_unit_test_if_not_present(lines, unit_test_name, file_name):
|
||||
# core_getversion is mandatory
|
||||
if "core_getversion" in unit_test_name:
|
||||
print("WARNING: core_getversion should pass, not adding it to", os.path.basename(file_name))
|
||||
elif all(unit_test_name not in line for line in lines):
|
||||
lines.append(unit_test_name + "\n")
|
||||
|
||||
|
||||
def update_unit_test_result_in_fails_txt(fails_txt, unit_test):
|
||||
unit_test_name, unit_test_result = get_unit_test_name_and_results(unit_test)
|
||||
for i, line in enumerate(fails_txt):
|
||||
if unit_test_name in line:
|
||||
_, current_result = get_unit_test_name_and_results(line)
|
||||
fails_txt[i] = unit_test + "\n"
|
||||
return
|
||||
|
||||
|
||||
def add_unit_test_or_update_result_to_fails_if_present(fails_txt, unit_test, fails_txt_path):
|
||||
unit_test_name, _ = get_unit_test_name_and_results(unit_test)
|
||||
if not is_test_present_on_file(fails_txt, unit_test_name):
|
||||
add_unit_test_if_not_present(fails_txt, unit_test, fails_txt_path)
|
||||
# if it is present but not with the same result
|
||||
elif not is_test_present_on_file(fails_txt, unit_test):
|
||||
update_unit_test_result_in_fails_txt(fails_txt, unit_test)
|
||||
|
||||
|
||||
def split_unit_test_from_collate(xfails):
|
||||
for job_name in xfails.keys():
|
||||
for job_id in xfails[job_name].copy().keys():
|
||||
if "not found" in xfails[job_name][job_id].content_as_str:
|
||||
del xfails[job_name][job_id]
|
||||
continue
|
||||
xfails[job_name][job_id] = xfails[job_name][job_id].content_as_str.splitlines()
|
||||
|
||||
|
||||
def get_xfails_from_pipeline_url(pipeline_url):
|
||||
parsed_url = urlparse(pipeline_url)
|
||||
path_components = parsed_url.path.strip("/").split("/")
|
||||
|
||||
namespace = path_components[0]
|
||||
project = path_components[1]
|
||||
pipeline_id = path_components[-1]
|
||||
|
||||
print("Collating from:", namespace, project, pipeline_id)
|
||||
xfails = (
|
||||
Collate(namespace=namespace, project=project)
|
||||
.from_pipeline(pipeline_id)
|
||||
.get_artifact("results/failures.csv")
|
||||
)
|
||||
|
||||
split_unit_test_from_collate(xfails)
|
||||
return xfails
|
||||
|
||||
|
||||
def get_xfails_from_pipeline_urls(pipelines_urls):
|
||||
xfails = defaultdict(dict)
|
||||
|
||||
for url in pipelines_urls:
|
||||
new_xfails = get_xfails_from_pipeline_url(url)
|
||||
for key in new_xfails:
|
||||
xfails[key].update(new_xfails[key])
|
||||
|
||||
return xfails
|
||||
|
||||
|
||||
def print_diff(old_content, new_content, file_name):
|
||||
diff = difflib.unified_diff(old_content, new_content, lineterm="", fromfile=file_name, tofile=file_name)
|
||||
diff = [colored(line, "green") if line.startswith("+") else
|
||||
colored(line, "red") if line.startswith("-") else line for line in diff]
|
||||
print("\n".join(diff[:3]))
|
||||
print("".join(diff[3:]))
|
||||
|
||||
|
||||
def main(pipelines_urls, only_flakes):
|
||||
xfails = get_xfails_from_pipeline_urls(pipelines_urls)
|
||||
|
||||
for job_name in xfails.keys():
|
||||
fails_txt_path = get_xfails_file_path(job_name, "fails")
|
||||
flakes_txt_path = get_xfails_file_path(job_name, "flakes")
|
||||
|
||||
fails_txt = read_file(fails_txt_path)
|
||||
flakes_txt = read_file(flakes_txt_path)
|
||||
|
||||
fails_txt_original = fails_txt.copy()
|
||||
flakes_txt_original = flakes_txt.copy()
|
||||
|
||||
for job_id in xfails[job_name].keys():
|
||||
for unit_test in xfails[job_name][job_id]:
|
||||
unit_test_name, unit_test_result = get_unit_test_name_and_results(unit_test)
|
||||
|
||||
if not unit_test_name:
|
||||
continue
|
||||
|
||||
if only_flakes:
|
||||
remove_unit_test_if_present(fails_txt, unit_test_name)
|
||||
add_unit_test_if_not_present(flakes_txt, unit_test_name, flakes_txt_path)
|
||||
continue
|
||||
|
||||
# drop it from flakes if it is present to analyze it again
|
||||
remove_unit_test_if_present(flakes_txt, unit_test_name)
|
||||
|
||||
if unit_test_result == "UnexpectedPass":
|
||||
remove_unit_test_if_present(fails_txt, unit_test_name)
|
||||
# flake result
|
||||
if not is_unit_test_present_in_other_jobs(unit_test, xfails[job_name]):
|
||||
add_unit_test_if_not_present(flakes_txt, unit_test_name, flakes_txt_path)
|
||||
continue
|
||||
|
||||
# flake result
|
||||
if not is_unit_test_present_in_other_jobs(unit_test, xfails[job_name]):
|
||||
remove_unit_test_if_present(fails_txt, unit_test_name)
|
||||
add_unit_test_if_not_present(flakes_txt, unit_test_name, flakes_txt_path)
|
||||
continue
|
||||
|
||||
# consistent result
|
||||
add_unit_test_or_update_result_to_fails_if_present(fails_txt, unit_test,
|
||||
fails_txt_path)
|
||||
|
||||
fails_txt.sort()
|
||||
flakes_txt.sort()
|
||||
|
||||
if fails_txt != fails_txt_original:
|
||||
save_file(fails_txt, fails_txt_path)
|
||||
print_diff(fails_txt_original, fails_txt, os.path.basename(fails_txt_path))
|
||||
if flakes_txt != flakes_txt_original:
|
||||
save_file(flakes_txt, flakes_txt_path)
|
||||
print_diff(flakes_txt_original, flakes_txt, os.path.basename(flakes_txt_path))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Update xfails from a given pipeline.")
|
||||
parser.add_argument("pipeline_urls", nargs="+", type=str, help="URLs to the pipelines to analyze the failures.")
|
||||
parser.add_argument("--only-flakes", action="store_true", help="Treat every detected failure as a flake, edit *-flakes.txt only.")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
main(args.pipeline_urls, args.only_flakes)
|
||||
print("Done.")
|
@ -129,7 +129,7 @@ bool drm_dev_needs_global_mutex(struct drm_device *dev)
|
||||
*/
|
||||
struct drm_file *drm_file_alloc(struct drm_minor *minor)
|
||||
{
|
||||
static atomic64_t ident = ATOMIC_INIT(0);
|
||||
static atomic64_t ident = ATOMIC64_INIT(0);
|
||||
struct drm_device *dev = minor->dev;
|
||||
struct drm_file *file;
|
||||
int ret;
|
||||
|
@ -341,8 +341,23 @@ static int drm_of_lvds_get_remote_pixels_type(
|
||||
return pixels_type;
|
||||
}
|
||||
|
||||
static int __drm_of_lvds_get_dual_link_pixel_order(int p1_pt, int p2_pt)
|
||||
{
|
||||
/*
|
||||
* A valid dual-lVDS bus is found when one port is marked with
|
||||
* "dual-lvds-even-pixels", and the other port is marked with
|
||||
* "dual-lvds-odd-pixels", bail out if the markers are not right.
|
||||
*/
|
||||
if (p1_pt + p2_pt != DRM_OF_LVDS_EVEN + DRM_OF_LVDS_ODD)
|
||||
return -EINVAL;
|
||||
|
||||
return p1_pt == DRM_OF_LVDS_EVEN ?
|
||||
DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS :
|
||||
DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_of_lvds_get_dual_link_pixel_order - Get LVDS dual-link pixel order
|
||||
* drm_of_lvds_get_dual_link_pixel_order - Get LVDS dual-link source pixel order
|
||||
* @port1: First DT port node of the Dual-link LVDS source
|
||||
* @port2: Second DT port node of the Dual-link LVDS source
|
||||
*
|
||||
@ -387,20 +402,59 @@ int drm_of_lvds_get_dual_link_pixel_order(const struct device_node *port1,
|
||||
if (remote_p2_pt < 0)
|
||||
return remote_p2_pt;
|
||||
|
||||
/*
|
||||
* A valid dual-lVDS bus is found when one remote port is marked with
|
||||
* "dual-lvds-even-pixels", and the other remote port is marked with
|
||||
* "dual-lvds-odd-pixels", bail out if the markers are not right.
|
||||
*/
|
||||
if (remote_p1_pt + remote_p2_pt != DRM_OF_LVDS_EVEN + DRM_OF_LVDS_ODD)
|
||||
return -EINVAL;
|
||||
|
||||
return remote_p1_pt == DRM_OF_LVDS_EVEN ?
|
||||
DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS :
|
||||
DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS;
|
||||
return __drm_of_lvds_get_dual_link_pixel_order(remote_p1_pt, remote_p2_pt);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_of_lvds_get_dual_link_pixel_order);
|
||||
|
||||
/**
|
||||
* drm_of_lvds_get_dual_link_pixel_order_sink - Get LVDS dual-link sink pixel order
|
||||
* @port1: First DT port node of the Dual-link LVDS sink
|
||||
* @port2: Second DT port node of the Dual-link LVDS sink
|
||||
*
|
||||
* An LVDS dual-link connection is made of two links, with even pixels
|
||||
* transitting on one link, and odd pixels on the other link. This function
|
||||
* returns, for two ports of an LVDS dual-link sink, which port shall transmit
|
||||
* the even and odd pixels, based on the requirements of the sink.
|
||||
*
|
||||
* The pixel order is determined from the dual-lvds-even-pixels and
|
||||
* dual-lvds-odd-pixels properties in the sink's DT port nodes. If those
|
||||
* properties are not present, or if their usage is not valid, this function
|
||||
* returns -EINVAL.
|
||||
*
|
||||
* If either port is not connected, this function returns -EPIPE.
|
||||
*
|
||||
* @port1 and @port2 are typically DT sibling nodes, but may have different
|
||||
* parents when, for instance, two separate LVDS decoders receive the even and
|
||||
* odd pixels.
|
||||
*
|
||||
* Return:
|
||||
* * DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS - @port1 receives even pixels and @port2
|
||||
* receives odd pixels
|
||||
* * DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS - @port1 receives odd pixels and @port2
|
||||
* receives even pixels
|
||||
* * -EINVAL - @port1 or @port2 are NULL
|
||||
* * -EPIPE - when @port1 or @port2 are not connected
|
||||
*/
|
||||
int drm_of_lvds_get_dual_link_pixel_order_sink(struct device_node *port1,
|
||||
struct device_node *port2)
|
||||
{
|
||||
int sink_p1_pt, sink_p2_pt;
|
||||
|
||||
if (!port1 || !port2)
|
||||
return -EINVAL;
|
||||
|
||||
sink_p1_pt = drm_of_lvds_get_port_pixels_type(port1);
|
||||
if (!sink_p1_pt)
|
||||
return -EPIPE;
|
||||
|
||||
sink_p2_pt = drm_of_lvds_get_port_pixels_type(port2);
|
||||
if (!sink_p2_pt)
|
||||
return -EPIPE;
|
||||
|
||||
return __drm_of_lvds_get_dual_link_pixel_order(sink_p1_pt, sink_p2_pt);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_of_lvds_get_dual_link_pixel_order_sink);
|
||||
|
||||
/**
|
||||
* drm_of_lvds_get_data_mapping - Get LVDS data mapping
|
||||
* @port: DT port node of the LVDS source or sink
|
||||
@ -410,7 +464,9 @@ EXPORT_SYMBOL_GPL(drm_of_lvds_get_dual_link_pixel_order);
|
||||
* Return:
|
||||
* * MEDIA_BUS_FMT_RGB666_1X7X3_SPWG - data-mapping is "jeida-18"
|
||||
* * MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA - data-mapping is "jeida-24"
|
||||
* * MEDIA_BUS_FMT_RGB101010_1X7X5_JEIDA - data-mapping is "jeida-30"
|
||||
* * MEDIA_BUS_FMT_RGB888_1X7X4_SPWG - data-mapping is "vesa-24"
|
||||
* * MEDIA_BUS_FMT_RGB101010_1X7X5_SPWG - data-mapping is "vesa-30"
|
||||
* * -EINVAL - the "data-mapping" property is unsupported
|
||||
* * -ENODEV - the "data-mapping" property is missing
|
||||
*/
|
||||
@ -427,8 +483,12 @@ int drm_of_lvds_get_data_mapping(const struct device_node *port)
|
||||
return MEDIA_BUS_FMT_RGB666_1X7X3_SPWG;
|
||||
if (!strcmp(mapping, "jeida-24"))
|
||||
return MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA;
|
||||
if (!strcmp(mapping, "jeida-30"))
|
||||
return MEDIA_BUS_FMT_RGB101010_1X7X5_JEIDA;
|
||||
if (!strcmp(mapping, "vesa-24"))
|
||||
return MEDIA_BUS_FMT_RGB888_1X7X4_SPWG;
|
||||
if (!strcmp(mapping, "vesa-30"))
|
||||
return MEDIA_BUS_FMT_RGB101010_1X7X5_SPWG;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -209,6 +209,14 @@ static u32 convert_xrgb8888_to_argb2101010(u32 pix)
|
||||
return GENMASK(31, 30) /* set alpha bits */ | pix | ((pix >> 8) & 0x00300C03);
|
||||
}
|
||||
|
||||
static u32 convert_xrgb8888_to_abgr2101010(u32 pix)
|
||||
{
|
||||
pix = ((pix & 0x00FF0000) >> 14) |
|
||||
((pix & 0x0000FF00) << 4) |
|
||||
((pix & 0x000000FF) << 22);
|
||||
return GENMASK(31, 30) /* set alpha bits */ | pix | ((pix >> 8) & 0x00300C03);
|
||||
}
|
||||
|
||||
/*
|
||||
* convert_from_xrgb8888 - convert one pixel from xrgb8888 to the desired format
|
||||
* @color: input color, in xrgb8888 format
|
||||
@ -242,6 +250,8 @@ static u32 convert_from_xrgb8888(u32 color, u32 format)
|
||||
return convert_xrgb8888_to_xrgb2101010(color);
|
||||
case DRM_FORMAT_ARGB2101010:
|
||||
return convert_xrgb8888_to_argb2101010(color);
|
||||
case DRM_FORMAT_ABGR2101010:
|
||||
return convert_xrgb8888_to_abgr2101010(color);
|
||||
default:
|
||||
WARN_ONCE(1, "Can't convert to %p4cc\n", &format);
|
||||
return 0;
|
||||
|
@ -2,7 +2,7 @@
|
||||
config DRM_MEDIATEK
|
||||
tristate "DRM Support for Mediatek SoCs"
|
||||
depends on DRM
|
||||
depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST
|
||||
depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||
depends on COMMON_CLK
|
||||
depends on HAVE_ARM_SMCCC || COMPILE_TEST
|
||||
depends on OF
|
||||
|
63
drivers/gpu/drm/nouveau/dispnv50/tile.h
Normal file
63
drivers/gpu/drm/nouveau/dispnv50/tile.h
Normal file
@ -0,0 +1,63 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
#ifndef __NV50_TILE_H__
|
||||
#define __NV50_TILE_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/math.h>
|
||||
|
||||
/*
|
||||
* Tiling parameters for NV50+.
|
||||
* GOB = Group of bytes, the main unit for tiling blocks.
|
||||
* Tiling blocks are a power of 2 number of GOB.
|
||||
* All GOBs and blocks have the same width: 64 bytes (so 16 pixels in 32bits).
|
||||
* tile_mode is the log2 of the number of GOB per block.
|
||||
*/
|
||||
|
||||
#define NV_TILE_GOB_HEIGHT_TESLA 4 /* 4 x 64 bytes = 256 bytes for a GOB on Tesla*/
|
||||
#define NV_TILE_GOB_HEIGHT 8 /* 8 x 64 bytes = 512 bytes for a GOB on Fermi and later */
|
||||
#define NV_TILE_GOB_WIDTH_BYTES 64
|
||||
|
||||
/* Number of blocks to cover the width of the framebuffer */
|
||||
static inline u32 nouveau_get_width_in_blocks(u32 stride)
|
||||
{
|
||||
return DIV_ROUND_UP(stride, NV_TILE_GOB_WIDTH_BYTES);
|
||||
}
|
||||
|
||||
/* Return the height in pixel of one GOB */
|
||||
static inline u32 nouveau_get_gob_height(u16 family)
|
||||
{
|
||||
if (family == NV_DEVICE_INFO_V0_TESLA)
|
||||
return NV_TILE_GOB_HEIGHT_TESLA;
|
||||
else
|
||||
return NV_TILE_GOB_HEIGHT;
|
||||
}
|
||||
|
||||
/* Number of blocks to cover the heigth of the framebuffer */
|
||||
static inline u32 nouveau_get_height_in_blocks(u32 height, u32 gobs_in_block, u16 family)
|
||||
{
|
||||
return DIV_ROUND_UP(height, nouveau_get_gob_height(family) * gobs_in_block);
|
||||
}
|
||||
|
||||
/* Return the GOB size in bytes */
|
||||
static inline u32 nouveau_get_gob_size(u16 family)
|
||||
{
|
||||
return nouveau_get_gob_height(family) * NV_TILE_GOB_WIDTH_BYTES;
|
||||
}
|
||||
|
||||
/* Return the number of GOB in a block */
|
||||
static inline int nouveau_get_gobs_in_block(u32 tile_mode, u16 chipset)
|
||||
{
|
||||
if (chipset >= 0xc0)
|
||||
return 1 << (tile_mode >> 4);
|
||||
return 1 << tile_mode;
|
||||
}
|
||||
|
||||
/* Return true if tile_mode is invalid */
|
||||
static inline bool nouveau_check_tile_mode(u32 tile_mode, u16 chipset)
|
||||
{
|
||||
if (chipset >= 0xc0)
|
||||
return (tile_mode & 0xfffff0f);
|
||||
return (tile_mode & 0xfffffff0);
|
||||
}
|
||||
|
||||
#endif
|
@ -30,14 +30,20 @@
|
||||
#include <nvhw/class/cl507e.h>
|
||||
#include <nvhw/class/clc37e.h>
|
||||
|
||||
#include <linux/iosys-map.h>
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_blend.h>
|
||||
#include <drm/drm_gem_atomic_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_gem_atomic_helper.h>
|
||||
#include <drm/drm_panic.h>
|
||||
#include <drm/ttm/ttm_bo.h>
|
||||
|
||||
#include "nouveau_bo.h"
|
||||
#include "nouveau_gem.h"
|
||||
#include "tile.h"
|
||||
|
||||
static void
|
||||
nv50_wndw_ctxdma_del(struct nv50_wndw_ctxdma *ctxdma)
|
||||
@ -577,6 +583,114 @@ nv50_wndw_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Only used by drm_panic get_scanout_buffer() and set_pixel(), so it is
|
||||
* protected by the drm panic spinlock
|
||||
*/
|
||||
static u32 nv50_panic_blk_h;
|
||||
|
||||
/* Return the framebuffer offset of the start of the block where pixel(x,y) is */
|
||||
static u32
|
||||
nv50_get_block_off(unsigned int x, unsigned int y, unsigned int pitch)
|
||||
{
|
||||
u32 blk_x, blk_y, blk_columns;
|
||||
|
||||
blk_columns = nouveau_get_width_in_blocks(pitch);
|
||||
blk_x = (x * 4) / NV_TILE_GOB_WIDTH_BYTES;
|
||||
blk_y = y / nv50_panic_blk_h;
|
||||
|
||||
return ((blk_y * blk_columns) + blk_x) * NV_TILE_GOB_WIDTH_BYTES * nv50_panic_blk_h;
|
||||
}
|
||||
|
||||
/* Turing and later have 2 level of tiles inside the block */
|
||||
static void
|
||||
nv50_set_pixel_swizzle(struct drm_scanout_buffer *sb, unsigned int x,
|
||||
unsigned int y, u32 color)
|
||||
{
|
||||
u32 blk_off, off, swizzle;
|
||||
|
||||
blk_off = nv50_get_block_off(x, y, sb->pitch[0]);
|
||||
|
||||
y = y % nv50_panic_blk_h;
|
||||
|
||||
/* Inside the block, use the fast address swizzle to compute the offset
|
||||
* For nvidia blocklinear, bit order is yn..y3 x3 y2 x2 y1 y0 x1 x0
|
||||
*/
|
||||
swizzle = (x & 3) | (y & 3) << 2 | (x & 4) << 2 | (y & 4) << 3;
|
||||
swizzle |= (x & 8) << 3 | (y >> 3) << 7;
|
||||
off = blk_off + swizzle * 4;
|
||||
|
||||
iosys_map_wr(&sb->map[0], off, u32, color);
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_set_pixel(struct drm_scanout_buffer *sb, unsigned int x, unsigned int y,
|
||||
u32 color)
|
||||
{
|
||||
u32 blk_off, off;
|
||||
|
||||
blk_off = nv50_get_block_off(x, y, sb->width);
|
||||
|
||||
x = x % (NV_TILE_GOB_WIDTH_BYTES / 4);
|
||||
y = y % nv50_panic_blk_h;
|
||||
off = blk_off + x * 4 + y * NV_TILE_GOB_WIDTH_BYTES;
|
||||
|
||||
iosys_map_wr(&sb->map[0], off, u32, color);
|
||||
}
|
||||
|
||||
static int
|
||||
nv50_wndw_get_scanout_buffer(struct drm_plane *plane, struct drm_scanout_buffer *sb)
|
||||
{
|
||||
struct drm_framebuffer *fb;
|
||||
struct nouveau_bo *nvbo;
|
||||
struct nouveau_drm *drm = nouveau_drm(plane->dev);
|
||||
u16 chipset = drm->client.device.info.chipset;
|
||||
u8 family = drm->client.device.info.family;
|
||||
u32 tile_mode;
|
||||
u8 kind;
|
||||
|
||||
if (!plane->state || !plane->state->fb)
|
||||
return -EINVAL;
|
||||
|
||||
fb = plane->state->fb;
|
||||
nvbo = nouveau_gem_object(fb->obj[0]);
|
||||
|
||||
/* Don't support compressed format, or multiplane yet. */
|
||||
if (nvbo->comp || fb->format->num_planes != 1)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (nouveau_bo_map(nvbo)) {
|
||||
drm_warn(plane->dev, "nouveau bo map failed, panic won't be displayed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (nvbo->kmap.bo_kmap_type & TTM_BO_MAP_IOMEM_MASK)
|
||||
iosys_map_set_vaddr_iomem(&sb->map[0], (void __iomem *)nvbo->kmap.virtual);
|
||||
else
|
||||
iosys_map_set_vaddr(&sb->map[0], nvbo->kmap.virtual);
|
||||
|
||||
sb->height = fb->height;
|
||||
sb->width = fb->width;
|
||||
sb->pitch[0] = fb->pitches[0];
|
||||
sb->format = fb->format;
|
||||
|
||||
nouveau_framebuffer_get_layout(fb, &tile_mode, &kind);
|
||||
if (kind) {
|
||||
/* If tiling is enabled, use set_pixel() to display correctly.
|
||||
* Only handle 32bits format for now.
|
||||
*/
|
||||
if (fb->format->cpp[0] != 4)
|
||||
return -EOPNOTSUPP;
|
||||
nv50_panic_blk_h = nouveau_get_gob_height(family) *
|
||||
nouveau_get_gobs_in_block(tile_mode, chipset);
|
||||
|
||||
if (chipset >= 0x160)
|
||||
sb->set_pixel = nv50_set_pixel_swizzle;
|
||||
else
|
||||
sb->set_pixel = nv50_set_pixel;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_plane_helper_funcs
|
||||
nv50_wndw_helper = {
|
||||
.prepare_fb = nv50_wndw_prepare_fb,
|
||||
@ -584,6 +698,14 @@ nv50_wndw_helper = {
|
||||
.atomic_check = nv50_wndw_atomic_check,
|
||||
};
|
||||
|
||||
static const struct drm_plane_helper_funcs
|
||||
nv50_wndw_primary_helper = {
|
||||
.prepare_fb = nv50_wndw_prepare_fb,
|
||||
.cleanup_fb = nv50_wndw_cleanup_fb,
|
||||
.atomic_check = nv50_wndw_atomic_check,
|
||||
.get_scanout_buffer = nv50_wndw_get_scanout_buffer,
|
||||
};
|
||||
|
||||
static void
|
||||
nv50_wndw_atomic_destroy_state(struct drm_plane *plane,
|
||||
struct drm_plane_state *state)
|
||||
@ -732,7 +854,10 @@ nv50_wndw_new_(const struct nv50_wndw_func *func, struct drm_device *dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
drm_plane_helper_add(&wndw->plane, &nv50_wndw_helper);
|
||||
if (type == DRM_PLANE_TYPE_PRIMARY)
|
||||
drm_plane_helper_add(&wndw->plane, &nv50_wndw_primary_helper);
|
||||
else
|
||||
drm_plane_helper_add(&wndw->plane, &nv50_wndw_helper);
|
||||
|
||||
if (wndw->func->ilut) {
|
||||
ret = nv50_lut_init(disp, mmu, &wndw->ilut);
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include <nvif/if0011.h>
|
||||
#include <nvif/if0013.h>
|
||||
#include <dispnv50/crc.h>
|
||||
#include <dispnv50/tile.h>
|
||||
|
||||
int
|
||||
nouveau_display_vblank_enable(struct drm_crtc *crtc)
|
||||
@ -220,69 +221,29 @@ nouveau_validate_decode_mod(struct nouveau_drm *drm,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
nouveau_get_width_in_blocks(uint32_t stride)
|
||||
{
|
||||
/* GOBs per block in the x direction is always one, and GOBs are
|
||||
* 64 bytes wide
|
||||
*/
|
||||
static const uint32_t log_block_width = 6;
|
||||
|
||||
return (stride + (1 << log_block_width) - 1) >> log_block_width;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
nouveau_get_height_in_blocks(struct nouveau_drm *drm,
|
||||
uint32_t height,
|
||||
uint32_t log_block_height_in_gobs)
|
||||
{
|
||||
uint32_t log_gob_height;
|
||||
uint32_t log_block_height;
|
||||
|
||||
BUG_ON(drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA);
|
||||
|
||||
if (drm->client.device.info.family < NV_DEVICE_INFO_V0_FERMI)
|
||||
log_gob_height = 2;
|
||||
else
|
||||
log_gob_height = 3;
|
||||
|
||||
log_block_height = log_block_height_in_gobs + log_gob_height;
|
||||
|
||||
return (height + (1 << log_block_height) - 1) >> log_block_height;
|
||||
}
|
||||
|
||||
static int
|
||||
nouveau_check_bl_size(struct nouveau_drm *drm, struct nouveau_bo *nvbo,
|
||||
uint32_t offset, uint32_t stride, uint32_t h,
|
||||
uint32_t tile_mode)
|
||||
{
|
||||
uint32_t gob_size, bw, bh;
|
||||
uint32_t gob_size, bw, bh, gobs_in_block;
|
||||
uint64_t bl_size;
|
||||
|
||||
BUG_ON(drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA);
|
||||
|
||||
if (drm->client.device.info.chipset >= 0xc0) {
|
||||
if (tile_mode & 0xF)
|
||||
return -EINVAL;
|
||||
tile_mode >>= 4;
|
||||
}
|
||||
|
||||
if (tile_mode & 0xFFFFFFF0)
|
||||
if (nouveau_check_tile_mode(tile_mode, drm->client.device.info.chipset))
|
||||
return -EINVAL;
|
||||
|
||||
if (drm->client.device.info.family < NV_DEVICE_INFO_V0_FERMI)
|
||||
gob_size = 256;
|
||||
else
|
||||
gob_size = 512;
|
||||
|
||||
gobs_in_block = nouveau_get_gobs_in_block(tile_mode, drm->client.device.info.chipset);
|
||||
bw = nouveau_get_width_in_blocks(stride);
|
||||
bh = nouveau_get_height_in_blocks(drm, h, tile_mode);
|
||||
bh = nouveau_get_height_in_blocks(h, gobs_in_block, drm->client.device.info.family);
|
||||
gob_size = nouveau_get_gob_size(drm->client.device.info.family);
|
||||
|
||||
bl_size = bw * bh * (1 << tile_mode) * gob_size;
|
||||
bl_size = bw * bh * gobs_in_block * gob_size;
|
||||
|
||||
DRM_DEBUG_KMS("offset=%u stride=%u h=%u tile_mode=0x%02x bw=%u bh=%u gob_size=%u bl_size=%llu size=%zu\n",
|
||||
offset, stride, h, tile_mode, bw, bh, gob_size, bl_size,
|
||||
nvbo->bo.base.size);
|
||||
DRM_DEBUG_KMS("offset=%u stride=%u h=%u gobs_in_block=%u bw=%u bh=%u gob_size=%u bl_size=%llu size=%zu\n",
|
||||
offset, stride, h, gobs_in_block, bw, bh, gob_size,
|
||||
bl_size, nvbo->bo.base.size);
|
||||
|
||||
if (bl_size + offset > nvbo->bo.base.size)
|
||||
return -ERANGE;
|
||||
|
@ -38,7 +38,7 @@ static int panfrost_devfreq_target(struct device *dev, unsigned long *freq,
|
||||
return PTR_ERR(opp);
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
err = dev_pm_opp_set_rate(dev, *freq);
|
||||
err = dev_pm_opp_set_rate(dev, *freq);
|
||||
if (!err)
|
||||
ptdev->pfdevfreq.current_frequency = *freq;
|
||||
|
||||
@ -182,6 +182,7 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev)
|
||||
* if any and will avoid a switch off by regulator_late_cleanup()
|
||||
*/
|
||||
ret = dev_pm_opp_set_opp(dev, opp);
|
||||
dev_pm_opp_put(opp);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dev, "Couldn't set recommended OPP\n");
|
||||
return ret;
|
||||
|
@ -163,13 +163,6 @@ int panthor_devfreq_init(struct panthor_device *ptdev)
|
||||
|
||||
cur_freq = clk_get_rate(ptdev->clks.core);
|
||||
|
||||
opp = devfreq_recommended_opp(dev, &cur_freq, 0);
|
||||
if (IS_ERR(opp))
|
||||
return PTR_ERR(opp);
|
||||
|
||||
panthor_devfreq_profile.initial_freq = cur_freq;
|
||||
ptdev->current_frequency = cur_freq;
|
||||
|
||||
/* Regulator coupling only takes care of synchronizing/balancing voltage
|
||||
* updates, but the coupled regulator needs to be enabled manually.
|
||||
*
|
||||
@ -200,18 +193,24 @@ int panthor_devfreq_init(struct panthor_device *ptdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
opp = devfreq_recommended_opp(dev, &cur_freq, 0);
|
||||
if (IS_ERR(opp))
|
||||
return PTR_ERR(opp);
|
||||
|
||||
panthor_devfreq_profile.initial_freq = cur_freq;
|
||||
ptdev->current_frequency = cur_freq;
|
||||
|
||||
/*
|
||||
* Set the recommend OPP this will enable and configure the regulator
|
||||
* if any and will avoid a switch off by regulator_late_cleanup()
|
||||
*/
|
||||
ret = dev_pm_opp_set_opp(dev, opp);
|
||||
dev_pm_opp_put(opp);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dev, "Couldn't set recommended OPP\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
/* Find the fastest defined rate */
|
||||
opp = dev_pm_opp_find_freq_floor(dev, &freq);
|
||||
if (IS_ERR(opp))
|
||||
|
@ -1350,6 +1350,19 @@ EXPORT_SYMBOL(drm_sched_init);
|
||||
* @sched: scheduler instance
|
||||
*
|
||||
* Tears down and cleans up the scheduler.
|
||||
*
|
||||
* This stops submission of new jobs to the hardware through
|
||||
* drm_sched_backend_ops.run_job(). Consequently, drm_sched_backend_ops.free_job()
|
||||
* will not be called for all jobs still in drm_gpu_scheduler.pending_list.
|
||||
* There is no solution for this currently. Thus, it is up to the driver to make
|
||||
* sure that
|
||||
* a) drm_sched_fini() is only called after for all submitted jobs
|
||||
* drm_sched_backend_ops.free_job() has been called or that
|
||||
* b) the jobs for which drm_sched_backend_ops.free_job() has not been called
|
||||
* after drm_sched_fini() ran are freed manually.
|
||||
*
|
||||
* FIXME: Take care of the above problem and prevent this function from leaking
|
||||
* the jobs in drm_gpu_scheduler.pending_list under any circumstances.
|
||||
*/
|
||||
void drm_sched_fini(struct drm_gpu_scheduler *sched)
|
||||
{
|
||||
@ -1445,8 +1458,10 @@ EXPORT_SYMBOL(drm_sched_wqueue_ready);
|
||||
|
||||
/**
|
||||
* drm_sched_wqueue_stop - stop scheduler submission
|
||||
*
|
||||
* @sched: scheduler instance
|
||||
*
|
||||
* Stops the scheduler from pulling new jobs from entities. It also stops
|
||||
* freeing jobs automatically through drm_sched_backend_ops.free_job().
|
||||
*/
|
||||
void drm_sched_wqueue_stop(struct drm_gpu_scheduler *sched)
|
||||
{
|
||||
@ -1458,8 +1473,12 @@ EXPORT_SYMBOL(drm_sched_wqueue_stop);
|
||||
|
||||
/**
|
||||
* drm_sched_wqueue_start - start scheduler submission
|
||||
*
|
||||
* @sched: scheduler instance
|
||||
*
|
||||
* Restarts the scheduler after drm_sched_wqueue_stop() has stopped it.
|
||||
*
|
||||
* This function is not necessary for 'conventional' startup. The scheduler is
|
||||
* fully operational after drm_sched_init() succeeded.
|
||||
*/
|
||||
void drm_sched_wqueue_start(struct drm_gpu_scheduler *sched)
|
||||
{
|
||||
|
@ -187,7 +187,7 @@ static void blend(struct vkms_writeback_job *wb,
|
||||
|
||||
const struct pixel_argb_u16 background_color = { .a = 0xffff };
|
||||
|
||||
size_t crtc_y_limit = crtc_state->base.crtc->mode.vdisplay;
|
||||
size_t crtc_y_limit = crtc_state->base.mode.vdisplay;
|
||||
|
||||
/*
|
||||
* The planes are composed line-by-line to avoid heavy memory usage. It is a necessary
|
||||
@ -270,7 +270,7 @@ static int compose_active_planes(struct vkms_writeback_job *active_wb,
|
||||
if (WARN_ON(check_format_funcs(crtc_state, active_wb)))
|
||||
return -EINVAL;
|
||||
|
||||
line_width = crtc_state->base.crtc->mode.hdisplay;
|
||||
line_width = crtc_state->base.mode.hdisplay;
|
||||
stage_buffer.n_pixels = line_width;
|
||||
output_buffer.n_pixels = line_width;
|
||||
|
||||
|
@ -64,8 +64,6 @@ static int vkms_enable_vblank(struct drm_crtc *crtc)
|
||||
struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
|
||||
struct vkms_output *out = drm_crtc_to_vkms_output(crtc);
|
||||
|
||||
drm_calc_timestamping_constants(crtc, &crtc->mode);
|
||||
|
||||
hrtimer_init(&out->vblank_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
out->vblank_hrtimer.function = &vkms_vblank_simulate;
|
||||
out->period_ns = ktime_set(0, vblank->framedur_ns);
|
||||
|
@ -92,7 +92,7 @@ int vkms_output_init(struct vkms_device *vkmsdev, int index)
|
||||
DRM_MODE_CONNECTOR_VIRTUAL);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to init connector\n");
|
||||
goto err_connector;
|
||||
return ret;
|
||||
}
|
||||
|
||||
drm_connector_helper_add(connector, &vkms_conn_helper_funcs);
|
||||
@ -131,8 +131,5 @@ int vkms_output_init(struct vkms_device *vkmsdev, int index)
|
||||
err_encoder:
|
||||
drm_connector_cleanup(connector);
|
||||
|
||||
err_connector:
|
||||
drm_crtc_cleanup(crtc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -131,8 +131,8 @@ static void vkms_wb_atomic_commit(struct drm_connector *conn,
|
||||
struct drm_connector_state *conn_state = wb_conn->base.state;
|
||||
struct vkms_crtc_state *crtc_state = output->composer_state;
|
||||
struct drm_framebuffer *fb = connector_state->writeback_job->fb;
|
||||
u16 crtc_height = crtc_state->base.crtc->mode.vdisplay;
|
||||
u16 crtc_width = crtc_state->base.crtc->mode.hdisplay;
|
||||
u16 crtc_height = crtc_state->base.mode.vdisplay;
|
||||
u16 crtc_width = crtc_state->base.mode.hdisplay;
|
||||
struct vkms_writeback_job *active_wb;
|
||||
struct vkms_frame_info *wb_frame_info;
|
||||
u32 wb_format = fb->format->format;
|
||||
|
@ -52,6 +52,8 @@ int drm_of_find_panel_or_bridge(const struct device_node *np,
|
||||
struct drm_bridge **bridge);
|
||||
int drm_of_lvds_get_dual_link_pixel_order(const struct device_node *port1,
|
||||
const struct device_node *port2);
|
||||
int drm_of_lvds_get_dual_link_pixel_order_sink(struct device_node *port1,
|
||||
struct device_node *port2);
|
||||
int drm_of_lvds_get_data_mapping(const struct device_node *port);
|
||||
int drm_of_get_data_lanes_count(const struct device_node *endpoint,
|
||||
const unsigned int min, const unsigned int max);
|
||||
@ -109,6 +111,13 @@ drm_of_lvds_get_dual_link_pixel_order(const struct device_node *port1,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int
|
||||
drm_of_lvds_get_dual_link_pixel_order_sink(struct device_node *port1,
|
||||
struct device_node *port2)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int
|
||||
drm_of_lvds_get_data_mapping(const struct device_node *port)
|
||||
{
|
||||
|
@ -34,7 +34,7 @@
|
||||
|
||||
#define MEDIA_BUS_FMT_FIXED 0x0001
|
||||
|
||||
/* RGB - next is 0x1026 */
|
||||
/* RGB - next is 0x1028 */
|
||||
#define MEDIA_BUS_FMT_RGB444_1X12 0x1016
|
||||
#define MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE 0x1001
|
||||
#define MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE 0x1002
|
||||
@ -68,6 +68,8 @@
|
||||
#define MEDIA_BUS_FMT_ARGB8888_1X32 0x100d
|
||||
#define MEDIA_BUS_FMT_RGB888_1X32_PADHI 0x100f
|
||||
#define MEDIA_BUS_FMT_RGB101010_1X30 0x1018
|
||||
#define MEDIA_BUS_FMT_RGB101010_1X7X5_SPWG 0x1026
|
||||
#define MEDIA_BUS_FMT_RGB101010_1X7X5_JEIDA 0x1027
|
||||
#define MEDIA_BUS_FMT_RGB666_1X36_CPADLO 0x1020
|
||||
#define MEDIA_BUS_FMT_RGB888_1X36_CPADLO 0x1021
|
||||
#define MEDIA_BUS_FMT_RGB121212_1X36 0x1019
|
||||
|
Loading…
Reference in New Issue
Block a user