diff options
231 files changed, 4576 insertions, 98 deletions
diff --git a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml index 35a48515836e..4590186c4a0b 100644 --- a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml +++ b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml @@ -94,7 +94,22 @@ properties: $ref: /schemas/graph.yaml#/$defs/port-base unevaluatedProperties: false description: - Video port for MIPI DSI input. + MIPI DSI/DPI input. + + properties: + endpoint: + $ref: /schemas/media/video-interfaces.yaml# + type: object + additionalProperties: false + + properties: + remote-endpoint: true + + bus-type: + enum: [7] + default: 1 + + data-lanes: true port@1: $ref: /schemas/graph.yaml#/properties/port @@ -143,6 +158,8 @@ examples: reg = <0>; anx7625_in: endpoint { remote-endpoint = <&mipi_dsi>; + bus-type = <7>; + data-lanes = <0 1 2 3>; }; }; diff --git a/Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-ldb.yaml b/Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-ldb.yaml new file mode 100644 index 000000000000..94543006f5de --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-ldb.yaml @@ -0,0 +1,173 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/bridge/fsl,imx8qxp-ldb.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qm/qxp LVDS Display Bridge + +maintainers: + - Liu Ying <victor.liu@nxp.com> + +description: | + The Freescale i.MX8qm/qxp LVDS Display Bridge(LDB) has two channels. + + The i.MX8qm/qxp LDB is controlled by Control and Status Registers(CSR) module. + The CSR module, as a system controller, contains the LDB's configuration + registers. + + For i.MX8qxp LDB, each channel supports up to 24bpp parallel input color + format and can map the input to VESA or JEIDA standards. The two channels + cannot be used simultaneously, that is to say, the user should pick one of + them to use. Two LDB channels from two LDB instances can work together in + LDB split mode to support a dual link LVDS display. The channel indexes + have to be different. Channel0 outputs odd pixels and channel1 outputs + even pixels. + + For i.MX8qm LDB, each channel additionally supports up to 30bpp parallel + input color format. The two channels can be used simultaneously, either + in dual mode or split mode. In dual mode, the two channels output identical + data. In split mode, channel0 outputs odd pixels and channel1 outputs even + pixels. + + A side note is that i.MX8qm/qxp LDB is officially called pixel mapper in + the SoC reference manuals. The pixel mapper uses logic of LDBs embedded in + i.MX6qdl/sx SoCs, i.e., it is essentially based on them. To keep the naming + consistency, this binding calls it LDB. + +properties: + compatible: + enum: + - fsl,imx8qm-ldb + - fsl,imx8qxp-ldb + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + clocks: + items: + - description: pixel clock + - description: bypass clock + + clock-names: + items: + - const: pixel + - const: bypass + + power-domains: + maxItems: 1 + + fsl,companion-ldb: + $ref: /schemas/types.yaml#/definitions/phandle + description: | + A phandle which points to companion LDB which is used in LDB split mode. + +patternProperties: + "^channel@[0-1]$": + type: object + description: Represents a channel of LDB. + + properties: + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + reg: + description: The channel index. + enum: [ 0, 1 ] + + phys: + description: A phandle to the phy module representing the LVDS PHY. + maxItems: 1 + + phy-names: + const: lvds_phy + + port@0: + $ref: /schemas/graph.yaml#/properties/port + description: Input port of the channel. + + port@1: + $ref: /schemas/graph.yaml#/properties/port + description: Output port of the channel. + + required: + - "#address-cells" + - "#size-cells" + - reg + - phys + - phy-names + + additionalProperties: false + +required: + - compatible + - "#address-cells" + - "#size-cells" + - clocks + - clock-names + - power-domains + - channel@0 + - channel@1 + +allOf: + - if: + properties: + compatible: + contains: + const: fsl,imx8qm-ldb + then: + properties: + fsl,companion-ldb: false + +additionalProperties: false + +examples: + - | + #include <dt-bindings/firmware/imx/rsrc.h> + ldb { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx8qxp-ldb"; + clocks = <&clk IMX_SC_R_LVDS_0 IMX_SC_PM_CLK_MISC2>, + <&clk IMX_SC_R_LVDS_0 IMX_SC_PM_CLK_BYPASS>; + clock-names = "pixel", "bypass"; + power-domains = <&pd IMX_SC_R_LVDS_0>; + + channel@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + phys = <&mipi_lvds_0_phy>; + phy-names = "lvds_phy"; + + port@0 { + reg = <0>; + + mipi_lvds_0_ldb_ch0_mipi_lvds_0_pxl2dpi: endpoint { + remote-endpoint = <&mipi_lvds_0_pxl2dpi_mipi_lvds_0_ldb_ch0>; + }; + }; + }; + + channel@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + phys = <&mipi_lvds_0_phy>; + phy-names = "lvds_phy"; + + port@0 { + reg = <0>; + + mipi_lvds_0_ldb_ch1_mipi_lvds_0_pxl2dpi: endpoint { + remote-endpoint = <&mipi_lvds_0_pxl2dpi_mipi_lvds_0_ldb_ch1>; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-pixel-combiner.yaml b/Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-pixel-combiner.yaml new file mode 100644 index 000000000000..50bae2122183 --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-pixel-combiner.yaml @@ -0,0 +1,144 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/bridge/fsl,imx8qxp-pixel-combiner.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qm/qxp Pixel Combiner + +maintainers: + - Liu Ying <victor.liu@nxp.com> + +description: | + The Freescale i.MX8qm/qxp Pixel Combiner takes two output streams from a + single display controller and manipulates the two streams to support a number + of modes(bypass, pixel combine, YUV444 to YUV422, split_RGB) configured as + either one screen, two screens, or virtual screens. The pixel combiner is + also responsible for generating some of the control signals for the pixel link + output channel. + +properties: + compatible: + enum: + - fsl,imx8qm-pixel-combiner + - fsl,imx8qxp-pixel-combiner + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + const: apb + + power-domains: + maxItems: 1 + +patternProperties: + "^channel@[0-1]$": + type: object + description: Represents a display stream of pixel combiner. + + properties: + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + reg: + description: The display stream index. + enum: [ 0, 1 ] + + port@0: + $ref: /schemas/graph.yaml#/properties/port + description: Input endpoint of the display stream. + + port@1: + $ref: /schemas/graph.yaml#/properties/port + description: Output endpoint of the display stream. + + required: + - "#address-cells" + - "#size-cells" + - reg + - port@0 + - port@1 + + additionalProperties: false + +required: + - compatible + - "#address-cells" + - "#size-cells" + - reg + - clocks + - clock-names + - power-domains + +additionalProperties: false + +examples: + - | + #include <dt-bindings/clock/imx8-lpcg.h> + #include <dt-bindings/firmware/imx/rsrc.h> + pixel-combiner@56020000 { + compatible = "fsl,imx8qxp-pixel-combiner"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x56020000 0x10000>; + clocks = <&dc0_pixel_combiner_lpcg IMX_LPCG_CLK_4>; + clock-names = "apb"; + power-domains = <&pd IMX_SC_R_DC_0>; + + channel@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + port@0 { + reg = <0>; + + dc0_pixel_combiner_ch0_dc0_dpu_disp0: endpoint { + remote-endpoint = <&dc0_dpu_disp0_dc0_pixel_combiner_ch0>; + }; + }; + + port@1 { + reg = <1>; + + dc0_pixel_combiner_ch0_dc0_pixel_link0: endpoint { + remote-endpoint = <&dc0_pixel_link0_dc0_pixel_combiner_ch0>; + }; + }; + }; + + channel@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + port@0 { + reg = <0>; + + dc0_pixel_combiner_ch1_dc0_dpu_disp1: endpoint { + remote-endpoint = <&dc0_dpu_disp1_dc0_pixel_combiner_ch1>; + }; + }; + + port@1 { + reg = <1>; + + dc0_pixel_combiner_ch1_dc0_pixel_link1: endpoint { + remote-endpoint = <&dc0_pixel_link1_dc0_pixel_combiner_ch1>; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-pixel-link.yaml b/Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-pixel-link.yaml new file mode 100644 index 000000000000..38ecc7926fad --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-pixel-link.yaml @@ -0,0 +1,144 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/bridge/fsl,imx8qxp-pixel-link.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qm/qxp Display Pixel Link + +maintainers: + - Liu Ying <victor.liu@nxp.com> + +description: | + The Freescale i.MX8qm/qxp Display Pixel Link(DPL) forms a standard + asynchronous linkage between pixel sources(display controller or + camera module) and pixel consumers(imaging or displays). + It consists of two distinct functions, a pixel transfer function and a + control interface. Multiple pixel channels can exist per one control channel. + This binding documentation is only for pixel links whose pixel sources are + display controllers. + + The i.MX8qm/qxp Display Pixel Link is accessed via System Controller Unit(SCU) + firmware. + +properties: + compatible: + enum: + - fsl,imx8qm-dc-pixel-link + - fsl,imx8qxp-dc-pixel-link + + fsl,dc-id: + $ref: /schemas/types.yaml#/definitions/uint8 + description: | + u8 value representing the display controller index that the pixel link + connects to. + + fsl,dc-stream-id: + $ref: /schemas/types.yaml#/definitions/uint8 + description: | + u8 value representing the display controller stream index that the pixel + link connects to. + enum: [0, 1] + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + properties: + port@0: + $ref: /schemas/graph.yaml#/properties/port + description: The pixel link input port node from upstream video source. + + patternProperties: + "^port@[1-4]$": + $ref: /schemas/graph.yaml#/properties/port + description: The pixel link output port node to downstream bridge. + + required: + - port@0 + - port@1 + - port@2 + - port@3 + - port@4 + +allOf: + - if: + properties: + compatible: + contains: + const: fsl,imx8qxp-dc-pixel-link + then: + properties: + fsl,dc-id: + const: 0 + + - if: + properties: + compatible: + contains: + const: fsl,imx8qm-dc-pixel-link + then: + properties: + fsl,dc-id: + enum: [0, 1] + +required: + - compatible + - fsl,dc-id + - fsl,dc-stream-id + - ports + +additionalProperties: false + +examples: + - | + dc0-pixel-link0 { + compatible = "fsl,imx8qxp-dc-pixel-link"; + fsl,dc-id = /bits/ 8 <0>; + fsl,dc-stream-id = /bits/ 8 <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + /* from dc0 pixel combiner channel0 */ + port@0 { + reg = <0>; + + dc0_pixel_link0_dc0_pixel_combiner_ch0: endpoint { + remote-endpoint = <&dc0_pixel_combiner_ch0_dc0_pixel_link0>; + }; + }; + + /* to PXL2DPIs in MIPI/LVDS combo subsystems */ + port@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + dc0_pixel_link0_mipi_lvds_0_pxl2dpi: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi_lvds_0_pxl2dpi_dc0_pixel_link0>; + }; + + dc0_pixel_link0_mipi_lvds_1_pxl2dpi: endpoint@1 { + reg = <1>; + remote-endpoint = <&mipi_lvds_1_pxl2dpi_dc0_pixel_link0>; + }; + }; + + /* unused */ + port@2 { + reg = <2>; + }; + + /* unused */ + port@3 { + reg = <3>; + }; + + /* to imaging subsystem */ + port@4 { + reg = <4>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-pxl2dpi.yaml b/Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-pxl2dpi.yaml new file mode 100644 index 000000000000..e4e77fad05f1 --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-pxl2dpi.yaml @@ -0,0 +1,108 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/bridge/fsl,imx8qxp-pxl2dpi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qxp Pixel Link to Display Pixel Interface + +maintainers: + - Liu Ying <victor.liu@nxp.com> + +description: | + The Freescale i.MX8qxp Pixel Link to Display Pixel Interface(PXL2DPI) + interfaces the pixel link 36-bit data output and the DSI controller’s + MIPI-DPI 24-bit data input, and inputs of LVDS Display Bridge(LDB) module + used in LVDS mode, to remap the pixel color codings between those modules. + This module is purely combinatorial. + + The i.MX8qxp PXL2DPI is controlled by Control and Status Registers(CSR) module. + The CSR module, as a system controller, contains the PXL2DPI's configuration + register. + +properties: + compatible: + const: fsl,imx8qxp-pxl2dpi + + fsl,sc-resource: + $ref: /schemas/types.yaml#/definitions/uint32 + description: The SCU resource ID associated with this PXL2DPI instance. + + power-domains: + maxItems: 1 + + fsl,companion-pxl2dpi: + $ref: /schemas/types.yaml#/definitions/phandle + description: | + A phandle which points to companion PXL2DPI which is used by downstream + LVDS Display Bridge(LDB) in split mode. + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + properties: + port@0: + $ref: /schemas/graph.yaml#/properties/port + description: The PXL2DPI input port node from pixel link. + + port@1: + $ref: /schemas/graph.yaml#/properties/port + description: The PXL2DPI output port node to downstream bridge. + + required: + - port@0 + - port@1 + +required: + - compatible + - fsl,sc-resource + - power-domains + - ports + +additionalProperties: false + +examples: + - | + #include <dt-bindings/firmware/imx/rsrc.h> + pxl2dpi { + compatible = "fsl,imx8qxp-pxl2dpi"; + fsl,sc-resource = <IMX_SC_R_MIPI_0>; + power-domains = <&pd IMX_SC_R_MIPI_0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + mipi_lvds_0_pxl2dpi_dc_pixel_link0: endpoint@0 { + reg = <0>; + remote-endpoint = <&dc_pixel_link0_mipi_lvds_0_pxl2dpi>; + }; + + mipi_lvds_0_pxl2dpi_dc_pixel_link1: endpoint@1 { + reg = <1>; + remote-endpoint = <&dc_pixel_link1_mipi_lvds_0_pxl2dpi>; + }; + }; + + port@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + mipi_lvds_0_pxl2dpi_mipi_lvds_0_ldb_ch0: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi_lvds_0_ldb_ch0_mipi_lvds_0_pxl2dpi>; + }; + + mipi_lvds_0_pxl2dpi_mipi_lvds_0_ldb_ch1: endpoint@1 { + reg = <1>; + remote-endpoint = <&mipi_lvds_0_ldb_ch1_mipi_lvds_0_pxl2dpi>; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/mfd/fsl,imx8qxp-csr.yaml b/Documentation/devicetree/bindings/mfd/fsl,imx8qxp-csr.yaml new file mode 100644 index 000000000000..f09577105b50 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/fsl,imx8qxp-csr.yaml @@ -0,0 +1,192 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/fsl,imx8qxp-csr.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qm/qxp Control and Status Registers Module Bindings + +maintainers: + - Liu Ying <victor.liu@nxp.com> + +description: | + As a system controller, the Freescale i.MX8qm/qxp Control and Status + Registers(CSR) module represents a set of miscellaneous registers of a + specific subsystem. It may provide control and/or status report interfaces + to a mix of standalone hardware devices within that subsystem. One typical + use-case is for some other nodes to acquire a reference to the syscon node + by phandle, and the other typical use-case is that the operating system + should consider all subnodes of the CSR module as separate child devices. + +properties: + $nodename: + pattern: "^syscon@[0-9a-f]+$" + + compatible: + items: + - enum: + - fsl,imx8qxp-mipi-lvds-csr + - fsl,imx8qm-lvds-csr + - const: syscon + - const: simple-mfd + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + const: ipg + +patternProperties: + "^(ldb|phy|pxl2dpi)$": + type: object + description: The possible child devices of the CSR module. + +required: + - compatible + - reg + - clocks + - clock-names + +allOf: + - if: + properties: + compatible: + contains: + const: fsl,imx8qxp-mipi-lvds-csr + then: + required: + - pxl2dpi + - ldb + + - if: + properties: + compatible: + contains: + const: fsl,imx8qm-lvds-csr + then: + required: + - phy + - ldb + +additionalProperties: false + +examples: + - | + #include <dt-bindings/clock/imx8-lpcg.h> + #include <dt-bindings/firmware/imx/rsrc.h> + mipi_lvds_0_csr: syscon@56221000 { + compatible = "fsl,imx8qxp-mipi-lvds-csr", "syscon", "simple-mfd"; + reg = <0x56221000 0x1000>; + clocks = <&mipi_lvds_0_di_mipi_lvds_regs_lpcg IMX_LPCG_CLK_4>; + clock-names = "ipg"; + + mipi_lvds_0_pxl2dpi: pxl2dpi { + compatible = "fsl,imx8qxp-pxl2dpi"; + fsl,sc-resource = <IMX_SC_R_MIPI_0>; + power-domains = <&pd IMX_SC_R_MIPI_0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + mipi_lvds_0_pxl2dpi_dc0_pixel_link0: endpoint@0 { + reg = <0>; + remote-endpoint = <&dc0_pixel_link0_mipi_lvds_0_pxl2dpi>; + }; + + mipi_lvds_0_pxl2dpi_dc0_pixel_link1: endpoint@1 { + reg = <1>; + remote-endpoint = <&dc0_pixel_link1_mipi_lvds_0_pxl2dpi>; + }; + }; + + port@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + mipi_lvds_0_pxl2dpi_mipi_lvds_0_ldb_ch0: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi_lvds_0_ldb_ch0_mipi_lvds_0_pxl2dpi>; + }; + + mipi_lvds_0_pxl2dpi_mipi_lvds_0_ldb_ch1: endpoint@1 { + reg = <1>; + remote-endpoint = <&mipi_lvds_0_ldb_ch1_mipi_lvds_0_pxl2dpi>; + }; + }; + }; + }; + + mipi_lvds_0_ldb: ldb { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx8qxp-ldb"; + clocks = <&clk IMX_SC_R_LVDS_0 IMX_SC_PM_CLK_MISC2>, + <&clk IMX_SC_R_LVDS_0 IMX_SC_PM_CLK_BYPASS>; + clock-names = "pixel", "bypass"; + power-domains = <&pd IMX_SC_R_LVDS_0>; + + channel@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + phys = <&mipi_lvds_0_phy>; + phy-names = "lvds_phy"; + + port@0 { + reg = <0>; + + mipi_lvds_0_ldb_ch0_mipi_lvds_0_pxl2dpi: endpoint { + remote-endpoint = <&mipi_lvds_0_pxl2dpi_mipi_lvds_0_ldb_ch0>; + }; + }; + + port@1 { + reg = <1>; + + /* ... */ + }; + }; + + channel@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + phys = <&mipi_lvds_0_phy>; + phy-names = "lvds_phy"; + + port@0 { + reg = <0>; + + mipi_lvds_0_ldb_ch1_mipi_lvds_0_pxl2dpi: endpoint { + remote-endpoint = <&mipi_lvds_0_pxl2dpi_mipi_lvds_0_ldb_ch1>; + }; + }; + + port@1 { + reg = <1>; + + /* ... */ + }; + }; + }; + }; + + mipi_lvds_0_phy: phy@56228300 { + compatible = "fsl,imx8qxp-mipi-dphy"; + reg = <0x56228300 0x100>; + clocks = <&clk IMX_SC_R_LVDS_0 IMX_SC_PM_CLK_PHY>; + clock-names = "phy_ref"; + #phy-cells = <0>; + fsl,syscon = <&mipi_lvds_0_csr>; + power-domains = <&pd IMX_SC_R_MIPI_0>; + }; diff --git a/Documentation/userspace-api/media/v4l/subdev-formats.rst b/Documentation/userspace-api/media/v4l/subdev-formats.rst index 0cbc045d5df6..d21d532eee15 100644 --- a/Documentation/userspace-api/media/v4l/subdev-formats.rst +++ b/Documentation/userspace-api/media/v4l/subdev-formats.rst @@ -1492,6 +1492,80 @@ The following tables list existing packed RGB formats. - b\ :sub:`2` - b\ :sub:`1` - b\ :sub:`0` + * .. _MEDIA-BUS-FMT-RGB666-1X30-CPADLO: + + - MEDIA_BUS_FMT_RGB666_1X30-CPADLO + - 0x101e + - + - + - + - r\ :sub:`5` + - r\ :sub:`4` + - r\ :sub:`3` + - r\ :sub:`2` + - r\ :sub:`1` + - r\ :sub:`0` + - 0 + - 0 + - 0 + - 0 + - g\ :sub:`5` + - g\ :sub:`4` + - g\ :sub:`3` + - g\ :sub:`2` + - g\ :sub:`1` + - g\ :sub:`0` + - 0 + - 0 + - 0 + - 0 + - b\ :sub:`5` + - b\ :sub:`4` + - b\ :sub:`3` + - b\ :sub:`2` + - b\ :sub:`1` + - b\ :sub:`0` + - 0 + - 0 + - 0 + - 0 + * .. _MEDIA-BUS-FMT-RGB888-1X30-CPADLO: + + - MEDIA_BUS_FMT_RGB888_1X30-CPADLO + - 0x101f + - + - + - + - r\ :sub:`7` + - r\ :sub:`6` + - r\ :sub:`5` + - r\ :sub:`4` + - r\ :sub:`3` + - r\ :sub:`2` + - r\ :sub:`1` + - r\ :sub:`0` + - 0 + - 0 + - g\ :sub:`7` + - g\ :sub:`6` + - g\ :sub:`5` + - g\ :sub:`4` + - g\ :sub:`3` + - g\ :sub:`2` + - g\ :sub:`1` + - g\ :sub:`0` + - 0 + - 0 + - b\ :sub:`7` + - b\ :sub:`6` + - b\ :sub:`5` + - b\ :sub:`4` + - b\ :sub:`3` + - b\ :sub:`2` + - b\ :sub:`1` + - b\ :sub:`0` + - 0 + - 0 * .. _MEDIA-BUS-FMT-ARGB888-1X32: - MEDIA_BUS_FMT_ARGB888_1X32 @@ -1669,6 +1743,88 @@ The following table list existing packed 36bit wide RGB formats. - 2 - 1 - 0 + * .. _MEDIA-BUS-FMT-RGB666-1X36-CPADLO: + + - MEDIA_BUS_FMT_RGB666_1X36_CPADLO + - 0x1020 + - + - r\ :sub:`5` + - r\ :sub:`4` + - r\ :sub:`3` + - r\ :sub:`2` + - r\ :sub:`1` + - r\ :sub:`0` + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - g\ :sub:`5` + - g\ :sub:`4` + - g\ :sub:`3` + - g\ :sub:`2` + - g\ :sub:`1` + - g\ :sub:`0` + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - b\ :sub:`5` + - b\ :sub:`4` + - b\ :sub:`3` + - b\ :sub:`2` + - b\ :sub:`1` + - b\ :sub:`0` + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + * .. _MEDIA-BUS-FMT-RGB888-1X36-CPADLO: + + - MEDIA_BUS_FMT_RGB888_1X36_CPADLO + - 0x1021 + - + - r\ :sub:`7` + - r\ :sub:`6` + - r\ :sub:`5` + - r\ :sub:`4` + - r\ :sub:`3` + - r\ :sub:`2` + - r\ :sub:`1` + - r\ :sub:`0` + - 0 + - 0 + - 0 + - 0 + - g\ :sub:`7` + - g\ :sub:`6` + - g\ :sub:`5` + - g\ :sub:`4` + - g\ :sub:`3` + - g\ :sub:`2` + - g\ :sub:`1` + - g\ :sub:`0` + - 0 + - 0 + - 0 + - 0 + - b\ :sub:`7` + - b\ :sub:`6` + - b\ :sub:`5` + - b\ :sub:`4` + - b\ :sub:`3` + - b\ :sub:`2` + - b\ :sub:`1` + - b\ :sub:`0` + - 0 + - 0 + - 0 + - 0 * .. _MEDIA-BUS-FMT-RGB121212-1X36: - MEDIA_BUS_FMT_RGB121212_1X36 diff --git a/MAINTAINERS b/MAINTAINERS index 3412310537cc..4036b64ed7b0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6674,6 +6674,16 @@ F: Documentation/devicetree/bindings/display/imx/ F: drivers/gpu/drm/imx/ F: drivers/gpu/ipu-v3/ +DRM DRIVERS FOR FREESCALE IMX BRIDGE +M: Liu Ying <victor.liu@nxp.com> +L: dri-devel@lists.freedesktop.org +S: Maintained +F: Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-ldb.yaml +F: Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-pixel-combiner.yaml +F: Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-pixel-link.yaml +F: Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-pxl2dpi.yaml +F: drivers/gpu/drm/bridge/imx/ + DRM DRIVERS FOR GMA500 (Poulsbo, Moorestown and derivative chipsets) M: Patrik Jakobsson <patrik.r.jakobsson@gmail.com> L: dri-devel@lists.freedesktop.org diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index f80b4838cea1..450d32ccd69d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -37,6 +37,7 @@ #include <drm/drm_fixed.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <linux/i2c.h> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index eb6c55e9f6b5..2f4422d4c8a4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -78,6 +78,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_uapi.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_edid.h> @@ -9138,7 +9139,6 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, to_dm_crtc_state(drm_atomic_get_old_crtc_state(state, pcrtc)); int planes_count = 0, vpos, hpos; unsigned long flags; - struct amdgpu_bo *abo; uint32_t target_vblank, last_flip_vblank; bool vrr_active = amdgpu_dm_vrr_active(acrtc_state); bool pflip_present = false; @@ -9210,7 +9210,6 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, continue; } - abo = gem_to_amdgpu_bo(fb->obj[0]); fill_dc_plane_info_and_addr( dm->adev, new_plane_state, afb->tiling_flags, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h index fdcaea22b456..d3bc9dc21771 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h @@ -34,6 +34,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_plane.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_encoder.h> #include <drm/drm_atomic.h> diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c b/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c index 00fa56c29b3e..daa1faccd3e7 100644 --- a/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c +++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c @@ -5,6 +5,7 @@ * */ +#include <drm/drm_blend.h> #include <drm/drm_print.h> #include "d71_dev.h" #include "malidp_io.h" diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h index 456f3c435719..7889e380ab23 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h @@ -10,6 +10,7 @@ #include <linux/list.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_device.h> #include <drm/drm_writeback.h> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c index e0b9f7063b20..dff22dec54b5 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c @@ -6,6 +6,7 @@ */ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_plane_helper.h> #include <drm/drm_print.h> #include "komeda_dev.h" diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c b/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c index ce4b760a691b..ebccb74306a7 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c @@ -4,6 +4,7 @@ * Author: James.Qian.Wang <james.qian.wang@arm.com> * */ +#include <drm/drm_framebuffer.h> #include "komeda_dev.h" #include "komeda_kms.h" diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c index 7adb065169e9..afc9cd856501 100644 --- a/drivers/gpu/drm/arm/hdlcd_crtc.c +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c @@ -20,6 +20,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_of.h> #include <drm/drm_plane_helper.h> diff --git a/drivers/gpu/drm/arm/malidp_crtc.c b/drivers/gpu/drm/arm/malidp_crtc.c index b5928b52e279..962730772b2f 100644 --- a/drivers/gpu/drm/arm/malidp_crtc.c +++ b/drivers/gpu/drm/arm/malidp_crtc.c @@ -14,6 +14,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_print.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/arm/malidp_mw.c b/drivers/gpu/drm/arm/malidp_mw.c index 204c869d9fe2..b66ca5b33a7f 100644 --- a/drivers/gpu/drm/arm/malidp_mw.c +++ b/drivers/gpu/drm/arm/malidp_mw.c @@ -9,8 +9,10 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> +#include <drm/drm_edid.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_writeback.h> diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 338cec4a3fff..8a9562642d16 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -11,9 +11,11 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_drv.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_plane_helper.h> diff --git a/drivers/gpu/drm/armada/armada_fb.h b/drivers/gpu/drm/armada/armada_fb.h index 7dda5f2a0af4..c5bc53d7e0c4 100644 --- a/drivers/gpu/drm/armada/armada_fb.h +++ b/drivers/gpu/drm/armada/armada_fb.h @@ -5,6 +5,8 @@ #ifndef ARMADA_FB_H #define ARMADA_FB_H +#include <drm/drm_framebuffer.h> + struct armada_framebuffer { struct drm_framebuffer fb; uint8_t fmt; diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c b/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c index 827e62c1daba..f3788d7d82d6 100644 --- a/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c +++ b/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c @@ -9,6 +9,7 @@ #include <drm/drm_device.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_panel.h> diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_out.c b/drivers/gpu/drm/aspeed/aspeed_gfx_out.c index 6759cb88415a..4f2187025a21 100644 --- a/drivers/gpu/drm/aspeed/aspeed_gfx_out.c +++ b/drivers/gpu/drm/aspeed/aspeed_gfx_out.c @@ -4,6 +4,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_connector.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_edid.h> #include <drm/drm_probe_helper.h> #include "aspeed_gfx.h" diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index db2010a55674..3eb9afecd9d4 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -36,6 +36,7 @@ #include <drm/drm_atomic_state_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_edid.h> #include <drm/drm_fourcc.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_framebuffer_helper.h> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c index a077d93c78d7..2306ceb3e999 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c @@ -11,8 +11,10 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_plane_helper.h> diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 1afe99dac0ff..57946d80b02d 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -385,6 +385,8 @@ source "drivers/gpu/drm/bridge/adv7511/Kconfig" source "drivers/gpu/drm/bridge/cadence/Kconfig" +source "drivers/gpu/drm/bridge/imx/Kconfig" + source "drivers/gpu/drm/bridge/synopsys/Kconfig" endmenu diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index 043b499545e3..1884803c6860 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -36,4 +36,5 @@ obj-$(CONFIG_DRM_ITE_IT66121) += ite-it66121.o obj-y += analogix/ obj-y += cadence/ +obj-y += imx/ obj-y += synopsys/ diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 01c8b80e34ec..8aadcc0aa90b 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -24,6 +24,7 @@ #include <drm/drm_bridge.h> #include <drm/drm_crtc.h> #include <drm/drm_device.h> +#include <drm/drm_edid.h> #include <drm/drm_panel.h> #include <drm/drm_print.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index f08f3307079e..3710fa9ee0ac 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -1623,14 +1623,14 @@ static int anx7625_parse_dt(struct device *dev, anx7625_get_swing_setting(dev, pdata); - pdata->is_dpi = 1; /* default dpi mode */ + pdata->is_dpi = 0; /* default dsi mode */ pdata->mipi_host_node = of_graph_get_remote_node(np, 0, 0); if (!pdata->mipi_host_node) { DRM_DEV_ERROR(dev, "fail to get internal panel.\n"); return -ENODEV; } - bus_type = V4L2_FWNODE_BUS_TYPE_PARALLEL; + bus_type = 0; mipi_lanes = MAX_LANES_SUPPORT; ep0 = of_graph_get_endpoint_by_regs(np, 0, 0); if (ep0) { @@ -1641,8 +1641,8 @@ static int anx7625_parse_dt(struct device *dev, of_node_put(ep0); } - if (bus_type == V4L2_FWNODE_BUS_TYPE_PARALLEL) /* bus type is Parallel(DSI) */ - pdata->is_dpi = 0; + if (bus_type == V4L2_FWNODE_BUS_TYPE_DPI) /* bus type is DPI */ + pdata->is_dpi = 1; pdata->mipi_lanes = MAX_LANES_SUPPORT; if (mipi_lanes > 0) diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c index 67f0f444b4e8..ba5f695703dc 100644 --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c @@ -43,6 +43,7 @@ #include <drm/drm_bridge.h> #include <drm/drm_connector.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_edid.h> #include <drm/drm_modeset_helper_vtables.h> #include <drm/drm_print.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/bridge/imx/Kconfig b/drivers/gpu/drm/bridge/imx/Kconfig new file mode 100644 index 000000000000..212a7b0e64fd --- /dev/null +++ b/drivers/gpu/drm/bridge/imx/Kconfig @@ -0,0 +1,43 @@ +config DRM_IMX8QM_LDB + tristate "Freescale i.MX8QM LVDS display bridge" + depends on OF + depends on COMMON_CLK + select DRM_KMS_HELPER + help + Choose this to enable the internal LVDS Display Bridge(LDB) found in + Freescale i.MX8qm processor. Official name of LDB is pixel mapper. + +config DRM_IMX8QXP_LDB + tristate "Freescale i.MX8QXP LVDS display bridge" + depends on OF + depends on COMMON_CLK + select DRM_KMS_HELPER + help + Choose this to enable the internal LVDS Display Bridge(LDB) found in + Freescale i.MX8qxp processor. Official name of LDB is pixel mapper. + +config DRM_IMX8QXP_PIXEL_COMBINER + tristate "Freescale i.MX8QM/QXP pixel combiner" + depends on OF + depends on COMMON_CLK + select DRM_KMS_HELPER + help + Choose this to enable pixel combiner found in + Freescale i.MX8qm/qxp processors. + +config DRM_IMX8QXP_PIXEL_LINK + tristate "Freescale i.MX8QM/QXP display pixel link" + depends on OF + depends on IMX_SCU + select DRM_KMS_HELPER + help + Choose this to enable display pixel link found in + Freescale i.MX8qm/qxp processors. + +config DRM_IMX8QXP_PIXEL_LINK_TO_DPI + tristate "Freescale i.MX8QXP pixel link to display pixel interface" + depends on OF + select DRM_KMS_HELPER + help + Choose this to enable pixel link to display pixel interface(PXL2DPI) + found in Freescale i.MX8qxp processor. diff --git a/drivers/gpu/drm/bridge/imx/Makefile b/drivers/gpu/drm/bridge/imx/Makefile new file mode 100644 index 000000000000..aa90ec8d5433 --- /dev/null +++ b/drivers/gpu/drm/bridge/imx/Makefile @@ -0,0 +1,9 @@ +imx8qm-ldb-objs := imx-ldb-helper.o imx8qm-ldb-drv.o +obj-$(CONFIG_DRM_IMX8QM_LDB) += imx8qm-ldb.o + +imx8qxp-ldb-objs := imx-ldb-helper.o imx8qxp-ldb-drv.o +obj-$(CONFIG_DRM_IMX8QXP_LDB) += imx8qxp-ldb.o + +obj-$(CONFIG_DRM_IMX8QXP_PIXEL_COMBINER) += imx8qxp-pixel-combiner.o +obj-$(CONFIG_DRM_IMX8QXP_PIXEL_LINK) += imx8qxp-pixel-link.o +obj-$(CONFIG_DRM_IMX8QXP_PIXEL_LINK_TO_DPI) += imx8qxp-pxl2dpi.o diff --git a/drivers/gpu/drm/bridge/imx/imx-ldb-helper.c b/drivers/gpu/drm/bridge/imx/imx-ldb-helper.c new file mode 100644 index 000000000000..e85eb9ab5947 --- /dev/null +++ b/drivers/gpu/drm/bridge/imx/imx-ldb-helper.c @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2012 Sascha Hauer, Pengutronix + * Copyright 2019,2020,2022 NXP + */ + +#include <linux/mfd/syscon.h> +#include <linux/of.h> +#include <linux/regmap.h> + +#include <drm/drm_bridge.h> +#include <drm/drm_of.h> +#include <drm/drm_print.h> + +#include "imx-ldb-helper.h" + +bool ldb_channel_is_single_link(struct ldb_channel *ldb_ch) +{ + return ldb_ch->link_type == LDB_CH_SINGLE_LINK; +} + +bool ldb_channel_is_split_link(struct ldb_channel *ldb_ch) +{ + return ldb_ch->link_type == LDB_CH_DUAL_LINK_EVEN_ODD_PIXELS || + ldb_ch->link_type == LDB_CH_DUAL_LINK_ODD_EVEN_PIXELS; +} + +int ldb_bridge_atomic_check_helper(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct ldb_channel *ldb_ch = bridge->driver_private; + + ldb_ch->in_bus_format = bridge_state->input_bus_cfg.format; + ldb_ch->out_bus_format = bridge_state->output_bus_cfg.format; + + return 0; +} + +void ldb_bridge_mode_set_helper(struct drm_bridge *bridge, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) +{ + struct ldb_channel *ldb_ch = bridge->driver_private; + struct ldb *ldb = ldb_ch->ldb; + bool is_split = ldb_channel_is_split_link(ldb_ch); + + if (is_split) + ldb->ldb_ctrl |= LDB_SPLIT_MODE_EN; + + switch (ldb_ch->out_bus_format) { + case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: + break; + case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: + if (ldb_ch->chno == 0 || is_split) + ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24; + if (ldb_ch->chno == 1 || is_split) + ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24; + break; + case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: + if (ldb_ch->chno == 0 || is_split) + ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24 | + LDB_BIT_MAP_CH0_JEIDA; + if (ldb_ch->chno == 1 || is_split) + ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24 | + LDB_BIT_MAP_CH1_JEIDA; + break; + } +} + +void ldb_bridge_enable_helper(struct drm_bridge *bridge) +{ + struct ldb_channel *ldb_ch = bridge->driver_private; + struct ldb *ldb = ldb_ch->ldb; + + /* + * Platform specific bridge drivers should set ldb_ctrl properly + * for the enablement, so just write the ctrl_reg here. + */ + regmap_write(ldb->regmap, ldb->ctrl_reg, ldb->ldb_ctrl); +} + +void ldb_bridge_disable_helper(struct drm_bridge *bridge) +{ + struct ldb_channel *ldb_ch = bridge->driver_private; + struct ldb *ldb = ldb_ch->ldb; + bool is_split = ldb_channel_is_split_link(ldb_ch); + + if (ldb_ch->chno == 0 || is_split) + ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK; + if (ldb_ch->chno == 1 || is_split) + ldb->ldb_ctrl &= ~LDB_CH1_MODE_EN_MASK; + + regmap_write(ldb->regmap, ldb->ctrl_reg, ldb->ldb_ctrl); +} + +int ldb_bridge_attach_helper(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) +{ + struct ldb_channel *ldb_ch = bridge->driver_private; + struct ldb *ldb = ldb_ch->ldb; + + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) { + DRM_DEV_ERROR(ldb->dev, + "do not support creating a drm_connector\n"); + return -EINVAL; + } + + if (!bridge->encoder) { + DRM_DEV_ERROR(ldb->dev, "missing encoder\n"); + return -ENODEV; + } + + return drm_bridge_attach(bridge->encoder, + ldb_ch->next_bridge, bridge, + DRM_BRIDGE_ATTACH_NO_CONNECTOR); +} + +int ldb_init_helper(struct ldb *ldb) +{ + struct device *dev = ldb->dev; + struct device_node *np = dev->of_node; + struct device_node *child; + int ret; + u32 i; + + ldb->regmap = syscon_node_to_regmap(np->parent); + if (IS_ERR(ldb->regmap)) { + ret = PTR_ERR(ldb->regmap); + if (ret != -EPROBE_DEFER) + DRM_DEV_ERROR(dev, "failed to get regmap: %d\n", ret); + return ret; + } + + for_each_available_child_of_node(np, child) { + struct ldb_channel *ldb_ch; + + ret = of_property_read_u32(child, "reg", &i); + if (ret || i > MAX_LDB_CHAN_NUM - 1) { + ret = -EINVAL; + DRM_DEV_ERROR(dev, + "invalid channel node address: %u\n", i); + of_node_put(child); + return ret; + } + + ldb_ch = ldb->channel[i]; + ldb_ch->ldb = ldb; + ldb_ch->chno = i; + ldb_ch->is_available = true; + ldb_ch->np = child; + + ldb->available_ch_cnt++; + } + + return 0; +} + +int ldb_find_next_bridge_helper(struct ldb *ldb) +{ + struct device *dev = ldb->dev; + struct ldb_channel *ldb_ch; + int ret, i; + + for (i = 0; i < MAX_LDB_CHAN_NUM; i++) { + ldb_ch = ldb->channel[i]; + + if (!ldb_ch->is_available) + continue; + + ldb_ch->next_bridge = devm_drm_of_get_bridge(dev, ldb_ch->np, + 1, 0); + if (IS_ERR(ldb_ch->next_bridge)) { + ret = PTR_ERR(ldb_ch->next_bridge); + if (ret != -EPROBE_DEFER) + DRM_DEV_ERROR(dev, + "failed to get next bridge: %d\n", + ret); + return ret; + } + } + + return 0; +} + +void ldb_add_bridge_helper(struct ldb *ldb, + const struct drm_bridge_funcs *bridge_funcs) +{ + struct ldb_channel *ldb_ch; + int i; + + for (i = 0; i < MAX_LDB_CHAN_NUM; i++) { + ldb_ch = ldb->channel[i]; + + if (!ldb_ch->is_available) + continue; + + ldb_ch->bridge.driver_private = ldb_ch; + ldb_ch->bridge.funcs = bridge_funcs; + ldb_ch->bridge.of_node = ldb_ch->np; + + drm_bridge_add(&ldb_ch->bridge); + } +} + +void ldb_remove_bridge_helper(struct ldb *ldb) +{ + struct ldb_channel *ldb_ch; + int i; + + for (i = 0; i < MAX_LDB_CHAN_NUM; i++) { + ldb_ch = ldb->channel[i]; + + if (!ldb_ch->is_available) + continue; + + drm_bridge_remove(&ldb_ch->bridge); + } +} diff --git a/drivers/gpu/drm/bridge/imx/imx-ldb-helper.h b/drivers/gpu/drm/bridge/imx/imx-ldb-helper.h new file mode 100644 index 000000000000..a0a5cde27fbc --- /dev/null +++ b/drivers/gpu/drm/bridge/imx/imx-ldb-helper.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +/* + * Copyright 2019,2020,2022 NXP + */ + +#ifndef __IMX_LDB_HELPER__ +#define __IMX_LDB_HELPER__ + +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/of.h> +#include <linux/regmap.h> + +#include <drm/drm_atomic.h> +#include <drm/drm_bridge.h> +#include <drm/drm_device.h> +#include <drm/drm_encoder.h> +#include <drm/drm_modeset_helper_vtables.h> + +#define LDB_CH0_MODE_EN_TO_DI0 BIT(0) +#define LDB_CH0_MODE_EN_TO_DI1 (3 << 0) +#define LDB_CH0_MODE_EN_MASK (3 << 0) +#define LDB_CH1_MODE_EN_TO_DI0 BIT(2) +#define LDB_CH1_MODE_EN_TO_DI1 (3 << 2) +#define LDB_CH1_MODE_EN_MASK (3 << 2) +#define LDB_SPLIT_MODE_EN BIT(4) +#define LDB_DATA_WIDTH_CH0_24 BIT(5) +#define LDB_BIT_MAP_CH0_JEIDA BIT(6) +#define LDB_DATA_WIDTH_CH1_24 BIT(7) +#define LDB_BIT_MAP_CH1_JEIDA BIT(8) +#define LDB_DI0_VS_POL_ACT_LOW BIT(9) +#define LDB_DI1_VS_POL_ACT_LOW BIT(10) + +#define MAX_LDB_CHAN_NUM 2 + +enum ldb_channel_link_type { + LDB_CH_SINGLE_LINK, + LDB_CH_DUAL_LINK_EVEN_ODD_PIXELS, + LDB_CH_DUAL_LINK_ODD_EVEN_PIXELS, +}; + +struct ldb; + +struct ldb_channel { + struct ldb *ldb; + struct drm_bridge bridge; + struct drm_bridge *next_bridge; + struct device_node *np; + u32 chno; + bool is_available; + u32 in_bus_format; + u32 out_bus_format; + enum ldb_channel_link_type link_type; +}; + +struct ldb { + struct regmap *regmap; + struct device *dev; + struct ldb_channel *channel[MAX_LDB_CHAN_NUM]; + unsigned int ctrl_reg; + u32 ldb_ctrl; + unsigned int available_ch_cnt; +}; + +#define bridge_to_ldb_ch(b) container_of(b, struct ldb_channel, bridge) + +bool ldb_channel_is_single_link(struct ldb_channel *ldb_ch); +bool ldb_channel_is_split_link(struct ldb_channel *ldb_ch); + +int ldb_bridge_atomic_check_helper(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state); + +void ldb_bridge_mode_set_helper(struct drm_bridge *bridge, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode); + +void ldb_bridge_enable_helper(struct drm_bridge *bridge); + +void ldb_bridge_disable_helper(struct drm_bridge *bridge); + +int ldb_bridge_attach_helper(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags); + +int ldb_init_helper(struct ldb *ldb); + +int ldb_find_next_bridge_helper(struct ldb *ldb); + +void ldb_add_bridge_helper(struct ldb *ldb, + const struct drm_bridge_funcs *bridge_funcs); + +void ldb_remove_bridge_helper(struct ldb *ldb); + +#endif /* __IMX_LDB_HELPER__ */ diff --git a/drivers/gpu/drm/bridge/imx/imx8qm-ldb-drv.c b/drivers/gpu/drm/bridge/imx/imx8qm-ldb-drv.c new file mode 100644 index 000000000000..29f8f36f814e --- /dev/null +++ b/drivers/gpu/drm/bridge/imx/imx8qm-ldb-drv.c @@ -0,0 +1,587 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/* + * Copyright 2020 NXP + */ + +#include <linux/clk.h> +#include <linux/mfd/syscon.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/of_graph.h> +#include <linux/phy/phy.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> + +#include <drm/drm_atomic_state_helper.h> +#include <drm/drm_bridge.h> +#include <drm/drm_connector.h> +#include <drm/drm_fourcc.h> +#include <drm/drm_of.h> +#include <drm/drm_print.h> + +#include "imx-ldb-helper.h" + +#define LDB_CH0_10BIT_EN BIT(22) +#define LDB_CH1_10BIT_EN BIT(23) +#define LDB_CH0_DATA_WIDTH_24BIT BIT(24) +#define LDB_CH1_DATA_WIDTH_24BIT BIT(26) +#define LDB_CH0_DATA_WIDTH_30BIT (2 << 24) +#define LDB_CH1_DATA_WIDTH_30BIT (2 << 26) + +#define SS_CTRL 0x20 +#define CH_HSYNC_M(id) BIT(0 + ((id) * 2)) +#define CH_VSYNC_M(id) BIT(1 + ((id) * 2)) +#define CH_PHSYNC(id) BIT(0 + ((id) * 2)) +#define CH_PVSYNC(id) BIT(1 + ((id) * 2)) + +#define DRIVER_NAME "imx8qm-ldb" + +struct imx8qm_ldb_channel { + struct ldb_channel base; + struct phy *phy; +}; + +struct imx8qm_ldb { + struct ldb base; + struct device *dev; + struct imx8qm_ldb_channel channel[MAX_LDB_CHAN_NUM]; + struct clk *clk_pixel; + struct clk *clk_bypass; + int active_chno; +}; + +static inline struct imx8qm_ldb_channel * +base_to_imx8qm_ldb_channel(struct ldb_channel *base) +{ + return container_of(base, struct imx8qm_ldb_channel, base); +} + +static inline struct imx8qm_ldb *base_to_imx8qm_ldb(struct ldb *base) +{ + return container_of(base, struct imx8qm_ldb, base); +} + +static void imx8qm_ldb_set_phy_cfg(struct imx8qm_ldb *imx8qm_ldb, + unsigned long di_clk, + bool is_split, bool is_slave, + struct phy_configure_opts_lvds *phy_cfg) +{ + phy_cfg->bits_per_lane_and_dclk_cycle = 7; + phy_cfg->lanes = 4; + phy_cfg->differential_clk_rate = is_split ? di_clk / 2 : di_clk; + phy_cfg->is_slave = is_slave; +} + +static int imx8qm_ldb_bridge_atomic_check(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct ldb_channel *ldb_ch = bridge->driver_private; + struct ldb *ldb = ldb_ch->ldb; + struct imx8qm_ldb_channel *imx8qm_ldb_ch = + base_to_imx8qm_ldb_channel(ldb_ch); + struct imx8qm_ldb *imx8qm_ldb = base_to_imx8qm_ldb(ldb); + struct drm_display_mode *adj = &crtc_state->adjusted_mode; + unsigned long di_clk = adj->clock * 1000; + bool is_split = ldb_channel_is_split_link(ldb_ch); + union phy_configure_opts opts = { }; + struct phy_configure_opts_lvds *phy_cfg = &opts.lvds; + int ret; + + ret = ldb_bridge_atomic_check_helper(bridge, bridge_state, + crtc_state, conn_state); + if (ret) + return ret; + + imx8qm_ldb_set_phy_cfg(imx8qm_ldb, di_clk, is_split, false, phy_cfg); + ret = phy_validate(imx8qm_ldb_ch->phy, PHY_MODE_LVDS, 0, &opts); + if (ret < 0) { + DRM_DEV_DEBUG_DRIVER(imx8qm_ldb->dev, + "failed to validate PHY: %d\n", ret); + return ret; + } + + if (is_split) { + imx8qm_ldb_ch = + &imx8qm_ldb->channel[imx8qm_ldb->active_chno ^ 1]; + imx8qm_ldb_set_phy_cfg(imx8qm_ldb, di_clk, is_split, true, + phy_cfg); + ret = phy_validate(imx8qm_ldb_ch->phy, PHY_MODE_LVDS, 0, &opts); + if (ret < 0) { + DRM_DEV_DEBUG_DRIVER(imx8qm_ldb->dev, + "failed to validate slave PHY: %d\n", + ret); + return ret; + } + } + + return ret; +} + +static void +imx8qm_ldb_bridge_mode_set(struct drm_bridge *bridge, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) +{ + struct ldb_channel *ldb_ch = bridge->driver_private; + struct ldb *ldb = ldb_ch->ldb; + struct imx8qm_ldb_channel *imx8qm_ldb_ch = + base_to_imx8qm_ldb_channel(ldb_ch); + struct imx8qm_ldb *imx8qm_ldb = base_to_imx8qm_ldb(ldb); + struct device *dev = imx8qm_ldb->dev; + unsigned long di_clk = adjusted_mode->clock * 1000; + bool is_split = ldb_channel_is_split_link(ldb_ch); + union phy_configure_opts opts = { }; + struct phy_configure_opts_lvds *phy_cfg = &opts.lvds; + u32 chno = ldb_ch->chno; + int ret; + + ret = pm_runtime_get_sync(dev); + if (ret < 0) + DRM_DEV_ERROR(dev, "failed to get runtime PM sync: %d\n", ret); + + ret = phy_init(imx8qm_ldb_ch->phy); + if (ret < 0) + DRM_DEV_ERROR(dev, "failed to initialize PHY: %d\n", ret); + + clk_set_rate(imx8qm_ldb->clk_bypass, di_clk); + clk_set_rate(imx8qm_ldb->clk_pixel, di_clk); + + imx8qm_ldb_set_phy_cfg(imx8qm_ldb, di_clk, is_split, false, phy_cfg); + ret = phy_configure(imx8qm_ldb_ch->phy, &opts); + if (ret < 0) + DRM_DEV_ERROR(dev, "failed to configure PHY: %d\n", ret); + + if (is_split) { + imx8qm_ldb_ch = + &imx8qm_ldb->channel[imx8qm_ldb->active_chno ^ 1]; + imx8qm_ldb_set_phy_cfg(imx8qm_ldb, di_clk, is_split, true, + phy_cfg); + ret = phy_configure(imx8qm_ldb_ch->phy, &opts); + if (ret < 0) + DRM_DEV_ERROR(dev, "failed to configure slave PHY: %d\n", + ret); + } + + /* input VSYNC signal from pixel link is active low */ + if (ldb_ch->chno == 0 || is_split) + ldb->ldb_ctrl |= LDB_DI0_VS_POL_ACT_LOW; + if (ldb_ch->chno == 1 || is_split) + ldb->ldb_ctrl |= LDB_DI1_VS_POL_ACT_LOW; + + switch (ldb_ch->out_bus_format) { + case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: + break; + case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: + case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: + if (ldb_ch->chno == 0 || is_split) + ldb->ldb_ctrl |= LDB_CH0_DATA_WIDTH_24BIT; + if (ldb_ch->chno == 1 || is_split) + ldb->ldb_ctrl |= LDB_CH1_DATA_WIDTH_24BIT; + break; + } + + ldb_bridge_mode_set_helper(bridge, mode, adjusted_mode); + + if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) + regmap_update_bits(ldb->regmap, SS_CTRL, CH_VSYNC_M(chno), 0); + else if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) + regmap_update_bits(ldb->regmap, SS_CTRL, + CH_VSYNC_M(chno), CH_PVSYNC(chno)); + + if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) + regmap_update_bits(ldb->regmap, SS_CTRL, CH_HSYNC_M(chno), 0); + else if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) + regmap_update_bits(ldb->regmap, SS_CTRL, + CH_HSYNC_M(chno), CH_PHSYNC(chno)); +} + +static void +imx8qm_ldb_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) +{ + struct ldb_channel *ldb_ch = bridge->driver_private; + struct ldb *ldb = ldb_ch->ldb; + struct imx8qm_ldb_channel *imx8qm_ldb_ch = + base_to_imx8qm_ldb_channel(ldb_ch); + struct imx8qm_ldb *imx8qm_ldb = base_to_imx8qm_ldb(ldb); + struct device *dev = imx8qm_ldb->dev; + bool is_split = ldb_channel_is_split_link(ldb_ch); + int ret; + + clk_prepare_enable(imx8qm_ldb->clk_pixel); + clk_prepare_enable(imx8qm_ldb->clk_bypass); + + /* both DI0 and DI1 connect with pixel link, so ok to use DI0 only */ + if (ldb_ch->chno == 0 || is_split) { + ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK; + ldb->ldb_ctrl |= LDB_CH0_MODE_EN_TO_DI0; + } + if (ldb_ch->chno == 1 || is_split) { + ldb->ldb_ctrl &= ~LDB_CH1_MODE_EN_MASK; + ldb->ldb_ctrl |= LDB_CH1_MODE_EN_TO_DI0; + } + + if (is_split) { + ret = phy_power_on(imx8qm_ldb->channel[0].phy); + if (ret) + DRM_DEV_ERROR(dev, + "failed to power on channel0 PHY: %d\n", + ret); + + ret = phy_power_on(imx8qm_ldb->channel[1].phy); + if (ret) + DRM_DEV_ERROR(dev, + "failed to power on channel1 PHY: %d\n", + ret); + } else { + ret = phy_power_on(imx8qm_ldb_ch->phy); + if (ret) + DRM_DEV_ERROR(dev, "failed to power on PHY: %d\n", ret); + } + + ldb_bridge_enable_helper(bridge); +} + +static void +imx8qm_ldb_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) +{ + struct ldb_channel *ldb_ch = bridge->driver_private; + struct ldb *ldb = ldb_ch->ldb; + struct imx8qm_ldb_channel *imx8qm_ldb_ch = + base_to_imx8qm_ldb_channel(ldb_ch); + struct imx8qm_ldb *imx8qm_ldb = base_to_imx8qm_ldb(ldb); + struct device *dev = imx8qm_ldb->dev; + bool is_split = ldb_channel_is_split_link(ldb_ch); + int ret; + + ldb_bridge_disable_helper(bridge); + + if (is_split) { + ret = phy_power_off(imx8qm_ldb->channel[0].phy); + if (ret) + DRM_DEV_ERROR(dev, + "failed to power off channel0 PHY: %d\n", + ret); + ret = phy_power_off(imx8qm_ldb->channel[1].phy); + if (ret) + DRM_DEV_ERROR(dev, + "failed to power off channel1 PHY: %d\n", + ret); + } else { + ret = phy_power_off(imx8qm_ldb_ch->phy); + if (ret) + DRM_DEV_ERROR(dev, "failed to power off PHY: %d\n", ret); + } + + clk_disable_unprepare(imx8qm_ldb->clk_bypass); + clk_disable_unprepare(imx8qm_ldb->clk_pixel); + + ret = pm_runtime_put(dev); + if (ret < 0) + DRM_DEV_ERROR(dev, "failed to put runtime PM: %d\n", ret); +} + +static const u32 imx8qm_ldb_bus_output_fmts[] = { + MEDIA_BUS_FMT_RGB666_1X7X3_SPWG, + MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, + MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA, + MEDIA_BUS_FMT_FIXED, +}; + +static bool imx8qm_ldb_bus_output_fmt_supported(u32 fmt) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(imx8qm_ldb_bus_output_fmts); i++) { + if (imx8qm_ldb_bus_output_fmts[i] == fmt) + return true; + } + + return false; +} + +static u32 * +imx8qm_ldb_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 drm_display_info *di; + const struct drm_format_info *finfo; + u32 *input_fmts; + + if (!imx8qm_ldb_bus_output_fmt_supported(output_fmt)) + return NULL; + + *num_input_fmts = 1; + + input_fmts = kmalloc(sizeof(*input_fmts), GFP_KERNEL); + if (!input_fmts) + return NULL; + + switch (output_fmt) { + case MEDIA_BUS_FMT_FIXED: + di = &conn_state->connector->display_info; + + /* + * Look at the first bus format to determine input format. + * Default to MEDIA_BUS_FMT_RGB888_1X36_CPADLO, if no match. + */ + if (di->num_bus_formats) { + finfo = drm_format_info(di->bus_formats[0]); + + input_fmts[0] = finfo->depth == 18 ? + MEDIA_BUS_FMT_RGB666_1X36_CPADLO : + MEDIA_BUS_FMT_RGB888_1X36_CPADLO; + } else { + input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X36_CPADLO; + } + break; + case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: + input_fmts[0] = MEDIA_BUS_FMT_RGB666_1X36_CPADLO; + break; + case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: + case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: + input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X36_CPADLO; + break; + default: + kfree(input_fmts); + input_fmts = NULL; + break; + } + + return input_fmts; +} + +static u32 * +imx8qm_ldb_bridge_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) +{ + *num_output_fmts = ARRAY_SIZE(imx8qm_ldb_bus_output_fmts); + return kmemdup(imx8qm_ldb_bus_output_fmts, + sizeof(imx8qm_ldb_bus_output_fmts), GFP_KERNEL); +} + +static enum drm_mode_status +imx8qm_ldb_bridge_mode_valid(struct drm_bridge *bridge, + const struct drm_display_info *info, + const struct drm_display_mode *mode) +{ + struct ldb_channel *ldb_ch = bridge->driver_private; + bool is_single = ldb_channel_is_single_link(ldb_ch); + + if (mode->clock > 300000) + return MODE_CLOCK_HIGH; + + if (mode->clock > 150000 && is_single) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +static const struct drm_bridge_funcs imx8qm_ldb_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, + .mode_valid = imx8qm_ldb_bridge_mode_valid, + .attach = ldb_bridge_attach_helper, + .atomic_check = imx8qm_ldb_bridge_atomic_check, + .mode_set = imx8qm_ldb_bridge_mode_set, + .atomic_enable = imx8qm_ldb_bridge_atomic_enable, + .atomic_disable = imx8qm_ldb_bridge_atomic_disable, + .atomic_get_input_bus_fmts = + imx8qm_ldb_bridge_atomic_get_input_bus_fmts, + .atomic_get_output_bus_fmts = + imx8qm_ldb_bridge_atomic_get_output_bus_fmts, +}; + +static int imx8qm_ldb_get_phy(struct imx8qm_ldb *imx8qm_ldb) +{ + struct imx8qm_ldb_channel *imx8qm_ldb_ch; + struct ldb_channel *ldb_ch; + struct device *dev = imx8qm_ldb->dev; + int i, ret; + + for (i = 0; i < MAX_LDB_CHAN_NUM; i++) { + imx8qm_ldb_ch = &imx8qm_ldb->channel[i]; + ldb_ch = &imx8qm_ldb_ch->base; + + if (!ldb_ch->is_available) + continue; + + imx8qm_ldb_ch->phy = devm_of_phy_get(dev, ldb_ch->np, + "lvds_phy"); + if (IS_ERR(imx8qm_ldb_ch->phy)) { + ret = PTR_ERR(imx8qm_ldb_ch->phy); + if (ret != -EPROBE_DEFER) + DRM_DEV_ERROR(dev, + "failed to get channel%d PHY: %d\n", + i, ret); + return ret; + } + } + + return 0; +} + +static int imx8qm_ldb_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct imx8qm_ldb *imx8qm_ldb; + struct imx8qm_ldb_channel *imx8qm_ldb_ch; + struct ldb *ldb; + struct ldb_channel *ldb_ch; + struct device_node *port1, *port2; + int pixel_order; + int ret, i; + + imx8qm_ldb = devm_kzalloc(dev, sizeof(*imx8qm_ldb), GFP_KERNEL); + if (!imx8qm_ldb) + return -ENOMEM; + + imx8qm_ldb->clk_pixel = devm_clk_get(dev, "pixel"); + if (IS_ERR(imx8qm_ldb->clk_pixel)) { + ret = PTR_ERR(imx8qm_ldb->clk_pixel); + if (ret != -EPROBE_DEFER) + DRM_DEV_ERROR(dev, + "failed to get pixel clock: %d\n", ret); + return ret; + } + + imx8qm_ldb->clk_bypass = devm_clk_get(dev, "bypass"); + if (IS_ERR(imx8qm_ldb->clk_bypass)) { + ret = PTR_ERR(imx8qm_ldb->clk_bypass); + if (ret != -EPROBE_DEFER) + DRM_DEV_ERROR(dev, + "failed to get bypass clock: %d\n", ret); + return ret; + } + + imx8qm_ldb->dev = dev; + + ldb = &imx8qm_ldb->base; + ldb->dev = dev; + ldb->ctrl_reg = 0xe0; + + for (i = 0; i < MAX_LDB_CHAN_NUM; i++) + ldb->channel[i] = &imx8qm_ldb->channel[i].base; + + ret = ldb_init_helper(ldb); + if (ret) + return ret; + + if (ldb->available_ch_cnt == 0) { + DRM_DEV_DEBUG_DRIVER(dev, "no available channel\n"); + return 0; + } + + if (ldb->available_ch_cnt == 2) { + port1 = of_graph_get_port_by_id(ldb->channel[0]->np, 1); + port2 = of_graph_get_port_by_id(ldb->channel[1]->np, 1); + pixel_order = + drm_of_lvds_get_dual_link_pixel_order(port1, port2); + of_node_put(port1); + of_node_put(port2); + + if (pixel_order != DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS) { + DRM_DEV_ERROR(dev, "invalid dual link pixel order: %d\n", + pixel_order); + return -EINVAL; + } + + imx8qm_ldb->active_chno = 0; + imx8qm_ldb_ch = &imx8qm_ldb->channel[0]; + ldb_ch = &imx8qm_ldb_ch->base; + ldb_ch->link_type = pixel_order; + } else { + for (i = 0; i < MAX_LDB_CHAN_NUM; i++) { + imx8qm_ldb_ch = &imx8qm_ldb->channel[i]; + ldb_ch = &imx8qm_ldb_ch->base; + + if (ldb_ch->is_available) { + imx8qm_ldb->active_chno = ldb_ch->chno; + break; + } + } + } + + ret = imx8qm_ldb_get_phy(imx8qm_ldb); + if (ret) + return ret; + + ret = ldb_find_next_bridge_helper(ldb); + if (ret) + return ret; + + platform_set_drvdata(pdev, imx8qm_ldb); + pm_runtime_enable(dev); + + ldb_add_bridge_helper(ldb, &imx8qm_ldb_bridge_funcs); + + return ret; +} + +static int imx8qm_ldb_remove(struct platform_device *pdev) +{ + struct imx8qm_ldb *imx8qm_ldb = platform_get_drvdata(pdev); + struct ldb *ldb = &imx8qm_ldb->base; + + ldb_remove_bridge_helper(ldb); + + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static int __maybe_unused imx8qm_ldb_runtime_suspend(struct device *dev) +{ + return 0; +} + +static int __maybe_unused imx8qm_ldb_runtime_resume(struct device *dev) +{ + struct imx8qm_ldb *imx8qm_ldb = dev_get_drvdata(dev); + struct ldb *ldb = &imx8qm_ldb->base; + + /* disable LDB by resetting the control register to POR default */ + regmap_write(ldb->regmap, ldb->ctrl_reg, 0); + + return 0; +} + +static const struct dev_pm_ops imx8qm_ldb_pm_ops = { + SET_RUNTIME_PM_OPS(imx8qm_ldb_runtime_suspend, + imx8qm_ldb_runtime_resume, NULL) +}; + +static const struct of_device_id imx8qm_ldb_dt_ids[] = { + { .compatible = "fsl,imx8qm-ldb" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, imx8qm_ldb_dt_ids); + +static struct platform_driver imx8qm_ldb_driver = { + .probe = imx8qm_ldb_probe, + .remove = imx8qm_ldb_remove, + .driver = { + .pm = &imx8qm_ldb_pm_ops, + .name = DRIVER_NAME, + .of_match_table = imx8qm_ldb_dt_ids, + }, +}; +module_platform_driver(imx8qm_ldb_driver); + +MODULE_DESCRIPTION("i.MX8QM LVDS Display Bridge(LDB)/Pixel Mapper bridge driver"); +MODULE_AUTHOR("Liu Ying <victor.liu@nxp.com>"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-ldb-drv.c b/drivers/gpu/drm/bridge/imx/imx8qxp-ldb-drv.c new file mode 100644 index 000000000000..1cca5fc96a4b --- /dev/null +++ b/drivers/gpu/drm/bridge/imx/imx8qxp-ldb-drv.c @@ -0,0 +1,722 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/* + * Copyright 2020 NXP + */ + +#include <linux/clk.h> +#include <linux/mfd/syscon.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/of_graph.h> +#include <linux/phy/phy.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> + +#include <drm/drm_atomic_state_helper.h> +#include <drm/drm_bridge.h> +#include <drm/drm_connector.h> +#include <drm/drm_fourcc.h> +#include <drm/drm_of.h> +#include <drm/drm_print.h> + +#include "imx-ldb-helper.h" + +#define LDB_CH_SEL BIT(28) + +#define SS_CTRL 0x20 +#define CH_HSYNC_M(id) BIT(0 + ((id) * 2)) +#define CH_VSYNC_M(id) BIT(1 + ((id) * 2)) +#define CH_PHSYNC(id) BIT(0 + ((id) * 2)) +#define CH_PVSYNC(id) BIT(1 + ((id) * 2)) + +#define DRIVER_NAME "imx8qxp-ldb" + +struct imx8qxp_ldb_channel { + struct ldb_channel base; + struct phy *phy; + unsigned int di_id; +}; + +struct imx8qxp_ldb { + struct ldb base; + struct device *dev; + struct imx8qxp_ldb_channel channel[MAX_LDB_CHAN_NUM]; + struct clk *clk_pixel; + struct clk *clk_bypass; + struct drm_bridge *companion; + int active_chno; +}; + +static inline struct imx8qxp_ldb_channel * +base_to_imx8qxp_ldb_channel(struct ldb_channel *base) +{ + return container_of(base, struct imx8qxp_ldb_channel, base); +} + +static inline struct imx8qxp_ldb *base_to_imx8qxp_ldb(struct ldb *base) +{ + return container_of(base, struct imx8qxp_ldb, base); +} + +static void imx8qxp_ldb_set_phy_cfg(struct imx8qxp_ldb *imx8qxp_ldb, + unsigned long di_clk, bool is_split, + struct phy_configure_opts_lvds *phy_cfg) +{ + phy_cfg->bits_per_lane_and_dclk_cycle = 7; + phy_cfg->lanes = 4; + + if (is_split) { + phy_cfg->differential_clk_rate = di_clk / 2; + phy_cfg->is_slave = !imx8qxp_ldb->companion; + } else { + phy_cfg->differential_clk_rate = di_clk; + phy_cfg->is_slave = false; + } +} + +static int +imx8qxp_ldb_bridge_atomic_check(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct ldb_channel *ldb_ch = bridge->driver_private; + struct ldb *ldb = ldb_ch->ldb; + struct imx8qxp_ldb_channel *imx8qxp_ldb_ch = + base_to_imx8qxp_ldb_channel(ldb_ch); + struct imx8qxp_ldb *imx8qxp_ldb = base_to_imx8qxp_ldb(ldb); + struct drm_bridge *companion = imx8qxp_ldb->companion; + struct drm_display_mode *adj = &crtc_state->adjusted_mode; + unsigned long di_clk = adj->clock * 1000; + bool is_split = ldb_channel_is_split_link(ldb_ch); + union phy_configure_opts opts = { }; + struct phy_configure_opts_lvds *phy_cfg = &opts.lvds; + int ret; + + ret = ldb_bridge_atomic_check_helper(bridge, bridge_state, + crtc_state, conn_state); + if (ret) + return ret; + + imx8qxp_ldb_set_phy_cfg(imx8qxp_ldb, di_clk, is_split, phy_cfg); + ret = phy_validate(imx8qxp_ldb_ch->phy, PHY_MODE_LVDS, 0, &opts); + if (ret < 0) { + DRM_DEV_DEBUG_DRIVER(imx8qxp_ldb->dev, + "failed to validate PHY: %d\n", ret); + return ret; + } + + if (is_split && companion) { + ret = companion->funcs->atomic_check(companion, + bridge_state, crtc_state, conn_state); + if (ret) + return ret; + } + + return ret; +} + +static void +imx8qxp_ldb_bridge_mode_set(struct drm_bridge *bridge, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) +{ + struct ldb_channel *ldb_ch = bridge->driver_private; + struct ldb_channel *companion_ldb_ch; + struct ldb *ldb = ldb_ch->ldb; + struct imx8qxp_ldb_channel *imx8qxp_ldb_ch = + base_to_imx8qxp_ldb_channel(ldb_ch); + struct imx8qxp_ldb *imx8qxp_ldb = base_to_imx8qxp_ldb(ldb); + struct drm_bridge *companion = imx8qxp_ldb->companion; + struct device *dev = imx8qxp_ldb->dev; + unsigned long di_clk = adjusted_mode->clock * 1000; + bool is_split = ldb_channel_is_split_link(ldb_ch); + union phy_configure_opts opts = { }; + struct phy_configure_opts_lvds *phy_cfg = &opts.lvds; + u32 chno = ldb_ch->chno; + int ret; + + ret = pm_runtime_get_sync(dev); + if (ret < 0) + DRM_DEV_ERROR(dev, "failed to get runtime PM sync: %d\n", ret); + + ret = phy_init(imx8qxp_ldb_ch->phy); + if (ret < 0) + DRM_DEV_ERROR(dev, "failed to initialize PHY: %d\n", ret); + + ret = phy_set_mode(imx8qxp_ldb_ch->phy, PHY_MODE_LVDS); + if (ret < 0) + DRM_DEV_ERROR(dev, "failed to set PHY mode: %d\n", ret); + + if (is_split && companion) { + companion_ldb_ch = bridge_to_ldb_ch(companion); + + companion_ldb_ch->in_bus_format = ldb_ch->in_bus_format; + companion_ldb_ch->out_bus_format = ldb_ch->out_bus_format; + } + + clk_set_rate(imx8qxp_ldb->clk_bypass, di_clk); + clk_set_rate(imx8qxp_ldb->clk_pixel, di_clk); + + imx8qxp_ldb_set_phy_cfg(imx8qxp_ldb, di_clk, is_split, phy_cfg); + ret = phy_configure(imx8qxp_ldb_ch->phy, &opts); + if (ret < 0) + DRM_DEV_ERROR(dev, "failed to configure PHY: %d\n", ret); + + if (chno == 0) + ldb->ldb_ctrl &= ~LDB_CH_SEL; + else + ldb->ldb_ctrl |= LDB_CH_SEL; + + /* input VSYNC signal from pixel link is active low */ + if (imx8qxp_ldb_ch->di_id == 0) + ldb->ldb_ctrl |= LDB_DI0_VS_POL_ACT_LOW; + else + ldb->ldb_ctrl |= LDB_DI1_VS_POL_ACT_LOW; + + /* + * For split mode, settle input VSYNC signal polarity and + * channel selection down early. + */ + if (is_split) + regmap_write(ldb->regmap, ldb->ctrl_reg, ldb->ldb_ctrl); + + ldb_bridge_mode_set_helper(bridge, mode, adjusted_mode); + + if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) + regmap_update_bits(ldb->regmap, SS_CTRL, CH_VSYNC_M(chno), 0); + else if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) + regmap_update_bits(ldb->regmap, SS_CTRL, + CH_VSYNC_M(chno), CH_PVSYNC(chno)); + + if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) + regmap_update_bits(ldb->regmap, SS_CTRL, CH_HSYNC_M(chno), 0); + else if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) + regmap_update_bits(ldb->regmap, SS_CTRL, + CH_HSYNC_M(chno), CH_PHSYNC(chno)); + + if (is_split && companion) + companion->funcs->mode_set(companion, mode, adjusted_mode); +} + +static void +imx8qxp_ldb_bridge_atomic_pre_enable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) +{ + struct ldb_channel *ldb_ch = bridge->driver_private; + struct ldb *ldb = ldb_ch->ldb; + struct imx8qxp_ldb *imx8qxp_ldb = base_to_imx8qxp_ldb(ldb); + struct drm_bridge *companion = imx8qxp_ldb->companion; + bool is_split = ldb_channel_is_split_link(ldb_ch); + + clk_prepare_enable(imx8qxp_ldb->clk_pixel); + clk_prepare_enable(imx8qxp_ldb->clk_bypass); + + if (is_split && companion) + companion->funcs->atomic_pre_enable(companion, old_bridge_state); +} + +static void +imx8qxp_ldb_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) +{ + struct ldb_channel *ldb_ch = bridge->driver_private; + struct ldb *ldb = ldb_ch->ldb; + struct imx8qxp_ldb_channel *imx8qxp_ldb_ch = + base_to_imx8qxp_ldb_channel(ldb_ch); + struct imx8qxp_ldb *imx8qxp_ldb = base_to_imx8qxp_ldb(ldb); + struct drm_bridge *companion = imx8qxp_ldb->companion; + struct device *dev = imx8qxp_ldb->dev; + bool is_split = ldb_channel_is_split_link(ldb_ch); + int ret; + + if (ldb_ch->chno == 0 || is_split) { + ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK; + ldb->ldb_ctrl |= imx8qxp_ldb_ch->di_id == 0 ? + LDB_CH0_MODE_EN_TO_DI0 : LDB_CH0_MODE_EN_TO_DI1; + } + if (ldb_ch->chno == 1 || is_split) { + ldb->ldb_ctrl &= ~LDB_CH1_MODE_EN_MASK; + ldb->ldb_ctrl |= imx8qxp_ldb_ch->di_id == 0 ? + LDB_CH1_MODE_EN_TO_DI0 : LDB_CH1_MODE_EN_TO_DI1; + } + + ldb_bridge_enable_helper(bridge); + + ret = phy_power_on(imx8qxp_ldb_ch->phy); + if (ret) + DRM_DEV_ERROR(dev, "failed to power on PHY: %d\n", ret); + + if (is_split && companion) + companion->funcs->atomic_enable(companion, old_bridge_state); +} + +static void +imx8qxp_ldb_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) +{ + struct ldb_channel *ldb_ch = bridge->driver_private; + struct ldb *ldb = ldb_ch->ldb; + struct imx8qxp_ldb_channel *imx8qxp_ldb_ch = + base_to_imx8qxp_ldb_channel(ldb_ch); + struct imx8qxp_ldb *imx8qxp_ldb = base_to_imx8qxp_ldb(ldb); + struct drm_bridge *companion = imx8qxp_ldb->companion; + struct device *dev = imx8qxp_ldb->dev; + bool is_split = ldb_channel_is_split_link(ldb_ch); + int ret; + + ret = phy_power_off(imx8qxp_ldb_ch->phy); + if (ret) + DRM_DEV_ERROR(dev, "failed to power off PHY: %d\n", ret); + + ret = phy_exit(imx8qxp_ldb_ch->phy); + if (ret < 0) + DRM_DEV_ERROR(dev, "failed to teardown PHY: %d\n", ret); + + ldb_bridge_disable_helper(bridge); + + clk_disable_unprepare(imx8qxp_ldb->clk_bypass); + clk_disable_unprepare(imx8qxp_ldb->clk_pixel); + + if (is_split && companion) + companion->funcs->atomic_disable(companion, old_bridge_state); + + ret = pm_runtime_put(dev); + if (ret < 0) + DRM_DEV_ERROR(dev, "failed to put runtime PM: %d\n", ret); +} + +static const u32 imx8qxp_ldb_bus_output_fmts[] = { + MEDIA_BUS_FMT_RGB666_1X7X3_SPWG, + MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, + MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA, + MEDIA_BUS_FMT_FIXED, +}; + +static bool imx8qxp_ldb_bus_output_fmt_supported(u32 fmt) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(imx8qxp_ldb_bus_output_fmts); i++) { + if (imx8qxp_ldb_bus_output_fmts[i] == fmt) + return true; + } + + return false; +} + +static u32 * +imx8qxp_ldb_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 drm_display_info *di; + const struct drm_format_info *finfo; + u32 *input_fmts; + + if (!imx8qxp_ldb_bus_output_fmt_supported(output_fmt)) + return NULL; + + *num_input_fmts = 1; + + input_fmts = kmalloc(sizeof(*input_fmts), GFP_KERNEL); + if (!input_fmts) + return NULL; + + switch (output_fmt) { + case MEDIA_BUS_FMT_FIXED: + di = &conn_state->connector->display_info; + + /* + * Look at the first bus format to determine input format. + * Default to MEDIA_BUS_FMT_RGB888_1X24, if no match. + */ + if (di->num_bus_formats) { + finfo = drm_format_info(di->bus_formats[0]); + + input_fmts[0] = finfo->depth == 18 ? + MEDIA_BUS_FMT_RGB666_1X24_CPADHI : + MEDIA_BUS_FMT_RGB888_1X24; + } else { + input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24; + } + break; + case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: + input_fmts[0] = MEDIA_BUS_FMT_RGB666_1X24_CPADHI; + break; + case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: + case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: + input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24; + break; + default: + kfree(input_fmts); + input_fmts = NULL; + break; + } + + return input_fmts; +} + +static u32 * +imx8qxp_ldb_bridge_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) +{ + *num_output_fmts = ARRAY_SIZE(imx8qxp_ldb_bus_output_fmts); + return kmemdup(imx8qxp_ldb_bus_output_fmts, + sizeof(imx8qxp_ldb_bus_output_fmts), GFP_KERNEL); +} + +static enum drm_mode_status +imx8qxp_ldb_bridge_mode_valid(struct drm_bridge *bridge, + const struct drm_display_info *info, + const struct drm_display_mode *mode) +{ + struct ldb_channel *ldb_ch = bridge->driver_private; + bool is_single = ldb_channel_is_single_link(ldb_ch); + + if (mode->clock > 170000) + return MODE_CLOCK_HIGH; + + if (mode->clock > 150000 && is_single) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +static const struct drm_bridge_funcs imx8qxp_ldb_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, + .mode_valid = imx8qxp_ldb_bridge_mode_valid, + .attach = ldb_bridge_attach_helper, + .atomic_check = imx8qxp_ldb_bridge_atomic_check, + .mode_set = imx8qxp_ldb_bridge_mode_set, + .atomic_pre_enable = imx8qxp_ldb_bridge_atomic_pre_enable, + .atomic_enable = imx8qxp_ldb_bridge_atomic_enable, + .atomic_disable = imx8qxp_ldb_bridge_atomic_disable, + .atomic_get_input_bus_fmts = + imx8qxp_ldb_bridge_atomic_get_input_bus_fmts, + .atomic_get_output_bus_fmts = + imx8qxp_ldb_bridge_atomic_get_output_bus_fmts, +}; + +static int imx8qxp_ldb_set_di_id(struct imx8qxp_ldb *imx8qxp_ldb) +{ + struct imx8qxp_ldb_channel *imx8qxp_ldb_ch = + &imx8qxp_ldb->channel[imx8qxp_ldb->active_chno]; + struct ldb_channel *ldb_ch = &imx8qxp_ldb_ch->base; + struct device_node *ep, *remote; + struct device *dev = imx8qxp_ldb->dev; + struct of_endpoint endpoint; + int ret; + + ep = of_graph_get_endpoint_by_regs(ldb_ch->np, 0, -1); + if (!ep) { + DRM_DEV_ERROR(dev, "failed to get port0 endpoint\n"); + return -EINVAL; + } + + remote = of_graph_get_remote_endpoint(ep); + of_node_put(ep); + if (!remote) { + DRM_DEV_ERROR(dev, "failed to get port0 remote endpoint\n"); + return -EINVAL; + } + + ret = of_graph_parse_endpoint(remote, &endpoint); + of_node_put(remote); + if (ret) { + DRM_DEV_ERROR(dev, "failed to parse port0 remote endpoint: %d\n", + ret); + return ret; + } + + imx8qxp_ldb_ch->di_id = endpoint.id; + + return 0; +} + +static int +imx8qxp_ldb_check_chno_and_dual_link(struct ldb_channel *ldb_ch, int link) +{ + if ((link == DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS && ldb_ch->chno != 0) || + (link == DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS && ldb_ch->chno != 1)) + return -EINVAL; + + return 0; +} + +static int imx8qxp_ldb_parse_dt_companion(struct imx8qxp_ldb *imx8qxp_ldb) +{ + struct imx8qxp_ldb_channel *imx8qxp_ldb_ch = + &imx8qxp_ldb->channel[imx8qxp_ldb->active_chno]; + struct ldb_channel *ldb_ch = &imx8qxp_ldb_ch->base; + struct ldb_channel *companion_ldb_ch; + struct device_node *companion; + struct device_node *child; + struct device_node *companion_port = NULL; + struct device_node *port1, *port2; + struct device *dev = imx8qxp_ldb->dev; + const struct of_device_id *match; + u32 i; + int dual_link; + int ret; + + /* Locate the companion LDB for dual-link operation, if any. */ + companion = of_parse_phandle(dev->of_node, "fsl,companion-ldb", 0); + if (!companion) + return 0; + + if (!of_device_is_available(companion)) { + DRM_DEV_ERROR(dev, "companion LDB is not available\n"); + ret = -ENODEV; + goto out; + } + + /* + * Sanity check: the companion bridge must have the same compatible + * string. + */ + match = of_match_device(dev->driver->of_match_table, dev); + if (!of_device_is_compatible(companion, match->compatible)) { + DRM_DEV_ERROR(dev, "companion LDB is incompatible\n"); + ret = -ENXIO; + goto out; + } + + for_each_available_child_of_node(companion, child) { + ret = of_property_read_u32(child, "reg", &i); + if (ret || i > MAX_LDB_CHAN_NUM - 1) { + DRM_DEV_ERROR(dev, + "invalid channel node address: %u\n", i); + ret = -EINVAL; + of_node_put(child); + goto out; + } + + /* + * Channel numbers have to be different, because channel0 + * transmits odd pixels and channel1 transmits even pixels. + */ + if (i == (ldb_ch->chno ^ 0x1)) { + companion_port = child; + break; + } + } + + if (!companion_port) { + DRM_DEV_ERROR(dev, + "failed to find companion LDB channel port\n"); + ret = -EINVAL; + goto out; + } + + /* + * We need to work out if the sink is expecting us to function in + * dual-link mode. We do this by looking at the DT port nodes we are + * connected to. If they are marked as expecting odd pixels and + * even pixels than we need to enable LDB split mode. + */ + port1 = of_graph_get_port_by_id(ldb_ch->np, 1); + port2 = of_graph_get_port_by_id(companion_port, 1); + dual_link = drm_of_lvds_get_dual_link_pixel_order(port1, port2); + of_node_put(port1); + of_node_put(port2); + + switch (dual_link) { + case DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS: + ldb_ch->link_type = LDB_CH_DUAL_LINK_ODD_EVEN_PIXELS; + break; + case DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS: + ldb_ch->link_type = LDB_CH_DUAL_LINK_EVEN_ODD_PIXELS; + break; + default: + ret = dual_link; + DRM_DEV_ERROR(dev, + "failed to get dual link pixel order: %d\n", ret); + goto out; + } + + ret = imx8qxp_ldb_check_chno_and_dual_link(ldb_ch, dual_link); + if (ret < 0) { + DRM_DEV_ERROR(dev, + "unmatched channel number(%u) vs dual link(%d)\n", + ldb_ch->chno, dual_link); + goto out; + } + + imx8qxp_ldb->companion = of_drm_find_bridge(companion_port); + if (!imx8qxp_ldb->companion) { + ret = -EPROBE_DEFER; + DRM_DEV_DEBUG_DRIVER(dev, + "failed to find bridge for companion bridge: %d\n", + ret); + goto out; + } + + DRM_DEV_DEBUG_DRIVER(dev, + "dual-link configuration detected (companion bridge %pOF)\n", + companion); + + companion_ldb_ch = bridge_to_ldb_ch(imx8qxp_ldb->companion); + companion_ldb_ch->link_type = ldb_ch->link_type; +out: + of_node_put(companion_port); + of_node_put(companion); + return ret; +} + +static int imx8qxp_ldb_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct imx8qxp_ldb *imx8qxp_ldb; + struct imx8qxp_ldb_channel *imx8qxp_ldb_ch; + struct ldb *ldb; + struct ldb_channel *ldb_ch; + int ret, i; + + imx8qxp_ldb = devm_kzalloc(dev, sizeof(*imx8qxp_ldb), GFP_KERNEL); + if (!imx8qxp_ldb) + return -ENOMEM; + + imx8qxp_ldb->clk_pixel = devm_clk_get(dev, "pixel"); + if (IS_ERR(imx8qxp_ldb->clk_pixel)) { + ret = PTR_ERR(imx8qxp_ldb->clk_pixel); + if (ret != -EPROBE_DEFER) + DRM_DEV_ERROR(dev, + "failed to get pixel clock: %d\n", ret); + return ret; + } + + imx8qxp_ldb->clk_bypass = devm_clk_get(dev, "bypass"); + if (IS_ERR(imx8qxp_ldb->clk_bypass)) { + ret = PTR_ERR(imx8qxp_ldb->clk_bypass); + if (ret != -EPROBE_DEFER) + DRM_DEV_ERROR(dev, + "failed to get bypass clock: %d\n", ret); + return ret; + } + + imx8qxp_ldb->dev = dev; + + ldb = &imx8qxp_ldb->base; + ldb->dev = dev; + ldb->ctrl_reg = 0xe0; + + for (i = 0; i < MAX_LDB_CHAN_NUM; i++) + ldb->channel[i] = &imx8qxp_ldb->channel[i].base; + + ret = ldb_init_helper(ldb); + if (ret) + return ret; + + if (ldb->available_ch_cnt == 0) { + DRM_DEV_DEBUG_DRIVER(dev, "no available channel\n"); + return 0; + } else if (ldb->available_ch_cnt > 1) { + DRM_DEV_ERROR(dev, "invalid available channel number(%u)\n", + ldb->available_ch_cnt); + return -EINVAL; + } + + for (i = 0; i < MAX_LDB_CHAN_NUM; i++) { + imx8qxp_ldb_ch = &imx8qxp_ldb->channel[i]; + ldb_ch = &imx8qxp_ldb_ch->base; + + if (ldb_ch->is_available) { + imx8qxp_ldb->active_chno = ldb_ch->chno; + break; + } + } + + imx8qxp_ldb_ch->phy = devm_of_phy_get(dev, ldb_ch->np, "lvds_phy"); + if (IS_ERR(imx8qxp_ldb_ch->phy)) { + ret = PTR_ERR(imx8qxp_ldb_ch->phy); + if (ret != -EPROBE_DEFER) + DRM_DEV_ERROR(dev, "failed to get channel%d PHY: %d\n", + imx8qxp_ldb->active_chno, ret); + return ret; + } + + ret = ldb_find_next_bridge_helper(ldb); + if (ret) + return ret; + + ret = imx8qxp_ldb_set_di_id(imx8qxp_ldb); + if (ret) + return ret; + + ret = imx8qxp_ldb_parse_dt_companion(imx8qxp_ldb); + if (ret) + return ret; + + platform_set_drvdata(pdev, imx8qxp_ldb); + pm_runtime_enable(dev); + + ldb_add_bridge_helper(ldb, &imx8qxp_ldb_bridge_funcs); + + return ret; +} + +static int imx8qxp_ldb_remove(struct platform_device *pdev) +{ + struct imx8qxp_ldb *imx8qxp_ldb = platform_get_drvdata(pdev); + struct ldb *ldb = &imx8qxp_ldb->base; + + ldb_remove_bridge_helper(ldb); + + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static int __maybe_unused imx8qxp_ldb_runtime_suspend(struct device *dev) +{ + return 0; +} + +static int __maybe_unused imx8qxp_ldb_runtime_resume(struct device *dev) +{ + struct imx8qxp_ldb *imx8qxp_ldb = dev_get_drvdata(dev); + struct ldb *ldb = &imx8qxp_ldb->base; + + /* disable LDB by resetting the control register to POR default */ + regmap_write(ldb->regmap, ldb->ctrl_reg, 0); + + return 0; +} + +static const struct dev_pm_ops imx8qxp_ldb_pm_ops = { + SET_RUNTIME_PM_OPS(imx8qxp_ldb_runtime_suspend, + imx8qxp_ldb_runtime_resume, NULL) +}; + +static const struct of_device_id imx8qxp_ldb_dt_ids[] = { + { .compatible = "fsl,imx8qxp-ldb" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, imx8qxp_ldb_dt_ids); + +static struct platform_driver imx8qxp_ldb_driver = { + .probe = imx8qxp_ldb_probe, + .remove = imx8qxp_ldb_remove, + .driver = { + .pm = &imx8qxp_ldb_pm_ops, + .name = DRIVER_NAME, + .of_match_table = imx8qxp_ldb_dt_ids, + }, +}; +module_platform_driver(imx8qxp_ldb_driver); + +MODULE_DESCRIPTION("i.MX8QXP LVDS Display Bridge(LDB)/Pixel Mapper bridge driver"); +MODULE_AUTHOR("Liu Ying <victor.liu@nxp.com>"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c new file mode 100644 index 000000000000..86ae98a211b4 --- /dev/null +++ b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c @@ -0,0 +1,448 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/* + * Copyright 2020 NXP + */ + +#include <linux/bitfield.h> +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_graph.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> + +#include <drm/drm_atomic_state_helper.h> +#include <drm/drm_bridge.h> +#include <drm/drm_print.h> + +#define PC_CTRL_REG 0x0 +#define PC_COMBINE_ENABLE BIT(0) +#define PC_DISP_BYPASS(n) BIT(1 + 21 * (n)) +#define PC_DISP_HSYNC_POLARITY(n) BIT(2 + 11 * (n)) +#define PC_DISP_HSYNC_POLARITY_POS(n) DISP_HSYNC_POLARITY(n) +#define PC_DISP_VSYNC_POLARITY(n) BIT(3 + 11 * (n)) +#define PC_DISP_VSYNC_POLARITY_POS(n) DISP_VSYNC_POLARITY(n) +#define PC_DISP_DVALID_POLARITY(n) BIT(4 + 11 * (n)) +#define PC_DISP_DVALID_POLARITY_POS(n) DISP_DVALID_POLARITY(n) +#define PC_VSYNC_MASK_ENABLE BIT(5) +#define PC_SKIP_MODE BIT(6) +#define PC_SKIP_NUMBER_MASK GENMASK(12, 7) +#define PC_SKIP_NUMBER(n) FIELD_PREP(PC_SKIP_NUMBER_MASK, (n)) +#define PC_DISP0_PIX_DATA_FORMAT_MASK GENMASK(18, 16) +#define PC_DISP0_PIX_DATA_FORMAT(fmt) \ + FIELD_PREP(PC_DISP0_PIX_DATA_FORMAT_MASK, (fmt)) +#define PC_DISP1_PIX_DATA_FORMAT_MASK GENMASK(21, 19) +#define PC_DISP1_PIX_DATA_FORMAT(fmt) \ + FIELD_PREP(PC_DISP1_PIX_DATA_FORMAT_MASK, (fmt)) + +#define PC_SW_RESET_REG 0x20 +#define PC_SW_RESET_N BIT(0) +#define PC_DISP_SW_RESET_N(n) BIT(1 + (n)) +#define PC_FULL_RESET_N (PC_SW_RESET_N | \ + PC_DISP_SW_RESET_N(0) | \ + PC_DISP_SW_RESET_N(1)) + +#define PC_REG_SET 0x4 +#define PC_REG_CLR 0x8 + +#define DRIVER_NAME "imx8qxp-pixel-combiner" + +enum imx8qxp_pc_pix_data_format { + RGB, + YUV444, + YUV422, + SPLIT_RGB, +}; + +struct imx8qxp_pc_channel { + struct drm_bridge bridge; + struct drm_bridge *next_bridge; + struct imx8qxp_pc *pc; + unsigned int stream_id; + bool is_available; +}; + +struct imx8qxp_pc { + struct device *dev; + struct imx8qxp_pc_channel ch[2]; + struct clk *clk_apb; + void __iomem *base; +}; + +static inline u32 imx8qxp_pc_read(struct imx8qxp_pc *pc, unsigned int offset) +{ + return readl(pc->base + offset); +} + +static inline void +imx8qxp_pc_write(struct imx8qxp_pc *pc, unsigned int offset, u32 value) +{ + writel(value, pc->base + offset); +} + +static inline void +imx8qxp_pc_write_set(struct imx8qxp_pc *pc, unsigned int offset, u32 value) +{ + imx8qxp_pc_write(pc, offset + PC_REG_SET, value); +} + +static inline void +imx8qxp_pc_write_clr(struct imx8qxp_pc *pc, unsigned int offset, u32 value) +{ + imx8qxp_pc_write(pc, offset + PC_REG_CLR, value); +} + +static enum drm_mode_status +imx8qxp_pc_bridge_mode_valid(struct drm_bridge *bridge, + const struct drm_display_info *info, + const struct drm_display_mode *mode) +{ + if (mode->hdisplay > 2560) + return MODE_BAD_HVALUE; + + return MODE_OK; +} + +static int imx8qxp_pc_bridge_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) +{ + struct imx8qxp_pc_channel *ch = bridge->driver_private; + struct imx8qxp_pc *pc = ch->pc; + + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) { + DRM_DEV_ERROR(pc->dev, + "do not support creating a drm_connector\n"); + return -EINVAL; + } + + if (!bridge->encoder) { + DRM_DEV_ERROR(pc->dev, "missing encoder\n"); + return -ENODEV; + } + + return drm_bridge_attach(bridge->encoder, + ch->next_bridge, bridge, + DRM_BRIDGE_ATTACH_NO_CONNECTOR); +} + +static void +imx8qxp_pc_bridge_mode_set(struct drm_bridge *bridge, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) +{ + struct imx8qxp_pc_channel *ch = bridge->driver_private; + struct imx8qxp_pc *pc = ch->pc; + u32 val; + int ret; + + ret = pm_runtime_get_sync(pc->dev); + if (ret < 0) + DRM_DEV_ERROR(pc->dev, + "failed to get runtime PM sync: %d\n", ret); + + ret = clk_prepare_enable(pc->clk_apb); + if (ret) + DRM_DEV_ERROR(pc->dev, "%s: failed to enable apb clock: %d\n", + __func__, ret); + + /* HSYNC to pixel link is active low. */ + imx8qxp_pc_write_clr(pc, PC_CTRL_REG, + PC_DISP_HSYNC_POLARITY(ch->stream_id)); + + /* VSYNC to pixel link is active low. */ + imx8qxp_pc_write_clr(pc, PC_CTRL_REG, + PC_DISP_VSYNC_POLARITY(ch->stream_id)); + + /* Data enable to pixel link is active high. */ + imx8qxp_pc_write_set(pc, PC_CTRL_REG, + PC_DISP_DVALID_POLARITY(ch->stream_id)); + + /* Mask the first frame output which may be incomplete. */ + imx8qxp_pc_write_set(pc, PC_CTRL_REG, PC_VSYNC_MASK_ENABLE); + + /* Only support RGB currently. */ + val = imx8qxp_pc_read(pc, PC_CTRL_REG); + if (ch->stream_id == 0) { + val &= ~PC_DISP0_PIX_DATA_FORMAT_MASK; + val |= PC_DISP0_PIX_DATA_FORMAT(RGB); + } else { + val &= ~PC_DISP1_PIX_DATA_FORMAT_MASK; + val |= PC_DISP1_PIX_DATA_FORMAT(RGB); + } + imx8qxp_pc_write(pc, PC_CTRL_REG, val); + + /* Only support bypass mode currently. */ + imx8qxp_pc_write_set(pc, PC_CTRL_REG, PC_DISP_BYPASS(ch->stream_id)); + + clk_disable_unprepare(pc->clk_apb); +} + +static void +imx8qxp_pc_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) +{ + struct imx8qxp_pc_channel *ch = bridge->driver_private; + struct imx8qxp_pc *pc = ch->pc; + int ret; + + ret = pm_runtime_put(pc->dev); + if (ret < 0) + DRM_DEV_ERROR(pc->dev, "failed to put runtime PM: %d\n", ret); +} + +static const u32 imx8qxp_pc_bus_output_fmts[] = { + MEDIA_BUS_FMT_RGB888_1X36_CPADLO, + MEDIA_BUS_FMT_RGB666_1X36_CPADLO, +}; + +static bool imx8qxp_pc_bus_output_fmt_supported(u32 fmt) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(imx8qxp_pc_bus_output_fmts); i++) { + if (imx8qxp_pc_bus_output_fmts[i] == fmt) + return true; + } + + return false; +} + +static u32 * +imx8qxp_pc_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) +{ + u32 *input_fmts; + + if (!imx8qxp_pc_bus_output_fmt_supported(output_fmt)) + return NULL; + + *num_input_fmts = 1; + + input_fmts = kmalloc(sizeof(*input_fmts), GFP_KERNEL); + if (!input_fmts) + return NULL; + + switch (output_fmt) { + case MEDIA_BUS_FMT_RGB888_1X36_CPADLO: + input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X30_CPADLO; + break; + case MEDIA_BUS_FMT_RGB666_1X36_CPADLO: + input_fmts[0] = MEDIA_BUS_FMT_RGB666_1X30_CPADLO; + break; + default: + kfree(input_fmts); + input_fmts = NULL; + break; + } + + return input_fmts; +} + +static u32 * +imx8qxp_pc_bridge_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) +{ + *num_output_fmts = ARRAY_SIZE(imx8qxp_pc_bus_output_fmts); + return kmemdup(imx8qxp_pc_bus_output_fmts, + sizeof(imx8qxp_pc_bus_output_fmts), GFP_KERNEL); +} + +static const struct drm_bridge_funcs imx8qxp_pc_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, + .mode_valid = imx8qxp_pc_bridge_mode_valid, + .attach = imx8qxp_pc_bridge_attach, + .mode_set = imx8qxp_pc_bridge_mode_set, + .atomic_disable = imx8qxp_pc_bridge_atomic_disable, + .atomic_get_input_bus_fmts = + imx8qxp_pc_bridge_atomic_get_input_bus_fmts, + .atomic_get_output_bus_fmts = + imx8qxp_pc_bridge_atomic_get_output_bus_fmts, +}; + +static int imx8qxp_pc_bridge_probe(struct platform_device *pdev) +{ + struct imx8qxp_pc *pc; + struct imx8qxp_pc_channel *ch; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct device_node *child, *remote; + u32 i; + int ret; + + pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL); + if (!pc) + return -ENOMEM; + + pc->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(pc->base)) + return PTR_ERR(pc->base); + + pc->dev = dev; + + pc->clk_apb = devm_clk_get(dev, "apb"); + if (IS_ERR(pc->clk_apb)) { + ret = PTR_ERR(pc->clk_apb); + if (ret != -EPROBE_DEFER) + DRM_DEV_ERROR(dev, "failed to get apb clock: %d\n", ret); + return ret; + } + + platform_set_drvdata(pdev, pc); + pm_runtime_enable(dev); + + for_each_available_child_of_node(np, child) { + ret = of_property_read_u32(child, "reg", &i); + if (ret || i > 1) { + ret = -EINVAL; + DRM_DEV_ERROR(dev, + "invalid channel(%u) node address\n", i); + goto free_child; + } + + ch = &pc->ch[i]; + ch->pc = pc; + ch->stream_id = i; + + remote = of_graph_get_remote_node(child, 1, 0); + if (!remote) { + ret = -ENODEV; + DRM_DEV_ERROR(dev, + "channel%u failed to get port1's remote node: %d\n", + i, ret); + goto free_child; + } + + ch->next_bridge = of_drm_find_bridge(remote); + if (!ch->next_bridge) { + of_node_put(remote); + ret = -EPROBE_DEFER; + DRM_DEV_DEBUG_DRIVER(dev, + "channel%u failed to find next bridge: %d\n", + i, ret); + goto free_child; + } + + of_node_put(remote); + + ch->bridge.driver_private = ch; + ch->bridge.funcs = &imx8qxp_pc_bridge_funcs; + ch->bridge.of_node = child; + ch->is_available = true; + + drm_bridge_add(&ch->bridge); + } + + return 0; + +free_child: + of_node_put(child); + + if (i == 1 && pc->ch[0].next_bridge) + drm_bridge_remove(&pc->ch[0].bridge); + + pm_runtime_disable(dev); + return ret; +} + +static int imx8qxp_pc_bridge_remove(struct platform_device *pdev) +{ + struct imx8qxp_pc *pc = platform_get_drvdata(pdev); + struct imx8qxp_pc_channel *ch; + int i; + + for (i = 0; i < 2; i++) { + ch = &pc->ch[i]; + + if (!ch->is_available) + continue; + + drm_bridge_remove(&ch->bridge); + ch->is_available = false; + } + + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static int __maybe_unused imx8qxp_pc_runtime_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct imx8qxp_pc *pc = platform_get_drvdata(pdev); + int ret; + + ret = clk_prepare_enable(pc->clk_apb); + if (ret) + DRM_DEV_ERROR(pc->dev, "%s: failed to enable apb clock: %d\n", + __func__, ret); + + /* Disable pixel combiner by full reset. */ + imx8qxp_pc_write_clr(pc, PC_SW_RESET_REG, PC_FULL_RESET_N); + + clk_disable_unprepare(pc->clk_apb); + + /* Ensure the reset takes effect. */ + usleep_range(10, 20); + + return ret; +} + +static int __maybe_unused imx8qxp_pc_runtime_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct imx8qxp_pc *pc = platform_get_drvdata(pdev); + int ret; + + ret = clk_prepare_enable(pc->clk_apb); + if (ret) { + DRM_DEV_ERROR(pc->dev, "%s: failed to enable apb clock: %d\n", + __func__, ret); + return ret; + } + + /* out of reset */ + imx8qxp_pc_write_set(pc, PC_SW_RESET_REG, PC_FULL_RESET_N); + + clk_disable_unprepare(pc->clk_apb); + + return ret; +} + +static const struct dev_pm_ops imx8qxp_pc_pm_ops = { + SET_RUNTIME_PM_OPS(imx8qxp_pc_runtime_suspend, + imx8qxp_pc_runtime_resume, NULL) +}; + +static const struct of_device_id imx8qxp_pc_dt_ids[] = { + { .compatible = "fsl,imx8qm-pixel-combiner", }, + { .compatible = "fsl,imx8qxp-pixel-combiner", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, imx8qxp_pc_dt_ids); + +static struct platform_driver imx8qxp_pc_bridge_driver = { + .probe = imx8qxp_pc_bridge_probe, + .remove = imx8qxp_pc_bridge_remove, + .driver = { + .pm = &imx8qxp_pc_pm_ops, + .name = DRIVER_NAME, + .of_match_table = imx8qxp_pc_dt_ids, + }, +}; +module_platform_driver(imx8qxp_pc_bridge_driver); + +MODULE_DESCRIPTION("i.MX8QM/QXP pixel combiner bridge driver"); +MODULE_AUTHOR("Liu Ying <victor.liu@nxp.com>"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c new file mode 100644 index 000000000000..305c833f11ee --- /dev/null +++ b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c @@ -0,0 +1,429 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/* + * Copyright 2020,2022 NXP + */ + +#include <linux/firmware/imx/svc/misc.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_graph.h> +#include <linux/platform_device.h> + +#include <drm/drm_atomic_state_helper.h> +#include <drm/drm_bridge.h> +#include <drm/drm_print.h> + +#include <dt-bindings/firmware/imx/rsrc.h> + +#define DRIVER_NAME "imx8qxp-display-pixel-link" +#define PL_MAX_MST_ADDR 3 +#define PL_MAX_NEXT_BRIDGES 2 + +struct imx8qxp_pixel_link { + struct drm_bridge bridge; + struct drm_bridge *next_bridge; + struct device *dev; + struct imx_sc_ipc *ipc_handle; + u8 stream_id; + u8 dc_id; + u32 sink_rsc; + u32 mst_addr; + u8 mst_addr_ctrl; + u8 mst_en_ctrl; + u8 mst_vld_ctrl; + u8 sync_ctrl; +}; + +static void imx8qxp_pixel_link_enable_mst_en(struct imx8qxp_pixel_link *pl) +{ + int ret; + + ret = imx_sc_misc_set_control(pl->ipc_handle, pl->sink_rsc, + pl->mst_en_ctrl, true); + if (ret) + DRM_DEV_ERROR(pl->dev, + "failed to enable DC%u stream%u pixel link mst_en: %d\n", + pl->dc_id, pl->stream_id, ret); +} + +static void imx8qxp_pixel_link_enable_mst_vld(struct imx8qxp_pixel_link *pl) +{ + int ret; + + ret = imx_sc_misc_set_control(pl->ipc_handle, pl->sink_rsc, + pl->mst_vld_ctrl, true); + if (ret) + DRM_DEV_ERROR(pl->dev, + "failed to enable DC%u stream%u pixel link mst_vld: %d\n", + pl->dc_id, pl->stream_id, ret); +} + +static void imx8qxp_pixel_link_enable_sync(struct imx8qxp_pixel_link *pl) +{ + int ret; + + ret = imx_sc_misc_set_control(pl->ipc_handle, pl->sink_rsc, + pl->sync_ctrl, true); + if (ret) + DRM_DEV_ERROR(pl->dev, + "failed to enable DC%u stream%u pixel link sync: %d\n", + pl->dc_id, pl->stream_id, ret); +} + +static int imx8qxp_pixel_link_disable_mst_en(struct imx8qxp_pixel_link *pl) +{ + int ret; + + ret = imx_sc_misc_set_control(pl->ipc_handle, pl->sink_rsc, + pl->mst_en_ctrl, false); + if (ret) + DRM_DEV_ERROR(pl->dev, + "failed to disable DC%u stream%u pixel link mst_en: %d\n", + pl->dc_id, pl->stream_id, ret); + + return ret; +} + +static int imx8qxp_pixel_link_disable_mst_vld(struct imx8qxp_pixel_link *pl) +{ + int ret; + + ret = imx_sc_misc_set_control(pl->ipc_handle, pl->sink_rsc, + pl->mst_vld_ctrl, false); + if (ret) + DRM_DEV_ERROR(pl->dev, + "failed to disable DC%u stream%u pixel link mst_vld: %d\n", + pl->dc_id, pl->stream_id, ret); + + return ret; +} + +static int imx8qxp_pixel_link_disable_sync(struct imx8qxp_pixel_link *pl) +{ + int ret; + + ret = imx_sc_misc_set_control(pl->ipc_handle, pl->sink_rsc, + pl->sync_ctrl, false); + if (ret) + DRM_DEV_ERROR(pl->dev, + "failed to disable DC%u stream%u pixel link sync: %d\n", + pl->dc_id, pl->stream_id, ret); + + return ret; +} + +static void imx8qxp_pixel_link_set_mst_addr(struct imx8qxp_pixel_link *pl) +{ + int ret; + + ret = imx_sc_misc_set_control(pl->ipc_handle, + pl->sink_rsc, pl->mst_addr_ctrl, + pl->mst_addr); + if (ret) + DRM_DEV_ERROR(pl->dev, + "failed to set DC%u stream%u pixel link mst addr(%u): %d\n", + pl->dc_id, pl->stream_id, pl->mst_addr, ret); +} + +static int imx8qxp_pixel_link_bridge_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) +{ + struct imx8qxp_pixel_link *pl = bridge->driver_private; + + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) { + DRM_DEV_ERROR(pl->dev, + "do not support creating a drm_connector\n"); + return -EINVAL; + } + + if (!bridge->encoder) { + DRM_DEV_ERROR(pl->dev, "missing encoder\n"); + return -ENODEV; + } + + return drm_bridge_attach(bridge->encoder, + pl->next_bridge, bridge, + DRM_BRIDGE_ATTACH_NO_CONNECTOR); +} + +static void +imx8qxp_pixel_link_bridge_mode_set(struct drm_bridge *bridge, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) +{ + struct imx8qxp_pixel_link *pl = bridge->driver_private; + + imx8qxp_pixel_link_set_mst_addr(pl); +} + +static void +imx8qxp_pixel_link_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) +{ + struct imx8qxp_pixel_link *pl = bridge->driver_private; + + imx8qxp_pixel_link_enable_mst_en(pl); + imx8qxp_pixel_link_enable_mst_vld(pl); + imx8qxp_pixel_link_enable_sync(pl); +} + +static void +imx8qxp_pixel_link_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) +{ + struct imx8qxp_pixel_link *pl = bridge->driver_private; + + imx8qxp_pixel_link_disable_mst_en(pl); + imx8qxp_pixel_link_disable_mst_vld(pl); + imx8qxp_pixel_link_disable_sync(pl); +} + +static const u32 imx8qxp_pixel_link_bus_output_fmts[] = { + MEDIA_BUS_FMT_RGB888_1X36_CPADLO, + MEDIA_BUS_FMT_RGB666_1X36_CPADLO, +}; + +static bool imx8qxp_pixel_link_bus_output_fmt_supported(u32 fmt) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(imx8qxp_pixel_link_bus_output_fmts); i++) { + if (imx8qxp_pixel_link_bus_output_fmts[i] == fmt) + return true; + } + + return false; +} + +static u32 * +imx8qxp_pixel_link_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) +{ + u32 *input_fmts; + + if (!imx8qxp_pixel_link_bus_output_fmt_supported(output_fmt)) + return NULL; + + *num_input_fmts = 1; + + input_fmts = kmalloc(sizeof(*input_fmts), GFP_KERNEL); + if (!input_fmts) + return NULL; + + input_fmts[0] = output_fmt; + + return input_fmts; +} + +static u32 * +imx8qxp_pixel_link_bridge_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) +{ + *num_output_fmts = ARRAY_SIZE(imx8qxp_pixel_link_bus_output_fmts); + return kmemdup(imx8qxp_pixel_link_bus_output_fmts, + sizeof(imx8qxp_pixel_link_bus_output_fmts), GFP_KERNEL); +} + +static const struct drm_bridge_funcs imx8qxp_pixel_link_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 = imx8qxp_pixel_link_bridge_attach, + .mode_set = imx8qxp_pixel_link_bridge_mode_set, + .atomic_enable = imx8qxp_pixel_link_bridge_atomic_enable, + .atomic_disable = imx8qxp_pixel_link_bridge_atomic_disable, + .atomic_get_input_bus_fmts = + imx8qxp_pixel_link_bridge_atomic_get_input_bus_fmts, + .atomic_get_output_bus_fmts = + imx8qxp_pixel_link_bridge_atomic_get_output_bus_fmts, +}; + +static int imx8qxp_pixel_link_disable_all_controls(struct imx8qxp_pixel_link *pl) +{ + int ret; + + ret = imx8qxp_pixel_link_disable_mst_en(pl); + if (ret) + return ret; + + ret = imx8qxp_pixel_link_disable_mst_vld(pl); + if (ret) + return ret; + + return imx8qxp_pixel_link_disable_sync(pl); +} + +static struct drm_bridge * +imx8qxp_pixel_link_find_next_bridge(struct imx8qxp_pixel_link *pl) +{ + struct device_node *np = pl->dev->of_node; + struct device_node *port, *remote; + struct drm_bridge *next_bridge[PL_MAX_NEXT_BRIDGES]; + u32 port_id; + bool found_port = false; + int reg, ep_cnt = 0; + /* select the first next bridge by default */ + int bridge_sel = 0; + + for (port_id = 1; port_id <= PL_MAX_MST_ADDR + 1; port_id++) { + port = of_graph_get_port_by_id(np, port_id); + if (!port) + continue; + + if (of_device_is_available(port)) { + found_port = true; + of_node_put(port); + break; + } + + of_node_put(port); + } + + if (!found_port) { + DRM_DEV_ERROR(pl->dev, "no available output port\n"); + return ERR_PTR(-ENODEV); + } + + for (reg = 0; reg < PL_MAX_NEXT_BRIDGES; reg++) { + remote = of_graph_get_remote_node(np, port_id, reg); + if (!remote) + continue; + + if (!of_device_is_available(remote->parent)) { + DRM_DEV_DEBUG(pl->dev, + "port%u endpoint%u remote parent is not available\n", + port_id, reg); + of_node_put(remote); + continue; + } + + next_bridge[ep_cnt] = of_drm_find_bridge(remote); + if (!next_bridge[ep_cnt]) { + of_node_put(remote); + return ERR_PTR(-EPROBE_DEFER); + } + + /* specially select the next bridge with companion PXL2DPI */ + if (of_find_property(remote, "fsl,companion-pxl2dpi", NULL)) + bridge_sel = ep_cnt; + + ep_cnt++; + + of_node_put(remote); + } + + pl->mst_addr = port_id - 1; + + return next_bridge[bridge_sel]; +} + +static int imx8qxp_pixel_link_bridge_probe(struct platform_device *pdev) +{ + struct imx8qxp_pixel_link *pl; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + int ret; + + pl = devm_kzalloc(dev, sizeof(*pl), GFP_KERNEL); + if (!pl) + return -ENOMEM; + + ret = imx_scu_get_handle(&pl->ipc_handle); + if (ret) { + if (ret != -EPROBE_DEFER) + DRM_DEV_ERROR(dev, "failed to get SCU ipc handle: %d\n", + ret); + return ret; + } + + ret = of_property_read_u8(np, "fsl,dc-id", &pl->dc_id); + if (ret) { + DRM_DEV_ERROR(dev, "failed to get DC index: %d\n", ret); + return ret; + } + + ret = of_property_read_u8(np, "fsl,dc-stream-id", &pl->stream_id); + if (ret) { + DRM_DEV_ERROR(dev, "failed to get DC stream index: %d\n", ret); + return ret; + } + + pl->dev = dev; + + pl->sink_rsc = pl->dc_id ? IMX_SC_R_DC_1 : IMX_SC_R_DC_0; + + if (pl->stream_id == 0) { + pl->mst_addr_ctrl = IMX_SC_C_PXL_LINK_MST1_ADDR; + pl->mst_en_ctrl = IMX_SC_C_PXL_LINK_MST1_ENB; + pl->mst_vld_ctrl = IMX_SC_C_PXL_LINK_MST1_VLD; + pl->sync_ctrl = IMX_SC_C_SYNC_CTRL0; + } else { + pl->mst_addr_ctrl = IMX_SC_C_PXL_LINK_MST2_ADDR; + pl->mst_en_ctrl = IMX_SC_C_PXL_LINK_MST2_ENB; + pl->mst_vld_ctrl = IMX_SC_C_PXL_LINK_MST2_VLD; + pl->sync_ctrl = IMX_SC_C_SYNC_CTRL1; + } + + /* disable all controls to POR default */ + ret = imx8qxp_pixel_link_disable_all_controls(pl); + if (ret) + return ret; + + pl->next_bridge = imx8qxp_pixel_link_find_next_bridge(pl); + if (IS_ERR(pl->next_bridge)) { + ret = PTR_ERR(pl->next_bridge); + if (ret != -EPROBE_DEFER) + DRM_DEV_ERROR(dev, "failed to find next bridge: %d\n", + ret); + return ret; + } + + platform_set_drvdata(pdev, pl); + + pl->bridge.driver_private = pl; + pl->bridge.funcs = &imx8qxp_pixel_link_bridge_funcs; + pl->bridge.of_node = np; + + drm_bridge_add(&pl->bridge); + + return ret; +} + +static int imx8qxp_pixel_link_bridge_remove(struct platform_device *pdev) +{ + struct imx8qxp_pixel_link *pl = platform_get_drvdata(pdev); + + drm_bridge_remove(&pl->bridge); + + return 0; +} + +static const struct of_device_id imx8qxp_pixel_link_dt_ids[] = { + { .compatible = "fsl,imx8qm-dc-pixel-link", }, + { .compatible = "fsl,imx8qxp-dc-pixel-link", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, imx8qxp_pixel_link_dt_ids); + +static struct platform_driver imx8qxp_pixel_link_bridge_driver = { + .probe = imx8qxp_pixel_link_bridge_probe, + .remove = imx8qxp_pixel_link_bridge_remove, + .driver = { + .of_match_table = imx8qxp_pixel_link_dt_ids, + .name = DRIVER_NAME, + }, +}; +module_platform_driver(imx8qxp_pixel_link_bridge_driver); + +MODULE_DESCRIPTION("i.MX8QXP/QM display pixel link bridge driver"); +MODULE_AUTHOR("Liu Ying <victor.liu@nxp.com>"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c b/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c new file mode 100644 index 000000000000..309f47a14cb6 --- /dev/null +++ b/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c @@ -0,0 +1,487 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/* + * Copyright 2020 NXP + */ + +#include <linux/firmware/imx/svc/misc.h> +#include <linux/mfd/syscon.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/of_graph.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> + +#include <drm/drm_atomic_state_helper.h> +#include <drm/drm_bridge.h> +#include <drm/drm_of.h> +#include <drm/drm_print.h> + +#include <dt-bindings/firmware/imx/rsrc.h> + +#define PXL2DPI_CTRL 0x40 +#define CFG1_16BIT 0x0 +#define CFG2_16BIT 0x1 +#define CFG3_16BIT 0x2 +#define CFG1_18BIT 0x3 +#define CFG2_18BIT 0x4 +#define CFG_24BIT 0x5 + +#define DRIVER_NAME "imx8qxp-pxl2dpi" + +struct imx8qxp_pxl2dpi { + struct regmap *regmap; + struct drm_bridge bridge; + struct drm_bridge *next_bridge; + struct drm_bridge *companion; + struct device *dev; + struct imx_sc_ipc *ipc_handle; + u32 sc_resource; + u32 in_bus_format; + u32 out_bus_format; + u32 pl_sel; +}; + +#define bridge_to_p2d(b) container_of(b, struct imx8qxp_pxl2dpi, bridge) + +static int imx8qxp_pxl2dpi_bridge_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) +{ + struct imx8qxp_pxl2dpi *p2d = bridge->driver_private; + + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) { + DRM_DEV_ERROR(p2d->dev, + "do not support creating a drm_connector\n"); + return -EINVAL; + } + + if (!bridge->encoder) { + DRM_DEV_ERROR(p2d->dev, "missing encoder\n"); + return -ENODEV; + } + + return drm_bridge_attach(bridge->encoder, + p2d->next_bridge, bridge, + DRM_BRIDGE_ATTACH_NO_CONNECTOR); +} + +static int +imx8qxp_pxl2dpi_bridge_atomic_check(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct imx8qxp_pxl2dpi *p2d = bridge->driver_private; + + p2d->in_bus_format = bridge_state->input_bus_cfg.format; + p2d->out_bus_format = bridge_state->output_bus_cfg.format; + + return 0; +} + +static void +imx8qxp_pxl2dpi_bridge_mode_set(struct drm_bridge *bridge, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) +{ + struct imx8qxp_pxl2dpi *p2d = bridge->driver_private; + struct imx8qxp_pxl2dpi *companion_p2d; + int ret; + + ret = pm_runtime_get_sync(p2d->dev); + if (ret < 0) + DRM_DEV_ERROR(p2d->dev, + "failed to get runtime PM sync: %d\n", ret); + + ret = imx_sc_misc_set_control(p2d->ipc_handle, p2d->sc_resource, + IMX_SC_C_PXL_LINK_SEL, p2d->pl_sel); + if (ret) + DRM_DEV_ERROR(p2d->dev, + "failed to set pixel link selection(%u): %d\n", + p2d->pl_sel, ret); + + switch (p2d->out_bus_format) { + case MEDIA_BUS_FMT_RGB888_1X24: + regmap_write(p2d->regmap, PXL2DPI_CTRL, CFG_24BIT); + break; + case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: + regmap_write(p2d->regmap, PXL2DPI_CTRL, CFG2_18BIT); + break; + default: + DRM_DEV_ERROR(p2d->dev, + "unsupported output bus format 0x%08x\n", + p2d->out_bus_format); + } + + if (p2d->companion) { + companion_p2d = bridge_to_p2d(p2d->companion); + + companion_p2d->in_bus_format = p2d->in_bus_format; + companion_p2d->out_bus_format = p2d->out_bus_format; + + p2d->companion->funcs->mode_set(p2d->companion, mode, + adjusted_mode); + } +} + +static void +imx8qxp_pxl2dpi_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) +{ + struct imx8qxp_pxl2dpi *p2d = bridge->driver_private; + int ret; + + ret = pm_runtime_put(p2d->dev); + if (ret < 0) + DRM_DEV_ERROR(p2d->dev, "failed to put runtime PM: %d\n", ret); + + if (p2d->companion) + p2d->companion->funcs->atomic_disable(p2d->companion, + old_bridge_state); +} + +static const u32 imx8qxp_pxl2dpi_bus_output_fmts[] = { + MEDIA_BUS_FMT_RGB888_1X24, + MEDIA_BUS_FMT_RGB666_1X24_CPADHI, +}; + +static bool imx8qxp_pxl2dpi_bus_output_fmt_supported(u32 fmt) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(imx8qxp_pxl2dpi_bus_output_fmts); i++) { + if (imx8qxp_pxl2dpi_bus_output_fmts[i] == fmt) + return true; + } + + return false; +} + +static u32 * +imx8qxp_pxl2dpi_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) +{ + u32 *input_fmts; + + if (!imx8qxp_pxl2dpi_bus_output_fmt_supported(output_fmt)) + return NULL; + + *num_input_fmts = 1; + + input_fmts = kmalloc(sizeof(*input_fmts), GFP_KERNEL); + if (!input_fmts) + return NULL; + + switch (output_fmt) { + case MEDIA_BUS_FMT_RGB888_1X24: + input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X36_CPADLO; + break; + case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: + input_fmts[0] = MEDIA_BUS_FMT_RGB666_1X36_CPADLO; + break; + default: + kfree(input_fmts); + input_fmts = NULL; + break; + } + + return input_fmts; +} + +static u32 * +imx8qxp_pxl2dpi_bridge_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) +{ + *num_output_fmts = ARRAY_SIZE(imx8qxp_pxl2dpi_bus_output_fmts); + return kmemdup(imx8qxp_pxl2dpi_bus_output_fmts, + sizeof(imx8qxp_pxl2dpi_bus_output_fmts), GFP_KERNEL); +} + +static const struct drm_bridge_funcs imx8qxp_pxl2dpi_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 = imx8qxp_pxl2dpi_bridge_attach, + .atomic_check = imx8qxp_pxl2dpi_bridge_atomic_check, + .mode_set = imx8qxp_pxl2dpi_bridge_mode_set, + .atomic_disable = imx8qxp_pxl2dpi_bridge_atomic_disable, + .atomic_get_input_bus_fmts = + imx8qxp_pxl2dpi_bridge_atomic_get_input_bus_fmts, + .atomic_get_output_bus_fmts = + imx8qxp_pxl2dpi_bridge_atomic_get_output_bus_fmts, +}; + +static struct device_node * +imx8qxp_pxl2dpi_get_available_ep_from_port(struct imx8qxp_pxl2dpi *p2d, + u32 port_id) +{ + struct device_node *port, *ep; + int ep_cnt; + + port = of_graph_get_port_by_id(p2d->dev->of_node, port_id); + if (!port) { + DRM_DEV_ERROR(p2d->dev, "failed to get port@%u\n", port_id); + return ERR_PTR(-ENODEV); + } + + ep_cnt = of_get_available_child_count(port); + if (ep_cnt == 0) { + DRM_DEV_ERROR(p2d->dev, "no available endpoints of port@%u\n", + port_id); + ep = ERR_PTR(-ENODEV); + goto out; + } else if (ep_cnt > 1) { + DRM_DEV_ERROR(p2d->dev, + "invalid available endpoints of port@%u\n", + port_id); + ep = ERR_PTR(-EINVAL); + goto out; + } + + ep = of_get_next_available_child(port, NULL); + if (!ep) { + DRM_DEV_ERROR(p2d->dev, + "failed to get available endpoint of port@%u\n", + port_id); + ep = ERR_PTR(-ENODEV); + goto out; + } +out: + of_node_put(port); + return ep; +} + +static struct drm_bridge * +imx8qxp_pxl2dpi_find_next_bridge(struct imx8qxp_pxl2dpi *p2d) +{ + struct device_node *ep, *remote; + struct drm_bridge *next_bridge; + int ret; + + ep = imx8qxp_pxl2dpi_get_available_ep_from_port(p2d, 1); + if (IS_ERR(ep)) { + ret = PTR_ERR(ep); + return ERR_PTR(ret); + } + + remote = of_graph_get_remote_port_parent(ep); + if (!remote || !of_device_is_available(remote)) { + DRM_DEV_ERROR(p2d->dev, "no available remote\n"); + next_bridge = ERR_PTR(-ENODEV); + goto out; + } else if (!of_device_is_available(remote->parent)) { + DRM_DEV_ERROR(p2d->dev, "remote parent is not available\n"); + next_bridge = ERR_PTR(-ENODEV); + goto out; + } + + next_bridge = of_drm_find_bridge(remote); + if (!next_bridge) { + next_bridge = ERR_PTR(-EPROBE_DEFER); + goto out; + } +out: + of_node_put(remote); + of_node_put(ep); + + return next_bridge; +} + +static int imx8qxp_pxl2dpi_set_pixel_link_sel(struct imx8qxp_pxl2dpi *p2d) +{ + struct device_node *ep; + struct of_endpoint endpoint; + int ret; + + ep = imx8qxp_pxl2dpi_get_available_ep_from_port(p2d, 0); + if (IS_ERR(ep)) + return PTR_ERR(ep); + + ret = of_graph_parse_endpoint(ep, &endpoint); + if (ret) { + DRM_DEV_ERROR(p2d->dev, + "failed to parse endpoint of port@0: %d\n", ret); + goto out; + } + + p2d->pl_sel = endpoint.id; +out: + of_node_put(ep); + + return ret; +} + +static int imx8qxp_pxl2dpi_parse_dt_companion(struct imx8qxp_pxl2dpi *p2d) +{ + struct imx8qxp_pxl2dpi *companion_p2d; + struct device *dev = p2d->dev; + struct device_node *companion; + struct device_node *port1, *port2; + const struct of_device_id *match; + int dual_link; + int ret = 0; + + /* Locate the companion PXL2DPI for dual-link operation, if any. */ + companion = of_parse_phandle(dev->of_node, "fsl,companion-pxl2dpi", 0); + if (!companion) + return 0; + + if (!of_device_is_available(companion)) { + DRM_DEV_ERROR(dev, "companion PXL2DPI is not available\n"); + ret = -ENODEV; + goto out; + } + + /* + * Sanity check: the companion bridge must have the same compatible + * string. + */ + match = of_match_device(dev->driver->of_match_table, dev); + if (!of_device_is_compatible(companion, match->compatible)) { + DRM_DEV_ERROR(dev, "companion PXL2DPI is incompatible\n"); + ret = -ENXIO; + goto out; + } + + p2d->companion = of_drm_find_bridge(companion); + if (!p2d->companion) { + ret = -EPROBE_DEFER; + DRM_DEV_DEBUG_DRIVER(p2d->dev, + "failed to find companion bridge: %d\n", + ret); + goto out; + } + + companion_p2d = bridge_to_p2d(p2d->companion); + + /* + * We need to work out if the sink is expecting us to function in + * dual-link mode. We do this by looking at the DT port nodes that + * the next bridges are connected to. If they are marked as expecting + * even pixels and odd pixels than we need to use the companion PXL2DPI. + */ + port1 = of_graph_get_port_by_id(p2d->next_bridge->of_node, 1); + port2 = of_graph_get_port_by_id(companion_p2d->next_bridge->of_node, 1); + dual_link = drm_of_lvds_get_dual_link_pixel_order(port1, port2); + of_node_put(port1); + of_node_put(port2); + + if (dual_link < 0) { + ret = dual_link; + DRM_DEV_ERROR(dev, "failed to get dual link pixel order: %d\n", + ret); + goto out; + } + + DRM_DEV_DEBUG_DRIVER(dev, + "dual-link configuration detected (companion bridge %pOF)\n", + companion); +out: + of_node_put(companion); + return ret; +} + +static int imx8qxp_pxl2dpi_bridge_probe(struct platform_device *pdev) +{ + struct imx8qxp_pxl2dpi *p2d; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + int ret; + + p2d = devm_kzalloc(dev, sizeof(*p2d), GFP_KERNEL); + if (!p2d) + return -ENOMEM; + + p2d->regmap = syscon_node_to_regmap(np->parent); + if (IS_ERR(p2d->regmap)) { + ret = PTR_ERR(p2d->regmap); + if (ret != -EPROBE_DEFER) + DRM_DEV_ERROR(dev, "failed to get regmap: %d\n", ret); + return ret; + } + + ret = imx_scu_get_handle(&p2d->ipc_handle); + if (ret) { + if (ret != -EPROBE_DEFER) + DRM_DEV_ERROR(dev, "failed to get SCU ipc handle: %d\n", + ret); + return ret; + } + + p2d->dev = dev; + + ret = of_property_read_u32(np, "fsl,sc-resource", &p2d->sc_resource); + if (ret) { + DRM_DEV_ERROR(dev, "failed to get SC resource %d\n", ret); + return ret; + } + + p2d->next_bridge = imx8qxp_pxl2dpi_find_next_bridge(p2d); + if (IS_ERR(p2d->next_bridge)) { + ret = PTR_ERR(p2d->next_bridge); + if (ret != -EPROBE_DEFER) + DRM_DEV_ERROR(dev, "failed to find next bridge: %d\n", + ret); + return ret; + } + + ret = imx8qxp_pxl2dpi_set_pixel_link_sel(p2d); + if (ret) + return ret; + + ret = imx8qxp_pxl2dpi_parse_dt_companion(p2d); + if (ret) + return ret; + + platform_set_drvdata(pdev, p2d); + pm_runtime_enable(dev); + + p2d->bridge.driver_private = p2d; + p2d->bridge.funcs = &imx8qxp_pxl2dpi_bridge_funcs; + p2d->bridge.of_node = np; + + drm_bridge_add(&p2d->bridge); + + return ret; +} + +static int imx8qxp_pxl2dpi_bridge_remove(struct platform_device *pdev) +{ + struct imx8qxp_pxl2dpi *p2d = platform_get_drvdata(pdev); + + drm_bridge_remove(&p2d->bridge); + + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static const struct of_device_id imx8qxp_pxl2dpi_dt_ids[] = { + { .compatible = "fsl,imx8qxp-pxl2dpi", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, imx8qxp_pxl2dpi_dt_ids); + +static struct platform_driver imx8qxp_pxl2dpi_bridge_driver = { + .probe = imx8qxp_pxl2dpi_bridge_probe, + .remove = imx8qxp_pxl2dpi_bridge_remove, + .driver = { + .of_match_table = imx8qxp_pxl2dpi_dt_ids, + .name = DRIVER_NAME, + }, +}; +module_platform_driver(imx8qxp_pxl2dpi_bridge_driver); + +MODULE_DESCRIPTION("i.MX8QXP pixel link to DPI bridge driver"); +MODULE_AUTHOR("Liu Ying <victor.liu@nxp.com>"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c index c92515834ff2..6a7a6983e796 100644 --- a/drivers/gpu/drm/bridge/lontium-lt8912b.c +++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c @@ -11,6 +11,7 @@ #include <drm/drm_probe_helper.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_edid.h> #include <drm/drm_mipi_dsi.h> #include <drm/drm_of.h> diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c index 0ee563eb2b6f..4277bf4f032b 100644 --- a/drivers/gpu/drm/bridge/panel.c +++ b/drivers/gpu/drm/bridge/panel.c @@ -171,6 +171,19 @@ static const struct drm_bridge_funcs panel_bridge_bridge_funcs = { }; /** + * drm_bridge_is_panel - Checks if a drm_bridge is a panel_bridge. + * + * @bridge: The drm_bridge to be checked. + * + * Returns true if the bridge is a panel bridge, or false otherwise. + */ +bool drm_bridge_is_panel(const struct drm_bridge *bridge) +{ + return bridge->funcs == &panel_bridge_bridge_funcs; +} +EXPORT_SYMBOL(drm_bridge_is_panel); + +/** * drm_panel_bridge_add - Creates a &drm_bridge and &drm_connector that * just calls the appropriate functions from &drm_panel. * @@ -269,6 +282,27 @@ void drm_panel_bridge_remove(struct drm_bridge *bridge) } EXPORT_SYMBOL(drm_panel_bridge_remove); +/** + * drm_panel_bridge_set_orientation - Set the connector's panel orientation + * from the bridge that can be transformed to panel bridge. + * + * @connector: The connector to be set panel orientation. + * @bridge: The drm_bridge to be transformed to panel bridge. + * + * Returns 0 on success, negative errno on failure. + */ +int drm_panel_bridge_set_orientation(struct drm_connector *connector, + struct drm_bridge *bridge) +{ + struct panel_bridge *panel_bridge; + + panel_bridge = drm_bridge_to_panel_bridge(bridge); + + return drm_connector_set_orientation_from_panel(connector, + panel_bridge->panel); +} +EXPORT_SYMBOL(drm_panel_bridge_set_orientation); + static void devm_drm_panel_bridge_release(struct device *dev, void *res) { struct drm_bridge **bridge = res; diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c index ff4227f6d800..31e88cb39f8a 100644 --- a/drivers/gpu/drm/bridge/parade-ps8640.c +++ b/drivers/gpu/drm/bridge/parade-ps8640.c @@ -16,6 +16,7 @@ #include <drm/display/drm_dp_aux_bus.h> #include <drm/display/drm_dp_helper.h> #include <drm/drm_bridge.h> +#include <drm/drm_edid.h> #include <drm/drm_mipi_dsi.h> #include <drm/drm_of.h> #include <drm/drm_panel.h> @@ -168,23 +169,35 @@ static bool ps8640_of_panel_on_aux_bus(struct device *dev) return true; } -static int ps8640_ensure_hpd(struct ps8640 *ps_bridge) +static int _ps8640_wait_hpd_asserted(struct ps8640 *ps_bridge, unsigned long wait_us) { struct regmap *map = ps_bridge->regmap[PAGE2_TOP_CNTL]; - struct device *dev = &ps_bridge->page[PAGE2_TOP_CNTL]->dev; int status; - int ret; /* * Apparently something about the firmware in the chip signals that * HPD goes high by reporting GPIO9 as high (even though HPD isn't * actually connected to GPIO9). */ - ret = regmap_read_poll_timeout(map, PAGE2_GPIO_H, status, - status & PS_GPIO9, 20 * 1000, 200 * 1000); + return regmap_read_poll_timeout(map, PAGE2_GPIO_H, status, + status & PS_GPIO9, wait_us / 10, wait_us); +} - if (ret < 0) - dev_warn(dev, "HPD didn't go high: %d\n", ret); +static int ps8640_wait_hpd_asserted(struct drm_dp_aux *aux, unsigned long wait_us) +{ + struct ps8640 *ps_bridge = aux_to_ps8640(aux); + struct device *dev = &ps_bridge->page[PAGE0_DP_CNTL]->dev; + int ret; + + /* + * Note that this function is called by code that has already powered + * the panel. We have to power ourselves up but we don't need to worry + * about powering the panel. + */ + pm_runtime_get_sync(dev); + ret = _ps8640_wait_hpd_asserted(ps_bridge, wait_us); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); return ret; } @@ -323,9 +336,7 @@ static ssize_t ps8640_aux_transfer(struct drm_dp_aux *aux, int ret; pm_runtime_get_sync(dev); - ret = ps8640_ensure_hpd(ps_bridge); - if (!ret) - ret = ps8640_aux_transfer_msg(aux, msg); + ret = ps8640_aux_transfer_msg(aux, msg); pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); @@ -369,8 +380,8 @@ static int __maybe_unused ps8640_resume(struct device *dev) * Mystery 200 ms delay for the "MCU to be ready". It's unclear if * this is truly necessary since the MCU will already signal that * things are "good to go" by signaling HPD on "gpio 9". See - * ps8640_ensure_hpd(). For now we'll keep this mystery delay just in - * case. + * _ps8640_wait_hpd_asserted(). For now we'll keep this mystery delay + * just in case. */ msleep(200); @@ -406,7 +417,9 @@ static void ps8640_pre_enable(struct drm_bridge *bridge) int ret; pm_runtime_get_sync(dev); - ps8640_ensure_hpd(ps_bridge); + ret = _ps8640_wait_hpd_asserted(ps_bridge, 200 * 1000); + if (ret < 0) + dev_warn(dev, "HPD didn't go high: %d\n", ret); /* * The Manufacturer Command Set (MCS) is a device dependent interface @@ -682,6 +695,7 @@ static int ps8640_probe(struct i2c_client *client) ps_bridge->aux.name = "parade-ps8640-aux"; ps_bridge->aux.dev = dev; ps_bridge->aux.transfer = ps8640_aux_transfer; + ps_bridge->aux.wait_hpd_asserted = ps8640_wait_hpd_asserted; drm_dp_aux_init(&ps_bridge->aux); pm_runtime_enable(dev); diff --git a/drivers/gpu/drm/bridge/simple-bridge.c b/drivers/gpu/drm/bridge/simple-bridge.c index d974282c12b2..2c5c5211bdab 100644 --- a/drivers/gpu/drm/bridge/simple-bridge.c +++ b/drivers/gpu/drm/bridge/simple-bridge.c @@ -15,6 +15,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> #include <drm/drm_crtc.h> +#include <drm/drm_edid.h> #include <drm/drm_print.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/bridge/tc358775.c b/drivers/gpu/drm/bridge/tc358775.c index e5d00a6e7880..7423b1b9d961 100644 --- a/drivers/gpu/drm/bridge/tc358775.c +++ b/drivers/gpu/drm/bridge/tc358775.c @@ -339,6 +339,7 @@ static void d2l_read(struct i2c_client *i2c, u16 addr, u32 *val) goto fail; pr_debug("d2l: I2C : addr:%04x value:%08x\n", addr, *val); + return; fail: dev_err(&i2c->dev, "Error %d reading from subaddress 0x%x\n", @@ -429,7 +430,7 @@ static void tc_bridge_enable(struct drm_bridge *bridge) val = TC358775_VPCTRL_MSF(1); dsiclk = mode->crtc_clock * 3 * tc->bpc / tc->num_dsi_lanes / 1000; - clkdiv = dsiclk / DIVIDE_BY_3 * tc->lvds_link; + clkdiv = dsiclk / (tc->lvds_link == DUAL_LINK ? DIVIDE_BY_6 : DIVIDE_BY_3); byteclk = dsiclk / 4; t1 = hactive * (tc->bpc * 3 / 8) / tc->num_dsi_lanes; t2 = ((100000 / clkdiv)) * (hactive + hback_porch + hsync_len + hfront_porch) / 1000; diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c index b27c0d7c451a..dc26640e7d9b 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c @@ -344,7 +344,7 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge, } /* Deassert reset */ - gpiod_set_value(ctx->enable_gpio, 1); + gpiod_set_value_cansleep(ctx->enable_gpio, 1); usleep_range(1000, 1100); /* Get the LVDS format from the bridge state. */ @@ -500,7 +500,7 @@ static void sn65dsi83_atomic_disable(struct drm_bridge *bridge, int ret; /* Put the chip in reset, pull EN line low, and assure 10ms reset low timing. */ - gpiod_set_value(ctx->enable_gpio, 0); + gpiod_set_value_cansleep(ctx->enable_gpio, 0); usleep_range(10000, 11000); ret = regulator_disable(ctx->vcc); @@ -677,7 +677,7 @@ static int sn65dsi83_probe(struct i2c_client *client, ctx->enable_gpio = devm_gpiod_get_optional(ctx->dev, "enable", GPIOD_OUT_LOW); if (IS_ERR(ctx->enable_gpio)) - return PTR_ERR(ctx->enable_gpio); + return dev_err_probe(dev, PTR_ERR(ctx->enable_gpio), "failed to get enable GPIO\n"); usleep_range(10000, 11000); @@ -687,7 +687,7 @@ static int sn65dsi83_probe(struct i2c_client *client, ctx->regmap = devm_regmap_init_i2c(client, &sn65dsi83_regmap_config); if (IS_ERR(ctx->regmap)) - return PTR_ERR(ctx->regmap); + return dev_err_probe(dev, PTR_ERR(ctx->regmap), "failed to get regmap\n"); dev_set_drvdata(dev, ctx); i2c_set_clientdata(client, ctx); diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c index 756b3e6e776b..4541126a45ea 100644 --- a/drivers/gpu/drm/bridge/ti-tfp410.c +++ b/drivers/gpu/drm/bridge/ti-tfp410.c @@ -14,6 +14,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> #include <drm/drm_crtc.h> +#include <drm/drm_edid.h> #include <drm/drm_print.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c index e7c22c2ca90c..0c765375640f 100644 --- a/drivers/gpu/drm/display/drm_dp_helper.c +++ b/drivers/gpu/drm/display/drm_dp_helper.c @@ -32,6 +32,7 @@ #include <drm/display/drm_dp_helper.h> #include <drm/display/drm_dp_mst_helper.h> +#include <drm/drm_edid.h> #include <drm/drm_print.h> #include <drm/drm_vblank.h> #include <drm/drm_panel.h> @@ -1597,7 +1598,7 @@ static int drm_dp_aux_reply_duration(const struct drm_dp_aux_msg *msg) * Calculate the length of the i2c transfer in usec, assuming * the i2c bus speed is as specified. Gives the the "worst" * case estimate, ie. successful while as long as possible. - * Doesn't account the the "MOT" bit, and instead assumes each + * Doesn't account the "MOT" bit, and instead assumes each * message includes a START, ADDRESS and STOP. Neither does it * account for additional random variables such as clock stretching. */ diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index 18f2b6075b78..57e65423e50d 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -42,6 +42,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> +#include <drm/drm_edid.h> #include <drm/drm_print.h> #include <drm/drm_probe_helper.h> @@ -2666,24 +2667,14 @@ static int drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *mg } list_for_each_entry(port, &mstb->ports, next) { - struct drm_dp_mst_branch *mstb_child = NULL; - - if (port->input || !port->ddps) + if (port->input || !port->ddps || !port->mstb) continue; - if (port->mstb) - mstb_child = drm_dp_mst_topology_get_mstb_validated( - mgr, port->mstb); - - if (mstb_child) { - ret = drm_dp_check_and_send_link_address(mgr, - mstb_child); - drm_dp_mst_topology_put_mstb(mstb_child); - if (ret == 1) - changed = true; - else if (ret < 0) - return ret; - } + ret = drm_dp_check_and_send_link_address(mgr, port->mstb); + if (ret == 1) + changed = true; + else if (ret < 0) + return ret; } return changed; @@ -5465,8 +5456,7 @@ EXPORT_SYMBOL(drm_dp_mst_topology_state_funcs); * * This function wraps drm_atomic_get_priv_obj_state() passing in the MST atomic * state vtable so that the private object state returned is that of a MST - * topology object. Also, drm_atomic_get_private_obj_state() expects the caller - * to care of the locking, so warn if don't hold the connection_mutex. + * topology object. * * RETURNS: * diff --git a/drivers/gpu/drm/drm_aperture.c b/drivers/gpu/drm/drm_aperture.c index 74bd4a76b253..059fd71424f6 100644 --- a/drivers/gpu/drm/drm_aperture.c +++ b/drivers/gpu/drm/drm_aperture.c @@ -329,7 +329,20 @@ int drm_aperture_remove_conflicting_pci_framebuffers(struct pci_dev *pdev, const struct drm_driver *req_driver) { resource_size_t base, size; - int bar, ret = 0; + int bar, ret; + + /* + * WARNING: Apparently we must kick fbdev drivers before vgacon, + * otherwise the vga fbdev driver falls over. + */ +#if IS_REACHABLE(CONFIG_FB) + ret = remove_conflicting_pci_framebuffers(pdev, req_driver->name); + if (ret) + return ret; +#endif + ret = vga_remove_vgacon(pdev); + if (ret) + return ret; for (bar = 0; bar < PCI_STD_NUM_BARS; ++bar) { if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) @@ -339,15 +352,6 @@ int drm_aperture_remove_conflicting_pci_framebuffers(struct pci_dev *pdev, drm_aperture_detach_drivers(base, size); } - /* - * WARNING: Apparently we must kick fbdev drivers before vgacon, - * otherwise the vga fbdev driver falls over. - */ -#if IS_REACHABLE(CONFIG_FB) - ret = remove_conflicting_pci_framebuffers(pdev, req_driver->name); -#endif - if (ret == 0) - ret = vga_remove_vgacon(pdev); - return ret; + return 0; } EXPORT_SYMBOL(drm_aperture_remove_conflicting_pci_framebuffers); diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 58c0283fb6b0..f197f59f6d99 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -31,12 +31,14 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_uapi.h> +#include <drm/drm_blend.h> #include <drm/drm_bridge.h> #include <drm/drm_debugfs.h> #include <drm/drm_device.h> #include <drm/drm_drv.h> #include <drm/drm_file.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_mode.h> #include <drm/drm_print.h> #include <drm/drm_writeback.h> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 987e4b212e9f..0f685f4b2911 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -31,10 +31,12 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_uapi.h> +#include <drm/drm_blend.h> #include <drm/drm_bridge.h> #include <drm/drm_damage_helper.h> #include <drm/drm_device.h> #include <drm/drm_drv.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_print.h> diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index 3b6d3bdbd099..bf31b9d92094 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -26,10 +26,12 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_state_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_bridge.h> #include <drm/drm_connector.h> #include <drm/drm_crtc.h> #include <drm/drm_device.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_plane.h> #include <drm/drm_print.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 434f3d4cb8a2..79730fa1dd8e 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -29,6 +29,7 @@ #include <drm/drm_atomic_uapi.h> #include <drm/drm_atomic.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_print.h> #include <drm/drm_drv.h> #include <drm/drm_writeback.h> diff --git a/drivers/gpu/drm/drm_bridge_connector.c b/drivers/gpu/drm/drm_bridge_connector.c index 6b3dad03d77d..1c7d936523df 100644 --- a/drivers/gpu/drm/drm_bridge_connector.c +++ b/drivers/gpu/drm/drm_bridge_connector.c @@ -331,7 +331,7 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm, struct drm_bridge_connector *bridge_connector; struct drm_connector *connector; struct i2c_adapter *ddc = NULL; - struct drm_bridge *bridge; + struct drm_bridge *bridge, *panel_bridge = NULL; int connector_type; bridge_connector = kzalloc(sizeof(*bridge_connector), GFP_KERNEL); @@ -373,6 +373,9 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm, if (bridge->ddc) ddc = bridge->ddc; + + if (drm_bridge_is_panel(bridge)) + panel_bridge = bridge; } if (connector_type == DRM_MODE_CONNECTOR_Unknown) { @@ -392,6 +395,9 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm, connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; + if (panel_bridge) + drm_panel_bridge_set_orientation(connector, panel_bridge); + return connector; } EXPORT_SYMBOL_GPL(drm_bridge_connector_init); diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c index 48e6ce16439f..bbc535cc50dd 100644 --- a/drivers/gpu/drm/drm_client_modeset.c +++ b/drivers/gpu/drm/drm_client_modeset.c @@ -19,6 +19,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_device.h> #include <drm/drm_drv.h> +#include <drm/drm_edid.h> #include <drm/drm_encoder.h> #include <drm/drm_print.h> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 1c48d162c77e..28ea0f8196b9 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -24,6 +24,7 @@ #include <drm/drm_connector.h> #include <drm/drm_edid.h> #include <drm/drm_encoder.h> +#include <drm/drm_panel.h> #include <drm/drm_utils.h> #include <drm/drm_print.h> #include <drm/drm_drv.h> @@ -2320,6 +2321,9 @@ EXPORT_SYMBOL(drm_connector_set_vrr_capable_property); * It is allowed to call this function with a panel_orientation of * DRM_MODE_PANEL_ORIENTATION_UNKNOWN, in which case it is a no-op. * + * The function shouldn't be called in panel after drm is registered (i.e. + * drm_dev_register() is called in drm). + * * Returns: * Zero on success, negative errno on failure. */ @@ -2389,6 +2393,33 @@ int drm_connector_set_panel_orientation_with_quirk( } EXPORT_SYMBOL(drm_connector_set_panel_orientation_with_quirk); +/** + * drm_connector_set_orientation_from_panel - + * set the connector's panel_orientation from panel's callback. + * @connector: connector for which to init the panel-orientation property. + * @panel: panel that can provide orientation information. + * + * Drm drivers should call this function before drm_dev_register(). + * Orientation is obtained from panel's .get_orientation() callback. + * + * Returns: + * Zero on success, negative errno on failure. + */ +int drm_connector_set_orientation_from_panel( + struct drm_connector *connector, + struct drm_panel *panel) +{ + enum drm_panel_orientation orientation; + + if (panel && panel->funcs && panel->funcs->get_orientation) + orientation = panel->funcs->get_orientation(panel); + else + orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; + + return drm_connector_set_panel_orientation(connector, orientation); +} +EXPORT_SYMBOL(drm_connector_set_orientation_from_panel); + static const struct drm_prop_enum_list privacy_screen_enum[] = { { PRIVACY_SCREEN_DISABLED, "Disabled" }, { PRIVACY_SCREEN_ENABLED, "Enabled" }, diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 26a77a735905..cad2a7e5166f 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -35,9 +35,11 @@ #include <linux/export.h> #include <linux/dma-fence.h> #include <linux/uaccess.h> +#include <drm/drm_blend.h> #include <drm/drm_crtc.h> #include <drm/drm_edid.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_managed.h> #include <drm/drm_modeset_lock.h> #include <drm/drm_atomic.h> diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index b632825654a9..8a6d54515f92 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -44,6 +44,7 @@ #include <drm/drm_encoder.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_plane_helper.h> #include <drm/drm_print.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/drm_damage_helper.c b/drivers/gpu/drm/drm_damage_helper.c index 8eeff0c7bdd4..937b699ac2a8 100644 --- a/drivers/gpu/drm/drm_damage_helper.c +++ b/drivers/gpu/drm/drm_damage_helper.c @@ -33,6 +33,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_damage_helper.h> #include <drm/drm_device.h> +#include <drm/drm_framebuffer.h> static void convert_clip_rect_to_rect(const struct drm_clip_rect *src, struct drm_mode_rect *dest, diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 5ad2b6a2778c..5e9c373e6b88 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -43,6 +43,7 @@ #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_print.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/drm_gem_atomic_helper.c b/drivers/gpu/drm/drm_gem_atomic_helper.c index f16d60217c6c..b6a0110eb64a 100644 --- a/drivers/gpu/drm/drm_gem_atomic_helper.c +++ b/drivers/gpu/drm/drm_gem_atomic_helper.c @@ -5,6 +5,7 @@ #include <drm/drm_atomic_state_helper.h> #include <drm/drm_atomic_uapi.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_framebuffer_helper.h> diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 51fcf1298023..8faad23dc1d8 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -83,7 +83,7 @@ * * 1. Directly call VERSION to get the version and to match against the driver * name returned by that ioctl. Note that SET_VERSION is not called, which - * means the the unique name for the master node just opening is _not_ filled + * means the unique name for the master node just opening is _not_ filled * out. This despite that with current drm device nodes are always bound to * one device, and can't be runtime assigned like with drm 1.0. * 2. Match driver name. If it mismatches, proceed to the next device node. diff --git a/drivers/gpu/drm/drm_kms_helper_common.c b/drivers/gpu/drm/drm_kms_helper_common.c index 8be20080cd8d..0bf0fc1abf54 100644 --- a/drivers/gpu/drm/drm_kms_helper_common.c +++ b/drivers/gpu/drm/drm_kms_helper_common.c @@ -27,6 +27,7 @@ #include <linux/module.h> +#include <drm/drm_edid.h> #include <drm/drm_print.h> #include "drm_crtc_helper_internal.h" diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c index 09e4edb5a992..0eda9dcb0e52 100644 --- a/drivers/gpu/drm/drm_mipi_dbi.c +++ b/drivers/gpu/drm/drm_mipi_dbi.c @@ -18,6 +18,7 @@ #include <drm/drm_file.h> #include <drm/drm_format_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_mipi_dbi.h> diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c index 37b4b9f0e468..59b34f07cfce 100644 --- a/drivers/gpu/drm/drm_mode_config.c +++ b/drivers/gpu/drm/drm_mode_config.c @@ -25,6 +25,7 @@ #include <drm/drm_drv.h> #include <drm/drm_encoder.h> #include <drm/drm_file.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_managed.h> #include <drm/drm_mode_config.h> #include <drm/drm_print.h> diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 40b7b245e98c..a2542254233e 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -41,6 +41,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_device.h> +#include <drm/drm_edid.h> #include <drm/drm_modes.h> #include <drm/drm_print.h> diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c index da483125e063..0f08319453b2 100644 --- a/drivers/gpu/drm/drm_modeset_helper.c +++ b/drivers/gpu/drm/drm_modeset_helper.c @@ -23,6 +23,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_modeset_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_print.h> diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index 4e853acfd1e8..1276edf0fc0d 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c @@ -187,7 +187,7 @@ static const struct dmi_system_id orientation_data[] = { }, .driver_data = (void *)&lcd800x1280_rightside_up, }, { /* - * GPD Pocket, note that the the DMI data is less generic then + * GPD Pocket, note that the DMI data is less generic then * it seems, devices with a board-vendor of "AMI Corporation" * are quite rare, as are devices which have both board- *and* * product-id set to "Default String" diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index e3f09f18110c..a3f180653b8b 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -839,7 +839,7 @@ EXPORT_SYMBOL(drm_prime_pages_to_sg); * @sgt: sg_table describing the buffer to check * * This helper calculates the contiguous size in the DMA address space - * of the the buffer described by the provided sg_table. + * of the buffer described by the provided sg_table. * * This is useful for implementing * &drm_gem_object_funcs.gem_prime_import_sg_table. diff --git a/drivers/gpu/drm/drm_writeback.c b/drivers/gpu/drm/drm_writeback.c index 99fd15d1b366..a031c335bdb9 100644 --- a/drivers/gpu/drm/drm_writeback.c +++ b/drivers/gpu/drm/drm_writeback.c @@ -14,6 +14,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_device.h> #include <drm/drm_drv.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_modeset_helper_vtables.h> #include <drm/drm_property.h> #include <drm/drm_writeback.h> diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index b5001db7a95c..8155d7e650f1 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -17,7 +17,9 @@ #include <linux/pm_runtime.h> #include <linux/regmap.h> +#include <drm/drm_blend.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_vblank.h> #include "exynos_drm_crtc.h" diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c index c04264f70ad1..3047edf355b5 100644 --- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c @@ -20,6 +20,7 @@ #include <video/of_videomode.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_vblank.h> #include <drm/exynos_drm.h> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c index 79fa3649185c..97f2dee2db29 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c @@ -12,6 +12,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_fourcc.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index 02c97b9ca926..767afd2bfa82 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -15,6 +15,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_prime.h> #include <drm/drm_probe_helper.h> #include <drm/exynos_drm.h> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index d5720fab510c..ae6636e6658e 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -21,7 +21,9 @@ #include <video/of_videomode.h> #include <video/samsung_fimd.h> +#include <drm/drm_blend.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_vblank.h> #include <drm/exynos_drm.h> diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c index 9ae868935357..ea9f66037600 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c @@ -18,6 +18,7 @@ #include <linux/uaccess.h> +#include <drm/drm_blend.h> #include <drm/drm_file.h> #include <drm/drm_fourcc.h> #include <drm/drm_mode.h> diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index df76bdee7dca..66e5f1e34044 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -7,6 +7,8 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_plane_helper.h> #include <drm/exynos_drm.h> diff --git a/drivers/gpu/drm/exynos/exynos_drm_scaler.c b/drivers/gpu/drm/exynos/exynos_drm_scaler.c index 3a7851b7dc66..3c049fb658a3 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_scaler.c +++ b/drivers/gpu/drm/exynos/exynos_drm_scaler.c @@ -15,6 +15,7 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> +#include <drm/drm_blend.h> #include <drm/drm_fourcc.h> #include <drm/exynos_drm.h> diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index e5662bdcbbde..4d56c8c799c5 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -13,6 +13,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_edid.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index e5204be86093..65260a658684 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -25,7 +25,10 @@ #include <linux/spinlock.h> #include <linux/wait.h> +#include <drm/drm_blend.h> +#include <drm/drm_edid.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_vblank.h> #include <drm/exynos_drm.h> diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c index 8fe953d6e0a9..0cd527f0c146 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c @@ -12,6 +12,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c index 9ee99a7d4fbe..bb2e9d64018a 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c @@ -32,6 +32,7 @@ #include <drm/display/drm_dp_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_edid.h> #include <drm/drm_simple_kms_helper.h> #include "gma_display.h" diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 0ac6ea5fd3a1..aa3ecf771fd3 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -21,6 +21,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_framebuffer_helper.h> #include "framebuffer.h" diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c index 34ec3fca09ba..bd40c040a2c9 100644 --- a/drivers/gpu/drm/gma500/gma_display.c +++ b/drivers/gpu/drm/gma500/gma_display.c @@ -12,6 +12,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_vblank.h> #include "framebuffer.h" diff --git a/drivers/gpu/drm/gma500/oaktrail_crtc.c b/drivers/gpu/drm/gma500/oaktrail_crtc.c index 22398d34853a..6004390d647a 100644 --- a/drivers/gpu/drm/gma500/oaktrail_crtc.c +++ b/drivers/gpu/drm/gma500/oaktrail_crtc.c @@ -8,6 +8,7 @@ #include <linux/pm_runtime.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include "framebuffer.h" #include "gem.h" diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/drivers/gpu/drm/gma500/oaktrail_hdmi.c index b5946a1cdcd5..95b7cb099e63 100644 --- a/drivers/gpu/drm/gma500/oaktrail_hdmi.c +++ b/drivers/gpu/drm/gma500/oaktrail_hdmi.c @@ -27,6 +27,7 @@ #include <linux/delay.h> #include <drm/drm.h> +#include <drm/drm_edid.h> #include <drm/drm_simple_kms_helper.h> #include "psb_drv.h" diff --git a/drivers/gpu/drm/gma500/oaktrail_lvds.c b/drivers/gpu/drm/gma500/oaktrail_lvds.c index 9c9ebf8e29c4..4d98df189e10 100644 --- a/drivers/gpu/drm/gma500/oaktrail_lvds.c +++ b/drivers/gpu/drm/gma500/oaktrail_lvds.c @@ -13,6 +13,7 @@ #include <asm/intel-mid.h> +#include <drm/drm_edid.h> #include <drm/drm_simple_kms_helper.h> #include "intel_bios.h" diff --git a/drivers/gpu/drm/gma500/psb_intel_modes.c b/drivers/gpu/drm/gma500/psb_intel_modes.c index 60306780e16c..8be0ec340de5 100644 --- a/drivers/gpu/drm/gma500/psb_intel_modes.c +++ b/drivers/gpu/drm/gma500/psb_intel_modes.c @@ -7,6 +7,8 @@ #include <linux/i2c.h> +#include <drm/drm_edid.h> + #include "psb_intel_drv.h" /** diff --git a/drivers/gpu/drm/gud/gud_connector.c b/drivers/gpu/drm/gud/gud_connector.c index ae051133e050..d0addd478815 100644 --- a/drivers/gpu/drm/gud/gud_connector.c +++ b/drivers/gpu/drm/gud/gud_connector.c @@ -10,6 +10,7 @@ #include <drm/drm_atomic_state_helper.h> #include <drm/drm_connector.h> #include <drm/drm_drv.h> +#include <drm/drm_edid.h> #include <drm/drm_encoder.h> #include <drm/drm_file.h> #include <drm/drm_modeset_helper_vtables.h> diff --git a/drivers/gpu/drm/gud/gud_drv.c b/drivers/gpu/drm/gud/gud_drv.c index 3f9d4b9a1e3d..8d1630b8edac 100644 --- a/drivers/gpu/drm/gud/gud_drv.c +++ b/drivers/gpu/drm/gud/gud_drv.c @@ -14,6 +14,7 @@ #include <linux/workqueue.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_damage_helper.h> #include <drm/drm_debugfs.h> #include <drm/drm_drv.h> diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c index 1ab94620776f..61c29c2834e6 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c @@ -26,6 +26,7 @@ #include <drm/drm_drv.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c index 27f4fcb058f9..b8e64dd8d3a6 100644 --- a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c +++ b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c @@ -7,9 +7,11 @@ #include <drm/drm_damage_helper.h> #include <drm/drm_drv.h> +#include <drm/drm_edid.h> #include <drm/drm_fb_helper.h> #include <drm/drm_format_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_gem_shmem_helper.h> diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index 7fe1a4e57654..592e5adfed8b 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -5,6 +5,7 @@ #include <linux/kernel.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_fourcc.h> #include <drm/drm_plane_helper.h> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 0c5638f5b72b..96cd1f0b9d32 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -25,6 +25,7 @@ * */ +#include <drm/drm_edid.h> #include <drm/display/drm_dp_helper.h> #include <drm/display/drm_dsc_helper.h> diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c index 8c80de877605..c2797ad2d313 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -6,6 +6,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_uapi.h> +#include <drm/drm_blend.h> #include <drm/drm_damage_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_fourcc.h> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 408152f9f46a..a0ec5b02b80b 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -38,6 +38,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_encoder.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_probe_helper.h> #include <drm/drm_rect.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index e4a79c11fd25..7c96088d80c7 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -40,6 +40,7 @@ #include <drm/display/drm_hdmi_helper.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> +#include <drm/drm_edid.h> #include <drm/drm_probe_helper.h> #include "g4x_dp.h" diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 9f5a6b79e95b..b191915ab351 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -3,6 +3,7 @@ * Copyright © 2021 Intel Corporation */ +#include <drm/drm_blend.h> #include <drm/drm_framebuffer.h> #include <drm/drm_modeset_helper.h> diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index bbdc34a23d54..6efae745ca5a 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -40,6 +40,7 @@ #include <linux/string_helpers.h> +#include <drm/drm_blend.h> #include <drm/drm_fourcc.h> #include "i915_drv.h" diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c index 7fbc8031a5aa..15d59de8810e 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.c +++ b/drivers/gpu/drm/i915/display/intel_lspcon.c @@ -26,6 +26,7 @@ #include <drm/display/drm_dp_dual_mode_helper.h> #include <drm/display/drm_hdmi_helper.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_edid.h> #include "intel_de.h" #include "intel_display_types.h" diff --git a/drivers/gpu/drm/i915/display/intel_opregion.c b/drivers/gpu/drm/i915/display/intel_opregion.c index f31e8c3f8ce0..3aea4e42d55e 100644 --- a/drivers/gpu/drm/i915/display/intel_opregion.c +++ b/drivers/gpu/drm/i915/display/intel_opregion.c @@ -30,6 +30,8 @@ #include <linux/firmware.h> #include <acpi/video.h> +#include <drm/drm_edid.h> + #include "i915_drv.h" #include "intel_acpi.h" #include "intel_backlight.h" diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index 7c0df80612d0..2713faad0625 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -34,6 +34,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_color_mgmt.h> #include <drm/drm_crtc.h> #include <drm/drm_damage_helper.h> diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index caa03324a733..c11e15a93164 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -4,6 +4,7 @@ */ #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_damage_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_plane_helper.h> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 5735915facc5..16a08be7a99a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -30,6 +30,7 @@ #include <linux/pm_runtime.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_fourcc.h> #include <drm/drm_plane_helper.h> diff --git a/drivers/gpu/drm/imx/dcss/dcss-plane.c b/drivers/gpu/drm/imx/dcss/dcss-plane.c index ac45d54acd4e..c29f343f33e5 100644 --- a/drivers/gpu/drm/imx/dcss/dcss-plane.c +++ b/drivers/gpu/drm/imx/dcss/dcss-plane.c @@ -5,7 +5,9 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_fb_cma_helper.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c index 14a058a42854..8bf885137977 100644 --- a/drivers/gpu/drm/imx/imx-ldb.c +++ b/drivers/gpu/drm/imx/imx-ldb.c @@ -21,6 +21,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> +#include <drm/drm_edid.h> #include <drm/drm_fb_helper.h> #include <drm/drm_managed.h> #include <drm/drm_of.h> diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c index 2b1fdf2cbbce..6b34fac3f73a 100644 --- a/drivers/gpu/drm/imx/imx-tve.c +++ b/drivers/gpu/drm/imx/imx-tve.c @@ -18,6 +18,7 @@ #include <video/imx-ipu-v3.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_edid.h> #include <drm/drm_fb_helper.h> #include <drm/drm_managed.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index 36b32e8806e3..ea5f594955df 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -7,8 +7,10 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_managed.h> diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c index 63ba2ad84679..e4fd453afa3c 100644 --- a/drivers/gpu/drm/imx/parallel-display.c +++ b/drivers/gpu/drm/imx/parallel-display.c @@ -14,6 +14,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> +#include <drm/drm_edid.h> #include <drm/drm_fb_helper.h> #include <drm/drm_managed.h> #include <drm/drm_of.h> diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index 8eb0ad501a7b..2c559885347a 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -33,6 +33,7 @@ #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_managed.h> diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c b/drivers/gpu/drm/ingenic/ingenic-ipu.c index 2737fc521e15..32a50935aa6d 100644 --- a/drivers/gpu/drm/ingenic/ingenic-ipu.c +++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c @@ -24,6 +24,7 @@ #include <drm/drm_drv.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> diff --git a/drivers/gpu/drm/kmb/kmb_plane.c b/drivers/gpu/drm/kmb/kmb_plane.c index 2735b8eb3537..89d055a089a6 100644 --- a/drivers/gpu/drm/kmb/kmb_plane.c +++ b/drivers/gpu/drm/kmb/kmb_plane.c @@ -5,11 +5,13 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_managed.h> #include <drm/drm_plane_helper.h> diff --git a/drivers/gpu/drm/logicvc/logicvc_layer.c b/drivers/gpu/drm/logicvc/logicvc_layer.c index bae1c7f99569..fbebe966f93a 100644 --- a/drivers/gpu/drm/logicvc/logicvc_layer.c +++ b/drivers/gpu/drm/logicvc/logicvc_layer.c @@ -9,8 +9,10 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_plane.h> #include <drm/drm_plane_helper.h> #include <drm/drm_print.h> diff --git a/drivers/gpu/drm/mcde/mcde_display.c b/drivers/gpu/drm/mcde/mcde_display.c index ce12a36e2db4..4df477540d07 100644 --- a/drivers/gpu/drm/mcde/mcde_display.c +++ b/drivers/gpu/drm/mcde/mcde_display.c @@ -13,6 +13,7 @@ #include <drm/drm_device.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_mipi_dsi.h> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 70ab22964f3b..002b0f6cae1a 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -3,7 +3,9 @@ * Copyright (c) 2015 MediaTek Inc. */ +#include <drm/drm_blend.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <linux/clk.h> #include <linux/component.h> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c index 1be4caf9ff96..2cb90466798c 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c @@ -3,6 +3,8 @@ * Copyright (c) 2015 MediaTek Inc. */ +#include <drm/drm_fourcc.h> + #include <linux/clk.h> #include <linux/component.h> #include <linux/module.h> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.c b/drivers/gpu/drm/mediatek/mtk_drm_plane.c index e5fae4ec2337..91f57cbde06b 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_plane.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_plane.c @@ -7,7 +7,9 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_uapi.h> +#include <drm/drm_blend.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_plane_helper.h> diff --git a/drivers/gpu/drm/meson/meson_overlay.c b/drivers/gpu/drm/meson/meson_overlay.c index dfef8afcc245..b4a0518c1028 100644 --- a/drivers/gpu/drm/meson/meson_overlay.c +++ b/drivers/gpu/drm/meson/meson_overlay.c @@ -9,9 +9,11 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_device.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_plane_helper.h> diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c index 8640a8a8a469..b9ac932af8d0 100644 --- a/drivers/gpu/drm/meson/meson_plane.c +++ b/drivers/gpu/drm/meson/meson_plane.c @@ -13,9 +13,11 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_device.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_plane_helper.h> diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index e339f50d6bc8..225cca2ed60e 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -17,6 +17,7 @@ #include <drm/drm_damage_helper.h> #include <drm/drm_format_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_plane_helper.h> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index b56f777dbd0e..c141548416aa 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -12,8 +12,10 @@ #include <linux/bits.h> #include <drm/drm_atomic.h> +#include <drm/drm_blend.h> #include <drm/drm_crtc.h> #include <drm/drm_flip_work.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_mode.h> #include <drm/drm_probe_helper.h> #include <drm/drm_rect.h> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c index 59da348ff339..45846c7833e5 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c @@ -7,6 +7,8 @@ #include <linux/debugfs.h> +#include <drm/drm_framebuffer.h> + #include "dpu_encoder_phys.h" #include "dpu_formats.h" #include "dpu_hw_top.h" diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c index 440ae93d7bd1..f436a1f3419d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c @@ -5,6 +5,7 @@ #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ #include <uapi/drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include "msm_media_info.h" #include "dpu_kms.h" diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index e23e2552e802..7a21fd680b42 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -16,6 +16,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_file.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_vblank.h> #include <drm/drm_writeback.h> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 5b5aef249390..edf324889b75 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -12,7 +12,9 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_uapi.h> +#include <drm/drm_blend.h> #include <drm/drm_damage_helper.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include "msm_drv.h" diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c index 399115e4e217..1ea62ecafb2e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c @@ -3,6 +3,8 @@ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ +#include <drm/drm_edid.h> + #include "dpu_writeback.h" static int dpu_wb_conn_get_modes(struct drm_connector *connector) diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c index 3e20f72d75ef..b689b618da78 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c @@ -7,6 +7,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_damage_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include "mdp4_kms.h" diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c index 31447da0af25..e86421c69bd1 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c @@ -8,6 +8,7 @@ #include <linux/sort.h> #include <drm/drm_atomic.h> +#include <drm/drm_blend.h> #include <drm/drm_mode.h> #include <drm/drm_crtc.h> #include <drm/drm_flip_work.h> diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c index e8c47a4a1d31..bd2c4ac45601 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c @@ -6,8 +6,10 @@ */ #include <drm/drm_atomic.h> +#include <drm/drm_blend.h> #include <drm/drm_damage_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_print.h> diff --git a/drivers/gpu/drm/msm/disp/mdp_format.c b/drivers/gpu/drm/msm/disp/mdp_format.c index 5495d8b3f5b9..025595336f26 100644 --- a/drivers/gpu/drm/msm/disp/mdp_format.c +++ b/drivers/gpu/drm/msm/disp/mdp_format.c @@ -5,6 +5,8 @@ * Author: Rob Clark <robdclark@gmail.com> */ +#include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include "msm_drv.h" #include "mdp_kms.h" diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c index 97c24010c4d1..2e4c2d5f8460 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c @@ -6,6 +6,7 @@ #include <linux/delay.h> #include <drm/drm_bridge_connector.h> +#include <drm/drm_edid.h> #include "msm_kms.h" #include "hdmi.h" diff --git a/drivers/gpu/drm/msm/msm_debugfs.c b/drivers/gpu/drm/msm/msm_debugfs.c index ea2a20699cb4..7d2dab260f86 100644 --- a/drivers/gpu/drm/msm/msm_debugfs.c +++ b/drivers/gpu/drm/msm/msm_debugfs.c @@ -10,6 +10,7 @@ #include <drm/drm_debugfs.h> #include <drm/drm_file.h> +#include <drm/drm_framebuffer.h> #include "msm_drv.h" #include "msm_gpu.h" diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c index 4269da268a4a..e3f61c39df69 100644 --- a/drivers/gpu/drm/msm/msm_fb.c +++ b/drivers/gpu/drm/msm/msm_fb.c @@ -8,6 +8,7 @@ #include <drm/drm_damage_helper.h> #include <drm/drm_file.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c index 4c39ef9dd75d..46168eccfac4 100644 --- a/drivers/gpu/drm/msm/msm_fbdev.c +++ b/drivers/gpu/drm/msm/msm_fbdev.c @@ -8,6 +8,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_prime.h> #include "msm_drv.h" diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c index f021ab2c4520..7d38769821c3 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c @@ -21,6 +21,7 @@ #include <drm/drm_encoder.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_plane.h> diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c b/drivers/gpu/drm/nouveau/dispnv50/wndw.c index bb8a4601e0d9..ef21cfa2b28e 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c @@ -32,6 +32,7 @@ #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> diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c index ca74775834dd..ae793f400ba1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c @@ -1048,7 +1048,7 @@ nvkm_vmm_ctor(const struct nvkm_vmm_func *func, struct nvkm_mmu *mmu, __mutex_init(&vmm->mutex, "&vmm->mutex", key ? key : &_key); /* Locate the smallest page size supported by the backend, it will - * have the the deepest nesting of page tables. + * have the deepest nesting of page tables. */ while (page[1].shift) page++; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index 35b750cebaeb..a8a75dc24751 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -29,6 +29,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_state_helper.h> +#include <drm/drm_edid.h> #include "omapdss.h" #include "hdmi4_core.h" diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c index 65085d886da5..868712cd8a3a 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c @@ -32,6 +32,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_state_helper.h> +#include <drm/drm_edid.h> #include "omapdss.h" #include "hdmi5_core.h" diff --git a/drivers/gpu/drm/omapdrm/omap_debugfs.c b/drivers/gpu/drm/omapdrm/omap_debugfs.c index 2d3909a37f51..bfb2ccb40bd1 100644 --- a/drivers/gpu/drm/omapdrm/omap_debugfs.c +++ b/drivers/gpu/drm/omapdrm/omap_debugfs.c @@ -10,6 +10,7 @@ #include <drm/drm_debugfs.h> #include <drm/drm_file.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_framebuffer.h> #include "omap_drv.h" #include "omap_dmm_tiler.h" diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c index 895e66b08a81..1d414b33fee3 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.c +++ b/drivers/gpu/drm/omapdrm/omap_fb.c @@ -6,8 +6,10 @@ #include <linux/dma-mapping.h> +#include <drm/drm_blend.h> #include <drm/drm_modeset_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_framebuffer_helper.h> #include "omap_dmm_tiler.h" diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c index 42eac6ad12bd..40706c5aad7b 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.c +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c @@ -9,6 +9,7 @@ #include <drm/drm_fb_helper.h> #include <drm/drm_file.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include "omap_drv.h" diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index b83d91ec030a..b6cb537f7689 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -6,9 +6,11 @@ #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_plane_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include "omap_dmm_tiler.h" #include "omap_drv.h" diff --git a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c index 1be150ac758f..07f722f33fc5 100644 --- a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c +++ b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c @@ -1511,16 +1511,28 @@ static int boe_panel_get_modes(struct drm_panel *panel, connector->display_info.width_mm = boe->desc->size.width_mm; connector->display_info.height_mm = boe->desc->size.height_mm; connector->display_info.bpc = boe->desc->bpc; + /* + * TODO: Remove once all drm drivers call + * drm_connector_set_orientation_from_panel() + */ drm_connector_set_panel_orientation(connector, boe->orientation); return 1; } +static enum drm_panel_orientation boe_panel_get_orientation(struct drm_panel *panel) +{ + struct boe_panel *boe = to_boe_panel(panel); + + return boe->orientation; +} + static const struct drm_panel_funcs boe_panel_funcs = { .unprepare = boe_panel_unprepare, .prepare = boe_panel_prepare, .enable = boe_panel_enable, .get_modes = boe_panel_get_modes, + .get_orientation = boe_panel_get_orientation, }; static int boe_panel_add(struct boe_panel *boe) diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index c96014464355..16bdcd83d550 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -39,6 +39,7 @@ #include <drm/display/drm_dp_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_device.h> +#include <drm/drm_edid.h> #include <drm/drm_panel.h> /** @@ -417,6 +418,11 @@ static int panel_edp_get_hpd_gpio(struct device *dev, struct panel_edp *p) return 0; } +static bool panel_edp_can_read_hpd(struct panel_edp *p) +{ + return !p->no_hpd && (p->hpd_gpio || (p->aux && p->aux->wait_hpd_asserted)); +} + static int panel_edp_prepare_once(struct panel_edp *p) { struct device *dev = p->base.dev; @@ -441,17 +447,21 @@ static int panel_edp_prepare_once(struct panel_edp *p) if (delay) msleep(delay); - if (p->hpd_gpio) { + if (panel_edp_can_read_hpd(p)) { if (p->desc->delay.hpd_absent) hpd_wait_us = p->desc->delay.hpd_absent * 1000UL; else hpd_wait_us = 2000000; - err = readx_poll_timeout(gpiod_get_value_cansleep, p->hpd_gpio, - hpd_asserted, hpd_asserted, - 1000, hpd_wait_us); - if (hpd_asserted < 0) - err = hpd_asserted; + if (p->hpd_gpio) { + err = readx_poll_timeout(gpiod_get_value_cansleep, + p->hpd_gpio, hpd_asserted, + hpd_asserted, 1000, hpd_wait_us); + if (hpd_asserted < 0) + err = hpd_asserted; + } else { + err = p->aux->wait_hpd_asserted(p->aux, hpd_wait_us); + } if (err) { if (err != -ETIMEDOUT) @@ -532,18 +542,22 @@ static int panel_edp_enable(struct drm_panel *panel) /* * If there is a "prepare_to_enable" delay then that's supposed to be * the delay from HPD going high until we can turn the backlight on. - * However, we can only count this if HPD is handled by the panel - * driver, not if it goes to a dedicated pin on the controller. + * However, we can only count this if HPD is readable by the panel + * driver. + * * If we aren't handling the HPD pin ourselves then the best we * can do is assume that HPD went high immediately before we were - * called (and link training took zero time). + * called (and link training took zero time). Note that "no-hpd" + * actually counts as handling HPD ourselves since we're doing the + * worst case delay (in prepare) ourselves. * * NOTE: if we ever end up in this "if" statement then we're * guaranteed that the panel_edp_wait() call below will do no delay. * It already handles that case, though, so we don't need any special * code for it. */ - if (p->desc->delay.prepare_to_enable && !p->hpd_gpio && !p->no_hpd) + if (p->desc->delay.prepare_to_enable && + !panel_edp_can_read_hpd(p) && !p->no_hpd) delay = max(delay, p->desc->delay.prepare_to_enable); if (delay) @@ -586,7 +600,10 @@ static int panel_edp_get_modes(struct drm_panel *panel, else if (!num) dev_warn(p->base.dev, "No display modes\n"); - /* set up connector's "panel orientation" property */ + /* + * TODO: Remove once all drm drivers call + * drm_connector_set_orientation_from_panel() + */ drm_connector_set_panel_orientation(connector, p->orientation); return num; @@ -609,6 +626,13 @@ static int panel_edp_get_timings(struct drm_panel *panel, return p->desc->num_timings; } +static enum drm_panel_orientation panel_edp_get_orientation(struct drm_panel *panel) +{ + struct panel_edp *p = to_panel_edp(panel); + + return p->orientation; +} + static int detected_panel_show(struct seq_file *s, void *data) { struct drm_panel *panel = s->private; @@ -637,6 +661,7 @@ static const struct drm_panel_funcs panel_edp_funcs = { .prepare = panel_edp_prepare, .enable = panel_edp_enable, .get_modes = panel_edp_get_modes, + .get_orientation = panel_edp_get_orientation, .get_timings = panel_edp_get_timings, .debugfs_init = panel_edp_debugfs_init, }; diff --git a/drivers/gpu/drm/panel/panel-elida-kd35t133.c b/drivers/gpu/drm/panel/panel-elida-kd35t133.c index 80227617a4d6..01dd555a7f26 100644 --- a/drivers/gpu/drm/panel/panel-elida-kd35t133.c +++ b/drivers/gpu/drm/panel/panel-elida-kd35t133.c @@ -217,15 +217,27 @@ static int kd35t133_get_modes(struct drm_panel *panel, connector->display_info.width_mm = mode->width_mm; connector->display_info.height_mm = mode->height_mm; drm_mode_probed_add(connector, mode); + /* + * TODO: Remove once all drm drivers call + * drm_connector_set_orientation_from_panel() + */ drm_connector_set_panel_orientation(connector, ctx->orientation); return 1; } +static enum drm_panel_orientation kd35t133_get_orientation(struct drm_panel *panel) +{ + struct kd35t133 *ctx = panel_to_kd35t133(panel); + + return ctx->orientation; +} + static const struct drm_panel_funcs kd35t133_funcs = { .unprepare = kd35t133_unprepare, .prepare = kd35t133_prepare, .get_modes = kd35t133_get_modes, + .get_orientation = kd35t133_get_orientation, }; static int kd35t133_probe(struct mipi_dsi_device *dsi) diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c b/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c index ba30d11547ad..596861269774 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c @@ -853,17 +853,29 @@ static int ili9881c_get_modes(struct drm_panel *panel, connector->display_info.width_mm = mode->width_mm; connector->display_info.height_mm = mode->height_mm; + /* + * TODO: Remove once all drm drivers call + * drm_connector_set_orientation_from_panel() + */ drm_connector_set_panel_orientation(connector, ctx->orientation); return 1; } +static enum drm_panel_orientation ili9881c_get_orientation(struct drm_panel *panel) +{ + struct ili9881c *ctx = panel_to_ili9881c(panel); + + return ctx->orientation; +} + static const struct drm_panel_funcs ili9881c_funcs = { .prepare = ili9881c_prepare, .unprepare = ili9881c_unprepare, .enable = ili9881c_enable, .disable = ili9881c_disable, .get_modes = ili9881c_get_modes, + .get_orientation = ili9881c_get_orientation, }; static int ili9881c_dsi_probe(struct mipi_dsi_device *dsi) diff --git a/drivers/gpu/drm/panel/panel-lvds.c b/drivers/gpu/drm/panel/panel-lvds.c index f11252fb00fe..de8758c30e6e 100644 --- a/drivers/gpu/drm/panel/panel-lvds.c +++ b/drivers/gpu/drm/panel/panel-lvds.c @@ -99,15 +99,28 @@ static int panel_lvds_get_modes(struct drm_panel *panel, drm_display_info_set_bus_formats(&connector->display_info, &lvds->bus_format, 1); connector->display_info.bus_flags = lvds->bus_flags; + + /* + * TODO: Remove once all drm drivers call + * drm_connector_set_orientation_from_panel() + */ drm_connector_set_panel_orientation(connector, lvds->orientation); return 1; } +static enum drm_panel_orientation panel_lvds_get_orientation(struct drm_panel *panel) +{ + struct panel_lvds *lvds = to_panel_lvds(panel); + + return lvds->orientation; +} + static const struct drm_panel_funcs panel_lvds_funcs = { .unprepare = panel_lvds_unprepare, .prepare = panel_lvds_prepare, .get_modes = panel_lvds_get_modes, + .get_orientation = panel_lvds_get_orientation, }; static int panel_lvds_parse_dt(struct panel_lvds *lvds) diff --git a/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c b/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c index 3dd10412d147..5a8b978c6415 100644 --- a/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c +++ b/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c @@ -19,6 +19,10 @@ #include <drm/drm_edid.h> #include <drm/drm_panel.h> +/* T3 VCC to HPD high is max 200 ms */ +#define HPD_MAX_MS 200 +#define HPD_MAX_US (HPD_MAX_MS * 1000) + struct atana33xc20_panel { struct drm_panel base; bool prepared; @@ -30,6 +34,7 @@ struct atana33xc20_panel { struct regulator *supply; struct gpio_desc *el_on3_gpio; + struct drm_dp_aux *aux; struct edid *edid; @@ -79,7 +84,7 @@ static int atana33xc20_suspend(struct device *dev) static int atana33xc20_resume(struct device *dev) { struct atana33xc20_panel *p = dev_get_drvdata(dev); - bool hpd_asserted = false; + int hpd_asserted; int ret; /* T12 (Power off time) is min 500 ms */ @@ -90,23 +95,41 @@ static int atana33xc20_resume(struct device *dev) return ret; p->powered_on_time = ktime_get(); - /* - * Handle HPD. Note: if HPD is hooked up to a dedicated pin on the - * eDP controller then "no_hpd" will be false _and_ "hpd_gpio" will be - * NULL. It's up to the controller driver to wait for HPD after - * preparing the panel in that case. - */ if (p->no_hpd) { - /* T3 VCC to HPD high is max 200 ms */ - msleep(200); - } else if (p->hpd_gpio) { + msleep(HPD_MAX_MS); + return 0; + } + + if (p->hpd_gpio) { ret = readx_poll_timeout(gpiod_get_value_cansleep, p->hpd_gpio, hpd_asserted, hpd_asserted, - 1000, 200000); - if (!hpd_asserted) - dev_warn(dev, "Timeout waiting for HPD\n"); + 1000, HPD_MAX_US); + if (hpd_asserted < 0) + ret = hpd_asserted; + + if (ret) + dev_warn(dev, "Error waiting for HPD GPIO: %d\n", ret); + + return ret; } + if (p->aux->wait_hpd_asserted) { + ret = p->aux->wait_hpd_asserted(p->aux, HPD_MAX_US); + + if (ret) + dev_warn(dev, "Controller error waiting for HPD: %d\n", ret); + + return ret; + } + + /* + * Note that it's possible that no_hpd is false, hpd_gpio is + * NULL, and wait_hpd_asserted is NULL. This is because + * wait_hpd_asserted() is optional even if HPD is hooked up to + * a dedicated pin on the eDP controller. In this case we just + * assume that the controller driver will wait for HPD at the + * right times. + */ return 0; } @@ -263,6 +286,8 @@ static int atana33xc20_probe(struct dp_aux_ep_device *aux_ep) return -ENOMEM; dev_set_drvdata(dev, panel); + panel->aux = aux_ep->aux; + panel->supply = devm_regulator_get(dev, "power"); if (IS_ERR(panel->supply)) return dev_err_probe(dev, PTR_ERR(panel->supply), diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 4a2e580a2f7b..a1c12bde686f 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -35,6 +35,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_device.h> +#include <drm/drm_edid.h> #include <drm/drm_mipi_dsi.h> #include <drm/drm_panel.h> @@ -411,7 +412,10 @@ static int panel_simple_get_modes(struct drm_panel *panel, /* add hard-coded panel modes */ num += panel_simple_get_non_edid_modes(p, connector); - /* set up connector's "panel orientation" property */ + /* + * TODO: Remove once all drm drivers call + * drm_connector_set_orientation_from_panel() + */ drm_connector_set_panel_orientation(connector, p->orientation); return num; @@ -434,12 +438,20 @@ static int panel_simple_get_timings(struct drm_panel *panel, return p->desc->num_timings; } +static enum drm_panel_orientation panel_simple_get_orientation(struct drm_panel *panel) +{ + struct panel_simple *p = to_panel_simple(panel); + + return p->orientation; +} + static const struct drm_panel_funcs panel_simple_funcs = { .disable = panel_simple_disable, .unprepare = panel_simple_unprepare, .prepare = panel_simple_prepare, .enable = panel_simple_enable, .get_modes = panel_simple_get_modes, + .get_orientation = panel_simple_get_orientation, .get_timings = panel_simple_get_timings, }; diff --git a/drivers/gpu/drm/pl111/pl111_display.c b/drivers/gpu/drm/pl111/pl111_display.c index 443e3b932322..ccf5f02b2962 100644 --- a/drivers/gpu/drm/pl111/pl111_display.c +++ b/drivers/gpu/drm/pl111/pl111_display.c @@ -16,6 +16,7 @@ #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/pl111/pl111_drv.c b/drivers/gpu/drm/pl111/pl111_drv.c index 520301b405f1..19a4324bd356 100644 --- a/drivers/gpu/drm/pl111/pl111_drv.c +++ b/drivers/gpu/drm/pl111/pl111_drv.c @@ -50,6 +50,7 @@ #include <drm/drm_drv.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_fourcc.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_of.h> diff --git a/drivers/gpu/drm/pl111/pl111_versatile.c b/drivers/gpu/drm/pl111/pl111_versatile.c index bdd883f4f0da..efb01a554574 100644 --- a/drivers/gpu/drm/pl111/pl111_versatile.c +++ b/drivers/gpu/drm/pl111/pl111_versatile.c @@ -18,6 +18,8 @@ #include <linux/regmap.h> #include <linux/vexpress.h> +#include <drm/drm_fourcc.h> + #include "pl111_versatile.h" #include "pl111_drm.h" diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 9a64fa4c7530..2e8949863d6b 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -30,6 +30,8 @@ #include <drm/drm_drv.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_edid.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/qxl/qxl_draw.c b/drivers/gpu/drm/qxl/qxl_draw.c index a93de9e1977a..3a3e127ce297 100644 --- a/drivers/gpu/drm/qxl/qxl_draw.c +++ b/drivers/gpu/drm/qxl/qxl_draw.c @@ -23,6 +23,7 @@ #include <linux/iosys-map.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include "qxl_drv.h" #include "qxl_object.h" diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index c94e429e75f9..69f1bc073902 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -28,6 +28,7 @@ #include <drm/drm_fb_helper.h> #include <drm/drm_fixed.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_vblank.h> #include <drm/radeon_drm.h> diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 455f8036aa54..4f06356d9ce2 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -29,6 +29,7 @@ #include <drm/drm_vblank.h> #include <drm/radeon_drm.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include "atom.h" #include "avivod.h" diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 2dd85ba1faa2..d4f09ecc3d22 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -35,6 +35,7 @@ #include <drm/drm_device.h> #include <drm/drm_file.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_vblank.h> #include <drm/radeon_drm.h> diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 15692cb241fc..f508aefcf786 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -38,6 +38,7 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_device.h> #include <drm/drm_file.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_probe_helper.h> #include <drm/radeon_drm.h> diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 57ff2b723c87..f12675e3d261 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -36,6 +36,7 @@ #include <drm/drm_edid.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index ca382fbf7a86..6ccea51d4072 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -34,6 +34,7 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/radeon_drm.h> #include "radeon.h" diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 8817fd033cd0..6072ed5f2dd3 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -28,6 +28,7 @@ #include <drm/drm_fb_helper.h> #include <drm/drm_fixed.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_vblank.h> #include <drm/radeon_drm.h> diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index b87dd551e939..8cf87a0a2b2a 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -42,6 +42,7 @@ #include <drm/drm_device.h> #include <drm/drm_vblank.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include "atom.h" #include "radeon.h" diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 38796af4fadd..26fa9b095514 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -33,6 +33,7 @@ #include <drm/drm_device.h> #include <drm/radeon_drm.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include "atom.h" #include "avivod.h" diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index 190dbb7f15dd..0f09e1ee0390 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -12,6 +12,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_device.h> #include <drm/drm_fb_cma_helper.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_managed.h> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index 5c1c7bb04f3f..e98b76db703a 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c @@ -9,10 +9,12 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_crtc.h> #include <drm/drm_device.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_plane_helper.h> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index 8eb9b2b097ae..e778fd52f890 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -9,9 +9,11 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_crtc.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_managed.h> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_writeback.c b/drivers/gpu/drm/rcar-du/rcar_du_writeback.c index 505a905e3ad1..4fd6067f6fb4 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_writeback.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_writeback.c @@ -7,7 +7,9 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_device.h> +#include <drm/drm_edid.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_probe_helper.h> #include <drm/drm_writeback.h> diff --git a/drivers/gpu/drm/rockchip/rk3066_hdmi.c b/drivers/gpu/drm/rockchip/rk3066_hdmi.c index c8c3612a4fe2..cf2cf51091a3 100644 --- a/drivers/gpu/drm/rockchip/rk3066_hdmi.c +++ b/drivers/gpu/drm/rockchip/rk3066_hdmi.c @@ -4,6 +4,7 @@ * Zheng Yang <zhengyang@rock-chips.com> */ +#include <drm/drm_edid.h> #include <drm/drm_of.h> #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index 0d2cb4f3922b..092bf863110b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -11,6 +11,7 @@ #include <drm/drm_damage_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 74562d40f639..82b011dce5e7 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -20,9 +20,11 @@ #include <drm/drm.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_uapi.h> +#include <drm/drm_blend.h> #include <drm/drm_crtc.h> #include <drm/drm_flip_work.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_plane_helper.h> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 6b72894e02d4..16791693b8e6 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -22,10 +22,12 @@ #include <drm/drm.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_uapi.h> +#include <drm/drm_blend.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_debugfs.h> #include <drm/drm_flip_work.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/selftests/test-drm_damage_helper.c b/drivers/gpu/drm/selftests/test-drm_damage_helper.c index 8d8d8e214c28..816e1464a98f 100644 --- a/drivers/gpu/drm/selftests/test-drm_damage_helper.c +++ b/drivers/gpu/drm/selftests/test-drm_damage_helper.c @@ -6,6 +6,7 @@ #define pr_fmt(fmt) "drm_damage_helper: " fmt #include <drm/drm_damage_helper.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_plane.h> #include <drm/drm_drv.h> diff --git a/drivers/gpu/drm/selftests/test-drm_plane_helper.c b/drivers/gpu/drm/selftests/test-drm_plane_helper.c index b61273e9c403..64e8938ab194 100644 --- a/drivers/gpu/drm/selftests/test-drm_plane_helper.c +++ b/drivers/gpu/drm/selftests/test-drm_plane_helper.c @@ -6,6 +6,7 @@ #define pr_fmt(fmt) "drm_plane_helper: " fmt #include <drm/drm_atomic_helper.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_plane_helper.h> #include <drm/drm_modes.h> diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c index 03556dbfcafb..071a929e9fe3 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c @@ -14,6 +14,7 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/shmobile/shmob_drm_kms.c b/drivers/gpu/drm/shmobile/shmob_drm_kms.c index 7a866d6ce6bb..68d21be784aa 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_kms.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_kms.c @@ -10,6 +10,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fourcc.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/shmobile/shmob_drm_plane.c b/drivers/gpu/drm/shmobile/shmob_drm_plane.c index cbc464f006b4..4763ea8e1af0 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_plane.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_plane.c @@ -11,6 +11,7 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include "shmob_drm_drv.h" diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c index 08394444dd6e..77f80b0d3a5e 100644 --- a/drivers/gpu/drm/solomon/ssd130x.c +++ b/drivers/gpu/drm/solomon/ssd130x.c @@ -20,9 +20,11 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_damage_helper.h> +#include <drm/drm_edid.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_format_helper.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_gem_shmem_helper.h> diff --git a/drivers/gpu/drm/sprd/sprd_dpu.c b/drivers/gpu/drm/sprd/sprd_dpu.c index 1637203ea103..3664089b6983 100644 --- a/drivers/gpu/drm/sprd/sprd_dpu.c +++ b/drivers/gpu/drm/sprd/sprd_dpu.c @@ -17,8 +17,10 @@ #include <linux/workqueue.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_fb_cma_helper.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_plane_helper.h> diff --git a/drivers/gpu/drm/sti/sti_cursor.c b/drivers/gpu/drm/sti/sti_cursor.c index 414c9973aa6d..1e9bd4241f10 100644 --- a/drivers/gpu/drm/sti/sti_cursor.c +++ b/drivers/gpu/drm/sti/sti_cursor.c @@ -12,6 +12,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_device.h> #include <drm/drm_fb_cma_helper.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include "sti_compositor.h" diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c index b58415f2e4d8..a1f78d52fb33 100644 --- a/drivers/gpu/drm/sti/sti_gdp.c +++ b/drivers/gpu/drm/sti/sti_gdp.c @@ -13,6 +13,7 @@ #include <drm/drm_device.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include "sti_compositor.h" diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c index 2201a50353eb..b5ae5d217bc0 100644 --- a/drivers/gpu/drm/sti/sti_hqvdp.c +++ b/drivers/gpu/drm/sti/sti_hqvdp.c @@ -17,6 +17,7 @@ #include <drm/drm_device.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include "sti_compositor.h" diff --git a/drivers/gpu/drm/sti/sti_plane.c b/drivers/gpu/drm/sti/sti_plane.c index 173409cdb99e..c74b524663ab 100644 --- a/drivers/gpu/drm/sti/sti_plane.c +++ b/drivers/gpu/drm/sti/sti_plane.c @@ -8,8 +8,10 @@ #include <linux/types.h> +#include <drm/drm_blend.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include "sti_compositor.h" diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c index 6bd45df8f5a7..76230f775081 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c @@ -23,10 +23,13 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_bridge.h> #include <drm/drm_device.h> +#include <drm/drm_edid.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_of.h> diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index decd95ad519d..287e8c4bbaea 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -17,9 +17,11 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_crtc.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/sun4i/sun4i_framebuffer.c b/drivers/gpu/drm/sun4i/sun4i_framebuffer.c index 6825ef46f43f..260136d60ceb 100644 --- a/drivers/gpu/drm/sun4i/sun4i_framebuffer.c +++ b/drivers/gpu/drm/sun4i/sun4i_framebuffer.c @@ -8,6 +8,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_gem_framebuffer_helper.h> #include "sun4i_drv.h" diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c index 6d43080791a0..a0920e173fcc 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.c +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c @@ -8,6 +8,7 @@ #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_plane_helper.h> diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c index 875a1156c04e..648b38a73066 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c @@ -17,6 +17,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_fb_cma_helper.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c index 4632dea2dc1e..36da962de394 100644 --- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c @@ -11,9 +11,11 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_crtc.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_plane_helper.h> diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c index f7d0b082d634..1fee6499bdd3 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -5,8 +5,10 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_crtc.h> #include <drm/drm_fb_cma_helper.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_plane_helper.h> diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index c6951cf5d2ca..a2a731e8a8a3 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -21,8 +21,10 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_debugfs.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_plane_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 9464f522e257..4cdc8faf798f 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -18,6 +18,7 @@ #include <drm/drm_debugfs.h> #include <drm/drm_drv.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_ioctl.h> #include <drm/drm_prime.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c index c04dda8353fd..ed828de5ac01 100644 --- a/drivers/gpu/drm/tegra/fb.c +++ b/drivers/gpu/drm/tegra/fb.c @@ -10,6 +10,7 @@ #include <linux/console.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_modeset_helper.h> diff --git a/drivers/gpu/drm/tegra/hub.c b/drivers/gpu/drm/tegra/hub.c index b8d3174c04c9..61729ea9f0af 100644 --- a/drivers/gpu/drm/tegra/hub.c +++ b/drivers/gpu/drm/tegra/hub.c @@ -16,7 +16,9 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_probe_helper.h> #include "drm.h" diff --git a/drivers/gpu/drm/tegra/plane.c b/drivers/gpu/drm/tegra/plane.c index e0e6938c6200..d049b211c9b3 100644 --- a/drivers/gpu/drm/tegra/plane.c +++ b/drivers/gpu/drm/tegra/plane.c @@ -9,6 +9,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_plane_helper.h> diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c b/drivers/gpu/drm/tidss/tidss_dispc.c index dae47853b728..73f591cfb5a0 100644 --- a/drivers/gpu/drm/tidss/tidss_dispc.c +++ b/drivers/gpu/drm/tidss/tidss_dispc.c @@ -21,8 +21,10 @@ #include <linux/regmap.h> #include <linux/sys_soc.h> +#include <drm/drm_blend.h> #include <drm/drm_fourcc.h> #include <drm/drm_fb_cma_helper.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_panel.h> diff --git a/drivers/gpu/drm/tidss/tidss_plane.c b/drivers/gpu/drm/tidss/tidss_plane.c index 217415ec8eea..68a85a94ffcb 100644 --- a/drivers/gpu/drm/tidss/tidss_plane.c +++ b/drivers/gpu/drm/tidss/tidss_plane.c @@ -6,9 +6,11 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_atomic_helper.h> diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 0dae7d5806bb..509fbae8c9a6 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -14,6 +14,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_modeset_helper_vtables.h> #include <drm/drm_print.h> diff --git a/drivers/gpu/drm/tilcdc/tilcdc_plane.c b/drivers/gpu/drm/tilcdc/tilcdc_plane.c index 74a5c8832229..960136518814 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_plane.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_plane.c @@ -8,6 +8,7 @@ #include <drm/drm_plane_helper.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include "tilcdc_drv.h" diff --git a/drivers/gpu/drm/tiny/arcpgu.c b/drivers/gpu/drm/tiny/arcpgu.c index f0fa3b15c341..7461cb401407 100644 --- a/drivers/gpu/drm/tiny/arcpgu.c +++ b/drivers/gpu/drm/tiny/arcpgu.c @@ -10,9 +10,11 @@ #include <drm/drm_debugfs.h> #include <drm/drm_device.h> #include <drm/drm_drv.h> +#include <drm/drm_edid.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_module.h> diff --git a/drivers/gpu/drm/tiny/bochs.c b/drivers/gpu/drm/tiny/bochs.c index 4f8bf86633df..82364a0a7b18 100644 --- a/drivers/gpu/drm/tiny/bochs.c +++ b/drivers/gpu/drm/tiny/bochs.c @@ -6,8 +6,10 @@ #include <drm/drm_aperture.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> +#include <drm/drm_edid.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_gem_vram_helper.h> #include <drm/drm_managed.h> diff --git a/drivers/gpu/drm/tiny/cirrus.c b/drivers/gpu/drm/tiny/cirrus.c index c8e791840862..c4f5beea1f90 100644 --- a/drivers/gpu/drm/tiny/cirrus.c +++ b/drivers/gpu/drm/tiny/cirrus.c @@ -29,10 +29,12 @@ #include <drm/drm_connector.h> #include <drm/drm_damage_helper.h> #include <drm/drm_drv.h> +#include <drm/drm_edid.h> #include <drm/drm_fb_helper.h> #include <drm/drm_file.h> #include <drm/drm_format_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_gem_shmem_helper.h> diff --git a/drivers/gpu/drm/tiny/gm12u320.c b/drivers/gpu/drm/tiny/gm12u320.c index 648e585d40a8..7441d992a5d7 100644 --- a/drivers/gpu/drm/tiny/gm12u320.c +++ b/drivers/gpu/drm/tiny/gm12u320.c @@ -11,10 +11,12 @@ #include <drm/drm_connector.h> #include <drm/drm_damage_helper.h> #include <drm/drm_drv.h> +#include <drm/drm_edid.h> #include <drm/drm_fb_helper.h> #include <drm/drm_file.h> #include <drm/drm_format_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_gem_shmem_helper.h> diff --git a/drivers/gpu/drm/tiny/ili9225.c b/drivers/gpu/drm/tiny/ili9225.c index cc92eb9f2a07..8d686eecd5f4 100644 --- a/drivers/gpu/drm/tiny/ili9225.c +++ b/drivers/gpu/drm/tiny/ili9225.c @@ -22,6 +22,7 @@ #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_managed.h> diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c index a096fb8b83e9..013790c45d0a 100644 --- a/drivers/gpu/drm/tiny/repaper.c +++ b/drivers/gpu/drm/tiny/repaper.c @@ -28,6 +28,7 @@ #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_format_helper.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> diff --git a/drivers/gpu/drm/tiny/st7586.c b/drivers/gpu/drm/tiny/st7586.c index 3f38faa1cd8c..8eddb020c43e 100644 --- a/drivers/gpu/drm/tiny/st7586.c +++ b/drivers/gpu/drm/tiny/st7586.c @@ -18,6 +18,7 @@ #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_format_helper.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> diff --git a/drivers/gpu/drm/tve200/tve200_display.c b/drivers/gpu/drm/tve200/tve200_display.c index 17b8c8dd169d..771bad881714 100644 --- a/drivers/gpu/drm/tve200/tve200_display.c +++ b/drivers/gpu/drm/tve200/tve200_display.c @@ -17,6 +17,7 @@ #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_panel.h> diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c index 318fdb38b47a..fade4c7adbf7 100644 --- a/drivers/gpu/drm/udl/udl_connector.c +++ b/drivers/gpu/drm/udl/udl_connector.c @@ -8,6 +8,7 @@ */ #include <drm/drm_atomic_state_helper.h> +#include <drm/drm_edid.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/vboxvideo/vbox_mode.c b/drivers/gpu/drm/vboxvideo/vbox_mode.c index 4017b0a621fc..fa0d73ce07bc 100644 --- a/drivers/gpu/drm/vboxvideo/vbox_mode.c +++ b/drivers/gpu/drm/vboxvideo/vbox_mode.c @@ -15,8 +15,10 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_edid.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_plane_helper.h> diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c index 49c0f2ac868b..3700d737ee71 100644 --- a/drivers/gpu/drm/vc4/vc4_bo.c +++ b/drivers/gpu/drm/vc4/vc4_bo.c @@ -18,6 +18,8 @@ #include <linux/dma-buf.h> +#include <drm/drm_fourcc.h> + #include "vc4_drv.h" #include "uapi/drm/vc4_drm.h" diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 59b20c8f132b..0b80d84a92bd 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -38,6 +38,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_uapi.h> #include <drm/drm_fb_cma_helper.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_print.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index c169bd72e53b..a1819df6c190 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -16,6 +16,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> +#include <drm/drm_fourcc.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index b3438f4a81ce..311077647394 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -18,8 +18,10 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_uapi.h> +#include <drm/drm_blend.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_plane_helper.h> diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h index a2b5cbbbc1b0..f0290fad991d 100644 --- a/drivers/gpu/drm/vc4/vc4_regs.h +++ b/drivers/gpu/drm/vc4/vc4_regs.h @@ -264,7 +264,7 @@ * output line. */ # define SCALER_DISPSTAT_ESLINE(x) BIT(10 + ((x) * 8)) -/* Set when the the downstream tries to read from the display FIFO +/* Set when the downstream tries to read from the display FIFO * while it's empty. */ # define SCALER_DISPSTAT_EUFLOW(x) BIT(9 + ((x) * 8)) diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c index 3579d487402e..d20b0bc51a18 100644 --- a/drivers/gpu/drm/vc4/vc4_txp.c +++ b/drivers/gpu/drm/vc4/vc4_txp.c @@ -18,6 +18,7 @@ #include <drm/drm_edid.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_panel.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index f73352e7b832..5c7f198c0712 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -27,6 +27,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_damage_helper.h> +#include <drm/drm_edid.h> #include <drm/drm_fourcc.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index 0a194aaad419..f80664cf98d0 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -37,6 +37,7 @@ #include <drm/drm_encoder.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem.h> #include <drm/drm_gem_shmem_helper.h> #include <drm/drm_ioctl.h> diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index 7c052efe8836..b7529b2b9883 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -31,6 +31,8 @@ #include <linux/virtio_config.h> #include <linux/virtio_ring.h> +#include <drm/drm_edid.h> + #include "virtgpu_drv.h" #include "virtgpu_trace.h" diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index 91e63b12f60f..1d60654b553b 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -6,6 +6,7 @@ #include <linux/hrtimer.h> #include <drm/drm.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_encoder.h> diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c index ba0e82ae549a..991857125bb4 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -2,6 +2,7 @@ #include "vkms_drv.h" #include <drm/drm_atomic_helper.h> +#include <drm/drm_edid.h> #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> diff --git a/drivers/gpu/drm/vkms/vkms_writeback.c b/drivers/gpu/drm/vkms/vkms_writeback.c index 0a315221d1f5..3b3c1e757ab4 100644 --- a/drivers/gpu/drm/vkms/vkms_writeback.c +++ b/drivers/gpu/drm/vkms/vkms_writeback.c @@ -3,6 +3,7 @@ #include <linux/iosys-map.h> #include <drm/drm_atomic.h> +#include <drm/drm_edid.h> #include <drm/drm_fourcc.h> #include <drm/drm_writeback.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index 1d1c8b82c898..7046dfd0d1c6 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h @@ -29,6 +29,7 @@ #define VMWGFX_KMS_H_ #include <drm/drm_encoder.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_probe_helper.h> #include "vmwgfx_drv.h" diff --git a/drivers/gpu/drm/xen/xen_drm_front_conn.c b/drivers/gpu/drm/xen/xen_drm_front_conn.c index 44f1f70c0aed..a1ba6d3d0568 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_conn.c +++ b/drivers/gpu/drm/xen/xen_drm_front_conn.c @@ -10,6 +10,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> +#include <drm/drm_fourcc.h> #include <drm/drm_probe_helper.h> #include <video/videomode.h> diff --git a/drivers/gpu/drm/xen/xen_drm_front_kms.c b/drivers/gpu/drm/xen/xen_drm_front_kms.c index cfda74490765..dfa78a49a6d9 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_kms.c +++ b/drivers/gpu/drm/xen/xen_drm_front_kms.c @@ -12,6 +12,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_framebuffer_helper.h> diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c b/drivers/gpu/drm/xlnx/zynqmp_disp.c index 11c409cbc88e..cc32aa89cf8f 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_disp.c +++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c @@ -12,6 +12,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_uapi.h> +#include <drm/drm_blend.h> #include <drm/drm_crtc.h> #include <drm/drm_device.h> #include <drm/drm_fb_cma_helper.h> diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index d765bbdf19dc..1be8aa9f8074 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -125,8 +125,8 @@ static int logo_lines; enums. */ static int logo_shown = FBCON_LOGO_CANSHOW; /* console mappings */ -static int first_fb_vc; -static int last_fb_vc = MAX_NR_CONSOLES - 1; +static unsigned int first_fb_vc; +static unsigned int last_fb_vc = MAX_NR_CONSOLES - 1; static int fbcon_is_default = 1; static int primary_device = -1; static int fbcon_has_console_bind; @@ -440,10 +440,12 @@ static int __init fb_console_setup(char *this_opt) options += 3; if (*options) first_fb_vc = simple_strtoul(options, &options, 10) - 1; - if (first_fb_vc < 0) + if (first_fb_vc >= MAX_NR_CONSOLES) first_fb_vc = 0; if (*options++ == '-') last_fb_vc = simple_strtoul(options, &options, 10) - 1; + if (last_fb_vc < first_fb_vc || last_fb_vc >= MAX_NR_CONSOLES) + last_fb_vc = MAX_NR_CONSOLES - 1; fbcon_is_default = 0; continue; } @@ -1758,8 +1760,6 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b, case SM_UP: if (count > vc->vc_rows) /* Maximum realistic size */ count = vc->vc_rows; - if (logo_shown >= 0) - goto redraw_up; switch (fb_scrollmode(p)) { case SCROLL_MOVE: fbcon_redraw_blit(vc, info, p, t, b - t - count, @@ -1848,8 +1848,6 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b, case SM_DOWN: if (count > vc->vc_rows) /* Maximum realistic size */ count = vc->vc_rows; - if (logo_shown >= 0) - goto redraw_down; switch (fb_scrollmode(p)) { case SCROLL_MOVE: fbcon_redraw_blit(vc, info, p, b - 1, b - t - count, diff --git a/include/drm/display/drm_dp_helper.h b/include/drm/display/drm_dp_helper.h index c5f8f45511ed..db0fe9f8a612 100644 --- a/include/drm/display/drm_dp_helper.h +++ b/include/drm/display/drm_dp_helper.h @@ -390,6 +390,36 @@ struct drm_dp_aux { struct drm_dp_aux_msg *msg); /** + * @wait_hpd_asserted: wait for HPD to be asserted + * + * This is mainly useful for eDP panels drivers to wait for an eDP + * panel to finish powering on. This is an optional function. + * + * This function will efficiently wait for the HPD signal to be + * asserted. The `wait_us` parameter that is passed in says that we + * know that the HPD signal is expected to be asserted within `wait_us` + * microseconds. This function could wait for longer than `wait_us` if + * the logic in the DP controller has a long debouncing time. The + * important thing is that if this function returns success that the + * DP controller is ready to send AUX transactions. + * + * This function returns 0 if HPD was asserted or -ETIMEDOUT if time + * expired and HPD wasn't asserted. This function should not print + * timeout errors to the log. + * + * The semantics of this function are designed to match the + * readx_poll_timeout() function. That means a `wait_us` of 0 means + * to wait forever. Like readx_poll_timeout(), this function may sleep. + * + * NOTE: this function specifically reports the state of the HPD pin + * that's associated with the DP AUX channel. This is different from + * the HPD concept in much of the rest of DRM which is more about + * physical presence of a display. For eDP, for instance, a display is + * assumed always present even if the HPD pin is deasserted. + */ + int (*wait_hpd_asserted)(struct drm_dp_aux *aux, unsigned long wait_us); + + /** * @i2c_nack_count: Counts I2C NACKs, used for DP validation. */ unsigned i2c_nack_count; diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 42aec8612f37..d434ab416ad4 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -918,16 +918,30 @@ void drm_bridge_hpd_notify(struct drm_bridge *bridge, enum drm_connector_status status); #ifdef CONFIG_DRM_PANEL_BRIDGE +bool drm_bridge_is_panel(const struct drm_bridge *bridge); struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel); struct drm_bridge *drm_panel_bridge_add_typed(struct drm_panel *panel, u32 connector_type); void drm_panel_bridge_remove(struct drm_bridge *bridge); +int drm_panel_bridge_set_orientation(struct drm_connector *connector, + struct drm_bridge *bridge); struct drm_bridge *devm_drm_panel_bridge_add(struct device *dev, struct drm_panel *panel); struct drm_bridge *devm_drm_panel_bridge_add_typed(struct device *dev, struct drm_panel *panel, u32 connector_type); struct drm_connector *drm_panel_bridge_connector(struct drm_bridge *bridge); +#else +static inline bool drm_bridge_is_panel(const struct drm_bridge *bridge) +{ + return false; +} + +static inline int drm_panel_bridge_set_orientation(struct drm_connector *connector, + struct drm_bridge *bridge) +{ + return -EINVAL; +} #endif #if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL_BRIDGE) diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 3ac4bf87f257..94b422b55cc1 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -38,6 +38,7 @@ struct drm_modeset_acquire_ctx; struct drm_device; struct drm_crtc; struct drm_encoder; +struct drm_panel; struct drm_property; struct drm_property_blob; struct drm_printer; @@ -1802,6 +1803,9 @@ int drm_connector_set_panel_orientation_with_quirk( struct drm_connector *connector, enum drm_panel_orientation panel_orientation, int width, int height); +int drm_connector_set_orientation_from_panel( + struct drm_connector *connector, + struct drm_panel *panel); int drm_connector_attach_max_bpc_property(struct drm_connector *connector, int min, int max); void drm_connector_create_privacy_screen_properties(struct drm_connector *conn); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index a70baea0636c..c404b6e81220 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -36,19 +36,17 @@ #include <drm/drm_modeset_lock.h> #include <drm/drm_rect.h> #include <drm/drm_mode_object.h> -#include <drm/drm_framebuffer.h> #include <drm/drm_modes.h> -#include <drm/drm_connector.h> #include <drm/drm_device.h> #include <drm/drm_property.h> -#include <drm/drm_edid.h> #include <drm/drm_plane.h> -#include <drm/drm_blend.h> #include <drm/drm_color_mgmt.h> #include <drm/drm_debugfs_crc.h> #include <drm/drm_mode_config.h> +struct drm_connector; struct drm_device; +struct drm_framebuffer; struct drm_mode_set; struct drm_file; struct drm_clip_rect; diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index d279ee455f01..3a271128c078 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -117,6 +117,15 @@ struct drm_panel_funcs { struct drm_connector *connector); /** + * @get_orientation: + * + * Return the panel orientation set by device tree or EDID. + * + * This function is optional. + */ + enum drm_panel_orientation (*get_orientation)(struct drm_panel *panel); + + /** * @get_timings: * * Copy display timings into the provided array and return diff --git a/include/uapi/linux/media-bus-format.h b/include/uapi/linux/media-bus-format.h index 0dfc11ee243a..ec3323dbb927 100644 --- a/include/uapi/linux/media-bus-format.h +++ b/include/uapi/linux/media-bus-format.h @@ -34,7 +34,7 @@ #define MEDIA_BUS_FMT_FIXED 0x0001 -/* RGB - next is 0x101e */ +/* RGB - next is 0x1022 */ #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 @@ -59,9 +59,13 @@ #define MEDIA_BUS_FMT_RGB888_3X8_DELTA 0x101d #define MEDIA_BUS_FMT_RGB888_1X7X4_SPWG 0x1011 #define MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA 0x1012 +#define MEDIA_BUS_FMT_RGB666_1X30_CPADLO 0x101e +#define MEDIA_BUS_FMT_RGB888_1X30_CPADLO 0x101f #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_RGB666_1X36_CPADLO 0x1020 +#define MEDIA_BUS_FMT_RGB888_1X36_CPADLO 0x1021 #define MEDIA_BUS_FMT_RGB121212_1X36 0x1019 #define MEDIA_BUS_FMT_RGB161616_1X48 0x101a |