Xilinx ZynqMP DisplayPort Subsystem driver
-----BEGIN PGP SIGNATURE----- iQJWBAABCgBAFiEEvZRkio5H7O2/GZsYYiVdKZ4oCyQFAl8SPokiHGxhdXJlbnQu cGluY2hhcnRAaWRlYXNvbmJvYXJkLmNvbQAKCRBiJV0pnigLJEfMEACTOIz88BhU UHi/ZiLGrziEgQ/tr+TnGE98Usclm2C1PLOHR+vHQKvm4fhppqvDaAFdXCuDg1Qd korMYFMSBC3iD8TMHrU7CPX5H3tDixpnwE6DreifHnTXWvLSJA9bgYrqLuOD5fv9 dTyhfzQQhfLjNmqwTJDQAmZqW9lBsYwBXxvCwgACjnSZo3CMzNbUEADv7ZdptuzN k+CbR4mgn+plQljaOp1iRvQz30BdNxQMPyIqsFU/oDxjznls/RQ2YFtU40k72mso dUrpP/VdBTkYXAu7nsfGTlATgPoj8z7ZVSAGNGvltmasQw/t2Na62kmmC+AAGNmw KHPP2HUMqTnC1SjlHOZIMncSRr/64fdY8Gr26Z3Qtb/odNlJ2k6pWM4O7/7DBPlJ QBfOWWVBfhezj525KJkLU8MkBa0ztuENFqmDHe3d5SkBtCfIkw0LC6Orjn2HROqd rhsUw8DUKrWxVe8lar+twCueoK21GqvyIc9rAJxvR/Uph7dJUYCzAHeCNysMOjlf hpfCJ4pwksXzUjVSqEUazh3TWqkVwDQSEmg5KO4OM/Tpg3oHFKDE0O4VMsz2CZ4W 1tLlnNwHwXmPX3AS34Qe2LTnXqueIqEj6uqNsNfZNLhYKirDWNKnroigRdfoXvXI I6Eeo5caMBMmdjZwgt+US2y9lhX2YpxQyA== =eq5n -----END PGP SIGNATURE----- Merge tag 'drm-xilinx-dpsub-20200718' of git://linuxtv.org/pinchartl/media into drm-next Xilinx ZynqMP DisplayPort Subsystem driver Signed-off-by: Dave Airlie <airlied@redhat.com> From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200718001755.GA5962@pendragon.ideasonboard.com
This commit is contained in:
Коммит
959ed53808
|
@ -0,0 +1,174 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/xlnx/xlnx,zynqmp-dpsub.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Xilinx ZynqMP DisplayPort Subsystem
|
||||
|
||||
description: |
|
||||
The DisplayPort subsystem of Xilinx ZynqMP (Zynq UltraScale+ MPSoC)
|
||||
implements the display and audio pipelines based on the DisplayPort v1.2
|
||||
standard. The subsystem includes multiple functional blocks as below:
|
||||
|
||||
+------------------------------------------------------------+
|
||||
+--------+ | +----------------+ +-----------+ |
|
||||
| DPDMA | --->| | --> | Video | Video +-------------+ |
|
||||
| 4x vid | | | | | Rendering | -+--> | | | +------+
|
||||
| 2x aud | | | Audio/Video | --> | Pipeline | | | DisplayPort |---> | PHY0 |
|
||||
+--------+ | | Buffer Manager | +-----------+ | | Source | | +------+
|
||||
| | and STC | +-----------+ | | Controller | | +------+
|
||||
Live Video --->| | --> | Audio | Audio | |---> | PHY1 |
|
||||
| | | | Mixer | --+-> | | | +------+
|
||||
Live Audio --->| | --> | | || +-------------+ |
|
||||
| +----------------+ +-----------+ || |
|
||||
+---------------------------------------||-------------------+
|
||||
vv
|
||||
Blended Video and
|
||||
Mixed Audio to PL
|
||||
|
||||
The Buffer Manager interacts with external interface such as DMA engines or
|
||||
live audio/video streams from the programmable logic. The Video Rendering
|
||||
Pipeline blends the video and graphics layers and performs colorspace
|
||||
conversion. The Audio Mixer mixes the incoming audio streams. The DisplayPort
|
||||
Source Controller handles the DisplayPort protocol and connects to external
|
||||
PHYs.
|
||||
|
||||
The subsystem supports 2 video and 2 audio streams, and various pixel formats
|
||||
and depths up to 4K@30 resolution.
|
||||
|
||||
Please refer to "Zynq UltraScale+ Device Technical Reference Manual"
|
||||
(https://www.xilinx.com/support/documentation/user_guides/ug1085-zynq-ultrascale-trm.pdf)
|
||||
for more details.
|
||||
|
||||
maintainers:
|
||||
- Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: xlnx,zynqmp-dpsub-1.7
|
||||
|
||||
reg:
|
||||
maxItems: 4
|
||||
reg-names:
|
||||
items:
|
||||
- const: dp
|
||||
- const: blend
|
||||
- const: av_buf
|
||||
- const: aud
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
description:
|
||||
The APB clock and at least one video clock are mandatory, the audio clock
|
||||
is optional.
|
||||
minItems: 2
|
||||
maxItems: 4
|
||||
items:
|
||||
- description: dp_apb_clk is the APB clock
|
||||
- description: dp_aud_clk is the Audio clock
|
||||
- description:
|
||||
dp_vtc_pixel_clk_in is the non-live video clock (from Processing
|
||||
System)
|
||||
- description:
|
||||
dp_live_video_in_clk is the live video clock (from Programmable
|
||||
Logic)
|
||||
clock-names:
|
||||
oneOf:
|
||||
- minItems: 2
|
||||
maxItems: 3
|
||||
items:
|
||||
- const: dp_apb_clk
|
||||
- enum: [ dp_vtc_pixel_clk_in, dp_live_video_in_clk ]
|
||||
- enum: [ dp_vtc_pixel_clk_in, dp_live_video_in_clk ]
|
||||
- minItems: 3
|
||||
maxItems: 4
|
||||
items:
|
||||
- const: dp_apb_clk
|
||||
- const: dp_aud_clk
|
||||
- enum: [ dp_vtc_pixel_clk_in, dp_live_video_in_clk ]
|
||||
- enum: [ dp_vtc_pixel_clk_in, dp_live_video_in_clk ]
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
dmas:
|
||||
maxItems: 4
|
||||
items:
|
||||
- description: Video layer, plane 0 (RGB or luma)
|
||||
- description: Video layer, plane 1 (U/V or U)
|
||||
- description: Video layer, plane 2 (V)
|
||||
- description: Graphics layer
|
||||
dma-names:
|
||||
items:
|
||||
- const: vid0
|
||||
- const: vid1
|
||||
- const: vid2
|
||||
- const: gfx0
|
||||
|
||||
phys:
|
||||
description: PHYs for the DP data lanes
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
phy-names:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
items:
|
||||
- const: dp-phy0
|
||||
- const: dp-phy1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
- power-domains
|
||||
- resets
|
||||
- dmas
|
||||
- dma-names
|
||||
- phys
|
||||
- phy-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/phy/phy.h>
|
||||
#include <dt-bindings/reset/xlnx-zynqmp-resets.h>
|
||||
|
||||
display@fd4a0000 {
|
||||
compatible = "xlnx,zynqmp-dpsub-1.7";
|
||||
reg = <0x0 0xfd4a0000 0x0 0x1000>,
|
||||
<0x0 0xfd4aa000 0x0 0x1000>,
|
||||
<0x0 0xfd4ab000 0x0 0x1000>,
|
||||
<0x0 0xfd4ac000 0x0 0x1000>;
|
||||
reg-names = "dp", "blend", "av_buf", "aud";
|
||||
interrupts = <0 119 4>;
|
||||
interrupt-parent = <&gic>;
|
||||
|
||||
clock-names = "dp_apb_clk", "dp_aud_clk", "dp_live_video_in_clk";
|
||||
clocks = <&dp_aclk>, <&clkc 17>, <&si570_1>;
|
||||
|
||||
power-domains = <&pd_dp>;
|
||||
resets = <&reset ZYNQMP_RESET_DP>;
|
||||
|
||||
dma-names = "vid0", "vid1", "vid2", "gfx0";
|
||||
dmas = <&xlnx_dpdma 0>,
|
||||
<&xlnx_dpdma 1>,
|
||||
<&xlnx_dpdma 2>,
|
||||
<&xlnx_dpdma 3>;
|
||||
|
||||
phys = <&psgtr 1 PHY_TYPE_DP 0 3 27000000>,
|
||||
<&psgtr 0 PHY_TYPE_DP 1 3 27000000>;
|
||||
|
||||
phy-names = "dp-phy0", "dp-phy1";
|
||||
};
|
||||
|
||||
...
|
|
@ -0,0 +1,68 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/dma/xilinx/xlnx,zynqmp-dpdma.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Xilinx ZynqMP DisplayPort DMA Controller Device Tree Bindings
|
||||
|
||||
description: |
|
||||
These bindings describe the DMA engine included in the Xilinx ZynqMP
|
||||
DisplayPort Subsystem. The DMA engine supports up to 6 DMA channels (3
|
||||
channels for a video stream, 1 channel for a graphics stream, and 2 channels
|
||||
for an audio stream).
|
||||
|
||||
maintainers:
|
||||
- Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
|
||||
allOf:
|
||||
- $ref: "../dma-controller.yaml#"
|
||||
|
||||
properties:
|
||||
"#dma-cells":
|
||||
const: 1
|
||||
description: |
|
||||
The cell is the DMA channel ID (see dt-bindings/dma/xlnx-zynqmp-dpdma.h
|
||||
for a list of channel IDs).
|
||||
|
||||
compatible:
|
||||
const: xlnx,zynqmp-dpdma
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
description: The AXI clock
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
const: axi_clk
|
||||
|
||||
required:
|
||||
- "#dma-cells"
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
dma: dma-controller@fd4c0000 {
|
||||
compatible = "xlnx,zynqmp-dpdma";
|
||||
reg = <0x0 0xfd4c0000 0x0 0x1000>;
|
||||
interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-parent = <&gic>;
|
||||
clocks = <&dpdma_clk>;
|
||||
clock-names = "axi_clk";
|
||||
#dma-cells = <1>;
|
||||
};
|
||||
|
||||
...
|
|
@ -86,7 +86,9 @@ The details of these operations are:
|
|||
- interleaved_dma: This is common to Slave as well as M2M clients. For slave
|
||||
address of devices' fifo could be already known to the driver.
|
||||
Various types of operations could be expressed by setting
|
||||
appropriate values to the 'dma_interleaved_template' members.
|
||||
appropriate values to the 'dma_interleaved_template' members. Cyclic
|
||||
interleaved DMA transfers are also possible if supported by the channel by
|
||||
setting the DMA_PREP_REPEAT transfer flag.
|
||||
|
||||
A non-NULL return of this transfer API represents a "descriptor" for
|
||||
the given transaction.
|
||||
|
|
|
@ -239,6 +239,27 @@ Currently, the types available are:
|
|||
want to transfer a portion of uncompressed data directly to the
|
||||
display to print it
|
||||
|
||||
- DMA_REPEAT
|
||||
|
||||
- The device supports repeated transfers. A repeated transfer, indicated by
|
||||
the DMA_PREP_REPEAT transfer flag, is similar to a cyclic transfer in that
|
||||
it gets automatically repeated when it ends, but can additionally be
|
||||
replaced by the client.
|
||||
|
||||
- This feature is limited to interleaved transfers, this flag should thus not
|
||||
be set if the DMA_INTERLEAVE flag isn't set. This limitation is based on
|
||||
the current needs of DMA clients, support for additional transfer types
|
||||
should be added in the future if and when the need arises.
|
||||
|
||||
- DMA_LOAD_EOT
|
||||
|
||||
- The device supports replacing repeated transfers at end of transfer (EOT)
|
||||
by queuing a new transfer with the DMA_PREP_LOAD_EOT flag set.
|
||||
|
||||
- Support for replacing a currently running transfer at another point (such
|
||||
as end of burst instead of end of transfer) will be added in the future
|
||||
based on DMA clients needs, if and when the need arises.
|
||||
|
||||
These various types will also affect how the source and destination
|
||||
addresses change over time.
|
||||
|
||||
|
@ -531,6 +552,34 @@ DMA_CTRL_REUSE
|
|||
writes for which the descriptor should be in different format from
|
||||
normal data descriptors.
|
||||
|
||||
- DMA_PREP_REPEAT
|
||||
|
||||
- If set, the transfer will be automatically repeated when it ends until a
|
||||
new transfer is queued on the same channel with the DMA_PREP_LOAD_EOT flag.
|
||||
If the next transfer to be queued on the channel does not have the
|
||||
DMA_PREP_LOAD_EOT flag set, the current transfer will be repeated until the
|
||||
client terminates all transfers.
|
||||
|
||||
- This flag is only supported if the channel reports the DMA_REPEAT
|
||||
capability.
|
||||
|
||||
- DMA_PREP_LOAD_EOT
|
||||
|
||||
- If set, the transfer will replace the transfer currently being executed at
|
||||
the end of the transfer.
|
||||
|
||||
- This is the default behaviour for non-repeated transfers, specifying
|
||||
DMA_PREP_LOAD_EOT for non-repeated transfers will thus make no difference.
|
||||
|
||||
- When using repeated transfers, DMA clients will usually need to set the
|
||||
DMA_PREP_LOAD_EOT flag on all transfers, otherwise the channel will keep
|
||||
repeating the last repeated transfer and ignore the new transfers being
|
||||
queued. Failure to set DMA_PREP_LOAD_EOT will appear as if the channel was
|
||||
stuck on the previous transfer.
|
||||
|
||||
- This flag is only supported if the channel reports the DMA_LOAD_EOT
|
||||
capability.
|
||||
|
||||
General Design Notes
|
||||
====================
|
||||
|
||||
|
|
18
MAINTAINERS
18
MAINTAINERS
|
@ -5839,6 +5839,15 @@ T: git git://anongit.freedesktop.org/drm/drm-misc
|
|||
F: Documentation/gpu/xen-front.rst
|
||||
F: drivers/gpu/drm/xen/
|
||||
|
||||
DRM DRIVERS FOR XILINX
|
||||
M: Hyun Kwon <hyun.kwon@xilinx.com>
|
||||
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
F: Documentation/devicetree/bindings/display/xlnx/
|
||||
F: drivers/gpu/drm/xlnx/
|
||||
|
||||
DRM DRIVERS FOR ZTE ZX
|
||||
M: Shawn Guo <shawnguo@kernel.org>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
|
@ -18853,6 +18862,15 @@ F: Documentation/devicetree/bindings/media/xilinx/
|
|||
F: drivers/media/platform/xilinx/
|
||||
F: include/uapi/linux/xilinx-v4l2-controls.h
|
||||
|
||||
XILINX ZYNQMP DPDMA DRIVER
|
||||
M: Hyun Kwon <hyun.kwon@xilinx.com>
|
||||
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
L: dmaengine@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/dma/xilinx/xlnx,zynqmp-dpdma.yaml
|
||||
F: drivers/dma/xilinx/xilinx_dpdma.c
|
||||
F: include/dt-bindings/dma/xlnx-zynqmp-dpdma.h
|
||||
|
||||
XILLYBUS DRIVER
|
||||
M: Eli Billauer <eli.billauer@gmail.com>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
|
|
|
@ -707,6 +707,16 @@ config XILINX_ZYNQMP_DMA
|
|||
help
|
||||
Enable support for Xilinx ZynqMP DMA controller.
|
||||
|
||||
config XILINX_ZYNQMP_DPDMA
|
||||
tristate "Xilinx DPDMA Engine"
|
||||
select DMA_ENGINE
|
||||
select DMA_VIRTUAL_CHANNELS
|
||||
help
|
||||
Enable support for Xilinx ZynqMP DisplayPort DMA. Choose this option
|
||||
if you have a Xilinx ZynqMP SoC with a DisplayPort subsystem. The
|
||||
driver provides the dmaengine required by the DisplayPort subsystem
|
||||
display driver.
|
||||
|
||||
config ZX_DMA
|
||||
tristate "ZTE ZX DMA support"
|
||||
depends on ARCH_ZX || COMPILE_TEST
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
obj-$(CONFIG_XILINX_DMA) += xilinx_dma.o
|
||||
obj-$(CONFIG_XILINX_ZYNQMP_DMA) += zynqmp_dma.o
|
||||
obj-$(CONFIG_XILINX_ZYNQMP_DPDMA) += xilinx_dpdma.o
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -386,6 +386,8 @@ source "drivers/gpu/drm/mcde/Kconfig"
|
|||
|
||||
source "drivers/gpu/drm/tidss/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/xlnx/Kconfig"
|
||||
|
||||
# Keep legacy drivers last
|
||||
|
||||
menuconfig DRM_LEGACY
|
||||
|
|
|
@ -123,3 +123,4 @@ obj-$(CONFIG_DRM_PANFROST) += panfrost/
|
|||
obj-$(CONFIG_DRM_ASPEED_GFX) += aspeed/
|
||||
obj-$(CONFIG_DRM_MCDE) += mcde/
|
||||
obj-$(CONFIG_DRM_TIDSS) += tidss/
|
||||
obj-y += xlnx/
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
config DRM_ZYNQMP_DPSUB
|
||||
tristate "ZynqMP DisplayPort Controller Driver"
|
||||
depends on ARCH_ZYNQMP || COMPILE_TEST
|
||||
depends on COMMON_CLK && DRM && OF
|
||||
select DMA_ENGINE
|
||||
select DRM_GEM_CMA_HELPER
|
||||
select DRM_KMS_CMA_HELPER
|
||||
select DRM_KMS_HELPER
|
||||
select GENERIC_PHY
|
||||
help
|
||||
This is a DRM/KMS driver for ZynqMP DisplayPort controller. Choose
|
||||
this option if you have a Xilinx ZynqMP SoC with DisplayPort
|
||||
subsystem.
|
|
@ -0,0 +1,2 @@
|
|||
zynqmp-dpsub-y := zynqmp_disp.o zynqmp_dpsub.o zynqmp_dp.o
|
||||
obj-$(CONFIG_DRM_ZYNQMP_DPSUB) += zynqmp-dpsub.o
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,42 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* ZynqMP Display Driver
|
||||
*
|
||||
* Copyright (C) 2017 - 2020 Xilinx, Inc.
|
||||
*
|
||||
* Authors:
|
||||
* - Hyun Woo Kwon <hyun.kwon@xilinx.com>
|
||||
* - Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
*/
|
||||
|
||||
#ifndef _ZYNQMP_DISP_H_
|
||||
#define _ZYNQMP_DISP_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/*
|
||||
* 3840x2160 is advertised as the maximum resolution, but almost any
|
||||
* resolutions under a 300Mhz pixel rate would work. Pick 4096x4096.
|
||||
*/
|
||||
#define ZYNQMP_DISP_MAX_WIDTH 4096
|
||||
#define ZYNQMP_DISP_MAX_HEIGHT 4096
|
||||
|
||||
/* The DPDMA is limited to 44 bit addressing. */
|
||||
#define ZYNQMP_DISP_MAX_DMA_BIT 44
|
||||
|
||||
struct device;
|
||||
struct drm_device;
|
||||
struct platform_device;
|
||||
struct zynqmp_disp;
|
||||
struct zynqmp_dpsub;
|
||||
|
||||
void zynqmp_disp_handle_vblank(struct zynqmp_disp *disp);
|
||||
bool zynqmp_disp_audio_enabled(struct zynqmp_disp *disp);
|
||||
unsigned int zynqmp_disp_get_audio_clk_rate(struct zynqmp_disp *disp);
|
||||
uint32_t zynqmp_disp_get_crtc_mask(struct zynqmp_disp *disp);
|
||||
|
||||
int zynqmp_disp_drm_init(struct zynqmp_dpsub *dpsub);
|
||||
int zynqmp_disp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm);
|
||||
void zynqmp_disp_remove(struct zynqmp_dpsub *dpsub);
|
||||
|
||||
#endif /* _ZYNQMP_DISP_H_ */
|
|
@ -0,0 +1,201 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* ZynqMP Display Controller Driver - Register Definitions
|
||||
*
|
||||
* Copyright (C) 2017 - 2020 Xilinx, Inc.
|
||||
*
|
||||
* Authors:
|
||||
* - Hyun Woo Kwon <hyun.kwon@xilinx.com>
|
||||
* - Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
*/
|
||||
|
||||
#ifndef _ZYNQMP_DISP_REGS_H_
|
||||
#define _ZYNQMP_DISP_REGS_H_
|
||||
|
||||
#include <linux/bits.h>
|
||||
|
||||
/* Blender registers */
|
||||
#define ZYNQMP_DISP_V_BLEND_BG_CLR_0 0x0
|
||||
#define ZYNQMP_DISP_V_BLEND_BG_CLR_1 0x4
|
||||
#define ZYNQMP_DISP_V_BLEND_BG_CLR_2 0x8
|
||||
#define ZYNQMP_DISP_V_BLEND_BG_MAX 0xfff
|
||||
#define ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA 0xc
|
||||
#define ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_VALUE(n) ((n) << 1)
|
||||
#define ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_EN BIT(0)
|
||||
#define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT 0x14
|
||||
#define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_RGB 0x0
|
||||
#define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YCBCR444 0x1
|
||||
#define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YCBCR422 0x2
|
||||
#define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YONLY 0x3
|
||||
#define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_XVYCC 0x4
|
||||
#define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_EN_DOWNSAMPLE BIT(4)
|
||||
#define ZYNQMP_DISP_V_BLEND_LAYER_CONTROL(n) (0x18 + ((n) * 4))
|
||||
#define ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_EN_US BIT(0)
|
||||
#define ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_RGB BIT(1)
|
||||
#define ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_BYPASS BIT(8)
|
||||
#define ZYNQMP_DISP_V_BLEND_NUM_COEFF 9
|
||||
#define ZYNQMP_DISP_V_BLEND_NUM_OFFSET 3
|
||||
#define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF(n) (0x20 + ((n) * 4))
|
||||
#define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF(n) (0x44 + ((n) * 4))
|
||||
#define ZYNQMP_DISP_V_BLEND_IN1CSC_OFFSET(n) (0x68 + ((n) * 4))
|
||||
#define ZYNQMP_DISP_V_BLEND_OUTCSC_OFFSET(n) (0x74 + ((n) * 4))
|
||||
#define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF(n) (0x80 + ((n) * 4))
|
||||
#define ZYNQMP_DISP_V_BLEND_IN2CSC_OFFSET(n) (0xa4 + ((n) * 4))
|
||||
#define ZYNQMP_DISP_V_BLEND_CHROMA_KEY_ENABLE 0x1d0
|
||||
#define ZYNQMP_DISP_V_BLEND_CHROMA_KEY_COMP1 0x1d4
|
||||
#define ZYNQMP_DISP_V_BLEND_CHROMA_KEY_COMP2 0x1d8
|
||||
#define ZYNQMP_DISP_V_BLEND_CHROMA_KEY_COMP3 0x1dc
|
||||
|
||||
/* AV buffer manager registers */
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT 0x0
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_SHIFT 0
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MASK (0x1f << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_UYVY (0 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_VYUY (1 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YVYU (2 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YUYV (3 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16 (4 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV24 (5 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI (6 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MONO (7 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI2 (8 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YUV444 (9 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888 (10 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGBA8880 (11 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888_10 (12 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YUV444_10 (13 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI2_10 (14 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_10 (15 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16_10 (16 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV24_10 (17 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YONLY_10 (18 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16_420 (19 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_420 (20 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI2_420 (21 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16_420_10 (22 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_420_10 (23 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI2_420_10 (24 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_SHIFT 8
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_MASK (0xf << 8)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA8888 (0 << 8)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_ABGR8888 (1 << 8)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGB888 (2 << 8)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_BGR888 (3 << 8)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA5551 (4 << 8)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA4444 (5 << 8)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGB565 (6 << 8)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_8BPP (7 << 8)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_4BPP (8 << 8)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_2BPP (9 << 8)
|
||||
#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_1BPP (10 << 8)
|
||||
#define ZYNQMP_DISP_AV_BUF_NON_LIVE_LATENCY 0x8
|
||||
#define ZYNQMP_DISP_AV_BUF_CHBUF(n) (0x10 + ((n) * 4))
|
||||
#define ZYNQMP_DISP_AV_BUF_CHBUF_EN BIT(0)
|
||||
#define ZYNQMP_DISP_AV_BUF_CHBUF_FLUSH BIT(1)
|
||||
#define ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_SHIFT 2
|
||||
#define ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_MASK (0xf << 2)
|
||||
#define ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_MAX 0xf
|
||||
#define ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_AUD_MAX 0x3
|
||||
#define ZYNQMP_DISP_AV_BUF_STATUS 0x28
|
||||
#define ZYNQMP_DISP_AV_BUF_STC_CTRL 0x2c
|
||||
#define ZYNQMP_DISP_AV_BUF_STC_CTRL_EN BIT(0)
|
||||
#define ZYNQMP_DISP_AV_BUF_STC_CTRL_EVENT_SHIFT 1
|
||||
#define ZYNQMP_DISP_AV_BUF_STC_CTRL_EVENT_EX_VSYNC 0
|
||||
#define ZYNQMP_DISP_AV_BUF_STC_CTRL_EVENT_EX_VID 1
|
||||
#define ZYNQMP_DISP_AV_BUF_STC_CTRL_EVENT_EX_AUD 2
|
||||
#define ZYNQMP_DISP_AV_BUF_STC_CTRL_EVENT_INT_VSYNC 3
|
||||
#define ZYNQMP_DISP_AV_BUF_STC_INIT_VALUE0 0x30
|
||||
#define ZYNQMP_DISP_AV_BUF_STC_INIT_VALUE1 0x34
|
||||
#define ZYNQMP_DISP_AV_BUF_STC_ADJ 0x38
|
||||
#define ZYNQMP_DISP_AV_BUF_STC_VID_VSYNC_TS0 0x3c
|
||||
#define ZYNQMP_DISP_AV_BUF_STC_VID_VSYNC_TS1 0x40
|
||||
#define ZYNQMP_DISP_AV_BUF_STC_EXT_VSYNC_TS0 0x44
|
||||
#define ZYNQMP_DISP_AV_BUF_STC_EXT_VSYNC_TS1 0x48
|
||||
#define ZYNQMP_DISP_AV_BUF_STC_CUSTOM_EVENT_TS0 0x4c
|
||||
#define ZYNQMP_DISP_AV_BUF_STC_CUSTOM_EVENT_TS1 0x50
|
||||
#define ZYNQMP_DISP_AV_BUF_STC_CUSTOM_EVENT2_TS0 0x54
|
||||
#define ZYNQMP_DISP_AV_BUF_STC_CUSTOM_EVENT2_TS1 0x58
|
||||
#define ZYNQMP_DISP_AV_BUF_STC_SNAPSHOT0 0x60
|
||||
#define ZYNQMP_DISP_AV_BUF_STC_SNAPSHOT1 0x64
|
||||
#define ZYNQMP_DISP_AV_BUF_OUTPUT 0x70
|
||||
#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_SHIFT 0
|
||||
#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK (0x3 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_LIVE (0 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MEM (1 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_PATTERN (2 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_NONE (3 << 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_SHIFT 2
|
||||
#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MASK (0x3 << 2)
|
||||
#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_DISABLE (0 << 2)
|
||||
#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MEM (1 << 2)
|
||||
#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_LIVE (2 << 2)
|
||||
#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_NONE (3 << 2)
|
||||
#define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_SHIFT 4
|
||||
#define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MASK (0x3 << 4)
|
||||
#define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_PL (0 << 4)
|
||||
#define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MEM (1 << 4)
|
||||
#define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_PATTERN (2 << 4)
|
||||
#define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_DISABLE (3 << 4)
|
||||
#define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD2_EN BIT(6)
|
||||
#define ZYNQMP_DISP_AV_BUF_HCOUNT_VCOUNT_INT0 0x74
|
||||
#define ZYNQMP_DISP_AV_BUF_HCOUNT_VCOUNT_INT1 0x78
|
||||
#define ZYNQMP_DISP_AV_BUF_PATTERN_GEN_SELECT 0x100
|
||||
#define ZYNQMP_DISP_AV_BUF_CLK_SRC 0x120
|
||||
#define ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_FROM_PS BIT(0)
|
||||
#define ZYNQMP_DISP_AV_BUF_CLK_SRC_AUD_FROM_PS BIT(1)
|
||||
#define ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING BIT(2)
|
||||
#define ZYNQMP_DISP_AV_BUF_SRST_REG 0x124
|
||||
#define ZYNQMP_DISP_AV_BUF_SRST_REG_VID_RST BIT(1)
|
||||
#define ZYNQMP_DISP_AV_BUF_AUDIO_CH_CONFIG 0x12c
|
||||
#define ZYNQMP_DISP_AV_BUF_GFX_COMP_SF(n) (0x200 + ((n) * 4))
|
||||
#define ZYNQMP_DISP_AV_BUF_VID_COMP_SF(n) (0x20c + ((n) * 4))
|
||||
#define ZYNQMP_DISP_AV_BUF_LIVD_VID_COMP_SF(n) (0x218 + ((n) * 4))
|
||||
#define ZYNQMP_DISP_AV_BUF_LIVE_VID_CONFIG 0x224
|
||||
#define ZYNQMP_DISP_AV_BUF_LIVD_GFX_COMP_SF(n) (0x228 + ((n) * 4))
|
||||
#define ZYNQMP_DISP_AV_BUF_LIVE_GFX_CONFIG 0x234
|
||||
#define ZYNQMP_DISP_AV_BUF_4BIT_SF 0x11111
|
||||
#define ZYNQMP_DISP_AV_BUF_5BIT_SF 0x10842
|
||||
#define ZYNQMP_DISP_AV_BUF_6BIT_SF 0x10410
|
||||
#define ZYNQMP_DISP_AV_BUF_8BIT_SF 0x10101
|
||||
#define ZYNQMP_DISP_AV_BUF_10BIT_SF 0x10040
|
||||
#define ZYNQMP_DISP_AV_BUF_NULL_SF 0
|
||||
#define ZYNQMP_DISP_AV_BUF_NUM_SF 3
|
||||
#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_6 0x0
|
||||
#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8 0x1
|
||||
#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_10 0x2
|
||||
#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_12 0x3
|
||||
#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_MASK GENMASK(2, 0)
|
||||
#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_RGB 0x0
|
||||
#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV444 0x1
|
||||
#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422 0x2
|
||||
#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YONLY 0x3
|
||||
#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_MASK GENMASK(5, 4)
|
||||
#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_CB_FIRST BIT(8)
|
||||
#define ZYNQMP_DISP_AV_BUF_PALETTE_MEMORY 0x400
|
||||
|
||||
/* Audio registers */
|
||||
#define ZYNQMP_DISP_AUD_MIXER_VOLUME 0x0
|
||||
#define ZYNQMP_DISP_AUD_MIXER_VOLUME_NO_SCALE 0x20002000
|
||||
#define ZYNQMP_DISP_AUD_MIXER_META_DATA 0x4
|
||||
#define ZYNQMP_DISP_AUD_CH_STATUS0 0x8
|
||||
#define ZYNQMP_DISP_AUD_CH_STATUS1 0xc
|
||||
#define ZYNQMP_DISP_AUD_CH_STATUS2 0x10
|
||||
#define ZYNQMP_DISP_AUD_CH_STATUS3 0x14
|
||||
#define ZYNQMP_DISP_AUD_CH_STATUS4 0x18
|
||||
#define ZYNQMP_DISP_AUD_CH_STATUS5 0x1c
|
||||
#define ZYNQMP_DISP_AUD_CH_A_DATA0 0x20
|
||||
#define ZYNQMP_DISP_AUD_CH_A_DATA1 0x24
|
||||
#define ZYNQMP_DISP_AUD_CH_A_DATA2 0x28
|
||||
#define ZYNQMP_DISP_AUD_CH_A_DATA3 0x2c
|
||||
#define ZYNQMP_DISP_AUD_CH_A_DATA4 0x30
|
||||
#define ZYNQMP_DISP_AUD_CH_A_DATA5 0x34
|
||||
#define ZYNQMP_DISP_AUD_CH_B_DATA0 0x38
|
||||
#define ZYNQMP_DISP_AUD_CH_B_DATA1 0x3c
|
||||
#define ZYNQMP_DISP_AUD_CH_B_DATA2 0x40
|
||||
#define ZYNQMP_DISP_AUD_CH_B_DATA3 0x44
|
||||
#define ZYNQMP_DISP_AUD_CH_B_DATA4 0x48
|
||||
#define ZYNQMP_DISP_AUD_CH_B_DATA5 0x4c
|
||||
#define ZYNQMP_DISP_AUD_SOFT_RESET 0xc00
|
||||
#define ZYNQMP_DISP_AUD_SOFT_RESET_AUD_SRST BIT(0)
|
||||
|
||||
#endif /* _ZYNQMP_DISP_REGS_H_ */
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,27 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* ZynqMP DisplayPort Driver
|
||||
*
|
||||
* Copyright (C) 2017 - 2020 Xilinx, Inc.
|
||||
*
|
||||
* Authors:
|
||||
* - Hyun Woo Kwon <hyun.kwon@xilinx.com>
|
||||
* - Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
*/
|
||||
|
||||
#ifndef _ZYNQMP_DP_H_
|
||||
#define _ZYNQMP_DP_H_
|
||||
|
||||
struct drm_device;
|
||||
struct platform_device;
|
||||
struct zynqmp_dp;
|
||||
struct zynqmp_dpsub;
|
||||
|
||||
void zynqmp_dp_enable_vblank(struct zynqmp_dp *dp);
|
||||
void zynqmp_dp_disable_vblank(struct zynqmp_dp *dp);
|
||||
|
||||
int zynqmp_dp_drm_init(struct zynqmp_dpsub *dpsub);
|
||||
int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm);
|
||||
void zynqmp_dp_remove(struct zynqmp_dpsub *dpsub);
|
||||
|
||||
#endif /* _ZYNQMP_DP_H_ */
|
|
@ -0,0 +1,322 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* ZynqMP DisplayPort Subsystem Driver
|
||||
*
|
||||
* Copyright (C) 2017 - 2020 Xilinx, Inc.
|
||||
*
|
||||
* Authors:
|
||||
* - Hyun Woo Kwon <hyun.kwon@xilinx.com>
|
||||
* - Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_reserved_mem.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_managed.h>
|
||||
#include <drm/drm_mode_config.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
|
||||
#include "zynqmp_disp.h"
|
||||
#include "zynqmp_dp.h"
|
||||
#include "zynqmp_dpsub.h"
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Dumb Buffer & Framebuffer Allocation
|
||||
*/
|
||||
|
||||
static int zynqmp_dpsub_dumb_create(struct drm_file *file_priv,
|
||||
struct drm_device *drm,
|
||||
struct drm_mode_create_dumb *args)
|
||||
{
|
||||
struct zynqmp_dpsub *dpsub = to_zynqmp_dpsub(drm);
|
||||
unsigned int pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
|
||||
|
||||
/* Enforce the alignment constraints of the DMA engine. */
|
||||
args->pitch = ALIGN(pitch, dpsub->dma_align);
|
||||
|
||||
return drm_gem_cma_dumb_create_internal(file_priv, drm, args);
|
||||
}
|
||||
|
||||
static struct drm_framebuffer *
|
||||
zynqmp_dpsub_fb_create(struct drm_device *drm, struct drm_file *file_priv,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
{
|
||||
struct zynqmp_dpsub *dpsub = to_zynqmp_dpsub(drm);
|
||||
struct drm_mode_fb_cmd2 cmd = *mode_cmd;
|
||||
unsigned int i;
|
||||
|
||||
/* Enforce the alignment constraints of the DMA engine. */
|
||||
for (i = 0; i < ARRAY_SIZE(cmd.pitches); ++i)
|
||||
cmd.pitches[i] = ALIGN(cmd.pitches[i], dpsub->dma_align);
|
||||
|
||||
return drm_gem_fb_create(drm, file_priv, &cmd);
|
||||
}
|
||||
|
||||
static const struct drm_mode_config_funcs zynqmp_dpsub_mode_config_funcs = {
|
||||
.fb_create = zynqmp_dpsub_fb_create,
|
||||
.atomic_check = drm_atomic_helper_check,
|
||||
.atomic_commit = drm_atomic_helper_commit,
|
||||
};
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* DRM/KMS Driver
|
||||
*/
|
||||
|
||||
DEFINE_DRM_GEM_CMA_FOPS(zynqmp_dpsub_drm_fops);
|
||||
|
||||
static struct drm_driver zynqmp_dpsub_drm_driver = {
|
||||
.driver_features = DRIVER_MODESET | DRIVER_GEM |
|
||||
DRIVER_ATOMIC,
|
||||
|
||||
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
|
||||
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
|
||||
.gem_prime_export = drm_gem_prime_export,
|
||||
.gem_prime_import = drm_gem_prime_import,
|
||||
.gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
|
||||
.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
|
||||
.gem_prime_vmap = drm_gem_cma_prime_vmap,
|
||||
.gem_prime_vunmap = drm_gem_cma_prime_vunmap,
|
||||
.gem_prime_mmap = drm_gem_cma_prime_mmap,
|
||||
.gem_free_object_unlocked = drm_gem_cma_free_object,
|
||||
.gem_vm_ops = &drm_gem_cma_vm_ops,
|
||||
.dumb_create = zynqmp_dpsub_dumb_create,
|
||||
.dumb_destroy = drm_gem_dumb_destroy,
|
||||
|
||||
.fops = &zynqmp_dpsub_drm_fops,
|
||||
|
||||
.name = "zynqmp-dpsub",
|
||||
.desc = "Xilinx DisplayPort Subsystem Driver",
|
||||
.date = "20130509",
|
||||
.major = 1,
|
||||
.minor = 0,
|
||||
};
|
||||
|
||||
static int zynqmp_dpsub_drm_init(struct zynqmp_dpsub *dpsub)
|
||||
{
|
||||
struct drm_device *drm = &dpsub->drm;
|
||||
int ret;
|
||||
|
||||
/* Initialize mode config, vblank and the KMS poll helper. */
|
||||
ret = drmm_mode_config_init(drm);
|
||||
if (ret < 0)
|
||||
goto err_dev_put;
|
||||
|
||||
drm->mode_config.funcs = &zynqmp_dpsub_mode_config_funcs;
|
||||
drm->mode_config.min_width = 0;
|
||||
drm->mode_config.min_height = 0;
|
||||
drm->mode_config.max_width = ZYNQMP_DISP_MAX_WIDTH;
|
||||
drm->mode_config.max_height = ZYNQMP_DISP_MAX_HEIGHT;
|
||||
|
||||
ret = drm_vblank_init(drm, 1);
|
||||
if (ret)
|
||||
goto err_dev_put;
|
||||
|
||||
drm->irq_enabled = 1;
|
||||
|
||||
drm_kms_helper_poll_init(drm);
|
||||
|
||||
/*
|
||||
* Initialize the DISP and DP components. This will creates planes,
|
||||
* CRTC, encoder and connector. The DISP should be initialized first as
|
||||
* the DP encoder needs the CRTC.
|
||||
*/
|
||||
ret = zynqmp_disp_drm_init(dpsub);
|
||||
if (ret)
|
||||
goto err_poll_fini;
|
||||
|
||||
ret = zynqmp_dp_drm_init(dpsub);
|
||||
if (ret)
|
||||
goto err_poll_fini;
|
||||
|
||||
/* Reset all components and register the DRM device. */
|
||||
drm_mode_config_reset(drm);
|
||||
|
||||
ret = drm_dev_register(drm, 0);
|
||||
if (ret < 0)
|
||||
goto err_poll_fini;
|
||||
|
||||
/* Initialize fbdev generic emulation. */
|
||||
drm_fbdev_generic_setup(drm, 24);
|
||||
|
||||
return 0;
|
||||
|
||||
err_poll_fini:
|
||||
drm_kms_helper_poll_fini(drm);
|
||||
err_dev_put:
|
||||
drm_dev_put(drm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Power Management
|
||||
*/
|
||||
|
||||
static int __maybe_unused zynqmp_dpsub_suspend(struct device *dev)
|
||||
{
|
||||
struct zynqmp_dpsub *dpsub = dev_get_drvdata(dev);
|
||||
|
||||
return drm_mode_config_helper_suspend(&dpsub->drm);
|
||||
}
|
||||
|
||||
static int __maybe_unused zynqmp_dpsub_resume(struct device *dev)
|
||||
{
|
||||
struct zynqmp_dpsub *dpsub = dev_get_drvdata(dev);
|
||||
|
||||
return drm_mode_config_helper_resume(&dpsub->drm);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops zynqmp_dpsub_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(zynqmp_dpsub_suspend, zynqmp_dpsub_resume)
|
||||
};
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Probe & Remove
|
||||
*/
|
||||
|
||||
static int zynqmp_dpsub_init_clocks(struct zynqmp_dpsub *dpsub)
|
||||
{
|
||||
int ret;
|
||||
|
||||
dpsub->apb_clk = devm_clk_get(dpsub->dev, "dp_apb_clk");
|
||||
if (IS_ERR(dpsub->apb_clk))
|
||||
return PTR_ERR(dpsub->apb_clk);
|
||||
|
||||
ret = clk_prepare_enable(dpsub->apb_clk);
|
||||
if (ret) {
|
||||
dev_err(dpsub->dev, "failed to enable the APB clock\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zynqmp_dpsub_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct zynqmp_dpsub *dpsub;
|
||||
int ret;
|
||||
|
||||
/* Allocate private data. */
|
||||
dpsub = kzalloc(sizeof(*dpsub), GFP_KERNEL);
|
||||
if (!dpsub)
|
||||
return -ENOMEM;
|
||||
|
||||
dpsub->dev = &pdev->dev;
|
||||
platform_set_drvdata(pdev, dpsub);
|
||||
|
||||
dma_set_mask(dpsub->dev, DMA_BIT_MASK(ZYNQMP_DISP_MAX_DMA_BIT));
|
||||
|
||||
/*
|
||||
* Initialize the DRM device early, as the DRM core mandates usage of
|
||||
* the managed memory helpers tied to the DRM device.
|
||||
*/
|
||||
ret = drm_dev_init(&dpsub->drm, &zynqmp_dpsub_drm_driver, &pdev->dev);
|
||||
if (ret < 0) {
|
||||
kfree(dpsub);
|
||||
return ret;
|
||||
}
|
||||
|
||||
drmm_add_final_kfree(&dpsub->drm, dpsub);
|
||||
|
||||
/* Try the reserved memory. Proceed if there's none. */
|
||||
of_reserved_mem_device_init(&pdev->dev);
|
||||
|
||||
ret = zynqmp_dpsub_init_clocks(dpsub);
|
||||
if (ret < 0)
|
||||
goto err_mem;
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
/*
|
||||
* DP should be probed first so that the zynqmp_disp can set the output
|
||||
* format accordingly.
|
||||
*/
|
||||
ret = zynqmp_dp_probe(dpsub, &dpsub->drm);
|
||||
if (ret)
|
||||
goto err_pm;
|
||||
|
||||
ret = zynqmp_disp_probe(dpsub, &dpsub->drm);
|
||||
if (ret)
|
||||
goto err_dp;
|
||||
|
||||
ret = zynqmp_dpsub_drm_init(dpsub);
|
||||
if (ret)
|
||||
goto err_disp;
|
||||
|
||||
dev_info(&pdev->dev, "ZynqMP DisplayPort Subsystem driver probed");
|
||||
|
||||
return 0;
|
||||
|
||||
err_disp:
|
||||
zynqmp_disp_remove(dpsub);
|
||||
err_dp:
|
||||
zynqmp_dp_remove(dpsub);
|
||||
err_pm:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
clk_disable_unprepare(dpsub->apb_clk);
|
||||
err_mem:
|
||||
of_reserved_mem_device_release(&pdev->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int zynqmp_dpsub_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct zynqmp_dpsub *dpsub = platform_get_drvdata(pdev);
|
||||
struct drm_device *drm = &dpsub->drm;
|
||||
|
||||
drm_dev_unregister(drm);
|
||||
drm_atomic_helper_shutdown(drm);
|
||||
drm_kms_helper_poll_fini(drm);
|
||||
|
||||
zynqmp_disp_remove(dpsub);
|
||||
zynqmp_dp_remove(dpsub);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
clk_disable_unprepare(dpsub->apb_clk);
|
||||
of_reserved_mem_device_release(&pdev->dev);
|
||||
|
||||
drm_dev_put(drm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void zynqmp_dpsub_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct zynqmp_dpsub *dpsub = platform_get_drvdata(pdev);
|
||||
|
||||
drm_atomic_helper_shutdown(&dpsub->drm);
|
||||
}
|
||||
|
||||
static const struct of_device_id zynqmp_dpsub_of_match[] = {
|
||||
{ .compatible = "xlnx,zynqmp-dpsub-1.7", },
|
||||
{ /* end of table */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, zynqmp_dpsub_of_match);
|
||||
|
||||
static struct platform_driver zynqmp_dpsub_driver = {
|
||||
.probe = zynqmp_dpsub_probe,
|
||||
.remove = zynqmp_dpsub_remove,
|
||||
.shutdown = zynqmp_dpsub_shutdown,
|
||||
.driver = {
|
||||
.name = "zynqmp-dpsub",
|
||||
.pm = &zynqmp_dpsub_pm_ops,
|
||||
.of_match_table = zynqmp_dpsub_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(zynqmp_dpsub_driver);
|
||||
|
||||
MODULE_AUTHOR("Xilinx, Inc.");
|
||||
MODULE_DESCRIPTION("ZynqMP DP Subsystem Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -0,0 +1,54 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* ZynqMP DPSUB Subsystem Driver
|
||||
*
|
||||
* Copyright (C) 2017 - 2020 Xilinx, Inc.
|
||||
*
|
||||
* Authors:
|
||||
* - Hyun Woo Kwon <hyun.kwon@xilinx.com>
|
||||
* - Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
*/
|
||||
|
||||
#ifndef _ZYNQMP_DPSUB_H_
|
||||
#define _ZYNQMP_DPSUB_H_
|
||||
|
||||
struct clk;
|
||||
struct device;
|
||||
struct drm_device;
|
||||
struct zynqmp_disp;
|
||||
struct zynqmp_dp;
|
||||
|
||||
enum zynqmp_dpsub_format {
|
||||
ZYNQMP_DPSUB_FORMAT_RGB,
|
||||
ZYNQMP_DPSUB_FORMAT_YCRCB444,
|
||||
ZYNQMP_DPSUB_FORMAT_YCRCB422,
|
||||
ZYNQMP_DPSUB_FORMAT_YONLY,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct zynqmp_dpsub - ZynqMP DisplayPort Subsystem
|
||||
* @drm: The DRM/KMS device
|
||||
* @dev: The physical device
|
||||
* @apb_clk: The APB clock
|
||||
* @disp: The display controller
|
||||
* @dp: The DisplayPort controller
|
||||
* @dma_align: DMA alignment constraint (must be a power of 2)
|
||||
*/
|
||||
struct zynqmp_dpsub {
|
||||
struct drm_device drm;
|
||||
struct device *dev;
|
||||
|
||||
struct clk *apb_clk;
|
||||
|
||||
struct zynqmp_disp *disp;
|
||||
struct zynqmp_dp *dp;
|
||||
|
||||
unsigned int dma_align;
|
||||
};
|
||||
|
||||
static inline struct zynqmp_dpsub *to_zynqmp_dpsub(struct drm_device *drm)
|
||||
{
|
||||
return container_of(drm, struct zynqmp_dpsub, drm);
|
||||
}
|
||||
|
||||
#endif /* _ZYNQMP_DPSUB_H_ */
|
|
@ -0,0 +1,16 @@
|
|||
/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
|
||||
/*
|
||||
* Copyright 2019 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
*/
|
||||
|
||||
#ifndef __DT_BINDINGS_DMA_XLNX_ZYNQMP_DPDMA_H__
|
||||
#define __DT_BINDINGS_DMA_XLNX_ZYNQMP_DPDMA_H__
|
||||
|
||||
#define ZYNQMP_DPDMA_VIDEO0 0
|
||||
#define ZYNQMP_DPDMA_VIDEO1 1
|
||||
#define ZYNQMP_DPDMA_VIDEO2 2
|
||||
#define ZYNQMP_DPDMA_GRAPHICS 3
|
||||
#define ZYNQMP_DPDMA_AUDIO0 4
|
||||
#define ZYNQMP_DPDMA_AUDIO1 5
|
||||
|
||||
#endif /* __DT_BINDINGS_DMA_XLNX_ZYNQMP_DPDMA_H__ */
|
|
@ -61,6 +61,8 @@ enum dma_transaction_type {
|
|||
DMA_SLAVE,
|
||||
DMA_CYCLIC,
|
||||
DMA_INTERLEAVE,
|
||||
DMA_REPEAT,
|
||||
DMA_LOAD_EOT,
|
||||
/* last transaction type for creation of the capabilities mask */
|
||||
DMA_TX_TYPE_END,
|
||||
};
|
||||
|
@ -176,6 +178,16 @@ struct dma_interleaved_template {
|
|||
* @DMA_PREP_CMD: tell the driver that the data passed to DMA API is command
|
||||
* data and the descriptor should be in different format from normal
|
||||
* data descriptors.
|
||||
* @DMA_PREP_REPEAT: tell the driver that the transaction shall be automatically
|
||||
* repeated when it ends until a transaction is issued on the same channel
|
||||
* with the DMA_PREP_LOAD_EOT flag set. This flag is only applicable to
|
||||
* interleaved transactions and is ignored for all other transaction types.
|
||||
* @DMA_PREP_LOAD_EOT: tell the driver that the transaction shall replace any
|
||||
* active repeated (as indicated by DMA_PREP_REPEAT) transaction when the
|
||||
* repeated transaction ends. Not setting this flag when the previously queued
|
||||
* transaction is marked with DMA_PREP_REPEAT will cause the new transaction
|
||||
* to never be processed and stay in the issued queue forever. The flag is
|
||||
* ignored if the previous transaction is not a repeated transaction.
|
||||
*/
|
||||
enum dma_ctrl_flags {
|
||||
DMA_PREP_INTERRUPT = (1 << 0),
|
||||
|
@ -186,6 +198,8 @@ enum dma_ctrl_flags {
|
|||
DMA_PREP_FENCE = (1 << 5),
|
||||
DMA_CTRL_REUSE = (1 << 6),
|
||||
DMA_PREP_CMD = (1 << 7),
|
||||
DMA_PREP_REPEAT = (1 << 8),
|
||||
DMA_PREP_LOAD_EOT = (1 << 9),
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -980,6 +994,9 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_interleaved_dma(
|
|||
{
|
||||
if (!chan || !chan->device || !chan->device->device_prep_interleaved_dma)
|
||||
return NULL;
|
||||
if (flags & DMA_PREP_REPEAT &&
|
||||
!test_bit(DMA_REPEAT, chan->device->cap_mask.bits))
|
||||
return NULL;
|
||||
|
||||
return chan->device->device_prep_interleaved_dma(chan, xt, flags);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче