mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-01-19 11:06:26 +07:00
drm-misc-next for v5.6:
UAPI Changes: - Commandline parser: Add support for panel orientation, and per-mode options. - Fix IOCTL naming for dma-buf heaps. Cross-subsystem Changes: - Rename DMA_HEAP_IOC_ALLOC to DMA_HEAP_IOCTL_ALLOC before it becomes abi. - Change DMA-BUF system-heap's name to system. - Fix leak in error handling in dma_heap_ioctl(), and make a symbol static. - Fix udma-buf cpu access. - Fix ti devicetree bindings. Core Changes: - Add CTA-861-G modes with VIC >= 193. - Change error handling and remove bug_on in *drm_dev_init. - Export drm_panel_of_backlight() correctly once more. - Add support for lvds decoders. - Convert drm/client and drm/(gem-,)fb-helper to drm-device based logging and update logging todo. Driver Changes: - Add support for dsi/px30 to rockchip. - Add fb damage support to virtio. - Use dma_resv locking wrappers in vc4, msm, etnaviv. - Make functions in virtio static, and perform some simplifications. - Add suspend support to sun4i. - Add A64 mipi dsi support to sun4i. - Add runtime pm suspend to komeda. - Associated driver fixes. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEuXvWqAysSYEJGuVH/lWMcqZwE8MFAl4N6t8ACgkQ/lWMcqZw E8P0ww/9EEa1W1nkaYmxfWCtmBV3D6QS4490jj62RMBXETezZmLPV11xpFqTPzcw 9vRwD7PwP+rIDPTnEcg8vIMnhDgZuUMGv93PZrFZMHxe4MHeykQ6BOj4pWEnrkr4 CQxC0exyIG8sQkH5+OngXkPnANPpzsegAAQ2rGbUf0HxxdZ1WeV3aqlQFo2YDpd9 c8ouYhgnIP4NfLPYnVN3NQs/hQIVJRJ9vOHr+o8k7Fn9YoFak7ry6UFsSAan4j7I ZQDQzPnT5CQBBSRTh9vQinOexj5bkW3AFyNFA7mknv05LHYb1kMPIIqnY01pbi2w SyWc5oqJwwdCFPCLZIUHZMOBKYqGKWP0KTjy7+QKx2ty+Sjgf3hTZwnVdtNVLFJe 7WsXP6Dg+PoSsSEGZuwGOzbr7GCJitSXhUs5GGiMbdbTPzr3rJsDLuyf9/Q1ObUC F+yIKkcwYZogeXRShFFQ3wjAxEQ83yyuTchyagvqSoqFsT5ccUjuUqInGAbYifPS QfhI1U9hQGmINqXPSkQYHXxMKg+Vl2KWvFknhmLIc0Cf3fRsu+wf3NAokrHsraxd RINvo2U5XDhPctRYXaPjPiYtPlnikR69mhyGcd7VG81F72ECzZr/2q1NmsEMmUac VqowhgoG8Tm4LcZHloMw4UlCtjV2esvztc2T6b95Mg6j1r4aav0= =ye8f -----END PGP SIGNATURE----- Merge tag 'drm-misc-next-2020-01-02' of git://anongit.freedesktop.org/drm/drm-misc into drm-next drm-misc-next for v5.6: UAPI Changes: - Commandline parser: Add support for panel orientation, and per-mode options. - Fix IOCTL naming for dma-buf heaps. Cross-subsystem Changes: - Rename DMA_HEAP_IOC_ALLOC to DMA_HEAP_IOCTL_ALLOC before it becomes abi. - Change DMA-BUF system-heap's name to system. - Fix leak in error handling in dma_heap_ioctl(), and make a symbol static. - Fix udma-buf cpu access. - Fix ti devicetree bindings. Core Changes: - Add CTA-861-G modes with VIC >= 193. - Change error handling and remove bug_on in *drm_dev_init. - Export drm_panel_of_backlight() correctly once more. - Add support for lvds decoders. - Convert drm/client and drm/(gem-,)fb-helper to drm-device based logging and update logging todo. Driver Changes: - Add support for dsi/px30 to rockchip. - Add fb damage support to virtio. - Use dma_resv locking wrappers in vc4, msm, etnaviv. - Make functions in virtio static, and perform some simplifications. - Add suspend support to sun4i. - Add A64 mipi dsi support to sun4i. - Add runtime pm suspend to komeda. - Associated driver fixes. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/efc11139-1653-86bc-1b0f-0aefde219850@linux.intel.com
This commit is contained in:
commit
f5c547efa1
@ -15,7 +15,9 @@ properties:
|
||||
"#size-cells": true
|
||||
|
||||
compatible:
|
||||
const: allwinner,sun6i-a31-mipi-dsi
|
||||
enum:
|
||||
- allwinner,sun6i-a31-mipi-dsi
|
||||
- allwinner,sun50i-a64-mipi-dsi
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
@ -24,6 +26,8 @@ properties:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
items:
|
||||
- description: Bus Clock
|
||||
- description: Module Clock
|
||||
@ -63,13 +67,38 @@ required:
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
- phys
|
||||
- phy-names
|
||||
- resets
|
||||
- vcc-dsi-supply
|
||||
- port
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: allwinner,sun6i-a31-mipi-dsi
|
||||
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 2
|
||||
|
||||
required:
|
||||
- clock-names
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: allwinner,sun50i-a64-mipi-dsi
|
||||
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 1
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
|
131
Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml
Normal file
131
Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml
Normal file
@ -0,0 +1,131 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/bridge/lvds-codec.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Transparent LVDS encoders and decoders
|
||||
|
||||
maintainers:
|
||||
- Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
|
||||
description: |
|
||||
This binding supports transparent LVDS encoders and decoders that don't
|
||||
require any configuration.
|
||||
|
||||
LVDS is a physical layer specification defined in ANSI/TIA/EIA-644-A. Multiple
|
||||
incompatible data link layers have been used over time to transmit image data
|
||||
to LVDS panels. This binding targets devices compatible with the following
|
||||
specifications only.
|
||||
|
||||
[JEIDA] "Digital Interface Standards for Monitor", JEIDA-59-1999, February
|
||||
1999 (Version 1.0), Japan Electronic Industry Development Association (JEIDA)
|
||||
[LDI] "Open LVDS Display Interface", May 1999 (Version 0.95), National
|
||||
Semiconductor
|
||||
[VESA] "VESA Notebook Panel Standard", October 2007 (Version 1.0), Video
|
||||
Electronics Standards Association (VESA)
|
||||
|
||||
Those devices have been marketed under the FPD-Link and FlatLink brand names
|
||||
among others.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- ti,ds90c185 # For the TI DS90C185 FPD-Link Serializer
|
||||
- ti,ds90c187 # For the TI DS90C187 FPD-Link Serializer
|
||||
- ti,sn75lvds83 # For the TI SN75LVDS83 FlatLink transmitter
|
||||
- const: lvds-encoder # Generic LVDS encoder compatible fallback
|
||||
- items:
|
||||
- enum:
|
||||
- ti,ds90cf384a # For the DS90CF384A FPD-Link LVDS Receiver
|
||||
- const: lvds-decoder # Generic LVDS decoders compatible fallback
|
||||
- enum:
|
||||
- thine,thc63lvdm83d # For the THC63LVDM83D LVDS serializer
|
||||
|
||||
ports:
|
||||
type: object
|
||||
description: |
|
||||
This device has two video ports. Their connections are modeled using the
|
||||
OF graph bindings specified in Documentation/devicetree/bindings/graph.txt
|
||||
properties:
|
||||
port@0:
|
||||
type: object
|
||||
description: |
|
||||
For LVDS encoders, port 0 is the parallel input
|
||||
For LVDS decoders, port 0 is the LVDS input
|
||||
|
||||
port@1:
|
||||
type: object
|
||||
description: |
|
||||
For LVDS encoders, port 1 is the LVDS output
|
||||
For LVDS decoders, port 1 is the parallel output
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
powerdown-gpios:
|
||||
description:
|
||||
The GPIO used to control the power down line of this device.
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- ports
|
||||
|
||||
examples:
|
||||
- |
|
||||
lvds-encoder {
|
||||
compatible = "ti,ds90c185", "lvds-encoder";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
lvds_enc_in: endpoint {
|
||||
remote-endpoint = <&display_out_rgb>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
lvds_enc_out: endpoint {
|
||||
remote-endpoint = <&lvds_panel_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
- |
|
||||
lvds-decoder {
|
||||
compatible = "ti,ds90cf384a", "lvds-decoder";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
lvds_dec_in: endpoint {
|
||||
remote-endpoint = <&display_out_lvds>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
lvds_dec_out: endpoint {
|
||||
remote-endpoint = <&rgb_panel_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -1,66 +0,0 @@
|
||||
Parallel to LVDS Encoder
|
||||
------------------------
|
||||
|
||||
This binding supports the parallel to LVDS encoders that don't require any
|
||||
configuration.
|
||||
|
||||
LVDS is a physical layer specification defined in ANSI/TIA/EIA-644-A. Multiple
|
||||
incompatible data link layers have been used over time to transmit image data
|
||||
to LVDS panels. This binding targets devices compatible with the following
|
||||
specifications only.
|
||||
|
||||
[JEIDA] "Digital Interface Standards for Monitor", JEIDA-59-1999, February
|
||||
1999 (Version 1.0), Japan Electronic Industry Development Association (JEIDA)
|
||||
[LDI] "Open LVDS Display Interface", May 1999 (Version 0.95), National
|
||||
Semiconductor
|
||||
[VESA] "VESA Notebook Panel Standard", October 2007 (Version 1.0), Video
|
||||
Electronics Standards Association (VESA)
|
||||
|
||||
Those devices have been marketed under the FPD-Link and FlatLink brand names
|
||||
among others.
|
||||
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: Must be "lvds-encoder"
|
||||
|
||||
Any encoder compatible with this generic binding, but with additional
|
||||
properties not listed here, must list a device specific compatible first
|
||||
followed by this generic compatible.
|
||||
|
||||
Required nodes:
|
||||
|
||||
This device has two video ports. Their connections are modeled using the OF
|
||||
graph bindings specified in Documentation/devicetree/bindings/graph.txt.
|
||||
|
||||
- Video port 0 for parallel input
|
||||
- Video port 1 for LVDS output
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
lvds-encoder {
|
||||
compatible = "lvds-encoder";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
lvds_enc_in: endpoint {
|
||||
remote-endpoint = <&display_out_rgb>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
lvds_enc_out: endpoint {
|
||||
remote-endpoint = <&lvds_panel_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -1,50 +0,0 @@
|
||||
THine Electronics THC63LVDM83D LVDS serializer
|
||||
----------------------------------------------
|
||||
|
||||
The THC63LVDM83D is an LVDS serializer designed to support pixel data
|
||||
transmission between a host and a flat panel.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: Should be "thine,thc63lvdm83d"
|
||||
|
||||
Optional properties:
|
||||
|
||||
- powerdown-gpios: Power down control GPIO (the /PWDN pin, active low).
|
||||
|
||||
Required nodes:
|
||||
|
||||
The THC63LVDM83D has two video ports. Their connections are modeled using the
|
||||
OFgraph bindings specified in Documentation/devicetree/bindings/graph.txt.
|
||||
|
||||
- Video port 0 for CMOS/TTL input
|
||||
- Video port 1 for LVDS output
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
lvds_enc: encoder@0 {
|
||||
compatible = "thine,thc63lvdm83d";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
lvds_enc_in: endpoint@0 {
|
||||
remote-endpoint = <&rgb_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
lvds_enc_out: endpoint@0 {
|
||||
remote-endpoint = <&panel_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -1,55 +0,0 @@
|
||||
Texas Instruments FPD-Link (LVDS) Serializer
|
||||
--------------------------------------------
|
||||
|
||||
The DS90C185 and DS90C187 are low-power serializers for portable
|
||||
battery-powered applications that reduces the size of the RGB
|
||||
interface between the host GPU and the display.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: Should be
|
||||
"ti,ds90c185", "lvds-encoder" for the TI DS90C185 FPD-Link Serializer
|
||||
"ti,ds90c187", "lvds-encoder" for the TI DS90C187 FPD-Link Serializer
|
||||
|
||||
Optional properties:
|
||||
|
||||
- powerdown-gpios: Power down control GPIO (the PDB pin, active-low)
|
||||
|
||||
Required nodes:
|
||||
|
||||
The devices have two video ports. Their connections are modeled using the OF
|
||||
graph bindings specified in Documentation/devicetree/bindings/graph.txt.
|
||||
|
||||
- Video port 0 for parallel input
|
||||
- Video port 1 for LVDS output
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
lvds-encoder {
|
||||
compatible = "ti,ds90c185", "lvds-encoder";
|
||||
|
||||
powerdown-gpios = <&gpio 17 GPIO_ACTIVE_LOW>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
lvds_enc_in: endpoint {
|
||||
remote-endpoint = <&lcdc_out_rgb>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
lvds_enc_out: endpoint {
|
||||
remote-endpoint = <&lvds_panel_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -4,13 +4,16 @@ Rockchip specific extensions to the Synopsys Designware MIPI DSI
|
||||
Required properties:
|
||||
- #address-cells: Should be <1>.
|
||||
- #size-cells: Should be <0>.
|
||||
- compatible: "rockchip,rk3288-mipi-dsi", "snps,dw-mipi-dsi".
|
||||
"rockchip,rk3399-mipi-dsi", "snps,dw-mipi-dsi".
|
||||
- compatible: one of
|
||||
"rockchip,px30-mipi-dsi", "snps,dw-mipi-dsi"
|
||||
"rockchip,rk3288-mipi-dsi", "snps,dw-mipi-dsi"
|
||||
"rockchip,rk3399-mipi-dsi", "snps,dw-mipi-dsi"
|
||||
- reg: Represent the physical address range of the controller.
|
||||
- interrupts: Represent the controller's interrupt to the CPU(s).
|
||||
- clocks, clock-names: Phandles to the controller's pll reference
|
||||
clock(ref) and APB clock(pclk). For RK3399, a phy config clock
|
||||
(phy_cfg) and a grf clock(grf) are required. As described in [1].
|
||||
clock(ref) when using an internal dphy and APB clock(pclk).
|
||||
For RK3399, a phy config clock (phy_cfg) and a grf clock(grf)
|
||||
are required. As described in [1].
|
||||
- rockchip,grf: this soc should set GRF regs to mux vopl/vopb.
|
||||
- ports: contain a port node with endpoint definitions as defined in [2].
|
||||
For vopb,set the reg = <0> and set the reg = <1> for vopl.
|
||||
@ -18,6 +21,8 @@ Required properties:
|
||||
- video port 1 for either a panel or subsequent encoder
|
||||
|
||||
Optional properties:
|
||||
- phys: from general PHY binding: the phandle for the PHY device.
|
||||
- phy-names: Should be "dphy" if phys references an external phy.
|
||||
- power-domains: a phandle to mipi dsi power domain node.
|
||||
- resets: list of phandle + reset specifier pairs, as described in [3].
|
||||
- reset-names: string reset name, must be "apb".
|
||||
|
@ -15,7 +15,11 @@ properties:
|
||||
const: 0
|
||||
|
||||
compatible:
|
||||
const: allwinner,sun6i-a31-mipi-dphy
|
||||
oneOf:
|
||||
- const: allwinner,sun6i-a31-mipi-dphy
|
||||
- items:
|
||||
- const: allwinner,sun50i-a64-mipi-dphy
|
||||
- const: allwinner,sun6i-a31-mipi-dphy
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -65,6 +65,9 @@ Valid options are::
|
||||
- reflect_y (boolean): Perform an axial symmetry on the Y axis
|
||||
- rotate (integer): Rotate the initial framebuffer by x
|
||||
degrees. Valid values are 0, 90, 180 and 270.
|
||||
- panel_orientation, one of "normal", "upside_down", "left_side_up", or
|
||||
"right_side_up". For KMS drivers only, this sets the "panel orientation"
|
||||
property on the kms connector as hint for kms users.
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
@ -142,14 +142,14 @@ Contact: Daniel Vetter, respective driver maintainers
|
||||
|
||||
Level: Advanced
|
||||
|
||||
Convert instances of dev_info/dev_err/dev_warn to their DRM_DEV_* equivalent
|
||||
----------------------------------------------------------------------------
|
||||
Convert logging to drm_* functions with drm_device paramater
|
||||
------------------------------------------------------------
|
||||
|
||||
For drivers which could have multiple instances, it is necessary to
|
||||
differentiate between which is which in the logs. Since DRM_INFO/WARN/ERROR
|
||||
don't do this, drivers used dev_info/warn/err to make this differentiation. We
|
||||
now have DRM_DEV_* variants of the drm print macros, so we can start to convert
|
||||
those drivers back to using drm-formwatted specific log messages.
|
||||
now have drm_* variants of the drm print functions, so we can start to convert
|
||||
those drivers back to using drm-formatted specific log messages.
|
||||
|
||||
Before you start this conversion please contact the relevant maintainers to make
|
||||
sure your work will be merged - not everyone agrees that the DRM dmesg macros
|
||||
|
@ -106,8 +106,8 @@ static long dma_heap_ioctl_allocate(struct file *file, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int dma_heap_ioctl_cmds[] = {
|
||||
DMA_HEAP_IOC_ALLOC,
|
||||
static unsigned int dma_heap_ioctl_cmds[] = {
|
||||
DMA_HEAP_IOCTL_ALLOC,
|
||||
};
|
||||
|
||||
static long dma_heap_ioctl(struct file *file, unsigned int ucmd,
|
||||
@ -153,11 +153,12 @@ static long dma_heap_ioctl(struct file *file, unsigned int ucmd,
|
||||
memset(kdata + in_size, 0, ksize - in_size);
|
||||
|
||||
switch (kcmd) {
|
||||
case DMA_HEAP_IOC_ALLOC:
|
||||
case DMA_HEAP_IOCTL_ALLOC:
|
||||
ret = dma_heap_ioctl_allocate(file, kdata);
|
||||
break;
|
||||
default:
|
||||
return -ENOTTY;
|
||||
ret = -ENOTTY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (copy_to_user((void __user *)arg, kdata, out_size) != 0)
|
||||
|
@ -109,7 +109,7 @@ static int system_heap_create(void)
|
||||
struct dma_heap_export_info exp_info;
|
||||
int ret = 0;
|
||||
|
||||
exp_info.name = "system_heap";
|
||||
exp_info.name = "system";
|
||||
exp_info.ops = &system_heap_ops;
|
||||
exp_info.priv = NULL;
|
||||
|
||||
|
@ -122,9 +122,8 @@ static int begin_cpu_udmabuf(struct dma_buf *buf,
|
||||
if (IS_ERR(ubuf->sg))
|
||||
return PTR_ERR(ubuf->sg);
|
||||
} else {
|
||||
dma_sync_sg_for_device(dev, ubuf->sg->sgl,
|
||||
ubuf->sg->nents,
|
||||
direction);
|
||||
dma_sync_sg_for_cpu(dev, ubuf->sg->sgl, ubuf->sg->nents,
|
||||
direction);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -139,7 +138,7 @@ static int end_cpu_udmabuf(struct dma_buf *buf,
|
||||
if (!ubuf->sg)
|
||||
return -EINVAL;
|
||||
|
||||
dma_sync_sg_for_cpu(dev, ubuf->sg->sgl, ubuf->sg->nents, direction);
|
||||
dma_sync_sg_for_device(dev, ubuf->sg->sgl, ubuf->sg->nents, direction);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -20,8 +20,10 @@ static u64 get_lpu_event(struct d71_pipeline *d71_pipeline)
|
||||
evts |= KOMEDA_EVENT_IBSY;
|
||||
if (raw_status & LPU_IRQ_EOW)
|
||||
evts |= KOMEDA_EVENT_EOW;
|
||||
if (raw_status & LPU_IRQ_OVR)
|
||||
evts |= KOMEDA_EVENT_OVR;
|
||||
|
||||
if (raw_status & (LPU_IRQ_ERR | LPU_IRQ_IBSY)) {
|
||||
if (raw_status & (LPU_IRQ_ERR | LPU_IRQ_IBSY | LPU_IRQ_OVR)) {
|
||||
u32 restore = 0, tbu_status;
|
||||
/* Check error of LPU status */
|
||||
status = malidp_read32(reg, BLK_STATUS);
|
||||
@ -45,6 +47,15 @@ static u64 get_lpu_event(struct d71_pipeline *d71_pipeline)
|
||||
restore |= LPU_STATUS_ACE3;
|
||||
evts |= KOMEDA_ERR_ACE3;
|
||||
}
|
||||
if (status & LPU_STATUS_FEMPTY) {
|
||||
restore |= LPU_STATUS_FEMPTY;
|
||||
evts |= KOMEDA_EVENT_EMPTY;
|
||||
}
|
||||
if (status & LPU_STATUS_FFULL) {
|
||||
restore |= LPU_STATUS_FFULL;
|
||||
evts |= KOMEDA_EVENT_FULL;
|
||||
}
|
||||
|
||||
if (restore != 0)
|
||||
malidp_write32_mask(reg, BLK_STATUS, restore, 0);
|
||||
|
||||
|
@ -175,6 +175,7 @@
|
||||
#define TBU_DOUTSTDCAPB_MASK 0x3F
|
||||
|
||||
/* LPU_IRQ_BITS */
|
||||
#define LPU_IRQ_OVR BIT(9)
|
||||
#define LPU_IRQ_IBSY BIT(10)
|
||||
#define LPU_IRQ_ERR BIT(11)
|
||||
#define LPU_IRQ_EOW BIT(12)
|
||||
@ -185,6 +186,8 @@
|
||||
#define LPU_STATUS_AXIE BIT(4)
|
||||
#define LPU_STATUS_AXIRP BIT(5)
|
||||
#define LPU_STATUS_AXIWP BIT(6)
|
||||
#define LPU_STATUS_FEMPTY BIT(11)
|
||||
#define LPU_STATUS_FFULL BIT(14)
|
||||
#define LPU_STATUS_ACE0 BIT(16)
|
||||
#define LPU_STATUS_ACE1 BIT(17)
|
||||
#define LPU_STATUS_ACE2 BIT(18)
|
||||
|
@ -5,6 +5,7 @@
|
||||
*
|
||||
*/
|
||||
#include <linux/clk.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
@ -274,6 +275,7 @@ static void
|
||||
komeda_crtc_atomic_enable(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *old)
|
||||
{
|
||||
pm_runtime_get_sync(crtc->dev->dev);
|
||||
komeda_crtc_prepare(to_kcrtc(crtc));
|
||||
drm_crtc_vblank_on(crtc);
|
||||
WARN_ON(drm_crtc_vblank_get(crtc));
|
||||
@ -372,6 +374,7 @@ komeda_crtc_atomic_disable(struct drm_crtc *crtc,
|
||||
drm_crtc_vblank_put(crtc);
|
||||
drm_crtc_vblank_off(crtc);
|
||||
komeda_crtc_unprepare(kcrtc);
|
||||
pm_runtime_put(crtc->dev->dev);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/of_reserved_mem.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
#include <linux/debugfs.h>
|
||||
@ -27,12 +28,16 @@ static int komeda_register_show(struct seq_file *sf, void *x)
|
||||
|
||||
seq_puts(sf, "\n====== Komeda register dump =========\n");
|
||||
|
||||
pm_runtime_get_sync(mdev->dev);
|
||||
|
||||
if (mdev->funcs->dump_register)
|
||||
mdev->funcs->dump_register(mdev, sf);
|
||||
|
||||
for (i = 0; i < mdev->n_pipelines; i++)
|
||||
komeda_pipeline_dump_register(mdev->pipelines[i], sf);
|
||||
|
||||
pm_runtime_put(mdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -263,15 +268,6 @@ struct komeda_dev *komeda_dev_create(struct device *dev)
|
||||
if (!mdev->iommu)
|
||||
DRM_INFO("continue without IOMMU support!\n");
|
||||
|
||||
if (mdev->iommu && mdev->funcs->connect_iommu) {
|
||||
err = mdev->funcs->connect_iommu(mdev);
|
||||
if (err) {
|
||||
DRM_ERROR("connect iommu failed.\n");
|
||||
mdev->iommu = NULL;
|
||||
goto disable_clk;
|
||||
}
|
||||
}
|
||||
|
||||
clk_disable_unprepare(mdev->aclk);
|
||||
|
||||
err = sysfs_create_group(&dev->kobj, &komeda_sysfs_attr_group);
|
||||
@ -310,11 +306,6 @@ void komeda_dev_destroy(struct komeda_dev *mdev)
|
||||
if (mdev->aclk)
|
||||
clk_prepare_enable(mdev->aclk);
|
||||
|
||||
if (mdev->iommu && mdev->funcs->disconnect_iommu)
|
||||
if (mdev->funcs->disconnect_iommu(mdev))
|
||||
DRM_ERROR("disconnect iommu failed.\n");
|
||||
mdev->iommu = NULL;
|
||||
|
||||
for (i = 0; i < mdev->n_pipelines; i++) {
|
||||
komeda_pipeline_destroy(mdev, mdev->pipelines[i]);
|
||||
mdev->pipelines[i] = NULL;
|
||||
@ -343,44 +334,26 @@ void komeda_dev_destroy(struct komeda_dev *mdev)
|
||||
|
||||
int komeda_dev_resume(struct komeda_dev *mdev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
clk_prepare_enable(mdev->aclk);
|
||||
|
||||
if (mdev->iommu && mdev->funcs->connect_iommu) {
|
||||
ret = mdev->funcs->connect_iommu(mdev);
|
||||
if (ret < 0) {
|
||||
mdev->funcs->enable_irq(mdev);
|
||||
|
||||
if (mdev->iommu && mdev->funcs->connect_iommu)
|
||||
if (mdev->funcs->connect_iommu(mdev))
|
||||
DRM_ERROR("connect iommu failed.\n");
|
||||
goto disable_clk;
|
||||
}
|
||||
}
|
||||
|
||||
ret = mdev->funcs->enable_irq(mdev);
|
||||
|
||||
disable_clk:
|
||||
clk_disable_unprepare(mdev->aclk);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int komeda_dev_suspend(struct komeda_dev *mdev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
clk_prepare_enable(mdev->aclk);
|
||||
|
||||
if (mdev->iommu && mdev->funcs->disconnect_iommu) {
|
||||
ret = mdev->funcs->disconnect_iommu(mdev);
|
||||
if (ret < 0) {
|
||||
if (mdev->iommu && mdev->funcs->disconnect_iommu)
|
||||
if (mdev->funcs->disconnect_iommu(mdev))
|
||||
DRM_ERROR("disconnect iommu failed.\n");
|
||||
goto disable_clk;
|
||||
}
|
||||
}
|
||||
|
||||
ret = mdev->funcs->disable_irq(mdev);
|
||||
mdev->funcs->disable_irq(mdev);
|
||||
|
||||
disable_clk:
|
||||
clk_disable_unprepare(mdev->aclk);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
@ -20,6 +20,8 @@
|
||||
#define KOMEDA_EVENT_OVR BIT_ULL(4)
|
||||
#define KOMEDA_EVENT_EOW BIT_ULL(5)
|
||||
#define KOMEDA_EVENT_MODE BIT_ULL(6)
|
||||
#define KOMEDA_EVENT_FULL BIT_ULL(7)
|
||||
#define KOMEDA_EVENT_EMPTY BIT_ULL(8)
|
||||
|
||||
#define KOMEDA_ERR_TETO BIT_ULL(14)
|
||||
#define KOMEDA_ERR_TEMR BIT_ULL(15)
|
||||
@ -49,7 +51,8 @@
|
||||
KOMEDA_ERR_ZME | KOMEDA_ERR_MERR | KOMEDA_ERR_TCF |\
|
||||
KOMEDA_ERR_TTNG | KOMEDA_ERR_TTF)
|
||||
|
||||
#define KOMEDA_WARN_EVENTS KOMEDA_ERR_CSCE
|
||||
#define KOMEDA_WARN_EVENTS \
|
||||
(KOMEDA_ERR_CSCE | KOMEDA_EVENT_FULL | KOMEDA_EVENT_EMPTY)
|
||||
|
||||
#define KOMEDA_INFO_EVENTS (0 \
|
||||
| KOMEDA_EVENT_VSYNC \
|
||||
|
@ -33,6 +33,12 @@ static void komeda_unbind(struct device *dev)
|
||||
return;
|
||||
|
||||
komeda_kms_detach(mdrv->kms);
|
||||
|
||||
if (pm_runtime_enabled(dev))
|
||||
pm_runtime_disable(dev);
|
||||
else
|
||||
komeda_dev_suspend(mdrv->mdev);
|
||||
|
||||
komeda_dev_destroy(mdrv->mdev);
|
||||
|
||||
dev_set_drvdata(dev, NULL);
|
||||
@ -54,6 +60,10 @@ static int komeda_bind(struct device *dev)
|
||||
goto free_mdrv;
|
||||
}
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
if (!pm_runtime_enabled(dev))
|
||||
komeda_dev_resume(mdrv->mdev);
|
||||
|
||||
mdrv->kms = komeda_kms_attach(mdrv->mdev);
|
||||
if (IS_ERR(mdrv->kms)) {
|
||||
err = PTR_ERR(mdrv->kms);
|
||||
@ -65,6 +75,11 @@ static int komeda_bind(struct device *dev)
|
||||
return 0;
|
||||
|
||||
destroy_mdev:
|
||||
if (pm_runtime_enabled(dev))
|
||||
pm_runtime_disable(dev);
|
||||
else
|
||||
komeda_dev_suspend(mdrv->mdev);
|
||||
|
||||
komeda_dev_destroy(mdrv->mdev);
|
||||
|
||||
free_mdrv:
|
||||
@ -131,15 +146,29 @@ static const struct of_device_id komeda_of_match[] = {
|
||||
|
||||
MODULE_DEVICE_TABLE(of, komeda_of_match);
|
||||
|
||||
static int komeda_rt_pm_suspend(struct device *dev)
|
||||
{
|
||||
struct komeda_drv *mdrv = dev_get_drvdata(dev);
|
||||
|
||||
return komeda_dev_suspend(mdrv->mdev);
|
||||
}
|
||||
|
||||
static int komeda_rt_pm_resume(struct device *dev)
|
||||
{
|
||||
struct komeda_drv *mdrv = dev_get_drvdata(dev);
|
||||
|
||||
return komeda_dev_resume(mdrv->mdev);
|
||||
}
|
||||
|
||||
static int __maybe_unused komeda_pm_suspend(struct device *dev)
|
||||
{
|
||||
struct komeda_drv *mdrv = dev_get_drvdata(dev);
|
||||
struct drm_device *drm = &mdrv->kms->base;
|
||||
int res;
|
||||
|
||||
res = drm_mode_config_helper_suspend(drm);
|
||||
res = drm_mode_config_helper_suspend(&mdrv->kms->base);
|
||||
|
||||
komeda_dev_suspend(mdrv->mdev);
|
||||
if (!pm_runtime_status_suspended(dev))
|
||||
komeda_dev_suspend(mdrv->mdev);
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -147,15 +176,16 @@ static int __maybe_unused komeda_pm_suspend(struct device *dev)
|
||||
static int __maybe_unused komeda_pm_resume(struct device *dev)
|
||||
{
|
||||
struct komeda_drv *mdrv = dev_get_drvdata(dev);
|
||||
struct drm_device *drm = &mdrv->kms->base;
|
||||
|
||||
komeda_dev_resume(mdrv->mdev);
|
||||
if (!pm_runtime_status_suspended(dev))
|
||||
komeda_dev_resume(mdrv->mdev);
|
||||
|
||||
return drm_mode_config_helper_resume(drm);
|
||||
return drm_mode_config_helper_resume(&mdrv->kms->base);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops komeda_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(komeda_pm_suspend, komeda_pm_resume)
|
||||
SET_RUNTIME_PM_OPS(komeda_rt_pm_suspend, komeda_rt_pm_resume, NULL)
|
||||
};
|
||||
|
||||
static struct platform_driver komeda_platform_driver = {
|
||||
|
@ -78,6 +78,8 @@ static void evt_str(struct komeda_str *str, u64 events)
|
||||
|
||||
/* LPU errors or events */
|
||||
evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
|
||||
evt_sprintf(str, events & KOMEDA_EVENT_EMPTY, "EMPTY|");
|
||||
evt_sprintf(str, events & KOMEDA_EVENT_FULL, "FULL|");
|
||||
evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
|
||||
evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
|
||||
evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
|
||||
|
@ -308,10 +308,6 @@ struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev)
|
||||
if (err)
|
||||
goto free_component_binding;
|
||||
|
||||
err = mdev->funcs->enable_irq(mdev);
|
||||
if (err)
|
||||
goto free_component_binding;
|
||||
|
||||
drm->irq_enabled = true;
|
||||
|
||||
drm_kms_helper_poll_init(drm);
|
||||
@ -325,7 +321,6 @@ struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev)
|
||||
free_interrupts:
|
||||
drm_kms_helper_poll_fini(drm);
|
||||
drm->irq_enabled = false;
|
||||
mdev->funcs->disable_irq(mdev);
|
||||
free_component_binding:
|
||||
component_unbind_all(mdev->dev, drm);
|
||||
cleanup_mode_config:
|
||||
@ -347,7 +342,6 @@ void komeda_kms_detach(struct komeda_kms_dev *kms)
|
||||
drm_kms_helper_poll_fini(drm);
|
||||
drm_atomic_helper_shutdown(drm);
|
||||
drm->irq_enabled = false;
|
||||
mdev->funcs->disable_irq(mdev);
|
||||
component_unbind_all(mdev->dev, drm);
|
||||
drm_mode_config_cleanup(drm);
|
||||
komeda_kms_cleanup_private_objs(kms);
|
||||
|
@ -512,7 +512,7 @@ static int malidp_de_plane_check(struct drm_plane *plane,
|
||||
int i, ret;
|
||||
unsigned int block_w, block_h;
|
||||
|
||||
if (!state->crtc || !state->fb)
|
||||
if (!state->crtc || WARN_ON(!state->fb))
|
||||
return 0;
|
||||
|
||||
fb = state->fb;
|
||||
|
@ -255,7 +255,7 @@ void bochs_hw_setformat(struct bochs_device *bochs,
|
||||
DRM_ERROR("%s: Huh? Got framebuffer format 0x%x",
|
||||
__func__, format->format);
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void bochs_hw_setbase(struct bochs_device *bochs,
|
||||
|
@ -35,14 +35,14 @@ config DRM_DUMB_VGA_DAC
|
||||
Support for non-programmable RGB to VGA DAC bridges, such as ADI
|
||||
ADV7123, TI THS8134 and THS8135 or passive resistor ladder DACs.
|
||||
|
||||
config DRM_LVDS_ENCODER
|
||||
tristate "Transparent parallel to LVDS encoder support"
|
||||
config DRM_LVDS_CODEC
|
||||
tristate "Transparent LVDS encoders and decoders support"
|
||||
depends on OF
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_PANEL_BRIDGE
|
||||
help
|
||||
Support for transparent parallel to LVDS encoders that don't require
|
||||
any configuration.
|
||||
Support for transparent LVDS encoders and decoders that don't
|
||||
require any configuration.
|
||||
|
||||
config DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW
|
||||
tristate "MegaChips stdp4028-ge-b850v3-fw and stdp2690-ge-b850v3-fw"
|
||||
|
@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o
|
||||
obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o
|
||||
obj-$(CONFIG_DRM_LVDS_ENCODER) += lvds-encoder.o
|
||||
obj-$(CONFIG_DRM_LVDS_CODEC) += lvds-codec.o
|
||||
obj-$(CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW) += megachips-stdpxxxx-ge-b850v3-fw.o
|
||||
obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
|
||||
obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
|
||||
|
151
drivers/gpu/drm/bridge/lvds-codec.c
Normal file
151
drivers/gpu/drm/bridge/lvds-codec.c
Normal file
@ -0,0 +1,151 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2019 Renesas Electronics Corporation
|
||||
* Copyright (C) 2016 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
*/
|
||||
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
struct lvds_codec {
|
||||
struct drm_bridge bridge;
|
||||
struct drm_bridge *panel_bridge;
|
||||
struct gpio_desc *powerdown_gpio;
|
||||
u32 connector_type;
|
||||
};
|
||||
|
||||
static int lvds_codec_attach(struct drm_bridge *bridge)
|
||||
{
|
||||
struct lvds_codec *lvds_codec = container_of(bridge,
|
||||
struct lvds_codec, bridge);
|
||||
|
||||
return drm_bridge_attach(bridge->encoder, lvds_codec->panel_bridge,
|
||||
bridge);
|
||||
}
|
||||
|
||||
static void lvds_codec_enable(struct drm_bridge *bridge)
|
||||
{
|
||||
struct lvds_codec *lvds_codec = container_of(bridge,
|
||||
struct lvds_codec, bridge);
|
||||
|
||||
if (lvds_codec->powerdown_gpio)
|
||||
gpiod_set_value_cansleep(lvds_codec->powerdown_gpio, 0);
|
||||
}
|
||||
|
||||
static void lvds_codec_disable(struct drm_bridge *bridge)
|
||||
{
|
||||
struct lvds_codec *lvds_codec = container_of(bridge,
|
||||
struct lvds_codec, bridge);
|
||||
|
||||
if (lvds_codec->powerdown_gpio)
|
||||
gpiod_set_value_cansleep(lvds_codec->powerdown_gpio, 1);
|
||||
}
|
||||
|
||||
static struct drm_bridge_funcs funcs = {
|
||||
.attach = lvds_codec_attach,
|
||||
.enable = lvds_codec_enable,
|
||||
.disable = lvds_codec_disable,
|
||||
};
|
||||
|
||||
static int lvds_codec_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *panel_node;
|
||||
struct drm_panel *panel;
|
||||
struct lvds_codec *lvds_codec;
|
||||
|
||||
lvds_codec = devm_kzalloc(dev, sizeof(*lvds_codec), GFP_KERNEL);
|
||||
if (!lvds_codec)
|
||||
return -ENOMEM;
|
||||
|
||||
lvds_codec->connector_type = (uintptr_t)of_device_get_match_data(dev);
|
||||
lvds_codec->powerdown_gpio = devm_gpiod_get_optional(dev, "powerdown",
|
||||
GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(lvds_codec->powerdown_gpio)) {
|
||||
int err = PTR_ERR(lvds_codec->powerdown_gpio);
|
||||
|
||||
if (err != -EPROBE_DEFER)
|
||||
dev_err(dev, "powerdown GPIO failure: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Locate the panel DT node. */
|
||||
panel_node = of_graph_get_remote_node(dev->of_node, 1, 0);
|
||||
if (!panel_node) {
|
||||
dev_dbg(dev, "panel DT node not found\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
panel = of_drm_find_panel(panel_node);
|
||||
of_node_put(panel_node);
|
||||
if (IS_ERR(panel)) {
|
||||
dev_dbg(dev, "panel not found, deferring probe\n");
|
||||
return PTR_ERR(panel);
|
||||
}
|
||||
|
||||
lvds_codec->panel_bridge =
|
||||
devm_drm_panel_bridge_add_typed(dev, panel,
|
||||
lvds_codec->connector_type);
|
||||
if (IS_ERR(lvds_codec->panel_bridge))
|
||||
return PTR_ERR(lvds_codec->panel_bridge);
|
||||
|
||||
/*
|
||||
* The panel_bridge bridge is attached to the panel's of_node,
|
||||
* but we need a bridge attached to our of_node for our user
|
||||
* to look up.
|
||||
*/
|
||||
lvds_codec->bridge.of_node = dev->of_node;
|
||||
lvds_codec->bridge.funcs = &funcs;
|
||||
drm_bridge_add(&lvds_codec->bridge);
|
||||
|
||||
platform_set_drvdata(pdev, lvds_codec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lvds_codec_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct lvds_codec *lvds_codec = platform_get_drvdata(pdev);
|
||||
|
||||
drm_bridge_remove(&lvds_codec->bridge);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id lvds_codec_match[] = {
|
||||
{
|
||||
.compatible = "lvds-decoder",
|
||||
.data = (void *)DRM_MODE_CONNECTOR_DPI,
|
||||
},
|
||||
{
|
||||
.compatible = "lvds-encoder",
|
||||
.data = (void *)DRM_MODE_CONNECTOR_LVDS,
|
||||
},
|
||||
{
|
||||
.compatible = "thine,thc63lvdm83d",
|
||||
.data = (void *)DRM_MODE_CONNECTOR_LVDS,
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lvds_codec_match);
|
||||
|
||||
static struct platform_driver lvds_codec_driver = {
|
||||
.probe = lvds_codec_probe,
|
||||
.remove = lvds_codec_remove,
|
||||
.driver = {
|
||||
.name = "lvds-codec",
|
||||
.of_match_table = lvds_codec_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(lvds_codec_driver);
|
||||
|
||||
MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
|
||||
MODULE_DESCRIPTION("LVDS encoders and decoders");
|
||||
MODULE_LICENSE("GPL");
|
@ -1,155 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2016 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
*/
|
||||
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
struct lvds_encoder {
|
||||
struct drm_bridge bridge;
|
||||
struct drm_bridge *panel_bridge;
|
||||
struct gpio_desc *powerdown_gpio;
|
||||
};
|
||||
|
||||
static int lvds_encoder_attach(struct drm_bridge *bridge)
|
||||
{
|
||||
struct lvds_encoder *lvds_encoder = container_of(bridge,
|
||||
struct lvds_encoder,
|
||||
bridge);
|
||||
|
||||
return drm_bridge_attach(bridge->encoder, lvds_encoder->panel_bridge,
|
||||
bridge);
|
||||
}
|
||||
|
||||
static void lvds_encoder_enable(struct drm_bridge *bridge)
|
||||
{
|
||||
struct lvds_encoder *lvds_encoder = container_of(bridge,
|
||||
struct lvds_encoder,
|
||||
bridge);
|
||||
|
||||
if (lvds_encoder->powerdown_gpio)
|
||||
gpiod_set_value_cansleep(lvds_encoder->powerdown_gpio, 0);
|
||||
}
|
||||
|
||||
static void lvds_encoder_disable(struct drm_bridge *bridge)
|
||||
{
|
||||
struct lvds_encoder *lvds_encoder = container_of(bridge,
|
||||
struct lvds_encoder,
|
||||
bridge);
|
||||
|
||||
if (lvds_encoder->powerdown_gpio)
|
||||
gpiod_set_value_cansleep(lvds_encoder->powerdown_gpio, 1);
|
||||
}
|
||||
|
||||
static struct drm_bridge_funcs funcs = {
|
||||
.attach = lvds_encoder_attach,
|
||||
.enable = lvds_encoder_enable,
|
||||
.disable = lvds_encoder_disable,
|
||||
};
|
||||
|
||||
static int lvds_encoder_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *port;
|
||||
struct device_node *endpoint;
|
||||
struct device_node *panel_node;
|
||||
struct drm_panel *panel;
|
||||
struct lvds_encoder *lvds_encoder;
|
||||
|
||||
lvds_encoder = devm_kzalloc(dev, sizeof(*lvds_encoder), GFP_KERNEL);
|
||||
if (!lvds_encoder)
|
||||
return -ENOMEM;
|
||||
|
||||
lvds_encoder->powerdown_gpio = devm_gpiod_get_optional(dev, "powerdown",
|
||||
GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(lvds_encoder->powerdown_gpio)) {
|
||||
int err = PTR_ERR(lvds_encoder->powerdown_gpio);
|
||||
|
||||
if (err != -EPROBE_DEFER)
|
||||
dev_err(dev, "powerdown GPIO failure: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Locate the panel DT node. */
|
||||
port = of_graph_get_port_by_id(dev->of_node, 1);
|
||||
if (!port) {
|
||||
dev_dbg(dev, "port 1 not found\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
endpoint = of_get_child_by_name(port, "endpoint");
|
||||
of_node_put(port);
|
||||
if (!endpoint) {
|
||||
dev_dbg(dev, "no endpoint for port 1\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
panel_node = of_graph_get_remote_port_parent(endpoint);
|
||||
of_node_put(endpoint);
|
||||
if (!panel_node) {
|
||||
dev_dbg(dev, "no remote endpoint for port 1\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
panel = of_drm_find_panel(panel_node);
|
||||
of_node_put(panel_node);
|
||||
if (IS_ERR(panel)) {
|
||||
dev_dbg(dev, "panel not found, deferring probe\n");
|
||||
return PTR_ERR(panel);
|
||||
}
|
||||
|
||||
lvds_encoder->panel_bridge =
|
||||
devm_drm_panel_bridge_add_typed(dev, panel,
|
||||
DRM_MODE_CONNECTOR_LVDS);
|
||||
if (IS_ERR(lvds_encoder->panel_bridge))
|
||||
return PTR_ERR(lvds_encoder->panel_bridge);
|
||||
|
||||
/* The panel_bridge bridge is attached to the panel's of_node,
|
||||
* but we need a bridge attached to our of_node for our user
|
||||
* to look up.
|
||||
*/
|
||||
lvds_encoder->bridge.of_node = dev->of_node;
|
||||
lvds_encoder->bridge.funcs = &funcs;
|
||||
drm_bridge_add(&lvds_encoder->bridge);
|
||||
|
||||
platform_set_drvdata(pdev, lvds_encoder);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lvds_encoder_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct lvds_encoder *lvds_encoder = platform_get_drvdata(pdev);
|
||||
|
||||
drm_bridge_remove(&lvds_encoder->bridge);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id lvds_encoder_match[] = {
|
||||
{ .compatible = "lvds-encoder" },
|
||||
{ .compatible = "thine,thc63lvdm83d" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lvds_encoder_match);
|
||||
|
||||
static struct platform_driver lvds_encoder_driver = {
|
||||
.probe = lvds_encoder_probe,
|
||||
.remove = lvds_encoder_remove,
|
||||
.driver = {
|
||||
.name = "lvds-encoder",
|
||||
.of_match_table = lvds_encoder_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(lvds_encoder_driver);
|
||||
|
||||
MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
|
||||
MODULE_DESCRIPTION("Transparent parallel to LVDS encoder");
|
||||
MODULE_LICENSE("GPL");
|
@ -719,7 +719,15 @@ static void dw_mipi_dsi_vertical_timing_config(struct dw_mipi_dsi *dsi,
|
||||
|
||||
static void dw_mipi_dsi_dphy_timing_config(struct dw_mipi_dsi *dsi)
|
||||
{
|
||||
const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops;
|
||||
struct dw_mipi_dsi_dphy_timing timing;
|
||||
u32 hw_version;
|
||||
int ret;
|
||||
|
||||
ret = phy_ops->get_timing(dsi->plat_data->priv_data,
|
||||
dsi->lane_mbps, &timing);
|
||||
if (ret)
|
||||
DRM_DEV_ERROR(dsi->dev, "Retrieving phy timings failed\n");
|
||||
|
||||
/*
|
||||
* TODO dw drv improvements
|
||||
@ -732,16 +740,20 @@ static void dw_mipi_dsi_dphy_timing_config(struct dw_mipi_dsi *dsi)
|
||||
hw_version = dsi_read(dsi, DSI_VERSION) & VERSION;
|
||||
|
||||
if (hw_version >= HWVER_131) {
|
||||
dsi_write(dsi, DSI_PHY_TMR_CFG, PHY_HS2LP_TIME_V131(0x40) |
|
||||
PHY_LP2HS_TIME_V131(0x40));
|
||||
dsi_write(dsi, DSI_PHY_TMR_CFG,
|
||||
PHY_HS2LP_TIME_V131(timing.data_hs2lp) |
|
||||
PHY_LP2HS_TIME_V131(timing.data_lp2hs));
|
||||
dsi_write(dsi, DSI_PHY_TMR_RD_CFG, MAX_RD_TIME_V131(10000));
|
||||
} else {
|
||||
dsi_write(dsi, DSI_PHY_TMR_CFG, PHY_HS2LP_TIME(0x40) |
|
||||
PHY_LP2HS_TIME(0x40) | MAX_RD_TIME(10000));
|
||||
dsi_write(dsi, DSI_PHY_TMR_CFG,
|
||||
PHY_HS2LP_TIME(timing.data_hs2lp) |
|
||||
PHY_LP2HS_TIME(timing.data_lp2hs) |
|
||||
MAX_RD_TIME(10000));
|
||||
}
|
||||
|
||||
dsi_write(dsi, DSI_PHY_TMR_LPCLK_CFG, PHY_CLKHS2LP_TIME(0x40)
|
||||
| PHY_CLKLP2HS_TIME(0x40));
|
||||
dsi_write(dsi, DSI_PHY_TMR_LPCLK_CFG,
|
||||
PHY_CLKHS2LP_TIME(timing.clk_hs2lp) |
|
||||
PHY_CLKLP2HS_TIME(timing.clk_lp2hs));
|
||||
}
|
||||
|
||||
static void dw_mipi_dsi_dphy_interface_config(struct dw_mipi_dsi *dsi)
|
||||
@ -798,9 +810,6 @@ static void dw_mipi_dsi_bridge_post_disable(struct drm_bridge *bridge)
|
||||
struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
|
||||
const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops;
|
||||
|
||||
if (phy_ops->power_off)
|
||||
phy_ops->power_off(dsi->plat_data->priv_data);
|
||||
|
||||
/*
|
||||
* Switch to command mode before panel-bridge post_disable &
|
||||
* panel unprepare.
|
||||
@ -817,6 +826,9 @@ static void dw_mipi_dsi_bridge_post_disable(struct drm_bridge *bridge)
|
||||
*/
|
||||
dsi->panel_bridge->funcs->post_disable(dsi->panel_bridge);
|
||||
|
||||
if (phy_ops->power_off)
|
||||
phy_ops->power_off(dsi->plat_data->priv_data);
|
||||
|
||||
if (dsi->slave) {
|
||||
dw_mipi_dsi_disable(dsi->slave);
|
||||
clk_disable_unprepare(dsi->slave->pclk);
|
||||
@ -883,6 +895,9 @@ static void dw_mipi_dsi_mode_set(struct dw_mipi_dsi *dsi,
|
||||
|
||||
/* Switch to cmd mode for panel-bridge pre_enable & panel prepare */
|
||||
dw_mipi_dsi_set_mode(dsi, 0);
|
||||
|
||||
if (phy_ops->power_on)
|
||||
phy_ops->power_on(dsi->plat_data->priv_data);
|
||||
}
|
||||
|
||||
static void dw_mipi_dsi_bridge_mode_set(struct drm_bridge *bridge,
|
||||
@ -899,15 +914,11 @@ static void dw_mipi_dsi_bridge_mode_set(struct drm_bridge *bridge,
|
||||
static void dw_mipi_dsi_bridge_enable(struct drm_bridge *bridge)
|
||||
{
|
||||
struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
|
||||
const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops;
|
||||
|
||||
/* Switch to video mode for panel-bridge enable & panel enable */
|
||||
dw_mipi_dsi_set_mode(dsi, MIPI_DSI_MODE_VIDEO);
|
||||
if (dsi->slave)
|
||||
dw_mipi_dsi_set_mode(dsi->slave, MIPI_DSI_MODE_VIDEO);
|
||||
|
||||
if (phy_ops->power_on)
|
||||
phy_ops->power_on(dsi->plat_data->priv_data);
|
||||
}
|
||||
|
||||
static enum drm_mode_status
|
||||
@ -991,7 +1002,8 @@ __dw_mipi_dsi_probe(struct platform_device *pdev,
|
||||
dsi->dev = dev;
|
||||
dsi->plat_data = plat_data;
|
||||
|
||||
if (!plat_data->phy_ops->init || !plat_data->phy_ops->get_lane_mbps) {
|
||||
if (!plat_data->phy_ops->init || !plat_data->phy_ops->get_lane_mbps ||
|
||||
!plat_data->phy_ops->get_timing) {
|
||||
DRM_ERROR("Phy not properly configured\n");
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
@ -251,7 +251,7 @@ EXPORT_SYMBOL(drm_atomic_state_clear);
|
||||
* @ref: This atomic state to deallocate
|
||||
*
|
||||
* This frees all memory associated with an atomic state, including all the
|
||||
* per-object state for planes, crtcs and connectors.
|
||||
* per-object state for planes, CRTCs and connectors.
|
||||
*/
|
||||
void __drm_atomic_state_free(struct kref *ref)
|
||||
{
|
||||
@ -272,12 +272,12 @@ void __drm_atomic_state_free(struct kref *ref)
|
||||
EXPORT_SYMBOL(__drm_atomic_state_free);
|
||||
|
||||
/**
|
||||
* drm_atomic_get_crtc_state - get crtc state
|
||||
* drm_atomic_get_crtc_state - get CRTC state
|
||||
* @state: global atomic state object
|
||||
* @crtc: crtc to get state object for
|
||||
* @crtc: CRTC to get state object for
|
||||
*
|
||||
* This function returns the crtc state for the given crtc, allocating it if
|
||||
* needed. It will also grab the relevant crtc lock to make sure that the state
|
||||
* This function returns the CRTC state for the given CRTC, allocating it if
|
||||
* needed. It will also grab the relevant CRTC lock to make sure that the state
|
||||
* is consistent.
|
||||
*
|
||||
* Returns:
|
||||
@ -1018,14 +1018,14 @@ static void drm_atomic_connector_print_state(struct drm_printer *p,
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_atomic_add_affected_connectors - add connectors for crtc
|
||||
* drm_atomic_add_affected_connectors - add connectors for CRTC
|
||||
* @state: atomic state
|
||||
* @crtc: DRM crtc
|
||||
* @crtc: DRM CRTC
|
||||
*
|
||||
* This function walks the current configuration and adds all connectors
|
||||
* currently using @crtc to the atomic configuration @state. Note that this
|
||||
* function must acquire the connection mutex. This can potentially cause
|
||||
* unneeded seralization if the update is just for the planes on one crtc. Hence
|
||||
* unneeded seralization if the update is just for the planes on one CRTC. Hence
|
||||
* drivers and helpers should only call this when really needed (e.g. when a
|
||||
* full modeset needs to happen due to some change).
|
||||
*
|
||||
@ -1078,9 +1078,9 @@ drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
|
||||
EXPORT_SYMBOL(drm_atomic_add_affected_connectors);
|
||||
|
||||
/**
|
||||
* drm_atomic_add_affected_planes - add planes for crtc
|
||||
* drm_atomic_add_affected_planes - add planes for CRTC
|
||||
* @state: atomic state
|
||||
* @crtc: DRM crtc
|
||||
* @crtc: DRM CRTC
|
||||
*
|
||||
* This function walks the current configuration and adds all planes
|
||||
* currently used by @crtc to the atomic configuration @state. This is useful
|
||||
|
@ -150,8 +150,8 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state,
|
||||
* is not set, an error is returned. Userspace can provide a solution
|
||||
* through the atomic ioctl.
|
||||
*
|
||||
* If the flag is set conflicting connectors are removed from the crtc
|
||||
* and the crtc is disabled if no encoder is left. This preserves
|
||||
* If the flag is set conflicting connectors are removed from the CRTC
|
||||
* and the CRTC is disabled if no encoder is left. This preserves
|
||||
* compatibility with the legacy set_config behavior.
|
||||
*/
|
||||
drm_connector_list_iter_begin(state->dev, &conn_iter);
|
||||
@ -220,7 +220,7 @@ set_best_encoder(struct drm_atomic_state *state,
|
||||
crtc = conn_state->connector->state->crtc;
|
||||
|
||||
/* A NULL crtc is an error here because we should have
|
||||
* duplicated a NULL best_encoder when crtc was NULL.
|
||||
* duplicated a NULL best_encoder when crtc was NULL.
|
||||
* As an exception restoring duplicated atomic state
|
||||
* during resume is allowed, so don't warn when
|
||||
* best_encoder is equal to encoder we intend to set.
|
||||
@ -561,27 +561,27 @@ mode_valid(struct drm_atomic_state *state)
|
||||
* @state: the driver state object
|
||||
*
|
||||
* Check the state object to see if the requested state is physically possible.
|
||||
* This does all the crtc and connector related computations for an atomic
|
||||
* This does all the CRTC and connector related computations for an atomic
|
||||
* update and adds any additional connectors needed for full modesets. It calls
|
||||
* the various per-object callbacks in the follow order:
|
||||
*
|
||||
* 1. &drm_connector_helper_funcs.atomic_best_encoder for determining the new encoder.
|
||||
* 2. &drm_connector_helper_funcs.atomic_check to validate the connector state.
|
||||
* 3. If it's determined a modeset is needed then all connectors on the affected crtc
|
||||
* crtc are added and &drm_connector_helper_funcs.atomic_check is run on them.
|
||||
* 3. If it's determined a modeset is needed then all connectors on the affected
|
||||
* CRTC are added and &drm_connector_helper_funcs.atomic_check is run on them.
|
||||
* 4. &drm_encoder_helper_funcs.mode_valid, &drm_bridge_funcs.mode_valid and
|
||||
* &drm_crtc_helper_funcs.mode_valid are called on the affected components.
|
||||
* 5. &drm_bridge_funcs.mode_fixup is called on all encoder bridges.
|
||||
* 6. &drm_encoder_helper_funcs.atomic_check is called to validate any encoder state.
|
||||
* This function is only called when the encoder will be part of a configured crtc,
|
||||
* This function is only called when the encoder will be part of a configured CRTC,
|
||||
* it must not be used for implementing connector property validation.
|
||||
* If this function is NULL, &drm_atomic_encoder_helper_funcs.mode_fixup is called
|
||||
* instead.
|
||||
* 7. &drm_crtc_helper_funcs.mode_fixup is called last, to fix up the mode with crtc constraints.
|
||||
* 7. &drm_crtc_helper_funcs.mode_fixup is called last, to fix up the mode with CRTC constraints.
|
||||
*
|
||||
* &drm_crtc_state.mode_changed is set when the input mode is changed.
|
||||
* &drm_crtc_state.connectors_changed is set when a connector is added or
|
||||
* removed from the crtc. &drm_crtc_state.active_changed is set when
|
||||
* removed from the CRTC. &drm_crtc_state.active_changed is set when
|
||||
* &drm_crtc_state.active changes, which is used for DPMS.
|
||||
* See also: drm_atomic_crtc_needs_modeset()
|
||||
*
|
||||
@ -692,7 +692,7 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
|
||||
|
||||
/*
|
||||
* After all the routing has been prepared we need to add in any
|
||||
* connector which is itself unchanged, but whose crtc changes its
|
||||
* connector which is itself unchanged, but whose CRTC changes its
|
||||
* configuration. This must be done before calling mode_fixup in case a
|
||||
* crtc only changed its mode but has the same set of connectors.
|
||||
*/
|
||||
@ -741,13 +741,13 @@ EXPORT_SYMBOL(drm_atomic_helper_check_modeset);
|
||||
/**
|
||||
* drm_atomic_helper_check_plane_state() - Check plane state for validity
|
||||
* @plane_state: plane state to check
|
||||
* @crtc_state: crtc state to check
|
||||
* @crtc_state: CRTC state to check
|
||||
* @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
|
||||
* @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point
|
||||
* @can_position: is it legal to position the plane such that it
|
||||
* doesn't cover the entire crtc? This will generally
|
||||
* doesn't cover the entire CRTC? This will generally
|
||||
* only be false for primary planes.
|
||||
* @can_update_disabled: can the plane be updated while the crtc
|
||||
* @can_update_disabled: can the plane be updated while the CRTC
|
||||
* is disabled?
|
||||
*
|
||||
* Checks that a desired plane update is valid, and updates various
|
||||
@ -844,7 +844,7 @@ EXPORT_SYMBOL(drm_atomic_helper_check_plane_state);
|
||||
* &drm_crtc_helper_funcs.atomic_check and &drm_plane_helper_funcs.atomic_check
|
||||
* hooks provided by the driver.
|
||||
*
|
||||
* It also sets &drm_crtc_state.planes_changed to indicate that a crtc has
|
||||
* It also sets &drm_crtc_state.planes_changed to indicate that a CRTC has
|
||||
* updated planes.
|
||||
*
|
||||
* RETURNS:
|
||||
@ -908,7 +908,7 @@ EXPORT_SYMBOL(drm_atomic_helper_check_planes);
|
||||
* @state: the driver state object
|
||||
*
|
||||
* Check the state object to see if the requested state is physically possible.
|
||||
* Only crtcs and planes have check callbacks, so for any additional (global)
|
||||
* Only CRTCs and planes have check callbacks, so for any additional (global)
|
||||
* checking that a driver needs it can simply wrap that around this function.
|
||||
* Drivers without such needs can directly use this as their
|
||||
* &drm_mode_config_funcs.atomic_check callback.
|
||||
@ -961,14 +961,14 @@ crtc_needs_disable(struct drm_crtc_state *old_state,
|
||||
struct drm_crtc_state *new_state)
|
||||
{
|
||||
/*
|
||||
* No new_state means the crtc is off, so the only criteria is whether
|
||||
* No new_state means the CRTC is off, so the only criteria is whether
|
||||
* it's currently active or in self refresh mode.
|
||||
*/
|
||||
if (!new_state)
|
||||
return drm_atomic_crtc_effectively_active(old_state);
|
||||
|
||||
/*
|
||||
* We need to run through the crtc_funcs->disable() function if the crtc
|
||||
* We need to run through the crtc_funcs->disable() function if the CRTC
|
||||
* is currently on, if it's transitioning to self refresh mode, or if
|
||||
* it's in self refresh mode and needs to be fully disabled.
|
||||
*/
|
||||
@ -1087,7 +1087,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
|
||||
* @old_state: atomic state object with old state structures
|
||||
*
|
||||
* This function updates all the various legacy modeset state pointers in
|
||||
* connectors, encoders and crtcs. It also updates the timestamping constants
|
||||
* connectors, encoders and CRTCs. It also updates the timestamping constants
|
||||
* used for precise vblank timestamps by calling
|
||||
* drm_calc_timestamping_constants().
|
||||
*
|
||||
@ -1236,7 +1236,7 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
|
||||
* This function shuts down all the outputs that need to be shut down and
|
||||
* prepares them (if required) with the new mode.
|
||||
*
|
||||
* For compatibility with legacy crtc helpers this should be called before
|
||||
* For compatibility with legacy CRTC helpers this should be called before
|
||||
* drm_atomic_helper_commit_planes(), which is what the default commit function
|
||||
* does. But drivers with different needs can group the modeset commits together
|
||||
* and do the plane commits at the end. This is useful for drivers doing runtime
|
||||
@ -1282,7 +1282,7 @@ static void drm_atomic_helper_commit_writebacks(struct drm_device *dev,
|
||||
* This function enables all the outputs with the new configuration which had to
|
||||
* be turned off for the update.
|
||||
*
|
||||
* For compatibility with legacy crtc helpers this should be called after
|
||||
* For compatibility with legacy CRTC helpers this should be called after
|
||||
* drm_atomic_helper_commit_planes(), which is what the default commit function
|
||||
* does. But drivers with different needs can group the modeset commits together
|
||||
* and do the plane commits at the end. This is useful for drivers doing runtime
|
||||
@ -1414,12 +1414,12 @@ int drm_atomic_helper_wait_for_fences(struct drm_device *dev,
|
||||
EXPORT_SYMBOL(drm_atomic_helper_wait_for_fences);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_wait_for_vblanks - wait for vblank on crtcs
|
||||
* drm_atomic_helper_wait_for_vblanks - wait for vblank on CRTCs
|
||||
* @dev: DRM device
|
||||
* @old_state: atomic state object with old state structures
|
||||
*
|
||||
* Helper to, after atomic commit, wait for vblanks on all effected
|
||||
* crtcs (ie. before cleaning up old framebuffers using
|
||||
* Helper to, after atomic commit, wait for vblanks on all affected
|
||||
* CRTCs (ie. before cleaning up old framebuffers using
|
||||
* drm_atomic_helper_cleanup_planes()). It will only wait on CRTCs where the
|
||||
* framebuffers have actually changed to optimize for the legacy cursor and
|
||||
* plane update use-case.
|
||||
@ -1478,10 +1478,10 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_vblanks);
|
||||
* @dev: DRM device
|
||||
* @old_state: atomic state object with old state structures
|
||||
*
|
||||
* Helper to, after atomic commit, wait for page flips on all effected
|
||||
* Helper to, after atomic commit, wait for page flips on all affected
|
||||
* crtcs (ie. before cleaning up old framebuffers using
|
||||
* drm_atomic_helper_cleanup_planes()). Compared to
|
||||
* drm_atomic_helper_wait_for_vblanks() this waits for the completion of on all
|
||||
* drm_atomic_helper_wait_for_vblanks() this waits for the completion on all
|
||||
* CRTCs, assuming that cursors-only updates are signalling their completion
|
||||
* immediately (or using a different path).
|
||||
*
|
||||
@ -2208,7 +2208,7 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_dependencies);
|
||||
* drm_atomic_helper_fake_vblank - fake VBLANK events if needed
|
||||
* @old_state: atomic state object with old state structures
|
||||
*
|
||||
* This function walks all CRTCs and fake VBLANK events on those with
|
||||
* This function walks all CRTCs and fakes VBLANK events on those with
|
||||
* &drm_crtc_state.no_vblank set to true and &drm_crtc_state.event != NULL.
|
||||
* The primary use of this function is writeback connectors working in oneshot
|
||||
* mode and faking VBLANK events. In this case they only fake the VBLANK event
|
||||
@ -2404,7 +2404,7 @@ static bool plane_crtc_active(const struct drm_plane_state *state)
|
||||
* @flags: flags for committing plane state
|
||||
*
|
||||
* This function commits the new plane state using the plane and atomic helper
|
||||
* functions for planes and crtcs. It assumes that the atomic state has already
|
||||
* functions for planes and CRTCs. It assumes that the atomic state has already
|
||||
* been pushed into the relevant object state pointers, since this step can no
|
||||
* longer fail.
|
||||
*
|
||||
@ -2525,15 +2525,15 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
|
||||
EXPORT_SYMBOL(drm_atomic_helper_commit_planes);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_commit_planes_on_crtc - commit plane state for a crtc
|
||||
* @old_crtc_state: atomic state object with the old crtc state
|
||||
* drm_atomic_helper_commit_planes_on_crtc - commit plane state for a CRTC
|
||||
* @old_crtc_state: atomic state object with the old CRTC state
|
||||
*
|
||||
* This function commits the new plane state using the plane and atomic helper
|
||||
* functions for planes on the specific crtc. It assumes that the atomic state
|
||||
* functions for planes on the specific CRTC. It assumes that the atomic state
|
||||
* has already been pushed into the relevant object state pointers, since this
|
||||
* step can no longer fail.
|
||||
*
|
||||
* This function is useful when plane updates should be done crtc-by-crtc
|
||||
* This function is useful when plane updates should be done CRTC-by-CRTC
|
||||
* instead of one global step like drm_atomic_helper_commit_planes() does.
|
||||
*
|
||||
* This function can only be savely used when planes are not allowed to move
|
||||
@ -2823,10 +2823,10 @@ EXPORT_SYMBOL(drm_atomic_helper_swap_state);
|
||||
* @plane: plane object to update
|
||||
* @crtc: owning CRTC of owning plane
|
||||
* @fb: framebuffer to flip onto plane
|
||||
* @crtc_x: x offset of primary plane on crtc
|
||||
* @crtc_y: y offset of primary plane on crtc
|
||||
* @crtc_w: width of primary plane rectangle on crtc
|
||||
* @crtc_h: height of primary plane rectangle on crtc
|
||||
* @crtc_x: x offset of primary plane on @crtc
|
||||
* @crtc_y: y offset of primary plane on @crtc
|
||||
* @crtc_w: width of primary plane rectangle on @crtc
|
||||
* @crtc_h: height of primary plane rectangle on @crtc
|
||||
* @src_x: x offset of @fb for panning
|
||||
* @src_y: y offset of @fb for panning
|
||||
* @src_w: width of source rectangle in @fb
|
||||
@ -2932,7 +2932,7 @@ EXPORT_SYMBOL(drm_atomic_helper_disable_plane);
|
||||
* @set: mode set configuration
|
||||
* @ctx: lock acquisition context
|
||||
*
|
||||
* Provides a default crtc set_config handler using the atomic driver interface.
|
||||
* Provides a default CRTC set_config handler using the atomic driver interface.
|
||||
*
|
||||
* NOTE: For backwards compatibility with old userspace this automatically
|
||||
* resets the "link-status" property to GOOD, to force any link
|
||||
@ -3345,7 +3345,7 @@ static int page_flip_common(struct drm_atomic_state *state,
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_page_flip - execute a legacy page flip
|
||||
* @crtc: DRM crtc
|
||||
* @crtc: DRM CRTC
|
||||
* @fb: DRM framebuffer
|
||||
* @event: optional DRM event to signal upon completion
|
||||
* @flags: flip flags for non-vblank sync'ed updates
|
||||
@ -3389,7 +3389,7 @@ EXPORT_SYMBOL(drm_atomic_helper_page_flip);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_page_flip_target - do page flip on target vblank period.
|
||||
* @crtc: DRM crtc
|
||||
* @crtc: DRM CRTC
|
||||
* @fb: DRM framebuffer
|
||||
* @event: optional DRM event to signal upon completion
|
||||
* @flags: flip flags for non-vblank sync'ed updates
|
||||
|
@ -160,12 +160,12 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
|
||||
EXPORT_SYMBOL(drm_atomic_set_mode_prop_for_crtc);
|
||||
|
||||
/**
|
||||
* drm_atomic_set_crtc_for_plane - set crtc for plane
|
||||
* drm_atomic_set_crtc_for_plane - set CRTC for plane
|
||||
* @plane_state: the plane whose incoming state to update
|
||||
* @crtc: crtc to use for the plane
|
||||
* @crtc: CRTC to use for the plane
|
||||
*
|
||||
* Changing the assigned crtc for a plane requires us to grab the lock and state
|
||||
* for the new crtc, as needed. This function takes care of all these details
|
||||
* Changing the assigned CRTC for a plane requires us to grab the lock and state
|
||||
* for the new CRTC, as needed. This function takes care of all these details
|
||||
* besides updating the pointer in the state object itself.
|
||||
*
|
||||
* Returns:
|
||||
@ -279,12 +279,12 @@ drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
|
||||
EXPORT_SYMBOL(drm_atomic_set_fence_for_plane);
|
||||
|
||||
/**
|
||||
* drm_atomic_set_crtc_for_connector - set crtc for connector
|
||||
* drm_atomic_set_crtc_for_connector - set CRTC for connector
|
||||
* @conn_state: atomic state object for the connector
|
||||
* @crtc: crtc to use for the connector
|
||||
* @crtc: CRTC to use for the connector
|
||||
*
|
||||
* Changing the assigned crtc for a connector requires us to grab the lock and
|
||||
* state for the new crtc, as needed. This function takes care of all these
|
||||
* Changing the assigned CRTC for a connector requires us to grab the lock and
|
||||
* state for the new CRTC, as needed. This function takes care of all these
|
||||
* details besides updating the pointer in the state object itself.
|
||||
*
|
||||
* Returns:
|
||||
|
@ -150,7 +150,7 @@ void drm_client_release(struct drm_client_dev *client)
|
||||
{
|
||||
struct drm_device *dev = client->dev;
|
||||
|
||||
DRM_DEV_DEBUG_KMS(dev->dev, "%s\n", client->name);
|
||||
drm_dbg_kms(dev, "%s\n", client->name);
|
||||
|
||||
drm_client_modeset_free(client);
|
||||
drm_client_close(client);
|
||||
@ -203,7 +203,7 @@ void drm_client_dev_hotplug(struct drm_device *dev)
|
||||
continue;
|
||||
|
||||
ret = client->funcs->hotplug(client);
|
||||
DRM_DEV_DEBUG_KMS(dev->dev, "%s: ret=%d\n", client->name, ret);
|
||||
drm_dbg_kms(dev, "%s: ret=%d\n", client->name, ret);
|
||||
}
|
||||
mutex_unlock(&dev->clientlist_mutex);
|
||||
}
|
||||
@ -223,7 +223,7 @@ void drm_client_dev_restore(struct drm_device *dev)
|
||||
continue;
|
||||
|
||||
ret = client->funcs->restore(client);
|
||||
DRM_DEV_DEBUG_KMS(dev->dev, "%s: ret=%d\n", client->name, ret);
|
||||
drm_dbg_kms(dev, "%s: ret=%d\n", client->name, ret);
|
||||
if (!ret) /* The first one to return zero gets the privilege to restore */
|
||||
break;
|
||||
}
|
||||
@ -351,8 +351,8 @@ static void drm_client_buffer_rmfb(struct drm_client_buffer *buffer)
|
||||
|
||||
ret = drm_mode_rmfb(buffer->client->dev, buffer->fb->base.id, buffer->client->file);
|
||||
if (ret)
|
||||
DRM_DEV_ERROR(buffer->client->dev->dev,
|
||||
"Error removing FB:%u (%d)\n", buffer->fb->base.id, ret);
|
||||
drm_err(buffer->client->dev,
|
||||
"Error removing FB:%u (%d)\n", buffer->fb->base.id, ret);
|
||||
|
||||
buffer->fb = NULL;
|
||||
}
|
||||
|
@ -622,7 +622,8 @@ int drm_dev_init(struct drm_device *dev,
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
BUG_ON(!parent);
|
||||
if (WARN_ON(!parent))
|
||||
return -EINVAL;
|
||||
|
||||
kref_init(&dev->ref);
|
||||
dev->dev = get_device(parent);
|
||||
@ -725,7 +726,7 @@ int devm_drm_dev_init(struct device *parent,
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (WARN_ON(!parent || !driver->release))
|
||||
if (WARN_ON(!driver->release))
|
||||
return -EINVAL;
|
||||
|
||||
ret = drm_dev_init(dev, driver, parent);
|
||||
|
@ -710,14 +710,11 @@ static const struct minimode extra_modes[] = {
|
||||
};
|
||||
|
||||
/*
|
||||
* Probably taken from CEA-861 spec.
|
||||
* This table is converted from xorg's hw/xfree86/modes/xf86EdidModes.c.
|
||||
* From CEA/CTA-861 spec.
|
||||
*
|
||||
* Index using the VIC.
|
||||
* Do not access directly, instead always use cea_mode_for_vic().
|
||||
*/
|
||||
static const struct drm_display_mode edid_cea_modes[] = {
|
||||
/* 0 - dummy, VICs start at 1 */
|
||||
{ },
|
||||
static const struct drm_display_mode edid_cea_modes_1[] = {
|
||||
/* 1 - 640x480@60Hz 4:3 */
|
||||
{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
|
||||
752, 800, 0, 480, 490, 492, 525, 0,
|
||||
@ -1380,6 +1377,149 @@ static const struct drm_display_mode edid_cea_modes[] = {
|
||||
.vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
|
||||
};
|
||||
|
||||
/*
|
||||
* From CEA/CTA-861 spec.
|
||||
*
|
||||
* Do not access directly, instead always use cea_mode_for_vic().
|
||||
*/
|
||||
static const struct drm_display_mode edid_cea_modes_193[] = {
|
||||
/* 193 - 5120x2160@120Hz 64:27 */
|
||||
{ DRM_MODE("5120x2160", DRM_MODE_TYPE_DRIVER, 1485000, 5120, 5284,
|
||||
5372, 5500, 0, 2160, 2168, 2178, 2250, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
|
||||
/* 194 - 7680x4320@24Hz 16:9 */
|
||||
{ DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 1188000, 7680, 10232,
|
||||
10408, 11000, 0, 4320, 4336, 4356, 4500, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
|
||||
/* 195 - 7680x4320@25Hz 16:9 */
|
||||
{ DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 1188000, 7680, 10032,
|
||||
10208, 10800, 0, 4320, 4336, 4356, 4400, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
|
||||
/* 196 - 7680x4320@30Hz 16:9 */
|
||||
{ DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 1188000, 7680, 8232,
|
||||
8408, 9000, 0, 4320, 4336, 4356, 4400, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
|
||||
/* 197 - 7680x4320@48Hz 16:9 */
|
||||
{ DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 2376000, 7680, 10232,
|
||||
10408, 11000, 0, 4320, 4336, 4356, 4500, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 48, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
|
||||
/* 198 - 7680x4320@50Hz 16:9 */
|
||||
{ DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 2376000, 7680, 10032,
|
||||
10208, 10800, 0, 4320, 4336, 4356, 4400, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
|
||||
/* 199 - 7680x4320@60Hz 16:9 */
|
||||
{ DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 2376000, 7680, 8232,
|
||||
8408, 9000, 0, 4320, 4336, 4356, 4400, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
|
||||
/* 200 - 7680x4320@100Hz 16:9 */
|
||||
{ DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 4752000, 7680, 9792,
|
||||
9968, 10560, 0, 4320, 4336, 4356, 4500, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
|
||||
/* 201 - 7680x4320@120Hz 16:9 */
|
||||
{ DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 4752000, 7680, 8032,
|
||||
8208, 8800, 0, 4320, 4336, 4356, 4500, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
|
||||
/* 202 - 7680x4320@24Hz 64:27 */
|
||||
{ DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 1188000, 7680, 10232,
|
||||
10408, 11000, 0, 4320, 4336, 4356, 4500, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
|
||||
/* 203 - 7680x4320@25Hz 64:27 */
|
||||
{ DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 1188000, 7680, 10032,
|
||||
10208, 10800, 0, 4320, 4336, 4356, 4400, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
|
||||
/* 204 - 7680x4320@30Hz 64:27 */
|
||||
{ DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 1188000, 7680, 8232,
|
||||
8408, 9000, 0, 4320, 4336, 4356, 4400, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
|
||||
/* 205 - 7680x4320@48Hz 64:27 */
|
||||
{ DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 2376000, 7680, 10232,
|
||||
10408, 11000, 0, 4320, 4336, 4356, 4500, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 48, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
|
||||
/* 206 - 7680x4320@50Hz 64:27 */
|
||||
{ DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 2376000, 7680, 10032,
|
||||
10208, 10800, 0, 4320, 4336, 4356, 4400, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
|
||||
/* 207 - 7680x4320@60Hz 64:27 */
|
||||
{ DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 2376000, 7680, 8232,
|
||||
8408, 9000, 0, 4320, 4336, 4356, 4400, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
|
||||
/* 208 - 7680x4320@100Hz 64:27 */
|
||||
{ DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 4752000, 7680, 9792,
|
||||
9968, 10560, 0, 4320, 4336, 4356, 4500, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
|
||||
/* 209 - 7680x4320@120Hz 64:27 */
|
||||
{ DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 4752000, 7680, 8032,
|
||||
8208, 8800, 0, 4320, 4336, 4356, 4500, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
|
||||
/* 210 - 10240x4320@24Hz 64:27 */
|
||||
{ DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 1485000, 10240, 11732,
|
||||
11908, 12500, 0, 4320, 4336, 4356, 4950, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
|
||||
/* 211 - 10240x4320@25Hz 64:27 */
|
||||
{ DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 1485000, 10240, 12732,
|
||||
12908, 13500, 0, 4320, 4336, 4356, 4400, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
|
||||
/* 212 - 10240x4320@30Hz 64:27 */
|
||||
{ DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 1485000, 10240, 10528,
|
||||
10704, 11000, 0, 4320, 4336, 4356, 4500, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
|
||||
/* 213 - 10240x4320@48Hz 64:27 */
|
||||
{ DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 2970000, 10240, 11732,
|
||||
11908, 12500, 0, 4320, 4336, 4356, 4950, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 48, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
|
||||
/* 214 - 10240x4320@50Hz 64:27 */
|
||||
{ DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 2970000, 10240, 12732,
|
||||
12908, 13500, 0, 4320, 4336, 4356, 4400, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
|
||||
/* 215 - 10240x4320@60Hz 64:27 */
|
||||
{ DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 2970000, 10240, 10528,
|
||||
10704, 11000, 0, 4320, 4336, 4356, 4500, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
|
||||
/* 216 - 10240x4320@100Hz 64:27 */
|
||||
{ DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 5940000, 10240, 12432,
|
||||
12608, 13200, 0, 4320, 4336, 4356, 4500, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
|
||||
/* 217 - 10240x4320@120Hz 64:27 */
|
||||
{ DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 5940000, 10240, 10528,
|
||||
10704, 11000, 0, 4320, 4336, 4356, 4500, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
|
||||
/* 218 - 4096x2160@100Hz 256:135 */
|
||||
{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 1188000, 4096, 4896,
|
||||
4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
|
||||
/* 219 - 4096x2160@120Hz 256:135 */
|
||||
{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 1188000, 4096, 4184,
|
||||
4272, 4400, 0, 2160, 2168, 2178, 2250, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
|
||||
};
|
||||
|
||||
/*
|
||||
* HDMI 1.4 4k modes. Index using the VIC.
|
||||
*/
|
||||
@ -3071,6 +3211,30 @@ static u8 *drm_find_cea_extension(const struct edid *edid)
|
||||
return cea;
|
||||
}
|
||||
|
||||
static const struct drm_display_mode *cea_mode_for_vic(u8 vic)
|
||||
{
|
||||
BUILD_BUG_ON(1 + ARRAY_SIZE(edid_cea_modes_1) - 1 != 127);
|
||||
BUILD_BUG_ON(193 + ARRAY_SIZE(edid_cea_modes_193) - 1 != 219);
|
||||
|
||||
if (vic >= 1 && vic < 1 + ARRAY_SIZE(edid_cea_modes_1))
|
||||
return &edid_cea_modes_1[vic - 1];
|
||||
if (vic >= 193 && vic < 193 + ARRAY_SIZE(edid_cea_modes_193))
|
||||
return &edid_cea_modes_193[vic - 193];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static u8 cea_num_vics(void)
|
||||
{
|
||||
return 193 + ARRAY_SIZE(edid_cea_modes_193);
|
||||
}
|
||||
|
||||
static u8 cea_next_vic(u8 vic)
|
||||
{
|
||||
if (++vic == 1 + ARRAY_SIZE(edid_cea_modes_1))
|
||||
vic = 193;
|
||||
return vic;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the alternate clock for the CEA mode
|
||||
* (60Hz vs. 59.94Hz etc.)
|
||||
@ -3108,14 +3272,14 @@ cea_mode_alternate_timings(u8 vic, struct drm_display_mode *mode)
|
||||
* get the other variants by simply increasing the
|
||||
* vertical front porch length.
|
||||
*/
|
||||
BUILD_BUG_ON(edid_cea_modes[8].vtotal != 262 ||
|
||||
edid_cea_modes[9].vtotal != 262 ||
|
||||
edid_cea_modes[12].vtotal != 262 ||
|
||||
edid_cea_modes[13].vtotal != 262 ||
|
||||
edid_cea_modes[23].vtotal != 312 ||
|
||||
edid_cea_modes[24].vtotal != 312 ||
|
||||
edid_cea_modes[27].vtotal != 312 ||
|
||||
edid_cea_modes[28].vtotal != 312);
|
||||
BUILD_BUG_ON(cea_mode_for_vic(8)->vtotal != 262 ||
|
||||
cea_mode_for_vic(9)->vtotal != 262 ||
|
||||
cea_mode_for_vic(12)->vtotal != 262 ||
|
||||
cea_mode_for_vic(13)->vtotal != 262 ||
|
||||
cea_mode_for_vic(23)->vtotal != 312 ||
|
||||
cea_mode_for_vic(24)->vtotal != 312 ||
|
||||
cea_mode_for_vic(27)->vtotal != 312 ||
|
||||
cea_mode_for_vic(28)->vtotal != 312);
|
||||
|
||||
if (((vic == 8 || vic == 9 ||
|
||||
vic == 12 || vic == 13) && mode->vtotal < 263) ||
|
||||
@ -3143,8 +3307,8 @@ static u8 drm_match_cea_mode_clock_tolerance(const struct drm_display_mode *to_m
|
||||
if (to_match->picture_aspect_ratio)
|
||||
match_flags |= DRM_MODE_MATCH_ASPECT_RATIO;
|
||||
|
||||
for (vic = 1; vic < ARRAY_SIZE(edid_cea_modes); vic++) {
|
||||
struct drm_display_mode cea_mode = edid_cea_modes[vic];
|
||||
for (vic = 1; vic < cea_num_vics(); vic = cea_next_vic(vic)) {
|
||||
struct drm_display_mode cea_mode = *cea_mode_for_vic(vic);
|
||||
unsigned int clock1, clock2;
|
||||
|
||||
/* Check both 60Hz and 59.94Hz */
|
||||
@ -3182,8 +3346,8 @@ u8 drm_match_cea_mode(const struct drm_display_mode *to_match)
|
||||
if (to_match->picture_aspect_ratio)
|
||||
match_flags |= DRM_MODE_MATCH_ASPECT_RATIO;
|
||||
|
||||
for (vic = 1; vic < ARRAY_SIZE(edid_cea_modes); vic++) {
|
||||
struct drm_display_mode cea_mode = edid_cea_modes[vic];
|
||||
for (vic = 1; vic < cea_num_vics(); vic = cea_next_vic(vic)) {
|
||||
struct drm_display_mode cea_mode = *cea_mode_for_vic(vic);
|
||||
unsigned int clock1, clock2;
|
||||
|
||||
/* Check both 60Hz and 59.94Hz */
|
||||
@ -3206,12 +3370,17 @@ EXPORT_SYMBOL(drm_match_cea_mode);
|
||||
|
||||
static bool drm_valid_cea_vic(u8 vic)
|
||||
{
|
||||
return vic > 0 && vic < ARRAY_SIZE(edid_cea_modes);
|
||||
return cea_mode_for_vic(vic) != NULL;
|
||||
}
|
||||
|
||||
static enum hdmi_picture_aspect drm_get_cea_aspect_ratio(const u8 video_code)
|
||||
{
|
||||
return edid_cea_modes[video_code].picture_aspect_ratio;
|
||||
const struct drm_display_mode *mode = cea_mode_for_vic(video_code);
|
||||
|
||||
if (mode)
|
||||
return mode->picture_aspect_ratio;
|
||||
|
||||
return HDMI_PICTURE_ASPECT_NONE;
|
||||
}
|
||||
|
||||
static enum hdmi_picture_aspect drm_get_hdmi_aspect_ratio(const u8 video_code)
|
||||
@ -3323,7 +3492,7 @@ add_alternate_cea_modes(struct drm_connector *connector, struct edid *edid)
|
||||
unsigned int clock1, clock2;
|
||||
|
||||
if (drm_valid_cea_vic(vic)) {
|
||||
cea_mode = &edid_cea_modes[vic];
|
||||
cea_mode = cea_mode_for_vic(vic);
|
||||
clock2 = cea_mode_alternate_clock(cea_mode);
|
||||
} else {
|
||||
vic = drm_match_hdmi_mode(mode);
|
||||
@ -3398,7 +3567,7 @@ drm_display_mode_from_vic_index(struct drm_connector *connector,
|
||||
if (!drm_valid_cea_vic(vic))
|
||||
return NULL;
|
||||
|
||||
newmode = drm_mode_duplicate(dev, &edid_cea_modes[vic]);
|
||||
newmode = drm_mode_duplicate(dev, cea_mode_for_vic(vic));
|
||||
if (!newmode)
|
||||
return NULL;
|
||||
|
||||
@ -3432,7 +3601,7 @@ static int do_y420vdb_modes(struct drm_connector *connector,
|
||||
if (!drm_valid_cea_vic(vic))
|
||||
continue;
|
||||
|
||||
newmode = drm_mode_duplicate(dev, &edid_cea_modes[vic]);
|
||||
newmode = drm_mode_duplicate(dev, cea_mode_for_vic(vic));
|
||||
if (!newmode)
|
||||
break;
|
||||
bitmap_set(hdmi->y420_vdb_modes, vic, 1);
|
||||
@ -4001,7 +4170,7 @@ static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode)
|
||||
vic = drm_match_cea_mode_clock_tolerance(mode, 5);
|
||||
if (drm_valid_cea_vic(vic)) {
|
||||
type = "CEA";
|
||||
cea_mode = &edid_cea_modes[vic];
|
||||
cea_mode = cea_mode_for_vic(vic);
|
||||
clock1 = cea_mode->clock;
|
||||
clock2 = cea_mode_alternate_clock(cea_mode);
|
||||
} else {
|
||||
@ -4577,7 +4746,7 @@ static void drm_parse_hdmi_forum_vsdb(struct drm_connector *connector,
|
||||
if (scdc->supported) {
|
||||
scdc->scrambling.supported = true;
|
||||
|
||||
/* Few sinks support scrambling for cloks < 340M */
|
||||
/* Few sinks support scrambling for clocks < 340M */
|
||||
if ((hf_vsdb[6] & 0x8))
|
||||
scdc->scrambling.low_rates = true;
|
||||
}
|
||||
|
@ -191,6 +191,7 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
|
||||
{
|
||||
struct drm_fb_helper *helper = info->par;
|
||||
struct drm_client_dev *client = &helper->client;
|
||||
struct drm_device *dev = helper->dev;
|
||||
struct drm_crtc *crtc;
|
||||
const struct drm_crtc_helper_funcs *funcs;
|
||||
struct drm_mode_set *mode_set;
|
||||
@ -209,7 +210,7 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
|
||||
continue;
|
||||
|
||||
if (!fb) {
|
||||
DRM_ERROR("no fb to restore??\n");
|
||||
drm_err(dev, "no fb to restore?\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1248,12 +1249,13 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
|
||||
{
|
||||
struct drm_fb_helper *fb_helper = info->par;
|
||||
struct drm_framebuffer *fb = fb_helper->fb;
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
|
||||
if (in_dbg_master())
|
||||
return -EINVAL;
|
||||
|
||||
if (var->pixclock != 0) {
|
||||
DRM_DEBUG("fbdev emulation doesn't support changing the pixel clock, value of pixclock is ignored\n");
|
||||
drm_dbg_kms(dev, "fbdev emulation doesn't support changing the pixel clock, value of pixclock is ignored\n");
|
||||
var->pixclock = 0;
|
||||
}
|
||||
|
||||
@ -1268,7 +1270,7 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
|
||||
if (var->bits_per_pixel != fb->format->cpp[0] * 8 ||
|
||||
var->xres > fb->width || var->yres > fb->height ||
|
||||
var->xres_virtual > fb->width || var->yres_virtual > fb->height) {
|
||||
DRM_DEBUG("fb requested width/height/bpp can't fit in current fb "
|
||||
drm_dbg_kms(dev, "fb requested width/height/bpp can't fit in current fb "
|
||||
"request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n",
|
||||
var->xres, var->yres, var->bits_per_pixel,
|
||||
var->xres_virtual, var->yres_virtual,
|
||||
@ -1295,7 +1297,7 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
|
||||
* so reject all pixel format changing requests.
|
||||
*/
|
||||
if (!drm_fb_pixel_format_equal(var, &info->var)) {
|
||||
DRM_DEBUG("fbdev emulation doesn't support changing the pixel format\n");
|
||||
drm_dbg_kms(dev, "fbdev emulation doesn't support changing the pixel format\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1320,7 +1322,7 @@ int drm_fb_helper_set_par(struct fb_info *info)
|
||||
return -EBUSY;
|
||||
|
||||
if (var->pixclock != 0) {
|
||||
DRM_ERROR("PIXEL CLOCK SET\n");
|
||||
drm_err(fb_helper->dev, "PIXEL CLOCK SET\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1430,6 +1432,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
|
||||
int preferred_bpp)
|
||||
{
|
||||
struct drm_client_dev *client = &fb_helper->client;
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
int ret = 0;
|
||||
int crtc_count = 0;
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
@ -1493,7 +1496,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
|
||||
struct drm_plane *plane = crtc->primary;
|
||||
int j;
|
||||
|
||||
DRM_DEBUG("test CRTC %u primary plane\n", drm_crtc_index(crtc));
|
||||
drm_dbg_kms(dev, "test CRTC %u primary plane\n", drm_crtc_index(crtc));
|
||||
|
||||
for (j = 0; j < plane->format_count; j++) {
|
||||
const struct drm_format_info *fmt;
|
||||
@ -1526,7 +1529,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
|
||||
}
|
||||
}
|
||||
if (sizes.surface_depth != best_depth && best_depth) {
|
||||
DRM_INFO("requested bpp %d, scaled depth down to %d",
|
||||
drm_info(dev, "requested bpp %d, scaled depth down to %d",
|
||||
sizes.surface_bpp, best_depth);
|
||||
sizes.surface_depth = best_depth;
|
||||
}
|
||||
@ -1574,7 +1577,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
|
||||
mutex_unlock(&client->modeset_mutex);
|
||||
|
||||
if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) {
|
||||
DRM_INFO("Cannot find any crtc or sizes\n");
|
||||
drm_info(dev, "Cannot find any crtc or sizes\n");
|
||||
|
||||
/* First time: disable all crtc's.. */
|
||||
if (!fb_helper->deferred_setup)
|
||||
@ -1889,7 +1892,7 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
|
||||
|
||||
drm_master_internal_release(fb_helper->dev);
|
||||
|
||||
DRM_DEBUG_KMS("\n");
|
||||
drm_dbg_kms(fb_helper->dev, "\n");
|
||||
|
||||
drm_client_modeset_probe(&fb_helper->client, fb_helper->fb->width, fb_helper->fb->height);
|
||||
drm_setup_crtcs_fb(fb_helper);
|
||||
@ -2026,15 +2029,16 @@ static int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
|
||||
struct drm_fb_helper_surface_size *sizes)
|
||||
{
|
||||
struct drm_client_dev *client = &fb_helper->client;
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
struct drm_client_buffer *buffer;
|
||||
struct drm_framebuffer *fb;
|
||||
struct fb_info *fbi;
|
||||
u32 format;
|
||||
void *vaddr;
|
||||
|
||||
DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d)\n",
|
||||
sizes->surface_width, sizes->surface_height,
|
||||
sizes->surface_bpp);
|
||||
drm_dbg_kms(dev, "surface width(%d), height(%d) and bpp(%d)\n",
|
||||
sizes->surface_width, sizes->surface_height,
|
||||
sizes->surface_bpp);
|
||||
|
||||
format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth);
|
||||
buffer = drm_client_framebuffer_create(client, sizes->surface_width,
|
||||
@ -2118,7 +2122,7 @@ static int drm_fbdev_client_hotplug(struct drm_client_dev *client)
|
||||
return drm_fb_helper_hotplug_event(dev->fb_helper);
|
||||
|
||||
if (!dev->mode_config.num_connector) {
|
||||
DRM_DEV_DEBUG(dev->dev, "No connectors found, will not create framebuffer!\n");
|
||||
drm_dbg_kms(dev, "No connectors found, will not create framebuffer!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2143,7 +2147,7 @@ static int drm_fbdev_client_hotplug(struct drm_client_dev *client)
|
||||
fb_helper->dev = NULL;
|
||||
fb_helper->fbdev = NULL;
|
||||
|
||||
DRM_DEV_ERROR(dev->dev, "fbdev: Failed to setup generic emulation (ret=%d)\n", ret);
|
||||
drm_err(dev, "fbdev: Failed to setup generic emulation (ret=%d)\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -2200,7 +2204,7 @@ int drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
|
||||
ret = drm_client_init(dev, &fb_helper->client, "fbdev", &drm_fbdev_client_funcs);
|
||||
if (ret) {
|
||||
kfree(fb_helper);
|
||||
DRM_DEV_ERROR(dev->dev, "Failed to register client: %d\n", ret);
|
||||
drm_err(dev, "Failed to register client: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2212,7 +2216,7 @@ int drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
|
||||
|
||||
ret = drm_fbdev_client_hotplug(&fb_helper->client);
|
||||
if (ret)
|
||||
DRM_DEV_DEBUG(dev->dev, "client hotplug ret=%d\n", ret);
|
||||
drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);
|
||||
|
||||
drm_client_register(&fb_helper->client);
|
||||
|
||||
|
@ -74,8 +74,7 @@ drm_gem_fb_alloc(struct drm_device *dev,
|
||||
|
||||
ret = drm_framebuffer_init(dev, fb, funcs);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dev->dev, "Failed to init framebuffer: %d\n",
|
||||
ret);
|
||||
drm_err(dev, "Failed to init framebuffer: %d\n", ret);
|
||||
kfree(fb);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
@ -160,7 +159,7 @@ drm_gem_fb_create_with_funcs(struct drm_device *dev, struct drm_file *file,
|
||||
|
||||
objs[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]);
|
||||
if (!objs[i]) {
|
||||
DRM_DEBUG_KMS("Failed to lookup GEM object\n");
|
||||
drm_dbg_kms(dev, "Failed to lookup GEM object\n");
|
||||
ret = -ENOENT;
|
||||
goto err_gem_object_put;
|
||||
}
|
||||
|
@ -1568,33 +1568,76 @@ static int drm_mode_parse_cmdline_res_mode(const char *str, unsigned int length,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drm_mode_parse_cmdline_options(char *str, size_t len,
|
||||
static int drm_mode_parse_cmdline_int(const char *delim, unsigned int *int_ret)
|
||||
{
|
||||
const char *value;
|
||||
char *endp;
|
||||
|
||||
/*
|
||||
* delim must point to the '=', otherwise it is a syntax error and
|
||||
* if delim points to the terminating zero, then delim + 1 wil point
|
||||
* past the end of the string.
|
||||
*/
|
||||
if (*delim != '=')
|
||||
return -EINVAL;
|
||||
|
||||
value = delim + 1;
|
||||
*int_ret = simple_strtol(value, &endp, 10);
|
||||
|
||||
/* Make sure we have parsed something */
|
||||
if (endp == value)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drm_mode_parse_panel_orientation(const char *delim,
|
||||
struct drm_cmdline_mode *mode)
|
||||
{
|
||||
const char *value;
|
||||
|
||||
if (*delim != '=')
|
||||
return -EINVAL;
|
||||
|
||||
value = delim + 1;
|
||||
delim = strchr(value, ',');
|
||||
if (!delim)
|
||||
delim = value + strlen(value);
|
||||
|
||||
if (!strncmp(value, "normal", delim - value))
|
||||
mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL;
|
||||
else if (!strncmp(value, "upside_down", delim - value))
|
||||
mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP;
|
||||
else if (!strncmp(value, "left_side_up", delim - value))
|
||||
mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP;
|
||||
else if (!strncmp(value, "right_side_up", delim - value))
|
||||
mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drm_mode_parse_cmdline_options(const char *str,
|
||||
bool freestanding,
|
||||
const struct drm_connector *connector,
|
||||
struct drm_cmdline_mode *mode)
|
||||
{
|
||||
unsigned int rotation = 0;
|
||||
char *sep = str;
|
||||
unsigned int deg, margin, rotation = 0;
|
||||
const char *delim, *option, *sep;
|
||||
|
||||
while ((sep = strchr(sep, ','))) {
|
||||
char *delim, *option;
|
||||
|
||||
option = sep + 1;
|
||||
option = str;
|
||||
do {
|
||||
delim = strchr(option, '=');
|
||||
if (!delim) {
|
||||
delim = strchr(option, ',');
|
||||
|
||||
if (!delim)
|
||||
delim = str + len;
|
||||
delim = option + strlen(option);
|
||||
}
|
||||
|
||||
if (!strncmp(option, "rotate", delim - option)) {
|
||||
const char *value = delim + 1;
|
||||
unsigned int deg;
|
||||
|
||||
deg = simple_strtol(value, &sep, 10);
|
||||
|
||||
/* Make sure we have parsed something */
|
||||
if (sep == value)
|
||||
if (drm_mode_parse_cmdline_int(delim, °))
|
||||
return -EINVAL;
|
||||
|
||||
switch (deg) {
|
||||
@ -1619,58 +1662,40 @@ static int drm_mode_parse_cmdline_options(char *str, size_t len,
|
||||
}
|
||||
} else if (!strncmp(option, "reflect_x", delim - option)) {
|
||||
rotation |= DRM_MODE_REFLECT_X;
|
||||
sep = delim;
|
||||
} else if (!strncmp(option, "reflect_y", delim - option)) {
|
||||
rotation |= DRM_MODE_REFLECT_Y;
|
||||
sep = delim;
|
||||
} else if (!strncmp(option, "margin_right", delim - option)) {
|
||||
const char *value = delim + 1;
|
||||
unsigned int margin;
|
||||
|
||||
margin = simple_strtol(value, &sep, 10);
|
||||
|
||||
/* Make sure we have parsed something */
|
||||
if (sep == value)
|
||||
if (drm_mode_parse_cmdline_int(delim, &margin))
|
||||
return -EINVAL;
|
||||
|
||||
mode->tv_margins.right = margin;
|
||||
} else if (!strncmp(option, "margin_left", delim - option)) {
|
||||
const char *value = delim + 1;
|
||||
unsigned int margin;
|
||||
|
||||
margin = simple_strtol(value, &sep, 10);
|
||||
|
||||
/* Make sure we have parsed something */
|
||||
if (sep == value)
|
||||
if (drm_mode_parse_cmdline_int(delim, &margin))
|
||||
return -EINVAL;
|
||||
|
||||
mode->tv_margins.left = margin;
|
||||
} else if (!strncmp(option, "margin_top", delim - option)) {
|
||||
const char *value = delim + 1;
|
||||
unsigned int margin;
|
||||
|
||||
margin = simple_strtol(value, &sep, 10);
|
||||
|
||||
/* Make sure we have parsed something */
|
||||
if (sep == value)
|
||||
if (drm_mode_parse_cmdline_int(delim, &margin))
|
||||
return -EINVAL;
|
||||
|
||||
mode->tv_margins.top = margin;
|
||||
} else if (!strncmp(option, "margin_bottom", delim - option)) {
|
||||
const char *value = delim + 1;
|
||||
unsigned int margin;
|
||||
|
||||
margin = simple_strtol(value, &sep, 10);
|
||||
|
||||
/* Make sure we have parsed something */
|
||||
if (sep == value)
|
||||
if (drm_mode_parse_cmdline_int(delim, &margin))
|
||||
return -EINVAL;
|
||||
|
||||
mode->tv_margins.bottom = margin;
|
||||
} else if (!strncmp(option, "panel_orientation", delim - option)) {
|
||||
if (drm_mode_parse_panel_orientation(delim, mode))
|
||||
return -EINVAL;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
sep = strchr(delim, ',');
|
||||
option = sep + 1;
|
||||
} while (sep);
|
||||
|
||||
if (rotation && freestanding)
|
||||
return -EINVAL;
|
||||
|
||||
mode->rotation_reflection = rotation;
|
||||
|
||||
@ -1682,17 +1707,6 @@ static const char * const drm_named_modes_whitelist[] = {
|
||||
"PAL",
|
||||
};
|
||||
|
||||
static bool drm_named_mode_is_in_whitelist(const char *mode, unsigned int size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++)
|
||||
if (!strncmp(mode, drm_named_modes_whitelist[i], size))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_mode_parse_command_line_for_connector - parse command line modeline for connector
|
||||
* @mode_option: optional per connector mode option
|
||||
@ -1723,72 +1737,30 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
|
||||
struct drm_cmdline_mode *mode)
|
||||
{
|
||||
const char *name;
|
||||
bool named_mode = false, parse_extras = false;
|
||||
bool freestanding = false, parse_extras = false;
|
||||
unsigned int bpp_off = 0, refresh_off = 0, options_off = 0;
|
||||
unsigned int mode_end = 0;
|
||||
char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
|
||||
char *options_ptr = NULL;
|
||||
const char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
|
||||
const char *options_ptr = NULL;
|
||||
char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
|
||||
int ret;
|
||||
int i, len, ret;
|
||||
|
||||
memset(mode, 0, sizeof(*mode));
|
||||
mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
|
||||
|
||||
#ifdef CONFIG_FB
|
||||
if (!mode_option)
|
||||
mode_option = fb_mode_option;
|
||||
#endif
|
||||
|
||||
if (!mode_option) {
|
||||
mode->specified = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
name = mode_option;
|
||||
|
||||
/*
|
||||
* This is a bit convoluted. To differentiate between the
|
||||
* named modes and poorly formatted resolutions, we need a
|
||||
* bunch of things:
|
||||
* - We need to make sure that the first character (which
|
||||
* would be our resolution in X) is a digit.
|
||||
* - If not, then it's either a named mode or a force on/off.
|
||||
* To distinguish between the two, we need to run the
|
||||
* extra parsing function, and if not, then we consider it
|
||||
* a named mode.
|
||||
*
|
||||
* If this isn't enough, we should add more heuristics here,
|
||||
* and matching unit-tests.
|
||||
*/
|
||||
if (!isdigit(name[0]) && name[0] != 'x') {
|
||||
unsigned int namelen = strlen(name);
|
||||
|
||||
/*
|
||||
* Only the force on/off options can be in that case,
|
||||
* and they all take a single character.
|
||||
*/
|
||||
if (namelen == 1) {
|
||||
ret = drm_mode_parse_cmdline_extra(name, namelen, true,
|
||||
connector, mode);
|
||||
if (!ret)
|
||||
return true;
|
||||
}
|
||||
|
||||
named_mode = true;
|
||||
}
|
||||
|
||||
/* Try to locate the bpp and refresh specifiers, if any */
|
||||
bpp_ptr = strchr(name, '-');
|
||||
if (bpp_ptr) {
|
||||
if (bpp_ptr)
|
||||
bpp_off = bpp_ptr - name;
|
||||
mode->bpp_specified = true;
|
||||
}
|
||||
|
||||
refresh_ptr = strchr(name, '@');
|
||||
if (refresh_ptr) {
|
||||
if (named_mode)
|
||||
return false;
|
||||
|
||||
if (refresh_ptr)
|
||||
refresh_off = refresh_ptr - name;
|
||||
mode->refresh_specified = true;
|
||||
}
|
||||
|
||||
/* Locate the start of named options */
|
||||
options_ptr = strchr(name, ',');
|
||||
@ -1802,33 +1774,58 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
|
||||
mode_end = refresh_off;
|
||||
} else if (options_ptr) {
|
||||
mode_end = options_off;
|
||||
parse_extras = true;
|
||||
} else {
|
||||
mode_end = strlen(name);
|
||||
parse_extras = true;
|
||||
}
|
||||
|
||||
if (named_mode) {
|
||||
if (mode_end + 1 > DRM_DISPLAY_MODE_LEN)
|
||||
return false;
|
||||
/* First check for a named mode */
|
||||
for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) {
|
||||
ret = str_has_prefix(name, drm_named_modes_whitelist[i]);
|
||||
if (ret == mode_end) {
|
||||
if (refresh_ptr)
|
||||
return false; /* named + refresh is invalid */
|
||||
|
||||
if (!drm_named_mode_is_in_whitelist(name, mode_end))
|
||||
return false;
|
||||
strcpy(mode->name, drm_named_modes_whitelist[i]);
|
||||
mode->specified = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
strscpy(mode->name, name, mode_end + 1);
|
||||
} else {
|
||||
/* No named mode? Check for a normal mode argument, e.g. 1024x768 */
|
||||
if (!mode->specified && isdigit(name[0])) {
|
||||
ret = drm_mode_parse_cmdline_res_mode(name, mode_end,
|
||||
parse_extras,
|
||||
connector,
|
||||
mode);
|
||||
if (ret)
|
||||
return false;
|
||||
|
||||
mode->specified = true;
|
||||
}
|
||||
|
||||
/* No mode? Check for freestanding extras and/or options */
|
||||
if (!mode->specified) {
|
||||
unsigned int len = strlen(mode_option);
|
||||
|
||||
if (bpp_ptr || refresh_ptr)
|
||||
return false; /* syntax error */
|
||||
|
||||
if (len == 1 || (len >= 2 && mode_option[1] == ','))
|
||||
extra_ptr = mode_option;
|
||||
else
|
||||
options_ptr = mode_option - 1;
|
||||
|
||||
freestanding = true;
|
||||
}
|
||||
mode->specified = true;
|
||||
|
||||
if (bpp_ptr) {
|
||||
ret = drm_mode_parse_cmdline_bpp(bpp_ptr, &bpp_end_ptr, mode);
|
||||
if (ret)
|
||||
return false;
|
||||
|
||||
mode->bpp_specified = true;
|
||||
}
|
||||
|
||||
if (refresh_ptr) {
|
||||
@ -1836,6 +1833,8 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
|
||||
&refresh_end_ptr, mode);
|
||||
if (ret)
|
||||
return false;
|
||||
|
||||
mode->refresh_specified = true;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1849,20 +1848,21 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
|
||||
else if (refresh_ptr)
|
||||
extra_ptr = refresh_end_ptr;
|
||||
|
||||
if (extra_ptr &&
|
||||
extra_ptr != options_ptr) {
|
||||
int len = strlen(name) - (extra_ptr - name);
|
||||
if (extra_ptr) {
|
||||
if (options_ptr)
|
||||
len = options_ptr - extra_ptr;
|
||||
else
|
||||
len = strlen(extra_ptr);
|
||||
|
||||
ret = drm_mode_parse_cmdline_extra(extra_ptr, len, false,
|
||||
ret = drm_mode_parse_cmdline_extra(extra_ptr, len, freestanding,
|
||||
connector, mode);
|
||||
if (ret)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (options_ptr) {
|
||||
int len = strlen(name) - (options_ptr - name);
|
||||
|
||||
ret = drm_mode_parse_cmdline_options(options_ptr, len,
|
||||
ret = drm_mode_parse_cmdline_options(options_ptr + 1,
|
||||
freestanding,
|
||||
connector, mode);
|
||||
if (ret)
|
||||
return false;
|
||||
|
@ -302,7 +302,7 @@ struct drm_panel *of_drm_find_panel(const struct device_node *np)
|
||||
EXPORT_SYMBOL(of_drm_find_panel);
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
|
||||
#if IS_REACHABLE(CONFIG_BACKLIGHT_CLASS_DEVICE)
|
||||
/**
|
||||
* drm_panel_of_backlight - use backlight device node for backlight
|
||||
* @panel: DRM panel
|
||||
|
@ -113,7 +113,7 @@ static void submit_unlock_object(struct etnaviv_gem_submit *submit, int i)
|
||||
if (submit->bos[i].flags & BO_LOCKED) {
|
||||
struct drm_gem_object *obj = &submit->bos[i].obj->base;
|
||||
|
||||
ww_mutex_unlock(&obj->resv->lock);
|
||||
dma_resv_unlock(obj->resv);
|
||||
submit->bos[i].flags &= ~BO_LOCKED;
|
||||
}
|
||||
}
|
||||
@ -133,8 +133,7 @@ static int submit_lock_objects(struct etnaviv_gem_submit *submit,
|
||||
contended = i;
|
||||
|
||||
if (!(submit->bos[i].flags & BO_LOCKED)) {
|
||||
ret = ww_mutex_lock_interruptible(&obj->resv->lock,
|
||||
ticket);
|
||||
ret = dma_resv_lock_interruptible(obj->resv, ticket);
|
||||
if (ret == -EALREADY)
|
||||
DRM_ERROR("BO at index %u already on submit list\n",
|
||||
i);
|
||||
@ -161,8 +160,7 @@ static int submit_lock_objects(struct etnaviv_gem_submit *submit,
|
||||
obj = &submit->bos[contended].obj->base;
|
||||
|
||||
/* we lost out in a seqno race, lock and retry.. */
|
||||
ret = ww_mutex_lock_slow_interruptible(&obj->resv->lock,
|
||||
ticket);
|
||||
ret = dma_resv_lock_slow_interruptible(obj->resv, ticket);
|
||||
if (!ret) {
|
||||
submit->bos[contended].flags |= BO_LOCKED;
|
||||
slow_locked = contended;
|
||||
|
@ -228,8 +228,8 @@ static void psbfb_copyarea_accel(struct fb_info *info,
|
||||
{
|
||||
struct drm_fb_helper *fb_helper = info->par;
|
||||
struct drm_framebuffer *fb = fb_helper->fb;
|
||||
struct drm_device *dev = fb->dev;
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
struct drm_device *dev;
|
||||
struct drm_psb_private *dev_priv;
|
||||
uint32_t offset;
|
||||
uint32_t stride;
|
||||
uint32_t src_format;
|
||||
@ -238,6 +238,8 @@ static void psbfb_copyarea_accel(struct fb_info *info,
|
||||
if (!fb)
|
||||
return;
|
||||
|
||||
dev = fb->dev;
|
||||
dev_priv = dev->dev_private;
|
||||
offset = to_gtt_range(fb->obj[0])->offset;
|
||||
stride = fb->pitches[0];
|
||||
|
||||
|
@ -388,13 +388,14 @@ void mcde_dsi_te_request(struct mipi_dsi_device *mdsi)
|
||||
static void mcde_dsi_setup_video_mode(struct mcde_dsi *d,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
u8 bpp = mipi_dsi_pixel_format_to_bpp(d->mdsi->format);
|
||||
/* cpp, characters per pixel, number of bytes per pixel */
|
||||
u8 cpp = mipi_dsi_pixel_format_to_bpp(d->mdsi->format) / 8;
|
||||
u64 pclk;
|
||||
u64 bpl;
|
||||
u32 hfp;
|
||||
u32 hbp;
|
||||
u32 hsa;
|
||||
int hfp;
|
||||
int hbp;
|
||||
int hsa;
|
||||
u32 blkline_pck, line_duration;
|
||||
u32 blkeol_pck, blkeol_duration;
|
||||
u32 val;
|
||||
|
||||
val = 0;
|
||||
@ -431,11 +432,21 @@ static void mcde_dsi_setup_video_mode(struct mcde_dsi *d,
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO: TVG could be enabled here */
|
||||
/* TODO: TVG (test video generator) could be enabled here */
|
||||
|
||||
/* Send blanking packet */
|
||||
/*
|
||||
* During vertical blanking: go to LP mode
|
||||
* Like with the EOL setting, if this is not set, the EOL area will be
|
||||
* filled with NULL or blanking packets in the vblank area.
|
||||
* FIXME: some Samsung phones and display panels such as s6e63m0 use
|
||||
* DSI_VID_MAIN_CTL_REG_BLKLINE_MODE_BLANKING here instead,
|
||||
* figure out how to properly configure that from the panel.
|
||||
*/
|
||||
val |= DSI_VID_MAIN_CTL_REG_BLKLINE_MODE_LP_0;
|
||||
/* Send EOL packet */
|
||||
/*
|
||||
* During EOL: go to LP mode. If this is not set, the EOL area will be
|
||||
* filled with NULL or blanking packets.
|
||||
*/
|
||||
val |= DSI_VID_MAIN_CTL_REG_BLKEOL_MODE_LP_0;
|
||||
/* Recovery mode 1 */
|
||||
val |= 1 << DSI_VID_MAIN_CTL_RECOVERY_MODE_SHIFT;
|
||||
@ -443,13 +454,13 @@ static void mcde_dsi_setup_video_mode(struct mcde_dsi *d,
|
||||
writel(val, d->regs + DSI_VID_MAIN_CTL);
|
||||
|
||||
/* Vertical frame parameters are pretty straight-forward */
|
||||
val = mode->vdisplay << DSI_VID_VSIZE_VSA_LENGTH_SHIFT;
|
||||
val = mode->vdisplay << DSI_VID_VSIZE_VACT_LENGTH_SHIFT;
|
||||
/* vertical front porch */
|
||||
val |= (mode->vsync_start - mode->vdisplay)
|
||||
<< DSI_VID_VSIZE_VFP_LENGTH_SHIFT;
|
||||
/* vertical sync active */
|
||||
val |= (mode->vsync_end - mode->vsync_start)
|
||||
<< DSI_VID_VSIZE_VACT_LENGTH_SHIFT;
|
||||
<< DSI_VID_VSIZE_VSA_LENGTH_SHIFT;
|
||||
/* vertical back porch */
|
||||
val |= (mode->vtotal - mode->vsync_end)
|
||||
<< DSI_VID_VSIZE_VBP_LENGTH_SHIFT;
|
||||
@ -457,36 +468,54 @@ static void mcde_dsi_setup_video_mode(struct mcde_dsi *d,
|
||||
|
||||
/*
|
||||
* Horizontal frame parameters:
|
||||
* horizontal resolution is given in pixels and must be re-calculated
|
||||
* into bytes since this is what the hardware expects.
|
||||
* horizontal resolution is given in pixels but must be re-calculated
|
||||
* into bytes since this is what the hardware expects, these registers
|
||||
* define the payload size of the packet.
|
||||
*
|
||||
* hfp = horizontal front porch in bytes
|
||||
* hbp = horizontal back porch in bytes
|
||||
* hsa = horizontal sync active in bytes
|
||||
*
|
||||
* 6 + 2 is HFP header + checksum
|
||||
*/
|
||||
hfp = (mode->hsync_start - mode->hdisplay) * bpp - 6 - 2;
|
||||
hfp = (mode->hsync_start - mode->hdisplay) * cpp - 6 - 2;
|
||||
if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {
|
||||
/*
|
||||
* Use sync pulse for sync: explicit HSA time
|
||||
* 6 is HBP header + checksum
|
||||
* 4 is RGB header + checksum
|
||||
*/
|
||||
hbp = (mode->htotal - mode->hsync_end) * bpp - 4 - 6;
|
||||
hbp = (mode->htotal - mode->hsync_end) * cpp - 4 - 6;
|
||||
/*
|
||||
* 6 is HBP header + checksum
|
||||
* 4 is HSW packet bytes
|
||||
* 4 is RGB header + checksum
|
||||
*/
|
||||
hsa = (mode->hsync_end - mode->hsync_start) * bpp - 4 - 4 - 6;
|
||||
hsa = (mode->hsync_end - mode->hsync_start) * cpp - 4 - 4 - 6;
|
||||
} else {
|
||||
/*
|
||||
* HBP includes both back porch and sync
|
||||
* Use event for sync: HBP includes both back porch and sync
|
||||
* 6 is HBP header + checksum
|
||||
* 4 is HSW packet bytes
|
||||
* 4 is RGB header + checksum
|
||||
*/
|
||||
hbp = (mode->htotal - mode->hsync_start) * bpp - 4 - 4 - 6;
|
||||
/* HSA is not considered in this mode and set to 0 */
|
||||
hbp = (mode->htotal - mode->hsync_start) * cpp - 4 - 4 - 6;
|
||||
/* HSA is not present in this mode and set to 0 */
|
||||
hsa = 0;
|
||||
}
|
||||
dev_dbg(d->dev, "hfp: %u, hbp: %u, hsa: %u\n",
|
||||
if (hfp < 0) {
|
||||
dev_info(d->dev, "hfp negative, set to 0\n");
|
||||
hfp = 0;
|
||||
}
|
||||
if (hbp < 0) {
|
||||
dev_info(d->dev, "hbp negative, set to 0\n");
|
||||
hbp = 0;
|
||||
}
|
||||
if (hsa < 0) {
|
||||
dev_info(d->dev, "hsa negative, set to 0\n");
|
||||
hsa = 0;
|
||||
}
|
||||
dev_dbg(d->dev, "hfp: %u, hbp: %u, hsa: %u bytes\n",
|
||||
hfp, hbp, hsa);
|
||||
|
||||
/* Frame parameters: horizontal sync active */
|
||||
@ -497,71 +526,185 @@ static void mcde_dsi_setup_video_mode(struct mcde_dsi *d,
|
||||
val |= hfp << DSI_VID_HSIZE1_HFP_LENGTH_SHIFT;
|
||||
writel(val, d->regs + DSI_VID_HSIZE1);
|
||||
|
||||
/* RGB data length (bytes on one scanline) */
|
||||
val = mode->hdisplay * (bpp / 8);
|
||||
/* RGB data length (visible bytes on one scanline) */
|
||||
val = mode->hdisplay * cpp;
|
||||
writel(val, d->regs + DSI_VID_HSIZE2);
|
||||
|
||||
/* TODO: further adjustments for TVG mode here */
|
||||
dev_dbg(d->dev, "RGB length, visible area on a line: %u bytes\n", val);
|
||||
|
||||
/*
|
||||
* EOL packet length from bits per line calculations: pixel clock
|
||||
* is given in kHz, calculate the time between two pixels in
|
||||
* picoseconds.
|
||||
* Calculate the time between two pixels in picoseconds using
|
||||
* the supplied refresh rate and total resolution including
|
||||
* porches and sync.
|
||||
*/
|
||||
bpl = mode->clock * mode->htotal;
|
||||
bpl *= (d->hs_freq / 8);
|
||||
do_div(bpl, 1000000); /* microseconds */
|
||||
do_div(bpl, 1000000); /* seconds */
|
||||
/* (ps/s) / (pixels/s) = ps/pixels */
|
||||
pclk = DIV_ROUND_UP_ULL(1000000000000,
|
||||
(mode->vrefresh * mode->htotal * mode->vtotal));
|
||||
dev_dbg(d->dev, "picoseconds between two pixels: %llu\n",
|
||||
pclk);
|
||||
|
||||
/*
|
||||
* How many bytes per line will this update frequency yield?
|
||||
*
|
||||
* Calculate the number of picoseconds for one scanline (1), then
|
||||
* divide by 1000000000000 (2) to get in pixels per second we
|
||||
* want to output.
|
||||
*
|
||||
* Multiply with number of bytes per second at this video display
|
||||
* frequency (3) to get number of bytes transferred during this
|
||||
* time. Notice that we use the frequency the display wants,
|
||||
* not what we actually get from the DSI PLL, which is hs_freq.
|
||||
*
|
||||
* These arithmetics are done in a different order to avoid
|
||||
* overflow.
|
||||
*/
|
||||
bpl = pclk * mode->htotal; /* (1) picoseconds per line */
|
||||
dev_dbg(d->dev, "picoseconds per line: %llu\n", bpl);
|
||||
/* Multiply with bytes per second (3) */
|
||||
bpl *= (d->mdsi->hs_rate / 8);
|
||||
/* Pixels per second (2) */
|
||||
bpl = DIV_ROUND_DOWN_ULL(bpl, 1000000); /* microseconds */
|
||||
bpl = DIV_ROUND_DOWN_ULL(bpl, 1000000); /* seconds */
|
||||
/* parallel transactions in all lanes */
|
||||
bpl *= d->mdsi->lanes;
|
||||
dev_dbg(d->dev, "calculated bytes per line: %llu\n", bpl);
|
||||
dev_dbg(d->dev,
|
||||
"calculated bytes per line: %llu @ %d Hz with HS %lu Hz\n",
|
||||
bpl, mode->vrefresh, d->mdsi->hs_rate);
|
||||
|
||||
/*
|
||||
* 6 is header + checksum, header = 4 bytes, checksum = 2 bytes
|
||||
* 4 is short packet for vsync/hsync
|
||||
*/
|
||||
if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {
|
||||
/* Fixme: isn't the hsync width in pixels? */
|
||||
/* Set the event packet size to 0 (not used) */
|
||||
writel(0, d->regs + DSI_VID_BLKSIZE1);
|
||||
/*
|
||||
* FIXME: isn't the hsync width in pixels? The porch and
|
||||
* sync area size is in pixels here, but this -6
|
||||
* seems to be for bytes. It looks like this in the vendor
|
||||
* code though. Is it completely untested?
|
||||
*/
|
||||
blkline_pck = bpl - (mode->hsync_end - mode->hsync_start) - 6;
|
||||
val = blkline_pck << DSI_VID_BLKSIZE2_BLKLINE_PULSE_PCK_SHIFT;
|
||||
writel(val, d->regs + DSI_VID_BLKSIZE2);
|
||||
} else {
|
||||
/* Set the sync pulse packet size to 0 (not used) */
|
||||
writel(0, d->regs + DSI_VID_BLKSIZE2);
|
||||
/* Specifying payload size in bytes (-4-6 from manual) */
|
||||
blkline_pck = bpl - 4 - 6;
|
||||
if (blkline_pck > 0x1FFF)
|
||||
dev_err(d->dev, "blkline_pck too big %d bytes\n",
|
||||
blkline_pck);
|
||||
val = blkline_pck << DSI_VID_BLKSIZE1_BLKLINE_EVENT_PCK_SHIFT;
|
||||
val &= DSI_VID_BLKSIZE1_BLKLINE_EVENT_PCK_MASK;
|
||||
writel(val, d->regs + DSI_VID_BLKSIZE1);
|
||||
}
|
||||
|
||||
line_duration = (blkline_pck + 6) / d->mdsi->lanes;
|
||||
dev_dbg(d->dev, "line duration %u\n", line_duration);
|
||||
/*
|
||||
* The line duration is used to scale back the frequency from
|
||||
* the max frequency supported by the HS clock to the desired
|
||||
* update frequency in vrefresh.
|
||||
*/
|
||||
line_duration = blkline_pck + 6;
|
||||
/*
|
||||
* The datasheet contains this complex condition to decreasing
|
||||
* the line duration by 1 under very specific circumstances.
|
||||
* Here we also imply that LP is used during burst EOL.
|
||||
*/
|
||||
if (d->mdsi->lanes == 2 && (hsa & 0x01) && (hfp & 0x01)
|
||||
&& (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST))
|
||||
line_duration--;
|
||||
line_duration = DIV_ROUND_CLOSEST(line_duration, d->mdsi->lanes);
|
||||
dev_dbg(d->dev, "line duration %u bytes\n", line_duration);
|
||||
val = line_duration << DSI_VID_DPHY_TIME_REG_LINE_DURATION_SHIFT;
|
||||
/*
|
||||
* This is the time to perform LP->HS on D-PHY
|
||||
* FIXME: nowhere to get this from: DT property on the DSI?
|
||||
* The manual says this is "system dependent".
|
||||
* values like 48 and 72 seen in the vendor code.
|
||||
*/
|
||||
val |= 0 << DSI_VID_DPHY_TIME_REG_WAKEUP_TIME_SHIFT;
|
||||
val |= 48 << DSI_VID_DPHY_TIME_REG_WAKEUP_TIME_SHIFT;
|
||||
writel(val, d->regs + DSI_VID_DPHY_TIME);
|
||||
|
||||
/* Calculate block end of line */
|
||||
blkeol_pck = bpl - mode->hdisplay * bpp - 6;
|
||||
blkeol_duration = (blkeol_pck + 6) / d->mdsi->lanes;
|
||||
dev_dbg(d->dev, "blkeol pck: %u, duration: %u\n",
|
||||
blkeol_pck, blkeol_duration);
|
||||
|
||||
/*
|
||||
* See the manual figure 657 page 2203 for understanding the impact
|
||||
* of the different burst mode settings.
|
||||
*/
|
||||
if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) {
|
||||
/* Set up EOL clock for burst mode */
|
||||
int blkeol_pck, blkeol_duration;
|
||||
/*
|
||||
* Packet size at EOL for burst mode, this is only used
|
||||
* if DSI_VID_MAIN_CTL_REG_BLKEOL_MODE_LP_0 is NOT set,
|
||||
* but we instead send NULL or blanking packets at EOL.
|
||||
* This is given in number of bytes.
|
||||
*
|
||||
* See the manual page 2198 for the 13 reg_blkeol_pck bits.
|
||||
*/
|
||||
blkeol_pck = bpl - (mode->htotal * cpp) - 6;
|
||||
if (blkeol_pck < 0) {
|
||||
dev_err(d->dev, "video block does not fit on line!\n");
|
||||
dev_err(d->dev,
|
||||
"calculated bytes per line: %llu @ %d Hz\n",
|
||||
bpl, mode->vrefresh);
|
||||
dev_err(d->dev,
|
||||
"bytes per line (blkline_pck) %u bytes\n",
|
||||
blkline_pck);
|
||||
dev_err(d->dev,
|
||||
"blkeol_pck becomes %d bytes\n", blkeol_pck);
|
||||
return;
|
||||
}
|
||||
dev_dbg(d->dev, "BLKEOL packet: %d bytes\n", blkeol_pck);
|
||||
|
||||
val = readl(d->regs + DSI_VID_BLKSIZE1);
|
||||
val &= ~DSI_VID_BLKSIZE1_BLKEOL_PCK_MASK;
|
||||
val |= blkeol_pck << DSI_VID_BLKSIZE1_BLKEOL_PCK_SHIFT;
|
||||
writel(val, d->regs + DSI_VID_BLKSIZE1);
|
||||
writel(blkeol_pck, d->regs + DSI_VID_VCA_SETTING2);
|
||||
/* Use the same value for exact burst limit */
|
||||
val = blkeol_pck <<
|
||||
DSI_VID_VCA_SETTING2_EXACT_BURST_LIMIT_SHIFT;
|
||||
val &= DSI_VID_VCA_SETTING2_EXACT_BURST_LIMIT_MASK;
|
||||
writel(val, d->regs + DSI_VID_VCA_SETTING2);
|
||||
/*
|
||||
* This BLKEOL duration is claimed to be the duration in clock
|
||||
* cycles of the BLLP end-of-line (EOL) period for each line if
|
||||
* DSI_VID_MAIN_CTL_REG_BLKEOL_MODE_LP_0 is set.
|
||||
*
|
||||
* It is hard to trust the manuals' claim that this is in clock
|
||||
* cycles as we mimic the behaviour of the vendor code, which
|
||||
* appears to write a number of bytes that would have been
|
||||
* transferred on a single lane.
|
||||
*
|
||||
* See the manual figure 657 page 2203 and page 2198 for the 13
|
||||
* reg_blkeol_duration bits.
|
||||
*
|
||||
* FIXME: should this also be set up also for non-burst mode
|
||||
* according to figure 565 page 2202?
|
||||
*/
|
||||
blkeol_duration = DIV_ROUND_CLOSEST(blkeol_pck + 6,
|
||||
d->mdsi->lanes);
|
||||
dev_dbg(d->dev, "BLKEOL duration: %d clock cycles\n",
|
||||
blkeol_duration);
|
||||
|
||||
writel(blkeol_duration, d->regs + DSI_VID_PCK_TIME);
|
||||
writel(blkeol_duration - 6, d->regs + DSI_VID_VCA_SETTING1);
|
||||
val = readl(d->regs + DSI_VID_PCK_TIME);
|
||||
val &= ~DSI_VID_PCK_TIME_BLKEOL_DURATION_MASK;
|
||||
val |= blkeol_duration <<
|
||||
DSI_VID_PCK_TIME_BLKEOL_DURATION_SHIFT;
|
||||
writel(val, d->regs + DSI_VID_PCK_TIME);
|
||||
|
||||
/* Max burst limit, this is given in bytes */
|
||||
val = readl(d->regs + DSI_VID_VCA_SETTING1);
|
||||
val &= ~DSI_VID_VCA_SETTING1_MAX_BURST_LIMIT_MASK;
|
||||
val |= (blkeol_pck - 6) <<
|
||||
DSI_VID_VCA_SETTING1_MAX_BURST_LIMIT_SHIFT;
|
||||
writel(val, d->regs + DSI_VID_VCA_SETTING1);
|
||||
}
|
||||
|
||||
/* Maximum line limit */
|
||||
val = readl(d->regs + DSI_VID_VCA_SETTING2);
|
||||
val |= blkline_pck <<
|
||||
DSI_VID_VCA_SETTING2_EXACT_BURST_LIMIT_SHIFT;
|
||||
val &= ~DSI_VID_VCA_SETTING2_MAX_LINE_LIMIT_MASK;
|
||||
val |= (blkline_pck - 6) <<
|
||||
DSI_VID_VCA_SETTING2_MAX_LINE_LIMIT_SHIFT;
|
||||
writel(val, d->regs + DSI_VID_VCA_SETTING2);
|
||||
|
||||
dev_dbg(d->dev, "blkline pck: %d bytes\n", blkline_pck - 6);
|
||||
}
|
||||
|
||||
static void mcde_dsi_start(struct mcde_dsi *d)
|
||||
|
@ -228,6 +228,7 @@
|
||||
|
||||
#define DSI_VID_PCK_TIME 0x000000A8
|
||||
#define DSI_VID_PCK_TIME_BLKEOL_DURATION_SHIFT 0
|
||||
#define DSI_VID_PCK_TIME_BLKEOL_DURATION_MASK 0x00000FFF
|
||||
|
||||
#define DSI_VID_DPHY_TIME 0x000000AC
|
||||
#define DSI_VID_DPHY_TIME_REG_LINE_DURATION_SHIFT 0
|
||||
|
@ -94,7 +94,7 @@ static int mtk_plane_atomic_check(struct drm_plane *plane,
|
||||
if (!fb)
|
||||
return 0;
|
||||
|
||||
if (!state->crtc)
|
||||
if (WARN_ON(!state->crtc))
|
||||
return 0;
|
||||
|
||||
ret = mtk_drm_crtc_plane_check(state->crtc, plane,
|
||||
|
@ -157,7 +157,7 @@ static void submit_unlock_unpin_bo(struct msm_gem_submit *submit,
|
||||
msm_gem_unpin_iova(&msm_obj->base, submit->aspace);
|
||||
|
||||
if (submit->bos[i].flags & BO_LOCKED)
|
||||
ww_mutex_unlock(&msm_obj->base.resv->lock);
|
||||
dma_resv_unlock(msm_obj->base.resv);
|
||||
|
||||
if (backoff && !(submit->bos[i].flags & BO_VALID))
|
||||
submit->bos[i].iova = 0;
|
||||
@ -180,8 +180,8 @@ static int submit_lock_objects(struct msm_gem_submit *submit)
|
||||
contended = i;
|
||||
|
||||
if (!(submit->bos[i].flags & BO_LOCKED)) {
|
||||
ret = ww_mutex_lock_interruptible(&msm_obj->base.resv->lock,
|
||||
&submit->ticket);
|
||||
ret = dma_resv_lock_interruptible(msm_obj->base.resv,
|
||||
&submit->ticket);
|
||||
if (ret)
|
||||
goto fail;
|
||||
submit->bos[i].flags |= BO_LOCKED;
|
||||
@ -202,8 +202,8 @@ static int submit_lock_objects(struct msm_gem_submit *submit)
|
||||
if (ret == -EDEADLK) {
|
||||
struct msm_gem_object *msm_obj = submit->bos[contended].obj;
|
||||
/* we lost out in a seqno race, lock and retry.. */
|
||||
ret = ww_mutex_lock_slow_interruptible(&msm_obj->base.resv->lock,
|
||||
&submit->ticket);
|
||||
ret = dma_resv_lock_slow_interruptible(msm_obj->base.resv,
|
||||
&submit->ticket);
|
||||
if (!ret) {
|
||||
submit->bos[contended].flags |= BO_LOCKED;
|
||||
slow_locked = contended;
|
||||
|
@ -42,7 +42,7 @@ static int lg4573_spi_write_u16(struct lg4573 *ctx, u16 data)
|
||||
struct spi_transfer xfer = {
|
||||
.len = 2,
|
||||
};
|
||||
u16 temp = cpu_to_be16(data);
|
||||
__be16 temp = cpu_to_be16(data);
|
||||
struct spi_message msg;
|
||||
|
||||
dev_dbg(ctx->panel.dev, "writing data: %x\n", data);
|
||||
|
@ -46,6 +46,7 @@ config ROCKCHIP_DW_HDMI
|
||||
|
||||
config ROCKCHIP_DW_MIPI_DSI
|
||||
bool "Rockchip specific extensions for Synopsys DW MIPI DSI"
|
||||
select GENERIC_PHY_MIPI_DPHY
|
||||
help
|
||||
This selects support for Rockchip SoC specific extensions
|
||||
for the Synopsys DesignWare HDMI driver. If you want to
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
@ -139,6 +140,12 @@
|
||||
#define DW_MIPI_NEEDS_PHY_CFG_CLK BIT(0)
|
||||
#define DW_MIPI_NEEDS_GRF_CLK BIT(1)
|
||||
|
||||
#define PX30_GRF_PD_VO_CON1 0x0438
|
||||
#define PX30_DSI_FORCETXSTOPMODE (0xf << 7)
|
||||
#define PX30_DSI_FORCERXMODE BIT(6)
|
||||
#define PX30_DSI_TURNDISABLE BIT(5)
|
||||
#define PX30_DSI_LCDC_SEL BIT(0)
|
||||
|
||||
#define RK3288_GRF_SOC_CON6 0x025c
|
||||
#define RK3288_DSI0_LCDC_SEL BIT(6)
|
||||
#define RK3288_DSI1_LCDC_SEL BIT(9)
|
||||
@ -223,6 +230,10 @@ struct dw_mipi_dsi_rockchip {
|
||||
bool is_slave;
|
||||
struct dw_mipi_dsi_rockchip *slave;
|
||||
|
||||
/* optional external dphy */
|
||||
struct phy *phy;
|
||||
union phy_configure_opts phy_opts;
|
||||
|
||||
unsigned int lane_mbps; /* per lane */
|
||||
u16 input_div;
|
||||
u16 feedback_div;
|
||||
@ -359,6 +370,9 @@ static int dw_mipi_dsi_phy_init(void *priv_data)
|
||||
struct dw_mipi_dsi_rockchip *dsi = priv_data;
|
||||
int ret, i, vco;
|
||||
|
||||
if (dsi->phy)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Get vco from frequency(lane_mbps)
|
||||
* vco frequency table
|
||||
@ -467,6 +481,28 @@ static int dw_mipi_dsi_phy_init(void *priv_data)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dw_mipi_dsi_phy_power_on(void *priv_data)
|
||||
{
|
||||
struct dw_mipi_dsi_rockchip *dsi = priv_data;
|
||||
int ret;
|
||||
|
||||
ret = phy_set_mode(dsi->phy, PHY_MODE_MIPI_DPHY);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dsi->dev, "failed to set phy mode: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
phy_configure(dsi->phy, &dsi->phy_opts);
|
||||
phy_power_on(dsi->phy);
|
||||
}
|
||||
|
||||
static void dw_mipi_dsi_phy_power_off(void *priv_data)
|
||||
{
|
||||
struct dw_mipi_dsi_rockchip *dsi = priv_data;
|
||||
|
||||
phy_power_off(dsi->phy);
|
||||
}
|
||||
|
||||
static int
|
||||
dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,
|
||||
unsigned long mode_flags, u32 lanes, u32 format,
|
||||
@ -504,6 +540,17 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,
|
||||
"DPHY clock frequency is out of range\n");
|
||||
}
|
||||
|
||||
/* for external phy only a the mipi_dphy_config is necessary */
|
||||
if (dsi->phy) {
|
||||
phy_mipi_dphy_get_default_config(mode->clock * 1000 * 10 / 8,
|
||||
bpp, lanes,
|
||||
&dsi->phy_opts.mipi_dphy);
|
||||
dsi->lane_mbps = target_mbps;
|
||||
*lane_mbps = dsi->lane_mbps;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
fin = clk_get_rate(dsi->pllref_clk);
|
||||
fout = target_mbps * USEC_PER_SEC;
|
||||
|
||||
@ -559,9 +606,89 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct hstt {
|
||||
unsigned int maxfreq;
|
||||
struct dw_mipi_dsi_dphy_timing timing;
|
||||
};
|
||||
|
||||
#define HSTT(_maxfreq, _c_lp2hs, _c_hs2lp, _d_lp2hs, _d_hs2lp) \
|
||||
{ \
|
||||
.maxfreq = _maxfreq, \
|
||||
.timing = { \
|
||||
.clk_lp2hs = _c_lp2hs, \
|
||||
.clk_hs2lp = _c_hs2lp, \
|
||||
.data_lp2hs = _d_lp2hs, \
|
||||
.data_hs2lp = _d_hs2lp, \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Table A-3 High-Speed Transition Times */
|
||||
struct hstt hstt_table[] = {
|
||||
HSTT( 90, 32, 20, 26, 13),
|
||||
HSTT( 100, 35, 23, 28, 14),
|
||||
HSTT( 110, 32, 22, 26, 13),
|
||||
HSTT( 130, 31, 20, 27, 13),
|
||||
HSTT( 140, 33, 22, 26, 14),
|
||||
HSTT( 150, 33, 21, 26, 14),
|
||||
HSTT( 170, 32, 20, 27, 13),
|
||||
HSTT( 180, 36, 23, 30, 15),
|
||||
HSTT( 200, 40, 22, 33, 15),
|
||||
HSTT( 220, 40, 22, 33, 15),
|
||||
HSTT( 240, 44, 24, 36, 16),
|
||||
HSTT( 250, 48, 24, 38, 17),
|
||||
HSTT( 270, 48, 24, 38, 17),
|
||||
HSTT( 300, 50, 27, 41, 18),
|
||||
HSTT( 330, 56, 28, 45, 18),
|
||||
HSTT( 360, 59, 28, 48, 19),
|
||||
HSTT( 400, 61, 30, 50, 20),
|
||||
HSTT( 450, 67, 31, 55, 21),
|
||||
HSTT( 500, 73, 31, 59, 22),
|
||||
HSTT( 550, 79, 36, 63, 24),
|
||||
HSTT( 600, 83, 37, 68, 25),
|
||||
HSTT( 650, 90, 38, 73, 27),
|
||||
HSTT( 700, 95, 40, 77, 28),
|
||||
HSTT( 750, 102, 40, 84, 28),
|
||||
HSTT( 800, 106, 42, 87, 30),
|
||||
HSTT( 850, 113, 44, 93, 31),
|
||||
HSTT( 900, 118, 47, 98, 32),
|
||||
HSTT( 950, 124, 47, 102, 34),
|
||||
HSTT(1000, 130, 49, 107, 35),
|
||||
HSTT(1050, 135, 51, 111, 37),
|
||||
HSTT(1100, 139, 51, 114, 38),
|
||||
HSTT(1150, 146, 54, 120, 40),
|
||||
HSTT(1200, 153, 57, 125, 41),
|
||||
HSTT(1250, 158, 58, 130, 42),
|
||||
HSTT(1300, 163, 58, 135, 44),
|
||||
HSTT(1350, 168, 60, 140, 45),
|
||||
HSTT(1400, 172, 64, 144, 47),
|
||||
HSTT(1450, 176, 65, 148, 48),
|
||||
HSTT(1500, 181, 66, 153, 50)
|
||||
};
|
||||
|
||||
static int
|
||||
dw_mipi_dsi_phy_get_timing(void *priv_data, unsigned int lane_mbps,
|
||||
struct dw_mipi_dsi_dphy_timing *timing)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(hstt_table); i++)
|
||||
if (lane_mbps < hstt_table[i].maxfreq)
|
||||
break;
|
||||
|
||||
if (i == ARRAY_SIZE(hstt_table))
|
||||
i--;
|
||||
|
||||
*timing = hstt_table[i].timing;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dw_mipi_dsi_phy_ops dw_mipi_dsi_rockchip_phy_ops = {
|
||||
.init = dw_mipi_dsi_phy_init,
|
||||
.power_on = dw_mipi_dsi_phy_power_on,
|
||||
.power_off = dw_mipi_dsi_phy_power_off,
|
||||
.get_lane_mbps = dw_mipi_dsi_get_lane_mbps,
|
||||
.get_timing = dw_mipi_dsi_phy_get_timing,
|
||||
};
|
||||
|
||||
static void dw_mipi_dsi_rockchip_config(struct dw_mipi_dsi_rockchip *dsi,
|
||||
@ -920,12 +1047,29 @@ static int dw_mipi_dsi_rockchip_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* try to get a possible external dphy */
|
||||
dsi->phy = devm_phy_optional_get(dev, "dphy");
|
||||
if (IS_ERR(dsi->phy)) {
|
||||
ret = PTR_ERR(dsi->phy);
|
||||
DRM_DEV_ERROR(dev, "failed to get mipi dphy: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dsi->pllref_clk = devm_clk_get(dev, "ref");
|
||||
if (IS_ERR(dsi->pllref_clk)) {
|
||||
ret = PTR_ERR(dsi->pllref_clk);
|
||||
DRM_DEV_ERROR(dev,
|
||||
"Unable to get pll reference clock: %d\n", ret);
|
||||
return ret;
|
||||
if (dsi->phy) {
|
||||
/*
|
||||
* if external phy is present, pll will be
|
||||
* generated there.
|
||||
*/
|
||||
dsi->pllref_clk = NULL;
|
||||
} else {
|
||||
ret = PTR_ERR(dsi->pllref_clk);
|
||||
DRM_DEV_ERROR(dev,
|
||||
"Unable to get pll reference clock: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (dsi->cdata->flags & DW_MIPI_NEEDS_PHY_CFG_CLK) {
|
||||
@ -989,6 +1133,24 @@ static int dw_mipi_dsi_rockchip_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct rockchip_dw_dsi_chip_data px30_chip_data[] = {
|
||||
{
|
||||
.reg = 0xff450000,
|
||||
.lcdsel_grf_reg = PX30_GRF_PD_VO_CON1,
|
||||
.lcdsel_big = HIWORD_UPDATE(0, PX30_DSI_LCDC_SEL),
|
||||
.lcdsel_lit = HIWORD_UPDATE(PX30_DSI_LCDC_SEL,
|
||||
PX30_DSI_LCDC_SEL),
|
||||
|
||||
.lanecfg1_grf_reg = PX30_GRF_PD_VO_CON1,
|
||||
.lanecfg1 = HIWORD_UPDATE(0, PX30_DSI_TURNDISABLE |
|
||||
PX30_DSI_FORCERXMODE |
|
||||
PX30_DSI_FORCETXSTOPMODE),
|
||||
|
||||
.max_data_lanes = 4,
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static const struct rockchip_dw_dsi_chip_data rk3288_chip_data[] = {
|
||||
{
|
||||
.reg = 0xff960000,
|
||||
@ -1057,6 +1219,9 @@ static const struct rockchip_dw_dsi_chip_data rk3399_chip_data[] = {
|
||||
|
||||
static const struct of_device_id dw_mipi_dsi_rockchip_dt_ids[] = {
|
||||
{
|
||||
.compatible = "rockchip,px30-mipi-dsi",
|
||||
.data = &px30_chip_data,
|
||||
}, {
|
||||
.compatible = "rockchip,rk3288-mipi-dsi",
|
||||
.data = &rk3288_chip_data,
|
||||
}, {
|
||||
|
@ -60,3 +60,8 @@ cmdline_test(drm_cmdline_test_vmirror)
|
||||
cmdline_test(drm_cmdline_test_margin_options)
|
||||
cmdline_test(drm_cmdline_test_multiple_options)
|
||||
cmdline_test(drm_cmdline_test_invalid_option)
|
||||
cmdline_test(drm_cmdline_test_bpp_extra_and_option)
|
||||
cmdline_test(drm_cmdline_test_extra_and_option)
|
||||
cmdline_test(drm_cmdline_test_freestanding_options)
|
||||
cmdline_test(drm_cmdline_test_freestanding_force_e_and_options)
|
||||
cmdline_test(drm_cmdline_test_panel_orientation)
|
||||
|
@ -992,6 +992,128 @@ static int drm_cmdline_test_invalid_option(void *ignored)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drm_cmdline_test_bpp_extra_and_option(void *ignored)
|
||||
{
|
||||
struct drm_cmdline_mode mode = { };
|
||||
|
||||
FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24e,rotate=180",
|
||||
&no_connector,
|
||||
&mode));
|
||||
FAIL_ON(!mode.specified);
|
||||
FAIL_ON(mode.xres != 720);
|
||||
FAIL_ON(mode.yres != 480);
|
||||
FAIL_ON(mode.rotation_reflection != DRM_MODE_ROTATE_180);
|
||||
|
||||
FAIL_ON(mode.refresh_specified);
|
||||
|
||||
FAIL_ON(!mode.bpp_specified);
|
||||
FAIL_ON(mode.bpp != 24);
|
||||
|
||||
FAIL_ON(mode.rb);
|
||||
FAIL_ON(mode.cvt);
|
||||
FAIL_ON(mode.interlace);
|
||||
FAIL_ON(mode.margins);
|
||||
FAIL_ON(mode.force != DRM_FORCE_ON);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drm_cmdline_test_extra_and_option(void *ignored)
|
||||
{
|
||||
struct drm_cmdline_mode mode = { };
|
||||
|
||||
FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480e,rotate=180",
|
||||
&no_connector,
|
||||
&mode));
|
||||
FAIL_ON(!mode.specified);
|
||||
FAIL_ON(mode.xres != 720);
|
||||
FAIL_ON(mode.yres != 480);
|
||||
FAIL_ON(mode.rotation_reflection != DRM_MODE_ROTATE_180);
|
||||
|
||||
FAIL_ON(mode.refresh_specified);
|
||||
FAIL_ON(mode.bpp_specified);
|
||||
|
||||
FAIL_ON(mode.rb);
|
||||
FAIL_ON(mode.cvt);
|
||||
FAIL_ON(mode.interlace);
|
||||
FAIL_ON(mode.margins);
|
||||
FAIL_ON(mode.force != DRM_FORCE_ON);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drm_cmdline_test_freestanding_options(void *ignored)
|
||||
{
|
||||
struct drm_cmdline_mode mode = { };
|
||||
|
||||
FAIL_ON(!drm_mode_parse_command_line_for_connector("margin_right=14,margin_left=24,margin_bottom=36,margin_top=42",
|
||||
&no_connector,
|
||||
&mode));
|
||||
FAIL_ON(mode.specified);
|
||||
FAIL_ON(mode.refresh_specified);
|
||||
FAIL_ON(mode.bpp_specified);
|
||||
|
||||
FAIL_ON(mode.tv_margins.right != 14);
|
||||
FAIL_ON(mode.tv_margins.left != 24);
|
||||
FAIL_ON(mode.tv_margins.bottom != 36);
|
||||
FAIL_ON(mode.tv_margins.top != 42);
|
||||
|
||||
FAIL_ON(mode.rb);
|
||||
FAIL_ON(mode.cvt);
|
||||
FAIL_ON(mode.interlace);
|
||||
FAIL_ON(mode.margins);
|
||||
FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drm_cmdline_test_freestanding_force_e_and_options(void *ignored)
|
||||
{
|
||||
struct drm_cmdline_mode mode = { };
|
||||
|
||||
FAIL_ON(!drm_mode_parse_command_line_for_connector("e,margin_right=14,margin_left=24,margin_bottom=36,margin_top=42",
|
||||
&no_connector,
|
||||
&mode));
|
||||
FAIL_ON(mode.specified);
|
||||
FAIL_ON(mode.refresh_specified);
|
||||
FAIL_ON(mode.bpp_specified);
|
||||
|
||||
FAIL_ON(mode.tv_margins.right != 14);
|
||||
FAIL_ON(mode.tv_margins.left != 24);
|
||||
FAIL_ON(mode.tv_margins.bottom != 36);
|
||||
FAIL_ON(mode.tv_margins.top != 42);
|
||||
|
||||
FAIL_ON(mode.rb);
|
||||
FAIL_ON(mode.cvt);
|
||||
FAIL_ON(mode.interlace);
|
||||
FAIL_ON(mode.margins);
|
||||
FAIL_ON(mode.force != DRM_FORCE_ON);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drm_cmdline_test_panel_orientation(void *ignored)
|
||||
{
|
||||
struct drm_cmdline_mode mode = { };
|
||||
|
||||
FAIL_ON(!drm_mode_parse_command_line_for_connector("panel_orientation=upside_down",
|
||||
&no_connector,
|
||||
&mode));
|
||||
FAIL_ON(mode.specified);
|
||||
FAIL_ON(mode.refresh_specified);
|
||||
FAIL_ON(mode.bpp_specified);
|
||||
|
||||
FAIL_ON(mode.panel_orientation != DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP);
|
||||
|
||||
FAIL_ON(mode.rb);
|
||||
FAIL_ON(mode.cvt);
|
||||
FAIL_ON(mode.interlace);
|
||||
FAIL_ON(mode.margins);
|
||||
FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "drm_selftest.c"
|
||||
|
||||
static int __init test_drm_cmdline_init(void)
|
||||
|
@ -309,11 +309,24 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
dw_mipi_dsi_phy_get_timing(void *priv_data, unsigned int lane_mbps,
|
||||
struct dw_mipi_dsi_dphy_timing *timing)
|
||||
{
|
||||
timing->clk_hs2lp = 0x40;
|
||||
timing->clk_lp2hs = 0x40;
|
||||
timing->data_hs2lp = 0x40;
|
||||
timing->data_lp2hs = 0x40;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dw_mipi_dsi_phy_ops dw_mipi_dsi_stm_phy_ops = {
|
||||
.init = dw_mipi_dsi_phy_init,
|
||||
.power_on = dw_mipi_dsi_phy_power_on,
|
||||
.power_off = dw_mipi_dsi_phy_power_off,
|
||||
.get_lane_mbps = dw_mipi_dsi_get_lane_mbps,
|
||||
.get_timing = dw_mipi_dsi_phy_get_timing,
|
||||
};
|
||||
|
||||
static struct dw_mipi_dsi_plat_data dw_mipi_dsi_stm_plat_data = {
|
||||
|
@ -437,9 +437,6 @@ static void ltdc_crtc_atomic_enable(struct drm_crtc *crtc,
|
||||
/* Commit shadow registers = update planes at next vblank */
|
||||
reg_set(ldev->regs, LTDC_SRCR, SRCR_VBR);
|
||||
|
||||
/* Enable LTDC */
|
||||
reg_set(ldev->regs, LTDC_GCR, GCR_LTDCEN);
|
||||
|
||||
drm_crtc_vblank_on(crtc);
|
||||
}
|
||||
|
||||
@ -453,9 +450,6 @@ static void ltdc_crtc_atomic_disable(struct drm_crtc *crtc,
|
||||
|
||||
drm_crtc_vblank_off(crtc);
|
||||
|
||||
/* disable LTDC */
|
||||
reg_clear(ldev->regs, LTDC_GCR, GCR_LTDCEN);
|
||||
|
||||
/* disable IRQ */
|
||||
reg_clear(ldev->regs, LTDC_IER, IER_RRIE | IER_FUIE | IER_TERRIE);
|
||||
|
||||
@ -1044,14 +1038,31 @@ static const struct drm_encoder_funcs ltdc_encoder_funcs = {
|
||||
static void ltdc_encoder_disable(struct drm_encoder *encoder)
|
||||
{
|
||||
struct drm_device *ddev = encoder->dev;
|
||||
struct ltdc_device *ldev = ddev->dev_private;
|
||||
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
|
||||
/* Disable LTDC */
|
||||
reg_clear(ldev->regs, LTDC_GCR, GCR_LTDCEN);
|
||||
|
||||
/* Set to sleep state the pinctrl whatever type of encoder */
|
||||
pinctrl_pm_select_sleep_state(ddev->dev);
|
||||
}
|
||||
|
||||
static void ltdc_encoder_enable(struct drm_encoder *encoder)
|
||||
{
|
||||
struct drm_device *ddev = encoder->dev;
|
||||
struct ltdc_device *ldev = ddev->dev_private;
|
||||
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
|
||||
/* Enable LTDC */
|
||||
reg_set(ldev->regs, LTDC_GCR, GCR_LTDCEN);
|
||||
}
|
||||
|
||||
static void ltdc_encoder_mode_set(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
struct drm_device *ddev = encoder->dev;
|
||||
|
||||
@ -1069,6 +1080,7 @@ static void ltdc_encoder_enable(struct drm_encoder *encoder)
|
||||
static const struct drm_encoder_helper_funcs ltdc_encoder_helper_funcs = {
|
||||
.disable = ltdc_encoder_disable,
|
||||
.enable = ltdc_encoder_enable,
|
||||
.mode_set = ltdc_encoder_mode_set,
|
||||
};
|
||||
|
||||
static int ltdc_encoder_init(struct drm_device *ddev, struct drm_bridge *bridge)
|
||||
|
@ -346,6 +346,27 @@ static int sun4i_drv_add_endpoints(struct device *dev,
|
||||
return count;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int sun4i_drv_drm_sys_suspend(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm = dev_get_drvdata(dev);
|
||||
|
||||
return drm_mode_config_helper_suspend(drm);
|
||||
}
|
||||
|
||||
static int sun4i_drv_drm_sys_resume(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm = dev_get_drvdata(dev);
|
||||
|
||||
return drm_mode_config_helper_resume(drm);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops sun4i_drv_drm_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(sun4i_drv_drm_sys_suspend,
|
||||
sun4i_drv_drm_sys_resume)
|
||||
};
|
||||
|
||||
static int sun4i_drv_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct component_match *match = NULL;
|
||||
@ -418,6 +439,7 @@ static struct platform_driver sun4i_drv_platform_driver = {
|
||||
.driver = {
|
||||
.name = "sun4i-drm",
|
||||
.of_match_table = sun4i_drv_of_table,
|
||||
.pm = &sun4i_drv_drm_pm_ops,
|
||||
},
|
||||
};
|
||||
module_platform_driver(sun4i_drv_platform_driver);
|
||||
|
@ -1081,6 +1081,7 @@ static const struct component_ops sun6i_dsi_ops = {
|
||||
static int sun6i_dsi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
const char *bus_clk_name = NULL;
|
||||
struct sun6i_dsi *dsi;
|
||||
struct resource *res;
|
||||
void __iomem *base;
|
||||
@ -1094,6 +1095,10 @@ static int sun6i_dsi_probe(struct platform_device *pdev)
|
||||
dsi->host.ops = &sun6i_dsi_host_ops;
|
||||
dsi->host.dev = dev;
|
||||
|
||||
if (of_device_is_compatible(dev->of_node,
|
||||
"allwinner,sun6i-a31-mipi-dsi"))
|
||||
bus_clk_name = "bus";
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(base)) {
|
||||
@ -1107,23 +1112,36 @@ static int sun6i_dsi_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(dsi->regulator);
|
||||
}
|
||||
|
||||
dsi->regs = devm_regmap_init_mmio_clk(dev, "bus", base,
|
||||
&sun6i_dsi_regmap_config);
|
||||
if (IS_ERR(dsi->regs)) {
|
||||
dev_err(dev, "Couldn't create the DSI encoder regmap\n");
|
||||
return PTR_ERR(dsi->regs);
|
||||
}
|
||||
|
||||
dsi->reset = devm_reset_control_get_shared(dev, NULL);
|
||||
if (IS_ERR(dsi->reset)) {
|
||||
dev_err(dev, "Couldn't get our reset line\n");
|
||||
return PTR_ERR(dsi->reset);
|
||||
}
|
||||
|
||||
dsi->mod_clk = devm_clk_get(dev, "mod");
|
||||
if (IS_ERR(dsi->mod_clk)) {
|
||||
dev_err(dev, "Couldn't get the DSI mod clock\n");
|
||||
return PTR_ERR(dsi->mod_clk);
|
||||
dsi->regs = devm_regmap_init_mmio(dev, base, &sun6i_dsi_regmap_config);
|
||||
if (IS_ERR(dsi->regs)) {
|
||||
dev_err(dev, "Couldn't init regmap\n");
|
||||
return PTR_ERR(dsi->regs);
|
||||
}
|
||||
|
||||
dsi->bus_clk = devm_clk_get(dev, bus_clk_name);
|
||||
if (IS_ERR(dsi->bus_clk)) {
|
||||
dev_err(dev, "Couldn't get the DSI bus clock\n");
|
||||
return PTR_ERR(dsi->bus_clk);
|
||||
}
|
||||
|
||||
ret = regmap_mmio_attach_clk(dsi->regs, dsi->bus_clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (of_device_is_compatible(dev->of_node,
|
||||
"allwinner,sun6i-a31-mipi-dsi")) {
|
||||
dsi->mod_clk = devm_clk_get(dev, "mod");
|
||||
if (IS_ERR(dsi->mod_clk)) {
|
||||
dev_err(dev, "Couldn't get the DSI mod clock\n");
|
||||
ret = PTR_ERR(dsi->mod_clk);
|
||||
goto err_attach_clk;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1161,6 +1179,9 @@ static int sun6i_dsi_probe(struct platform_device *pdev)
|
||||
pm_runtime_disable(dev);
|
||||
err_unprotect_clk:
|
||||
clk_rate_exclusive_put(dsi->mod_clk);
|
||||
err_attach_clk:
|
||||
if (!IS_ERR(dsi->bus_clk))
|
||||
regmap_mmio_detach_clk(dsi->regs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1174,6 +1195,9 @@ static int sun6i_dsi_remove(struct platform_device *pdev)
|
||||
pm_runtime_disable(dev);
|
||||
clk_rate_exclusive_put(dsi->mod_clk);
|
||||
|
||||
if (!IS_ERR(dsi->bus_clk))
|
||||
regmap_mmio_detach_clk(dsi->regs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1232,6 +1256,7 @@ static const struct dev_pm_ops sun6i_dsi_pm_ops = {
|
||||
|
||||
static const struct of_device_id sun6i_dsi_of_table[] = {
|
||||
{ .compatible = "allwinner,sun6i-a31-mipi-dsi" },
|
||||
{ .compatible = "allwinner,sun50i-a64-mipi-dsi" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sun6i_dsi_of_table);
|
||||
|
@ -568,7 +568,7 @@ vc4_unlock_bo_reservations(struct drm_device *dev,
|
||||
for (i = 0; i < exec->bo_count; i++) {
|
||||
struct drm_gem_object *bo = &exec->bo[i]->base;
|
||||
|
||||
ww_mutex_unlock(&bo->resv->lock);
|
||||
dma_resv_unlock(bo->resv);
|
||||
}
|
||||
|
||||
ww_acquire_fini(acquire_ctx);
|
||||
@ -595,8 +595,7 @@ vc4_lock_bo_reservations(struct drm_device *dev,
|
||||
retry:
|
||||
if (contended_lock != -1) {
|
||||
bo = &exec->bo[contended_lock]->base;
|
||||
ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock,
|
||||
acquire_ctx);
|
||||
ret = dma_resv_lock_slow_interruptible(bo->resv, acquire_ctx);
|
||||
if (ret) {
|
||||
ww_acquire_done(acquire_ctx);
|
||||
return ret;
|
||||
@ -609,19 +608,19 @@ vc4_lock_bo_reservations(struct drm_device *dev,
|
||||
|
||||
bo = &exec->bo[i]->base;
|
||||
|
||||
ret = ww_mutex_lock_interruptible(&bo->resv->lock, acquire_ctx);
|
||||
ret = dma_resv_lock_interruptible(bo->resv, acquire_ctx);
|
||||
if (ret) {
|
||||
int j;
|
||||
|
||||
for (j = 0; j < i; j++) {
|
||||
bo = &exec->bo[j]->base;
|
||||
ww_mutex_unlock(&bo->resv->lock);
|
||||
dma_resv_unlock(bo->resv);
|
||||
}
|
||||
|
||||
if (contended_lock != -1 && contended_lock >= i) {
|
||||
bo = &exec->bo[contended_lock]->base;
|
||||
|
||||
ww_mutex_unlock(&bo->resv->lock);
|
||||
dma_resv_unlock(bo->resv);
|
||||
}
|
||||
|
||||
if (ret == -EDEADLK) {
|
||||
|
@ -43,6 +43,9 @@
|
||||
#define XRES_MAX 8192
|
||||
#define YRES_MAX 8192
|
||||
|
||||
#define drm_connector_to_virtio_gpu_output(x) \
|
||||
container_of(x, struct virtio_gpu_output, conn)
|
||||
|
||||
static const struct drm_crtc_funcs virtio_gpu_crtc_funcs = {
|
||||
.set_config = drm_atomic_helper_set_config,
|
||||
.destroy = drm_crtc_cleanup,
|
||||
@ -59,7 +62,7 @@ static const struct drm_framebuffer_funcs virtio_gpu_fb_funcs = {
|
||||
.dirty = drm_atomic_helper_dirtyfb,
|
||||
};
|
||||
|
||||
int
|
||||
static int
|
||||
virtio_gpu_framebuffer_init(struct drm_device *dev,
|
||||
struct virtio_gpu_framebuffer *vgfb,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
|
@ -103,8 +103,6 @@ struct virtio_gpu_fence {
|
||||
struct virtio_gpu_fence_driver *drv;
|
||||
struct list_head node;
|
||||
};
|
||||
#define to_virtio_fence(x) \
|
||||
container_of(x, struct virtio_gpu_fence, f)
|
||||
|
||||
struct virtio_gpu_vbuffer {
|
||||
char *buf;
|
||||
@ -135,10 +133,6 @@ struct virtio_gpu_output {
|
||||
};
|
||||
#define drm_crtc_to_virtio_gpu_output(x) \
|
||||
container_of(x, struct virtio_gpu_output, crtc)
|
||||
#define drm_connector_to_virtio_gpu_output(x) \
|
||||
container_of(x, struct virtio_gpu_output, conn)
|
||||
#define drm_encoder_to_virtio_gpu_output(x) \
|
||||
container_of(x, struct virtio_gpu_output, enc)
|
||||
|
||||
struct virtio_gpu_framebuffer {
|
||||
struct drm_framebuffer base;
|
||||
@ -183,6 +177,9 @@ struct virtio_gpu_device {
|
||||
struct kmem_cache *vbufs;
|
||||
bool vqs_ready;
|
||||
|
||||
bool disable_notify;
|
||||
bool pending_notify;
|
||||
|
||||
struct ida resource_ida;
|
||||
|
||||
wait_queue_head_t resp_wq;
|
||||
@ -335,11 +332,10 @@ void virtio_gpu_dequeue_ctrl_func(struct work_struct *work);
|
||||
void virtio_gpu_dequeue_cursor_func(struct work_struct *work);
|
||||
void virtio_gpu_dequeue_fence_func(struct work_struct *work);
|
||||
|
||||
void virtio_gpu_disable_notify(struct virtio_gpu_device *vgdev);
|
||||
void virtio_gpu_enable_notify(struct virtio_gpu_device *vgdev);
|
||||
|
||||
/* virtio_gpu_display.c */
|
||||
int virtio_gpu_framebuffer_init(struct drm_device *dev,
|
||||
struct virtio_gpu_framebuffer *vgfb,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object *obj);
|
||||
void virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev);
|
||||
void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev);
|
||||
|
||||
@ -350,7 +346,6 @@ struct drm_plane *virtio_gpu_plane_init(struct virtio_gpu_device *vgdev,
|
||||
int index);
|
||||
|
||||
/* virtio_gpu_fence.c */
|
||||
bool virtio_fence_signaled(struct dma_fence *f);
|
||||
struct virtio_gpu_fence *virtio_gpu_fence_alloc(
|
||||
struct virtio_gpu_device *vgdev);
|
||||
void virtio_gpu_fence_emit(struct virtio_gpu_device *vgdev,
|
||||
@ -366,18 +361,12 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev,
|
||||
struct virtio_gpu_object_params *params,
|
||||
struct virtio_gpu_object **bo_ptr,
|
||||
struct virtio_gpu_fence *fence);
|
||||
|
||||
/* virtgpu_prime.c */
|
||||
struct drm_gem_object *virtgpu_gem_prime_import_sg_table(
|
||||
struct drm_device *dev, struct dma_buf_attachment *attach,
|
||||
struct sg_table *sgt);
|
||||
|
||||
static inline u64 virtio_gpu_object_mmap_offset(struct virtio_gpu_object *bo)
|
||||
{
|
||||
return drm_vma_node_offset_addr(&bo->base.base.vma_node);
|
||||
}
|
||||
|
||||
/* virgl debufs */
|
||||
/* virgl debugfs */
|
||||
int virtio_gpu_debugfs_init(struct drm_minor *minor);
|
||||
|
||||
#endif
|
||||
|
@ -27,6 +27,9 @@
|
||||
|
||||
#include "virtgpu_drv.h"
|
||||
|
||||
#define to_virtio_fence(x) \
|
||||
container_of(x, struct virtio_gpu_fence, f)
|
||||
|
||||
static const char *virtio_get_driver_name(struct dma_fence *f)
|
||||
{
|
||||
return "virtio_gpu";
|
||||
@ -37,7 +40,7 @@ static const char *virtio_get_timeline_name(struct dma_fence *f)
|
||||
return "controlq";
|
||||
}
|
||||
|
||||
bool virtio_fence_signaled(struct dma_fence *f)
|
||||
static bool virtio_fence_signaled(struct dma_fence *f)
|
||||
{
|
||||
struct virtio_gpu_fence *fence = to_virtio_fence(f);
|
||||
|
||||
|
@ -96,14 +96,12 @@ int virtio_gpu_mode_dumb_mmap(struct drm_file *file_priv,
|
||||
uint32_t handle, uint64_t *offset_p)
|
||||
{
|
||||
struct drm_gem_object *gobj;
|
||||
struct virtio_gpu_object *obj;
|
||||
|
||||
BUG_ON(!offset_p);
|
||||
gobj = drm_gem_object_lookup(file_priv, handle);
|
||||
if (gobj == NULL)
|
||||
return -ENOENT;
|
||||
obj = gem_to_virtio_gpu_obj(gobj);
|
||||
*offset_p = virtio_gpu_object_mmap_offset(obj);
|
||||
*offset_p = drm_vma_node_offset_addr(&gobj->vma_node);
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
return 0;
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
*/
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_damage_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
|
||||
@ -88,7 +89,7 @@ static int virtio_gpu_plane_atomic_check(struct drm_plane *plane,
|
||||
struct drm_crtc_state *crtc_state;
|
||||
int ret;
|
||||
|
||||
if (!state->fb || !state->crtc)
|
||||
if (!state->fb || WARN_ON(!state->crtc))
|
||||
return 0;
|
||||
|
||||
crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
|
||||
@ -103,22 +104,26 @@ static int virtio_gpu_plane_atomic_check(struct drm_plane *plane,
|
||||
}
|
||||
|
||||
static void virtio_gpu_update_dumb_bo(struct virtio_gpu_device *vgdev,
|
||||
struct virtio_gpu_object *bo,
|
||||
struct drm_plane_state *state)
|
||||
struct drm_plane_state *state,
|
||||
struct drm_rect *rect)
|
||||
{
|
||||
struct virtio_gpu_object *bo =
|
||||
gem_to_virtio_gpu_obj(state->fb->obj[0]);
|
||||
struct virtio_gpu_object_array *objs;
|
||||
uint32_t w = rect->x2 - rect->x1;
|
||||
uint32_t h = rect->y2 - rect->y1;
|
||||
uint32_t x = rect->x1;
|
||||
uint32_t y = rect->y1;
|
||||
uint32_t off = x * state->fb->format->cpp[0] +
|
||||
y * state->fb->pitches[0];
|
||||
|
||||
objs = virtio_gpu_array_alloc(1);
|
||||
if (!objs)
|
||||
return;
|
||||
virtio_gpu_array_add_obj(objs, &bo->base.base);
|
||||
virtio_gpu_cmd_transfer_to_host_2d
|
||||
(vgdev, 0,
|
||||
state->src_w >> 16,
|
||||
state->src_h >> 16,
|
||||
state->src_x >> 16,
|
||||
state->src_y >> 16,
|
||||
objs, NULL);
|
||||
|
||||
virtio_gpu_cmd_transfer_to_host_2d(vgdev, off, w, h, x, y,
|
||||
objs, NULL);
|
||||
}
|
||||
|
||||
static void virtio_gpu_primary_plane_update(struct drm_plane *plane,
|
||||
@ -127,8 +132,8 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane,
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct virtio_gpu_device *vgdev = dev->dev_private;
|
||||
struct virtio_gpu_output *output = NULL;
|
||||
struct virtio_gpu_framebuffer *vgfb;
|
||||
struct virtio_gpu_object *bo;
|
||||
struct drm_rect rect;
|
||||
|
||||
if (plane->state->crtc)
|
||||
output = drm_crtc_to_virtio_gpu_output(plane->state->crtc);
|
||||
@ -146,30 +151,43 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane,
|
||||
return;
|
||||
}
|
||||
|
||||
vgfb = to_virtio_gpu_framebuffer(plane->state->fb);
|
||||
bo = gem_to_virtio_gpu_obj(vgfb->base.obj[0]);
|
||||
if (bo->dumb)
|
||||
virtio_gpu_update_dumb_bo(vgdev, bo, plane->state);
|
||||
if (!drm_atomic_helper_damage_merged(old_state, plane->state, &rect))
|
||||
return;
|
||||
|
||||
virtio_gpu_disable_notify(vgdev);
|
||||
|
||||
bo = gem_to_virtio_gpu_obj(plane->state->fb->obj[0]);
|
||||
if (bo->dumb)
|
||||
virtio_gpu_update_dumb_bo(vgdev, plane->state, &rect);
|
||||
|
||||
if (plane->state->fb != old_state->fb ||
|
||||
plane->state->src_w != old_state->src_w ||
|
||||
plane->state->src_h != old_state->src_h ||
|
||||
plane->state->src_x != old_state->src_x ||
|
||||
plane->state->src_y != old_state->src_y) {
|
||||
DRM_DEBUG("handle 0x%x, crtc %dx%d+%d+%d, src %dx%d+%d+%d\n",
|
||||
bo->hw_res_handle,
|
||||
plane->state->crtc_w, plane->state->crtc_h,
|
||||
plane->state->crtc_x, plane->state->crtc_y,
|
||||
plane->state->src_w >> 16,
|
||||
plane->state->src_h >> 16,
|
||||
plane->state->src_x >> 16,
|
||||
plane->state->src_y >> 16);
|
||||
virtio_gpu_cmd_set_scanout(vgdev, output->index,
|
||||
bo->hw_res_handle,
|
||||
plane->state->src_w >> 16,
|
||||
plane->state->src_h >> 16,
|
||||
plane->state->src_x >> 16,
|
||||
plane->state->src_y >> 16);
|
||||
}
|
||||
|
||||
DRM_DEBUG("handle 0x%x, crtc %dx%d+%d+%d, src %dx%d+%d+%d\n",
|
||||
bo->hw_res_handle,
|
||||
plane->state->crtc_w, plane->state->crtc_h,
|
||||
plane->state->crtc_x, plane->state->crtc_y,
|
||||
plane->state->src_w >> 16,
|
||||
plane->state->src_h >> 16,
|
||||
plane->state->src_x >> 16,
|
||||
plane->state->src_y >> 16);
|
||||
virtio_gpu_cmd_set_scanout(vgdev, output->index,
|
||||
bo->hw_res_handle,
|
||||
plane->state->src_w >> 16,
|
||||
plane->state->src_h >> 16,
|
||||
plane->state->src_x >> 16,
|
||||
plane->state->src_y >> 16);
|
||||
virtio_gpu_cmd_resource_flush(vgdev, bo->hw_res_handle,
|
||||
plane->state->src_x >> 16,
|
||||
plane->state->src_y >> 16,
|
||||
plane->state->src_w >> 16,
|
||||
plane->state->src_h >> 16);
|
||||
rect.x1,
|
||||
rect.y1,
|
||||
rect.x2 - rect.x1,
|
||||
rect.y2 - rect.y1);
|
||||
|
||||
virtio_gpu_enable_notify(vgdev);
|
||||
}
|
||||
|
||||
static int virtio_gpu_cursor_prepare_fb(struct drm_plane *plane,
|
||||
|
@ -404,8 +404,12 @@ static void virtio_gpu_queue_fenced_ctrl_buffer(struct virtio_gpu_device *vgdev,
|
||||
}
|
||||
notify = virtio_gpu_queue_ctrl_buffer_locked(vgdev, vbuf, vout);
|
||||
spin_unlock(&vgdev->ctrlq.qlock);
|
||||
if (notify)
|
||||
virtqueue_notify(vgdev->ctrlq.vq);
|
||||
if (notify) {
|
||||
if (vgdev->disable_notify)
|
||||
vgdev->pending_notify = true;
|
||||
else
|
||||
virtqueue_notify(vgdev->ctrlq.vq);
|
||||
}
|
||||
|
||||
if (sgt) {
|
||||
sg_free_table(sgt);
|
||||
@ -413,6 +417,21 @@ static void virtio_gpu_queue_fenced_ctrl_buffer(struct virtio_gpu_device *vgdev,
|
||||
}
|
||||
}
|
||||
|
||||
void virtio_gpu_disable_notify(struct virtio_gpu_device *vgdev)
|
||||
{
|
||||
vgdev->disable_notify = true;
|
||||
}
|
||||
|
||||
void virtio_gpu_enable_notify(struct virtio_gpu_device *vgdev)
|
||||
{
|
||||
vgdev->disable_notify = false;
|
||||
|
||||
if (!vgdev->pending_notify)
|
||||
return;
|
||||
vgdev->pending_notify = false;
|
||||
virtqueue_notify(vgdev->ctrlq.vq);
|
||||
}
|
||||
|
||||
static void virtio_gpu_queue_ctrl_buffer(struct virtio_gpu_device *vgdev,
|
||||
struct virtio_gpu_vbuffer *vbuf)
|
||||
{
|
||||
|
@ -19,6 +19,13 @@ struct dw_mipi_dsi;
|
||||
struct mipi_dsi_device;
|
||||
struct platform_device;
|
||||
|
||||
struct dw_mipi_dsi_dphy_timing {
|
||||
u16 data_hs2lp;
|
||||
u16 data_lp2hs;
|
||||
u16 clk_hs2lp;
|
||||
u16 clk_lp2hs;
|
||||
};
|
||||
|
||||
struct dw_mipi_dsi_phy_ops {
|
||||
int (*init)(void *priv_data);
|
||||
void (*power_on)(void *priv_data);
|
||||
@ -27,6 +34,8 @@ struct dw_mipi_dsi_phy_ops {
|
||||
const struct drm_display_mode *mode,
|
||||
unsigned long mode_flags, u32 lanes, u32 format,
|
||||
unsigned int *lane_mbps);
|
||||
int (*get_timing)(void *priv_data, unsigned int lane_mbps,
|
||||
struct dw_mipi_dsi_dphy_timing *timing);
|
||||
};
|
||||
|
||||
struct dw_mipi_dsi_host_ops {
|
||||
|
@ -35,7 +35,7 @@
|
||||
* struct drm_crtc_commit - track modeset commits on a CRTC
|
||||
*
|
||||
* This structure is used to track pending modeset changes and atomic commit on
|
||||
* a per-CRTC basis. Since updating the list should never block this structure
|
||||
* a per-CRTC basis. Since updating the list should never block, this structure
|
||||
* is reference counted to allow waiters to safely wait on an event to complete,
|
||||
* without holding any locks.
|
||||
*
|
||||
@ -363,7 +363,7 @@ struct drm_atomic_state {
|
||||
* When a connector or plane is not bound to any CRTC, it's still important
|
||||
* to preserve linearity to prevent the atomic states from being freed to early.
|
||||
*
|
||||
* This commit (if set) is not bound to any crtc, but will be completed when
|
||||
* This commit (if set) is not bound to any CRTC, but will be completed when
|
||||
* drm_atomic_helper_commit_hw_done() is called.
|
||||
*/
|
||||
struct drm_crtc_commit *fake_commit;
|
||||
@ -476,12 +476,12 @@ drm_atomic_get_new_connector_for_encoder(struct drm_atomic_state *state,
|
||||
struct drm_encoder *encoder);
|
||||
|
||||
/**
|
||||
* drm_atomic_get_existing_crtc_state - get crtc state, if it exists
|
||||
* drm_atomic_get_existing_crtc_state - get CRTC state, if it exists
|
||||
* @state: global atomic state object
|
||||
* @crtc: crtc to grab
|
||||
* @crtc: CRTC to grab
|
||||
*
|
||||
* This function returns the crtc state for the given crtc, or NULL
|
||||
* if the crtc is not part of the global atomic state.
|
||||
* This function returns the CRTC state for the given CRTC, or NULL
|
||||
* if the CRTC is not part of the global atomic state.
|
||||
*
|
||||
* This function is deprecated, @drm_atomic_get_old_crtc_state or
|
||||
* @drm_atomic_get_new_crtc_state should be used instead.
|
||||
@ -494,12 +494,12 @@ drm_atomic_get_existing_crtc_state(struct drm_atomic_state *state,
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_atomic_get_old_crtc_state - get old crtc state, if it exists
|
||||
* drm_atomic_get_old_crtc_state - get old CRTC state, if it exists
|
||||
* @state: global atomic state object
|
||||
* @crtc: crtc to grab
|
||||
* @crtc: CRTC to grab
|
||||
*
|
||||
* This function returns the old crtc state for the given crtc, or
|
||||
* NULL if the crtc is not part of the global atomic state.
|
||||
* This function returns the old CRTC state for the given CRTC, or
|
||||
* NULL if the CRTC is not part of the global atomic state.
|
||||
*/
|
||||
static inline struct drm_crtc_state *
|
||||
drm_atomic_get_old_crtc_state(struct drm_atomic_state *state,
|
||||
@ -508,12 +508,12 @@ drm_atomic_get_old_crtc_state(struct drm_atomic_state *state,
|
||||
return state->crtcs[drm_crtc_index(crtc)].old_state;
|
||||
}
|
||||
/**
|
||||
* drm_atomic_get_new_crtc_state - get new crtc state, if it exists
|
||||
* drm_atomic_get_new_crtc_state - get new CRTC state, if it exists
|
||||
* @state: global atomic state object
|
||||
* @crtc: crtc to grab
|
||||
* @crtc: CRTC to grab
|
||||
*
|
||||
* This function returns the new crtc state for the given crtc, or
|
||||
* NULL if the crtc is not part of the global atomic state.
|
||||
* This function returns the new CRTC state for the given CRTC, or
|
||||
* NULL if the CRTC is not part of the global atomic state.
|
||||
*/
|
||||
static inline struct drm_crtc_state *
|
||||
drm_atomic_get_new_crtc_state(struct drm_atomic_state *state,
|
||||
@ -978,11 +978,11 @@ drm_atomic_crtc_needs_modeset(const struct drm_crtc_state *state)
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_atomic_crtc_effectively_active - compute whether crtc is actually active
|
||||
* drm_atomic_crtc_effectively_active - compute whether CRTC is actually active
|
||||
* @state: &drm_crtc_state for the CRTC
|
||||
*
|
||||
* When in self refresh mode, the crtc_state->active value will be false, since
|
||||
* the crtc is off. However in some cases we're interested in whether the crtc
|
||||
* the CRTC is off. However in some cases we're interested in whether the CRTC
|
||||
* is active, or effectively active (ie: it's connected to an active display).
|
||||
* In these cases, use this function instead of just checking active.
|
||||
*/
|
||||
|
@ -152,7 +152,7 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
|
||||
/**
|
||||
* drm_atomic_crtc_for_each_plane - iterate over planes currently attached to CRTC
|
||||
* @plane: the loop cursor
|
||||
* @crtc: the crtc whose planes are iterated
|
||||
* @crtc: the CRTC whose planes are iterated
|
||||
*
|
||||
* This iterates over the current state, useful (for example) when applying
|
||||
* atomic state after it has been checked and swapped. To iterate over the
|
||||
@ -166,7 +166,7 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
|
||||
/**
|
||||
* drm_crtc_atomic_state_for_each_plane - iterate over attached planes in new state
|
||||
* @plane: the loop cursor
|
||||
* @crtc_state: the incoming crtc-state
|
||||
* @crtc_state: the incoming CRTC state
|
||||
*
|
||||
* Similar to drm_crtc_for_each_plane(), but iterates the planes that will be
|
||||
* attached if the specified state is applied. Useful during for example
|
||||
@ -180,7 +180,7 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
|
||||
* drm_crtc_atomic_state_for_each_plane_state - iterate over attached planes in new state
|
||||
* @plane: the loop cursor
|
||||
* @plane_state: loop cursor for the plane's state, must be const
|
||||
* @crtc_state: the incoming crtc-state
|
||||
* @crtc_state: the incoming CRTC state
|
||||
*
|
||||
* Similar to drm_crtc_for_each_plane(), but iterates the planes that will be
|
||||
* attached if the specified state is applied. Useful during for example
|
||||
@ -189,7 +189,7 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
|
||||
*
|
||||
* Compared to just drm_atomic_crtc_state_for_each_plane() this also fills in a
|
||||
* const plane_state. This is useful when a driver just wants to peek at other
|
||||
* active planes on this crtc, but does not need to change it.
|
||||
* active planes on this CRTC, but does not need to change it.
|
||||
*/
|
||||
#define drm_atomic_crtc_state_for_each_plane_state(plane, plane_state, crtc_state) \
|
||||
drm_for_each_plane_mask(plane, (crtc_state)->state->dev, (crtc_state)->plane_mask) \
|
||||
|
@ -1069,6 +1069,14 @@ struct drm_cmdline_mode {
|
||||
*/
|
||||
unsigned int rotation_reflection;
|
||||
|
||||
/**
|
||||
* @panel_orientation:
|
||||
*
|
||||
* drm-connector "panel orientation" property override value,
|
||||
* DRM_MODE_PANEL_ORIENTATION_UNKNOWN if not set.
|
||||
*/
|
||||
enum drm_panel_orientation panel_orientation;
|
||||
|
||||
/**
|
||||
* @tv_margins: TV margins to apply to the mode.
|
||||
*/
|
||||
|
@ -198,7 +198,7 @@ static inline struct drm_panel *of_drm_find_panel(const struct device_node *np)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
|
||||
#if IS_REACHABLE(CONFIG_BACKLIGHT_CLASS_DEVICE)
|
||||
int drm_panel_of_backlight(struct drm_panel *panel);
|
||||
#else
|
||||
static inline int drm_panel_of_backlight(struct drm_panel *panel)
|
||||
|
@ -322,6 +322,8 @@ static inline bool drm_debug_enabled(enum drm_debug_category category)
|
||||
|
||||
/*
|
||||
* struct device based logging
|
||||
*
|
||||
* Prefer drm_device based logging over device or prink based logging.
|
||||
*/
|
||||
|
||||
__printf(3, 4)
|
||||
@ -417,8 +419,71 @@ void drm_dev_dbg(const struct device *dev, enum drm_debug_category category,
|
||||
_DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, DRM_UT_PRIME, \
|
||||
fmt, ##__VA_ARGS__)
|
||||
|
||||
/*
|
||||
* struct drm_device based logging
|
||||
*
|
||||
* Prefer drm_device based logging over device or prink based logging.
|
||||
*/
|
||||
|
||||
/* Helper for struct drm_device based logging. */
|
||||
#define __drm_printk(drm, level, type, fmt, ...) \
|
||||
dev_##level##type((drm)->dev, "[drm] " fmt, ##__VA_ARGS__)
|
||||
|
||||
|
||||
#define drm_info(drm, fmt, ...) \
|
||||
__drm_printk((drm), info,, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define drm_notice(drm, fmt, ...) \
|
||||
__drm_printk((drm), notice,, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define drm_warn(drm, fmt, ...) \
|
||||
__drm_printk((drm), warn,, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define drm_err(drm, fmt, ...) \
|
||||
__drm_printk((drm), err,, "*ERROR* " fmt, ##__VA_ARGS__)
|
||||
|
||||
|
||||
#define drm_info_once(drm, fmt, ...) \
|
||||
__drm_printk((drm), info, _once, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define drm_notice_once(drm, fmt, ...) \
|
||||
__drm_printk((drm), notice, _once, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define drm_warn_once(drm, fmt, ...) \
|
||||
__drm_printk((drm), warn, _once, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define drm_err_once(drm, fmt, ...) \
|
||||
__drm_printk((drm), err, _once, "*ERROR* " fmt, ##__VA_ARGS__)
|
||||
|
||||
|
||||
#define drm_err_ratelimited(drm, fmt, ...) \
|
||||
__drm_printk((drm), err, _ratelimited, "*ERROR* " fmt, ##__VA_ARGS__)
|
||||
|
||||
|
||||
#define drm_dbg_core(drm, fmt, ...) \
|
||||
drm_dev_dbg((drm)->dev, DRM_UT_CORE, fmt, ##__VA_ARGS__)
|
||||
#define drm_dbg(drm, fmt, ...) \
|
||||
drm_dev_dbg((drm)->dev, DRM_UT_DRIVER, fmt, ##__VA_ARGS__)
|
||||
#define drm_dbg_kms(drm, fmt, ...) \
|
||||
drm_dev_dbg((drm)->dev, DRM_UT_KMS, fmt, ##__VA_ARGS__)
|
||||
#define drm_dbg_prime(drm, fmt, ...) \
|
||||
drm_dev_dbg((drm)->dev, DRM_UT_PRIME, fmt, ##__VA_ARGS__)
|
||||
#define drm_dbg_atomic(drm, fmt, ...) \
|
||||
drm_dev_dbg((drm)->dev, DRM_UT_ATOMIC, fmt, ##__VA_ARGS__)
|
||||
#define drm_dbg_vbl(drm, fmt, ...) \
|
||||
drm_dev_dbg((drm)->dev, DRM_UT_VBL, fmt, ##__VA_ARGS__)
|
||||
#define drm_dbg_state(drm, fmt, ...) \
|
||||
drm_dev_dbg((drm)->dev, DRM_UT_STATE, fmt, ##__VA_ARGS__)
|
||||
#define drm_dbg_lease(drm, fmt, ...) \
|
||||
drm_dev_dbg((drm)->dev, DRM_UT_LEASE, fmt, ##__VA_ARGS__)
|
||||
#define drm_dbg_dp(drm, fmt, ...) \
|
||||
drm_dev_dbg((drm)->dev, DRM_UT_DP, fmt, ##__VA_ARGS__)
|
||||
|
||||
|
||||
/*
|
||||
* printk based logging
|
||||
*
|
||||
* Prefer drm_device based logging over device or prink based logging.
|
||||
*/
|
||||
|
||||
__printf(2, 3)
|
||||
|
@ -42,12 +42,12 @@ struct dma_heap_allocation_data {
|
||||
#define DMA_HEAP_IOC_MAGIC 'H'
|
||||
|
||||
/**
|
||||
* DOC: DMA_HEAP_IOC_ALLOC - allocate memory from pool
|
||||
* DOC: DMA_HEAP_IOCTL_ALLOC - allocate memory from pool
|
||||
*
|
||||
* Takes a dma_heap_allocation_data struct and returns it with the fd field
|
||||
* populated with the dmabuf handle of the allocation.
|
||||
*/
|
||||
#define DMA_HEAP_IOC_ALLOC _IOWR(DMA_HEAP_IOC_MAGIC, 0x0,\
|
||||
#define DMA_HEAP_IOCTL_ALLOC _IOWR(DMA_HEAP_IOC_MAGIC, 0x0,\
|
||||
struct dma_heap_allocation_data)
|
||||
|
||||
#endif /* _UAPI_LINUX_DMABUF_POOL_H */
|
||||
|
@ -116,7 +116,7 @@ static int dmabuf_heap_alloc_fdflags(int fd, size_t len, unsigned int fd_flags,
|
||||
if (!dmabuf_fd)
|
||||
return -EINVAL;
|
||||
|
||||
ret = ioctl(fd, DMA_HEAP_IOC_ALLOC, &data);
|
||||
ret = ioctl(fd, DMA_HEAP_IOCTL_ALLOC, &data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*dmabuf_fd = (int)data.fd;
|
||||
|
Loading…
Reference in New Issue
Block a user