mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-12-27 10:01:39 -05:00
Merge tag 'drm-misc-next-2025-06-12' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next
drm-misc-next for 6.17: UAPI Changes: Cross-subsystem Changes: Core Changes: - atomic-helpers: Tune the enable / disable sequence - bridge: Add destroy hook - color management: Add helpers for hardware gamma LUT handling - HDMI: Add CEC handling, YUV420 output support - sched: tracing improvements Driver Changes: - hyperv: Move out of simple-kms, drm_panic support - i915: drm_panel_follower support - imx: Add IMX8qxq Display Controller Support - lima: Add Rockchip RK3528 GPU Support - nouveau: fence handling cleanup - panfrost: Add BO labeling, 64-bit registers access - qaic: Add RAS Support - rz-du: Add RZ/V2H(P) Support, MIPI-DSI DCS Support - sun4i: Add H616 Support - tidss: Add TI AM62L Support - vkms: YUV and R* formats support - bridges: - Switched to reference counted drm_bridge allocations - panels: - Switched to reference counted drm_panel allocations - Add support for fwnode-based panel lookup - himax-hx8394: Support for Huiling hl055fhv028c - ilitek-ili9881c: Support for 7" Raspberry Pi 720x1280 - panel-edp: Support for KDC KD116N3730A05, N160JCE-ELL CMN, - panel-simple: Support for AUO P238HAN01 - st7701: Support for Winstar wf40eswaa6mnn0 - visionox-rm69299: Support for rm69299-shift - New panels: Renesas R61307, Renesas R69328 Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maxime Ripard <mripard@redhat.com> Link: https://lore.kernel.org/r/20250612-coucal-of-impossible-cleaning-a5eecf@houat
This commit is contained in:
18
Documentation/ABI/testing/sysfs-driver-qaic
Normal file
18
Documentation/ABI/testing/sysfs-driver-qaic
Normal file
@@ -0,0 +1,18 @@
|
||||
What: /sys/bus/pci/drivers/qaic/XXXX:XX:XX.X/ce_count
|
||||
Date: May 2025
|
||||
KernelVersion: 6.17
|
||||
Contact: dri-devel@lists.freedesktop.org
|
||||
Description: Number of correctable errors received from device since driver is loaded.
|
||||
|
||||
What: /sys/bus/pci/drivers/qaic/XXXX:XX:XX.X/ue_count
|
||||
Date: May 2025
|
||||
KernelVersion: 6.17
|
||||
Contact: dri-devel@lists.freedesktop.org
|
||||
Description: Number of uncorrectable errors received from device since driver is loaded.
|
||||
|
||||
What: /sys/bus/pci/drivers/qaic/XXXX:XX:XX.X/ue_nonfatal_count
|
||||
Date: May 2025
|
||||
KernelVersion: 6.17
|
||||
Contact: dri-devel@lists.freedesktop.org
|
||||
Description: Number of uncorrectable non-fatal errors received from device since driver
|
||||
is loaded.
|
||||
@@ -24,9 +24,11 @@ properties:
|
||||
- allwinner,sun50i-a64-de2-mixer-0
|
||||
- allwinner,sun50i-a64-de2-mixer-1
|
||||
- allwinner,sun50i-h6-de3-mixer-0
|
||||
- allwinner,sun50i-h616-de33-mixer-0
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
reg: true
|
||||
|
||||
reg-names: true
|
||||
|
||||
clocks:
|
||||
items:
|
||||
@@ -61,6 +63,34 @@ properties:
|
||||
required:
|
||||
- port@1
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- allwinner,sun50i-h616-de33-mixer-0
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
description: |
|
||||
Registers for controlling individual layers of the display
|
||||
engine (layers), global control (top), and display blending
|
||||
control (display). Names are from Allwinner BSP kernel.
|
||||
maxItems: 3
|
||||
reg-names:
|
||||
items:
|
||||
- const: layers
|
||||
- const: top
|
||||
- const: display
|
||||
required:
|
||||
- reg-names
|
||||
|
||||
else:
|
||||
properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-axi-performance-counter.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX8qxp Display Controller AXI Performance Counter
|
||||
|
||||
description: |
|
||||
Performance counters are provided to allow measurement of average bandwidth
|
||||
and latency during operation. The following features are supported:
|
||||
|
||||
* Manual and timer controlled measurement mode.
|
||||
|
||||
* Measurement counters:
|
||||
- GLOBAL_COUNTER for overall measurement time
|
||||
- BUSY_COUNTER for number of data bus busy cycles
|
||||
- DATA_COUNTER for number of data transfer cycles
|
||||
- TRANSFER_COUNTER for number of transfers
|
||||
- ADDRBUSY_COUNTER for number of address bus busy cycles
|
||||
- LATENCY_COUNTER for average latency
|
||||
|
||||
* Counter overflow detection.
|
||||
|
||||
* Outstanding Transfer Counters (OTC) which are used for latency measurement
|
||||
have to run immediately after reset, but can be disabled by software when
|
||||
there is no need for latency measurement.
|
||||
|
||||
maintainers:
|
||||
- Liu Ying <victor.liu@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-axi-performance-counter
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/imx8-lpcg.h>
|
||||
|
||||
pmu@5618f000 {
|
||||
compatible = "fsl,imx8qxp-dc-axi-performance-counter";
|
||||
reg = <0x5618f000 0x90>;
|
||||
clocks = <&dc0_lpcg IMX_LPCG_CLK_5>;
|
||||
};
|
||||
@@ -0,0 +1,204 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-blit-engine.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX8qxp Display Controller Blit Engine
|
||||
|
||||
description: |
|
||||
A blit operation (block based image transfer) reads up to 3 source images
|
||||
from memory and computes one destination image from it, which is written
|
||||
back to memory. The following basic operations are supported:
|
||||
|
||||
* Buffer Fill
|
||||
Fills a buffer with constant color
|
||||
|
||||
* Buffer Copy
|
||||
Copies one source to a destination buffer.
|
||||
|
||||
* Image Blend
|
||||
Combines two source images by a blending equation and writes result to
|
||||
destination (which can be one of the sources).
|
||||
|
||||
* Image Rop2/3
|
||||
Combines up to three source images by a logical equation (raster operation)
|
||||
and writes result to destination (which can be one of the sources).
|
||||
|
||||
* Image Flip
|
||||
Mirrors the source image in horizontal and/or vertical direction.
|
||||
|
||||
* Format Convert
|
||||
Convert between the supported color and buffer formats.
|
||||
|
||||
* Color Transform
|
||||
Modify colors by linear or non-linear transformations.
|
||||
|
||||
* Image Scale
|
||||
Changes size of the source image.
|
||||
|
||||
* Image Rotate
|
||||
Rotates the source image by any angle.
|
||||
|
||||
* Image Filter
|
||||
Performs an FIR filter operation on the source image.
|
||||
|
||||
* Image Warp
|
||||
Performs a re-sampling of the source image with any pattern. The sample
|
||||
point positions are read from a compressed coordinate buffer.
|
||||
|
||||
* Buffer Pack
|
||||
Writes an image with color components stored in up to three different
|
||||
buffers (planar formats) into a single buffer (packed format).
|
||||
|
||||
* Chroma Resample
|
||||
Converts between different YUV formats that differ in chroma sampling rate
|
||||
(4:4:4, 4:2:2, 4:2:0).
|
||||
|
||||
maintainers:
|
||||
- Liu Ying <victor.liu@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-blit-engine
|
||||
|
||||
reg:
|
||||
maxItems: 2
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: pec
|
||||
- const: cfg
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 1
|
||||
|
||||
ranges: true
|
||||
|
||||
patternProperties:
|
||||
"^blitblend@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-blitblend
|
||||
|
||||
"^clut@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-clut
|
||||
|
||||
"^fetchdecode@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-fetchdecode
|
||||
|
||||
"^fetcheco@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-fetcheco
|
||||
|
||||
"^fetchwarp@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-fetchwarp
|
||||
|
||||
"^filter@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-filter
|
||||
|
||||
"^hscaler@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-hscaler
|
||||
|
||||
"^matrix@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-matrix
|
||||
|
||||
"^rop@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-rop
|
||||
|
||||
"^store@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-store
|
||||
|
||||
"^vscaler@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-vscaler
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
- ranges
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
blit-engine@56180820 {
|
||||
compatible = "fsl,imx8qxp-dc-blit-engine";
|
||||
reg = <0x56180820 0x13c>, <0x56181000 0x3400>;
|
||||
reg-names = "pec", "cfg";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
fetchdecode@56180820 {
|
||||
compatible = "fsl,imx8qxp-dc-fetchdecode";
|
||||
reg = <0x56180820 0x10>, <0x56181000 0x404>;
|
||||
reg-names = "pec", "cfg";
|
||||
};
|
||||
|
||||
store@56180940 {
|
||||
compatible = "fsl,imx8qxp-dc-store";
|
||||
reg = <0x56180940 0x1c>, <0x56184000 0x5c>;
|
||||
reg-names = "pec", "cfg";
|
||||
interrupt-parent = <&dc0_intc>;
|
||||
interrupts = <0>, <1>, <2>;
|
||||
interrupt-names = "shdload", "framecomplete", "seqcomplete";
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,41 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-blitblend.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX8qxp Display Controller Blit Blend Unit
|
||||
|
||||
description:
|
||||
Combines two input frames to a single output frame, all frames having the
|
||||
same dimension.
|
||||
|
||||
maintainers:
|
||||
- Liu Ying <victor.liu@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-blitblend
|
||||
|
||||
reg:
|
||||
maxItems: 2
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: pec
|
||||
- const: cfg
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
blitblend@56180920 {
|
||||
compatible = "fsl,imx8qxp-dc-blitblend";
|
||||
reg = <0x56180920 0x10>, <0x56183c00 0x3c>;
|
||||
reg-names = "pec", "cfg";
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-clut.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX8qxp Display Controller Color Lookup Table
|
||||
|
||||
description: |
|
||||
The unit implements 3 look-up tables with 256 x 10 bit entries each. These
|
||||
can be used for different kinds of applications. From 10-bit input values
|
||||
only upper 8 bits are used.
|
||||
|
||||
The unit supports color lookup, index lookup, dithering and alpha masking.
|
||||
|
||||
maintainers:
|
||||
- Liu Ying <victor.liu@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-clut
|
||||
|
||||
reg:
|
||||
maxItems: 2
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: pec
|
||||
- const: cfg
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
clut@56180880 {
|
||||
compatible = "fsl,imx8qxp-dc-clut";
|
||||
reg = <0x56180880 0x10>, <0x56182400 0x404>;
|
||||
reg-names = "pec", "cfg";
|
||||
};
|
||||
@@ -0,0 +1,67 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-command-sequencer.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX8qxp Display Controller Command Sequencer
|
||||
|
||||
description: |
|
||||
The Command Sequencer is designed to autonomously process command lists.
|
||||
By that it can load setups into the DC configuration and synchronize to
|
||||
hardware events. This releases a system's CPU from workload, because it
|
||||
does not need to wait for certain events. Also it simplifies SW architecture,
|
||||
because no interrupt handlers are required. Setups are read via AXI bus,
|
||||
while write access to configuration registers occurs directly via an internal
|
||||
bus. This saves bandwidth for the AXI interconnect and improves the system
|
||||
architecture in terms of safety aspects.
|
||||
|
||||
maintainers:
|
||||
- Liu Ying <victor.liu@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-command-sequencer
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 5
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: error
|
||||
- const: sw0
|
||||
- const: sw1
|
||||
- const: sw2
|
||||
- const: sw3
|
||||
|
||||
sram:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: phandle pointing to the mmio-sram device node
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/imx8-lpcg.h>
|
||||
|
||||
command-sequencer@56180400 {
|
||||
compatible = "fsl,imx8qxp-dc-command-sequencer";
|
||||
reg = <0x56180400 0x1a4>;
|
||||
clocks = <&dc0_lpcg IMX_LPCG_CLK_5>;
|
||||
interrupt-parent = <&dc0_intc>;
|
||||
interrupts = <36>, <37>, <38>, <39>, <40>;
|
||||
interrupt-names = "error", "sw0", "sw1", "sw2", "sw3";
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-constframe.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX8qxp Display Controller Constant Frame
|
||||
|
||||
description: |
|
||||
The Constant Frame unit is used instead of a Fetch unit where generation of
|
||||
constant color frames only is sufficient. This is the case for the background
|
||||
planes of content and safety streams in a Display Controller.
|
||||
|
||||
The color can be setup to any RGBA value.
|
||||
|
||||
maintainers:
|
||||
- Liu Ying <victor.liu@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-constframe
|
||||
|
||||
reg:
|
||||
maxItems: 2
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: pec
|
||||
- const: cfg
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
constframe@56180960 {
|
||||
compatible = "fsl,imx8qxp-dc-constframe";
|
||||
reg = <0x56180960 0xc>, <0x56184400 0x20>;
|
||||
reg-names = "pec", "cfg";
|
||||
};
|
||||
@@ -0,0 +1,152 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-display-engine.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX8qxp Display Controller Display Engine
|
||||
|
||||
description:
|
||||
All Processing Units that operate in a display clock domain. Pixel pipeline
|
||||
is driven by a video timing and cannot be stalled. Implements all display
|
||||
specific processing.
|
||||
|
||||
maintainers:
|
||||
- Liu Ying <victor.liu@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-display-engine
|
||||
|
||||
reg:
|
||||
maxItems: 2
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: top
|
||||
- const: cfg
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 3
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: shdload
|
||||
- const: framecomplete
|
||||
- const: seqcomplete
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 1
|
||||
|
||||
ranges: true
|
||||
|
||||
patternProperties:
|
||||
"^dither@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-dither
|
||||
|
||||
"^framegen@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-framegen
|
||||
|
||||
"^gammacor@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-gammacor
|
||||
|
||||
"^matrix@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-matrix
|
||||
|
||||
"^signature@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-signature
|
||||
|
||||
"^tcon@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-tcon
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
- power-domains
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
- ranges
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/imx8-lpcg.h>
|
||||
#include <dt-bindings/firmware/imx/rsrc.h>
|
||||
|
||||
display-engine@5618b400 {
|
||||
compatible = "fsl,imx8qxp-dc-display-engine";
|
||||
reg = <0x5618b400 0x14>, <0x5618b800 0x1c00>;
|
||||
reg-names = "top", "cfg";
|
||||
interrupt-parent = <&dc0_intc>;
|
||||
interrupts = <15>, <16>, <17>;
|
||||
interrupt-names = "shdload", "framecomplete", "seqcomplete";
|
||||
power-domains = <&pd IMX_SC_R_DC_0_PLL_0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
framegen@5618b800 {
|
||||
compatible = "fsl,imx8qxp-dc-framegen";
|
||||
reg = <0x5618b800 0x98>;
|
||||
clocks = <&dc0_disp_lpcg IMX_LPCG_CLK_0>;
|
||||
interrupt-parent = <&dc0_intc>;
|
||||
interrupts = <18>, <19>, <20>, <21>, <41>, <42>, <43>, <44>;
|
||||
interrupt-names = "int0", "int1", "int2", "int3",
|
||||
"primsync_on", "primsync_off",
|
||||
"secsync_on", "secsync_off";
|
||||
};
|
||||
|
||||
tcon@5618c800 {
|
||||
compatible = "fsl,imx8qxp-dc-tcon";
|
||||
reg = <0x5618c800 0x588>;
|
||||
|
||||
port {
|
||||
dc0_disp0_dc0_pixel_combiner_ch0: endpoint {
|
||||
remote-endpoint = <&dc0_pixel_combiner_ch0_dc0_disp0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-dither.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX8qxp Display Controller Dither Unit
|
||||
|
||||
description: |
|
||||
The unit can increase the physical color resolution of a display from 5, 6, 7
|
||||
or 8 bits per RGB channel to a virtual resolution of 10 bits. The physical
|
||||
resolution can be set individually for each channel.
|
||||
|
||||
The resolution is increased by mixing the two physical colors that are nearest
|
||||
to the virtual color code in a variable ratio either by time (temporal
|
||||
dithering) or by position (spatial dithering).
|
||||
|
||||
An optimized algorithm for temporal dithering minimizes noise artifacts on the
|
||||
output image.
|
||||
|
||||
The dither operation can be individually enabled or disabled for each pixel
|
||||
using the alpha input bit.
|
||||
|
||||
maintainers:
|
||||
- Liu Ying <victor.liu@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-dither
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
dither@5618c400 {
|
||||
compatible = "fsl,imx8qxp-dc-dither";
|
||||
reg = <0x5618c400 0x14>;
|
||||
};
|
||||
@@ -0,0 +1,72 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-extdst.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX8qxp Display Controller External Destination Interface
|
||||
|
||||
description: |
|
||||
The External Destination unit is the interface between the internal pixel
|
||||
processing pipeline of the Pixel Engine, which is 30-bit RGB plus 8-bit Alpha,
|
||||
and a Display Engine.
|
||||
|
||||
It comprises the following built-in Gamma apply function.
|
||||
|
||||
+------X-----------------------+
|
||||
| | ExtDst Unit |
|
||||
| V |
|
||||
| +-------+ |
|
||||
| | Gamma | |
|
||||
| +-------+ |
|
||||
| | |
|
||||
| V +
|
||||
+------X-----------------------+
|
||||
|
||||
The output format is 24-bit RGB plus 1-bit Alpha. Conversion from 10 to 8
|
||||
bits is done by LSBit truncation. Alpha output bit is 1 for input 255, 0
|
||||
otherwise.
|
||||
|
||||
maintainers:
|
||||
- Liu Ying <victor.liu@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-extdst
|
||||
|
||||
reg:
|
||||
maxItems: 2
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: pec
|
||||
- const: cfg
|
||||
|
||||
interrupts:
|
||||
maxItems: 3
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: shdload
|
||||
- const: framecomplete
|
||||
- const: seqcomplete
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
extdst@56180980 {
|
||||
compatible = "fsl,imx8qxp-dc-extdst";
|
||||
reg = <0x56180980 0x1c>, <0x56184800 0x28>;
|
||||
reg-names = "pec", "cfg";
|
||||
interrupt-parent = <&dc0_intc>;
|
||||
interrupts = <3>, <4>, <5>;
|
||||
interrupt-names = "shdload", "framecomplete", "seqcomplete";
|
||||
};
|
||||
@@ -0,0 +1,141 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-fetchunit.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX8qxp Display Controller Fetch Unit
|
||||
|
||||
description: |
|
||||
The Fetch Unit is the interface between the AXI bus for source buffer access
|
||||
and the internal pixel processing pipeline, which is 30-bit RGB plus 8-bit
|
||||
Alpha.
|
||||
|
||||
It is used to generate foreground planes in Display Controllers and source
|
||||
planes in Blit Engines, and comprises the following built-in functions to
|
||||
convert a wide range of frame buffer types.
|
||||
|
||||
+---------X-----------------------------------------+
|
||||
| | Fetch Unit |
|
||||
| V |
|
||||
| +---------+ |
|
||||
| | | |
|
||||
| | Decode | Decompression [Decode] |
|
||||
| | | |
|
||||
| +---------+ |
|
||||
| | |
|
||||
| V |
|
||||
| +---------+ |
|
||||
| | Clip & | Clip Window [All] |
|
||||
| | Overlay | Plane composition [Layer, Warp] |
|
||||
| | | |
|
||||
| +---------+ |
|
||||
| | |
|
||||
| V |
|
||||
| +---------+ |
|
||||
| | Re- | Flip/Rotate/Repl./Drop [All] |
|
||||
X--> | sample | Perspective/Affine warping [Persp] |
|
||||
| | | | Arbitrary warping [Warp, Persp] |
|
||||
| | +---------+ |
|
||||
| | | |
|
||||
| | V |
|
||||
| | +---------+ |
|
||||
| | | | |
|
||||
| | | Palette | Color Palette [Layer, Decode] |
|
||||
| | | | |
|
||||
| | +---------+ |
|
||||
| | | |
|
||||
| | V |
|
||||
| | +---------+ |
|
||||
| | | Extract | Raw to RGBA/YUV [All] |
|
||||
| | | & | Bit width expansion [All] |
|
||||
| | | Expand | |
|
||||
| | +---------+ |
|
||||
| | | |
|
||||
| | V |
|
||||
| | +---------+ |
|
||||
| | | | Planar to packed |
|
||||
| |->| Combine | [Decode, Warp, Persp] |
|
||||
| | | | |
|
||||
| | +---------+ |
|
||||
| | | |
|
||||
| | V |
|
||||
| | +---------+ |
|
||||
| | | | YUV422 to YUV444 |
|
||||
| | | Chroma | [Decode, Persp] |
|
||||
| | | | |
|
||||
| | +---------+ |
|
||||
| | | |
|
||||
| | V |
|
||||
| | +---------+ |
|
||||
| | | | YUV to RGB |
|
||||
| | | Color | [Warp, Persp, Decode, Layer] |
|
||||
| | | | |
|
||||
| | +---------+ |
|
||||
| | | |
|
||||
| | V |
|
||||
| | +---------+ |
|
||||
| | | | Gamma removal |
|
||||
| | | Gamma | [Warp, Persp, Decode, Layer] |
|
||||
| | | | |
|
||||
| | +---------+ |
|
||||
| | | |
|
||||
| | V |
|
||||
| | +---------+ |
|
||||
| | | | Alpla multiply, RGB pre-multiply |
|
||||
| ->| Multiply| [Warp, Persp, Decode, Layer] |
|
||||
| | | |
|
||||
| --------- |
|
||||
| | |
|
||||
| V |
|
||||
| +---------+ |
|
||||
| | | Bilinear filter |
|
||||
| | Filter | [Warp, Persp] |
|
||||
| | | |
|
||||
| +---------+ |
|
||||
| | |
|
||||
| V |
|
||||
+---------X-----------------------------------------+
|
||||
|
||||
Note that different derivatives of the Fetch Unit exist. Each implements a
|
||||
specific subset only of the pipeline stages shown above. Restrictions for the
|
||||
units are specified in [square brackets].
|
||||
|
||||
maintainers:
|
||||
- Liu Ying <victor.liu@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- fsl,imx8qxp-dc-fetchdecode
|
||||
- fsl,imx8qxp-dc-fetcheco
|
||||
- fsl,imx8qxp-dc-fetchlayer
|
||||
- fsl,imx8qxp-dc-fetchwarp
|
||||
|
||||
reg:
|
||||
maxItems: 2
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: pec
|
||||
- const: cfg
|
||||
|
||||
fsl,prg:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
Optional Prefetch Resolve Gasket associated with the Fetch Unit.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
fetchlayer@56180ac0 {
|
||||
compatible = "fsl,imx8qxp-dc-fetchlayer";
|
||||
reg = <0x56180ac0 0xc>, <0x56188400 0x404>;
|
||||
reg-names = "pec", "cfg";
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-filter.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX8qxp Display Controller Filter Unit
|
||||
|
||||
description: |
|
||||
5x5 FIR filter with 25 programmable coefficients.
|
||||
|
||||
Typical applications are image blurring, sharpening or support for edge
|
||||
detection algorithms.
|
||||
|
||||
maintainers:
|
||||
- Liu Ying <victor.liu@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-filter
|
||||
|
||||
reg:
|
||||
maxItems: 2
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: pec
|
||||
- const: cfg
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
filter@56180900 {
|
||||
compatible = "fsl,imx8qxp-dc-filter";
|
||||
reg = <0x56180900 0x10>, <0x56183800 0x30>;
|
||||
reg-names = "pec", "cfg";
|
||||
};
|
||||
@@ -0,0 +1,64 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-framegen.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX8qxp Display Controller Frame Generator
|
||||
|
||||
description:
|
||||
The Frame Generator (FrameGen) module generates a programmable video timing
|
||||
and optionally allows to synchronize the generated video timing to external
|
||||
synchronization signals.
|
||||
|
||||
maintainers:
|
||||
- Liu Ying <victor.liu@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-framegen
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 8
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: int0
|
||||
- const: int1
|
||||
- const: int2
|
||||
- const: int3
|
||||
- const: primsync_on
|
||||
- const: primsync_off
|
||||
- const: secsync_on
|
||||
- const: secsync_off
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/imx8-lpcg.h>
|
||||
#include <dt-bindings/firmware/imx/rsrc.h>
|
||||
|
||||
framegen@5618b800 {
|
||||
compatible = "fsl,imx8qxp-dc-framegen";
|
||||
reg = <0x5618b800 0x98>;
|
||||
clocks = <&dc0_disp_lpcg IMX_LPCG_CLK_0>;
|
||||
interrupt-parent = <&dc0_intc>;
|
||||
interrupts = <18>, <19>, <20>, <21>, <41>, <42>, <43>, <44>;
|
||||
interrupt-names = "int0", "int1", "int2", "int3",
|
||||
"primsync_on", "primsync_off",
|
||||
"secsync_on", "secsync_off";
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-gammacor.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX8qxp Display Controller Gamma Correction Unit
|
||||
|
||||
description: The unit supports non-linear color transformation.
|
||||
|
||||
maintainers:
|
||||
- Liu Ying <victor.liu@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-gammacor
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
gammacor@5618c000 {
|
||||
compatible = "fsl,imx8qxp-dc-gammacor";
|
||||
reg = <0x5618c000 0x20>;
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-layerblend.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX8qxp Display Controller Layer Blend Unit
|
||||
|
||||
description: Combines two input frames to a single output frame.
|
||||
|
||||
maintainers:
|
||||
- Liu Ying <victor.liu@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-layerblend
|
||||
|
||||
reg:
|
||||
maxItems: 2
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: pec
|
||||
- const: cfg
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
layerblend@56180ba0 {
|
||||
compatible = "fsl,imx8qxp-dc-layerblend";
|
||||
reg = <0x56180ba0 0x10>, <0x5618a400 0x20>;
|
||||
reg-names = "pec", "cfg";
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-matrix.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX8qxp Display Controller Color Matrix
|
||||
|
||||
description:
|
||||
The unit supports linear color transformation, alpha pre-multiply and
|
||||
alpha masking.
|
||||
|
||||
maintainers:
|
||||
- Liu Ying <victor.liu@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-matrix
|
||||
|
||||
reg:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
reg-names:
|
||||
oneOf:
|
||||
- const: cfg # matrix in display engine
|
||||
- items: # matrix in pixel engine
|
||||
- const: pec
|
||||
- const: cfg
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
matrix@5618bc00 {
|
||||
compatible = "fsl,imx8qxp-dc-matrix";
|
||||
reg = <0x5618bc00 0x3c>;
|
||||
reg-names = "cfg";
|
||||
};
|
||||
@@ -0,0 +1,250 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-pixel-engine.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX8qxp Display Controller Pixel Engine
|
||||
|
||||
description:
|
||||
All Processing Units that operate in the AXI bus clock domain. Pixel
|
||||
pipelines have the ability to stall when a destination is busy. Implements
|
||||
all communication to memory resources and most of the image processing
|
||||
functions. Interconnection of Processing Units is re-configurable.
|
||||
|
||||
maintainers:
|
||||
- Liu Ying <victor.liu@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-pixel-engine
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 1
|
||||
|
||||
ranges: true
|
||||
|
||||
patternProperties:
|
||||
"^blit-engine@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-blit-engine
|
||||
|
||||
"^constframe@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-constframe
|
||||
|
||||
"^extdst@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-extdst
|
||||
|
||||
"^fetchdecode@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-fetchdecode
|
||||
|
||||
"^fetcheco@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-fetcheco
|
||||
|
||||
"^fetchlayer@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-fetchlayer
|
||||
|
||||
"^fetchwarp@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-fetchwarp
|
||||
|
||||
"^hscaler@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-hscaler
|
||||
|
||||
"^layerblend@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-layerblend
|
||||
|
||||
"^matrix@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-matrix
|
||||
|
||||
"^safety@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-safety
|
||||
|
||||
"^vscaler@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-vscaler
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
- ranges
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/imx8-lpcg.h>
|
||||
|
||||
pixel-engine@56180800 {
|
||||
compatible = "fsl,imx8qxp-dc-pixel-engine";
|
||||
reg = <0x56180800 0xac00>;
|
||||
clocks = <&dc0_lpcg IMX_LPCG_CLK_5>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
constframe@56180960 {
|
||||
compatible = "fsl,imx8qxp-dc-constframe";
|
||||
reg = <0x56180960 0xc>, <0x56184400 0x20>;
|
||||
reg-names = "pec", "cfg";
|
||||
};
|
||||
|
||||
extdst@56180980 {
|
||||
compatible = "fsl,imx8qxp-dc-extdst";
|
||||
reg = <0x56180980 0x1c>, <0x56184800 0x28>;
|
||||
reg-names = "pec", "cfg";
|
||||
interrupt-parent = <&dc0_intc>;
|
||||
interrupts = <3>, <4>, <5>;
|
||||
interrupt-names = "shdload", "framecomplete", "seqcomplete";
|
||||
};
|
||||
|
||||
constframe@561809a0 {
|
||||
compatible = "fsl,imx8qxp-dc-constframe";
|
||||
reg = <0x561809a0 0xc>, <0x56184c00 0x20>;
|
||||
reg-names = "pec", "cfg";
|
||||
};
|
||||
|
||||
extdst@561809c0 {
|
||||
compatible = "fsl,imx8qxp-dc-extdst";
|
||||
reg = <0x561809c0 0x1c>, <0x56185000 0x28>;
|
||||
reg-names = "pec", "cfg";
|
||||
interrupt-parent = <&dc0_intc>;
|
||||
interrupts = <6>, <7>, <8>;
|
||||
interrupt-names = "shdload", "framecomplete", "seqcomplete";
|
||||
};
|
||||
|
||||
constframe@561809e0 {
|
||||
compatible = "fsl,imx8qxp-dc-constframe";
|
||||
reg = <0x561809e0 0xc>, <0x56185400 0x20>;
|
||||
reg-names = "pec", "cfg";
|
||||
};
|
||||
|
||||
extdst@56180a00 {
|
||||
compatible = "fsl,imx8qxp-dc-extdst";
|
||||
reg = <0x56180a00 0x1c>, <0x56185800 0x28>;
|
||||
reg-names = "pec", "cfg";
|
||||
interrupt-parent = <&dc0_intc>;
|
||||
interrupts = <9>, <10>, <11>;
|
||||
interrupt-names = "shdload", "framecomplete", "seqcomplete";
|
||||
};
|
||||
|
||||
constframe@56180a20 {
|
||||
compatible = "fsl,imx8qxp-dc-constframe";
|
||||
reg = <0x56180a20 0xc>, <0x56185c00 0x20>;
|
||||
reg-names = "pec", "cfg";
|
||||
};
|
||||
|
||||
extdst@56180a40 {
|
||||
compatible = "fsl,imx8qxp-dc-extdst";
|
||||
reg = <0x56180a40 0x1c>, <0x56186000 0x28>;
|
||||
reg-names = "pec", "cfg";
|
||||
interrupt-parent = <&dc0_intc>;
|
||||
interrupts = <12>, <13>, <14>;
|
||||
interrupt-names = "shdload", "framecomplete", "seqcomplete";
|
||||
};
|
||||
|
||||
fetchwarp@56180a60 {
|
||||
compatible = "fsl,imx8qxp-dc-fetchwarp";
|
||||
reg = <0x56180a60 0x10>, <0x56186400 0x190>;
|
||||
reg-names = "pec", "cfg";
|
||||
};
|
||||
|
||||
fetchlayer@56180ac0 {
|
||||
compatible = "fsl,imx8qxp-dc-fetchlayer";
|
||||
reg = <0x56180ac0 0xc>, <0x56188400 0x404>;
|
||||
reg-names = "pec", "cfg";
|
||||
};
|
||||
|
||||
layerblend@56180ba0 {
|
||||
compatible = "fsl,imx8qxp-dc-layerblend";
|
||||
reg = <0x56180ba0 0x10>, <0x5618a400 0x20>;
|
||||
reg-names = "pec", "cfg";
|
||||
};
|
||||
|
||||
layerblend@56180bc0 {
|
||||
compatible = "fsl,imx8qxp-dc-layerblend";
|
||||
reg = <0x56180bc0 0x10>, <0x5618a800 0x20>;
|
||||
reg-names = "pec", "cfg";
|
||||
};
|
||||
|
||||
layerblend@56180be0 {
|
||||
compatible = "fsl,imx8qxp-dc-layerblend";
|
||||
reg = <0x56180be0 0x10>, <0x5618ac00 0x20>;
|
||||
reg-names = "pec", "cfg";
|
||||
};
|
||||
|
||||
layerblend@56180c00 {
|
||||
compatible = "fsl,imx8qxp-dc-layerblend";
|
||||
reg = <0x56180c00 0x10>, <0x5618b000 0x20>;
|
||||
reg-names = "pec", "cfg";
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-rop.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX8qxp Display Controller Raster Operation Unit
|
||||
|
||||
description: |
|
||||
The unit can combine up to three input frames to a single output frame, all
|
||||
having the same dimension.
|
||||
|
||||
The unit supports logic operations, arithmetic operations and packing.
|
||||
|
||||
maintainers:
|
||||
- Liu Ying <victor.liu@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-rop
|
||||
|
||||
reg:
|
||||
maxItems: 2
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: pec
|
||||
- const: cfg
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
rop@56180860 {
|
||||
compatible = "fsl,imx8qxp-dc-rop";
|
||||
reg = <0x56180860 0x10>, <0x56182000 0x20>;
|
||||
reg-names = "pec", "cfg";
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-safety.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX8qxp Display Controller Safety Unit
|
||||
|
||||
description:
|
||||
The unit allows corresponding processing units to be configured in a path
|
||||
leading to multiple endpoints.
|
||||
|
||||
maintainers:
|
||||
- Liu Ying <victor.liu@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-safety
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
safety@56180800 {
|
||||
compatible = "fsl,imx8qxp-dc-safety";
|
||||
reg = <0x56180800 0x1c>;
|
||||
};
|
||||
@@ -0,0 +1,83 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-scaling-engine.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX8qxp Display Controller Scaling Engine
|
||||
|
||||
description: |
|
||||
The unit can change the dimension of the input frame by nearest or linear
|
||||
re-sampling with 1/32 sub pixel precision.
|
||||
|
||||
Internally it consist of two independent blocks for horizontal and vertical
|
||||
scaling. The sequence of both operations is arbitrary.
|
||||
|
||||
Any frame dimensions between 1 and 16384 pixels in width and height are
|
||||
supported, except that the vertical scaler has a frame width maximum
|
||||
depending of the system's functional limitations.
|
||||
|
||||
In general all scale factors are supported inside the supported frame
|
||||
dimensions. In range of scale factors 1/16..16 the filtered output colors
|
||||
are LSBit precise (e.g. DC ripple free).
|
||||
|
||||
+-----------+
|
||||
| Line |
|
||||
| Buffer |
|
||||
+-----------+
|
||||
^
|
||||
|
|
||||
V
|
||||
|\ +-----------+
|
||||
------+ | | |
|
||||
| | +-->| Vertical |----
|
||||
| ----+ | | Scaler | |
|
||||
| | |/ +-----------+ |
|
||||
| | |
|
||||
| | |
|
||||
| | | |\
|
||||
| ------------- -------------+-----+ |
|
||||
Input --+ X | +--> Output
|
||||
| ------------- -------------+-----+ |
|
||||
| | | |/
|
||||
| | |
|
||||
| | |\ +-----------+ |
|
||||
| ----+ | | | |
|
||||
| | +-->| Horizontal|----
|
||||
------+ | | Scaler |
|
||||
|/ +-----------+
|
||||
|
||||
The unit supports downscaling, upscaling, sub pixel translation and bob
|
||||
de-interlacing.
|
||||
|
||||
maintainers:
|
||||
- Liu Ying <victor.liu@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- fsl,imx8qxp-dc-hscaler
|
||||
- fsl,imx8qxp-dc-vscaler
|
||||
|
||||
reg:
|
||||
maxItems: 2
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: pec
|
||||
- const: cfg
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
hscaler@561808c0 {
|
||||
compatible = "fsl,imx8qxp-dc-hscaler";
|
||||
reg = <0x561808c0 0x10>, <0x56183000 0x18>;
|
||||
reg-names = "pec", "cfg";
|
||||
};
|
||||
@@ -0,0 +1,53 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-signature.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX8qxp Display Controller Signature Unit
|
||||
|
||||
description: |
|
||||
In order to control the correctness of display output, signature values can
|
||||
be computed for each frame and compared against reference values. In case of
|
||||
a mismatch (signature violation) a HW event can be triggered, for example a
|
||||
SW interrupt.
|
||||
|
||||
This unit supports signature computation, reference check, evaluation windows,
|
||||
alpha masking and panic modes.
|
||||
|
||||
maintainers:
|
||||
- Liu Ying <victor.liu@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-signature
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 3
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: shdload
|
||||
- const: valid
|
||||
- const: error
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
signature@5618d000 {
|
||||
compatible = "fsl,imx8qxp-dc-signature";
|
||||
reg = <0x5618d000 0x140>;
|
||||
interrupt-parent = <&dc0_intc>;
|
||||
interrupts = <22>, <23>, <24>;
|
||||
interrupt-names = "shdload", "valid", "error";
|
||||
};
|
||||
@@ -0,0 +1,96 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-store.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX8qxp Display Controller Store Unit
|
||||
|
||||
description: |
|
||||
The Store unit is the interface between the internal pixel processing
|
||||
pipeline, which is 30-bit RGB plus 8-bit Alpha, and the AXI bus for
|
||||
destination buffer access. It is used for the destination of Blit Engines.
|
||||
It comprises a set of built-in functions to generate a wide range of buffer
|
||||
formats. Note, that these are exactly inverse to corresponding functions in
|
||||
the Fetch Unit.
|
||||
|
||||
+------X-------------------------+
|
||||
| | Store Unit |
|
||||
| V |
|
||||
| +-------+ |
|
||||
| | Gamma | Gamma apply |
|
||||
| +-------+ |
|
||||
| | |
|
||||
| V |
|
||||
| +-------+ |
|
||||
| | Color | RGB to YUV |
|
||||
| +-------+ |
|
||||
| | |
|
||||
| V |
|
||||
| +-------+ |
|
||||
| | Chroma| YUV444 to 422 |
|
||||
| +-------+ |
|
||||
| | |
|
||||
| V |
|
||||
| +-------+ |
|
||||
| | Reduce| Bit width reduction |
|
||||
| | | dithering |
|
||||
| +-------+ |
|
||||
| | |
|
||||
| V |
|
||||
| +-------+ |
|
||||
| | Pack | RGBA/YUV to RAW |
|
||||
| | Encode| or Compression |
|
||||
| +-------+ |
|
||||
| | |
|
||||
| V |
|
||||
+------X-------------------------+
|
||||
|
||||
maintainers:
|
||||
- Liu Ying <victor.liu@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-store
|
||||
|
||||
reg:
|
||||
maxItems: 2
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: pec
|
||||
- const: cfg
|
||||
|
||||
interrupts:
|
||||
maxItems: 3
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: shdload
|
||||
- const: framecomplete
|
||||
- const: seqcomplete
|
||||
|
||||
fsl,lts:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
Optional Linear Tile Store associated with the Store Unit.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
store@56180940 {
|
||||
compatible = "fsl,imx8qxp-dc-store";
|
||||
reg = <0x56180940 0x1c>, <0x56184000 0x5c>;
|
||||
reg-names = "pec", "cfg";
|
||||
interrupt-parent = <&dc0_intc>;
|
||||
interrupts = <0>, <1>, <2>;
|
||||
interrupt-names = "shdload", "framecomplete", "seqcomplete";
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-tcon.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX8qxp Display Controller Timing Controller
|
||||
|
||||
description:
|
||||
The TCon can generate a wide range of customized synchronization signals and
|
||||
does the mapping of the color bits to the output.
|
||||
|
||||
maintainers:
|
||||
- Liu Ying <victor.liu@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-tcon
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
port:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: video output
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
tcon@5618c800 {
|
||||
compatible = "fsl,imx8qxp-dc-tcon";
|
||||
reg = <0x5618c800 0x588>;
|
||||
|
||||
port {
|
||||
dc0_disp0_dc0_pixel_combiner_ch0: endpoint {
|
||||
remote-endpoint = <&dc0_pixel_combiner_ch0_dc0_disp0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,236 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX8qxp Display Controller
|
||||
|
||||
description: |
|
||||
The Freescale i.MX8qxp Display Controller(DC) is comprised of three main
|
||||
components that include a blit engine for 2D graphics accelerations, display
|
||||
controller for display output processing, as well as a command sequencer.
|
||||
|
||||
Display buffers Source buffers
|
||||
(AXI read master) (AXI read master)
|
||||
| .......... | | | |
|
||||
+---------------------------+------------+------------------+-+-+------+
|
||||
| Display Controller (DC) | .......... | | | | |
|
||||
| | | | | | |
|
||||
| @@@@@@@@@@@ +----------+------------+------------+ | | | |
|
||||
A | | Command | | V V | | | | |
|
||||
X <-+->| Sequencer | | @@@@@@@@@@@@@@@@@@@@@@@@@@@@ | V V V |
|
||||
I | | (AXI CLK) | | | | | @@@@@@@@@@ |
|
||||
| @@@@@@@@@@@ | | Pixel Engine | | | | |
|
||||
| | | | (AXI CLK) | | | | |
|
||||
| V | @@@@@@@@@@@@@@@@@@@@@@@@@@@@ | | | |
|
||||
A | *********** | | | | | | | Blit | |
|
||||
H <-+->| Configure | | V V V V | | Engine | |
|
||||
B | | (CFG CLK) | | 00000000000 11111111111 | | (AXI CLK)| |
|
||||
| *********** | | Display | | Display | | | | |
|
||||
| | | Engine | | Engine | | | | |
|
||||
| | | (Disp CLK)| | (Disp CLK)| | | | |
|
||||
| @@@@@@@@@@@ | 00000000000 11111111111 | @@@@@@@@@@ |
|
||||
I | | Common | | | | | | |
|
||||
R <-+--| Control | | | Display | | | |
|
||||
Q | | (AXI CLK) | | | Controller | | | |
|
||||
| @@@@@@@@@@@ +------------------------------------+ | |
|
||||
| | | ^ | |
|
||||
+--------------------------+----------------+-------+---------+--------+
|
||||
^ | | | |
|
||||
| V V | V
|
||||
Clocks & Resets Display Display Panic Destination
|
||||
Output0 Output1 Control buffer
|
||||
(AXI write master)
|
||||
|
||||
maintainers:
|
||||
- Liu Ying <victor.liu@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 2
|
||||
|
||||
reset-names:
|
||||
items:
|
||||
- const: axi
|
||||
- const: cfg
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 1
|
||||
|
||||
ranges: true
|
||||
|
||||
patternProperties:
|
||||
"^command-sequencer@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-command-sequencer
|
||||
|
||||
"^display-engine@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-display-engine
|
||||
|
||||
"^interrupt-controller@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-intc
|
||||
|
||||
"^pixel-engine@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-pixel-engine
|
||||
|
||||
"^pmu@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-axi-performance-counter
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- power-domains
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
- ranges
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/imx8-lpcg.h>
|
||||
#include <dt-bindings/firmware/imx/rsrc.h>
|
||||
|
||||
display-controller@56180000 {
|
||||
compatible = "fsl,imx8qxp-dc";
|
||||
reg = <0x56180000 0x40000>;
|
||||
clocks = <&dc0_lpcg IMX_LPCG_CLK_4>;
|
||||
power-domains = <&pd IMX_SC_R_DC_0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
interrupt-controller@56180040 {
|
||||
compatible = "fsl,imx8qxp-dc-intc";
|
||||
reg = <0x56180040 0x60>;
|
||||
clocks = <&dc0_lpcg IMX_LPCG_CLK_5>;
|
||||
interrupt-controller;
|
||||
interrupt-parent = <&dc0_irqsteer>;
|
||||
#interrupt-cells = <1>;
|
||||
interrupts = <448>, <449>, <450>, <64>,
|
||||
<65>, <66>, <67>, <68>,
|
||||
<69>, <70>, <193>, <194>,
|
||||
<195>, <196>, <197>, <72>,
|
||||
<73>, <74>, <75>, <76>,
|
||||
<77>, <78>, <79>, <80>,
|
||||
<81>, <199>, <200>, <201>,
|
||||
<202>, <203>, <204>, <205>,
|
||||
<206>, <207>, <208>, <5>,
|
||||
<0>, <1>, <2>, <3>,
|
||||
<4>, <82>, <83>, <84>,
|
||||
<85>, <209>, <210>, <211>,
|
||||
<212>;
|
||||
interrupt-names = "store9_shdload",
|
||||
"store9_framecomplete",
|
||||
"store9_seqcomplete",
|
||||
"extdst0_shdload",
|
||||
"extdst0_framecomplete",
|
||||
"extdst0_seqcomplete",
|
||||
"extdst4_shdload",
|
||||
"extdst4_framecomplete",
|
||||
"extdst4_seqcomplete",
|
||||
"extdst1_shdload",
|
||||
"extdst1_framecomplete",
|
||||
"extdst1_seqcomplete",
|
||||
"extdst5_shdload",
|
||||
"extdst5_framecomplete",
|
||||
"extdst5_seqcomplete",
|
||||
"disengcfg_shdload0",
|
||||
"disengcfg_framecomplete0",
|
||||
"disengcfg_seqcomplete0",
|
||||
"framegen0_int0",
|
||||
"framegen0_int1",
|
||||
"framegen0_int2",
|
||||
"framegen0_int3",
|
||||
"sig0_shdload",
|
||||
"sig0_valid",
|
||||
"sig0_error",
|
||||
"disengcfg_shdload1",
|
||||
"disengcfg_framecomplete1",
|
||||
"disengcfg_seqcomplete1",
|
||||
"framegen1_int0",
|
||||
"framegen1_int1",
|
||||
"framegen1_int2",
|
||||
"framegen1_int3",
|
||||
"sig1_shdload",
|
||||
"sig1_valid",
|
||||
"sig1_error",
|
||||
"reserved",
|
||||
"cmdseq_error",
|
||||
"comctrl_sw0",
|
||||
"comctrl_sw1",
|
||||
"comctrl_sw2",
|
||||
"comctrl_sw3",
|
||||
"framegen0_primsync_on",
|
||||
"framegen0_primsync_off",
|
||||
"framegen0_secsync_on",
|
||||
"framegen0_secsync_off",
|
||||
"framegen1_primsync_on",
|
||||
"framegen1_primsync_off",
|
||||
"framegen1_secsync_on",
|
||||
"framegen1_secsync_off";
|
||||
};
|
||||
|
||||
pixel-engine@56180800 {
|
||||
compatible = "fsl,imx8qxp-dc-pixel-engine";
|
||||
reg = <0x56180800 0xac00>;
|
||||
clocks = <&dc0_lpcg IMX_LPCG_CLK_5>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
};
|
||||
|
||||
display-engine@5618b400 {
|
||||
compatible = "fsl,imx8qxp-dc-display-engine";
|
||||
reg = <0x5618b400 0x14>, <0x5618b800 0x1c00>;
|
||||
reg-names = "top", "cfg";
|
||||
interrupt-parent = <&dc0_intc>;
|
||||
interrupts = <15>, <16>, <17>;
|
||||
interrupt-names = "shdload", "framecomplete", "seqcomplete";
|
||||
power-domains = <&pd IMX_SC_R_DC_0_PLL_0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
};
|
||||
};
|
||||
@@ -17,12 +17,17 @@ description:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- hannstar,hsd060bhw4
|
||||
- microchip,ac40t08a-mipi-panel
|
||||
- powkiddy,x55-panel
|
||||
- const: himax,hx8394
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- hannstar,hsd060bhw4
|
||||
- microchip,ac40t08a-mipi-panel
|
||||
- powkiddy,x55-panel
|
||||
- const: himax,hx8394
|
||||
- items:
|
||||
- enum:
|
||||
- huiling,hl055fhav028c
|
||||
- const: himax,hx8399c
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@@ -19,6 +19,7 @@ properties:
|
||||
- ampire,am8001280g
|
||||
- bananapi,lhr050h41
|
||||
- feixin,k101-im2byl02
|
||||
- raspberrypi,dsi-7inch
|
||||
- startek,kd050hdfia020
|
||||
- tdo,tl050hdv35
|
||||
- wanchanglong,w552946aba
|
||||
|
||||
@@ -57,6 +57,8 @@ properties:
|
||||
- auo,g121ean01
|
||||
# AU Optronics Corporation 15.6" (1366x768) TFT LCD panel
|
||||
- auo,g156xtn01
|
||||
# AU Optronics Corporation 23.8" FHD (1920x1080) TFT LCD panel
|
||||
- auo,p238han01
|
||||
# AU Optronics Corporation 31.5" FHD (1920x1080) TFT LCD panel
|
||||
- auo,p320hvn03
|
||||
# AU Optronics Corporation 21.5" FHD (1920x1080) color TFT LCD panel
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/renesas,r61307.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Renesas R61307 based DSI Display Panel
|
||||
|
||||
maintainers:
|
||||
- Svyatoslav Ryhel <clamor95@gmail.com>
|
||||
|
||||
description:
|
||||
The Renesas R61307 is a generic DSI Panel IC used to control LCD panels.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
# KOE/HITACHI TX13D100VM0EAA 5.0" XGA TFT LCD panel
|
||||
- hit,tx13d100vm0eaa
|
||||
- koe,tx13d100vm0eaa
|
||||
- const: renesas,r61307
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vcc-supply:
|
||||
description: Regulator for main power supply.
|
||||
|
||||
iovcc-supply:
|
||||
description: Regulator for 1.8V IO power supply.
|
||||
|
||||
backlight: true
|
||||
|
||||
renesas,gamma:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
0 - disabled
|
||||
1-3 - gamma setting A presets
|
||||
enum: [0, 1, 2, 3]
|
||||
|
||||
renesas,column-inversion:
|
||||
type: boolean
|
||||
description: switch between line and column inversion. The line
|
||||
inversion is set by default.
|
||||
|
||||
renesas,contrast:
|
||||
type: boolean
|
||||
description: digital contrast adjustment
|
||||
|
||||
reset-gpios: true
|
||||
port: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- port
|
||||
- backlight
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
dsi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
panel@1 {
|
||||
compatible = "koe,tx13d100vm0eaa", "renesas,r61307";
|
||||
reg = <1>;
|
||||
|
||||
reset-gpios = <&gpio 176 GPIO_ACTIVE_LOW>;
|
||||
|
||||
renesas,gamma = <3>;
|
||||
renesas,column-inversion;
|
||||
renesas,contrast;
|
||||
|
||||
vcc-supply = <&vcc_3v0_lcd>;
|
||||
iovcc-supply = <&iovcc_1v8_lcd>;
|
||||
|
||||
backlight = <&backlight>;
|
||||
|
||||
port {
|
||||
panel_in: endpoint {
|
||||
remote-endpoint = <&dsi_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
@@ -0,0 +1,73 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/renesas,r69328.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Renesas R69328 based DSI Display Panel
|
||||
|
||||
maintainers:
|
||||
- Svyatoslav Ryhel <clamor95@gmail.com>
|
||||
|
||||
description:
|
||||
The Renesas R69328 is a generic DSI Panel IC used to control LCD panels.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
# JDI DX12D100VM0EAA 4.7" WXGA TFT LCD panel
|
||||
- jdi,dx12d100vm0eaa
|
||||
- const: renesas,r69328
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply:
|
||||
description: Regulator for main power supply.
|
||||
|
||||
vddio-supply:
|
||||
description: Regulator for 1.8V IO power supply.
|
||||
|
||||
backlight: true
|
||||
|
||||
reset-gpios: true
|
||||
port: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- port
|
||||
- backlight
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
dsi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
panel@1 {
|
||||
compatible = "jdi,dx12d100vm0eaa", "renesas,r69328";
|
||||
reg = <1>;
|
||||
|
||||
reset-gpios = <&gpio 176 GPIO_ACTIVE_LOW>;
|
||||
|
||||
vdd-supply = <&vdd_3v0_lcd>;
|
||||
vddio-supply = <&vdd_1v8_io>;
|
||||
|
||||
backlight = <&backlight>;
|
||||
|
||||
port {
|
||||
panel_in: endpoint {
|
||||
remote-endpoint = <&dsi_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
@@ -29,6 +29,7 @@ properties:
|
||||
- densitron,dmt028vghmcmi-1a
|
||||
- elida,kd50t048a
|
||||
- techstar,ts8550b
|
||||
- winstar,wf40eswaa6mnn0
|
||||
- const: sitronix,st7701
|
||||
|
||||
reg:
|
||||
|
||||
@@ -18,7 +18,9 @@ allOf:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: visionox,rm69299-1080p-display
|
||||
enum:
|
||||
- visionox,rm69299-1080p-display
|
||||
- visionox,rm69299-shift
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@@ -20,6 +20,7 @@ properties:
|
||||
- enum:
|
||||
- renesas,r9a07g043u-du # RZ/G2UL
|
||||
- renesas,r9a07g044-du # RZ/G2{L,LC}
|
||||
- renesas,r9a09g057-du # RZ/V2H(P)
|
||||
- items:
|
||||
- enum:
|
||||
- renesas,r9a07g054-du # RZ/V2L
|
||||
@@ -101,7 +102,12 @@ allOf:
|
||||
|
||||
required:
|
||||
- port@0
|
||||
else:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: renesas,r9a07g044-du
|
||||
then:
|
||||
properties:
|
||||
ports:
|
||||
properties:
|
||||
@@ -113,6 +119,21 @@ allOf:
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: renesas,r9a09g057-du
|
||||
then:
|
||||
properties:
|
||||
ports:
|
||||
properties:
|
||||
port@0:
|
||||
description: DSI
|
||||
port@1: false
|
||||
|
||||
required:
|
||||
- port@0
|
||||
|
||||
examples:
|
||||
# RZ/G2L DU
|
||||
|
||||
@@ -12,18 +12,25 @@ maintainers:
|
||||
- Tomi Valkeinen <tomi.valkeinen@ti.com>
|
||||
|
||||
description: |
|
||||
The AM625 and AM65x TI Keystone Display SubSystem with two output
|
||||
The AM625 and AM65x TI Keystone Display SubSystem has two output
|
||||
ports and two video planes. In AM65x DSS, the first video port
|
||||
supports 1 OLDI TX and in AM625 DSS, the first video port output is
|
||||
internally routed to 2 OLDI TXes. The second video port supports DPI
|
||||
format. The first plane is full video plane with all features and the
|
||||
second is a "lite plane" without scaling support.
|
||||
The AM62L display subsystem has a single output port which supports DPI
|
||||
format but it only supports single video "lite plane" which does not support
|
||||
scaling. The output port is routed to SoC boundary via DPI interface and same
|
||||
DPI signals are also routed internally to DSI Tx controller present within the
|
||||
SoC. Due to clocking limitations only one of the interface i.e. either DSI or
|
||||
DPI can be used at once.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- ti,am625-dss
|
||||
- ti,am62a7-dss
|
||||
- ti,am62l-dss
|
||||
- ti,am65x-dss
|
||||
|
||||
reg:
|
||||
@@ -91,6 +98,8 @@ properties:
|
||||
For AM625 DSS, the internal DPI output port node from video
|
||||
port 1.
|
||||
For AM62A7 DSS, the port is tied off inside the SoC.
|
||||
For AM62L DSS, the DSS DPI output port node from video port 1
|
||||
or DSI Tx controller node connected to video port 1.
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
@@ -123,6 +132,16 @@ allOf:
|
||||
ports:
|
||||
properties:
|
||||
port@0: false
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: ti,am62l-dss
|
||||
then:
|
||||
properties:
|
||||
ports:
|
||||
properties:
|
||||
port@1: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
@@ -47,6 +47,7 @@ properties:
|
||||
- hisilicon,hi6220-mali
|
||||
- mediatek,mt7623-mali
|
||||
- rockchip,rk3328-mali
|
||||
- rockchip,rk3528-mali
|
||||
- const: arm,mali-450
|
||||
|
||||
# "arm,mali-300"
|
||||
@@ -148,6 +149,7 @@ allOf:
|
||||
- rockchip,rk3188-mali
|
||||
- rockchip,rk3228-mali
|
||||
- rockchip,rk3328-mali
|
||||
- rockchip,rk3528-mali
|
||||
then:
|
||||
required:
|
||||
- resets
|
||||
|
||||
@@ -0,0 +1,318 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/interrupt-controller/fsl,imx8qxp-dc-intc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX8qxp Display Controller interrupt controller
|
||||
|
||||
description: |
|
||||
The Display Controller has a built-in interrupt controller with the following
|
||||
features for all relevant HW events:
|
||||
|
||||
* Enable bit (mask)
|
||||
* Status bit (set by an HW event)
|
||||
* Preset bit (can be used by SW to set status)
|
||||
* Clear bit (used by SW to reset the status)
|
||||
|
||||
Each interrupt can be connected as IRQ (maskable) and/or NMI (non-maskable).
|
||||
Alternatively the un-masked trigger signals for all HW events are provided,
|
||||
allowing it to use a global interrupt controller instead.
|
||||
|
||||
Each interrupt can be protected against SW running in user mode. In that case,
|
||||
only privileged AHB access can control the interrupt status.
|
||||
|
||||
maintainers:
|
||||
- Liu Ying <victor.liu@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx8qxp-dc-intc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
interrupt-controller: true
|
||||
|
||||
"#interrupt-cells":
|
||||
const: 1
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: store9 shadow load interrupt(blit engine)
|
||||
- description: store9 frame complete interrupt(blit engine)
|
||||
- description: store9 sequence complete interrupt(blit engine)
|
||||
- description:
|
||||
extdst0 shadow load interrupt
|
||||
(display controller, content stream 0)
|
||||
- description:
|
||||
extdst0 frame complete interrupt
|
||||
(display controller, content stream 0)
|
||||
- description:
|
||||
extdst0 sequence complete interrupt
|
||||
(display controller, content stream 0)
|
||||
- description:
|
||||
extdst4 shadow load interrupt
|
||||
(display controller, safety stream 0)
|
||||
- description:
|
||||
extdst4 frame complete interrupt
|
||||
(display controller, safety stream 0)
|
||||
- description:
|
||||
extdst4 sequence complete interrupt
|
||||
(display controller, safety stream 0)
|
||||
- description:
|
||||
extdst1 shadow load interrupt
|
||||
(display controller, content stream 1)
|
||||
- description:
|
||||
extdst1 frame complete interrupt
|
||||
(display controller, content stream 1)
|
||||
- description:
|
||||
extdst1 sequence complete interrupt
|
||||
(display controller, content stream 1)
|
||||
- description:
|
||||
extdst5 shadow load interrupt
|
||||
(display controller, safety stream 1)
|
||||
- description:
|
||||
extdst5 frame complete interrupt
|
||||
(display controller, safety stream 1)
|
||||
- description:
|
||||
extdst5 sequence complete interrupt
|
||||
(display controller, safety stream 1)
|
||||
- description:
|
||||
disengcfg0 shadow load interrupt
|
||||
(display controller, display stream 0)
|
||||
- description:
|
||||
disengcfg0 frame complete interrupt
|
||||
(display controller, display stream 0)
|
||||
- description:
|
||||
disengcfg0 sequence complete interrupt
|
||||
(display controller, display stream 0)
|
||||
- description:
|
||||
framegen0 programmable interrupt0
|
||||
(display controller, display stream 0)
|
||||
- description:
|
||||
framegen0 programmable interrupt1
|
||||
(display controller, display stream 0)
|
||||
- description:
|
||||
framegen0 programmable interrupt2
|
||||
(display controller, display stream 0)
|
||||
- description:
|
||||
framegen0 programmable interrupt3
|
||||
(display controller, display stream 0)
|
||||
- description:
|
||||
signature0 shadow load interrupt
|
||||
(display controller, display stream 0)
|
||||
- description:
|
||||
signature0 measurement valid interrupt
|
||||
(display controller, display stream 0)
|
||||
- description:
|
||||
signature0 error condition interrupt
|
||||
(display controller, display stream 0)
|
||||
- description:
|
||||
disengcfg1 shadow load interrupt
|
||||
(display controller, display stream 1)
|
||||
- description:
|
||||
disengcfg1 frame complete interrupt
|
||||
(display controller, display stream 1)
|
||||
- description:
|
||||
disengcfg1 sequence complete interrupt
|
||||
(display controller, display stream 1)
|
||||
- description:
|
||||
framegen1 programmable interrupt0
|
||||
(display controller, display stream 1)
|
||||
- description:
|
||||
framegen1 programmable interrupt1
|
||||
(display controller, display stream 1)
|
||||
- description:
|
||||
framegen1 programmable interrupt2
|
||||
(display controller, display stream 1)
|
||||
- description:
|
||||
framegen1 programmable interrupt3
|
||||
(display controller, display stream 1)
|
||||
- description:
|
||||
signature1 shadow load interrupt
|
||||
(display controller, display stream 1)
|
||||
- description:
|
||||
signature1 measurement valid interrupt
|
||||
(display controller, display stream 1)
|
||||
- description:
|
||||
signature1 error condition interrupt
|
||||
(display controller, display stream 1)
|
||||
- description: reserved
|
||||
- description:
|
||||
command sequencer error condition interrupt(command sequencer)
|
||||
- description:
|
||||
common control software interrupt0(common control)
|
||||
- description:
|
||||
common control software interrupt1(common control)
|
||||
- description:
|
||||
common control software interrupt2(common control)
|
||||
- description:
|
||||
common control software interrupt3(common control)
|
||||
- description:
|
||||
framegen0 synchronization status activated interrupt
|
||||
(display controller, safety stream 0)
|
||||
- description:
|
||||
framegen0 synchronization status deactivated interrupt
|
||||
(display controller, safety stream 0)
|
||||
- description:
|
||||
framegen0 synchronization status activated interrupt
|
||||
(display controller, content stream 0)
|
||||
- description:
|
||||
framegen0 synchronization status deactivated interrupt
|
||||
(display controller, content stream 0)
|
||||
- description:
|
||||
framegen1 synchronization status activated interrupt
|
||||
(display controller, safety stream 1)
|
||||
- description:
|
||||
framegen1 synchronization status deactivated interrupt
|
||||
(display controller, safety stream 1)
|
||||
- description:
|
||||
framegen1 synchronization status activated interrupt
|
||||
(display controller, content stream 1)
|
||||
- description:
|
||||
framegen1 synchronization status deactivated interrupt
|
||||
(display controller, content stream 1)
|
||||
minItems: 49
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: store9_shdload
|
||||
- const: store9_framecomplete
|
||||
- const: store9_seqcomplete
|
||||
- const: extdst0_shdload
|
||||
- const: extdst0_framecomplete
|
||||
- const: extdst0_seqcomplete
|
||||
- const: extdst4_shdload
|
||||
- const: extdst4_framecomplete
|
||||
- const: extdst4_seqcomplete
|
||||
- const: extdst1_shdload
|
||||
- const: extdst1_framecomplete
|
||||
- const: extdst1_seqcomplete
|
||||
- const: extdst5_shdload
|
||||
- const: extdst5_framecomplete
|
||||
- const: extdst5_seqcomplete
|
||||
- const: disengcfg_shdload0
|
||||
- const: disengcfg_framecomplete0
|
||||
- const: disengcfg_seqcomplete0
|
||||
- const: framegen0_int0
|
||||
- const: framegen0_int1
|
||||
- const: framegen0_int2
|
||||
- const: framegen0_int3
|
||||
- const: sig0_shdload
|
||||
- const: sig0_valid
|
||||
- const: sig0_error
|
||||
- const: disengcfg_shdload1
|
||||
- const: disengcfg_framecomplete1
|
||||
- const: disengcfg_seqcomplete1
|
||||
- const: framegen1_int0
|
||||
- const: framegen1_int1
|
||||
- const: framegen1_int2
|
||||
- const: framegen1_int3
|
||||
- const: sig1_shdload
|
||||
- const: sig1_valid
|
||||
- const: sig1_error
|
||||
- const: reserved
|
||||
- const: cmdseq_error
|
||||
- const: comctrl_sw0
|
||||
- const: comctrl_sw1
|
||||
- const: comctrl_sw2
|
||||
- const: comctrl_sw3
|
||||
- const: framegen0_primsync_on
|
||||
- const: framegen0_primsync_off
|
||||
- const: framegen0_secsync_on
|
||||
- const: framegen0_secsync_off
|
||||
- const: framegen1_primsync_on
|
||||
- const: framegen1_primsync_off
|
||||
- const: framegen1_secsync_on
|
||||
- const: framegen1_secsync_off
|
||||
minItems: 49
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- interrupt-controller
|
||||
- "#interrupt-cells"
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/imx8-lpcg.h>
|
||||
|
||||
interrupt-controller@56180040 {
|
||||
compatible = "fsl,imx8qxp-dc-intc";
|
||||
reg = <0x56180040 0x60>;
|
||||
clocks = <&dc0_lpcg IMX_LPCG_CLK_5>;
|
||||
interrupt-controller;
|
||||
interrupt-parent = <&dc0_irqsteer>;
|
||||
#interrupt-cells = <1>;
|
||||
interrupts = <448>, <449>, <450>, <64>,
|
||||
<65>, <66>, <67>, <68>,
|
||||
<69>, <70>, <193>, <194>,
|
||||
<195>, <196>, <197>, <72>,
|
||||
<73>, <74>, <75>, <76>,
|
||||
<77>, <78>, <79>, <80>,
|
||||
<81>, <199>, <200>, <201>,
|
||||
<202>, <203>, <204>, <205>,
|
||||
<206>, <207>, <208>, <5>,
|
||||
<0>, <1>, <2>, <3>,
|
||||
<4>, <82>, <83>, <84>,
|
||||
<85>, <209>, <210>, <211>,
|
||||
<212>;
|
||||
interrupt-names = "store9_shdload",
|
||||
"store9_framecomplete",
|
||||
"store9_seqcomplete",
|
||||
"extdst0_shdload",
|
||||
"extdst0_framecomplete",
|
||||
"extdst0_seqcomplete",
|
||||
"extdst4_shdload",
|
||||
"extdst4_framecomplete",
|
||||
"extdst4_seqcomplete",
|
||||
"extdst1_shdload",
|
||||
"extdst1_framecomplete",
|
||||
"extdst1_seqcomplete",
|
||||
"extdst5_shdload",
|
||||
"extdst5_framecomplete",
|
||||
"extdst5_seqcomplete",
|
||||
"disengcfg_shdload0",
|
||||
"disengcfg_framecomplete0",
|
||||
"disengcfg_seqcomplete0",
|
||||
"framegen0_int0",
|
||||
"framegen0_int1",
|
||||
"framegen0_int2",
|
||||
"framegen0_int3",
|
||||
"sig0_shdload",
|
||||
"sig0_valid",
|
||||
"sig0_error",
|
||||
"disengcfg_shdload1",
|
||||
"disengcfg_framecomplete1",
|
||||
"disengcfg_seqcomplete1",
|
||||
"framegen1_int0",
|
||||
"framegen1_int1",
|
||||
"framegen1_int2",
|
||||
"framegen1_int3",
|
||||
"sig1_shdload",
|
||||
"sig1_valid",
|
||||
"sig1_error",
|
||||
"reserved",
|
||||
"cmdseq_error",
|
||||
"comctrl_sw0",
|
||||
"comctrl_sw1",
|
||||
"comctrl_sw2",
|
||||
"comctrl_sw3",
|
||||
"framegen0_primsync_on",
|
||||
"framegen0_primsync_off",
|
||||
"framegen0_secsync_on",
|
||||
"framegen0_secsync_off",
|
||||
"framegen1_primsync_on",
|
||||
"framegen1_primsync_off",
|
||||
"framegen1_secsync_on",
|
||||
"framegen1_secsync_off";
|
||||
};
|
||||
@@ -672,6 +672,8 @@ patternProperties:
|
||||
description: Huawei Technologies Co., Ltd.
|
||||
"^hugsun,.*":
|
||||
description: Shenzhen Hugsun Technology Co. Ltd.
|
||||
"^huiling,.*":
|
||||
description: Shenzhen Huiling Information Technology Co., Ltd.
|
||||
"^hwacom,.*":
|
||||
description: HwaCom Systems Inc.
|
||||
"^hxt,.*":
|
||||
|
||||
@@ -693,3 +693,22 @@ dma-buf interoperability
|
||||
|
||||
Please see Documentation/userspace-api/dma-buf-alloc-exchange.rst for
|
||||
information on how dma-buf is integrated and exposed within DRM.
|
||||
|
||||
|
||||
Trace events
|
||||
============
|
||||
|
||||
See Documentation/trace/tracepoints.rst for information about using
|
||||
Linux Kernel Tracepoints.
|
||||
In the DRM subsystem, some events are considered stable uAPI to avoid
|
||||
breaking tools (e.g.: GPUVis, umr) relying on them. Stable means that fields
|
||||
cannot be removed, nor their formatting updated. Adding new fields is
|
||||
possible, under the normal uAPI requirements.
|
||||
|
||||
Stable uAPI events
|
||||
------------------
|
||||
|
||||
From ``drivers/gpu/drm/scheduler/gpu_scheduler_trace.h``
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/scheduler/gpu_scheduler_trace.h
|
||||
:doc: uAPI trace events
|
||||
@@ -515,6 +515,21 @@ Contact: Douglas Anderson <dianders@chromium.org>
|
||||
|
||||
Level: Starter
|
||||
|
||||
Remove devm_drm_put_bridge()
|
||||
----------------------------
|
||||
|
||||
Due to how the panel bridge handles the drm_bridge object lifetime, special
|
||||
care must be taken to dispose of the drm_bridge object when the
|
||||
panel_bridge is removed. This is currently managed using
|
||||
devm_drm_put_bridge(), but that is an unsafe, temporary workaround. To fix
|
||||
that, the DRM panel lifetime needs to be reworked. After the rework is
|
||||
done, remove devm_drm_put_bridge() and the TODO in
|
||||
drm_panel_bridge_remove().
|
||||
|
||||
Contact: Maxime Ripard <mripard@kernel.org>,
|
||||
Luca Ceresoli <luca.ceresoli@bootlin.com>
|
||||
|
||||
Level: Intermediate
|
||||
|
||||
Core refactorings
|
||||
=================
|
||||
|
||||
@@ -89,6 +89,17 @@ You can also run subtests if you do not want to run the entire test::
|
||||
sudo ./build/tests/kms_flip --run-subtest basic-plain-flip --device "sys:/sys/devices/platform/vkms"
|
||||
sudo IGT_DEVICE="sys:/sys/devices/platform/vkms" ./build/tests/kms_flip --run-subtest basic-plain-flip
|
||||
|
||||
Testing With KUnit
|
||||
==================
|
||||
|
||||
KUnit (Kernel unit testing framework) provides a common framework for unit tests
|
||||
within the Linux kernel.
|
||||
More information in ../dev-tools/kunit/index.rst .
|
||||
|
||||
To run the VKMS KUnit tests::
|
||||
|
||||
tools/testing/kunit/kunit.py run --kunitconfig=drivers/gpu/drm/vkms/tests
|
||||
|
||||
TODO
|
||||
====
|
||||
|
||||
@@ -122,8 +133,8 @@ There's lots of plane features we could add support for:
|
||||
|
||||
- Scaling.
|
||||
|
||||
- Additional buffer formats, especially YUV formats for video like NV12.
|
||||
Low/high bpp RGB formats would also be interesting.
|
||||
- Additional buffer formats. Low/high bpp RGB formats would be interesting
|
||||
[Good to get started].
|
||||
|
||||
- Async updates (currently only possible on cursor plane using the legacy
|
||||
cursor api).
|
||||
|
||||
39
MAINTAINERS
39
MAINTAINERS
@@ -8064,6 +8064,14 @@ F: Documentation/devicetree/bindings/display/imx/
|
||||
F: drivers/gpu/drm/imx/ipuv3/
|
||||
F: drivers/gpu/ipu-v3/
|
||||
|
||||
DRM DRIVERS FOR FREESCALE IMX8 DISPLAY CONTROLLER
|
||||
M: Liu Ying <victor.liu@nxp.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc*.yaml
|
||||
F: drivers/gpu/drm/imx/dc/
|
||||
|
||||
DRM DRIVERS FOR FREESCALE IMX BRIDGE
|
||||
M: Liu Ying <victor.liu@nxp.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
@@ -8307,9 +8315,17 @@ T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/scheduler/
|
||||
F: include/drm/gpu_scheduler.h
|
||||
|
||||
DRM LOG
|
||||
M: Jocelyn Falempe <jfalempe@redhat.com>
|
||||
M: Javier Martinez Canillas <javierm@redhat.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Supported
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/clients/drm_log.c
|
||||
|
||||
DRM PANEL DRIVERS
|
||||
M: Neil Armstrong <neil.armstrong@linaro.org>
|
||||
R: Jessica Zhang <quic_jesszhan@quicinc.com>
|
||||
R: Jessica Zhang <jessica.zhang@oss.qualcomm.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
@@ -8318,6 +8334,26 @@ F: drivers/gpu/drm/drm_panel.c
|
||||
F: drivers/gpu/drm/panel/
|
||||
F: include/drm/drm_panel.h
|
||||
|
||||
DRM PANIC
|
||||
M: Jocelyn Falempe <jfalempe@redhat.com>
|
||||
M: Javier Martinez Canillas <javierm@redhat.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Supported
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/drm_draw.c
|
||||
F: drivers/gpu/drm/drm_draw_internal.h
|
||||
F: drivers/gpu/drm/drm_panic*.c
|
||||
F: include/drm/drm_panic*
|
||||
|
||||
DRM PANIC QR CODE
|
||||
M: Jocelyn Falempe <jfalempe@redhat.com>
|
||||
M: Javier Martinez Canillas <javierm@redhat.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
L: rust-for-linux@vger.kernel.org
|
||||
S: Supported
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/drm_panic_qr.rs
|
||||
|
||||
DRM PRIVACY-SCREEN CLASS
|
||||
M: Hans de Goede <hdegoede@redhat.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
@@ -20365,6 +20401,7 @@ L: linux-arm-msm@vger.kernel.org
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Supported
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/ABI/testing/sysfs-driver-qaic
|
||||
F: Documentation/accel/qaic/
|
||||
F: drivers/accel/qaic/
|
||||
F: include/uapi/drm/qaic_accel.h
|
||||
|
||||
@@ -848,7 +848,8 @@ int aie2_cmd_submit(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job,
|
||||
goto up_sem;
|
||||
}
|
||||
|
||||
ret = drm_sched_job_init(&job->base, &hwctx->priv->entity, 1, hwctx);
|
||||
ret = drm_sched_job_init(&job->base, &hwctx->priv->entity, 1, hwctx,
|
||||
hwctx->client->filp->client_id);
|
||||
if (ret) {
|
||||
XDNA_ERR(xdna, "DRM job init failed, ret %d", ret);
|
||||
goto free_chain;
|
||||
|
||||
@@ -1066,28 +1066,11 @@ static bool is_pci_link_healthy(struct hl_device *hdev)
|
||||
return (device_id == hdev->pdev->device);
|
||||
}
|
||||
|
||||
static void stringify_time_of_last_heartbeat(struct hl_device *hdev, char *time_str, size_t size,
|
||||
bool is_pq_hb)
|
||||
{
|
||||
time64_t seconds = is_pq_hb ? hdev->heartbeat_debug_info.last_pq_heartbeat_ts
|
||||
: hdev->heartbeat_debug_info.last_eq_heartbeat_ts;
|
||||
struct tm tm;
|
||||
|
||||
if (!seconds)
|
||||
return;
|
||||
|
||||
time64_to_tm(seconds, 0, &tm);
|
||||
|
||||
snprintf(time_str, size, "%ld-%02d-%02d %02d:%02d:%02d (UTC)",
|
||||
tm.tm_year + 1900, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
|
||||
}
|
||||
|
||||
static bool hl_device_eq_heartbeat_received(struct hl_device *hdev)
|
||||
{
|
||||
struct eq_heartbeat_debug_info *heartbeat_debug_info = &hdev->heartbeat_debug_info;
|
||||
u32 cpu_q_id = heartbeat_debug_info->cpu_queue_id, pq_pi_mask = (HL_QUEUE_LENGTH << 1) - 1;
|
||||
struct asic_fixed_properties *prop = &hdev->asic_prop;
|
||||
char pq_time_str[64] = "N/A", eq_time_str[64] = "N/A";
|
||||
|
||||
if (!prop->cpucp_info.eq_health_check_supported)
|
||||
return true;
|
||||
@@ -1095,17 +1078,15 @@ static bool hl_device_eq_heartbeat_received(struct hl_device *hdev)
|
||||
if (!hdev->eq_heartbeat_received) {
|
||||
dev_err(hdev->dev, "EQ heartbeat event was not received!\n");
|
||||
|
||||
stringify_time_of_last_heartbeat(hdev, pq_time_str, sizeof(pq_time_str), true);
|
||||
stringify_time_of_last_heartbeat(hdev, eq_time_str, sizeof(eq_time_str), false);
|
||||
dev_err(hdev->dev,
|
||||
"EQ: {CI %u, HB counter %u, last HB time: %s}, PQ: {PI: %u, CI: %u (%u), last HB time: %s}\n",
|
||||
"EQ: {CI %u, HB counter %u, last HB time: %ptTs}, PQ: {PI: %u, CI: %u (%u), last HB time: %ptTs}\n",
|
||||
hdev->event_queue.ci,
|
||||
heartbeat_debug_info->heartbeat_event_counter,
|
||||
eq_time_str,
|
||||
&hdev->heartbeat_debug_info.last_eq_heartbeat_ts,
|
||||
hdev->kernel_queues[cpu_q_id].pi,
|
||||
atomic_read(&hdev->kernel_queues[cpu_q_id].ci),
|
||||
atomic_read(&hdev->kernel_queues[cpu_q_id].ci) & pq_pi_mask,
|
||||
pq_time_str);
|
||||
&hdev->heartbeat_debug_info.last_pq_heartbeat_ts);
|
||||
|
||||
hl_eq_dump(hdev, &hdev->event_queue);
|
||||
|
||||
|
||||
@@ -165,6 +165,7 @@ struct ivpu_device {
|
||||
int boot;
|
||||
int jsm;
|
||||
int tdr;
|
||||
int inference;
|
||||
int autosuspend;
|
||||
int d0i3_entry_msg;
|
||||
int state_dump_msg;
|
||||
|
||||
@@ -94,12 +94,14 @@ static void timeouts_init(struct ivpu_device *vdev)
|
||||
vdev->timeout.boot = -1;
|
||||
vdev->timeout.jsm = -1;
|
||||
vdev->timeout.tdr = -1;
|
||||
vdev->timeout.inference = -1;
|
||||
vdev->timeout.autosuspend = -1;
|
||||
vdev->timeout.d0i3_entry_msg = -1;
|
||||
} else if (ivpu_is_fpga(vdev)) {
|
||||
vdev->timeout.boot = 50;
|
||||
vdev->timeout.jsm = 15000;
|
||||
vdev->timeout.tdr = 30000;
|
||||
vdev->timeout.inference = 900000;
|
||||
vdev->timeout.autosuspend = -1;
|
||||
vdev->timeout.d0i3_entry_msg = 500;
|
||||
vdev->timeout.state_dump_msg = 10000;
|
||||
@@ -107,6 +109,7 @@ static void timeouts_init(struct ivpu_device *vdev)
|
||||
vdev->timeout.boot = 50;
|
||||
vdev->timeout.jsm = 500;
|
||||
vdev->timeout.tdr = 10000;
|
||||
vdev->timeout.inference = 300000;
|
||||
vdev->timeout.autosuspend = 100;
|
||||
vdev->timeout.d0i3_entry_msg = 100;
|
||||
vdev->timeout.state_dump_msg = 10;
|
||||
@@ -114,6 +117,7 @@ static void timeouts_init(struct ivpu_device *vdev)
|
||||
vdev->timeout.boot = 1000;
|
||||
vdev->timeout.jsm = 500;
|
||||
vdev->timeout.tdr = 2000;
|
||||
vdev->timeout.inference = 60000;
|
||||
if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
|
||||
vdev->timeout.autosuspend = 10;
|
||||
else
|
||||
|
||||
@@ -33,8 +33,11 @@ static unsigned long ivpu_tdr_timeout_ms;
|
||||
module_param_named(tdr_timeout_ms, ivpu_tdr_timeout_ms, ulong, 0644);
|
||||
MODULE_PARM_DESC(tdr_timeout_ms, "Timeout for device hang detection, in milliseconds, 0 - default");
|
||||
|
||||
static unsigned long ivpu_inference_timeout_ms;
|
||||
module_param_named(inference_timeout_ms, ivpu_inference_timeout_ms, ulong, 0644);
|
||||
MODULE_PARM_DESC(inference_timeout_ms, "Inference maximum duration, in milliseconds, 0 - default");
|
||||
|
||||
#define PM_RESCHEDULE_LIMIT 5
|
||||
#define PM_TDR_HEARTBEAT_LIMIT 30
|
||||
|
||||
static void ivpu_pm_prepare_cold_boot(struct ivpu_device *vdev)
|
||||
{
|
||||
@@ -191,6 +194,10 @@ static void ivpu_job_timeout_work(struct work_struct *work)
|
||||
{
|
||||
struct ivpu_pm_info *pm = container_of(work, struct ivpu_pm_info, job_timeout_work.work);
|
||||
struct ivpu_device *vdev = pm->vdev;
|
||||
unsigned long timeout_ms = ivpu_tdr_timeout_ms ? ivpu_tdr_timeout_ms : vdev->timeout.tdr;
|
||||
unsigned long inference_timeout_ms = ivpu_inference_timeout_ms ? ivpu_inference_timeout_ms :
|
||||
vdev->timeout.inference;
|
||||
u64 inference_max_retries;
|
||||
u64 heartbeat;
|
||||
|
||||
if (ivpu_jsm_get_heartbeat(vdev, 0, &heartbeat) || heartbeat <= vdev->fw->last_heartbeat) {
|
||||
@@ -198,8 +205,10 @@ static void ivpu_job_timeout_work(struct work_struct *work)
|
||||
goto recovery;
|
||||
}
|
||||
|
||||
if (atomic_fetch_inc(&vdev->job_timeout_counter) > PM_TDR_HEARTBEAT_LIMIT) {
|
||||
ivpu_err(vdev, "Job timeout detected, heartbeat limit exceeded\n");
|
||||
inference_max_retries = DIV_ROUND_UP(inference_timeout_ms, timeout_ms);
|
||||
if (atomic_fetch_inc(&vdev->job_timeout_counter) >= inference_max_retries) {
|
||||
ivpu_err(vdev, "Job timeout detected, heartbeat limit (%lld) exceeded\n",
|
||||
inference_max_retries);
|
||||
goto recovery;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ qaic-y := \
|
||||
qaic_control.o \
|
||||
qaic_data.o \
|
||||
qaic_drv.o \
|
||||
qaic_ras.o \
|
||||
qaic_timesync.o \
|
||||
sahara.o
|
||||
|
||||
|
||||
@@ -167,6 +167,14 @@ struct qaic_device {
|
||||
struct workqueue_struct *bootlog_wq;
|
||||
/* Synchronizes access of pages in MHI bootlog device */
|
||||
struct mutex bootlog_mutex;
|
||||
/* MHI RAS channel device */
|
||||
struct mhi_device *ras_ch;
|
||||
/* Correctable error count */
|
||||
unsigned int ce_count;
|
||||
/* Un-correctable error count */
|
||||
unsigned int ue_count;
|
||||
/* Un-correctable non-fatal error count */
|
||||
unsigned int ue_nf_count;
|
||||
};
|
||||
|
||||
struct qaic_drm_device {
|
||||
@@ -213,8 +221,6 @@ struct qaic_bo {
|
||||
bool sliced;
|
||||
/* Request ID of this BO if it is queued for execution */
|
||||
u16 req_id;
|
||||
/* Handle assigned to this BO */
|
||||
u32 handle;
|
||||
/* Wait on this for completion of DMA transfer of this BO */
|
||||
struct completion xfer_done;
|
||||
/*
|
||||
|
||||
@@ -731,7 +731,6 @@ int qaic_create_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *fi
|
||||
if (ret)
|
||||
goto free_bo;
|
||||
|
||||
bo->handle = args->handle;
|
||||
drm_gem_object_put(obj);
|
||||
srcu_read_unlock(&qdev->dev_lock, qdev_rcu_id);
|
||||
srcu_read_unlock(&usr->qddev_lock, usr_rcu_id);
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "mhi_controller.h"
|
||||
#include "qaic.h"
|
||||
#include "qaic_debugfs.h"
|
||||
#include "qaic_ras.h"
|
||||
#include "qaic_timesync.h"
|
||||
#include "sahara.h"
|
||||
|
||||
@@ -695,6 +696,10 @@ static int __init qaic_init(void)
|
||||
if (ret)
|
||||
pr_debug("qaic: qaic_bootlog_register failed %d\n", ret);
|
||||
|
||||
ret = qaic_ras_register();
|
||||
if (ret)
|
||||
pr_debug("qaic: qaic_ras_register failed %d\n", ret);
|
||||
|
||||
return 0;
|
||||
|
||||
free_mhi:
|
||||
@@ -722,6 +727,7 @@ static void __exit qaic_exit(void)
|
||||
* reinitializing the link_up state after the cleanup is done.
|
||||
*/
|
||||
link_up = true;
|
||||
qaic_ras_unregister();
|
||||
qaic_bootlog_unregister();
|
||||
qaic_timesync_deinit();
|
||||
sahara_unregister();
|
||||
|
||||
642
drivers/accel/qaic/qaic_ras.c
Normal file
642
drivers/accel/qaic/qaic_ras.c
Normal file
@@ -0,0 +1,642 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
/* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */
|
||||
/* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. */
|
||||
/* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mhi.h>
|
||||
|
||||
#include "qaic.h"
|
||||
#include "qaic_ras.h"
|
||||
|
||||
#define MAGIC 0x55AA
|
||||
#define VERSION 0x2
|
||||
#define HDR_SZ 12
|
||||
#define NUM_TEMP_LVL 3
|
||||
#define POWER_BREAK BIT(0)
|
||||
|
||||
enum msg_type {
|
||||
MSG_PUSH, /* async push from device */
|
||||
MSG_REQ, /* sync request to device */
|
||||
MSG_RESP, /* sync response from device */
|
||||
};
|
||||
|
||||
enum err_type {
|
||||
CE, /* correctable error */
|
||||
UE, /* uncorrectable error */
|
||||
UE_NF, /* uncorrectable error that is non-fatal, expect a disruption */
|
||||
ERR_TYPE_MAX,
|
||||
};
|
||||
|
||||
static const char * const err_type_str[] = {
|
||||
[CE] = "Correctable",
|
||||
[UE] = "Uncorrectable",
|
||||
[UE_NF] = "Uncorrectable Non-Fatal",
|
||||
};
|
||||
|
||||
static const char * const err_class_str[] = {
|
||||
[CE] = "Warning",
|
||||
[UE] = "Fatal",
|
||||
[UE_NF] = "Warning",
|
||||
};
|
||||
|
||||
enum err_source {
|
||||
SOC_MEM,
|
||||
PCIE,
|
||||
DDR,
|
||||
SYS_BUS1,
|
||||
SYS_BUS2,
|
||||
NSP_MEM,
|
||||
TSENS,
|
||||
};
|
||||
|
||||
static const char * const err_src_str[TSENS + 1] = {
|
||||
[SOC_MEM] = "SoC Memory",
|
||||
[PCIE] = "PCIE",
|
||||
[DDR] = "DDR",
|
||||
[SYS_BUS1] = "System Bus source 1",
|
||||
[SYS_BUS2] = "System Bus source 2",
|
||||
[NSP_MEM] = "NSP Memory",
|
||||
[TSENS] = "Temperature Sensors",
|
||||
};
|
||||
|
||||
struct ras_data {
|
||||
/* header start */
|
||||
/* Magic number to validate the message */
|
||||
u16 magic;
|
||||
/* RAS version number */
|
||||
u16 ver;
|
||||
u32 seq_num;
|
||||
/* RAS message type */
|
||||
u8 type;
|
||||
u8 id;
|
||||
/* Size of RAS message without the header in byte */
|
||||
u16 len;
|
||||
/* header end */
|
||||
s32 result;
|
||||
/*
|
||||
* Error source
|
||||
* 0 : SoC Memory
|
||||
* 1 : PCIE
|
||||
* 2 : DDR
|
||||
* 3 : System Bus source 1
|
||||
* 4 : System Bus source 2
|
||||
* 5 : NSP Memory
|
||||
* 6 : Temperature Sensors
|
||||
*/
|
||||
u32 source;
|
||||
/*
|
||||
* Stores the error type, there are three types of error in RAS
|
||||
* 0 : correctable error (CE)
|
||||
* 1 : uncorrectable error (UE)
|
||||
* 2 : uncorrectable error that is non-fatal (UE_NF)
|
||||
*/
|
||||
u32 err_type;
|
||||
u32 err_threshold;
|
||||
u32 ce_count;
|
||||
u32 ue_count;
|
||||
u32 intr_num;
|
||||
/* Data specific to error source */
|
||||
u8 syndrome[64];
|
||||
} __packed;
|
||||
|
||||
struct soc_mem_syndrome {
|
||||
u64 error_address[8];
|
||||
} __packed;
|
||||
|
||||
struct nsp_mem_syndrome {
|
||||
u32 error_address[8];
|
||||
u8 nsp_id;
|
||||
} __packed;
|
||||
|
||||
struct ddr_syndrome {
|
||||
u32 count;
|
||||
u32 irq_status;
|
||||
u32 data_31_0[2];
|
||||
u32 data_63_32[2];
|
||||
u32 data_95_64[2];
|
||||
u32 data_127_96[2];
|
||||
u32 addr_lsb;
|
||||
u16 addr_msb;
|
||||
u16 parity_bits;
|
||||
u16 instance;
|
||||
u16 err_type;
|
||||
} __packed;
|
||||
|
||||
struct tsens_syndrome {
|
||||
u32 threshold_type;
|
||||
s32 temp;
|
||||
} __packed;
|
||||
|
||||
struct sysbus1_syndrome {
|
||||
u32 slave;
|
||||
u32 err_type;
|
||||
u16 addr[8];
|
||||
u8 instance;
|
||||
} __packed;
|
||||
|
||||
struct sysbus2_syndrome {
|
||||
u32 lsb3;
|
||||
u32 msb3;
|
||||
u32 lsb2;
|
||||
u32 msb2;
|
||||
u32 ext_id;
|
||||
u16 path;
|
||||
u16 op_type;
|
||||
u16 len;
|
||||
u16 redirect;
|
||||
u8 valid;
|
||||
u8 word_error;
|
||||
u8 non_secure;
|
||||
u8 opc;
|
||||
u8 error_code;
|
||||
u8 trans_type;
|
||||
u8 addr_space;
|
||||
u8 instance;
|
||||
} __packed;
|
||||
|
||||
struct pcie_syndrome {
|
||||
/* CE info */
|
||||
u32 bad_tlp;
|
||||
u32 bad_dllp;
|
||||
u32 replay_rollover;
|
||||
u32 replay_timeout;
|
||||
u32 rx_err;
|
||||
u32 internal_ce_count;
|
||||
/* UE_NF info */
|
||||
u32 fc_timeout;
|
||||
u32 poison_tlp;
|
||||
u32 ecrc_err;
|
||||
u32 unsupported_req;
|
||||
u32 completer_abort;
|
||||
u32 completion_timeout;
|
||||
/* UE info */
|
||||
u32 addr;
|
||||
u8 index;
|
||||
/*
|
||||
* Flag to indicate specific event of PCIe
|
||||
* BIT(0): Power break (low power)
|
||||
* BIT(1) to BIT(7): Reserved
|
||||
*/
|
||||
u8 flag;
|
||||
} __packed;
|
||||
|
||||
static const char * const threshold_type_str[NUM_TEMP_LVL] = {
|
||||
[0] = "lower",
|
||||
[1] = "upper",
|
||||
[2] = "critical",
|
||||
};
|
||||
|
||||
static void ras_msg_to_cpu(struct ras_data *msg)
|
||||
{
|
||||
struct sysbus1_syndrome *sysbus1_syndrome = (struct sysbus1_syndrome *)&msg->syndrome[0];
|
||||
struct sysbus2_syndrome *sysbus2_syndrome = (struct sysbus2_syndrome *)&msg->syndrome[0];
|
||||
struct soc_mem_syndrome *soc_syndrome = (struct soc_mem_syndrome *)&msg->syndrome[0];
|
||||
struct nsp_mem_syndrome *nsp_syndrome = (struct nsp_mem_syndrome *)&msg->syndrome[0];
|
||||
struct tsens_syndrome *tsens_syndrome = (struct tsens_syndrome *)&msg->syndrome[0];
|
||||
struct pcie_syndrome *pcie_syndrome = (struct pcie_syndrome *)&msg->syndrome[0];
|
||||
struct ddr_syndrome *ddr_syndrome = (struct ddr_syndrome *)&msg->syndrome[0];
|
||||
int i;
|
||||
|
||||
le16_to_cpus(&msg->magic);
|
||||
le16_to_cpus(&msg->ver);
|
||||
le32_to_cpus(&msg->seq_num);
|
||||
le16_to_cpus(&msg->len);
|
||||
le32_to_cpus(&msg->result);
|
||||
le32_to_cpus(&msg->source);
|
||||
le32_to_cpus(&msg->err_type);
|
||||
le32_to_cpus(&msg->err_threshold);
|
||||
le32_to_cpus(&msg->ce_count);
|
||||
le32_to_cpus(&msg->ue_count);
|
||||
le32_to_cpus(&msg->intr_num);
|
||||
|
||||
switch (msg->source) {
|
||||
case SOC_MEM:
|
||||
for (i = 0; i < 8; i++)
|
||||
le64_to_cpus(&soc_syndrome->error_address[i]);
|
||||
break;
|
||||
case PCIE:
|
||||
le32_to_cpus(&pcie_syndrome->bad_tlp);
|
||||
le32_to_cpus(&pcie_syndrome->bad_dllp);
|
||||
le32_to_cpus(&pcie_syndrome->replay_rollover);
|
||||
le32_to_cpus(&pcie_syndrome->replay_timeout);
|
||||
le32_to_cpus(&pcie_syndrome->rx_err);
|
||||
le32_to_cpus(&pcie_syndrome->internal_ce_count);
|
||||
le32_to_cpus(&pcie_syndrome->fc_timeout);
|
||||
le32_to_cpus(&pcie_syndrome->poison_tlp);
|
||||
le32_to_cpus(&pcie_syndrome->ecrc_err);
|
||||
le32_to_cpus(&pcie_syndrome->unsupported_req);
|
||||
le32_to_cpus(&pcie_syndrome->completer_abort);
|
||||
le32_to_cpus(&pcie_syndrome->completion_timeout);
|
||||
le32_to_cpus(&pcie_syndrome->addr);
|
||||
break;
|
||||
case DDR:
|
||||
le16_to_cpus(&ddr_syndrome->instance);
|
||||
le16_to_cpus(&ddr_syndrome->err_type);
|
||||
le32_to_cpus(&ddr_syndrome->count);
|
||||
le32_to_cpus(&ddr_syndrome->irq_status);
|
||||
le32_to_cpus(&ddr_syndrome->data_31_0[0]);
|
||||
le32_to_cpus(&ddr_syndrome->data_31_0[1]);
|
||||
le32_to_cpus(&ddr_syndrome->data_63_32[0]);
|
||||
le32_to_cpus(&ddr_syndrome->data_63_32[1]);
|
||||
le32_to_cpus(&ddr_syndrome->data_95_64[0]);
|
||||
le32_to_cpus(&ddr_syndrome->data_95_64[1]);
|
||||
le32_to_cpus(&ddr_syndrome->data_127_96[0]);
|
||||
le32_to_cpus(&ddr_syndrome->data_127_96[1]);
|
||||
le16_to_cpus(&ddr_syndrome->parity_bits);
|
||||
le16_to_cpus(&ddr_syndrome->addr_msb);
|
||||
le32_to_cpus(&ddr_syndrome->addr_lsb);
|
||||
break;
|
||||
case SYS_BUS1:
|
||||
le32_to_cpus(&sysbus1_syndrome->slave);
|
||||
le32_to_cpus(&sysbus1_syndrome->err_type);
|
||||
for (i = 0; i < 8; i++)
|
||||
le16_to_cpus(&sysbus1_syndrome->addr[i]);
|
||||
break;
|
||||
case SYS_BUS2:
|
||||
le16_to_cpus(&sysbus2_syndrome->op_type);
|
||||
le16_to_cpus(&sysbus2_syndrome->len);
|
||||
le16_to_cpus(&sysbus2_syndrome->redirect);
|
||||
le16_to_cpus(&sysbus2_syndrome->path);
|
||||
le32_to_cpus(&sysbus2_syndrome->ext_id);
|
||||
le32_to_cpus(&sysbus2_syndrome->lsb2);
|
||||
le32_to_cpus(&sysbus2_syndrome->msb2);
|
||||
le32_to_cpus(&sysbus2_syndrome->lsb3);
|
||||
le32_to_cpus(&sysbus2_syndrome->msb3);
|
||||
break;
|
||||
case NSP_MEM:
|
||||
for (i = 0; i < 8; i++)
|
||||
le32_to_cpus(&nsp_syndrome->error_address[i]);
|
||||
break;
|
||||
case TSENS:
|
||||
le32_to_cpus(&tsens_syndrome->threshold_type);
|
||||
le32_to_cpus(&tsens_syndrome->temp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void decode_ras_msg(struct qaic_device *qdev, struct ras_data *msg)
|
||||
{
|
||||
struct sysbus1_syndrome *sysbus1_syndrome = (struct sysbus1_syndrome *)&msg->syndrome[0];
|
||||
struct sysbus2_syndrome *sysbus2_syndrome = (struct sysbus2_syndrome *)&msg->syndrome[0];
|
||||
struct soc_mem_syndrome *soc_syndrome = (struct soc_mem_syndrome *)&msg->syndrome[0];
|
||||
struct nsp_mem_syndrome *nsp_syndrome = (struct nsp_mem_syndrome *)&msg->syndrome[0];
|
||||
struct tsens_syndrome *tsens_syndrome = (struct tsens_syndrome *)&msg->syndrome[0];
|
||||
struct pcie_syndrome *pcie_syndrome = (struct pcie_syndrome *)&msg->syndrome[0];
|
||||
struct ddr_syndrome *ddr_syndrome = (struct ddr_syndrome *)&msg->syndrome[0];
|
||||
char *class;
|
||||
char *level;
|
||||
|
||||
if (msg->magic != MAGIC) {
|
||||
pci_warn(qdev->pdev, "Dropping RAS message with invalid magic %x\n", msg->magic);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!msg->ver || msg->ver > VERSION) {
|
||||
pci_warn(qdev->pdev, "Dropping RAS message with invalid version %d\n", msg->ver);
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg->type != MSG_PUSH) {
|
||||
pci_warn(qdev->pdev, "Dropping non-PUSH RAS message\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg->len != sizeof(*msg) - HDR_SZ) {
|
||||
pci_warn(qdev->pdev, "Dropping RAS message with invalid len %d\n", msg->len);
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg->err_type >= ERR_TYPE_MAX) {
|
||||
pci_warn(qdev->pdev, "Dropping RAS message with err type %d\n", msg->err_type);
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg->err_type == UE)
|
||||
level = KERN_ERR;
|
||||
else
|
||||
level = KERN_WARNING;
|
||||
|
||||
switch (msg->source) {
|
||||
case SOC_MEM:
|
||||
dev_printk(level, &qdev->pdev->dev, "RAS event.\nClass:%s\nDescription:%s %s %s\nError Threshold for this report %d\nSyndrome:\n 0x%llx\n 0x%llx\n 0x%llx\n 0x%llx\n 0x%llx\n 0x%llx\n 0x%llx\n 0x%llx\n",
|
||||
err_class_str[msg->err_type],
|
||||
err_type_str[msg->err_type],
|
||||
"error from",
|
||||
err_src_str[msg->source],
|
||||
msg->err_threshold,
|
||||
soc_syndrome->error_address[0],
|
||||
soc_syndrome->error_address[1],
|
||||
soc_syndrome->error_address[2],
|
||||
soc_syndrome->error_address[3],
|
||||
soc_syndrome->error_address[4],
|
||||
soc_syndrome->error_address[5],
|
||||
soc_syndrome->error_address[6],
|
||||
soc_syndrome->error_address[7]);
|
||||
break;
|
||||
case PCIE:
|
||||
dev_printk(level, &qdev->pdev->dev, "RAS event.\nClass:%s\nDescription:%s %s %s\nError Threshold for this report %d\n",
|
||||
err_class_str[msg->err_type],
|
||||
err_type_str[msg->err_type],
|
||||
"error from",
|
||||
err_src_str[msg->source],
|
||||
msg->err_threshold);
|
||||
|
||||
switch (msg->err_type) {
|
||||
case CE:
|
||||
/*
|
||||
* Modeled after AER prints. This continues the dev_printk() from a few
|
||||
* lines up. We reduce duplication of code, but also avoid re-printing the
|
||||
* PCI device info so that the end result looks uniform to the log user.
|
||||
*/
|
||||
printk(KERN_WARNING pr_fmt("Syndrome:\n Bad TLP count %d\n Bad DLLP count %d\n Replay Rollover count %d\n Replay Timeout count %d\n Recv Error count %d\n Internal CE count %d\n"),
|
||||
pcie_syndrome->bad_tlp,
|
||||
pcie_syndrome->bad_dllp,
|
||||
pcie_syndrome->replay_rollover,
|
||||
pcie_syndrome->replay_timeout,
|
||||
pcie_syndrome->rx_err,
|
||||
pcie_syndrome->internal_ce_count);
|
||||
if (msg->ver > 0x1)
|
||||
pr_warn(" Power break %s\n",
|
||||
pcie_syndrome->flag & POWER_BREAK ? "ON" : "OFF");
|
||||
break;
|
||||
case UE:
|
||||
printk(KERN_ERR pr_fmt("Syndrome:\n Index %d\n Address 0x%x\n"),
|
||||
pcie_syndrome->index, pcie_syndrome->addr);
|
||||
break;
|
||||
case UE_NF:
|
||||
printk(KERN_WARNING pr_fmt("Syndrome:\n FC timeout count %d\n Poisoned TLP count %d\n ECRC error count %d\n Unsupported request count %d\n Completer abort count %d\n Completion timeout count %d\n"),
|
||||
pcie_syndrome->fc_timeout,
|
||||
pcie_syndrome->poison_tlp,
|
||||
pcie_syndrome->ecrc_err,
|
||||
pcie_syndrome->unsupported_req,
|
||||
pcie_syndrome->completer_abort,
|
||||
pcie_syndrome->completion_timeout);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case DDR:
|
||||
dev_printk(level, &qdev->pdev->dev, "RAS event.\nClass:%s\nDescription:%s %s %s\nError Threshold for this report %d\nSyndrome:\n Instance %d\n Count %d\n Data 31_0 0x%x 0x%x\n Data 63_32 0x%x 0x%x\n Data 95_64 0x%x 0x%x\n Data 127_96 0x%x 0x%x\n Parity bits 0x%x\n Address msb 0x%x\n Address lsb 0x%x\n",
|
||||
err_class_str[msg->err_type],
|
||||
err_type_str[msg->err_type],
|
||||
"error from",
|
||||
err_src_str[msg->source],
|
||||
msg->err_threshold,
|
||||
ddr_syndrome->instance,
|
||||
ddr_syndrome->count,
|
||||
ddr_syndrome->data_31_0[1],
|
||||
ddr_syndrome->data_31_0[0],
|
||||
ddr_syndrome->data_63_32[1],
|
||||
ddr_syndrome->data_63_32[0],
|
||||
ddr_syndrome->data_95_64[1],
|
||||
ddr_syndrome->data_95_64[0],
|
||||
ddr_syndrome->data_127_96[1],
|
||||
ddr_syndrome->data_127_96[0],
|
||||
ddr_syndrome->parity_bits,
|
||||
ddr_syndrome->addr_msb,
|
||||
ddr_syndrome->addr_lsb);
|
||||
break;
|
||||
case SYS_BUS1:
|
||||
dev_printk(level, &qdev->pdev->dev, "RAS event.\nClass:%s\nDescription:%s %s %s\nError Threshold for this report %d\nSyndrome:\n instance %d\n %s\n err_type %d\n address0 0x%x\n address1 0x%x\n address2 0x%x\n address3 0x%x\n address4 0x%x\n address5 0x%x\n address6 0x%x\n address7 0x%x\n",
|
||||
err_class_str[msg->err_type],
|
||||
err_type_str[msg->err_type],
|
||||
"error from",
|
||||
err_src_str[msg->source],
|
||||
msg->err_threshold,
|
||||
sysbus1_syndrome->instance,
|
||||
sysbus1_syndrome->slave ? "Slave" : "Master",
|
||||
sysbus1_syndrome->err_type,
|
||||
sysbus1_syndrome->addr[0],
|
||||
sysbus1_syndrome->addr[1],
|
||||
sysbus1_syndrome->addr[2],
|
||||
sysbus1_syndrome->addr[3],
|
||||
sysbus1_syndrome->addr[4],
|
||||
sysbus1_syndrome->addr[5],
|
||||
sysbus1_syndrome->addr[6],
|
||||
sysbus1_syndrome->addr[7]);
|
||||
break;
|
||||
case SYS_BUS2:
|
||||
dev_printk(level, &qdev->pdev->dev, "RAS event.\nClass:%s\nDescription:%s %s %s\nError Threshold for this report %d\nSyndrome:\n instance %d\n valid %d\n word error %d\n non-secure %d\n opc %d\n error code %d\n transaction type %d\n address space %d\n operation type %d\n len %d\n redirect %d\n path %d\n ext_id %d\n lsb2 %d\n msb2 %d\n lsb3 %d\n msb3 %d\n",
|
||||
err_class_str[msg->err_type],
|
||||
err_type_str[msg->err_type],
|
||||
"error from",
|
||||
err_src_str[msg->source],
|
||||
msg->err_threshold,
|
||||
sysbus2_syndrome->instance,
|
||||
sysbus2_syndrome->valid,
|
||||
sysbus2_syndrome->word_error,
|
||||
sysbus2_syndrome->non_secure,
|
||||
sysbus2_syndrome->opc,
|
||||
sysbus2_syndrome->error_code,
|
||||
sysbus2_syndrome->trans_type,
|
||||
sysbus2_syndrome->addr_space,
|
||||
sysbus2_syndrome->op_type,
|
||||
sysbus2_syndrome->len,
|
||||
sysbus2_syndrome->redirect,
|
||||
sysbus2_syndrome->path,
|
||||
sysbus2_syndrome->ext_id,
|
||||
sysbus2_syndrome->lsb2,
|
||||
sysbus2_syndrome->msb2,
|
||||
sysbus2_syndrome->lsb3,
|
||||
sysbus2_syndrome->msb3);
|
||||
break;
|
||||
case NSP_MEM:
|
||||
dev_printk(level, &qdev->pdev->dev, "RAS event.\nClass:%s\nDescription:%s %s %s\nError Threshold for this report %d\nSyndrome:\n NSP ID %d\n 0x%x\n 0x%x\n 0x%x\n 0x%x\n 0x%x\n 0x%x\n 0x%x\n 0x%x\n",
|
||||
err_class_str[msg->err_type],
|
||||
err_type_str[msg->err_type],
|
||||
"error from",
|
||||
err_src_str[msg->source],
|
||||
msg->err_threshold,
|
||||
nsp_syndrome->nsp_id,
|
||||
nsp_syndrome->error_address[0],
|
||||
nsp_syndrome->error_address[1],
|
||||
nsp_syndrome->error_address[2],
|
||||
nsp_syndrome->error_address[3],
|
||||
nsp_syndrome->error_address[4],
|
||||
nsp_syndrome->error_address[5],
|
||||
nsp_syndrome->error_address[6],
|
||||
nsp_syndrome->error_address[7]);
|
||||
break;
|
||||
case TSENS:
|
||||
if (tsens_syndrome->threshold_type >= NUM_TEMP_LVL) {
|
||||
pci_warn(qdev->pdev, "Dropping RAS message with invalid temp threshold %d\n",
|
||||
tsens_syndrome->threshold_type);
|
||||
break;
|
||||
}
|
||||
|
||||
if (msg->err_type)
|
||||
class = "Fatal";
|
||||
else if (tsens_syndrome->threshold_type)
|
||||
class = "Critical";
|
||||
else
|
||||
class = "Warning";
|
||||
|
||||
dev_printk(level, &qdev->pdev->dev, "RAS event.\nClass:%s\nDescription:%s %s %s\nError Threshold for this report %d\nSyndrome:\n %s threshold\n %d deg C\n",
|
||||
class,
|
||||
err_type_str[msg->err_type],
|
||||
"error from",
|
||||
err_src_str[msg->source],
|
||||
msg->err_threshold,
|
||||
threshold_type_str[tsens_syndrome->threshold_type],
|
||||
tsens_syndrome->temp);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Uncorrectable errors are fatal */
|
||||
if (msg->err_type == UE)
|
||||
mhi_soc_reset(qdev->mhi_cntrl);
|
||||
|
||||
switch (msg->err_type) {
|
||||
case CE:
|
||||
if (qdev->ce_count != UINT_MAX)
|
||||
qdev->ce_count++;
|
||||
break;
|
||||
case UE:
|
||||
if (qdev->ce_count != UINT_MAX)
|
||||
qdev->ue_count++;
|
||||
break;
|
||||
case UE_NF:
|
||||
if (qdev->ce_count != UINT_MAX)
|
||||
qdev->ue_nf_count++;
|
||||
break;
|
||||
default:
|
||||
/* not possible */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t ce_count_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct qaic_device *qdev = pci_get_drvdata(to_pci_dev(dev));
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", qdev->ce_count);
|
||||
}
|
||||
|
||||
static ssize_t ue_count_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct qaic_device *qdev = pci_get_drvdata(to_pci_dev(dev));
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", qdev->ue_count);
|
||||
}
|
||||
|
||||
static ssize_t ue_nonfatal_count_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct qaic_device *qdev = pci_get_drvdata(to_pci_dev(dev));
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", qdev->ue_nf_count);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(ce_count);
|
||||
static DEVICE_ATTR_RO(ue_count);
|
||||
static DEVICE_ATTR_RO(ue_nonfatal_count);
|
||||
|
||||
static struct attribute *ras_attrs[] = {
|
||||
&dev_attr_ce_count.attr,
|
||||
&dev_attr_ue_count.attr,
|
||||
&dev_attr_ue_nonfatal_count.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group ras_group = {
|
||||
.attrs = ras_attrs,
|
||||
};
|
||||
|
||||
static int qaic_ras_mhi_probe(struct mhi_device *mhi_dev, const struct mhi_device_id *id)
|
||||
{
|
||||
struct qaic_device *qdev = pci_get_drvdata(to_pci_dev(mhi_dev->mhi_cntrl->cntrl_dev));
|
||||
struct ras_data *resp;
|
||||
int ret;
|
||||
|
||||
ret = mhi_prepare_for_transfer(mhi_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
resp = kzalloc(sizeof(*resp), GFP_KERNEL);
|
||||
if (!resp) {
|
||||
mhi_unprepare_from_transfer(mhi_dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = mhi_queue_buf(mhi_dev, DMA_FROM_DEVICE, resp, sizeof(*resp), MHI_EOT);
|
||||
if (ret) {
|
||||
kfree(resp);
|
||||
mhi_unprepare_from_transfer(mhi_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = device_add_group(&qdev->pdev->dev, &ras_group);
|
||||
if (ret) {
|
||||
mhi_unprepare_from_transfer(mhi_dev);
|
||||
pci_dbg(qdev->pdev, "ras add sysfs failed %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_set_drvdata(&mhi_dev->dev, qdev);
|
||||
qdev->ras_ch = mhi_dev;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void qaic_ras_mhi_remove(struct mhi_device *mhi_dev)
|
||||
{
|
||||
struct qaic_device *qdev;
|
||||
|
||||
qdev = dev_get_drvdata(&mhi_dev->dev);
|
||||
qdev->ras_ch = NULL;
|
||||
device_remove_group(&qdev->pdev->dev, &ras_group);
|
||||
mhi_unprepare_from_transfer(mhi_dev);
|
||||
}
|
||||
|
||||
static void qaic_ras_mhi_ul_xfer_cb(struct mhi_device *mhi_dev, struct mhi_result *mhi_result) {}
|
||||
|
||||
static void qaic_ras_mhi_dl_xfer_cb(struct mhi_device *mhi_dev, struct mhi_result *mhi_result)
|
||||
{
|
||||
struct qaic_device *qdev = dev_get_drvdata(&mhi_dev->dev);
|
||||
struct ras_data *msg = mhi_result->buf_addr;
|
||||
int ret;
|
||||
|
||||
if (mhi_result->transaction_status) {
|
||||
kfree(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
ras_msg_to_cpu(msg);
|
||||
decode_ras_msg(qdev, msg);
|
||||
|
||||
ret = mhi_queue_buf(qdev->ras_ch, DMA_FROM_DEVICE, msg, sizeof(*msg), MHI_EOT);
|
||||
if (ret) {
|
||||
dev_err(&mhi_dev->dev, "Cannot requeue RAS recv buf %d\n", ret);
|
||||
kfree(msg);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct mhi_device_id qaic_ras_mhi_match_table[] = {
|
||||
{ .chan = "QAIC_STATUS", },
|
||||
{},
|
||||
};
|
||||
|
||||
static struct mhi_driver qaic_ras_mhi_driver = {
|
||||
.id_table = qaic_ras_mhi_match_table,
|
||||
.remove = qaic_ras_mhi_remove,
|
||||
.probe = qaic_ras_mhi_probe,
|
||||
.ul_xfer_cb = qaic_ras_mhi_ul_xfer_cb,
|
||||
.dl_xfer_cb = qaic_ras_mhi_dl_xfer_cb,
|
||||
.driver = {
|
||||
.name = "qaic_ras",
|
||||
},
|
||||
};
|
||||
|
||||
int qaic_ras_register(void)
|
||||
{
|
||||
return mhi_driver_register(&qaic_ras_mhi_driver);
|
||||
}
|
||||
|
||||
void qaic_ras_unregister(void)
|
||||
{
|
||||
mhi_driver_unregister(&qaic_ras_mhi_driver);
|
||||
}
|
||||
10
drivers/accel/qaic/qaic_ras.h
Normal file
10
drivers/accel/qaic/qaic_ras.h
Normal file
@@ -0,0 +1,10 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2020, The Linux Foundation. All rights reserved. */
|
||||
|
||||
#ifndef __QAIC_RAS_H__
|
||||
#define __QAIC_RAS_H__
|
||||
|
||||
int qaic_ras_register(void);
|
||||
void qaic_ras_unregister(void);
|
||||
|
||||
#endif /* __QAIC_RAS_H__ */
|
||||
@@ -36,7 +36,6 @@ config UDMABUF
|
||||
depends on DMA_SHARED_BUFFER
|
||||
depends on MEMFD_CREATE || COMPILE_TEST
|
||||
depends on MMU
|
||||
select VMAP_PFN
|
||||
help
|
||||
A driver to let userspace turn memfd regions into dma-bufs.
|
||||
Qemu can use this to create host dmabufs for guest framebuffers.
|
||||
|
||||
@@ -218,7 +218,6 @@ static void dma_fence_chain_set_deadline(struct dma_fence *fence,
|
||||
}
|
||||
|
||||
const struct dma_fence_ops dma_fence_chain_ops = {
|
||||
.use_64bit_seqno = true,
|
||||
.get_driver_name = dma_fence_chain_get_driver_name,
|
||||
.get_timeline_name = dma_fence_chain_get_timeline_name,
|
||||
.enable_signaling = dma_fence_chain_enable_signaling,
|
||||
@@ -252,7 +251,7 @@ void dma_fence_chain_init(struct dma_fence_chain *chain,
|
||||
chain->prev_seqno = 0;
|
||||
|
||||
/* Try to reuse the context of the previous chain node. */
|
||||
if (prev_chain && __dma_fence_is_later(seqno, prev->seqno, prev->ops)) {
|
||||
if (prev_chain && __dma_fence_is_later(prev, seqno, prev->seqno)) {
|
||||
context = prev->context;
|
||||
chain->prev_seqno = prev->seqno;
|
||||
} else {
|
||||
@@ -262,8 +261,8 @@ void dma_fence_chain_init(struct dma_fence_chain *chain,
|
||||
seqno = max(prev->seqno, seqno);
|
||||
}
|
||||
|
||||
dma_fence_init(&chain->base, &dma_fence_chain_ops,
|
||||
&chain->lock, context, seqno);
|
||||
dma_fence_init64(&chain->base, &dma_fence_chain_ops, &chain->lock,
|
||||
context, seqno);
|
||||
|
||||
/*
|
||||
* Chaining dma_fence_chain container together is only allowed through
|
||||
|
||||
@@ -538,8 +538,8 @@ void dma_fence_release(struct kref *kref)
|
||||
if (WARN(!list_empty(&fence->cb_list) &&
|
||||
!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags),
|
||||
"Fence %s:%s:%llx:%llx released with pending signals!\n",
|
||||
fence->ops->get_driver_name(fence),
|
||||
fence->ops->get_timeline_name(fence),
|
||||
dma_fence_driver_name(fence),
|
||||
dma_fence_timeline_name(fence),
|
||||
fence->context, fence->seqno)) {
|
||||
unsigned long flags;
|
||||
|
||||
@@ -983,12 +983,32 @@ EXPORT_SYMBOL(dma_fence_set_deadline);
|
||||
void dma_fence_describe(struct dma_fence *fence, struct seq_file *seq)
|
||||
{
|
||||
seq_printf(seq, "%s %s seq %llu %ssignalled\n",
|
||||
fence->ops->get_driver_name(fence),
|
||||
fence->ops->get_timeline_name(fence), fence->seqno,
|
||||
dma_fence_driver_name(fence),
|
||||
dma_fence_timeline_name(fence),
|
||||
fence->seqno,
|
||||
dma_fence_is_signaled(fence) ? "" : "un");
|
||||
}
|
||||
EXPORT_SYMBOL(dma_fence_describe);
|
||||
|
||||
static void
|
||||
__dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops,
|
||||
spinlock_t *lock, u64 context, u64 seqno, unsigned long flags)
|
||||
{
|
||||
BUG_ON(!lock);
|
||||
BUG_ON(!ops || !ops->get_driver_name || !ops->get_timeline_name);
|
||||
|
||||
kref_init(&fence->refcount);
|
||||
fence->ops = ops;
|
||||
INIT_LIST_HEAD(&fence->cb_list);
|
||||
fence->lock = lock;
|
||||
fence->context = context;
|
||||
fence->seqno = seqno;
|
||||
fence->flags = flags;
|
||||
fence->error = 0;
|
||||
|
||||
trace_dma_fence_init(fence);
|
||||
}
|
||||
|
||||
/**
|
||||
* dma_fence_init - Initialize a custom fence.
|
||||
* @fence: the fence to initialize
|
||||
@@ -1008,18 +1028,30 @@ void
|
||||
dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops,
|
||||
spinlock_t *lock, u64 context, u64 seqno)
|
||||
{
|
||||
BUG_ON(!lock);
|
||||
BUG_ON(!ops || !ops->get_driver_name || !ops->get_timeline_name);
|
||||
|
||||
kref_init(&fence->refcount);
|
||||
fence->ops = ops;
|
||||
INIT_LIST_HEAD(&fence->cb_list);
|
||||
fence->lock = lock;
|
||||
fence->context = context;
|
||||
fence->seqno = seqno;
|
||||
fence->flags = 0UL;
|
||||
fence->error = 0;
|
||||
|
||||
trace_dma_fence_init(fence);
|
||||
__dma_fence_init(fence, ops, lock, context, seqno, 0UL);
|
||||
}
|
||||
EXPORT_SYMBOL(dma_fence_init);
|
||||
|
||||
/**
|
||||
* dma_fence_init64 - Initialize a custom fence with 64-bit seqno support.
|
||||
* @fence: the fence to initialize
|
||||
* @ops: the dma_fence_ops for operations on this fence
|
||||
* @lock: the irqsafe spinlock to use for locking this fence
|
||||
* @context: the execution context this fence is run on
|
||||
* @seqno: a linear increasing sequence number for this context
|
||||
*
|
||||
* Initializes an allocated fence, the caller doesn't have to keep its
|
||||
* refcount after committing with this fence, but it will need to hold a
|
||||
* refcount again if &dma_fence_ops.enable_signaling gets called.
|
||||
*
|
||||
* Context and seqno are used for easy comparison between fences, allowing
|
||||
* to check which fence is later by simply using dma_fence_later().
|
||||
*/
|
||||
void
|
||||
dma_fence_init64(struct dma_fence *fence, const struct dma_fence_ops *ops,
|
||||
spinlock_t *lock, u64 context, u64 seqno)
|
||||
{
|
||||
__dma_fence_init(fence, ops, lock, context, seqno,
|
||||
BIT(DMA_FENCE_FLAG_SEQNO64_BIT));
|
||||
}
|
||||
EXPORT_SYMBOL(dma_fence_init64);
|
||||
|
||||
@@ -170,7 +170,7 @@ static bool timeline_fence_signaled(struct dma_fence *fence)
|
||||
{
|
||||
struct sync_timeline *parent = dma_fence_parent(fence);
|
||||
|
||||
return !__dma_fence_is_later(fence->seqno, parent->value, fence->ops);
|
||||
return !__dma_fence_is_later(fence, fence->seqno, parent->value);
|
||||
}
|
||||
|
||||
static void timeline_fence_set_deadline(struct dma_fence *fence, ktime_t deadline)
|
||||
|
||||
@@ -137,8 +137,8 @@ char *sync_file_get_name(struct sync_file *sync_file, char *buf, int len)
|
||||
struct dma_fence *fence = sync_file->fence;
|
||||
|
||||
snprintf(buf, len, "%s-%s%llu-%lld",
|
||||
fence->ops->get_driver_name(fence),
|
||||
fence->ops->get_timeline_name(fence),
|
||||
dma_fence_driver_name(fence),
|
||||
dma_fence_timeline_name(fence),
|
||||
fence->context,
|
||||
fence->seqno);
|
||||
}
|
||||
@@ -262,9 +262,9 @@ static long sync_file_ioctl_merge(struct sync_file *sync_file,
|
||||
static int sync_fill_fence_info(struct dma_fence *fence,
|
||||
struct sync_fence_info *info)
|
||||
{
|
||||
strscpy(info->obj_name, fence->ops->get_timeline_name(fence),
|
||||
strscpy(info->obj_name, dma_fence_timeline_name(fence),
|
||||
sizeof(info->obj_name));
|
||||
strscpy(info->driver_name, fence->ops->get_driver_name(fence),
|
||||
strscpy(info->driver_name, dma_fence_driver_name(fence),
|
||||
sizeof(info->driver_name));
|
||||
|
||||
info->status = dma_fence_get_status(fence);
|
||||
|
||||
@@ -109,29 +109,22 @@ static int mmap_udmabuf(struct dma_buf *buf, struct vm_area_struct *vma)
|
||||
static int vmap_udmabuf(struct dma_buf *buf, struct iosys_map *map)
|
||||
{
|
||||
struct udmabuf *ubuf = buf->priv;
|
||||
unsigned long *pfns;
|
||||
struct page **pages;
|
||||
void *vaddr;
|
||||
pgoff_t pg;
|
||||
|
||||
dma_resv_assert_held(buf->resv);
|
||||
|
||||
/**
|
||||
* HVO may free tail pages, so just use pfn to map each folio
|
||||
* into vmalloc area.
|
||||
*/
|
||||
pfns = kvmalloc_array(ubuf->pagecount, sizeof(*pfns), GFP_KERNEL);
|
||||
if (!pfns)
|
||||
pages = kvmalloc_array(ubuf->pagecount, sizeof(*pages), GFP_KERNEL);
|
||||
if (!pages)
|
||||
return -ENOMEM;
|
||||
|
||||
for (pg = 0; pg < ubuf->pagecount; pg++) {
|
||||
unsigned long pfn = folio_pfn(ubuf->folios[pg]);
|
||||
for (pg = 0; pg < ubuf->pagecount; pg++)
|
||||
pages[pg] = folio_page(ubuf->folios[pg],
|
||||
ubuf->offsets[pg] >> PAGE_SHIFT);
|
||||
|
||||
pfn += ubuf->offsets[pg] >> PAGE_SHIFT;
|
||||
pfns[pg] = pfn;
|
||||
}
|
||||
|
||||
vaddr = vmap_pfn(pfns, ubuf->pagecount, PAGE_KERNEL);
|
||||
kvfree(pfns);
|
||||
vaddr = vm_map_ram(pages, ubuf->pagecount, -1);
|
||||
kvfree(pages);
|
||||
if (!vaddr)
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
@@ -229,9 +229,10 @@ static int adp_mipi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct adp_mipi_drv_private *adp;
|
||||
|
||||
adp = devm_kzalloc(&pdev->dev, sizeof(*adp), GFP_KERNEL);
|
||||
if (!adp)
|
||||
return -ENOMEM;
|
||||
adp = devm_drm_bridge_alloc(&pdev->dev, struct adp_mipi_drv_private,
|
||||
bridge, &adp_dsi_bridge_funcs);
|
||||
if (IS_ERR(adp))
|
||||
return PTR_ERR(adp);
|
||||
|
||||
adp->mipi = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(adp->mipi)) {
|
||||
@@ -241,7 +242,6 @@ static int adp_mipi_probe(struct platform_device *pdev)
|
||||
|
||||
adp->dsi.dev = &pdev->dev;
|
||||
adp->dsi.ops = &adp_dsi_host_ops;
|
||||
adp->bridge.funcs = &adp_dsi_bridge_funcs;
|
||||
adp->bridge.of_node = pdev->dev.of_node;
|
||||
adp->bridge.type = DRM_MODE_CONNECTOR_DSI;
|
||||
dev_set_drvdata(&pdev->dev, adp);
|
||||
|
||||
@@ -642,7 +642,7 @@ int amdgpu_amdkfd_submit_ib(struct amdgpu_device *adev,
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = amdgpu_job_alloc(adev, NULL, NULL, NULL, 1, &job);
|
||||
ret = amdgpu_job_alloc(adev, NULL, NULL, NULL, 1, &job, 0);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
|
||||
@@ -293,7 +293,8 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p,
|
||||
|
||||
for (i = 0; i < p->gang_size; ++i) {
|
||||
ret = amdgpu_job_alloc(p->adev, vm, p->entities[i], vm,
|
||||
num_ibs[i], &p->jobs[i]);
|
||||
num_ibs[i], &p->jobs[i],
|
||||
p->filp->client_id);
|
||||
if (ret)
|
||||
goto free_all_kdata;
|
||||
switch (p->adev->enforce_isolation[fpriv->xcp_id]) {
|
||||
|
||||
@@ -143,7 +143,6 @@ static bool amdgpu_eviction_fence_enable_signaling(struct dma_fence *f)
|
||||
}
|
||||
|
||||
static const struct dma_fence_ops amdgpu_eviction_fence_ops = {
|
||||
.use_64bit_seqno = true,
|
||||
.get_driver_name = amdgpu_eviction_fence_get_driver_name,
|
||||
.get_timeline_name = amdgpu_eviction_fence_get_timeline_name,
|
||||
.enable_signaling = amdgpu_eviction_fence_enable_signaling,
|
||||
@@ -169,9 +168,9 @@ amdgpu_eviction_fence_create(struct amdgpu_eviction_fence_mgr *evf_mgr)
|
||||
ev_fence->evf_mgr = evf_mgr;
|
||||
get_task_comm(ev_fence->timeline_name, current);
|
||||
spin_lock_init(&ev_fence->lock);
|
||||
dma_fence_init(&ev_fence->base, &amdgpu_eviction_fence_ops,
|
||||
&ev_fence->lock, evf_mgr->ev_fence_ctx,
|
||||
atomic_inc_return(&evf_mgr->ev_fence_seq));
|
||||
dma_fence_init64(&ev_fence->base, &amdgpu_eviction_fence_ops,
|
||||
&ev_fence->lock, evf_mgr->ev_fence_ctx,
|
||||
atomic_inc_return(&evf_mgr->ev_fence_seq));
|
||||
return ev_fence;
|
||||
}
|
||||
|
||||
|
||||
@@ -204,7 +204,8 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
|
||||
|
||||
int amdgpu_job_alloc(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
||||
struct drm_sched_entity *entity, void *owner,
|
||||
unsigned int num_ibs, struct amdgpu_job **job)
|
||||
unsigned int num_ibs, struct amdgpu_job **job,
|
||||
u64 drm_client_id)
|
||||
{
|
||||
if (num_ibs == 0)
|
||||
return -EINVAL;
|
||||
@@ -222,7 +223,8 @@ int amdgpu_job_alloc(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
||||
if (!entity)
|
||||
return 0;
|
||||
|
||||
return drm_sched_job_init(&(*job)->base, entity, 1, owner);
|
||||
return drm_sched_job_init(&(*job)->base, entity, 1, owner,
|
||||
drm_client_id);
|
||||
}
|
||||
|
||||
int amdgpu_job_alloc_with_ib(struct amdgpu_device *adev,
|
||||
@@ -232,7 +234,7 @@ int amdgpu_job_alloc_with_ib(struct amdgpu_device *adev,
|
||||
{
|
||||
int r;
|
||||
|
||||
r = amdgpu_job_alloc(adev, NULL, entity, owner, 1, job);
|
||||
r = amdgpu_job_alloc(adev, NULL, entity, owner, 1, job, 0);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
|
||||
@@ -91,7 +91,8 @@ static inline struct amdgpu_ring *amdgpu_job_ring(struct amdgpu_job *job)
|
||||
|
||||
int amdgpu_job_alloc(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
||||
struct drm_sched_entity *entity, void *owner,
|
||||
unsigned int num_ibs, struct amdgpu_job **job);
|
||||
unsigned int num_ibs, struct amdgpu_job **job,
|
||||
u64 drm_client_id);
|
||||
int amdgpu_job_alloc_with_ib(struct amdgpu_device *adev,
|
||||
struct drm_sched_entity *entity, void *owner,
|
||||
size_t size, enum amdgpu_ib_pool_type pool_type,
|
||||
|
||||
@@ -167,25 +167,23 @@ TRACE_EVENT(amdgpu_cs_ioctl,
|
||||
TP_PROTO(struct amdgpu_job *job),
|
||||
TP_ARGS(job),
|
||||
TP_STRUCT__entry(
|
||||
__field(uint64_t, sched_job_id)
|
||||
__string(timeline, AMDGPU_JOB_GET_TIMELINE_NAME(job))
|
||||
__field(unsigned int, context)
|
||||
__field(unsigned int, seqno)
|
||||
__field(u64, context)
|
||||
__field(u64, seqno)
|
||||
__field(struct dma_fence *, fence)
|
||||
__string(ring, to_amdgpu_ring(job->base.sched)->name)
|
||||
__field(u32, num_ibs)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->sched_job_id = job->base.id;
|
||||
__assign_str(timeline);
|
||||
__entry->context = job->base.s_fence->finished.context;
|
||||
__entry->seqno = job->base.s_fence->finished.seqno;
|
||||
__assign_str(ring);
|
||||
__entry->num_ibs = job->num_ibs;
|
||||
),
|
||||
TP_printk("sched_job=%llu, timeline=%s, context=%u, seqno=%u, ring_name=%s, num_ibs=%u",
|
||||
__entry->sched_job_id, __get_str(timeline), __entry->context,
|
||||
TP_printk("timeline=%s, fence=%llu:%llu, ring_name=%s, num_ibs=%u",
|
||||
__get_str(timeline), __entry->context,
|
||||
__entry->seqno, __get_str(ring), __entry->num_ibs)
|
||||
);
|
||||
|
||||
@@ -193,24 +191,22 @@ TRACE_EVENT(amdgpu_sched_run_job,
|
||||
TP_PROTO(struct amdgpu_job *job),
|
||||
TP_ARGS(job),
|
||||
TP_STRUCT__entry(
|
||||
__field(uint64_t, sched_job_id)
|
||||
__string(timeline, AMDGPU_JOB_GET_TIMELINE_NAME(job))
|
||||
__field(unsigned int, context)
|
||||
__field(unsigned int, seqno)
|
||||
__field(u64, context)
|
||||
__field(u64, seqno)
|
||||
__string(ring, to_amdgpu_ring(job->base.sched)->name)
|
||||
__field(u32, num_ibs)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->sched_job_id = job->base.id;
|
||||
__assign_str(timeline);
|
||||
__entry->context = job->base.s_fence->finished.context;
|
||||
__entry->seqno = job->base.s_fence->finished.seqno;
|
||||
__assign_str(ring);
|
||||
__entry->num_ibs = job->num_ibs;
|
||||
),
|
||||
TP_printk("sched_job=%llu, timeline=%s, context=%u, seqno=%u, ring_name=%s, num_ibs=%u",
|
||||
__entry->sched_job_id, __get_str(timeline), __entry->context,
|
||||
TP_printk("timeline=%s, fence=%llu:%llu, ring_name=%s, num_ibs=%u",
|
||||
__get_str(timeline), __entry->context,
|
||||
__entry->seqno, __get_str(ring), __entry->num_ibs)
|
||||
);
|
||||
|
||||
@@ -551,23 +547,19 @@ TRACE_EVENT(amdgpu_ib_pipe_sync,
|
||||
TP_ARGS(sched_job, fence),
|
||||
TP_STRUCT__entry(
|
||||
__string(ring, sched_job->base.sched->name)
|
||||
__field(uint64_t, id)
|
||||
__field(struct dma_fence *, fence)
|
||||
__field(uint64_t, ctx)
|
||||
__field(unsigned, seqno)
|
||||
__field(u64, ctx)
|
||||
__field(u64, seqno)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(ring);
|
||||
__entry->id = sched_job->base.id;
|
||||
__entry->fence = fence;
|
||||
__entry->ctx = fence->context;
|
||||
__entry->seqno = fence->seqno;
|
||||
),
|
||||
TP_printk("job ring=%s, id=%llu, need pipe sync to fence=%p, context=%llu, seq=%u",
|
||||
__get_str(ring), __entry->id,
|
||||
__entry->fence, __entry->ctx,
|
||||
__entry->seqno)
|
||||
TP_printk("job ring=%s need pipe sync to fence=%llu:%llu",
|
||||
__get_str(ring), __entry->ctx, __entry->seqno)
|
||||
);
|
||||
|
||||
TRACE_EVENT(amdgpu_reset_reg_dumps,
|
||||
|
||||
@@ -239,8 +239,8 @@ static int amdgpu_userq_fence_create(struct amdgpu_usermode_queue *userq,
|
||||
fence = &userq_fence->base;
|
||||
userq_fence->fence_drv = fence_drv;
|
||||
|
||||
dma_fence_init(fence, &amdgpu_userq_fence_ops, &userq_fence->lock,
|
||||
fence_drv->context, seq);
|
||||
dma_fence_init64(fence, &amdgpu_userq_fence_ops, &userq_fence->lock,
|
||||
fence_drv->context, seq);
|
||||
|
||||
amdgpu_userq_fence_driver_get(fence_drv);
|
||||
dma_fence_get(fence);
|
||||
@@ -334,7 +334,6 @@ static void amdgpu_userq_fence_release(struct dma_fence *f)
|
||||
}
|
||||
|
||||
static const struct dma_fence_ops amdgpu_userq_fence_ops = {
|
||||
.use_64bit_seqno = true,
|
||||
.get_driver_name = amdgpu_userq_fence_get_driver_name,
|
||||
.get_timeline_name = amdgpu_userq_fence_get_timeline_name,
|
||||
.signaled = amdgpu_userq_fence_signaled,
|
||||
|
||||
@@ -71,7 +71,6 @@ static void amdgpu_tlb_fence_work(struct work_struct *work)
|
||||
}
|
||||
|
||||
static const struct dma_fence_ops amdgpu_tlb_fence_ops = {
|
||||
.use_64bit_seqno = true,
|
||||
.get_driver_name = amdgpu_tlb_fence_get_driver_name,
|
||||
.get_timeline_name = amdgpu_tlb_fence_get_timeline_name
|
||||
};
|
||||
@@ -101,8 +100,8 @@ void amdgpu_vm_tlb_fence_create(struct amdgpu_device *adev, struct amdgpu_vm *vm
|
||||
INIT_WORK(&f->work, amdgpu_tlb_fence_work);
|
||||
spin_lock_init(&f->lock);
|
||||
|
||||
dma_fence_init(&f->base, &amdgpu_tlb_fence_ops, &f->lock,
|
||||
vm->tlb_fence_context, atomic64_read(&vm->tlb_seq));
|
||||
dma_fence_init64(&f->base, &amdgpu_tlb_fence_ops, &f->lock,
|
||||
vm->tlb_fence_context, atomic64_read(&vm->tlb_seq));
|
||||
|
||||
/* TODO: We probably need a separate wq here */
|
||||
dma_fence_get(&f->base);
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/platform_data/simplefb.h>
|
||||
|
||||
#include <video/pixel_format.h>
|
||||
#include <video/videomode.h>
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
@@ -73,7 +73,17 @@ static const struct drm_crtc_funcs hdlcd_crtc_funcs = {
|
||||
.disable_vblank = hdlcd_crtc_disable_vblank,
|
||||
};
|
||||
|
||||
static struct simplefb_format supported_formats[] = SIMPLEFB_FORMATS;
|
||||
static const struct {
|
||||
u32 fourcc;
|
||||
struct pixel_format pixel;
|
||||
} supported_formats[] = {
|
||||
{ DRM_FORMAT_RGB565, PIXEL_FORMAT_RGB565 },
|
||||
{ DRM_FORMAT_XRGB1555, PIXEL_FORMAT_XRGB1555 },
|
||||
{ DRM_FORMAT_RGB888, PIXEL_FORMAT_RGB888 },
|
||||
{ DRM_FORMAT_XRGB8888, PIXEL_FORMAT_XRGB8888 },
|
||||
{ DRM_FORMAT_XBGR8888, PIXEL_FORMAT_XBGR8888 },
|
||||
{ DRM_FORMAT_XRGB2101010, PIXEL_FORMAT_XRGB2101010},
|
||||
};
|
||||
|
||||
/*
|
||||
* Setup the HDLCD registers for decoding the pixels out of the framebuffer
|
||||
@@ -83,15 +93,12 @@ static int hdlcd_set_pxl_fmt(struct drm_crtc *crtc)
|
||||
unsigned int btpp;
|
||||
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
|
||||
const struct drm_framebuffer *fb = crtc->primary->state->fb;
|
||||
uint32_t pixel_format;
|
||||
struct simplefb_format *format = NULL;
|
||||
const struct pixel_format *format = NULL;
|
||||
int i;
|
||||
|
||||
pixel_format = fb->format->format;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(supported_formats); i++) {
|
||||
if (supported_formats[i].fourcc == pixel_format)
|
||||
format = &supported_formats[i];
|
||||
if (supported_formats[i].fourcc == fb->format->format)
|
||||
format = &supported_formats[i].pixel;
|
||||
}
|
||||
|
||||
if (WARN_ON(!format))
|
||||
|
||||
@@ -64,7 +64,7 @@ static const struct drm_driver ast_driver = {
|
||||
.minor = DRIVER_MINOR,
|
||||
.patchlevel = DRIVER_PATCHLEVEL,
|
||||
|
||||
DRM_GEM_SHMEM_DRIVER_OPS,
|
||||
DRM_GEM_SHMEM_DRIVER_OPS_NO_MAP_SGT,
|
||||
DRM_FBDEV_SHMEM_DRIVER_OPS,
|
||||
};
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_color_mgmt.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_damage_helper.h>
|
||||
#include <drm/drm_format_helper.h>
|
||||
@@ -71,31 +72,44 @@ static unsigned long ast_fb_vram_size(struct ast_device *ast)
|
||||
return cursor_offset - offset;
|
||||
}
|
||||
|
||||
static inline void ast_load_palette_index(struct ast_device *ast,
|
||||
u8 index, u8 red, u8 green,
|
||||
u8 blue)
|
||||
static void ast_set_gamma_lut(struct drm_crtc *crtc, unsigned int index,
|
||||
u16 red, u16 green, u16 blue)
|
||||
{
|
||||
ast_io_write8(ast, AST_IO_VGADWR, index);
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct ast_device *ast = to_ast_device(dev);
|
||||
u8 i8 = index & 0xff;
|
||||
u8 r8 = red >> 8;
|
||||
u8 g8 = green >> 8;
|
||||
u8 b8 = blue >> 8;
|
||||
|
||||
if (drm_WARN_ON_ONCE(dev, index != i8))
|
||||
return; /* driver bug */
|
||||
|
||||
ast_io_write8(ast, AST_IO_VGADWR, i8);
|
||||
ast_io_read8(ast, AST_IO_VGASRI);
|
||||
ast_io_write8(ast, AST_IO_VGAPDR, red);
|
||||
ast_io_write8(ast, AST_IO_VGAPDR, r8);
|
||||
ast_io_read8(ast, AST_IO_VGASRI);
|
||||
ast_io_write8(ast, AST_IO_VGAPDR, green);
|
||||
ast_io_write8(ast, AST_IO_VGAPDR, g8);
|
||||
ast_io_read8(ast, AST_IO_VGASRI);
|
||||
ast_io_write8(ast, AST_IO_VGAPDR, blue);
|
||||
ast_io_write8(ast, AST_IO_VGAPDR, b8);
|
||||
ast_io_read8(ast, AST_IO_VGASRI);
|
||||
}
|
||||
|
||||
static void ast_crtc_set_gamma_linear(struct ast_device *ast,
|
||||
const struct drm_format_info *format)
|
||||
static void ast_crtc_fill_gamma(struct ast_device *ast,
|
||||
const struct drm_format_info *format)
|
||||
{
|
||||
int i;
|
||||
struct drm_crtc *crtc = &ast->crtc;
|
||||
|
||||
switch (format->format) {
|
||||
case DRM_FORMAT_C8: /* In this case, gamma table is used as color palette */
|
||||
case DRM_FORMAT_C8:
|
||||
/* gamma table is used as color palette */
|
||||
drm_crtc_fill_palette_8(crtc, ast_set_gamma_lut);
|
||||
break;
|
||||
case DRM_FORMAT_RGB565:
|
||||
/* also uses 8-bit gamma ramp on low-color modes */
|
||||
fallthrough;
|
||||
case DRM_FORMAT_XRGB8888:
|
||||
for (i = 0; i < AST_LUT_SIZE; i++)
|
||||
ast_load_palette_index(ast, i, i, i, i);
|
||||
drm_crtc_fill_gamma_888(crtc, ast_set_gamma_lut);
|
||||
break;
|
||||
default:
|
||||
drm_warn_once(&ast->base, "Unsupported format %p4cc for gamma correction\n",
|
||||
@@ -104,21 +118,22 @@ static void ast_crtc_set_gamma_linear(struct ast_device *ast,
|
||||
}
|
||||
}
|
||||
|
||||
static void ast_crtc_set_gamma(struct ast_device *ast,
|
||||
const struct drm_format_info *format,
|
||||
struct drm_color_lut *lut)
|
||||
static void ast_crtc_load_gamma(struct ast_device *ast,
|
||||
const struct drm_format_info *format,
|
||||
struct drm_color_lut *lut)
|
||||
{
|
||||
int i;
|
||||
struct drm_crtc *crtc = &ast->crtc;
|
||||
|
||||
switch (format->format) {
|
||||
case DRM_FORMAT_C8: /* In this case, gamma table is used as color palette */
|
||||
case DRM_FORMAT_C8:
|
||||
/* gamma table is used as color palette */
|
||||
drm_crtc_load_palette_8(crtc, lut, ast_set_gamma_lut);
|
||||
break;
|
||||
case DRM_FORMAT_RGB565:
|
||||
/* also uses 8-bit gamma ramp on low-color modes */
|
||||
fallthrough;
|
||||
case DRM_FORMAT_XRGB8888:
|
||||
for (i = 0; i < AST_LUT_SIZE; i++)
|
||||
ast_load_palette_index(ast, i,
|
||||
lut[i].red >> 8,
|
||||
lut[i].green >> 8,
|
||||
lut[i].blue >> 8);
|
||||
drm_crtc_load_gamma_888(crtc, lut, ast_set_gamma_lut);
|
||||
break;
|
||||
default:
|
||||
drm_warn_once(&ast->base, "Unsupported format %p4cc for gamma correction\n",
|
||||
@@ -811,11 +826,11 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
|
||||
*/
|
||||
if (crtc_state->enable && crtc_state->color_mgmt_changed) {
|
||||
if (crtc_state->gamma_lut)
|
||||
ast_crtc_set_gamma(ast,
|
||||
ast_crtc_state->format,
|
||||
crtc_state->gamma_lut->data);
|
||||
ast_crtc_load_gamma(ast,
|
||||
ast_crtc_state->format,
|
||||
crtc_state->gamma_lut->data);
|
||||
else
|
||||
ast_crtc_set_gamma_linear(ast, ast_crtc_state->format);
|
||||
ast_crtc_fill_gamma(ast, ast_crtc_state->format);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,9 @@ config DRM_I2C_ADV7511
|
||||
select DRM_KMS_HELPER
|
||||
select REGMAP_I2C
|
||||
select DRM_MIPI_DSI
|
||||
select DRM_DISPLAY_HELPER
|
||||
select DRM_BRIDGE_CONNECTOR
|
||||
select DRM_DISPLAY_HDMI_STATE_HELPER
|
||||
help
|
||||
Support for the Analog Devices ADV7511(W)/13/33/35 HDMI encoders.
|
||||
|
||||
@@ -19,7 +22,7 @@ config DRM_I2C_ADV7511_AUDIO
|
||||
config DRM_I2C_ADV7511_CEC
|
||||
bool "ADV7511/33/35 HDMI CEC driver"
|
||||
depends on DRM_I2C_ADV7511
|
||||
select CEC_CORE
|
||||
select DRM_DISPLAY_HDMI_CEC_HELPER
|
||||
default y
|
||||
help
|
||||
When selected the HDMI transmitter will support the CEC feature.
|
||||
|
||||
@@ -313,16 +313,11 @@ enum adv7511_csc_scaling {
|
||||
* @csc_enable: Whether to enable color space conversion
|
||||
* @csc_scaling_factor: Color space conversion scaling factor
|
||||
* @csc_coefficents: Color space conversion coefficents
|
||||
* @hdmi_mode: Whether to use HDMI or DVI output mode
|
||||
* @avi_infoframe: HDMI infoframe
|
||||
*/
|
||||
struct adv7511_video_config {
|
||||
bool csc_enable;
|
||||
enum adv7511_csc_scaling csc_scaling_factor;
|
||||
const uint16_t *csc_coefficents;
|
||||
|
||||
bool hdmi_mode;
|
||||
struct hdmi_avi_infoframe avi_infoframe;
|
||||
};
|
||||
|
||||
enum adv7511_type {
|
||||
@@ -337,6 +332,7 @@ struct adv7511_chip_info {
|
||||
enum adv7511_type type;
|
||||
unsigned int max_mode_clock_khz;
|
||||
unsigned int max_lane_freq_khz;
|
||||
const char *name;
|
||||
const char * const *supply_names;
|
||||
unsigned int num_supplies;
|
||||
unsigned int reg_cec_offset;
|
||||
@@ -371,7 +367,7 @@ struct adv7511 {
|
||||
struct work_struct hpd_work;
|
||||
|
||||
struct drm_bridge bridge;
|
||||
struct drm_connector connector;
|
||||
struct drm_connector *cec_connector;
|
||||
|
||||
bool embedded_sync;
|
||||
enum adv7511_sync_polarity vsync_polarity;
|
||||
@@ -389,9 +385,7 @@ struct adv7511 {
|
||||
bool use_timing_gen;
|
||||
|
||||
const struct adv7511_chip_info *info;
|
||||
struct platform_device *audio_pdev;
|
||||
|
||||
struct cec_adapter *cec_adap;
|
||||
u8 cec_addr[ADV7511_MAX_ADDRS];
|
||||
u8 cec_valid_addrs;
|
||||
bool cec_enabled_adap;
|
||||
@@ -399,20 +393,29 @@ struct adv7511 {
|
||||
u32 cec_clk_freq;
|
||||
};
|
||||
|
||||
static inline struct adv7511 *bridge_to_adv7511(struct drm_bridge *bridge)
|
||||
{
|
||||
return container_of(bridge, struct adv7511, bridge);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DRM_I2C_ADV7511_CEC
|
||||
int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511);
|
||||
int adv7511_cec_init(struct drm_connector *connector,
|
||||
struct drm_bridge *bridge);
|
||||
int adv7511_cec_enable(struct drm_bridge *bridge, bool enable);
|
||||
int adv7511_cec_log_addr(struct drm_bridge *bridge, u8 addr);
|
||||
int adv7511_cec_transmit(struct drm_bridge *bridge, u8 attempts,
|
||||
u32 signal_free_time, struct cec_msg *msg);
|
||||
int adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1);
|
||||
#else
|
||||
static inline int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511)
|
||||
{
|
||||
regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL,
|
||||
ADV7511_CEC_CTRL_POWER_DOWN);
|
||||
return 0;
|
||||
}
|
||||
#define adv7511_cec_init NULL
|
||||
#define adv7511_cec_enable NULL
|
||||
#define adv7511_cec_log_addr NULL
|
||||
#define adv7511_cec_transmit NULL
|
||||
#endif
|
||||
|
||||
void adv7533_dsi_power_on(struct adv7511 *adv);
|
||||
void adv7533_dsi_power_off(struct adv7511 *adv);
|
||||
void adv7533_dsi_config_timing_gen(struct adv7511 *adv);
|
||||
enum drm_mode_status adv7533_mode_valid(struct adv7511 *adv,
|
||||
const struct drm_display_mode *mode);
|
||||
int adv7533_patch_registers(struct adv7511 *adv);
|
||||
@@ -421,16 +424,18 @@ int adv7533_attach_dsi(struct adv7511 *adv);
|
||||
int adv7533_parse_dt(struct device_node *np, struct adv7511 *adv);
|
||||
|
||||
#ifdef CONFIG_DRM_I2C_ADV7511_AUDIO
|
||||
int adv7511_audio_init(struct device *dev, struct adv7511 *adv7511);
|
||||
void adv7511_audio_exit(struct adv7511 *adv7511);
|
||||
int adv7511_hdmi_audio_startup(struct drm_connector *connector,
|
||||
struct drm_bridge *bridge);
|
||||
void adv7511_hdmi_audio_shutdown(struct drm_connector *connector,
|
||||
struct drm_bridge *bridge);
|
||||
int adv7511_hdmi_audio_prepare(struct drm_connector *connector,
|
||||
struct drm_bridge *bridge,
|
||||
struct hdmi_codec_daifmt *fmt,
|
||||
struct hdmi_codec_params *hparms);
|
||||
#else /*CONFIG_DRM_I2C_ADV7511_AUDIO */
|
||||
static inline int adv7511_audio_init(struct device *dev, struct adv7511 *adv7511)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void adv7511_audio_exit(struct adv7511 *adv7511)
|
||||
{
|
||||
}
|
||||
#define adv7511_hdmi_audio_startup NULL
|
||||
#define adv7511_hdmi_audio_shutdown NULL
|
||||
#define adv7511_hdmi_audio_prepare NULL
|
||||
#endif /* CONFIG_DRM_I2C_ADV7511_AUDIO */
|
||||
|
||||
#endif /* __DRM_I2C_ADV7511_H__ */
|
||||
|
||||
@@ -55,11 +55,12 @@ static int adv7511_update_cts_n(struct adv7511 *adv7511)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adv7511_hdmi_hw_params(struct device *dev, void *data,
|
||||
struct hdmi_codec_daifmt *fmt,
|
||||
struct hdmi_codec_params *hparms)
|
||||
int adv7511_hdmi_audio_prepare(struct drm_connector *connector,
|
||||
struct drm_bridge *bridge,
|
||||
struct hdmi_codec_daifmt *fmt,
|
||||
struct hdmi_codec_params *hparms)
|
||||
{
|
||||
struct adv7511 *adv7511 = dev_get_drvdata(dev);
|
||||
struct adv7511 *adv7511 = bridge_to_adv7511(bridge);
|
||||
unsigned int audio_source, i2s_format = 0;
|
||||
unsigned int invert_clock;
|
||||
unsigned int rate;
|
||||
@@ -167,9 +168,10 @@ static int adv7511_hdmi_hw_params(struct device *dev, void *data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int audio_startup(struct device *dev, void *data)
|
||||
int adv7511_hdmi_audio_startup(struct drm_connector *connector,
|
||||
struct drm_bridge *bridge)
|
||||
{
|
||||
struct adv7511 *adv7511 = dev_get_drvdata(dev);
|
||||
struct adv7511 *adv7511 = bridge_to_adv7511(bridge);
|
||||
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG,
|
||||
BIT(7), 0);
|
||||
@@ -204,69 +206,12 @@ static int audio_startup(struct device *dev, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void audio_shutdown(struct device *dev, void *data)
|
||||
void adv7511_hdmi_audio_shutdown(struct drm_connector *connector,
|
||||
struct drm_bridge *bridge)
|
||||
{
|
||||
struct adv7511 *adv7511 = dev_get_drvdata(dev);
|
||||
struct adv7511 *adv7511 = bridge_to_adv7511(bridge);
|
||||
|
||||
if (adv7511->audio_source == ADV7511_AUDIO_SOURCE_SPDIF)
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG,
|
||||
BIT(7), 0);
|
||||
}
|
||||
|
||||
static int adv7511_hdmi_i2s_get_dai_id(struct snd_soc_component *component,
|
||||
struct device_node *endpoint,
|
||||
void *data)
|
||||
{
|
||||
struct of_endpoint of_ep;
|
||||
int ret;
|
||||
|
||||
ret = of_graph_parse_endpoint(endpoint, &of_ep);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* HDMI sound should be located as reg = <2>
|
||||
* Then, it is sound port 0
|
||||
*/
|
||||
if (of_ep.port == 2)
|
||||
return 0;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const struct hdmi_codec_ops adv7511_codec_ops = {
|
||||
.hw_params = adv7511_hdmi_hw_params,
|
||||
.audio_shutdown = audio_shutdown,
|
||||
.audio_startup = audio_startup,
|
||||
.get_dai_id = adv7511_hdmi_i2s_get_dai_id,
|
||||
};
|
||||
|
||||
static const struct hdmi_codec_pdata codec_data = {
|
||||
.ops = &adv7511_codec_ops,
|
||||
.i2s_formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |
|
||||
SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE |
|
||||
SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE),
|
||||
.max_i2s_channels = 2,
|
||||
.i2s = 1,
|
||||
.no_i2s_capture = 1,
|
||||
.spdif = 1,
|
||||
.no_spdif_capture = 1,
|
||||
};
|
||||
|
||||
int adv7511_audio_init(struct device *dev, struct adv7511 *adv7511)
|
||||
{
|
||||
adv7511->audio_pdev = platform_device_register_data(dev,
|
||||
HDMI_CODEC_DRV_NAME,
|
||||
PLATFORM_DEVID_AUTO,
|
||||
&codec_data,
|
||||
sizeof(codec_data));
|
||||
return PTR_ERR_OR_ZERO(adv7511->audio_pdev);
|
||||
}
|
||||
|
||||
void adv7511_audio_exit(struct adv7511 *adv7511)
|
||||
{
|
||||
if (adv7511->audio_pdev) {
|
||||
platform_device_unregister(adv7511->audio_pdev);
|
||||
adv7511->audio_pdev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
|
||||
#include <media/cec.h>
|
||||
|
||||
#include <drm/display/drm_hdmi_cec_helper.h>
|
||||
|
||||
#include "adv7511.h"
|
||||
|
||||
static const u8 ADV7511_REG_CEC_RX_FRAME_HDR[] = {
|
||||
@@ -44,8 +46,8 @@ static void adv_cec_tx_raw_status(struct adv7511 *adv7511, u8 tx_raw_status)
|
||||
return;
|
||||
|
||||
if (tx_raw_status & ADV7511_INT1_CEC_TX_ARBIT_LOST) {
|
||||
cec_transmit_attempt_done(adv7511->cec_adap,
|
||||
CEC_TX_STATUS_ARB_LOST);
|
||||
drm_connector_hdmi_cec_transmit_attempt_done(adv7511->cec_connector,
|
||||
CEC_TX_STATUS_ARB_LOST);
|
||||
return;
|
||||
}
|
||||
if (tx_raw_status & ADV7511_INT1_CEC_TX_RETRY_TIMEOUT) {
|
||||
@@ -72,12 +74,14 @@ static void adv_cec_tx_raw_status(struct adv7511 *adv7511, u8 tx_raw_status)
|
||||
if (low_drive_cnt)
|
||||
status |= CEC_TX_STATUS_LOW_DRIVE;
|
||||
}
|
||||
cec_transmit_done(adv7511->cec_adap, status,
|
||||
0, nack_cnt, low_drive_cnt, err_cnt);
|
||||
drm_connector_hdmi_cec_transmit_done(adv7511->cec_connector, status,
|
||||
0, nack_cnt, low_drive_cnt,
|
||||
err_cnt);
|
||||
return;
|
||||
}
|
||||
if (tx_raw_status & ADV7511_INT1_CEC_TX_READY) {
|
||||
cec_transmit_attempt_done(adv7511->cec_adap, CEC_TX_STATUS_OK);
|
||||
drm_connector_hdmi_cec_transmit_attempt_done(adv7511->cec_connector,
|
||||
CEC_TX_STATUS_OK);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -116,7 +120,7 @@ static void adv7511_cec_rx(struct adv7511 *adv7511, int rx_buf)
|
||||
regmap_update_bits(adv7511->regmap_cec,
|
||||
ADV7511_REG_CEC_RX_BUFFERS + offset, BIT(rx_buf), 0);
|
||||
|
||||
cec_received_msg(adv7511->cec_adap, &msg);
|
||||
drm_connector_hdmi_cec_received_msg(adv7511->cec_connector, &msg);
|
||||
}
|
||||
|
||||
int adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1)
|
||||
@@ -179,9 +183,9 @@ int adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int adv7511_cec_adap_enable(struct cec_adapter *adap, bool enable)
|
||||
int adv7511_cec_enable(struct drm_bridge *bridge, bool enable)
|
||||
{
|
||||
struct adv7511 *adv7511 = cec_get_drvdata(adap);
|
||||
struct adv7511 *adv7511 = bridge_to_adv7511(bridge);
|
||||
unsigned int offset = adv7511->info->reg_cec_offset;
|
||||
|
||||
if (adv7511->i2c_cec == NULL)
|
||||
@@ -225,9 +229,9 @@ static int adv7511_cec_adap_enable(struct cec_adapter *adap, bool enable)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adv7511_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
|
||||
int adv7511_cec_log_addr(struct drm_bridge *bridge, u8 addr)
|
||||
{
|
||||
struct adv7511 *adv7511 = cec_get_drvdata(adap);
|
||||
struct adv7511 *adv7511 = bridge_to_adv7511(bridge);
|
||||
unsigned int offset = adv7511->info->reg_cec_offset;
|
||||
unsigned int i, free_idx = ADV7511_MAX_ADDRS;
|
||||
|
||||
@@ -293,10 +297,10 @@ static int adv7511_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adv7511_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
|
||||
u32 signal_free_time, struct cec_msg *msg)
|
||||
int adv7511_cec_transmit(struct drm_bridge *bridge, u8 attempts,
|
||||
u32 signal_free_time, struct cec_msg *msg)
|
||||
{
|
||||
struct adv7511 *adv7511 = cec_get_drvdata(adap);
|
||||
struct adv7511 *adv7511 = bridge_to_adv7511(bridge);
|
||||
unsigned int offset = adv7511->info->reg_cec_offset;
|
||||
u8 len = msg->len;
|
||||
unsigned int i;
|
||||
@@ -328,12 +332,6 @@ static int adv7511_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct cec_adap_ops adv7511_cec_adap_ops = {
|
||||
.adap_enable = adv7511_cec_adap_enable,
|
||||
.adap_log_addr = adv7511_cec_adap_log_addr,
|
||||
.adap_transmit = adv7511_cec_adap_transmit,
|
||||
};
|
||||
|
||||
static int adv7511_cec_parse_dt(struct device *dev, struct adv7511 *adv7511)
|
||||
{
|
||||
adv7511->cec_clk = devm_clk_get(dev, "cec");
|
||||
@@ -348,20 +346,18 @@ static int adv7511_cec_parse_dt(struct device *dev, struct adv7511 *adv7511)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511)
|
||||
int adv7511_cec_init(struct drm_connector *connector,
|
||||
struct drm_bridge *bridge)
|
||||
{
|
||||
struct adv7511 *adv7511 = bridge_to_adv7511(bridge);
|
||||
struct device *dev = &adv7511->i2c_main->dev;
|
||||
unsigned int offset = adv7511->info->reg_cec_offset;
|
||||
int ret = adv7511_cec_parse_dt(dev, adv7511);
|
||||
|
||||
if (ret)
|
||||
goto err_cec_parse_dt;
|
||||
|
||||
adv7511->cec_adap = cec_allocate_adapter(&adv7511_cec_adap_ops,
|
||||
adv7511, dev_name(dev), CEC_CAP_DEFAULTS, ADV7511_MAX_ADDRS);
|
||||
if (IS_ERR(adv7511->cec_adap)) {
|
||||
ret = PTR_ERR(adv7511->cec_adap);
|
||||
goto err_cec_alloc;
|
||||
}
|
||||
adv7511->cec_connector = connector;
|
||||
|
||||
regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL, 0);
|
||||
/* cec soft reset */
|
||||
@@ -378,17 +374,8 @@ int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511)
|
||||
ADV7511_REG_CEC_CLK_DIV + offset,
|
||||
((adv7511->cec_clk_freq / 750000) - 1) << 2);
|
||||
|
||||
ret = cec_register_adapter(adv7511->cec_adap, dev);
|
||||
if (ret)
|
||||
goto err_cec_register;
|
||||
return 0;
|
||||
|
||||
err_cec_register:
|
||||
cec_delete_adapter(adv7511->cec_adap);
|
||||
adv7511->cec_adap = NULL;
|
||||
err_cec_alloc:
|
||||
dev_info(dev, "Initializing CEC failed with error %d, disabling CEC\n",
|
||||
ret);
|
||||
err_cec_parse_dt:
|
||||
regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL,
|
||||
ADV7511_CEC_CTRL_POWER_DOWN);
|
||||
|
||||
@@ -12,14 +12,17 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <media/cec.h>
|
||||
#include <sound/pcm.h>
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_bridge_connector.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/display/drm_hdmi_helper.h>
|
||||
#include <drm/display/drm_hdmi_state_helper.h>
|
||||
|
||||
#include "adv7511.h"
|
||||
|
||||
@@ -203,62 +206,37 @@ static const uint16_t adv7511_csc_ycbcr_to_rgb[] = {
|
||||
|
||||
static void adv7511_set_config_csc(struct adv7511 *adv7511,
|
||||
struct drm_connector *connector,
|
||||
bool rgb, bool hdmi_mode)
|
||||
bool rgb)
|
||||
{
|
||||
struct adv7511_video_config config;
|
||||
bool output_format_422, output_format_ycbcr;
|
||||
unsigned int mode;
|
||||
uint8_t infoframe[17];
|
||||
|
||||
config.hdmi_mode = hdmi_mode;
|
||||
|
||||
hdmi_avi_infoframe_init(&config.avi_infoframe);
|
||||
|
||||
config.avi_infoframe.scan_mode = HDMI_SCAN_MODE_UNDERSCAN;
|
||||
|
||||
if (rgb) {
|
||||
config.csc_enable = false;
|
||||
config.avi_infoframe.colorspace = HDMI_COLORSPACE_RGB;
|
||||
output_format_422 = false;
|
||||
output_format_ycbcr = false;
|
||||
} else {
|
||||
config.csc_scaling_factor = ADV7511_CSC_SCALING_4;
|
||||
config.csc_coefficents = adv7511_csc_ycbcr_to_rgb;
|
||||
|
||||
if ((connector->display_info.color_formats &
|
||||
DRM_COLOR_FORMAT_YCBCR422) &&
|
||||
config.hdmi_mode) {
|
||||
connector->display_info.is_hdmi) {
|
||||
config.csc_enable = false;
|
||||
config.avi_infoframe.colorspace =
|
||||
HDMI_COLORSPACE_YUV422;
|
||||
} else {
|
||||
config.csc_enable = true;
|
||||
config.avi_infoframe.colorspace = HDMI_COLORSPACE_RGB;
|
||||
}
|
||||
}
|
||||
|
||||
if (config.hdmi_mode) {
|
||||
mode = ADV7511_HDMI_CFG_MODE_HDMI;
|
||||
|
||||
switch (config.avi_infoframe.colorspace) {
|
||||
case HDMI_COLORSPACE_YUV444:
|
||||
output_format_422 = false;
|
||||
output_format_ycbcr = true;
|
||||
break;
|
||||
case HDMI_COLORSPACE_YUV422:
|
||||
output_format_422 = true;
|
||||
output_format_ycbcr = true;
|
||||
break;
|
||||
default:
|
||||
} else {
|
||||
config.csc_enable = true;
|
||||
output_format_422 = false;
|
||||
output_format_ycbcr = false;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
mode = ADV7511_HDMI_CFG_MODE_DVI;
|
||||
output_format_422 = false;
|
||||
output_format_ycbcr = false;
|
||||
}
|
||||
|
||||
adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_AVI_INFOFRAME);
|
||||
if (connector->display_info.is_hdmi)
|
||||
mode = ADV7511_HDMI_CFG_MODE_HDMI;
|
||||
else
|
||||
mode = ADV7511_HDMI_CFG_MODE_DVI;
|
||||
|
||||
adv7511_set_colormap(adv7511, config.csc_enable,
|
||||
config.csc_coefficents,
|
||||
@@ -269,15 +247,6 @@ static void adv7511_set_config_csc(struct adv7511 *adv7511,
|
||||
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_HDCP_HDMI_CFG,
|
||||
ADV7511_HDMI_CFG_MODE_MASK, mode);
|
||||
|
||||
hdmi_avi_infoframe_pack(&config.avi_infoframe, infoframe,
|
||||
sizeof(infoframe));
|
||||
|
||||
/* The AVI infoframe id is not configurable */
|
||||
regmap_bulk_write(adv7511->regmap, ADV7511_REG_AVI_INFOFRAME_VERSION,
|
||||
infoframe + 1, sizeof(infoframe) - 1);
|
||||
|
||||
adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_AVI_INFOFRAME);
|
||||
}
|
||||
|
||||
static void adv7511_set_link_config(struct adv7511 *adv7511,
|
||||
@@ -446,22 +415,16 @@ static void adv7511_hpd_work(struct work_struct *work)
|
||||
* restore its state.
|
||||
*/
|
||||
if (status == connector_status_connected &&
|
||||
adv7511->connector.status == connector_status_disconnected &&
|
||||
adv7511->status == connector_status_disconnected &&
|
||||
adv7511->powered) {
|
||||
regcache_mark_dirty(adv7511->regmap);
|
||||
adv7511_power_on(adv7511);
|
||||
}
|
||||
|
||||
if (adv7511->connector.status != status) {
|
||||
adv7511->connector.status = status;
|
||||
if (adv7511->status != status) {
|
||||
adv7511->status = status;
|
||||
|
||||
if (adv7511->connector.dev) {
|
||||
if (status == connector_status_disconnected)
|
||||
cec_phys_addr_invalidate(adv7511->cec_adap);
|
||||
drm_kms_helper_hotplug_event(adv7511->connector.dev);
|
||||
} else {
|
||||
drm_bridge_hpd_notify(&adv7511->bridge, status);
|
||||
}
|
||||
drm_bridge_hpd_notify(&adv7511->bridge, status);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -636,45 +599,11 @@ static const struct drm_edid *adv7511_edid_read(struct adv7511 *adv7511,
|
||||
if (!adv7511->powered)
|
||||
__adv7511_power_off(adv7511);
|
||||
|
||||
if (drm_edid) {
|
||||
/*
|
||||
* FIXME: The CEC physical address should be set using
|
||||
* cec_s_phys_addr(adap,
|
||||
* connector->display_info.source_physical_address, false) from
|
||||
* a path that has read the EDID and called
|
||||
* drm_edid_connector_update().
|
||||
*/
|
||||
const struct edid *edid = drm_edid_raw(drm_edid);
|
||||
|
||||
adv7511_set_config_csc(adv7511, connector, adv7511->rgb,
|
||||
drm_detect_hdmi_monitor(edid));
|
||||
|
||||
cec_s_phys_addr_from_edid(adv7511->cec_adap, edid);
|
||||
} else {
|
||||
cec_s_phys_addr_from_edid(adv7511->cec_adap, NULL);
|
||||
}
|
||||
|
||||
return drm_edid;
|
||||
}
|
||||
|
||||
static int adv7511_get_modes(struct adv7511 *adv7511,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
const struct drm_edid *drm_edid;
|
||||
unsigned int count;
|
||||
|
||||
drm_edid = adv7511_edid_read(adv7511, connector);
|
||||
|
||||
drm_edid_connector_update(connector, drm_edid);
|
||||
count = drm_edid_connector_add_modes(connector);
|
||||
|
||||
drm_edid_free(drm_edid);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
adv7511_detect(struct adv7511 *adv7511, struct drm_connector *connector)
|
||||
adv7511_detect(struct adv7511 *adv7511)
|
||||
{
|
||||
enum drm_connector_status status;
|
||||
unsigned int val;
|
||||
@@ -699,8 +628,6 @@ adv7511_detect(struct adv7511 *adv7511, struct drm_connector *connector)
|
||||
if (status == connector_status_connected && hpd && adv7511->powered) {
|
||||
regcache_mark_dirty(adv7511->regmap);
|
||||
adv7511_power_on(adv7511);
|
||||
if (connector)
|
||||
adv7511_get_modes(adv7511, connector);
|
||||
if (adv7511->status == connector_status_connected)
|
||||
status = connector_status_disconnected;
|
||||
} else {
|
||||
@@ -719,17 +646,7 @@ adv7511_detect(struct adv7511 *adv7511, struct drm_connector *connector)
|
||||
return status;
|
||||
}
|
||||
|
||||
static enum drm_mode_status adv7511_mode_valid(struct adv7511 *adv7511,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
if (mode->clock > 165000)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static void adv7511_mode_set(struct adv7511 *adv7511,
|
||||
const struct drm_display_mode *mode,
|
||||
const struct drm_display_mode *adj_mode)
|
||||
{
|
||||
unsigned int low_refresh_rate;
|
||||
@@ -800,11 +717,11 @@ static void adv7511_mode_set(struct adv7511 *adv7511,
|
||||
vsync_polarity = 1;
|
||||
}
|
||||
|
||||
if (drm_mode_vrefresh(mode) <= 24)
|
||||
if (drm_mode_vrefresh(adj_mode) <= 24)
|
||||
low_refresh_rate = ADV7511_LOW_REFRESH_RATE_24HZ;
|
||||
else if (drm_mode_vrefresh(mode) <= 25)
|
||||
else if (drm_mode_vrefresh(adj_mode) <= 25)
|
||||
low_refresh_rate = ADV7511_LOW_REFRESH_RATE_25HZ;
|
||||
else if (drm_mode_vrefresh(mode) <= 30)
|
||||
else if (drm_mode_vrefresh(adj_mode) <= 30)
|
||||
low_refresh_rate = ADV7511_LOW_REFRESH_RATE_30HZ;
|
||||
else
|
||||
low_refresh_rate = ADV7511_LOW_REFRESH_RATE_NONE;
|
||||
@@ -821,82 +738,30 @@ static void adv7511_mode_set(struct adv7511 *adv7511,
|
||||
|
||||
drm_mode_copy(&adv7511->curr_mode, adj_mode);
|
||||
|
||||
/* Update horizontal/vertical porch params */
|
||||
if (adv7511->info->has_dsi && adv7511->use_timing_gen)
|
||||
adv7533_dsi_config_timing_gen(adv7511);
|
||||
|
||||
/*
|
||||
* TODO Test first order 4:2:2 to 4:4:4 up conversion method, which is
|
||||
* supposed to give better results.
|
||||
*/
|
||||
|
||||
adv7511->f_tmds = mode->clock;
|
||||
adv7511->f_tmds = adj_mode->clock;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* DRM Connector Operations
|
||||
*/
|
||||
|
||||
static struct adv7511 *connector_to_adv7511(struct drm_connector *connector)
|
||||
{
|
||||
return container_of(connector, struct adv7511, connector);
|
||||
}
|
||||
|
||||
static int adv7511_connector_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct adv7511 *adv = connector_to_adv7511(connector);
|
||||
|
||||
return adv7511_get_modes(adv, connector);
|
||||
}
|
||||
|
||||
static enum drm_mode_status
|
||||
adv7511_connector_mode_valid(struct drm_connector *connector,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
struct adv7511 *adv = connector_to_adv7511(connector);
|
||||
|
||||
return adv7511_mode_valid(adv, mode);
|
||||
}
|
||||
|
||||
static struct drm_connector_helper_funcs adv7511_connector_helper_funcs = {
|
||||
.get_modes = adv7511_connector_get_modes,
|
||||
.mode_valid = adv7511_connector_mode_valid,
|
||||
};
|
||||
|
||||
static enum drm_connector_status
|
||||
adv7511_connector_detect(struct drm_connector *connector, bool force)
|
||||
{
|
||||
struct adv7511 *adv = connector_to_adv7511(connector);
|
||||
|
||||
return adv7511_detect(adv, connector);
|
||||
}
|
||||
|
||||
static const struct drm_connector_funcs adv7511_connector_funcs = {
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.detect = adv7511_connector_detect,
|
||||
.destroy = drm_connector_cleanup,
|
||||
.reset = drm_atomic_helper_connector_reset,
|
||||
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
};
|
||||
|
||||
static int adv7511_connector_init(struct adv7511 *adv)
|
||||
{
|
||||
struct drm_bridge *bridge = &adv->bridge;
|
||||
int ret;
|
||||
struct drm_connector *connector;
|
||||
|
||||
if (adv->i2c_main->irq)
|
||||
adv->connector.polled = DRM_CONNECTOR_POLL_HPD;
|
||||
else
|
||||
adv->connector.polled = DRM_CONNECTOR_POLL_CONNECT |
|
||||
DRM_CONNECTOR_POLL_DISCONNECT;
|
||||
|
||||
ret = drm_connector_init(bridge->dev, &adv->connector,
|
||||
&adv7511_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_HDMIA);
|
||||
if (ret < 0) {
|
||||
connector = drm_bridge_connector_init(bridge->dev, bridge->encoder);
|
||||
if (IS_ERR(connector)) {
|
||||
DRM_ERROR("Failed to initialize connector with drm\n");
|
||||
return ret;
|
||||
return PTR_ERR(connector);
|
||||
}
|
||||
drm_connector_helper_add(&adv->connector,
|
||||
&adv7511_connector_helper_funcs);
|
||||
drm_connector_attach_encoder(&adv->connector, bridge->encoder);
|
||||
|
||||
drm_connector_attach_encoder(connector, bridge->encoder);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -905,7 +770,7 @@ static int adv7511_connector_init(struct adv7511 *adv)
|
||||
* DRM Bridge Operations
|
||||
*/
|
||||
|
||||
static struct adv7511 *bridge_to_adv7511(struct drm_bridge *bridge)
|
||||
static const struct adv7511 *bridge_to_adv7511_const(const struct drm_bridge *bridge)
|
||||
{
|
||||
return container_of(bridge, struct adv7511, bridge);
|
||||
}
|
||||
@@ -914,8 +779,29 @@ static void adv7511_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct adv7511 *adv = bridge_to_adv7511(bridge);
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_state *conn_state;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
|
||||
adv7511_power_on(adv);
|
||||
|
||||
connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
|
||||
if (WARN_ON(!connector))
|
||||
return;
|
||||
|
||||
conn_state = drm_atomic_get_new_connector_state(state, connector);
|
||||
if (WARN_ON(!conn_state))
|
||||
return;
|
||||
|
||||
crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
|
||||
if (WARN_ON(!crtc_state))
|
||||
return;
|
||||
|
||||
adv7511_set_config_csc(adv, connector, adv->rgb);
|
||||
|
||||
adv7511_mode_set(adv, &crtc_state->adjusted_mode);
|
||||
|
||||
drm_atomic_helper_connector_hdmi_update_infoframes(connector, state);
|
||||
}
|
||||
|
||||
static void adv7511_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
@@ -926,13 +812,17 @@ static void adv7511_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
adv7511_power_off(adv);
|
||||
}
|
||||
|
||||
static void adv7511_bridge_mode_set(struct drm_bridge *bridge,
|
||||
const struct drm_display_mode *mode,
|
||||
const struct drm_display_mode *adj_mode)
|
||||
static enum drm_mode_status
|
||||
adv7511_bridge_hdmi_tmds_char_rate_valid(const struct drm_bridge *bridge,
|
||||
const struct drm_display_mode *mode,
|
||||
unsigned long long tmds_rate)
|
||||
{
|
||||
struct adv7511 *adv = bridge_to_adv7511(bridge);
|
||||
const struct adv7511 *adv = bridge_to_adv7511_const(bridge);
|
||||
|
||||
adv7511_mode_set(adv, mode, adj_mode);
|
||||
if (tmds_rate > 1000ULL * adv->info->max_mode_clock_khz)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static enum drm_mode_status adv7511_bridge_mode_valid(struct drm_bridge *bridge,
|
||||
@@ -941,10 +831,10 @@ static enum drm_mode_status adv7511_bridge_mode_valid(struct drm_bridge *bridge,
|
||||
{
|
||||
struct adv7511 *adv = bridge_to_adv7511(bridge);
|
||||
|
||||
if (adv->info->has_dsi)
|
||||
return adv7533_mode_valid(adv, mode);
|
||||
else
|
||||
return adv7511_mode_valid(adv, mode);
|
||||
if (!adv->info->has_dsi)
|
||||
return MODE_OK;
|
||||
|
||||
return adv7533_mode_valid(adv, mode);
|
||||
}
|
||||
|
||||
static int adv7511_bridge_attach(struct drm_bridge *bridge,
|
||||
@@ -978,7 +868,7 @@ static enum drm_connector_status adv7511_bridge_detect(struct drm_bridge *bridge
|
||||
{
|
||||
struct adv7511 *adv = bridge_to_adv7511(bridge);
|
||||
|
||||
return adv7511_detect(adv, NULL);
|
||||
return adv7511_detect(adv);
|
||||
}
|
||||
|
||||
static const struct drm_edid *adv7511_bridge_edid_read(struct drm_bridge *bridge,
|
||||
@@ -989,28 +879,71 @@ static const struct drm_edid *adv7511_bridge_edid_read(struct drm_bridge *bridge
|
||||
return adv7511_edid_read(adv, connector);
|
||||
}
|
||||
|
||||
static void adv7511_bridge_hpd_notify(struct drm_bridge *bridge,
|
||||
enum drm_connector_status status)
|
||||
static int adv7511_bridge_hdmi_clear_infoframe(struct drm_bridge *bridge,
|
||||
enum hdmi_infoframe_type type)
|
||||
{
|
||||
struct adv7511 *adv = bridge_to_adv7511(bridge);
|
||||
struct adv7511 *adv7511 = bridge_to_adv7511(bridge);
|
||||
|
||||
if (status == connector_status_disconnected)
|
||||
cec_phys_addr_invalidate(adv->cec_adap);
|
||||
switch (type) {
|
||||
case HDMI_INFOFRAME_TYPE_AVI:
|
||||
adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_AVI_INFOFRAME);
|
||||
break;
|
||||
default:
|
||||
drm_dbg_driver(adv7511->bridge.dev, "Unsupported HDMI InfoFrame %x\n", type);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adv7511_bridge_hdmi_write_infoframe(struct drm_bridge *bridge,
|
||||
enum hdmi_infoframe_type type,
|
||||
const u8 *buffer, size_t len)
|
||||
{
|
||||
struct adv7511 *adv7511 = bridge_to_adv7511(bridge);
|
||||
|
||||
adv7511_bridge_hdmi_clear_infoframe(bridge, type);
|
||||
|
||||
switch (type) {
|
||||
case HDMI_INFOFRAME_TYPE_AVI:
|
||||
/* The AVI infoframe id is not configurable */
|
||||
regmap_bulk_write(adv7511->regmap, ADV7511_REG_AVI_INFOFRAME_VERSION,
|
||||
buffer + 1, len - 1);
|
||||
|
||||
adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_AVI_INFOFRAME);
|
||||
break;
|
||||
default:
|
||||
drm_dbg_driver(adv7511->bridge.dev, "Unsupported HDMI InfoFrame %x\n", type);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_bridge_funcs adv7511_bridge_funcs = {
|
||||
.mode_set = adv7511_bridge_mode_set,
|
||||
.mode_valid = adv7511_bridge_mode_valid,
|
||||
.attach = adv7511_bridge_attach,
|
||||
.detect = adv7511_bridge_detect,
|
||||
.edid_read = adv7511_bridge_edid_read,
|
||||
.hpd_notify = adv7511_bridge_hpd_notify,
|
||||
|
||||
.atomic_enable = adv7511_bridge_atomic_enable,
|
||||
.atomic_disable = adv7511_bridge_atomic_disable,
|
||||
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
|
||||
.atomic_reset = drm_atomic_helper_bridge_reset,
|
||||
|
||||
.hdmi_tmds_char_rate_valid = adv7511_bridge_hdmi_tmds_char_rate_valid,
|
||||
.hdmi_clear_infoframe = adv7511_bridge_hdmi_clear_infoframe,
|
||||
.hdmi_write_infoframe = adv7511_bridge_hdmi_write_infoframe,
|
||||
|
||||
.hdmi_audio_startup = adv7511_hdmi_audio_startup,
|
||||
.hdmi_audio_prepare = adv7511_hdmi_audio_prepare,
|
||||
.hdmi_audio_shutdown = adv7511_hdmi_audio_shutdown,
|
||||
|
||||
.hdmi_cec_init = adv7511_cec_init,
|
||||
.hdmi_cec_enable = adv7511_cec_enable,
|
||||
.hdmi_cec_log_addr = adv7511_cec_log_addr,
|
||||
.hdmi_cec_transmit = adv7511_cec_transmit,
|
||||
};
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
@@ -1224,9 +1157,10 @@ static int adv7511_probe(struct i2c_client *i2c)
|
||||
if (!dev->of_node)
|
||||
return -EINVAL;
|
||||
|
||||
adv7511 = devm_kzalloc(dev, sizeof(*adv7511), GFP_KERNEL);
|
||||
if (!adv7511)
|
||||
return -ENOMEM;
|
||||
adv7511 = devm_drm_bridge_alloc(dev, struct adv7511, bridge,
|
||||
&adv7511_bridge_funcs);
|
||||
if (IS_ERR(adv7511))
|
||||
return PTR_ERR(adv7511);
|
||||
|
||||
adv7511->i2c_main = i2c;
|
||||
adv7511->powered = false;
|
||||
@@ -1323,22 +1257,43 @@ static int adv7511_probe(struct i2c_client *i2c)
|
||||
if (adv7511->info->link_config)
|
||||
adv7511_set_link_config(adv7511, &link_config);
|
||||
|
||||
ret = adv7511_cec_init(dev, adv7511);
|
||||
if (ret)
|
||||
goto err_unregister_cec;
|
||||
regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL,
|
||||
ADV7511_CEC_CTRL_POWER_DOWN);
|
||||
|
||||
adv7511->bridge.funcs = &adv7511_bridge_funcs;
|
||||
adv7511->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID;
|
||||
adv7511->bridge.ops = DRM_BRIDGE_OP_DETECT |
|
||||
DRM_BRIDGE_OP_EDID |
|
||||
DRM_BRIDGE_OP_HDMI |
|
||||
DRM_BRIDGE_OP_HDMI_AUDIO |
|
||||
DRM_BRIDGE_OP_HDMI_CEC_ADAPTER;
|
||||
if (adv7511->i2c_main->irq)
|
||||
adv7511->bridge.ops |= DRM_BRIDGE_OP_HPD;
|
||||
|
||||
adv7511->bridge.vendor = "Analog";
|
||||
adv7511->bridge.product = adv7511->info->name;
|
||||
|
||||
#ifdef CONFIG_DRM_I2C_ADV7511_AUDIO
|
||||
adv7511->bridge.hdmi_audio_dev = dev;
|
||||
adv7511->bridge.hdmi_audio_max_i2s_playback_channels = 2;
|
||||
adv7511->bridge.hdmi_audio_i2s_formats = (SNDRV_PCM_FMTBIT_S16_LE |
|
||||
SNDRV_PCM_FMTBIT_S20_3LE |
|
||||
SNDRV_PCM_FMTBIT_S24_3LE |
|
||||
SNDRV_PCM_FMTBIT_S24_LE |
|
||||
SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE),
|
||||
adv7511->bridge.hdmi_audio_spdif_playback = 1;
|
||||
adv7511->bridge.hdmi_audio_dai_port = 2;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DRM_I2C_ADV7511_CEC
|
||||
adv7511->bridge.hdmi_cec_dev = dev;
|
||||
adv7511->bridge.hdmi_cec_adapter_name = dev_name(dev);
|
||||
adv7511->bridge.hdmi_cec_available_las = ADV7511_MAX_ADDRS;
|
||||
#endif
|
||||
|
||||
adv7511->bridge.of_node = dev->of_node;
|
||||
adv7511->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
|
||||
|
||||
drm_bridge_add(&adv7511->bridge);
|
||||
|
||||
adv7511_audio_init(dev, adv7511);
|
||||
|
||||
if (i2c->irq) {
|
||||
init_waitqueue_head(&adv7511->wq);
|
||||
|
||||
@@ -1360,10 +1315,7 @@ static int adv7511_probe(struct i2c_client *i2c)
|
||||
return 0;
|
||||
|
||||
err_unregister_audio:
|
||||
adv7511_audio_exit(adv7511);
|
||||
drm_bridge_remove(&adv7511->bridge);
|
||||
err_unregister_cec:
|
||||
cec_unregister_adapter(adv7511->cec_adap);
|
||||
i2c_unregister_device(adv7511->i2c_cec);
|
||||
clk_disable_unprepare(adv7511->cec_clk);
|
||||
err_i2c_unregister_packet:
|
||||
@@ -1388,9 +1340,6 @@ static void adv7511_remove(struct i2c_client *i2c)
|
||||
|
||||
drm_bridge_remove(&adv7511->bridge);
|
||||
|
||||
adv7511_audio_exit(adv7511);
|
||||
|
||||
cec_unregister_adapter(adv7511->cec_adap);
|
||||
i2c_unregister_device(adv7511->i2c_cec);
|
||||
clk_disable_unprepare(adv7511->cec_clk);
|
||||
|
||||
@@ -1400,6 +1349,8 @@ static void adv7511_remove(struct i2c_client *i2c)
|
||||
|
||||
static const struct adv7511_chip_info adv7511_chip_info = {
|
||||
.type = ADV7511,
|
||||
.name = "ADV7511",
|
||||
.max_mode_clock_khz = 165000,
|
||||
.supply_names = adv7511_supply_names,
|
||||
.num_supplies = ARRAY_SIZE(adv7511_supply_names),
|
||||
.link_config = true,
|
||||
@@ -1407,6 +1358,7 @@ static const struct adv7511_chip_info adv7511_chip_info = {
|
||||
|
||||
static const struct adv7511_chip_info adv7533_chip_info = {
|
||||
.type = ADV7533,
|
||||
.name = "ADV7533",
|
||||
.max_mode_clock_khz = 80000,
|
||||
.max_lane_freq_khz = 800000,
|
||||
.supply_names = adv7533_supply_names,
|
||||
@@ -1417,6 +1369,7 @@ static const struct adv7511_chip_info adv7533_chip_info = {
|
||||
|
||||
static const struct adv7511_chip_info adv7535_chip_info = {
|
||||
.type = ADV7535,
|
||||
.name = "ADV7535",
|
||||
.max_mode_clock_khz = 148500,
|
||||
.max_lane_freq_khz = 891000,
|
||||
.supply_names = adv7533_supply_names,
|
||||
|
||||
@@ -24,7 +24,7 @@ static const struct reg_sequence adv7533_cec_fixed_registers[] = {
|
||||
{ 0x05, 0xc8 },
|
||||
};
|
||||
|
||||
static void adv7511_dsi_config_timing_gen(struct adv7511 *adv)
|
||||
void adv7533_dsi_config_timing_gen(struct adv7511 *adv)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = adv->dsi;
|
||||
struct drm_display_mode *mode = &adv->curr_mode;
|
||||
@@ -67,9 +67,6 @@ void adv7533_dsi_power_on(struct adv7511 *adv)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = adv->dsi;
|
||||
|
||||
if (adv->use_timing_gen)
|
||||
adv7511_dsi_config_timing_gen(adv);
|
||||
|
||||
/* set number of dsi lanes */
|
||||
regmap_write(adv->regmap_cec, 0x1c, dsi->lanes << 4);
|
||||
|
||||
@@ -106,10 +103,6 @@ enum drm_mode_status adv7533_mode_valid(struct adv7511 *adv,
|
||||
struct mipi_dsi_device *dsi = adv->dsi;
|
||||
u8 bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
|
||||
|
||||
/* Check max clock for either 7533 or 7535 */
|
||||
if (mode->clock > adv->info->max_mode_clock_khz)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
/* Check max clock for each lane */
|
||||
if (mode->clock * bpp > adv->info->max_lane_freq_khz * adv->num_dsi_lanes)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
@@ -1193,9 +1193,10 @@ static int anx78xx_i2c_probe(struct i2c_client *client)
|
||||
bool found = false;
|
||||
int err;
|
||||
|
||||
anx78xx = devm_kzalloc(&client->dev, sizeof(*anx78xx), GFP_KERNEL);
|
||||
if (!anx78xx)
|
||||
return -ENOMEM;
|
||||
anx78xx = devm_drm_bridge_alloc(&client->dev, struct anx78xx, bridge,
|
||||
&anx78xx_bridge_funcs);
|
||||
if (IS_ERR(anx78xx))
|
||||
return PTR_ERR(anx78xx);
|
||||
|
||||
pdata = &anx78xx->pdata;
|
||||
|
||||
@@ -1306,8 +1307,6 @@ static int anx78xx_i2c_probe(struct i2c_client *client)
|
||||
goto err_poweroff;
|
||||
}
|
||||
|
||||
anx78xx->bridge.funcs = &anx78xx_bridge_funcs;
|
||||
|
||||
drm_bridge_add(&anx78xx->bridge);
|
||||
|
||||
/* If cable is pulled out, just poweroff and wait for HPD event */
|
||||
|
||||
@@ -2596,7 +2596,6 @@ static int anx7625_link_bridge(struct drm_dp_aux *aux)
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform->bridge.funcs = &anx7625_bridge_funcs;
|
||||
platform->bridge.of_node = dev->of_node;
|
||||
if (!anx7625_of_panel_on_aux_bus(dev))
|
||||
platform->bridge.ops |= DRM_BRIDGE_OP_EDID;
|
||||
@@ -2630,10 +2629,10 @@ static int anx7625_i2c_probe(struct i2c_client *client)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
platform = devm_kzalloc(dev, sizeof(*platform), GFP_KERNEL);
|
||||
if (!platform) {
|
||||
platform = devm_drm_bridge_alloc(dev, struct anx7625_data, bridge, &anx7625_bridge_funcs);
|
||||
if (IS_ERR(platform)) {
|
||||
DRM_DEV_ERROR(dev, "fail to allocate driver data\n");
|
||||
return -ENOMEM;
|
||||
return PTR_ERR(platform);
|
||||
}
|
||||
|
||||
pdata = &platform->pdata;
|
||||
|
||||
@@ -109,9 +109,10 @@ static int drm_aux_bridge_probe(struct auxiliary_device *auxdev,
|
||||
{
|
||||
struct drm_aux_bridge_data *data;
|
||||
|
||||
data = devm_kzalloc(&auxdev->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
data = devm_drm_bridge_alloc(&auxdev->dev, struct drm_aux_bridge_data,
|
||||
bridge, &drm_aux_bridge_funcs);
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
data->dev = &auxdev->dev;
|
||||
data->next_bridge = devm_drm_of_get_bridge(&auxdev->dev, auxdev->dev.of_node, 0, 0);
|
||||
@@ -119,7 +120,6 @@ static int drm_aux_bridge_probe(struct auxiliary_device *auxdev,
|
||||
return dev_err_probe(&auxdev->dev, PTR_ERR(data->next_bridge),
|
||||
"failed to acquire drm_bridge\n");
|
||||
|
||||
data->bridge.funcs = &drm_aux_bridge_funcs;
|
||||
data->bridge.of_node = data->dev->of_node;
|
||||
|
||||
/* passthrough data, allow everything */
|
||||
|
||||
@@ -171,12 +171,13 @@ static int drm_aux_hpd_bridge_probe(struct auxiliary_device *auxdev,
|
||||
{
|
||||
struct drm_aux_hpd_bridge_data *data;
|
||||
|
||||
data = devm_kzalloc(&auxdev->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
data = devm_drm_bridge_alloc(&auxdev->dev,
|
||||
struct drm_aux_hpd_bridge_data, bridge,
|
||||
&drm_aux_hpd_bridge_funcs);
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
data->dev = &auxdev->dev;
|
||||
data->bridge.funcs = &drm_aux_hpd_bridge_funcs;
|
||||
data->bridge.of_node = dev_get_platdata(data->dev);
|
||||
data->bridge.ops = DRM_BRIDGE_OP_HPD;
|
||||
data->bridge.type = id->driver_data;
|
||||
|
||||
@@ -670,13 +670,28 @@ cdns_dsi_bridge_mode_valid(struct drm_bridge *bridge,
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static void cdns_dsi_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
static void cdns_dsi_bridge_atomic_post_disable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
|
||||
struct cdns_dsi *dsi = input_to_dsi(input);
|
||||
u32 val;
|
||||
|
||||
/*
|
||||
* The cdns-dsi controller needs to be disabled after it's DPI source
|
||||
* has stopped streaming. If this is not followed, there is a brief
|
||||
* window before DPI source is disabled and after cdns-dsi controller
|
||||
* has been disabled where the DPI stream is still on, but the cdns-dsi
|
||||
* controller is not ready anymore to accept the incoming signals. This
|
||||
* is one of the reasons why a shift in pixel colors is observed on
|
||||
* displays that have cdns-dsi as one of the bridges.
|
||||
*
|
||||
* To mitigate this, disable this bridge from the bridge post_disable()
|
||||
* hook, instead of the bridge _disable() hook. The bridge post_disable()
|
||||
* hook gets called after the CRTC disable, where often many DPI sources
|
||||
* disable their streams.
|
||||
*/
|
||||
|
||||
val = readl(dsi->regs + MCTL_MAIN_DATA_CTL);
|
||||
val &= ~(IF_VID_SELECT_MASK | IF_VID_MODE | VID_EN | HOST_EOT_GEN |
|
||||
DISP_EOT_GEN);
|
||||
@@ -688,15 +703,6 @@ static void cdns_dsi_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
if (dsi->platform_ops && dsi->platform_ops->disable)
|
||||
dsi->platform_ops->disable(dsi);
|
||||
|
||||
pm_runtime_put(dsi->base.dev);
|
||||
}
|
||||
|
||||
static void cdns_dsi_bridge_atomic_post_disable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
|
||||
struct cdns_dsi *dsi = input_to_dsi(input);
|
||||
|
||||
dsi->phy_initialized = false;
|
||||
dsi->link_initialized = false;
|
||||
phy_power_off(dsi->dphy);
|
||||
@@ -774,8 +780,8 @@ static void cdns_dsi_init_link(struct cdns_dsi *dsi)
|
||||
dsi->link_initialized = true;
|
||||
}
|
||||
|
||||
static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
static void cdns_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
|
||||
struct cdns_dsi *dsi = input_to_dsi(input);
|
||||
@@ -792,6 +798,21 @@ static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
u32 tmp, reg_wakeup, div, status;
|
||||
int nlanes;
|
||||
|
||||
/*
|
||||
* The cdns-dsi controller needs to be enabled before it's DPI source
|
||||
* has begun streaming. If this is not followed, there is a brief window
|
||||
* after DPI source enable and before cdns-dsi controller enable where
|
||||
* the DPI stream is on, but the cdns-dsi controller is not ready to
|
||||
* accept the incoming signals. This is one of the reasons why a shift
|
||||
* in pixel colors is observed on displays that have cdns-dsi as one of
|
||||
* the bridges.
|
||||
*
|
||||
* To mitigate this, enable this bridge from the bridge pre_enable()
|
||||
* hook, instead of the bridge _enable() hook. The bridge pre_enable()
|
||||
* hook gets called before the CRTC enable, where often many DPI sources
|
||||
* enable their streams.
|
||||
*/
|
||||
|
||||
if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
|
||||
return;
|
||||
|
||||
@@ -811,8 +832,8 @@ static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
mode = &crtc_state->adjusted_mode;
|
||||
nlanes = output->dev->lanes;
|
||||
|
||||
cdns_dsi_hs_init(dsi);
|
||||
cdns_dsi_init_link(dsi);
|
||||
cdns_dsi_hs_init(dsi);
|
||||
|
||||
/*
|
||||
* Now that the DSI Link and DSI Phy are initialized,
|
||||
@@ -941,19 +962,6 @@ static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
writel(tmp, dsi->regs + MCTL_MAIN_EN);
|
||||
}
|
||||
|
||||
static void cdns_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
|
||||
struct cdns_dsi *dsi = input_to_dsi(input);
|
||||
|
||||
if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
|
||||
return;
|
||||
|
||||
cdns_dsi_init_link(dsi);
|
||||
cdns_dsi_hs_init(dsi);
|
||||
}
|
||||
|
||||
static u32 *cdns_dsi_bridge_get_input_bus_fmts(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *bridge_state,
|
||||
struct drm_crtc_state *crtc_state,
|
||||
@@ -1048,9 +1056,7 @@ cdns_dsi_bridge_atomic_reset(struct drm_bridge *bridge)
|
||||
static const struct drm_bridge_funcs cdns_dsi_bridge_funcs = {
|
||||
.attach = cdns_dsi_bridge_attach,
|
||||
.mode_valid = cdns_dsi_bridge_mode_valid,
|
||||
.atomic_disable = cdns_dsi_bridge_atomic_disable,
|
||||
.atomic_pre_enable = cdns_dsi_bridge_atomic_pre_enable,
|
||||
.atomic_enable = cdns_dsi_bridge_atomic_enable,
|
||||
.atomic_post_disable = cdns_dsi_bridge_atomic_post_disable,
|
||||
.atomic_check = cdns_dsi_bridge_atomic_check,
|
||||
.atomic_reset = cdns_dsi_bridge_atomic_reset,
|
||||
@@ -1289,9 +1295,10 @@ static int cdns_dsi_drm_probe(struct platform_device *pdev)
|
||||
int ret, irq;
|
||||
u32 val;
|
||||
|
||||
dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL);
|
||||
if (!dsi)
|
||||
return -ENOMEM;
|
||||
dsi = devm_drm_bridge_alloc(&pdev->dev, struct cdns_dsi, input.bridge,
|
||||
&cdns_dsi_bridge_funcs);
|
||||
if (IS_ERR(dsi))
|
||||
return PTR_ERR(dsi);
|
||||
|
||||
platform_set_drvdata(pdev, dsi);
|
||||
|
||||
@@ -1349,7 +1356,6 @@ static int cdns_dsi_drm_probe(struct platform_device *pdev)
|
||||
* CDNS_DPI_INPUT.
|
||||
*/
|
||||
input->id = CDNS_DPI_INPUT;
|
||||
input->bridge.funcs = &cdns_dsi_bridge_funcs;
|
||||
input->bridge.of_node = pdev->dev.of_node;
|
||||
|
||||
/* Mask all interrupts before registering the IRQ handler. */
|
||||
|
||||
@@ -2389,9 +2389,10 @@ static int cdns_mhdp_probe(struct platform_device *pdev)
|
||||
int ret;
|
||||
int irq;
|
||||
|
||||
mhdp = devm_kzalloc(dev, sizeof(*mhdp), GFP_KERNEL);
|
||||
if (!mhdp)
|
||||
return -ENOMEM;
|
||||
mhdp = devm_drm_bridge_alloc(dev, struct cdns_mhdp_device, bridge,
|
||||
&cdns_mhdp_bridge_funcs);
|
||||
if (IS_ERR(mhdp))
|
||||
return PTR_ERR(mhdp);
|
||||
|
||||
clk = devm_clk_get_enabled(dev, NULL);
|
||||
if (IS_ERR(clk)) {
|
||||
@@ -2481,7 +2482,6 @@ static int cdns_mhdp_probe(struct platform_device *pdev)
|
||||
mhdp->display_fmt.bpc = 8;
|
||||
|
||||
mhdp->bridge.of_node = pdev->dev.of_node;
|
||||
mhdp->bridge.funcs = &cdns_mhdp_bridge_funcs;
|
||||
mhdp->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID |
|
||||
DRM_BRIDGE_OP_HPD;
|
||||
mhdp->bridge.type = DRM_MODE_CONNECTOR_DisplayPort;
|
||||
|
||||
@@ -691,9 +691,10 @@ static int chipone_common_probe(struct device *dev, struct chipone **icnr)
|
||||
struct chipone *icn;
|
||||
int ret;
|
||||
|
||||
icn = devm_kzalloc(dev, sizeof(struct chipone), GFP_KERNEL);
|
||||
if (!icn)
|
||||
return -ENOMEM;
|
||||
icn = devm_drm_bridge_alloc(dev, struct chipone, bridge,
|
||||
&chipone_bridge_funcs);
|
||||
if (IS_ERR(icn))
|
||||
return PTR_ERR(icn);
|
||||
|
||||
icn->dev = dev;
|
||||
|
||||
@@ -701,7 +702,6 @@ static int chipone_common_probe(struct device *dev, struct chipone **icnr)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
icn->bridge.funcs = &chipone_bridge_funcs;
|
||||
icn->bridge.type = DRM_MODE_CONNECTOR_DPI;
|
||||
icn->bridge.of_node = dev->of_node;
|
||||
|
||||
|
||||
@@ -536,9 +536,10 @@ static int ch7033_probe(struct i2c_client *client)
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
priv = devm_drm_bridge_alloc(dev, struct ch7033_priv, bridge,
|
||||
&ch7033_bridge_funcs);
|
||||
if (IS_ERR(priv))
|
||||
return PTR_ERR(priv);
|
||||
|
||||
dev_set_drvdata(dev, priv);
|
||||
|
||||
@@ -575,7 +576,6 @@ static int ch7033_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&priv->bridge.list);
|
||||
priv->bridge.funcs = &ch7033_bridge_funcs;
|
||||
priv->bridge.of_node = dev->of_node;
|
||||
drm_bridge_add(&priv->bridge);
|
||||
|
||||
|
||||
@@ -103,9 +103,10 @@ static int cros_ec_anx7688_bridge_probe(struct i2c_client *client)
|
||||
u8 buffer[4];
|
||||
int ret;
|
||||
|
||||
anx7688 = devm_kzalloc(dev, sizeof(*anx7688), GFP_KERNEL);
|
||||
if (!anx7688)
|
||||
return -ENOMEM;
|
||||
anx7688 = devm_drm_bridge_alloc(dev, struct cros_ec_anx7688, bridge,
|
||||
&cros_ec_anx7688_bridge_funcs);
|
||||
if (IS_ERR(anx7688))
|
||||
return PTR_ERR(anx7688);
|
||||
|
||||
anx7688->client = client;
|
||||
i2c_set_clientdata(client, anx7688);
|
||||
@@ -153,7 +154,6 @@ static int cros_ec_anx7688_bridge_probe(struct i2c_client *client)
|
||||
DRM_WARN("Old ANX7688 FW version (0x%04x), not filtering\n",
|
||||
fw_version);
|
||||
|
||||
anx7688->bridge.funcs = &cros_ec_anx7688_bridge_funcs;
|
||||
drm_bridge_add(&anx7688->bridge);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -298,16 +298,15 @@ static int fsl_ldb_probe(struct platform_device *pdev)
|
||||
struct fsl_ldb *fsl_ldb;
|
||||
int dual_link;
|
||||
|
||||
fsl_ldb = devm_kzalloc(dev, sizeof(*fsl_ldb), GFP_KERNEL);
|
||||
if (!fsl_ldb)
|
||||
return -ENOMEM;
|
||||
fsl_ldb = devm_drm_bridge_alloc(dev, struct fsl_ldb, bridge, &funcs);
|
||||
if (IS_ERR(fsl_ldb))
|
||||
return PTR_ERR(fsl_ldb);
|
||||
|
||||
fsl_ldb->devdata = of_device_get_match_data(dev);
|
||||
if (!fsl_ldb->devdata)
|
||||
return -EINVAL;
|
||||
|
||||
fsl_ldb->dev = &pdev->dev;
|
||||
fsl_ldb->bridge.funcs = &funcs;
|
||||
fsl_ldb->bridge.of_node = dev->of_node;
|
||||
|
||||
fsl_ldb->clk = devm_clk_get(dev, "ldb");
|
||||
|
||||
@@ -59,9 +59,10 @@ struct drm_bridge *devm_imx_drm_legacy_bridge(struct device *dev,
|
||||
struct imx_legacy_bridge *imx_bridge;
|
||||
int ret;
|
||||
|
||||
imx_bridge = devm_kzalloc(dev, sizeof(*imx_bridge), GFP_KERNEL);
|
||||
if (!imx_bridge)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
imx_bridge = devm_drm_bridge_alloc(dev, struct imx_legacy_bridge,
|
||||
base, &imx_legacy_bridge_funcs);
|
||||
if (IS_ERR(imx_bridge))
|
||||
return ERR_CAST(imx_bridge);
|
||||
|
||||
ret = of_get_drm_display_mode(np,
|
||||
&imx_bridge->mode,
|
||||
@@ -72,7 +73,6 @@ struct drm_bridge *devm_imx_drm_legacy_bridge(struct device *dev,
|
||||
|
||||
imx_bridge->mode.type |= DRM_MODE_TYPE_DRIVER;
|
||||
|
||||
imx_bridge->base.funcs = &imx_legacy_bridge_funcs;
|
||||
imx_bridge->base.of_node = np;
|
||||
imx_bridge->base.ops = DRM_BRIDGE_OP_MODES;
|
||||
imx_bridge->base.type = type;
|
||||
|
||||
@@ -140,9 +140,10 @@ static int imx8mp_hdmi_pvi_probe(struct platform_device *pdev)
|
||||
struct device_node *remote;
|
||||
struct imx8mp_hdmi_pvi *pvi;
|
||||
|
||||
pvi = devm_kzalloc(&pdev->dev, sizeof(*pvi), GFP_KERNEL);
|
||||
if (!pvi)
|
||||
return -ENOMEM;
|
||||
pvi = devm_drm_bridge_alloc(&pdev->dev, struct imx8mp_hdmi_pvi,
|
||||
bridge, &imx_hdmi_pvi_bridge_funcs);
|
||||
if (IS_ERR(pvi))
|
||||
return PTR_ERR(pvi);
|
||||
|
||||
platform_set_drvdata(pdev, pvi);
|
||||
pvi->dev = &pdev->dev;
|
||||
@@ -166,7 +167,6 @@ static int imx8mp_hdmi_pvi_probe(struct platform_device *pdev)
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
/* Register the bridge. */
|
||||
pvi->bridge.funcs = &imx_hdmi_pvi_bridge_funcs;
|
||||
pvi->bridge.of_node = pdev->dev.of_node;
|
||||
pvi->bridge.timings = pvi->next_bridge->timings;
|
||||
|
||||
|
||||
@@ -63,12 +63,11 @@ struct imx8qxp_pc_channel {
|
||||
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 imx8qxp_pc_channel *ch[2];
|
||||
struct clk *clk_apb;
|
||||
void __iomem *base;
|
||||
};
|
||||
@@ -307,7 +306,14 @@ static int imx8qxp_pc_bridge_probe(struct platform_device *pdev)
|
||||
goto free_child;
|
||||
}
|
||||
|
||||
ch = &pc->ch[i];
|
||||
ch = devm_drm_bridge_alloc(dev, struct imx8qxp_pc_channel, bridge,
|
||||
&imx8qxp_pc_bridge_funcs);
|
||||
if (IS_ERR(ch)) {
|
||||
ret = PTR_ERR(ch);
|
||||
goto free_child;
|
||||
}
|
||||
|
||||
pc->ch[i] = ch;
|
||||
ch->pc = pc;
|
||||
ch->stream_id = i;
|
||||
|
||||
@@ -333,9 +339,7 @@ static int imx8qxp_pc_bridge_probe(struct platform_device *pdev)
|
||||
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);
|
||||
}
|
||||
@@ -345,8 +349,8 @@ static int imx8qxp_pc_bridge_probe(struct platform_device *pdev)
|
||||
free_child:
|
||||
of_node_put(child);
|
||||
|
||||
if (i == 1 && pc->ch[0].next_bridge)
|
||||
drm_bridge_remove(&pc->ch[0].bridge);
|
||||
if (i == 1 && pc->ch[0]->next_bridge)
|
||||
drm_bridge_remove(&pc->ch[0]->bridge);
|
||||
|
||||
pm_runtime_disable(dev);
|
||||
return ret;
|
||||
@@ -359,13 +363,10 @@ static void imx8qxp_pc_bridge_remove(struct platform_device *pdev)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
ch = &pc->ch[i];
|
||||
ch = pc->ch[i];
|
||||
|
||||
if (!ch->is_available)
|
||||
continue;
|
||||
|
||||
drm_bridge_remove(&ch->bridge);
|
||||
ch->is_available = false;
|
||||
if (ch)
|
||||
drm_bridge_remove(&ch->bridge);
|
||||
}
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
@@ -327,9 +327,10 @@ static int imx8qxp_pixel_link_bridge_probe(struct platform_device *pdev)
|
||||
struct device_node *np = dev->of_node;
|
||||
int ret;
|
||||
|
||||
pl = devm_kzalloc(dev, sizeof(*pl), GFP_KERNEL);
|
||||
if (!pl)
|
||||
return -ENOMEM;
|
||||
pl = devm_drm_bridge_alloc(dev, struct imx8qxp_pixel_link, bridge,
|
||||
&imx8qxp_pixel_link_bridge_funcs);
|
||||
if (IS_ERR(pl))
|
||||
return PTR_ERR(pl);
|
||||
|
||||
ret = imx_scu_get_handle(&pl->ipc_handle);
|
||||
if (ret) {
|
||||
@@ -384,7 +385,6 @@ static int imx8qxp_pixel_link_bridge_probe(struct platform_device *pdev)
|
||||
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);
|
||||
|
||||
@@ -392,9 +392,10 @@ static int imx8qxp_pxl2dpi_bridge_probe(struct platform_device *pdev)
|
||||
struct device_node *np = dev->of_node;
|
||||
int ret;
|
||||
|
||||
p2d = devm_kzalloc(dev, sizeof(*p2d), GFP_KERNEL);
|
||||
if (!p2d)
|
||||
return -ENOMEM;
|
||||
p2d = devm_drm_bridge_alloc(dev, struct imx8qxp_pxl2dpi, bridge,
|
||||
&imx8qxp_pxl2dpi_bridge_funcs);
|
||||
if (IS_ERR(p2d))
|
||||
return PTR_ERR(p2d);
|
||||
|
||||
p2d->regmap = syscon_node_to_regmap(np->parent);
|
||||
if (IS_ERR(p2d->regmap)) {
|
||||
@@ -441,7 +442,6 @@ static int imx8qxp_pxl2dpi_bridge_probe(struct platform_device *pdev)
|
||||
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);
|
||||
|
||||
@@ -816,9 +816,10 @@ static int it6263_probe(struct i2c_client *client)
|
||||
struct it6263 *it;
|
||||
int ret;
|
||||
|
||||
it = devm_kzalloc(dev, sizeof(*it), GFP_KERNEL);
|
||||
if (!it)
|
||||
return -ENOMEM;
|
||||
it = devm_drm_bridge_alloc(dev, struct it6263, bridge,
|
||||
&it6263_bridge_funcs);
|
||||
if (IS_ERR(it))
|
||||
return PTR_ERR(it);
|
||||
|
||||
it->dev = dev;
|
||||
it->hdmi_i2c = client;
|
||||
@@ -866,7 +867,6 @@ static int it6263_probe(struct i2c_client *client)
|
||||
|
||||
i2c_set_clientdata(client, it);
|
||||
|
||||
it->bridge.funcs = &it6263_bridge_funcs;
|
||||
it->bridge.of_node = dev->of_node;
|
||||
/* IT6263 chip doesn't support HPD interrupt. */
|
||||
it->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID |
|
||||
|
||||
@@ -3583,9 +3583,10 @@ static int it6505_i2c_probe(struct i2c_client *client)
|
||||
struct extcon_dev *extcon;
|
||||
int err;
|
||||
|
||||
it6505 = devm_kzalloc(&client->dev, sizeof(*it6505), GFP_KERNEL);
|
||||
if (!it6505)
|
||||
return -ENOMEM;
|
||||
it6505 = devm_drm_bridge_alloc(&client->dev, struct it6505, bridge,
|
||||
&it6505_bridge_funcs);
|
||||
if (IS_ERR(it6505))
|
||||
return PTR_ERR(it6505);
|
||||
|
||||
mutex_init(&it6505->extcon_lock);
|
||||
mutex_init(&it6505->mode_lock);
|
||||
@@ -3660,7 +3661,6 @@ static int it6505_i2c_probe(struct i2c_client *client)
|
||||
it6505->aux.transfer = it6505_aux_transfer;
|
||||
drm_dp_aux_init(&it6505->aux);
|
||||
|
||||
it6505->bridge.funcs = &it6505_bridge_funcs;
|
||||
it6505->bridge.type = DRM_MODE_CONNECTOR_DisplayPort;
|
||||
it6505->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID |
|
||||
DRM_BRIDGE_OP_HPD;
|
||||
|
||||
@@ -1516,9 +1516,10 @@ static int it66121_probe(struct i2c_client *client)
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
ctx = devm_drm_bridge_alloc(dev, struct it66121_ctx, bridge,
|
||||
&it66121_bridge_funcs);
|
||||
if (IS_ERR(ctx))
|
||||
return PTR_ERR(ctx);
|
||||
|
||||
ep = of_graph_get_endpoint_by_regs(dev->of_node, 0, 0);
|
||||
if (!ep)
|
||||
@@ -1577,7 +1578,6 @@ static int it66121_probe(struct i2c_client *client)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ctx->bridge.funcs = &it66121_bridge_funcs;
|
||||
ctx->bridge.of_node = dev->of_node;
|
||||
ctx->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
|
||||
ctx->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID;
|
||||
|
||||
@@ -761,9 +761,10 @@ static int lt8912_probe(struct i2c_client *client)
|
||||
int ret = 0;
|
||||
struct device *dev = &client->dev;
|
||||
|
||||
lt = devm_kzalloc(dev, sizeof(struct lt8912), GFP_KERNEL);
|
||||
if (!lt)
|
||||
return -ENOMEM;
|
||||
lt = devm_drm_bridge_alloc(dev, struct lt8912, bridge,
|
||||
<8912_bridge_funcs);
|
||||
if (IS_ERR(lt))
|
||||
return PTR_ERR(lt);
|
||||
|
||||
lt->dev = dev;
|
||||
lt->i2c_client[0] = client;
|
||||
@@ -778,7 +779,6 @@ static int lt8912_probe(struct i2c_client *client)
|
||||
|
||||
i2c_set_clientdata(client, lt);
|
||||
|
||||
lt->bridge.funcs = <8912_bridge_funcs;
|
||||
lt->bridge.of_node = dev->of_node;
|
||||
lt->bridge.ops = (DRM_BRIDGE_OP_EDID |
|
||||
DRM_BRIDGE_OP_DETECT);
|
||||
|
||||
@@ -727,9 +727,9 @@ static int lt9211_probe(struct i2c_client *client)
|
||||
struct lt9211 *ctx;
|
||||
int ret;
|
||||
|
||||
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
ctx = devm_drm_bridge_alloc(dev, struct lt9211, bridge, <9211_funcs);
|
||||
if (IS_ERR(ctx))
|
||||
return PTR_ERR(ctx);
|
||||
|
||||
ctx->dev = dev;
|
||||
|
||||
@@ -755,7 +755,6 @@ static int lt9211_probe(struct i2c_client *client)
|
||||
dev_set_drvdata(dev, ctx);
|
||||
i2c_set_clientdata(client, ctx);
|
||||
|
||||
ctx->bridge.funcs = <9211_funcs;
|
||||
ctx->bridge.of_node = dev->of_node;
|
||||
drm_bridge_add(&ctx->bridge);
|
||||
|
||||
|
||||
@@ -1072,9 +1072,10 @@ static int lt9611_probe(struct i2c_client *client)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
lt9611 = devm_kzalloc(dev, sizeof(*lt9611), GFP_KERNEL);
|
||||
if (!lt9611)
|
||||
return -ENOMEM;
|
||||
lt9611 = devm_drm_bridge_alloc(dev, struct lt9611, bridge,
|
||||
<9611_bridge_funcs);
|
||||
if (IS_ERR(lt9611))
|
||||
return PTR_ERR(lt9611);
|
||||
|
||||
lt9611->dev = dev;
|
||||
lt9611->client = client;
|
||||
@@ -1127,7 +1128,6 @@ static int lt9611_probe(struct i2c_client *client)
|
||||
/* Disable Audio InfoFrame, enabled by default */
|
||||
regmap_update_bits(lt9611->regmap, 0x843d, LT9611_INFOFRAME_AUDIO, 0);
|
||||
|
||||
lt9611->bridge.funcs = <9611_bridge_funcs;
|
||||
lt9611->bridge.of_node = client->dev.of_node;
|
||||
lt9611->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID |
|
||||
DRM_BRIDGE_OP_HPD | DRM_BRIDGE_OP_MODES |
|
||||
|
||||
@@ -118,9 +118,10 @@ static int lvds_codec_probe(struct platform_device *pdev)
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
lvds_codec = devm_kzalloc(dev, sizeof(*lvds_codec), GFP_KERNEL);
|
||||
if (!lvds_codec)
|
||||
return -ENOMEM;
|
||||
lvds_codec = devm_drm_bridge_alloc(dev, struct lvds_codec, bridge,
|
||||
&funcs);
|
||||
if (IS_ERR(lvds_codec))
|
||||
return PTR_ERR(lvds_codec);
|
||||
|
||||
lvds_codec->dev = &pdev->dev;
|
||||
lvds_codec->connector_type = (uintptr_t)of_device_get_match_data(dev);
|
||||
@@ -156,8 +157,6 @@ static int lvds_codec_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(lvds_codec->panel_bridge))
|
||||
return PTR_ERR(lvds_codec->panel_bridge);
|
||||
|
||||
lvds_codec->bridge.funcs = &funcs;
|
||||
|
||||
/*
|
||||
* Decoder input LVDS format is a property of the decoder chip or even
|
||||
* its strapping. Handle data-mapping the same way lvds-panel does. In
|
||||
|
||||
@@ -225,13 +225,11 @@ static int ge_b850v3_lvds_init(struct device *dev)
|
||||
if (ge_b850v3_lvds_ptr)
|
||||
goto success;
|
||||
|
||||
ge_b850v3_lvds_ptr = devm_kzalloc(dev,
|
||||
sizeof(*ge_b850v3_lvds_ptr),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!ge_b850v3_lvds_ptr) {
|
||||
ge_b850v3_lvds_ptr = devm_drm_bridge_alloc(dev, struct ge_b850v3_lvds, bridge,
|
||||
&ge_b850v3_lvds_funcs);
|
||||
if (IS_ERR(ge_b850v3_lvds_ptr)) {
|
||||
mutex_unlock(&ge_b850v3_lvds_dev_mutex);
|
||||
return -ENOMEM;
|
||||
return PTR_ERR(ge_b850v3_lvds_ptr);
|
||||
}
|
||||
|
||||
success:
|
||||
@@ -264,7 +262,6 @@ static int ge_b850v3_register(void)
|
||||
struct device *dev = &stdp4028_i2c->dev;
|
||||
|
||||
/* drm bridge initialization */
|
||||
ge_b850v3_lvds_ptr->bridge.funcs = &ge_b850v3_lvds_funcs;
|
||||
ge_b850v3_lvds_ptr->bridge.ops = DRM_BRIDGE_OP_DETECT |
|
||||
DRM_BRIDGE_OP_EDID;
|
||||
ge_b850v3_lvds_ptr->bridge.type = DRM_MODE_CONNECTOR_DisplayPort;
|
||||
|
||||
@@ -157,9 +157,10 @@ static int mchp_lvds_probe(struct platform_device *pdev)
|
||||
if (!dev->of_node)
|
||||
return -ENODEV;
|
||||
|
||||
lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL);
|
||||
if (!lvds)
|
||||
return -ENOMEM;
|
||||
lvds = devm_drm_bridge_alloc(&pdev->dev, struct mchp_lvds, bridge,
|
||||
&mchp_lvds_bridge_funcs);
|
||||
if (IS_ERR(lvds))
|
||||
return PTR_ERR(lvds);
|
||||
|
||||
lvds->dev = dev;
|
||||
|
||||
@@ -192,7 +193,6 @@ static int mchp_lvds_probe(struct platform_device *pdev)
|
||||
|
||||
lvds->bridge.of_node = dev->of_node;
|
||||
lvds->bridge.type = DRM_MODE_CONNECTOR_LVDS;
|
||||
lvds->bridge.funcs = &mchp_lvds_bridge_funcs;
|
||||
|
||||
dev_set_drvdata(dev, lvds);
|
||||
ret = devm_pm_runtime_enable(dev);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user