mirror of https://gitee.com/openkylin/linux.git
drm-misc-next for 5.7:
UAPI Changes: Cross-subsystem Changes: Core Changes: Driver Changes: - fb-helper: Remove drm_fb_helper_{add,add_all,remove}_one_connector - fbdev: some cleanups and dead-code removal - Conversions to simple-encoder - zero-length array removal - Panel: panel-dpi support in panel-simple, Novatek NT35510, Elida KD35T133, -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQRcEzekXsqa64kGDp7j7w1vZxhRxQUCXmZKhwAKCRDj7w1vZxhR xUgxAQDB1kkf1xQdU7rdw344vaaMf270qBeG+GNX/py3h9pbnwEA7XQvbB1wWBec hR629PO+csE0dWcFkGi8d5kpdWQCOQY= =PRn3 -----END PGP SIGNATURE----- Merge tag 'drm-misc-next-2020-03-09' of git://anongit.freedesktop.org/drm/drm-misc into drm-next drm-misc-next for 5.7: UAPI Changes: Cross-subsystem Changes: Core Changes: Driver Changes: - fb-helper: Remove drm_fb_helper_{add,add_all,remove}_one_connector - fbdev: some cleanups and dead-code removal - Conversions to simple-encoder - zero-length array removal - Panel: panel-dpi support in panel-simple, Novatek NT35510, Elida KD35T133, Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20200309135439.dicfnbo4ikj4tkz7@gilmour
This commit is contained in:
commit
9e12da086e
|
@ -1,123 +1 @@
|
|||
display-timing bindings
|
||||
=======================
|
||||
|
||||
display-timings node
|
||||
--------------------
|
||||
|
||||
required properties:
|
||||
- none
|
||||
|
||||
optional properties:
|
||||
- native-mode: The native mode for the display, in case multiple modes are
|
||||
provided. When omitted, assume the first node is the native.
|
||||
|
||||
timing subnode
|
||||
--------------
|
||||
|
||||
required properties:
|
||||
- hactive, vactive: display resolution
|
||||
- hfront-porch, hback-porch, hsync-len: horizontal display timing parameters
|
||||
in pixels
|
||||
vfront-porch, vback-porch, vsync-len: vertical display timing parameters in
|
||||
lines
|
||||
- clock-frequency: display clock in Hz
|
||||
|
||||
optional properties:
|
||||
- hsync-active: hsync pulse is active low/high/ignored
|
||||
- vsync-active: vsync pulse is active low/high/ignored
|
||||
- de-active: data-enable pulse is active low/high/ignored
|
||||
- pixelclk-active: with
|
||||
- active high = drive pixel data on rising edge/
|
||||
sample data on falling edge
|
||||
- active low = drive pixel data on falling edge/
|
||||
sample data on rising edge
|
||||
- ignored = ignored
|
||||
- syncclk-active: with
|
||||
- active high = drive sync on rising edge/
|
||||
sample sync on falling edge of pixel
|
||||
clock
|
||||
- active low = drive sync on falling edge/
|
||||
sample sync on rising edge of pixel
|
||||
clock
|
||||
- omitted = same configuration as pixelclk-active
|
||||
- interlaced (bool): boolean to enable interlaced mode
|
||||
- doublescan (bool): boolean to enable doublescan mode
|
||||
- doubleclk (bool): boolean to enable doubleclock mode
|
||||
|
||||
All the optional properties that are not bool follow the following logic:
|
||||
<1>: high active
|
||||
<0>: low active
|
||||
omitted: not used on hardware
|
||||
|
||||
There are different ways of describing the capabilities of a display. The
|
||||
devicetree representation corresponds to the one commonly found in datasheets
|
||||
for displays. If a display supports multiple signal timings, the native-mode
|
||||
can be specified.
|
||||
|
||||
The parameters are defined as:
|
||||
|
||||
+----------+-------------------------------------+----------+-------+
|
||||
| | ^ | | |
|
||||
| | |vback_porch | | |
|
||||
| | v | | |
|
||||
+----------#######################################----------+-------+
|
||||
| # ^ # | |
|
||||
| # | # | |
|
||||
| hback # | # hfront | hsync |
|
||||
| porch # | hactive # porch | len |
|
||||
|<-------->#<-------+--------------------------->#<-------->|<----->|
|
||||
| # | # | |
|
||||
| # |vactive # | |
|
||||
| # | # | |
|
||||
| # v # | |
|
||||
+----------#######################################----------+-------+
|
||||
| | ^ | | |
|
||||
| | |vfront_porch | | |
|
||||
| | v | | |
|
||||
+----------+-------------------------------------+----------+-------+
|
||||
| | ^ | | |
|
||||
| | |vsync_len | | |
|
||||
| | v | | |
|
||||
+----------+-------------------------------------+----------+-------+
|
||||
|
||||
Note: In addition to being used as subnode(s) of display-timings, the timing
|
||||
subnode may also be used on its own. This is appropriate if only one mode
|
||||
need be conveyed. In this case, the node should be named 'panel-timing'.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
display-timings {
|
||||
native-mode = <&timing0>;
|
||||
timing0: 1080p24 {
|
||||
/* 1920x1080p24 */
|
||||
clock-frequency = <52000000>;
|
||||
hactive = <1920>;
|
||||
vactive = <1080>;
|
||||
hfront-porch = <25>;
|
||||
hback-porch = <25>;
|
||||
hsync-len = <25>;
|
||||
vback-porch = <2>;
|
||||
vfront-porch = <2>;
|
||||
vsync-len = <2>;
|
||||
hsync-active = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
Every required property also supports the use of ranges, so the commonly used
|
||||
datasheet description with minimum, typical and maximum values can be used.
|
||||
|
||||
Example:
|
||||
|
||||
timing1: timing {
|
||||
/* 1920x1080p24 */
|
||||
clock-frequency = <148500000>;
|
||||
hactive = <1920>;
|
||||
vactive = <1080>;
|
||||
hsync-len = <0 44 60>;
|
||||
hfront-porch = <80 88 95>;
|
||||
hback-porch = <100 148 160>;
|
||||
vfront-porch = <0 4 6>;
|
||||
vback-porch = <0 36 50>;
|
||||
vsync-len = <0 5 6>;
|
||||
};
|
||||
See display-timings.yaml in this directory.
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/display-timings.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: display timing bindings
|
||||
|
||||
maintainers:
|
||||
- Thierry Reding <thierry.reding@gmail.com>
|
||||
- Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
- Sam Ravnborg <sam@ravnborg.org>
|
||||
|
||||
description: |
|
||||
A display panel may be able to handle several display timings,
|
||||
with different resolutions.
|
||||
The display-timings node makes it possible to specify the timing
|
||||
and to specify the timing that is native for the display.
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
const: display-timings
|
||||
|
||||
native-mode:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: |
|
||||
The default display timing is the one specified as native-mode.
|
||||
If no native-mode is specified then the first node is assumed the
|
||||
native mode.
|
||||
|
||||
patternProperties:
|
||||
"^timing":
|
||||
type: object
|
||||
allOf:
|
||||
- $ref: panel-timing.yaml#
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |+
|
||||
|
||||
/*
|
||||
* Example that specifies panel timing using minimum, typical,
|
||||
* maximum values as commonly used in datasheet description.
|
||||
* timing1 is the native-mode.
|
||||
*/
|
||||
display-timings {
|
||||
native-mode = <&timing1>;
|
||||
timing0 {
|
||||
/* 1920x1080p24 */
|
||||
clock-frequency = <148500000>;
|
||||
hactive = <1920>;
|
||||
vactive = <1080>;
|
||||
hsync-len = <0 44 60>;
|
||||
hfront-porch = <80 88 95>;
|
||||
hback-porch = <100 148 160>;
|
||||
vfront-porch = <0 4 6>;
|
||||
vback-porch = <0 36 50>;
|
||||
vsync-len = <0 5 6>;
|
||||
};
|
||||
timing1 {
|
||||
/* 1920x1080p24 */
|
||||
clock-frequency = <52000000>;
|
||||
hactive = <1920>;
|
||||
vactive = <1080>;
|
||||
hfront-porch = <25>;
|
||||
hback-porch = <25>;
|
||||
hsync-len = <0 25 25>;
|
||||
vback-porch = <2>;
|
||||
vfront-porch = <2>;
|
||||
vsync-len = <2>;
|
||||
hsync-active = <1>;
|
||||
pixelclk-active = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -0,0 +1,49 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/elida,kd35t133.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Elida KD35T133 3.5in 320x480 DSI panel
|
||||
|
||||
maintainers:
|
||||
- Heiko Stuebner <heiko.stuebner@theobroma-systems.com>
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: elida,kd35t133
|
||||
reg: true
|
||||
backlight: true
|
||||
reset-gpios: true
|
||||
iovcc-supply:
|
||||
description: regulator that supplies the iovcc voltage
|
||||
vdd-supply:
|
||||
description: regulator that supplies the vdd voltage
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- backlight
|
||||
- iovcc-supply
|
||||
- vdd-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
dsi@ff450000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
panel@0 {
|
||||
compatible = "elida,kd35t133";
|
||||
reg = <0>;
|
||||
backlight = <&backlight>;
|
||||
iovcc-supply = <&vcc_1v8>;
|
||||
vdd-supply = <&vcc3v3_lcd>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -0,0 +1,56 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/novatek,nt35510.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Novatek NT35510-based display panels
|
||||
|
||||
maintainers:
|
||||
- Linus Walleij <linus.walleij@linaro.org>
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- const: hydis,hva40wv1
|
||||
- const: novatek,nt35510
|
||||
description: This indicates the panel manufacturer of the panel
|
||||
that is in turn using the NT35510 panel driver. The compatible
|
||||
string determines how the NT35510 panel driver shall be configured
|
||||
to work with the indicated panel. The novatek,nt35510 compatible shall
|
||||
always be provided as a fallback.
|
||||
reg: true
|
||||
reset-gpios: true
|
||||
vdd-supply:
|
||||
description: regulator that supplies the vdd voltage
|
||||
vddi-supply:
|
||||
description: regulator that supplies the vddi voltage
|
||||
backlight: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
dsi@a0351000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
panel {
|
||||
compatible = "hydis,hva40wv1", "novatek,nt35510";
|
||||
reg = <0>;
|
||||
vdd-supply = <&ab8500_ldo_aux4_reg>;
|
||||
vddi-supply = <&ab8500_ldo_aux6_reg>;
|
||||
reset-gpios = <&gpio4 11 GPIO_ACTIVE_LOW>;
|
||||
backlight = <&gpio_bl>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -54,13 +54,20 @@ properties:
|
|||
|
||||
# Display Timings
|
||||
panel-timing:
|
||||
type: object
|
||||
description:
|
||||
Most display panels are restricted to a single resolution and
|
||||
require specific display timings. The panel-timing subnode expresses those
|
||||
timings as specified in the timing subnode section of the display timing
|
||||
bindings defined in
|
||||
Documentation/devicetree/bindings/display/panel/display-timing.txt.
|
||||
timings.
|
||||
allOf:
|
||||
- $ref: panel-timing.yaml#
|
||||
|
||||
display-timings:
|
||||
description:
|
||||
Some display panels supports several resolutions with different timing.
|
||||
The display-timings bindings supports specifying several timings and
|
||||
optional specify which is the native mode.
|
||||
allOf:
|
||||
- $ref: display-timings.yaml#
|
||||
|
||||
# Connectivity
|
||||
port:
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
Generic MIPI DPI Panel
|
||||
======================
|
||||
|
||||
Required properties:
|
||||
- compatible: "panel-dpi"
|
||||
|
||||
Optional properties:
|
||||
- label: a symbolic name for the panel
|
||||
- enable-gpios: panel enable gpio
|
||||
- reset-gpios: GPIO to control the RESET pin
|
||||
- vcc-supply: phandle of regulator that will be used to enable power to the display
|
||||
- backlight: phandle of the backlight device
|
||||
|
||||
Required nodes:
|
||||
- "panel-timing" containing video timings
|
||||
(Documentation/devicetree/bindings/display/panel/display-timing.txt)
|
||||
- Video port for DPI input
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
lcd0: display@0 {
|
||||
compatible = "samsung,lte430wq-f0c", "panel-dpi";
|
||||
label = "lcd";
|
||||
|
||||
backlight = <&backlight>;
|
||||
|
||||
port {
|
||||
lcd_in: endpoint {
|
||||
remote-endpoint = <&dpi_out>;
|
||||
};
|
||||
};
|
||||
|
||||
panel-timing {
|
||||
clock-frequency = <9200000>;
|
||||
hactive = <480>;
|
||||
vactive = <272>;
|
||||
hfront-porch = <8>;
|
||||
hback-porch = <4>;
|
||||
hsync-len = <41>;
|
||||
vback-porch = <2>;
|
||||
vfront-porch = <4>;
|
||||
vsync-len = <10>;
|
||||
|
||||
hsync-active = <0>;
|
||||
vsync-active = <0>;
|
||||
de-active = <1>;
|
||||
pixelclk-active = <1>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,81 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/panel-dpi.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Generic MIPI DPI Panel
|
||||
|
||||
maintainers:
|
||||
- Sam Ravnborg <sam@ravnborg.org>
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
description:
|
||||
Shall contain a panel specific compatible and "panel-dpi"
|
||||
in that order.
|
||||
items:
|
||||
- {}
|
||||
- const: panel-dpi
|
||||
|
||||
data-mapping:
|
||||
enum:
|
||||
- rgb24
|
||||
- rgb565
|
||||
- bgr666
|
||||
description: |
|
||||
Describes the media format, how the display panel is connected
|
||||
to the display interface.
|
||||
|
||||
backlight: true
|
||||
enable-gpios: true
|
||||
height-mm: true
|
||||
label: true
|
||||
panel-timing: true
|
||||
port: true
|
||||
power-supply: true
|
||||
reset-gpios: true
|
||||
width-mm: true
|
||||
|
||||
required:
|
||||
- panel-timing
|
||||
- power-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
panel@0 {
|
||||
compatible = "osddisplays,osd057T0559-34ts", "panel-dpi";
|
||||
label = "osddisplay";
|
||||
power-supply = <&vcc_supply>;
|
||||
data-mapping = "rgb565";
|
||||
backlight = <&backlight>;
|
||||
|
||||
port {
|
||||
lcd_in: endpoint {
|
||||
remote-endpoint = <&dpi_out>;
|
||||
};
|
||||
};
|
||||
panel-timing {
|
||||
clock-frequency = <9200000>;
|
||||
hactive = <800>;
|
||||
vactive = <480>;
|
||||
hfront-porch = <8>;
|
||||
hback-porch = <4>;
|
||||
hsync-len = <41>;
|
||||
vback-porch = <2>;
|
||||
vfront-porch = <4>;
|
||||
vsync-len = <10>;
|
||||
|
||||
hsync-active = <0>;
|
||||
vsync-active = <0>;
|
||||
de-active = <1>;
|
||||
pixelclk-active = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -177,6 +177,8 @@ properties:
|
|||
- nec,nl4827hc19-05b
|
||||
# Netron-DY E231732 7.0" WSVGA TFT LCD panel
|
||||
- netron-dy,e231732
|
||||
# NewEast Optoelectronics CO., LTD WJFH116008A eDP TFT LCD panel
|
||||
- neweast,wjfh116008a
|
||||
# Newhaven Display International 480 x 272 TFT LCD panel
|
||||
- newhaven,nhd-4.3-480272ef-atxl
|
||||
# NLT Technologies, Ltd. 15.6" FHD (1920x1080) LVDS TFT LCD panel
|
||||
|
|
|
@ -0,0 +1,227 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/panel-timing.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: panel timing bindings
|
||||
|
||||
maintainers:
|
||||
- Thierry Reding <thierry.reding@gmail.com>
|
||||
- Sam Ravnborg <sam@ravnborg.org>
|
||||
|
||||
description: |
|
||||
There are different ways of describing the timing data of a panel. The
|
||||
devicetree representation corresponds to the one commonly found in datasheets
|
||||
for panels.
|
||||
|
||||
The parameters are defined as seen in the following illustration.
|
||||
|
||||
+----------+-------------------------------------+----------+-------+
|
||||
| | ^ | | |
|
||||
| | |vback_porch | | |
|
||||
| | v | | |
|
||||
+----------#######################################----------+-------+
|
||||
| # ^ # | |
|
||||
| # | # | |
|
||||
| hback # | # hfront | hsync |
|
||||
| porch # | hactive # porch | len |
|
||||
|<-------->#<-------+--------------------------->#<-------->|<----->|
|
||||
| # | # | |
|
||||
| # |vactive # | |
|
||||
| # | # | |
|
||||
| # v # | |
|
||||
+----------#######################################----------+-------+
|
||||
| | ^ | | |
|
||||
| | |vfront_porch | | |
|
||||
| | v | | |
|
||||
+----------+-------------------------------------+----------+-------+
|
||||
| | ^ | | |
|
||||
| | |vsync_len | | |
|
||||
| | v | | |
|
||||
+----------+-------------------------------------+----------+-------+
|
||||
|
||||
|
||||
The following is the panel timings shown with time on the x-axis.
|
||||
This matches the timing diagrams often found in data sheets.
|
||||
|
||||
Active Front Sync Back
|
||||
Region Porch Porch
|
||||
<-----------------------><----------------><-------------><-------------->
|
||||
//////////////////////|
|
||||
////////////////////// |
|
||||
////////////////////// |.................. ................
|
||||
_______________
|
||||
|
||||
Timing can be specified either as a typical value or as a tuple
|
||||
of min, typ, max values.
|
||||
|
||||
properties:
|
||||
|
||||
clock-frequency:
|
||||
description: Panel clock in Hz
|
||||
|
||||
hactive:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: Horizontal panel resolution in pixels
|
||||
|
||||
vactive:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: Vertical panel resolution in pixels
|
||||
|
||||
hfront-porch:
|
||||
description: Horizontal front porch panel timing
|
||||
oneOf:
|
||||
- allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32
|
||||
- maxItems: 1
|
||||
items:
|
||||
description: typical number of pixels
|
||||
- allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
- minItems: 3
|
||||
maxItems: 3
|
||||
items:
|
||||
description: min, typ, max number of pixels
|
||||
|
||||
hback-porch:
|
||||
description: Horizontal back porch timing
|
||||
oneOf:
|
||||
- allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32
|
||||
- maxItems: 1
|
||||
items:
|
||||
description: typical number of pixels
|
||||
- allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
- minItems: 3
|
||||
maxItems: 3
|
||||
items:
|
||||
description: min, typ, max number of pixels
|
||||
|
||||
hsync-len:
|
||||
description: Horizontal sync length panel timing
|
||||
oneOf:
|
||||
- allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32
|
||||
- maxItems: 1
|
||||
items:
|
||||
description: typical number of pixels
|
||||
- allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
- minItems: 3
|
||||
maxItems: 3
|
||||
items:
|
||||
description: min, typ, max number of pixels
|
||||
|
||||
vfront-porch:
|
||||
description: Vertical front porch panel timing
|
||||
oneOf:
|
||||
- allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32
|
||||
- maxItems: 1
|
||||
items:
|
||||
description: typical number of lines
|
||||
- allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
- minItems: 3
|
||||
maxItems: 3
|
||||
items:
|
||||
description: min, typ, max number of lines
|
||||
|
||||
vback-porch:
|
||||
description: Vertical back porch panel timing
|
||||
oneOf:
|
||||
- allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32
|
||||
- maxItems: 1
|
||||
items:
|
||||
description: typical number of lines
|
||||
- allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
- minItems: 3
|
||||
maxItems: 3
|
||||
items:
|
||||
description: min, typ, max number of lines
|
||||
|
||||
vsync-len:
|
||||
description: Vertical sync length panel timing
|
||||
oneOf:
|
||||
- allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32
|
||||
- maxItems: 1
|
||||
items:
|
||||
description: typical number of lines
|
||||
- allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
- minItems: 3
|
||||
maxItems: 3
|
||||
items:
|
||||
description: min, typ, max number of lines
|
||||
|
||||
hsync-active:
|
||||
description: |
|
||||
Horizontal sync pulse.
|
||||
0 selects active low, 1 selects active high.
|
||||
If omitted then it is not used by the hardware
|
||||
enum: [0, 1]
|
||||
|
||||
vsync-active:
|
||||
description: |
|
||||
Vertical sync pulse.
|
||||
0 selects active low, 1 selects active high.
|
||||
If omitted then it is not used by the hardware
|
||||
enum: [0, 1]
|
||||
|
||||
de-active:
|
||||
description: |
|
||||
Data enable.
|
||||
0 selects active low, 1 selects active high.
|
||||
If omitted then it is not used by the hardware
|
||||
enum: [0, 1]
|
||||
|
||||
pixelclk-active:
|
||||
description: |
|
||||
Data driving on rising or falling edge.
|
||||
Use 0 to drive pixel data on falling edge and
|
||||
sample data on rising edge.
|
||||
Use 1 to drive pixel data on rising edge and
|
||||
sample data on falling edge
|
||||
enum: [0, 1]
|
||||
|
||||
syncclk-active:
|
||||
description: |
|
||||
Drive sync on rising or sample sync on falling edge.
|
||||
If not specified then the setup is as specified by pixelclk-active.
|
||||
Use 0 to drive sync on falling edge and
|
||||
sample sync on rising edge of pixel clock.
|
||||
Use 1 to drive sync on rising edge and
|
||||
sample sync on falling edge of pixel clock
|
||||
enum: [0, 1]
|
||||
|
||||
interlaced:
|
||||
type: boolean
|
||||
description: Enable interlaced mode
|
||||
|
||||
doublescan:
|
||||
type: boolean
|
||||
description: Enable double scan mode
|
||||
|
||||
doubleclk:
|
||||
type: boolean
|
||||
description: Enable double clock mode
|
||||
|
||||
required:
|
||||
- clock-frequency
|
||||
- hactive
|
||||
- vactive
|
||||
- hfront-porch
|
||||
- hback-porch
|
||||
- hsync-len
|
||||
- vfront-porch
|
||||
- vback-porch
|
||||
- vsync-len
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
...
|
|
@ -1,19 +0,0 @@
|
|||
Rockchip DRM master device
|
||||
================================
|
||||
|
||||
The Rockchip DRM master device is a virtual device needed to list all
|
||||
vop devices or other display interface nodes that comprise the
|
||||
graphics subsystem.
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "rockchip,display-subsystem"
|
||||
- ports: Should contain a list of phandles pointing to display interface port
|
||||
of vop devices. vop definitions as defined in
|
||||
Documentation/devicetree/bindings/display/rockchip/rockchip-vop.txt
|
||||
|
||||
example:
|
||||
|
||||
display-subsystem {
|
||||
compatible = "rockchip,display-subsystem";
|
||||
ports = <&vopl_out>, <&vopb_out>;
|
||||
};
|
|
@ -0,0 +1,40 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/rockchip/rockchip-drm.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Rockchip DRM master device
|
||||
|
||||
maintainers:
|
||||
- Sandy Huang <hjc@rock-chips.com>
|
||||
- Heiko Stuebner <heiko@sntech.de>
|
||||
|
||||
description: |
|
||||
The Rockchip DRM master device is a virtual device needed to list all
|
||||
vop devices or other display interface nodes that comprise the
|
||||
graphics subsystem.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: rockchip,display-subsystem
|
||||
|
||||
ports:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
description: |
|
||||
Should contain a list of phandles pointing to display interface port
|
||||
of vop devices. vop definitions as defined in
|
||||
Documentation/devicetree/bindings/display/rockchip/rockchip-vop.txt
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- ports
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
display-subsystem {
|
||||
compatible = "rockchip,display-subsystem";
|
||||
ports = <&vopl_out>, <&vopb_out>;
|
||||
};
|
|
@ -425,6 +425,8 @@ patternProperties:
|
|||
description: Shenzhen Hugsun Technology Co. Ltd.
|
||||
"^hwacom,.*":
|
||||
description: HwaCom Systems Inc.
|
||||
"^hydis,.*":
|
||||
description: Hydis Technologies
|
||||
"^hyundai,.*":
|
||||
description: Hyundai Technology
|
||||
"^i2se,.*":
|
||||
|
@ -665,6 +667,8 @@ patternProperties:
|
|||
description: Netron DY
|
||||
"^netxeon,.*":
|
||||
description: Shenzhen Netxeon Technology CO., LTD
|
||||
"^neweast,.*":
|
||||
description: Guangdong Neweast Optoelectronics CO., LTD
|
||||
"^nexbox,.*":
|
||||
description: Nexbox
|
||||
"^nextthing,.*":
|
||||
|
|
|
@ -359,23 +359,6 @@ Contact: Sean Paul
|
|||
|
||||
Level: Starter
|
||||
|
||||
drm_fb_helper tasks
|
||||
-------------------
|
||||
|
||||
- drm_fb_helper_restore_fbdev_mode_unlocked() should call restore_fbdev_mode()
|
||||
not the _force variant so it can bail out if there is a master. But first
|
||||
these igt tests need to be fixed: kms_fbcon_fbt@psr and
|
||||
kms_fbcon_fbt@psr-suspend.
|
||||
|
||||
- The max connector argument for drm_fb_helper_init() isn't used anymore and
|
||||
can be removed.
|
||||
|
||||
- The helper doesn't keep an array of connectors anymore so these can be
|
||||
removed: drm_fb_helper_single_add_all_connectors(),
|
||||
drm_fb_helper_add_one_connector() and drm_fb_helper_remove_one_connector().
|
||||
|
||||
Level: Intermediate
|
||||
|
||||
connector register/unregister fixes
|
||||
-----------------------------------
|
||||
|
||||
|
|
|
@ -5022,7 +5022,7 @@ L: dri-devel@lists.freedesktop.org
|
|||
L: linaro-mm-sig@lists.linaro.org (moderated for non-subscribers)
|
||||
F: drivers/dma-buf/
|
||||
F: include/linux/dma-buf*
|
||||
F: include/linux/reservation.h
|
||||
F: include/linux/dma-resv.h
|
||||
F: include/linux/*fence.h
|
||||
F: Documentation/driver-api/dma-buf.rst
|
||||
K: dma_(buf|fence|resv)
|
||||
|
@ -5336,6 +5336,13 @@ F: drivers/gpu/drm/msm/
|
|||
F: include/uapi/drm/msm_drm.h
|
||||
F: Documentation/devicetree/bindings/display/msm/
|
||||
|
||||
DRM DRIVER FOR NOVATEK NT35510 PANELS
|
||||
M: Linus Walleij <linus.walleij@linaro.org>
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
S: Maintained
|
||||
F: drivers/gpu/drm/panel/panel-novatek-nt35510.c
|
||||
F: Documentation/devicetree/bindings/display/panel/novatek,nt35510.yaml
|
||||
|
||||
DRM DRIVER FOR NVIDIA GEFORCE/QUADRO GPUS
|
||||
M: Ben Skeggs <bskeggs@redhat.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
|
|
|
@ -39,6 +39,16 @@ config UDMABUF
|
|||
A driver to let userspace turn memfd regions into dma-bufs.
|
||||
Qemu can use this to create host dmabufs for guest framebuffers.
|
||||
|
||||
config DMABUF_MOVE_NOTIFY
|
||||
bool "Move notify between drivers (EXPERIMENTAL)"
|
||||
default n
|
||||
help
|
||||
Don''t pin buffers if the dynamic DMA-buf interface is available on both the
|
||||
exporter as well as the importer. This fixes a security problem where
|
||||
userspace is able to pin unrestricted amounts of memory through DMA-buf.
|
||||
But marked experimental because we don''t jet have a consistent execution
|
||||
context and memory management between drivers.
|
||||
|
||||
config DMABUF_SELFTESTS
|
||||
tristate "Selftests for the dma-buf interfaces"
|
||||
default n
|
||||
|
|
|
@ -525,7 +525,10 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
|
|||
}
|
||||
|
||||
if (WARN_ON(exp_info->ops->cache_sgt_mapping &&
|
||||
exp_info->ops->dynamic_mapping))
|
||||
(exp_info->ops->pin || exp_info->ops->unpin)))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (WARN_ON(!exp_info->ops->pin != !exp_info->ops->unpin))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (!try_module_get(exp_info->owner))
|
||||
|
@ -652,7 +655,8 @@ EXPORT_SYMBOL_GPL(dma_buf_put);
|
|||
* calls attach() of dma_buf_ops to allow device-specific attach functionality
|
||||
* @dmabuf: [in] buffer to attach device to.
|
||||
* @dev: [in] device to be attached.
|
||||
* @dynamic_mapping: [in] calling convention for map/unmap
|
||||
* @importer_ops [in] importer operations for the attachment
|
||||
* @importer_priv [in] importer private pointer for the attachment
|
||||
*
|
||||
* Returns struct dma_buf_attachment pointer for this attachment. Attachments
|
||||
* must be cleaned up by calling dma_buf_detach().
|
||||
|
@ -668,7 +672,8 @@ EXPORT_SYMBOL_GPL(dma_buf_put);
|
|||
*/
|
||||
struct dma_buf_attachment *
|
||||
dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
|
||||
bool dynamic_mapping)
|
||||
const struct dma_buf_attach_ops *importer_ops,
|
||||
void *importer_priv)
|
||||
{
|
||||
struct dma_buf_attachment *attach;
|
||||
int ret;
|
||||
|
@ -676,13 +681,17 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
|
|||
if (WARN_ON(!dmabuf || !dev))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (WARN_ON(importer_ops && !importer_ops->move_notify))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
attach = kzalloc(sizeof(*attach), GFP_KERNEL);
|
||||
if (!attach)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
attach->dev = dev;
|
||||
attach->dmabuf = dmabuf;
|
||||
attach->dynamic_mapping = dynamic_mapping;
|
||||
attach->importer_ops = importer_ops;
|
||||
attach->importer_priv = importer_priv;
|
||||
|
||||
if (dmabuf->ops->attach) {
|
||||
ret = dmabuf->ops->attach(dmabuf, attach);
|
||||
|
@ -701,15 +710,19 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
|
|||
dma_buf_is_dynamic(dmabuf)) {
|
||||
struct sg_table *sgt;
|
||||
|
||||
if (dma_buf_is_dynamic(attach->dmabuf))
|
||||
if (dma_buf_is_dynamic(attach->dmabuf)) {
|
||||
dma_resv_lock(attach->dmabuf->resv, NULL);
|
||||
ret = dma_buf_pin(attach);
|
||||
if (ret)
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
sgt = dmabuf->ops->map_dma_buf(attach, DMA_BIDIRECTIONAL);
|
||||
if (!sgt)
|
||||
sgt = ERR_PTR(-ENOMEM);
|
||||
if (IS_ERR(sgt)) {
|
||||
ret = PTR_ERR(sgt);
|
||||
goto err_unlock;
|
||||
goto err_unpin;
|
||||
}
|
||||
if (dma_buf_is_dynamic(attach->dmabuf))
|
||||
dma_resv_unlock(attach->dmabuf->resv);
|
||||
|
@ -723,6 +736,10 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
|
|||
kfree(attach);
|
||||
return ERR_PTR(ret);
|
||||
|
||||
err_unpin:
|
||||
if (dma_buf_is_dynamic(attach->dmabuf))
|
||||
dma_buf_unpin(attach);
|
||||
|
||||
err_unlock:
|
||||
if (dma_buf_is_dynamic(attach->dmabuf))
|
||||
dma_resv_unlock(attach->dmabuf->resv);
|
||||
|
@ -743,7 +760,7 @@ EXPORT_SYMBOL_GPL(dma_buf_dynamic_attach);
|
|||
struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
|
||||
struct device *dev)
|
||||
{
|
||||
return dma_buf_dynamic_attach(dmabuf, dev, false);
|
||||
return dma_buf_dynamic_attach(dmabuf, dev, NULL, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dma_buf_attach);
|
||||
|
||||
|
@ -766,8 +783,10 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
|
|||
|
||||
dmabuf->ops->unmap_dma_buf(attach, attach->sgt, attach->dir);
|
||||
|
||||
if (dma_buf_is_dynamic(attach->dmabuf))
|
||||
if (dma_buf_is_dynamic(attach->dmabuf)) {
|
||||
dma_buf_unpin(attach);
|
||||
dma_resv_unlock(attach->dmabuf->resv);
|
||||
}
|
||||
}
|
||||
|
||||
dma_resv_lock(dmabuf->resv, NULL);
|
||||
|
@ -780,6 +799,44 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(dma_buf_detach);
|
||||
|
||||
/**
|
||||
* dma_buf_pin - Lock down the DMA-buf
|
||||
*
|
||||
* @attach: [in] attachment which should be pinned
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success, negative error code on failure.
|
||||
*/
|
||||
int dma_buf_pin(struct dma_buf_attachment *attach)
|
||||
{
|
||||
struct dma_buf *dmabuf = attach->dmabuf;
|
||||
int ret = 0;
|
||||
|
||||
dma_resv_assert_held(dmabuf->resv);
|
||||
|
||||
if (dmabuf->ops->pin)
|
||||
ret = dmabuf->ops->pin(attach);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dma_buf_pin);
|
||||
|
||||
/**
|
||||
* dma_buf_unpin - Remove lock from DMA-buf
|
||||
*
|
||||
* @attach: [in] attachment which should be unpinned
|
||||
*/
|
||||
void dma_buf_unpin(struct dma_buf_attachment *attach)
|
||||
{
|
||||
struct dma_buf *dmabuf = attach->dmabuf;
|
||||
|
||||
dma_resv_assert_held(dmabuf->resv);
|
||||
|
||||
if (dmabuf->ops->unpin)
|
||||
dmabuf->ops->unpin(attach);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dma_buf_unpin);
|
||||
|
||||
/**
|
||||
* dma_buf_map_attachment - Returns the scatterlist table of the attachment;
|
||||
* mapped into _device_ address space. Is a wrapper for map_dma_buf() of the
|
||||
|
@ -799,6 +856,7 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
|
|||
enum dma_data_direction direction)
|
||||
{
|
||||
struct sg_table *sg_table;
|
||||
int r;
|
||||
|
||||
might_sleep();
|
||||
|
||||
|
@ -820,13 +878,23 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
|
|||
return attach->sgt;
|
||||
}
|
||||
|
||||
if (dma_buf_is_dynamic(attach->dmabuf))
|
||||
if (dma_buf_is_dynamic(attach->dmabuf)) {
|
||||
dma_resv_assert_held(attach->dmabuf->resv);
|
||||
if (!IS_ENABLED(CONFIG_DMABUF_MOVE_NOTIFY)) {
|
||||
r = dma_buf_pin(attach);
|
||||
if (r)
|
||||
return ERR_PTR(r);
|
||||
}
|
||||
}
|
||||
|
||||
sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction);
|
||||
if (!sg_table)
|
||||
sg_table = ERR_PTR(-ENOMEM);
|
||||
|
||||
if (IS_ERR(sg_table) && dma_buf_is_dynamic(attach->dmabuf) &&
|
||||
!IS_ENABLED(CONFIG_DMABUF_MOVE_NOTIFY))
|
||||
dma_buf_unpin(attach);
|
||||
|
||||
if (!IS_ERR(sg_table) && attach->dmabuf->ops->cache_sgt_mapping) {
|
||||
attach->sgt = sg_table;
|
||||
attach->dir = direction;
|
||||
|
@ -865,9 +933,33 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
|
|||
dma_resv_assert_held(attach->dmabuf->resv);
|
||||
|
||||
attach->dmabuf->ops->unmap_dma_buf(attach, sg_table, direction);
|
||||
|
||||
if (dma_buf_is_dynamic(attach->dmabuf) &&
|
||||
!IS_ENABLED(CONFIG_DMABUF_MOVE_NOTIFY))
|
||||
dma_buf_unpin(attach);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment);
|
||||
|
||||
/**
|
||||
* dma_buf_move_notify - notify attachments that DMA-buf is moving
|
||||
*
|
||||
* @dmabuf: [in] buffer which is moving
|
||||
*
|
||||
* Informs all attachmenst that they need to destroy and recreated all their
|
||||
* mappings.
|
||||
*/
|
||||
void dma_buf_move_notify(struct dma_buf *dmabuf)
|
||||
{
|
||||
struct dma_buf_attachment *attach;
|
||||
|
||||
dma_resv_assert_held(dmabuf->resv);
|
||||
|
||||
list_for_each_entry(attach, &dmabuf->attachments, node)
|
||||
if (attach->importer_ops)
|
||||
attach->importer_ops->move_notify(attach);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dma_buf_move_notify);
|
||||
|
||||
/**
|
||||
* DOC: cpu access
|
||||
*
|
||||
|
|
|
@ -54,9 +54,6 @@ config DRM_DEBUG_MM
|
|||
|
||||
If in doubt, say "N".
|
||||
|
||||
config DRM_EXPORT_FOR_TESTS
|
||||
bool
|
||||
|
||||
config DRM_DEBUG_SELFTEST
|
||||
tristate "kselftests for DRM"
|
||||
depends on DRM
|
||||
|
@ -470,6 +467,9 @@ config DRM_SAVAGE
|
|||
|
||||
endif # DRM_LEGACY
|
||||
|
||||
config DRM_EXPORT_FOR_TESTS
|
||||
bool
|
||||
|
||||
# Separate option because drm_panel_orientation_quirks.c is shared with fbdev
|
||||
config DRM_PANEL_ORIENTATION_QUIRKS
|
||||
tristate
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <linux/file.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/sync_file.h>
|
||||
#include <linux/dma-buf.h>
|
||||
|
||||
#include <drm/amdgpu_drm.h>
|
||||
#include <drm/drm_syncobj.h>
|
||||
|
@ -415,7 +416,9 @@ static int amdgpu_cs_bo_validate(struct amdgpu_cs_parser *p,
|
|||
/* Don't move this buffer if we have depleted our allowance
|
||||
* to move it. Don't move anything if the threshold is zero.
|
||||
*/
|
||||
if (p->bytes_moved < p->bytes_moved_threshold) {
|
||||
if (p->bytes_moved < p->bytes_moved_threshold &&
|
||||
(!bo->tbo.base.dma_buf ||
|
||||
list_empty(&bo->tbo.base.dma_buf->attachments))) {
|
||||
if (!amdgpu_gmc_vram_full_visible(&adev->gmc) &&
|
||||
(bo->flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED)) {
|
||||
/* And don't move a CPU_ACCESS_REQUIRED BO to limited
|
||||
|
|
|
@ -222,6 +222,37 @@ static void amdgpu_dma_buf_detach(struct dma_buf *dmabuf,
|
|||
bo->prime_shared_count--;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_dma_buf_pin - &dma_buf_ops.pin implementation
|
||||
*
|
||||
* @attach: attachment to pin down
|
||||
*
|
||||
* Pin the BO which is backing the DMA-buf so that it can't move any more.
|
||||
*/
|
||||
static int amdgpu_dma_buf_pin(struct dma_buf_attachment *attach)
|
||||
{
|
||||
struct drm_gem_object *obj = attach->dmabuf->priv;
|
||||
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
|
||||
|
||||
/* pin buffer into GTT */
|
||||
return amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_dma_buf_unpin - &dma_buf_ops.unpin implementation
|
||||
*
|
||||
* @attach: attachment to unpin
|
||||
*
|
||||
* Unpin a previously pinned BO to make it movable again.
|
||||
*/
|
||||
static void amdgpu_dma_buf_unpin(struct dma_buf_attachment *attach)
|
||||
{
|
||||
struct drm_gem_object *obj = attach->dmabuf->priv;
|
||||
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
|
||||
|
||||
amdgpu_bo_unpin(bo);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_dma_buf_map - &dma_buf_ops.map_dma_buf implementation
|
||||
* @attach: DMA-buf attachment
|
||||
|
@ -244,9 +275,19 @@ static struct sg_table *amdgpu_dma_buf_map(struct dma_buf_attachment *attach,
|
|||
struct sg_table *sgt;
|
||||
long r;
|
||||
|
||||
r = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT);
|
||||
if (r)
|
||||
return ERR_PTR(r);
|
||||
if (!bo->pin_count) {
|
||||
/* move buffer into GTT */
|
||||
struct ttm_operation_ctx ctx = { false, false };
|
||||
|
||||
amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_GTT);
|
||||
r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
|
||||
if (r)
|
||||
return ERR_PTR(r);
|
||||
|
||||
} else if (!(amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type) &
|
||||
AMDGPU_GEM_DOMAIN_GTT)) {
|
||||
return ERR_PTR(-EBUSY);
|
||||
}
|
||||
|
||||
sgt = drm_prime_pages_to_sg(bo->tbo.ttm->pages, bo->tbo.num_pages);
|
||||
if (IS_ERR(sgt))
|
||||
|
@ -277,13 +318,9 @@ static void amdgpu_dma_buf_unmap(struct dma_buf_attachment *attach,
|
|||
struct sg_table *sgt,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
struct drm_gem_object *obj = attach->dmabuf->priv;
|
||||
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
|
||||
|
||||
dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir);
|
||||
sg_free_table(sgt);
|
||||
kfree(sgt);
|
||||
amdgpu_bo_unpin(bo);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -327,9 +364,10 @@ static int amdgpu_dma_buf_begin_cpu_access(struct dma_buf *dma_buf,
|
|||
}
|
||||
|
||||
const struct dma_buf_ops amdgpu_dmabuf_ops = {
|
||||
.dynamic_mapping = true,
|
||||
.attach = amdgpu_dma_buf_attach,
|
||||
.detach = amdgpu_dma_buf_detach,
|
||||
.pin = amdgpu_dma_buf_pin,
|
||||
.unpin = amdgpu_dma_buf_unpin,
|
||||
.map_dma_buf = amdgpu_dma_buf_map,
|
||||
.unmap_dma_buf = amdgpu_dma_buf_unmap,
|
||||
.release = drm_gem_dmabuf_release,
|
||||
|
@ -412,6 +450,73 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, struct dma_buf *dma_buf)
|
|||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_dma_buf_move_notify - &attach.move_notify implementation
|
||||
*
|
||||
* @attach: the DMA-buf attachment
|
||||
*
|
||||
* Invalidate the DMA-buf attachment, making sure that the we re-create the
|
||||
* mapping before the next use.
|
||||
*/
|
||||
static void
|
||||
amdgpu_dma_buf_move_notify(struct dma_buf_attachment *attach)
|
||||
{
|
||||
struct drm_gem_object *obj = attach->importer_priv;
|
||||
struct ww_acquire_ctx *ticket = dma_resv_locking_ctx(obj->resv);
|
||||
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
|
||||
struct ttm_operation_ctx ctx = { false, false };
|
||||
struct ttm_placement placement = {};
|
||||
struct amdgpu_vm_bo_base *bo_base;
|
||||
int r;
|
||||
|
||||
if (bo->tbo.mem.mem_type == TTM_PL_SYSTEM)
|
||||
return;
|
||||
|
||||
r = ttm_bo_validate(&bo->tbo, &placement, &ctx);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed to invalidate DMA-buf import (%d))\n", r);
|
||||
return;
|
||||
}
|
||||
|
||||
for (bo_base = bo->vm_bo; bo_base; bo_base = bo_base->next) {
|
||||
struct amdgpu_vm *vm = bo_base->vm;
|
||||
struct dma_resv *resv = vm->root.base.bo->tbo.base.resv;
|
||||
|
||||
if (ticket) {
|
||||
/* When we get an error here it means that somebody
|
||||
* else is holding the VM lock and updating page tables
|
||||
* So we can just continue here.
|
||||
*/
|
||||
r = dma_resv_lock(resv, ticket);
|
||||
if (r)
|
||||
continue;
|
||||
|
||||
} else {
|
||||
/* TODO: This is more problematic and we actually need
|
||||
* to allow page tables updates without holding the
|
||||
* lock.
|
||||
*/
|
||||
if (!dma_resv_trylock(resv))
|
||||
continue;
|
||||
}
|
||||
|
||||
r = amdgpu_vm_clear_freed(adev, vm, NULL);
|
||||
if (!r)
|
||||
r = amdgpu_vm_handle_moved(adev, vm);
|
||||
|
||||
if (r && r != -EBUSY)
|
||||
DRM_ERROR("Failed to invalidate VM page tables (%d))\n",
|
||||
r);
|
||||
|
||||
dma_resv_unlock(resv);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct dma_buf_attach_ops amdgpu_dma_buf_attach_ops = {
|
||||
.move_notify = amdgpu_dma_buf_move_notify
|
||||
};
|
||||
|
||||
/**
|
||||
* amdgpu_gem_prime_import - &drm_driver.gem_prime_import implementation
|
||||
* @dev: DRM device
|
||||
|
@ -444,7 +549,8 @@ struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev,
|
|||
if (IS_ERR(obj))
|
||||
return obj;
|
||||
|
||||
attach = dma_buf_dynamic_attach(dma_buf, dev->dev, true);
|
||||
attach = dma_buf_dynamic_attach(dma_buf, dev->dev,
|
||||
&amdgpu_dma_buf_attach_ops, obj);
|
||||
if (IS_ERR(attach)) {
|
||||
drm_gem_object_put(obj);
|
||||
return ERR_CAST(attach);
|
||||
|
|
|
@ -336,15 +336,12 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev)
|
|||
drm_fb_helper_prepare(adev->ddev, &rfbdev->helper,
|
||||
&amdgpu_fb_helper_funcs);
|
||||
|
||||
ret = drm_fb_helper_init(adev->ddev, &rfbdev->helper,
|
||||
AMDGPUFB_CONN_LIMIT);
|
||||
ret = drm_fb_helper_init(adev->ddev, &rfbdev->helper);
|
||||
if (ret) {
|
||||
kfree(rfbdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
drm_fb_helper_single_add_all_connectors(&rfbdev->helper);
|
||||
|
||||
/* disable all the possible outputs/crtcs before entering KMS mode */
|
||||
if (!amdgpu_device_has_dc_support(adev))
|
||||
drm_helper_disable_unused_functions(adev->ddev);
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
*/
|
||||
#include <linux/list.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/dma-buf.h>
|
||||
|
||||
#include <drm/amdgpu_drm.h>
|
||||
#include <drm/drm_cache.h>
|
||||
|
@ -925,6 +926,9 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (bo->tbo.base.import_attach)
|
||||
dma_buf_pin(bo->tbo.base.import_attach);
|
||||
|
||||
bo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
|
||||
/* force to pin into visible video ram */
|
||||
if (!(bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS))
|
||||
|
@ -1008,6 +1012,9 @@ int amdgpu_bo_unpin(struct amdgpu_bo *bo)
|
|||
|
||||
amdgpu_bo_subtract_pin_size(bo);
|
||||
|
||||
if (bo->tbo.base.import_attach)
|
||||
dma_buf_unpin(bo->tbo.base.import_attach);
|
||||
|
||||
for (i = 0; i < bo->placement.num_placement; i++) {
|
||||
bo->placements[i].lpfn = 0;
|
||||
bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT;
|
||||
|
@ -1274,6 +1281,10 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
|
|||
|
||||
amdgpu_bo_kunmap(abo);
|
||||
|
||||
if (abo->tbo.base.dma_buf && !abo->tbo.base.import_attach &&
|
||||
bo->mem.mem_type != TTM_PL_SYSTEM)
|
||||
dma_buf_move_notify(abo->tbo.base.dma_buf);
|
||||
|
||||
/* remember the eviction */
|
||||
if (evict)
|
||||
atomic64_inc(&adev->num_evictions);
|
||||
|
|
|
@ -440,9 +440,6 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
|
|||
static void dm_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct amdgpu_dm_connector *master = container_of(mgr, struct amdgpu_dm_connector, mst_mgr);
|
||||
struct drm_device *dev = master->base.dev;
|
||||
struct amdgpu_device *adev = dev->dev_private;
|
||||
struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
|
||||
|
||||
DRM_INFO("DM_MST: Disabling connector: %p [id: %d] [master: %p]\n",
|
||||
|
@ -458,21 +455,11 @@ static void dm_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
|
|||
}
|
||||
|
||||
drm_connector_unregister(connector);
|
||||
if (adev->mode_info.rfbdev)
|
||||
drm_fb_helper_remove_one_connector(&adev->mode_info.rfbdev->helper, connector);
|
||||
drm_connector_put(connector);
|
||||
}
|
||||
|
||||
static void dm_dp_mst_register_connector(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct amdgpu_device *adev = dev->dev_private;
|
||||
|
||||
if (adev->mode_info.rfbdev)
|
||||
drm_fb_helper_add_one_connector(&adev->mode_info.rfbdev->helper, connector);
|
||||
else
|
||||
DRM_ERROR("adev->mode_info.rfbdev is NULL\n");
|
||||
|
||||
drm_connector_register(connector);
|
||||
}
|
||||
|
||||
|
|
|
@ -129,18 +129,12 @@ int armada_fbdev_init(struct drm_device *dev)
|
|||
|
||||
drm_fb_helper_prepare(dev, fbh, &armada_fb_helper_funcs);
|
||||
|
||||
ret = drm_fb_helper_init(dev, fbh, 1);
|
||||
ret = drm_fb_helper_init(dev, fbh);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to initialize drm fb helper\n");
|
||||
goto err_fb_helper;
|
||||
}
|
||||
|
||||
ret = drm_fb_helper_single_add_all_connectors(fbh);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to add fb connectors\n");
|
||||
goto err_fb_setup;
|
||||
}
|
||||
|
||||
ret = drm_fb_helper_initial_config(fbh, 32);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to set initial config\n");
|
||||
|
|
|
@ -121,6 +121,7 @@ struct ast_private {
|
|||
unsigned int next_index;
|
||||
} cursor;
|
||||
|
||||
struct drm_encoder encoder;
|
||||
struct drm_plane primary_plane;
|
||||
struct drm_plane cursor_plane;
|
||||
|
||||
|
@ -238,13 +239,8 @@ struct ast_crtc {
|
|||
u8 offset_x, offset_y;
|
||||
};
|
||||
|
||||
struct ast_encoder {
|
||||
struct drm_encoder base;
|
||||
};
|
||||
|
||||
#define to_ast_crtc(x) container_of(x, struct ast_crtc, base)
|
||||
#define to_ast_connector(x) container_of(x, struct ast_connector, base)
|
||||
#define to_ast_encoder(x) container_of(x, struct ast_encoder, base)
|
||||
|
||||
struct ast_vbios_stdtable {
|
||||
u8 misc;
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include <drm/drm_gem_vram_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_simple_kms_helper.h>
|
||||
|
||||
#include "ast_drv.h"
|
||||
#include "ast_tables.h"
|
||||
|
@ -957,28 +958,18 @@ static int ast_crtc_init(struct drm_device *dev)
|
|||
* Encoder
|
||||
*/
|
||||
|
||||
static void ast_encoder_destroy(struct drm_encoder *encoder)
|
||||
{
|
||||
drm_encoder_cleanup(encoder);
|
||||
kfree(encoder);
|
||||
}
|
||||
|
||||
static const struct drm_encoder_funcs ast_enc_funcs = {
|
||||
.destroy = ast_encoder_destroy,
|
||||
};
|
||||
|
||||
static int ast_encoder_init(struct drm_device *dev)
|
||||
{
|
||||
struct ast_encoder *ast_encoder;
|
||||
struct ast_private *ast = dev->dev_private;
|
||||
struct drm_encoder *encoder = &ast->encoder;
|
||||
int ret;
|
||||
|
||||
ast_encoder = kzalloc(sizeof(struct ast_encoder), GFP_KERNEL);
|
||||
if (!ast_encoder)
|
||||
return -ENOMEM;
|
||||
ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_DAC);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drm_encoder_init(dev, &ast_encoder->base, &ast_enc_funcs,
|
||||
DRM_MODE_ENCODER_DAC, NULL);
|
||||
encoder->possible_crtcs = 1;
|
||||
|
||||
ast_encoder->base.possible_crtcs = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -719,14 +719,18 @@ static int anx6345_i2c_probe(struct i2c_client *client,
|
|||
/* 1.2V digital core power regulator */
|
||||
anx6345->dvdd12 = devm_regulator_get(dev, "dvdd12");
|
||||
if (IS_ERR(anx6345->dvdd12)) {
|
||||
DRM_ERROR("dvdd12-supply not found\n");
|
||||
if (PTR_ERR(anx6345->dvdd12) != -EPROBE_DEFER)
|
||||
DRM_ERROR("Failed to get dvdd12 supply (%ld)\n",
|
||||
PTR_ERR(anx6345->dvdd12));
|
||||
return PTR_ERR(anx6345->dvdd12);
|
||||
}
|
||||
|
||||
/* 2.5V digital core power regulator */
|
||||
anx6345->dvdd25 = devm_regulator_get(dev, "dvdd25");
|
||||
if (IS_ERR(anx6345->dvdd25)) {
|
||||
DRM_ERROR("dvdd25-supply not found\n");
|
||||
if (PTR_ERR(anx6345->dvdd25) != -EPROBE_DEFER)
|
||||
DRM_ERROR("Failed to get dvdd25 supply (%ld)\n",
|
||||
PTR_ERR(anx6345->dvdd25));
|
||||
return PTR_ERR(anx6345->dvdd25);
|
||||
}
|
||||
|
||||
|
|
|
@ -375,7 +375,6 @@ static int tc358764_attach(struct drm_bridge *bridge,
|
|||
drm_connector_attach_encoder(&ctx->connector, bridge->encoder);
|
||||
drm_panel_attach(ctx->panel, &ctx->connector);
|
||||
ctx->connector.funcs->reset(&ctx->connector);
|
||||
drm_fb_helper_add_one_connector(drm->fb_helper, &ctx->connector);
|
||||
drm_connector_register(&ctx->connector);
|
||||
|
||||
return 0;
|
||||
|
@ -384,10 +383,8 @@ static int tc358764_attach(struct drm_bridge *bridge,
|
|||
static void tc358764_detach(struct drm_bridge *bridge)
|
||||
{
|
||||
struct tc358764 *ctx = bridge_to_tc358764(bridge);
|
||||
struct drm_device *drm = bridge->dev;
|
||||
|
||||
drm_connector_unregister(&ctx->connector);
|
||||
drm_fb_helper_remove_one_connector(drm->fb_helper, &ctx->connector);
|
||||
drm_panel_detach(ctx->panel);
|
||||
ctx->panel = NULL;
|
||||
drm_connector_put(&ctx->connector);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
// SPDX-License-Identifier: GPL-2.0 or MIT
|
||||
/*
|
||||
* Copyright 2018 Noralf Trønnes
|
||||
*/
|
||||
|
|
|
@ -736,6 +736,10 @@ static bool drm_dp_sideband_msg_build(struct drm_dp_sideband_msg_rx *msg,
|
|||
if (msg->curchunk_idx >= msg->curchunk_len) {
|
||||
/* do CRC */
|
||||
crc4 = drm_dp_msg_data_crc4(msg->chunk, msg->curchunk_len - 1);
|
||||
if (crc4 != msg->chunk[msg->curchunk_len - 1])
|
||||
print_hex_dump(KERN_DEBUG, "wrong crc",
|
||||
DUMP_PREFIX_NONE, 16, 1,
|
||||
msg->chunk, msg->curchunk_len, false);
|
||||
/* copy chunk into bigger msg */
|
||||
memcpy(&msg->msg[msg->curlen], msg->chunk, msg->curchunk_len - 1);
|
||||
msg->curlen += msg->curchunk_len - 1;
|
||||
|
@ -1035,7 +1039,8 @@ static bool drm_dp_sideband_parse_req(struct drm_dp_sideband_msg_rx *raw,
|
|||
}
|
||||
}
|
||||
|
||||
static int build_dpcd_write(struct drm_dp_sideband_msg_tx *msg, u8 port_num, u32 offset, u8 num_bytes, u8 *bytes)
|
||||
static void build_dpcd_write(struct drm_dp_sideband_msg_tx *msg,
|
||||
u8 port_num, u32 offset, u8 num_bytes, u8 *bytes)
|
||||
{
|
||||
struct drm_dp_sideband_msg_req_body req;
|
||||
|
||||
|
@ -1045,17 +1050,14 @@ static int build_dpcd_write(struct drm_dp_sideband_msg_tx *msg, u8 port_num, u32
|
|||
req.u.dpcd_write.num_bytes = num_bytes;
|
||||
req.u.dpcd_write.bytes = bytes;
|
||||
drm_dp_encode_sideband_req(&req, msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int build_link_address(struct drm_dp_sideband_msg_tx *msg)
|
||||
static void build_link_address(struct drm_dp_sideband_msg_tx *msg)
|
||||
{
|
||||
struct drm_dp_sideband_msg_req_body req;
|
||||
|
||||
req.req_type = DP_LINK_ADDRESS;
|
||||
drm_dp_encode_sideband_req(&req, msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int build_clear_payload_id_table(struct drm_dp_sideband_msg_tx *msg)
|
||||
|
@ -1067,7 +1069,8 @@ static int build_clear_payload_id_table(struct drm_dp_sideband_msg_tx *msg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int build_enum_path_resources(struct drm_dp_sideband_msg_tx *msg, int port_num)
|
||||
static int build_enum_path_resources(struct drm_dp_sideband_msg_tx *msg,
|
||||
int port_num)
|
||||
{
|
||||
struct drm_dp_sideband_msg_req_body req;
|
||||
|
||||
|
@ -1078,10 +1081,11 @@ static int build_enum_path_resources(struct drm_dp_sideband_msg_tx *msg, int por
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int build_allocate_payload(struct drm_dp_sideband_msg_tx *msg, int port_num,
|
||||
u8 vcpi, uint16_t pbn,
|
||||
u8 number_sdp_streams,
|
||||
u8 *sdp_stream_sink)
|
||||
static void build_allocate_payload(struct drm_dp_sideband_msg_tx *msg,
|
||||
int port_num,
|
||||
u8 vcpi, uint16_t pbn,
|
||||
u8 number_sdp_streams,
|
||||
u8 *sdp_stream_sink)
|
||||
{
|
||||
struct drm_dp_sideband_msg_req_body req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
|
@ -1094,11 +1098,10 @@ static int build_allocate_payload(struct drm_dp_sideband_msg_tx *msg, int port_n
|
|||
number_sdp_streams);
|
||||
drm_dp_encode_sideband_req(&req, msg);
|
||||
msg->path_msg = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int build_power_updown_phy(struct drm_dp_sideband_msg_tx *msg,
|
||||
int port_num, bool power_up)
|
||||
static void build_power_updown_phy(struct drm_dp_sideband_msg_tx *msg,
|
||||
int port_num, bool power_up)
|
||||
{
|
||||
struct drm_dp_sideband_msg_req_body req;
|
||||
|
||||
|
@ -1110,7 +1113,6 @@ static int build_power_updown_phy(struct drm_dp_sideband_msg_tx *msg,
|
|||
req.u.port_num.port_number = port_num;
|
||||
drm_dp_encode_sideband_req(&req, msg);
|
||||
msg->path_msg = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drm_dp_mst_assign_payload_id(struct drm_dp_mst_topology_mgr *mgr,
|
||||
|
@ -2073,29 +2075,24 @@ ssize_t drm_dp_mst_dpcd_write(struct drm_dp_aux *aux,
|
|||
offset, size, buffer);
|
||||
}
|
||||
|
||||
static void drm_dp_check_mstb_guid(struct drm_dp_mst_branch *mstb, u8 *guid)
|
||||
static int drm_dp_check_mstb_guid(struct drm_dp_mst_branch *mstb, u8 *guid)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
memcpy(mstb->guid, guid, 16);
|
||||
|
||||
if (!drm_dp_validate_guid(mstb->mgr, mstb->guid)) {
|
||||
if (mstb->port_parent) {
|
||||
ret = drm_dp_send_dpcd_write(
|
||||
mstb->mgr,
|
||||
mstb->port_parent,
|
||||
DP_GUID,
|
||||
16,
|
||||
mstb->guid);
|
||||
ret = drm_dp_send_dpcd_write(mstb->mgr,
|
||||
mstb->port_parent,
|
||||
DP_GUID, 16, mstb->guid);
|
||||
} else {
|
||||
|
||||
ret = drm_dp_dpcd_write(
|
||||
mstb->mgr->aux,
|
||||
DP_GUID,
|
||||
mstb->guid,
|
||||
16);
|
||||
ret = drm_dp_dpcd_write(mstb->mgr->aux,
|
||||
DP_GUID, mstb->guid, 16);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void build_mst_prop_path(const struct drm_dp_mst_branch *mstb,
|
||||
|
@ -2645,7 +2642,8 @@ static bool drm_dp_validate_guid(struct drm_dp_mst_topology_mgr *mgr,
|
|||
return false;
|
||||
}
|
||||
|
||||
static int build_dpcd_read(struct drm_dp_sideband_msg_tx *msg, u8 port_num, u32 offset, u8 num_bytes)
|
||||
static void build_dpcd_read(struct drm_dp_sideband_msg_tx *msg,
|
||||
u8 port_num, u32 offset, u8 num_bytes)
|
||||
{
|
||||
struct drm_dp_sideband_msg_req_body req;
|
||||
|
||||
|
@ -2654,8 +2652,6 @@ static int build_dpcd_read(struct drm_dp_sideband_msg_tx *msg, u8 port_num, u32
|
|||
req.u.dpcd_read.dpcd_address = offset;
|
||||
req.u.dpcd_read.num_bytes = num_bytes;
|
||||
drm_dp_encode_sideband_req(&req, msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drm_dp_send_sideband_msg(struct drm_dp_mst_topology_mgr *mgr,
|
||||
|
@ -2881,7 +2877,7 @@ static int drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
|
|||
struct drm_dp_sideband_msg_tx *txmsg;
|
||||
struct drm_dp_link_address_ack_reply *reply;
|
||||
struct drm_dp_mst_port *port, *tmp;
|
||||
int i, len, ret, port_mask = 0;
|
||||
int i, ret, port_mask = 0;
|
||||
bool changed = false;
|
||||
|
||||
txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
|
||||
|
@ -2889,7 +2885,7 @@ static int drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
|
|||
return -ENOMEM;
|
||||
|
||||
txmsg->dst = mstb;
|
||||
len = build_link_address(txmsg);
|
||||
build_link_address(txmsg);
|
||||
|
||||
mstb->link_address_sent = true;
|
||||
drm_dp_queue_down_tx(mgr, txmsg);
|
||||
|
@ -2910,7 +2906,9 @@ static int drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
|
|||
DRM_DEBUG_KMS("link address reply: %d\n", reply->nports);
|
||||
drm_dp_dump_link_address(reply);
|
||||
|
||||
drm_dp_check_mstb_guid(mstb, reply->guid);
|
||||
ret = drm_dp_check_mstb_guid(mstb, reply->guid);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < reply->nports; i++) {
|
||||
port_mask |= BIT(reply->ports[i].port_number);
|
||||
|
@ -2951,14 +2949,14 @@ void drm_dp_send_clear_payload_id_table(struct drm_dp_mst_topology_mgr *mgr,
|
|||
struct drm_dp_mst_branch *mstb)
|
||||
{
|
||||
struct drm_dp_sideband_msg_tx *txmsg;
|
||||
int len, ret;
|
||||
int ret;
|
||||
|
||||
txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
|
||||
if (!txmsg)
|
||||
return;
|
||||
|
||||
txmsg->dst = mstb;
|
||||
len = build_clear_payload_id_table(txmsg);
|
||||
build_clear_payload_id_table(txmsg);
|
||||
|
||||
drm_dp_queue_down_tx(mgr, txmsg);
|
||||
|
||||
|
@ -2976,7 +2974,6 @@ drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr,
|
|||
{
|
||||
struct drm_dp_enum_path_resources_ack_reply *path_res;
|
||||
struct drm_dp_sideband_msg_tx *txmsg;
|
||||
int len;
|
||||
int ret;
|
||||
|
||||
txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
|
||||
|
@ -2984,7 +2981,7 @@ drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr,
|
|||
return -ENOMEM;
|
||||
|
||||
txmsg->dst = mstb;
|
||||
len = build_enum_path_resources(txmsg, port->port_num);
|
||||
build_enum_path_resources(txmsg, port->port_num);
|
||||
|
||||
drm_dp_queue_down_tx(mgr, txmsg);
|
||||
|
||||
|
@ -3068,7 +3065,7 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr,
|
|||
{
|
||||
struct drm_dp_sideband_msg_tx *txmsg;
|
||||
struct drm_dp_mst_branch *mstb;
|
||||
int len, ret, port_num;
|
||||
int ret, port_num;
|
||||
u8 sinks[DRM_DP_MAX_SDP_STREAMS];
|
||||
int i;
|
||||
|
||||
|
@ -3093,9 +3090,9 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr,
|
|||
sinks[i] = i;
|
||||
|
||||
txmsg->dst = mstb;
|
||||
len = build_allocate_payload(txmsg, port_num,
|
||||
id,
|
||||
pbn, port->num_sdp_streams, sinks);
|
||||
build_allocate_payload(txmsg, port_num,
|
||||
id,
|
||||
pbn, port->num_sdp_streams, sinks);
|
||||
|
||||
drm_dp_queue_down_tx(mgr, txmsg);
|
||||
|
||||
|
@ -3124,7 +3121,7 @@ int drm_dp_send_power_updown_phy(struct drm_dp_mst_topology_mgr *mgr,
|
|||
struct drm_dp_mst_port *port, bool power_up)
|
||||
{
|
||||
struct drm_dp_sideband_msg_tx *txmsg;
|
||||
int len, ret;
|
||||
int ret;
|
||||
|
||||
port = drm_dp_mst_topology_get_port_validated(mgr, port);
|
||||
if (!port)
|
||||
|
@ -3137,7 +3134,7 @@ int drm_dp_send_power_updown_phy(struct drm_dp_mst_topology_mgr *mgr,
|
|||
}
|
||||
|
||||
txmsg->dst = port->parent;
|
||||
len = build_power_updown_phy(txmsg, port->port_num, power_up);
|
||||
build_power_updown_phy(txmsg, port->port_num, power_up);
|
||||
drm_dp_queue_down_tx(mgr, txmsg);
|
||||
|
||||
ret = drm_dp_mst_wait_tx_reply(port->parent, txmsg);
|
||||
|
@ -3359,7 +3356,6 @@ static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr,
|
|||
struct drm_dp_mst_port *port,
|
||||
int offset, int size, u8 *bytes)
|
||||
{
|
||||
int len;
|
||||
int ret = 0;
|
||||
struct drm_dp_sideband_msg_tx *txmsg;
|
||||
struct drm_dp_mst_branch *mstb;
|
||||
|
@ -3374,7 +3370,7 @@ static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr,
|
|||
goto fail_put;
|
||||
}
|
||||
|
||||
len = build_dpcd_read(txmsg, port->port_num, offset, size);
|
||||
build_dpcd_read(txmsg, port->port_num, offset, size);
|
||||
txmsg->dst = port->parent;
|
||||
|
||||
drm_dp_queue_down_tx(mgr, txmsg);
|
||||
|
@ -3412,7 +3408,6 @@ static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
|
|||
struct drm_dp_mst_port *port,
|
||||
int offset, int size, u8 *bytes)
|
||||
{
|
||||
int len;
|
||||
int ret;
|
||||
struct drm_dp_sideband_msg_tx *txmsg;
|
||||
struct drm_dp_mst_branch *mstb;
|
||||
|
@ -3427,7 +3422,7 @@ static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
|
|||
goto fail_put;
|
||||
}
|
||||
|
||||
len = build_dpcd_write(txmsg, port->port_num, offset, size, bytes);
|
||||
build_dpcd_write(txmsg, port->port_num, offset, size, bytes);
|
||||
txmsg->dst = mstb;
|
||||
|
||||
drm_dp_queue_down_tx(mgr, txmsg);
|
||||
|
@ -3673,7 +3668,12 @@ int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr,
|
|||
DRM_DEBUG_KMS("dpcd read failed - undocked during suspend?\n");
|
||||
goto out_fail;
|
||||
}
|
||||
drm_dp_check_mstb_guid(mgr->mst_primary, guid);
|
||||
|
||||
ret = drm_dp_check_mstb_guid(mgr->mst_primary, guid);
|
||||
if (ret) {
|
||||
DRM_DEBUG_KMS("check mstb failed - undocked during suspend?\n");
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* For the final step of resuming the topology, we need to bring the
|
||||
|
@ -4615,15 +4615,34 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
|
|||
int ret;
|
||||
|
||||
ret = drm_dp_dpcd_read(mgr->aux, DP_DPCD_REV, buf, DP_RECEIVER_CAP_SIZE);
|
||||
if (ret) {
|
||||
seq_printf(m, "dpcd read failed\n");
|
||||
goto out;
|
||||
}
|
||||
seq_printf(m, "dpcd: %*ph\n", DP_RECEIVER_CAP_SIZE, buf);
|
||||
|
||||
ret = drm_dp_dpcd_read(mgr->aux, DP_FAUX_CAP, buf, 2);
|
||||
if (ret) {
|
||||
seq_printf(m, "faux/mst read failed\n");
|
||||
goto out;
|
||||
}
|
||||
seq_printf(m, "faux/mst: %*ph\n", 2, buf);
|
||||
|
||||
ret = drm_dp_dpcd_read(mgr->aux, DP_MSTM_CTRL, buf, 1);
|
||||
if (ret) {
|
||||
seq_printf(m, "mst ctrl read failed\n");
|
||||
goto out;
|
||||
}
|
||||
seq_printf(m, "mst ctrl: %*ph\n", 1, buf);
|
||||
|
||||
/* dump the standard OUI branch header */
|
||||
ret = drm_dp_dpcd_read(mgr->aux, DP_BRANCH_OUI, buf, DP_BRANCH_OUI_HEADER_SIZE);
|
||||
if (ret) {
|
||||
seq_printf(m, "branch oui read failed\n");
|
||||
goto out;
|
||||
}
|
||||
seq_printf(m, "branch oui: %*phN devid: ", 3, buf);
|
||||
|
||||
for (i = 0x3; i < 0x8 && buf[i]; i++)
|
||||
seq_printf(m, "%c", buf[i]);
|
||||
seq_printf(m, " revision: hw: %x.%x sw: %x.%x\n",
|
||||
|
@ -4632,6 +4651,7 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
|
|||
seq_printf(m, "payload table: %*ph\n", DP_PAYLOAD_TABLE_SIZE, buf);
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&mgr->lock);
|
||||
|
||||
}
|
||||
|
|
|
@ -450,7 +450,6 @@ EXPORT_SYMBOL(drm_fb_helper_prepare);
|
|||
* drm_fb_helper_init - initialize a &struct drm_fb_helper
|
||||
* @dev: drm device
|
||||
* @fb_helper: driver-allocated fbdev helper structure to initialize
|
||||
* @max_conn_count: max connector count (not used)
|
||||
*
|
||||
* This allocates the structures for the fbdev helper with the given limits.
|
||||
* Note that this won't yet touch the hardware (through the driver interfaces)
|
||||
|
@ -463,8 +462,7 @@ EXPORT_SYMBOL(drm_fb_helper_prepare);
|
|||
* Zero if everything went ok, nonzero otherwise.
|
||||
*/
|
||||
int drm_fb_helper_init(struct drm_device *dev,
|
||||
struct drm_fb_helper *fb_helper,
|
||||
int max_conn_count)
|
||||
struct drm_fb_helper *fb_helper)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -2125,7 +2123,7 @@ static int drm_fbdev_client_hotplug(struct drm_client_dev *client)
|
|||
|
||||
drm_fb_helper_prepare(dev, fb_helper, &drm_fb_helper_generic_funcs);
|
||||
|
||||
ret = drm_fb_helper_init(dev, fb_helper, 0);
|
||||
ret = drm_fb_helper_init(dev, fb_helper);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
|
|
|
@ -23,14 +23,6 @@
|
|||
|
||||
#include "drm_internal.h"
|
||||
|
||||
static struct hdcp_srm {
|
||||
u32 revoked_ksv_cnt;
|
||||
u8 *revoked_ksv_list;
|
||||
|
||||
/* Mutex to protect above struct member */
|
||||
struct mutex mutex;
|
||||
} *srm_data;
|
||||
|
||||
static inline void drm_hdcp_print_ksv(const u8 *ksv)
|
||||
{
|
||||
DRM_DEBUG("\t%#02x, %#02x, %#02x, %#02x, %#02x\n",
|
||||
|
@ -60,11 +52,11 @@ static u32 drm_hdcp_get_revoked_ksv_count(const u8 *buf, u32 vrls_length)
|
|||
return ksv_count;
|
||||
}
|
||||
|
||||
static u32 drm_hdcp_get_revoked_ksvs(const u8 *buf, u8 *revoked_ksv_list,
|
||||
static u32 drm_hdcp_get_revoked_ksvs(const u8 *buf, u8 **revoked_ksv_list,
|
||||
u32 vrls_length)
|
||||
{
|
||||
u32 parsed_bytes = 0, ksv_count = 0;
|
||||
u32 vrl_ksv_cnt, vrl_ksv_sz, vrl_idx = 0;
|
||||
u32 parsed_bytes = 0, ksv_count = 0;
|
||||
|
||||
do {
|
||||
vrl_ksv_cnt = *buf;
|
||||
|
@ -74,10 +66,10 @@ static u32 drm_hdcp_get_revoked_ksvs(const u8 *buf, u8 *revoked_ksv_list,
|
|||
|
||||
DRM_DEBUG("vrl: %d, Revoked KSVs: %d\n", vrl_idx++,
|
||||
vrl_ksv_cnt);
|
||||
memcpy(revoked_ksv_list, buf, vrl_ksv_sz);
|
||||
memcpy((*revoked_ksv_list) + (ksv_count * DRM_HDCP_KSV_LEN),
|
||||
buf, vrl_ksv_sz);
|
||||
|
||||
ksv_count += vrl_ksv_cnt;
|
||||
revoked_ksv_list += vrl_ksv_sz;
|
||||
buf += vrl_ksv_sz;
|
||||
|
||||
parsed_bytes += (vrl_ksv_sz + 1);
|
||||
|
@ -91,7 +83,8 @@ static inline u32 get_vrl_length(const u8 *buf)
|
|||
return drm_hdcp_be24_to_cpu(buf);
|
||||
}
|
||||
|
||||
static int drm_hdcp_parse_hdcp1_srm(const u8 *buf, size_t count)
|
||||
static int drm_hdcp_parse_hdcp1_srm(const u8 *buf, size_t count,
|
||||
u8 **revoked_ksv_list, u32 *revoked_ksv_cnt)
|
||||
{
|
||||
struct hdcp_srm_header *header;
|
||||
u32 vrl_length, ksv_count;
|
||||
|
@ -131,29 +124,28 @@ static int drm_hdcp_parse_hdcp1_srm(const u8 *buf, size_t count)
|
|||
ksv_count = drm_hdcp_get_revoked_ksv_count(buf, vrl_length);
|
||||
if (!ksv_count) {
|
||||
DRM_DEBUG("Revoked KSV count is 0\n");
|
||||
return count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
kfree(srm_data->revoked_ksv_list);
|
||||
srm_data->revoked_ksv_list = kcalloc(ksv_count, DRM_HDCP_KSV_LEN,
|
||||
GFP_KERNEL);
|
||||
if (!srm_data->revoked_ksv_list) {
|
||||
*revoked_ksv_list = kcalloc(ksv_count, DRM_HDCP_KSV_LEN, GFP_KERNEL);
|
||||
if (!*revoked_ksv_list) {
|
||||
DRM_ERROR("Out of Memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (drm_hdcp_get_revoked_ksvs(buf, srm_data->revoked_ksv_list,
|
||||
if (drm_hdcp_get_revoked_ksvs(buf, revoked_ksv_list,
|
||||
vrl_length) != ksv_count) {
|
||||
srm_data->revoked_ksv_cnt = 0;
|
||||
kfree(srm_data->revoked_ksv_list);
|
||||
*revoked_ksv_cnt = 0;
|
||||
kfree(*revoked_ksv_list);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
srm_data->revoked_ksv_cnt = ksv_count;
|
||||
return count;
|
||||
*revoked_ksv_cnt = ksv_count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drm_hdcp_parse_hdcp2_srm(const u8 *buf, size_t count)
|
||||
static int drm_hdcp_parse_hdcp2_srm(const u8 *buf, size_t count,
|
||||
u8 **revoked_ksv_list, u32 *revoked_ksv_cnt)
|
||||
{
|
||||
struct hdcp_srm_header *header;
|
||||
u32 vrl_length, ksv_count, ksv_sz;
|
||||
|
@ -195,13 +187,11 @@ static int drm_hdcp_parse_hdcp2_srm(const u8 *buf, size_t count)
|
|||
ksv_count = (*buf << 2) | DRM_HDCP_2_KSV_COUNT_2_LSBITS(*(buf + 1));
|
||||
if (!ksv_count) {
|
||||
DRM_DEBUG("Revoked KSV count is 0\n");
|
||||
return count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
kfree(srm_data->revoked_ksv_list);
|
||||
srm_data->revoked_ksv_list = kcalloc(ksv_count, DRM_HDCP_KSV_LEN,
|
||||
GFP_KERNEL);
|
||||
if (!srm_data->revoked_ksv_list) {
|
||||
*revoked_ksv_list = kcalloc(ksv_count, DRM_HDCP_KSV_LEN, GFP_KERNEL);
|
||||
if (!*revoked_ksv_list) {
|
||||
DRM_ERROR("Out of Memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -210,10 +200,10 @@ static int drm_hdcp_parse_hdcp2_srm(const u8 *buf, size_t count)
|
|||
buf += DRM_HDCP_2_NO_OF_DEV_PLUS_RESERVED_SZ;
|
||||
|
||||
DRM_DEBUG("Revoked KSVs: %d\n", ksv_count);
|
||||
memcpy(srm_data->revoked_ksv_list, buf, ksv_sz);
|
||||
memcpy(*revoked_ksv_list, buf, ksv_sz);
|
||||
|
||||
srm_data->revoked_ksv_cnt = ksv_count;
|
||||
return count;
|
||||
*revoked_ksv_cnt = ksv_count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool is_srm_version_hdcp1(const u8 *buf)
|
||||
|
@ -226,22 +216,27 @@ static inline bool is_srm_version_hdcp2(const u8 *buf)
|
|||
return *buf == (u8)(DRM_HDCP_2_SRM_ID << 4 | DRM_HDCP_2_INDICATOR);
|
||||
}
|
||||
|
||||
static void drm_hdcp_srm_update(const u8 *buf, size_t count)
|
||||
static int drm_hdcp_srm_update(const u8 *buf, size_t count,
|
||||
u8 **revoked_ksv_list, u32 *revoked_ksv_cnt)
|
||||
{
|
||||
if (count < sizeof(struct hdcp_srm_header))
|
||||
return;
|
||||
return -EINVAL;
|
||||
|
||||
if (is_srm_version_hdcp1(buf))
|
||||
drm_hdcp_parse_hdcp1_srm(buf, count);
|
||||
return drm_hdcp_parse_hdcp1_srm(buf, count, revoked_ksv_list,
|
||||
revoked_ksv_cnt);
|
||||
else if (is_srm_version_hdcp2(buf))
|
||||
drm_hdcp_parse_hdcp2_srm(buf, count);
|
||||
return drm_hdcp_parse_hdcp2_srm(buf, count, revoked_ksv_list,
|
||||
revoked_ksv_cnt);
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void drm_hdcp_request_srm(struct drm_device *drm_dev)
|
||||
static int drm_hdcp_request_srm(struct drm_device *drm_dev,
|
||||
u8 **revoked_ksv_list, u32 *revoked_ksv_cnt)
|
||||
{
|
||||
char fw_name[36] = "display_hdcp_srm.bin";
|
||||
const struct firmware *fw;
|
||||
|
||||
int ret;
|
||||
|
||||
ret = request_firmware_direct(&fw, (const char *)fw_name,
|
||||
|
@ -250,10 +245,12 @@ static void drm_hdcp_request_srm(struct drm_device *drm_dev)
|
|||
goto exit;
|
||||
|
||||
if (fw->size && fw->data)
|
||||
drm_hdcp_srm_update(fw->data, fw->size);
|
||||
ret = drm_hdcp_srm_update(fw->data, fw->size, revoked_ksv_list,
|
||||
revoked_ksv_cnt);
|
||||
|
||||
exit:
|
||||
release_firmware(fw);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -279,71 +276,34 @@ static void drm_hdcp_request_srm(struct drm_device *drm_dev)
|
|||
* https://www.digital-cp.com/sites/default/files/specifications/HDCP%20on%20HDMI%20Specification%20Rev2_2_Final1.pdf
|
||||
*
|
||||
* Returns:
|
||||
* TRUE on any of the KSV is revoked, else FALSE.
|
||||
* Count of the revoked KSVs or -ve error number incase of the failure.
|
||||
*/
|
||||
bool drm_hdcp_check_ksvs_revoked(struct drm_device *drm_dev, u8 *ksvs,
|
||||
u32 ksv_count)
|
||||
int drm_hdcp_check_ksvs_revoked(struct drm_device *drm_dev, u8 *ksvs,
|
||||
u32 ksv_count)
|
||||
{
|
||||
u32 rev_ksv_cnt, cnt, i, j;
|
||||
u8 *rev_ksv_list;
|
||||
u32 revoked_ksv_cnt = 0, i, j;
|
||||
u8 *revoked_ksv_list = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (!srm_data)
|
||||
return false;
|
||||
ret = drm_hdcp_request_srm(drm_dev, &revoked_ksv_list,
|
||||
&revoked_ksv_cnt);
|
||||
|
||||
mutex_lock(&srm_data->mutex);
|
||||
drm_hdcp_request_srm(drm_dev);
|
||||
/* revoked_ksv_cnt will be zero when above function failed */
|
||||
for (i = 0; i < revoked_ksv_cnt; i++)
|
||||
for (j = 0; j < ksv_count; j++)
|
||||
if (!memcmp(&ksvs[j * DRM_HDCP_KSV_LEN],
|
||||
&revoked_ksv_list[i * DRM_HDCP_KSV_LEN],
|
||||
DRM_HDCP_KSV_LEN)) {
|
||||
DRM_DEBUG("Revoked KSV is ");
|
||||
drm_hdcp_print_ksv(&ksvs[j * DRM_HDCP_KSV_LEN]);
|
||||
ret++;
|
||||
}
|
||||
|
||||
rev_ksv_cnt = srm_data->revoked_ksv_cnt;
|
||||
rev_ksv_list = srm_data->revoked_ksv_list;
|
||||
|
||||
/* If the Revoked ksv list is empty */
|
||||
if (!rev_ksv_cnt || !rev_ksv_list) {
|
||||
mutex_unlock(&srm_data->mutex);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (cnt = 0; cnt < ksv_count; cnt++) {
|
||||
rev_ksv_list = srm_data->revoked_ksv_list;
|
||||
for (i = 0; i < rev_ksv_cnt; i++) {
|
||||
for (j = 0; j < DRM_HDCP_KSV_LEN; j++)
|
||||
if (ksvs[j] != rev_ksv_list[j]) {
|
||||
break;
|
||||
} else if (j == (DRM_HDCP_KSV_LEN - 1)) {
|
||||
DRM_DEBUG("Revoked KSV is ");
|
||||
drm_hdcp_print_ksv(ksvs);
|
||||
mutex_unlock(&srm_data->mutex);
|
||||
return true;
|
||||
}
|
||||
/* Move the offset to next KSV in the revoked list */
|
||||
rev_ksv_list += DRM_HDCP_KSV_LEN;
|
||||
}
|
||||
|
||||
/* Iterate to next ksv_offset */
|
||||
ksvs += DRM_HDCP_KSV_LEN;
|
||||
}
|
||||
mutex_unlock(&srm_data->mutex);
|
||||
return false;
|
||||
kfree(revoked_ksv_list);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_hdcp_check_ksvs_revoked);
|
||||
|
||||
int drm_setup_hdcp_srm(struct class *drm_class)
|
||||
{
|
||||
srm_data = kzalloc(sizeof(*srm_data), GFP_KERNEL);
|
||||
if (!srm_data)
|
||||
return -ENOMEM;
|
||||
mutex_init(&srm_data->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void drm_teardown_hdcp_srm(struct class *drm_class)
|
||||
{
|
||||
if (srm_data) {
|
||||
kfree(srm_data->revoked_ksv_list);
|
||||
kfree(srm_data);
|
||||
}
|
||||
}
|
||||
|
||||
static struct drm_prop_enum_list drm_cp_enum_list[] = {
|
||||
{ DRM_MODE_CONTENT_PROTECTION_UNDESIRED, "Undesired" },
|
||||
{ DRM_MODE_CONTENT_PROTECTION_DESIRED, "Desired" },
|
||||
|
|
|
@ -236,7 +236,3 @@ int drm_syncobj_query_ioctl(struct drm_device *dev, void *data,
|
|||
void drm_framebuffer_print_info(struct drm_printer *p, unsigned int indent,
|
||||
const struct drm_framebuffer *fb);
|
||||
int drm_framebuffer_debugfs_init(struct drm_minor *minor);
|
||||
|
||||
/* drm_hdcp.c */
|
||||
int drm_setup_hdcp_srm(struct class *drm_class);
|
||||
void drm_teardown_hdcp_srm(struct class *drm_class);
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include <linux/export.h>
|
||||
#include <linux/interval_tree_generic.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/sched/signal.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/stacktrace.h>
|
||||
|
||||
|
@ -366,6 +367,11 @@ next_hole(struct drm_mm *mm,
|
|||
struct drm_mm_node *node,
|
||||
enum drm_mm_insert_mode mode)
|
||||
{
|
||||
/* Searching is slow; check if we ran out of time/patience */
|
||||
cond_resched();
|
||||
if (fatal_signal_pending(current))
|
||||
return NULL;
|
||||
|
||||
switch (mode) {
|
||||
default:
|
||||
case DRM_MM_INSERT_BEST:
|
||||
|
@ -557,7 +563,7 @@ int drm_mm_insert_node_in_range(struct drm_mm * const mm,
|
|||
return 0;
|
||||
}
|
||||
|
||||
return -ENOSPC;
|
||||
return signal_pending(current) ? -ERESTARTSYS : -ENOSPC;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mm_insert_node_in_range);
|
||||
|
||||
|
|
|
@ -75,7 +75,6 @@ drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t ali
|
|||
|
||||
return dmah;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_pci_alloc);
|
||||
|
||||
/**
|
||||
|
@ -167,6 +166,18 @@ int drm_irq_by_busid(struct drm_device *dev, void *data,
|
|||
return drm_pci_irq_by_busid(dev, p);
|
||||
}
|
||||
|
||||
void drm_pci_agp_destroy(struct drm_device *dev)
|
||||
{
|
||||
if (dev->agp) {
|
||||
arch_phys_wc_del(dev->agp->agp_mtrr);
|
||||
drm_legacy_agp_clear(dev);
|
||||
kfree(dev->agp);
|
||||
dev->agp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DRM_LEGACY
|
||||
|
||||
static void drm_pci_agp_init(struct drm_device *dev)
|
||||
{
|
||||
if (drm_core_check_feature(dev, DRIVER_USE_AGP)) {
|
||||
|
@ -181,33 +192,9 @@ static void drm_pci_agp_init(struct drm_device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
void drm_pci_agp_destroy(struct drm_device *dev)
|
||||
{
|
||||
if (dev->agp) {
|
||||
arch_phys_wc_del(dev->agp->agp_mtrr);
|
||||
drm_legacy_agp_clear(dev);
|
||||
kfree(dev->agp);
|
||||
dev->agp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_get_pci_dev - Register a PCI device with the DRM subsystem
|
||||
* @pdev: PCI device
|
||||
* @ent: entry from the PCI ID table that matches @pdev
|
||||
* @driver: DRM device driver
|
||||
*
|
||||
* Attempt to gets inter module "drm" information. If we are first
|
||||
* then register the character device and inter module information.
|
||||
* Try and register, if we fail to register, backout previous work.
|
||||
*
|
||||
* NOTE: This function is deprecated, please use drm_dev_alloc() and
|
||||
* drm_dev_register() instead and remove your &drm_driver.load callback.
|
||||
*
|
||||
* Return: 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
|
||||
struct drm_driver *driver)
|
||||
static int drm_get_pci_dev(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent,
|
||||
struct drm_driver *driver)
|
||||
{
|
||||
struct drm_device *dev;
|
||||
int ret;
|
||||
|
@ -250,9 +237,6 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
|
|||
drm_dev_put(dev);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_get_pci_dev);
|
||||
|
||||
#ifdef CONFIG_DRM_LEGACY
|
||||
|
||||
/**
|
||||
* drm_legacy_pci_init - shadow-attach a legacy DRM PCI driver
|
||||
|
|
|
@ -99,6 +99,9 @@ int drm_legacy_sg_alloc(struct drm_device *dev, void *data,
|
|||
if (!drm_core_check_feature(dev, DRIVER_SG))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (request->size > SIZE_MAX - PAGE_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
if (dev->sg)
|
||||
return -EINVAL;
|
||||
|
||||
|
|
|
@ -26,12 +26,51 @@
|
|||
* entity. Some flexibility for code reuse is provided through a separately
|
||||
* allocated &drm_connector object and supporting optional &drm_bridge
|
||||
* encoder drivers.
|
||||
*
|
||||
* Many drivers require only a very simple encoder that fulfills the minimum
|
||||
* requirements of the display pipeline and does not add additional
|
||||
* functionality. The function drm_simple_encoder_init() provides an
|
||||
* implementation of such an encoder.
|
||||
*/
|
||||
|
||||
static const struct drm_encoder_funcs drm_simple_kms_encoder_funcs = {
|
||||
static const struct drm_encoder_funcs drm_simple_encoder_funcs_cleanup = {
|
||||
.destroy = drm_encoder_cleanup,
|
||||
};
|
||||
|
||||
/**
|
||||
* drm_simple_encoder_init - Initialize a preallocated encoder with
|
||||
* basic functionality.
|
||||
* @dev: drm device
|
||||
* @encoder: the encoder to initialize
|
||||
* @encoder_type: user visible type of the encoder
|
||||
*
|
||||
* Initialises a preallocated encoder that has no further functionality.
|
||||
* Settings for possible CRTC and clones are left to their initial values.
|
||||
* The encoder will be cleaned up automatically as part of the mode-setting
|
||||
* cleanup.
|
||||
*
|
||||
* The caller of drm_simple_encoder_init() is responsible for freeing
|
||||
* the encoder's memory after the encoder has been cleaned up. At the
|
||||
* moment this only works reliably if the encoder data structure is
|
||||
* stored in the device structure. Free the encoder's memory as part of
|
||||
* the device release function.
|
||||
*
|
||||
* FIXME: Later improvements to DRM's resource management may allow for
|
||||
* an automated kfree() of the encoder's memory.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, error code on failure.
|
||||
*/
|
||||
int drm_simple_encoder_init(struct drm_device *dev,
|
||||
struct drm_encoder *encoder,
|
||||
int encoder_type)
|
||||
{
|
||||
return drm_encoder_init(dev, encoder,
|
||||
&drm_simple_encoder_funcs_cleanup,
|
||||
encoder_type, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_simple_encoder_init);
|
||||
|
||||
static enum drm_mode_status
|
||||
drm_simple_kms_crtc_mode_valid(struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode)
|
||||
|
@ -288,8 +327,7 @@ int drm_simple_display_pipe_init(struct drm_device *dev,
|
|||
return ret;
|
||||
|
||||
encoder->possible_crtcs = drm_crtc_mask(crtc);
|
||||
ret = drm_encoder_init(dev, encoder, &drm_simple_kms_encoder_funcs,
|
||||
DRM_MODE_ENCODER_NONE, NULL);
|
||||
ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_NONE);
|
||||
if (ret || !connector)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -85,7 +85,6 @@ int drm_sysfs_init(void)
|
|||
}
|
||||
|
||||
drm_class->devnode = drm_devnode;
|
||||
drm_setup_hdcp_srm(drm_class);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -98,7 +97,6 @@ void drm_sysfs_destroy(void)
|
|||
{
|
||||
if (IS_ERR_OR_NULL(drm_class))
|
||||
return;
|
||||
drm_teardown_hdcp_srm(drm_class);
|
||||
class_remove_file(drm_class, &class_attr_version.attr);
|
||||
class_destroy(drm_class);
|
||||
drm_class = NULL;
|
||||
|
|
|
@ -592,8 +592,7 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants);
|
|||
/**
|
||||
* drm_crtc_vblank_helper_get_vblank_timestamp_internal - precise vblank
|
||||
* timestamp helper
|
||||
* @dev: DRM device
|
||||
* @pipe: index of CRTC whose vblank timestamp to retrieve
|
||||
* @crtc: CRTC whose vblank timestamp to retrieve
|
||||
* @max_error: Desired maximum allowable error in timestamps (nanosecs)
|
||||
* On return contains true maximum error of timestamp
|
||||
* @vblank_time: Pointer to time which should receive the timestamp
|
||||
|
|
|
@ -1514,7 +1514,6 @@ static int exynos_dsi_create_connector(struct drm_encoder *encoder)
|
|||
return 0;
|
||||
|
||||
connector->funcs->reset(connector);
|
||||
drm_fb_helper_add_one_connector(drm->fb_helper, connector);
|
||||
drm_connector_register(connector);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -200,21 +200,13 @@ int exynos_drm_fbdev_init(struct drm_device *dev)
|
|||
|
||||
drm_fb_helper_prepare(dev, helper, &exynos_drm_fb_helper_funcs);
|
||||
|
||||
ret = drm_fb_helper_init(dev, helper, MAX_CONNECTOR);
|
||||
ret = drm_fb_helper_init(dev, helper);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(dev->dev,
|
||||
"failed to initialize drm fb helper.\n");
|
||||
goto err_init;
|
||||
}
|
||||
|
||||
ret = drm_fb_helper_single_add_all_connectors(helper);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(dev->dev,
|
||||
"failed to register drm_fb_helper_connector.\n");
|
||||
goto err_setup;
|
||||
|
||||
}
|
||||
|
||||
ret = drm_fb_helper_initial_config(helper, PREFERRED_BPP);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(dev->dev,
|
||||
|
|
|
@ -513,14 +513,10 @@ int psb_fbdev_init(struct drm_device *dev)
|
|||
|
||||
drm_fb_helper_prepare(dev, fb_helper, &psb_fb_helper_funcs);
|
||||
|
||||
ret = drm_fb_helper_init(dev, fb_helper, INTELFB_CONN_LIMIT);
|
||||
ret = drm_fb_helper_init(dev, fb_helper);
|
||||
if (ret)
|
||||
goto free;
|
||||
|
||||
ret = drm_fb_helper_single_add_all_connectors(fb_helper);
|
||||
if (ret)
|
||||
goto fini;
|
||||
|
||||
/* disable all the possible outputs/crtcs before entering KMS mode */
|
||||
drm_helper_disable_unused_functions(dev);
|
||||
|
||||
|
|
|
@ -227,7 +227,7 @@ struct bdb_general_definitions {
|
|||
* number = (block_size - sizeof(bdb_general_definitions))/
|
||||
* sizeof(child_device_config);
|
||||
*/
|
||||
struct child_device_config devices[0];
|
||||
struct child_device_config devices[];
|
||||
};
|
||||
|
||||
struct bdb_lvds_options {
|
||||
|
|
|
@ -721,27 +721,15 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
|
|||
|
||||
static void intel_dp_register_mst_connector(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->dev);
|
||||
|
||||
if (dev_priv->fbdev)
|
||||
drm_fb_helper_add_one_connector(&dev_priv->fbdev->helper,
|
||||
connector);
|
||||
|
||||
drm_connector_register(connector);
|
||||
}
|
||||
|
||||
static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->dev);
|
||||
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, connector->name);
|
||||
drm_connector_unregister(connector);
|
||||
|
||||
if (dev_priv->fbdev)
|
||||
drm_fb_helper_remove_one_connector(&dev_priv->fbdev->helper,
|
||||
connector);
|
||||
|
||||
drm_connector_put(connector);
|
||||
}
|
||||
|
||||
|
|
|
@ -453,7 +453,7 @@ int intel_fbdev_init(struct drm_device *dev)
|
|||
if (!intel_fbdev_init_bios(dev, ifbdev))
|
||||
ifbdev->preferred_bpp = 32;
|
||||
|
||||
ret = drm_fb_helper_init(dev, &ifbdev->helper, 4);
|
||||
ret = drm_fb_helper_init(dev, &ifbdev->helper);
|
||||
if (ret) {
|
||||
kfree(ifbdev);
|
||||
return ret;
|
||||
|
@ -462,8 +462,6 @@ int intel_fbdev_init(struct drm_device *dev)
|
|||
dev_priv->fbdev = ifbdev;
|
||||
INIT_WORK(&dev_priv->fbdev_suspend_work, intel_fbdev_suspend_worker);
|
||||
|
||||
drm_fb_helper_single_add_all_connectors(&ifbdev->helper);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -95,7 +95,6 @@
|
|||
#define MATROX_DPMS_CLEARED (-1)
|
||||
|
||||
#define to_mga_crtc(x) container_of(x, struct mga_crtc, base)
|
||||
#define to_mga_encoder(x) container_of(x, struct mga_encoder, base)
|
||||
#define to_mga_connector(x) container_of(x, struct mga_connector, base)
|
||||
|
||||
struct mga_crtc {
|
||||
|
@ -110,12 +109,6 @@ struct mga_mode_info {
|
|||
struct mga_crtc *crtc;
|
||||
};
|
||||
|
||||
struct mga_encoder {
|
||||
struct drm_encoder base;
|
||||
int last_dpms;
|
||||
};
|
||||
|
||||
|
||||
struct mga_i2c_chan {
|
||||
struct i2c_adapter adapter;
|
||||
struct drm_device *dev;
|
||||
|
@ -185,6 +178,8 @@ struct mga_device {
|
|||
|
||||
/* SE model number stored in reg 0x1e24 */
|
||||
u32 unique_rev_id;
|
||||
|
||||
struct drm_encoder encoder;
|
||||
};
|
||||
|
||||
static inline enum mga_type
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_simple_kms_helper.h>
|
||||
|
||||
#include "mgag200_drv.h"
|
||||
|
||||
|
@ -1449,76 +1450,6 @@ static void mga_crtc_init(struct mga_device *mdev)
|
|||
drm_crtc_helper_add(&mga_crtc->base, &mga_helper_funcs);
|
||||
}
|
||||
|
||||
/*
|
||||
* The encoder comes after the CRTC in the output pipeline, but before
|
||||
* the connector. It's responsible for ensuring that the digital
|
||||
* stream is appropriately converted into the output format. Setup is
|
||||
* very simple in this case - all we have to do is inform qemu of the
|
||||
* colour depth in order to ensure that it displays appropriately
|
||||
*/
|
||||
|
||||
/*
|
||||
* These functions are analagous to those in the CRTC code, but are intended
|
||||
* to handle any encoder-specific limitations
|
||||
*/
|
||||
static void mga_encoder_mode_set(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void mga_encoder_dpms(struct drm_encoder *encoder, int state)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void mga_encoder_prepare(struct drm_encoder *encoder)
|
||||
{
|
||||
}
|
||||
|
||||
static void mga_encoder_commit(struct drm_encoder *encoder)
|
||||
{
|
||||
}
|
||||
|
||||
static void mga_encoder_destroy(struct drm_encoder *encoder)
|
||||
{
|
||||
struct mga_encoder *mga_encoder = to_mga_encoder(encoder);
|
||||
drm_encoder_cleanup(encoder);
|
||||
kfree(mga_encoder);
|
||||
}
|
||||
|
||||
static const struct drm_encoder_helper_funcs mga_encoder_helper_funcs = {
|
||||
.dpms = mga_encoder_dpms,
|
||||
.mode_set = mga_encoder_mode_set,
|
||||
.prepare = mga_encoder_prepare,
|
||||
.commit = mga_encoder_commit,
|
||||
};
|
||||
|
||||
static const struct drm_encoder_funcs mga_encoder_encoder_funcs = {
|
||||
.destroy = mga_encoder_destroy,
|
||||
};
|
||||
|
||||
static struct drm_encoder *mga_encoder_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_encoder *encoder;
|
||||
struct mga_encoder *mga_encoder;
|
||||
|
||||
mga_encoder = kzalloc(sizeof(struct mga_encoder), GFP_KERNEL);
|
||||
if (!mga_encoder)
|
||||
return NULL;
|
||||
|
||||
encoder = &mga_encoder->base;
|
||||
encoder->possible_crtcs = 0x1;
|
||||
|
||||
drm_encoder_init(dev, encoder, &mga_encoder_encoder_funcs,
|
||||
DRM_MODE_ENCODER_DAC, NULL);
|
||||
drm_encoder_helper_add(encoder, &mga_encoder_helper_funcs);
|
||||
|
||||
return encoder;
|
||||
}
|
||||
|
||||
|
||||
static int mga_vga_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct mga_connector *mga_connector = to_mga_connector(connector);
|
||||
|
@ -1686,8 +1617,9 @@ static struct drm_connector *mga_vga_init(struct drm_device *dev)
|
|||
|
||||
int mgag200_modeset_init(struct mga_device *mdev)
|
||||
{
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_encoder *encoder = &mdev->encoder;
|
||||
struct drm_connector *connector;
|
||||
int ret;
|
||||
|
||||
mdev->mode_info.mode_config_initialized = true;
|
||||
|
||||
|
@ -1698,11 +1630,15 @@ int mgag200_modeset_init(struct mga_device *mdev)
|
|||
|
||||
mga_crtc_init(mdev);
|
||||
|
||||
encoder = mga_encoder_init(mdev->dev);
|
||||
if (!encoder) {
|
||||
DRM_ERROR("mga_encoder_init failed\n");
|
||||
return -1;
|
||||
ret = drm_simple_encoder_init(mdev->dev, encoder,
|
||||
DRM_MODE_ENCODER_DAC);
|
||||
if (ret) {
|
||||
drm_err(mdev->dev,
|
||||
"drm_simple_encoder_init() failed, error %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
encoder->possible_crtcs = 0x1;
|
||||
|
||||
connector = mga_vga_init(mdev->dev);
|
||||
if (!connector) {
|
||||
|
|
|
@ -160,16 +160,12 @@ struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev)
|
|||
|
||||
drm_fb_helper_prepare(dev, helper, &msm_fb_helper_funcs);
|
||||
|
||||
ret = drm_fb_helper_init(dev, helper, priv->num_connectors);
|
||||
ret = drm_fb_helper_init(dev, helper);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dev->dev, "could not init fbdev: ret=%d\n", ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = drm_fb_helper_single_add_all_connectors(helper);
|
||||
if (ret)
|
||||
goto fini;
|
||||
|
||||
/* the fw fb could be anywhere in memory */
|
||||
drm_fb_helper_remove_conflicting_framebuffers(NULL, "msm", false);
|
||||
|
||||
|
|
|
@ -1260,23 +1260,16 @@ static void
|
|||
nv50_mstm_destroy_connector(struct drm_dp_mst_topology_mgr *mgr,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct nouveau_drm *drm = nouveau_drm(connector->dev);
|
||||
struct nv50_mstc *mstc = nv50_mstc(connector);
|
||||
|
||||
drm_connector_unregister(&mstc->connector);
|
||||
|
||||
drm_fb_helper_remove_one_connector(&drm->fbcon->helper, &mstc->connector);
|
||||
|
||||
drm_connector_put(&mstc->connector);
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_mstm_register_connector(struct drm_connector *connector)
|
||||
{
|
||||
struct nouveau_drm *drm = nouveau_drm(connector->dev);
|
||||
|
||||
drm_fb_helper_add_one_connector(&drm->fbcon->helper, connector);
|
||||
|
||||
drm_connector_register(connector);
|
||||
}
|
||||
|
||||
|
|
|
@ -558,14 +558,10 @@ nouveau_fbcon_init(struct drm_device *dev)
|
|||
|
||||
drm_fb_helper_prepare(dev, &fbcon->helper, &nouveau_fbcon_helper_funcs);
|
||||
|
||||
ret = drm_fb_helper_init(dev, &fbcon->helper, 4);
|
||||
ret = drm_fb_helper_init(dev, &fbcon->helper);
|
||||
if (ret)
|
||||
goto free;
|
||||
|
||||
ret = drm_fb_helper_single_add_all_connectors(&fbcon->helper);
|
||||
if (ret)
|
||||
goto fini;
|
||||
|
||||
if (preferred_bpp != 8 && preferred_bpp != 16 && preferred_bpp != 32) {
|
||||
if (drm->client.device.info.ram_size <= 32 * 1024 * 1024)
|
||||
preferred_bpp = 8;
|
||||
|
|
|
@ -242,14 +242,10 @@ void omap_fbdev_init(struct drm_device *dev)
|
|||
|
||||
drm_fb_helper_prepare(dev, helper, &omap_fb_helper_funcs);
|
||||
|
||||
ret = drm_fb_helper_init(dev, helper, priv->num_pipes);
|
||||
ret = drm_fb_helper_init(dev, helper);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
ret = drm_fb_helper_single_add_all_connectors(helper);
|
||||
if (ret)
|
||||
goto fini;
|
||||
|
||||
ret = drm_fb_helper_initial_config(helper, 32);
|
||||
if (ret)
|
||||
goto fini;
|
||||
|
|
|
@ -59,6 +59,16 @@ config DRM_PANEL_SIMPLE
|
|||
that it can be automatically turned off when the panel goes into a
|
||||
low power state.
|
||||
|
||||
config DRM_PANEL_ELIDA_KD35T133
|
||||
tristate "Elida KD35T133 panel driver"
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
help
|
||||
Say Y here if you want to enable support for the Elida
|
||||
KD35T133 controller for 320x480 LCD panels with MIPI-DSI
|
||||
system interfaces.
|
||||
|
||||
config DRM_PANEL_FEIXIN_K101_IM2BA02
|
||||
tristate "Feixin K101 IM2BA02 panel"
|
||||
depends on OF
|
||||
|
@ -167,6 +177,16 @@ config DRM_PANEL_NEC_NL8048HL11
|
|||
panel (found on the Zoom2/3/3630 SDP boards). To compile this driver
|
||||
as a module, choose M here.
|
||||
|
||||
config DRM_PANEL_NOVATEK_NT35510
|
||||
tristate "Novatek NT35510 RGB panel driver"
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
help
|
||||
Say Y here if you want to enable support for the panels built
|
||||
around the Novatek NT35510 display controller, such as some
|
||||
Hydis panels.
|
||||
|
||||
config DRM_PANEL_NOVATEK_NT39016
|
||||
tristate "Novatek NT39016 RGB/SPI panel"
|
||||
depends on OF && SPI
|
||||
|
|
|
@ -4,6 +4,7 @@ obj-$(CONFIG_DRM_PANEL_BOE_HIMAX8279D) += panel-boe-himax8279d.o
|
|||
obj-$(CONFIG_DRM_PANEL_BOE_TV101WUM_NL6) += panel-boe-tv101wum-nl6.o
|
||||
obj-$(CONFIG_DRM_PANEL_LVDS) += panel-lvds.o
|
||||
obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
|
||||
obj-$(CONFIG_DRM_PANEL_ELIDA_KD35T133) += panel-elida-kd35t133.o
|
||||
obj-$(CONFIG_DRM_PANEL_FEIXIN_K101_IM2BA02) += panel-feixin-k101-im2ba02.o
|
||||
obj-$(CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D) += panel-feiyang-fy07024di26a30d.o
|
||||
obj-$(CONFIG_DRM_PANEL_ILITEK_IL9322) += panel-ilitek-ili9322.o
|
||||
|
@ -15,6 +16,7 @@ obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829) += panel-leadtek-ltk500hd1829.o
|
|||
obj-$(CONFIG_DRM_PANEL_LG_LB035Q02) += panel-lg-lb035q02.o
|
||||
obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
|
||||
obj-$(CONFIG_DRM_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o
|
||||
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35510) += panel-novatek-nt35510.o
|
||||
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT39016) += panel-novatek-nt39016.o
|
||||
obj-$(CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO) += panel-olimex-lcd-olinuxino.o
|
||||
obj-$(CONFIG_DRM_PANEL_ORISETECH_OTM8009A) += panel-orisetech-otm8009a.o
|
||||
|
|
|
@ -0,0 +1,352 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Elida kd35t133 5.5" MIPI-DSI panel driver
|
||||
* Copyright (C) 2020 Theobroma Systems Design und Consulting GmbH
|
||||
*
|
||||
* based on
|
||||
*
|
||||
* Rockteck jh057n00900 5.5" MIPI-DSI panel driver
|
||||
* Copyright (C) Purism SPC 2019
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/media-bus-format.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <video/display_timing.h>
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_panel.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
/* Manufacturer specific Commands send via DSI */
|
||||
#define KD35T133_CMD_INTERFACEMODECTRL 0xb0
|
||||
#define KD35T133_CMD_FRAMERATECTRL 0xb1
|
||||
#define KD35T133_CMD_DISPLAYINVERSIONCTRL 0xb4
|
||||
#define KD35T133_CMD_DISPLAYFUNCTIONCTRL 0xb6
|
||||
#define KD35T133_CMD_POWERCONTROL1 0xc0
|
||||
#define KD35T133_CMD_POWERCONTROL2 0xc1
|
||||
#define KD35T133_CMD_VCOMCONTROL 0xc5
|
||||
#define KD35T133_CMD_POSITIVEGAMMA 0xe0
|
||||
#define KD35T133_CMD_NEGATIVEGAMMA 0xe1
|
||||
#define KD35T133_CMD_SETIMAGEFUNCTION 0xe9
|
||||
#define KD35T133_CMD_ADJUSTCONTROL3 0xf7
|
||||
|
||||
struct kd35t133 {
|
||||
struct device *dev;
|
||||
struct drm_panel panel;
|
||||
struct gpio_desc *reset_gpio;
|
||||
struct regulator *vdd;
|
||||
struct regulator *iovcc;
|
||||
bool prepared;
|
||||
};
|
||||
|
||||
static inline struct kd35t133 *panel_to_kd35t133(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct kd35t133, panel);
|
||||
}
|
||||
|
||||
#define dsi_dcs_write_seq(dsi, cmd, seq...) do { \
|
||||
static const u8 d[] = { seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_dcs_write(dsi, cmd, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
static int kd35t133_init_sequence(struct kd35t133 *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
struct device *dev = ctx->dev;
|
||||
|
||||
/*
|
||||
* Init sequence was supplied by the panel vendor with minimal
|
||||
* documentation.
|
||||
*/
|
||||
dsi_dcs_write_seq(dsi, KD35T133_CMD_POSITIVEGAMMA,
|
||||
0x00, 0x13, 0x18, 0x04, 0x0f, 0x06, 0x3a, 0x56,
|
||||
0x4d, 0x03, 0x0a, 0x06, 0x30, 0x3e, 0x0f);
|
||||
dsi_dcs_write_seq(dsi, KD35T133_CMD_NEGATIVEGAMMA,
|
||||
0x00, 0x13, 0x18, 0x01, 0x11, 0x06, 0x38, 0x34,
|
||||
0x4d, 0x06, 0x0d, 0x0b, 0x31, 0x37, 0x0f);
|
||||
dsi_dcs_write_seq(dsi, KD35T133_CMD_POWERCONTROL1, 0x18, 0x17);
|
||||
dsi_dcs_write_seq(dsi, KD35T133_CMD_POWERCONTROL2, 0x41);
|
||||
dsi_dcs_write_seq(dsi, KD35T133_CMD_VCOMCONTROL, 0x00, 0x1a, 0x80);
|
||||
dsi_dcs_write_seq(dsi, MIPI_DCS_SET_ADDRESS_MODE, 0x48);
|
||||
dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PIXEL_FORMAT, 0x55);
|
||||
dsi_dcs_write_seq(dsi, KD35T133_CMD_INTERFACEMODECTRL, 0x00);
|
||||
dsi_dcs_write_seq(dsi, KD35T133_CMD_FRAMERATECTRL, 0xa0);
|
||||
dsi_dcs_write_seq(dsi, KD35T133_CMD_DISPLAYINVERSIONCTRL, 0x02);
|
||||
dsi_dcs_write_seq(dsi, KD35T133_CMD_DISPLAYFUNCTIONCTRL,
|
||||
0x20, 0x02);
|
||||
dsi_dcs_write_seq(dsi, KD35T133_CMD_SETIMAGEFUNCTION, 0x00);
|
||||
dsi_dcs_write_seq(dsi, KD35T133_CMD_ADJUSTCONTROL3,
|
||||
0xa9, 0x51, 0x2c, 0x82);
|
||||
mipi_dsi_dcs_write(dsi, MIPI_DCS_ENTER_INVERT_MODE, NULL, 0);
|
||||
|
||||
DRM_DEV_DEBUG_DRIVER(dev, "Panel init sequence done\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kd35t133_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct kd35t133 *ctx = panel_to_kd35t133(panel);
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
int ret;
|
||||
|
||||
if (!ctx->prepared)
|
||||
return 0;
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_off(dsi);
|
||||
if (ret < 0)
|
||||
DRM_DEV_ERROR(ctx->dev, "failed to set display off: %d\n",
|
||||
ret);
|
||||
|
||||
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(ctx->dev, "failed to enter sleep mode: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
regulator_disable(ctx->iovcc);
|
||||
regulator_disable(ctx->vdd);
|
||||
|
||||
ctx->prepared = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kd35t133_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct kd35t133 *ctx = panel_to_kd35t133(panel);
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
int ret;
|
||||
|
||||
if (ctx->prepared)
|
||||
return 0;
|
||||
|
||||
DRM_DEV_DEBUG_DRIVER(ctx->dev, "Resetting the panel\n");
|
||||
ret = regulator_enable(ctx->vdd);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(ctx->dev,
|
||||
"Failed to enable vdd supply: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regulator_enable(ctx->iovcc);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(ctx->dev,
|
||||
"Failed to enable iovcc supply: %d\n", ret);
|
||||
goto disable_vdd;
|
||||
}
|
||||
|
||||
msleep(20);
|
||||
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
usleep_range(10, 20);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
|
||||
msleep(20);
|
||||
|
||||
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(ctx->dev, "Failed to exit sleep mode: %d\n", ret);
|
||||
goto disable_iovcc;
|
||||
}
|
||||
|
||||
msleep(250);
|
||||
|
||||
ret = kd35t133_init_sequence(ctx);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(ctx->dev, "Panel init sequence failed: %d\n",
|
||||
ret);
|
||||
goto disable_iovcc;
|
||||
}
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_on(dsi);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(ctx->dev, "Failed to set display on: %d\n", ret);
|
||||
goto disable_iovcc;
|
||||
}
|
||||
|
||||
msleep(50);
|
||||
|
||||
ctx->prepared = true;
|
||||
|
||||
return 0;
|
||||
|
||||
disable_iovcc:
|
||||
regulator_disable(ctx->iovcc);
|
||||
disable_vdd:
|
||||
regulator_disable(ctx->vdd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct drm_display_mode default_mode = {
|
||||
.hdisplay = 320,
|
||||
.hsync_start = 320 + 130,
|
||||
.hsync_end = 320 + 130 + 4,
|
||||
.htotal = 320 + 130 + 4 + 130,
|
||||
.vdisplay = 480,
|
||||
.vsync_start = 480 + 2,
|
||||
.vsync_end = 480 + 2 + 1,
|
||||
.vtotal = 480 + 2 + 1 + 2,
|
||||
.vrefresh = 60,
|
||||
.clock = 17000,
|
||||
.width_mm = 42,
|
||||
.height_mm = 82,
|
||||
};
|
||||
|
||||
static int kd35t133_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct kd35t133 *ctx = panel_to_kd35t133(panel);
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev, &default_mode);
|
||||
if (!mode) {
|
||||
DRM_DEV_ERROR(ctx->dev, "Failed to add mode %ux%u@%u\n",
|
||||
default_mode.hdisplay, default_mode.vdisplay,
|
||||
default_mode.vrefresh);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
drm_mode_set_name(mode);
|
||||
|
||||
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
||||
connector->display_info.width_mm = mode->width_mm;
|
||||
connector->display_info.height_mm = mode->height_mm;
|
||||
drm_mode_probed_add(connector, mode);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs kd35t133_funcs = {
|
||||
.unprepare = kd35t133_unprepare,
|
||||
.prepare = kd35t133_prepare,
|
||||
.get_modes = kd35t133_get_modes,
|
||||
};
|
||||
|
||||
static int kd35t133_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
struct kd35t133 *ctx;
|
||||
int ret;
|
||||
|
||||
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(ctx->reset_gpio)) {
|
||||
DRM_DEV_ERROR(dev, "cannot get reset gpio\n");
|
||||
return PTR_ERR(ctx->reset_gpio);
|
||||
}
|
||||
|
||||
ctx->vdd = devm_regulator_get(dev, "vdd");
|
||||
if (IS_ERR(ctx->vdd)) {
|
||||
ret = PTR_ERR(ctx->vdd);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
DRM_DEV_ERROR(dev,
|
||||
"Failed to request vdd regulator: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx->iovcc = devm_regulator_get(dev, "iovcc");
|
||||
if (IS_ERR(ctx->iovcc)) {
|
||||
ret = PTR_ERR(ctx->iovcc);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
DRM_DEV_ERROR(dev,
|
||||
"Failed to request iovcc regulator: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mipi_dsi_set_drvdata(dsi, ctx);
|
||||
|
||||
ctx->dev = dev;
|
||||
|
||||
dsi->lanes = 1;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
|
||||
MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET;
|
||||
|
||||
drm_panel_init(&ctx->panel, &dsi->dev, &kd35t133_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
|
||||
ret = drm_panel_of_backlight(&ctx->panel);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drm_panel_add(&ctx->panel);
|
||||
|
||||
ret = mipi_dsi_attach(dsi);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(dev, "mipi_dsi_attach failed: %d\n", ret);
|
||||
drm_panel_remove(&ctx->panel);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void kd35t133_shutdown(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct kd35t133 *ctx = mipi_dsi_get_drvdata(dsi);
|
||||
int ret;
|
||||
|
||||
ret = drm_panel_unprepare(&ctx->panel);
|
||||
if (ret < 0)
|
||||
DRM_DEV_ERROR(&dsi->dev, "Failed to unprepare panel: %d\n",
|
||||
ret);
|
||||
|
||||
ret = drm_panel_disable(&ctx->panel);
|
||||
if (ret < 0)
|
||||
DRM_DEV_ERROR(&dsi->dev, "Failed to disable panel: %d\n",
|
||||
ret);
|
||||
}
|
||||
|
||||
static int kd35t133_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct kd35t133 *ctx = mipi_dsi_get_drvdata(dsi);
|
||||
int ret;
|
||||
|
||||
kd35t133_shutdown(dsi);
|
||||
|
||||
ret = mipi_dsi_detach(dsi);
|
||||
if (ret < 0)
|
||||
DRM_DEV_ERROR(&dsi->dev, "Failed to detach from DSI host: %d\n",
|
||||
ret);
|
||||
|
||||
drm_panel_remove(&ctx->panel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id kd35t133_of_match[] = {
|
||||
{ .compatible = "elida,kd35t133" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, kd35t133_of_match);
|
||||
|
||||
static struct mipi_dsi_driver kd35t133_driver = {
|
||||
.driver = {
|
||||
.name = "panel-elida-kd35t133",
|
||||
.of_match_table = kd35t133_of_match,
|
||||
},
|
||||
.probe = kd35t133_probe,
|
||||
.remove = kd35t133_remove,
|
||||
.shutdown = kd35t133_shutdown,
|
||||
};
|
||||
module_mipi_dsi_driver(kd35t133_driver);
|
||||
|
||||
MODULE_AUTHOR("Heiko Stuebner <heiko.stuebner@theobroma-systems.com>");
|
||||
MODULE_DESCRIPTION("DRM driver for Elida kd35t133 MIPI DSI panel");
|
||||
MODULE_LICENSE("GPL v2");
|
File diff suppressed because it is too large
Load Diff
|
@ -351,6 +351,65 @@ static const struct drm_panel_funcs panel_simple_funcs = {
|
|||
.get_timings = panel_simple_get_timings,
|
||||
};
|
||||
|
||||
static struct panel_desc panel_dpi;
|
||||
|
||||
static int panel_dpi_probe(struct device *dev,
|
||||
struct panel_simple *panel)
|
||||
{
|
||||
struct display_timing *timing;
|
||||
const struct device_node *np;
|
||||
struct panel_desc *desc;
|
||||
unsigned int bus_flags;
|
||||
struct videomode vm;
|
||||
const char *mapping;
|
||||
int ret;
|
||||
|
||||
np = dev->of_node;
|
||||
desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
|
||||
if (!desc)
|
||||
return -ENOMEM;
|
||||
|
||||
timing = devm_kzalloc(dev, sizeof(*timing), GFP_KERNEL);
|
||||
if (!timing)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = of_get_display_timing(np, "panel-timing", timing);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%pOF: no panel-timing node found for \"panel-dpi\" binding\n",
|
||||
np);
|
||||
return ret;
|
||||
}
|
||||
|
||||
desc->timings = timing;
|
||||
desc->num_timings = 1;
|
||||
|
||||
of_property_read_u32(np, "width-mm", &desc->size.width);
|
||||
of_property_read_u32(np, "height-mm", &desc->size.height);
|
||||
|
||||
of_property_read_string(np, "data-mapping", &mapping);
|
||||
if (!strcmp(mapping, "rgb24"))
|
||||
desc->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
|
||||
else if (!strcmp(mapping, "rgb565"))
|
||||
desc->bus_format = MEDIA_BUS_FMT_RGB565_1X16;
|
||||
else if (!strcmp(mapping, "bgr666"))
|
||||
desc->bus_format = MEDIA_BUS_FMT_RGB666_1X18;
|
||||
else if (!strcmp(mapping, "lvds666"))
|
||||
desc->bus_format = MEDIA_BUS_FMT_RGB666_1X24_CPADHI;
|
||||
|
||||
/* Extract bus_flags from display_timing */
|
||||
bus_flags = 0;
|
||||
vm.flags = timing->flags;
|
||||
drm_bus_flags_from_videomode(&vm, &bus_flags);
|
||||
desc->bus_flags = bus_flags;
|
||||
|
||||
/* We do not know the connector for the DT node, so guess it */
|
||||
desc->connector_type = DRM_MODE_CONNECTOR_DPI;
|
||||
|
||||
panel->desc = desc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define PANEL_SIMPLE_BOUNDS_CHECK(to_check, bounds, field) \
|
||||
(to_check->field.typ >= bounds->field.min && \
|
||||
to_check->field.typ <= bounds->field.max)
|
||||
|
@ -437,8 +496,15 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
|
|||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
if (!of_get_display_timing(dev->of_node, "panel-timing", &dt))
|
||||
panel_simple_parse_panel_timing_node(dev, panel, &dt);
|
||||
if (desc == &panel_dpi) {
|
||||
/* Handle the generic panel-dpi binding */
|
||||
err = panel_dpi_probe(dev, panel);
|
||||
if (err)
|
||||
goto free_ddc;
|
||||
} else {
|
||||
if (!of_get_display_timing(dev->of_node, "panel-timing", &dt))
|
||||
panel_simple_parse_panel_timing_node(dev, panel, &dt);
|
||||
}
|
||||
|
||||
drm_panel_init(&panel->base, dev, &panel_simple_funcs,
|
||||
desc->connector_type);
|
||||
|
@ -2340,6 +2406,51 @@ static const struct panel_desc netron_dy_e231732 = {
|
|||
.bus_format = MEDIA_BUS_FMT_RGB666_1X18,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode neweast_wjfh116008a_modes[] = {
|
||||
{
|
||||
.clock = 138500,
|
||||
.hdisplay = 1920,
|
||||
.hsync_start = 1920 + 48,
|
||||
.hsync_end = 1920 + 48 + 32,
|
||||
.htotal = 1920 + 48 + 32 + 80,
|
||||
.vdisplay = 1080,
|
||||
.vsync_start = 1080 + 3,
|
||||
.vsync_end = 1080 + 3 + 5,
|
||||
.vtotal = 1080 + 3 + 5 + 23,
|
||||
.vrefresh = 60,
|
||||
.flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
|
||||
}, {
|
||||
.clock = 110920,
|
||||
.hdisplay = 1920,
|
||||
.hsync_start = 1920 + 48,
|
||||
.hsync_end = 1920 + 48 + 32,
|
||||
.htotal = 1920 + 48 + 32 + 80,
|
||||
.vdisplay = 1080,
|
||||
.vsync_start = 1080 + 3,
|
||||
.vsync_end = 1080 + 3 + 5,
|
||||
.vtotal = 1080 + 3 + 5 + 23,
|
||||
.vrefresh = 48,
|
||||
.flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
|
||||
}
|
||||
};
|
||||
|
||||
static const struct panel_desc neweast_wjfh116008a = {
|
||||
.modes = neweast_wjfh116008a_modes,
|
||||
.num_modes = 2,
|
||||
.bpc = 6,
|
||||
.size = {
|
||||
.width = 260,
|
||||
.height = 150,
|
||||
},
|
||||
.delay = {
|
||||
.prepare = 110,
|
||||
.enable = 20,
|
||||
.unprepare = 500,
|
||||
},
|
||||
.bus_format = MEDIA_BUS_FMT_RGB666_1X18,
|
||||
.connector_type = DRM_MODE_CONNECTOR_eDP,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode newhaven_nhd_43_480272ef_atxl_mode = {
|
||||
.clock = 9000,
|
||||
.hdisplay = 480,
|
||||
|
@ -2914,30 +3025,6 @@ static const struct panel_desc sharp_lq123p1jx31 = {
|
|||
},
|
||||
};
|
||||
|
||||
static const struct drm_display_mode sharp_lq150x1lg11_mode = {
|
||||
.clock = 71100,
|
||||
.hdisplay = 1024,
|
||||
.hsync_start = 1024 + 168,
|
||||
.hsync_end = 1024 + 168 + 64,
|
||||
.htotal = 1024 + 168 + 64 + 88,
|
||||
.vdisplay = 768,
|
||||
.vsync_start = 768 + 37,
|
||||
.vsync_end = 768 + 37 + 2,
|
||||
.vtotal = 768 + 37 + 2 + 8,
|
||||
.vrefresh = 60,
|
||||
};
|
||||
|
||||
static const struct panel_desc sharp_lq150x1lg11 = {
|
||||
.modes = &sharp_lq150x1lg11_mode,
|
||||
.num_modes = 1,
|
||||
.bpc = 6,
|
||||
.size = {
|
||||
.width = 304,
|
||||
.height = 228,
|
||||
},
|
||||
.bus_format = MEDIA_BUS_FMT_RGB565_1X16,
|
||||
};
|
||||
|
||||
static const struct display_timing sharp_ls020b1dd01d_timing = {
|
||||
.pixelclock = { 2000000, 4200000, 5000000 },
|
||||
.hactive = { 240, 240, 240 },
|
||||
|
@ -3560,6 +3647,9 @@ static const struct of_device_id platform_of_match[] = {
|
|||
}, {
|
||||
.compatible = "netron-dy,e231732",
|
||||
.data = &netron_dy_e231732,
|
||||
}, {
|
||||
.compatible = "neweast,wjfh116008a",
|
||||
.data = &neweast_wjfh116008a,
|
||||
}, {
|
||||
.compatible = "newhaven,nhd-4.3-480272ef-atxl",
|
||||
.data = &newhaven_nhd_43_480272ef_atxl,
|
||||
|
@ -3629,9 +3719,6 @@ static const struct of_device_id platform_of_match[] = {
|
|||
}, {
|
||||
.compatible = "sharp,lq123p1jx31",
|
||||
.data = &sharp_lq123p1jx31,
|
||||
}, {
|
||||
.compatible = "sharp,lq150x1lg11",
|
||||
.data = &sharp_lq150x1lg11,
|
||||
}, {
|
||||
.compatible = "sharp,ls020b1dd01d",
|
||||
.data = &sharp_ls020b1dd01d,
|
||||
|
@ -3689,6 +3776,10 @@ static const struct of_device_id platform_of_match[] = {
|
|||
}, {
|
||||
.compatible = "winstar,wf35ltiacd",
|
||||
.data = &winstar_wf35ltiacd,
|
||||
}, {
|
||||
/* Must be the last entry */
|
||||
.compatible = "panel-dpi",
|
||||
.data = &panel_dpi,
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
|
|
|
@ -659,7 +659,7 @@ static int panfrost_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
const char * const default_supplies[] = { "mali" };
|
||||
static const char * const default_supplies[] = { "mali" };
|
||||
static const struct panfrost_compatible default_data = {
|
||||
.num_supplies = ARRAY_SIZE(default_supplies),
|
||||
.supply_names = default_supplies,
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_simple_kms_helper.h>
|
||||
|
||||
#include "qxl_drv.h"
|
||||
#include "qxl_object.h"
|
||||
|
@ -1007,9 +1008,6 @@ static struct drm_encoder *qxl_best_encoder(struct drm_connector *connector)
|
|||
return &qxl_output->enc;
|
||||
}
|
||||
|
||||
static const struct drm_encoder_helper_funcs qxl_enc_helper_funcs = {
|
||||
};
|
||||
|
||||
static const struct drm_connector_helper_funcs qxl_connector_helper_funcs = {
|
||||
.get_modes = qxl_conn_get_modes,
|
||||
.mode_valid = qxl_conn_mode_valid,
|
||||
|
@ -1059,15 +1057,6 @@ static const struct drm_connector_funcs qxl_connector_funcs = {
|
|||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
};
|
||||
|
||||
static void qxl_enc_destroy(struct drm_encoder *encoder)
|
||||
{
|
||||
drm_encoder_cleanup(encoder);
|
||||
}
|
||||
|
||||
static const struct drm_encoder_funcs qxl_enc_funcs = {
|
||||
.destroy = qxl_enc_destroy,
|
||||
};
|
||||
|
||||
static int qxl_mode_create_hotplug_mode_update_property(struct qxl_device *qdev)
|
||||
{
|
||||
if (qdev->hotplug_mode_update_property)
|
||||
|
@ -1086,6 +1075,7 @@ static int qdev_output_init(struct drm_device *dev, int num_output)
|
|||
struct qxl_output *qxl_output;
|
||||
struct drm_connector *connector;
|
||||
struct drm_encoder *encoder;
|
||||
int ret;
|
||||
|
||||
qxl_output = kzalloc(sizeof(struct qxl_output), GFP_KERNEL);
|
||||
if (!qxl_output)
|
||||
|
@ -1098,15 +1088,19 @@ static int qdev_output_init(struct drm_device *dev, int num_output)
|
|||
drm_connector_init(dev, &qxl_output->base,
|
||||
&qxl_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL);
|
||||
|
||||
drm_encoder_init(dev, &qxl_output->enc, &qxl_enc_funcs,
|
||||
DRM_MODE_ENCODER_VIRTUAL, NULL);
|
||||
ret = drm_simple_encoder_init(dev, &qxl_output->enc,
|
||||
DRM_MODE_ENCODER_VIRTUAL);
|
||||
if (ret) {
|
||||
drm_err(dev, "drm_simple_encoder_init() failed, error %d\n",
|
||||
ret);
|
||||
goto err_drm_connector_cleanup;
|
||||
}
|
||||
|
||||
/* we get HPD via client monitors config */
|
||||
connector->polled = DRM_CONNECTOR_POLL_HPD;
|
||||
encoder->possible_crtcs = 1 << num_output;
|
||||
drm_connector_attach_encoder(&qxl_output->base,
|
||||
&qxl_output->enc);
|
||||
drm_encoder_helper_add(encoder, &qxl_enc_helper_funcs);
|
||||
drm_connector_helper_add(connector, &qxl_connector_helper_funcs);
|
||||
|
||||
drm_object_attach_property(&connector->base,
|
||||
|
@ -1116,6 +1110,11 @@ static int qdev_output_init(struct drm_device *dev, int num_output)
|
|||
drm_object_attach_property(&connector->base,
|
||||
dev->mode_config.suggested_y_property, 0);
|
||||
return 0;
|
||||
|
||||
err_drm_connector_cleanup:
|
||||
drm_connector_cleanup(&qxl_output->base);
|
||||
kfree(qxl_output);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct drm_framebuffer *
|
||||
|
|
|
@ -303,23 +303,13 @@ static struct drm_connector *radeon_dp_add_mst_connector(struct drm_dp_mst_topol
|
|||
|
||||
static void radeon_dp_register_mst_connector(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
|
||||
radeon_fb_add_connector(rdev, connector);
|
||||
|
||||
drm_connector_register(connector);
|
||||
}
|
||||
|
||||
static void radeon_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct radeon_connector *master = container_of(mgr, struct radeon_connector, mst_mgr);
|
||||
struct drm_device *dev = master->base.dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
|
||||
drm_connector_unregister(connector);
|
||||
radeon_fb_remove_connector(rdev, connector);
|
||||
drm_connector_cleanup(connector);
|
||||
|
||||
kfree(connector);
|
||||
|
|
|
@ -354,15 +354,10 @@ int radeon_fbdev_init(struct radeon_device *rdev)
|
|||
drm_fb_helper_prepare(rdev->ddev, &rfbdev->helper,
|
||||
&radeon_fb_helper_funcs);
|
||||
|
||||
ret = drm_fb_helper_init(rdev->ddev, &rfbdev->helper,
|
||||
RADEONFB_CONN_LIMIT);
|
||||
ret = drm_fb_helper_init(rdev->ddev, &rfbdev->helper);
|
||||
if (ret)
|
||||
goto free;
|
||||
|
||||
ret = drm_fb_helper_single_add_all_connectors(&rfbdev->helper);
|
||||
if (ret)
|
||||
goto fini;
|
||||
|
||||
/* disable all the possible outputs/crtcs before entering KMS mode */
|
||||
drm_helper_disable_unused_functions(rdev->ddev);
|
||||
|
||||
|
@ -404,15 +399,3 @@ bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj)
|
|||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void radeon_fb_add_connector(struct radeon_device *rdev, struct drm_connector *connector)
|
||||
{
|
||||
if (rdev->mode_info.rfbdev)
|
||||
drm_fb_helper_add_one_connector(&rdev->mode_info.rfbdev->helper, connector);
|
||||
}
|
||||
|
||||
void radeon_fb_remove_connector(struct radeon_device *rdev, struct drm_connector *connector)
|
||||
{
|
||||
if (rdev->mode_info.rfbdev)
|
||||
drm_fb_helper_remove_one_connector(&rdev->mode_info.rfbdev->helper, connector);
|
||||
}
|
||||
|
|
|
@ -986,9 +986,6 @@ bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj)
|
|||
|
||||
void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id);
|
||||
|
||||
void radeon_fb_add_connector(struct radeon_device *rdev, struct drm_connector *connector);
|
||||
void radeon_fb_remove_connector(struct radeon_device *rdev, struct drm_connector *connector);
|
||||
|
||||
void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id);
|
||||
|
||||
int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled);
|
||||
|
|
|
@ -124,7 +124,7 @@ int rockchip_drm_fbdev_init(struct drm_device *dev)
|
|||
|
||||
drm_fb_helper_prepare(dev, helper, &rockchip_drm_fb_helper_funcs);
|
||||
|
||||
ret = drm_fb_helper_init(dev, helper, ROCKCHIP_MAX_CONNECTOR);
|
||||
ret = drm_fb_helper_init(dev, helper);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(dev->dev,
|
||||
"Failed to initialize drm fb helper - %d.\n",
|
||||
|
@ -132,13 +132,6 @@ int rockchip_drm_fbdev_init(struct drm_device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = drm_fb_helper_single_add_all_connectors(helper);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(dev->dev,
|
||||
"Failed to add connectors - %d.\n", ret);
|
||||
goto err_drm_fb_helper_fini;
|
||||
}
|
||||
|
||||
ret = drm_fb_helper_initial_config(helper, PREFERRED_BPP);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(dev->dev,
|
||||
|
|
|
@ -314,19 +314,13 @@ static int tegra_fbdev_init(struct tegra_fbdev *fbdev,
|
|||
struct drm_device *drm = fbdev->base.dev;
|
||||
int err;
|
||||
|
||||
err = drm_fb_helper_init(drm, &fbdev->base, max_connectors);
|
||||
err = drm_fb_helper_init(drm, &fbdev->base);
|
||||
if (err < 0) {
|
||||
dev_err(drm->dev, "failed to initialize DRM FB helper: %d\n",
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = drm_fb_helper_single_add_all_connectors(&fbdev->base);
|
||||
if (err < 0) {
|
||||
dev_err(drm->dev, "failed to add connectors: %d\n", err);
|
||||
goto fini;
|
||||
}
|
||||
|
||||
err = drm_fb_helper_initial_config(&fbdev->base, preferred_bpp);
|
||||
if (err < 0) {
|
||||
dev_err(drm->dev, "failed to set initial configuration: %d\n",
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "tidss_dispc.h"
|
||||
#include "tidss_drv.h"
|
||||
#include "tidss_irq.h"
|
||||
#include "tidss_plane.h"
|
||||
|
||||
/* Page flip and frame done IRQs */
|
||||
|
||||
|
@ -111,6 +112,54 @@ static int tidss_crtc_atomic_check(struct drm_crtc *crtc,
|
|||
return dispc_vp_bus_check(dispc, hw_videoport, state);
|
||||
}
|
||||
|
||||
/*
|
||||
* This needs all affected planes to be present in the atomic
|
||||
* state. The untouched planes are added to the state in
|
||||
* tidss_atomic_check().
|
||||
*/
|
||||
static void tidss_crtc_position_planes(struct tidss_device *tidss,
|
||||
struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *old_state,
|
||||
bool newmodeset)
|
||||
{
|
||||
struct drm_atomic_state *ostate = old_state->state;
|
||||
struct tidss_crtc *tcrtc = to_tidss_crtc(crtc);
|
||||
struct drm_crtc_state *cstate = crtc->state;
|
||||
int layer;
|
||||
|
||||
if (!newmodeset && !cstate->zpos_changed &&
|
||||
!to_tidss_crtc_state(cstate)->plane_pos_changed)
|
||||
return;
|
||||
|
||||
for (layer = 0; layer < tidss->feat->num_planes; layer++) {
|
||||
struct drm_plane_state *pstate;
|
||||
struct drm_plane *plane;
|
||||
bool layer_active = false;
|
||||
int i;
|
||||
|
||||
for_each_new_plane_in_state(ostate, plane, pstate, i) {
|
||||
if (pstate->crtc != crtc || !pstate->visible)
|
||||
continue;
|
||||
|
||||
if (pstate->normalized_zpos == layer) {
|
||||
layer_active = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (layer_active) {
|
||||
struct tidss_plane *tplane = to_tidss_plane(plane);
|
||||
|
||||
dispc_ovr_set_plane(tidss->dispc, tplane->hw_plane_id,
|
||||
tcrtc->hw_videoport,
|
||||
pstate->crtc_x, pstate->crtc_y,
|
||||
layer);
|
||||
}
|
||||
dispc_ovr_enable_layer(tidss->dispc, tcrtc->hw_videoport, layer,
|
||||
layer_active);
|
||||
}
|
||||
}
|
||||
|
||||
static void tidss_crtc_atomic_flush(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *old_crtc_state)
|
||||
{
|
||||
|
@ -146,6 +195,9 @@ static void tidss_crtc_atomic_flush(struct drm_crtc *crtc,
|
|||
/* Write vp properties to HW if needed. */
|
||||
dispc_vp_setup(tidss->dispc, tcrtc->hw_videoport, crtc->state, false);
|
||||
|
||||
/* Update plane positions if needed. */
|
||||
tidss_crtc_position_planes(tidss, crtc, old_crtc_state, false);
|
||||
|
||||
WARN_ON(drm_crtc_vblank_get(crtc) != 0);
|
||||
|
||||
spin_lock_irqsave(&ddev->event_lock, flags);
|
||||
|
@ -183,6 +235,7 @@ static void tidss_crtc_atomic_enable(struct drm_crtc *crtc,
|
|||
return;
|
||||
|
||||
dispc_vp_setup(tidss->dispc, tcrtc->hw_videoport, crtc->state, true);
|
||||
tidss_crtc_position_planes(tidss, crtc, old_state, true);
|
||||
|
||||
/* Turn vertical blanking interrupt reporting on. */
|
||||
drm_crtc_vblank_on(crtc);
|
||||
|
@ -318,6 +371,8 @@ static struct drm_crtc_state *tidss_crtc_duplicate_state(struct drm_crtc *crtc)
|
|||
|
||||
__drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
|
||||
|
||||
state->plane_pos_changed = false;
|
||||
|
||||
state->bus_format = current_state->bus_format;
|
||||
state->bus_flags = current_state->bus_flags;
|
||||
|
||||
|
|
|
@ -32,6 +32,8 @@ struct tidss_crtc_state {
|
|||
/* Must be first. */
|
||||
struct drm_crtc_state base;
|
||||
|
||||
bool plane_pos_changed;
|
||||
|
||||
u32 bus_format;
|
||||
u32 bus_flags;
|
||||
};
|
||||
|
|
|
@ -281,11 +281,6 @@ struct dss_vp_data {
|
|||
u32 *gamma_table;
|
||||
};
|
||||
|
||||
struct dss_plane_data {
|
||||
u32 zorder;
|
||||
u32 hw_videoport;
|
||||
};
|
||||
|
||||
struct dispc_device {
|
||||
struct tidss_device *tidss;
|
||||
struct device *dev;
|
||||
|
@ -307,8 +302,6 @@ struct dispc_device {
|
|||
|
||||
struct dss_vp_data vp_data[TIDSS_MAX_PORTS];
|
||||
|
||||
struct dss_plane_data plane_data[TIDSS_MAX_PLANES];
|
||||
|
||||
u32 *fourccs;
|
||||
u32 num_fourccs;
|
||||
|
||||
|
@ -1235,7 +1228,7 @@ int dispc_vp_set_clk_rate(struct dispc_device *dispc, u32 hw_videoport,
|
|||
|
||||
if (dispc_pclk_diff(rate, new_rate) > 5)
|
||||
dev_warn(dispc->dev,
|
||||
"vp%d: Clock rate %lu differs over 5%% from requsted %lu\n",
|
||||
"vp%d: Clock rate %lu differs over 5%% from requested %lu\n",
|
||||
hw_videoport, new_rate, rate);
|
||||
|
||||
dev_dbg(dispc->dev, "vp%d: new rate %lu Hz (requested %lu Hz)\n",
|
||||
|
@ -1247,7 +1240,7 @@ int dispc_vp_set_clk_rate(struct dispc_device *dispc, u32 hw_videoport,
|
|||
/* OVR */
|
||||
static void dispc_k2g_ovr_set_plane(struct dispc_device *dispc,
|
||||
u32 hw_plane, u32 hw_videoport,
|
||||
u32 x, u32 y, u32 zpos)
|
||||
u32 x, u32 y, u32 layer)
|
||||
{
|
||||
/* On k2g there is only one plane and no need for ovr */
|
||||
dispc_vid_write(dispc, hw_plane, DISPC_VID_K2G_POSITION,
|
||||
|
@ -1256,44 +1249,43 @@ static void dispc_k2g_ovr_set_plane(struct dispc_device *dispc,
|
|||
|
||||
static void dispc_am65x_ovr_set_plane(struct dispc_device *dispc,
|
||||
u32 hw_plane, u32 hw_videoport,
|
||||
u32 x, u32 y, u32 zpos)
|
||||
u32 x, u32 y, u32 layer)
|
||||
{
|
||||
OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(zpos),
|
||||
OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer),
|
||||
hw_plane, 4, 1);
|
||||
OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(zpos),
|
||||
OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer),
|
||||
x, 17, 6);
|
||||
OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(zpos),
|
||||
OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer),
|
||||
y, 30, 19);
|
||||
}
|
||||
|
||||
static void dispc_j721e_ovr_set_plane(struct dispc_device *dispc,
|
||||
u32 hw_plane, u32 hw_videoport,
|
||||
u32 x, u32 y, u32 zpos)
|
||||
u32 x, u32 y, u32 layer)
|
||||
{
|
||||
OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(zpos),
|
||||
OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer),
|
||||
hw_plane, 4, 1);
|
||||
OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES2(zpos),
|
||||
OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES2(layer),
|
||||
x, 13, 0);
|
||||
OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES2(zpos),
|
||||
OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES2(layer),
|
||||
y, 29, 16);
|
||||
}
|
||||
|
||||
static void dispc_ovr_set_plane(struct dispc_device *dispc,
|
||||
u32 hw_plane, u32 hw_videoport,
|
||||
u32 x, u32 y, u32 zpos)
|
||||
void dispc_ovr_set_plane(struct dispc_device *dispc, u32 hw_plane,
|
||||
u32 hw_videoport, u32 x, u32 y, u32 layer)
|
||||
{
|
||||
switch (dispc->feat->subrev) {
|
||||
case DISPC_K2G:
|
||||
dispc_k2g_ovr_set_plane(dispc, hw_plane, hw_videoport,
|
||||
x, y, zpos);
|
||||
x, y, layer);
|
||||
break;
|
||||
case DISPC_AM65X:
|
||||
dispc_am65x_ovr_set_plane(dispc, hw_plane, hw_videoport,
|
||||
x, y, zpos);
|
||||
x, y, layer);
|
||||
break;
|
||||
case DISPC_J721E:
|
||||
dispc_j721e_ovr_set_plane(dispc, hw_plane, hw_videoport,
|
||||
x, y, zpos);
|
||||
x, y, layer);
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
|
@ -1301,10 +1293,13 @@ static void dispc_ovr_set_plane(struct dispc_device *dispc,
|
|||
}
|
||||
}
|
||||
|
||||
static void dispc_ovr_enable_plane(struct dispc_device *dispc,
|
||||
u32 hw_videoport, u32 zpos, bool enable)
|
||||
void dispc_ovr_enable_layer(struct dispc_device *dispc,
|
||||
u32 hw_videoport, u32 layer, bool enable)
|
||||
{
|
||||
OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(zpos),
|
||||
if (dispc->feat->subrev == DISPC_K2G)
|
||||
return;
|
||||
|
||||
OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer),
|
||||
!!enable, 0, 0);
|
||||
}
|
||||
|
||||
|
@ -1510,7 +1505,7 @@ struct dispc_csc_coef *dispc_find_csc(enum drm_color_encoding encoding,
|
|||
static void dispc_vid_csc_setup(struct dispc_device *dispc, u32 hw_plane,
|
||||
const struct drm_plane_state *state)
|
||||
{
|
||||
static const struct dispc_csc_coef *coef;
|
||||
const struct dispc_csc_coef *coef;
|
||||
|
||||
coef = dispc_find_csc(state->color_encoding, state->color_range);
|
||||
if (!coef) {
|
||||
|
@ -1699,7 +1694,7 @@ static int dispc_vid_calc_scaling(struct dispc_device *dispc,
|
|||
|
||||
if (sp->xinc > f->xinc_max) {
|
||||
dev_dbg(dispc->dev,
|
||||
"%s: Too wide input bufer %u > %u\n", __func__,
|
||||
"%s: Too wide input buffer %u > %u\n", __func__,
|
||||
state->src_w >> 16, in_width_max * f->xinc_max);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -2070,21 +2065,11 @@ int dispc_plane_setup(struct dispc_device *dispc, u32 hw_plane,
|
|||
VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES, 0,
|
||||
28, 28);
|
||||
|
||||
dispc_ovr_set_plane(dispc, hw_plane, hw_videoport,
|
||||
state->crtc_x, state->crtc_y,
|
||||
state->normalized_zpos);
|
||||
|
||||
dispc->plane_data[hw_plane].zorder = state->normalized_zpos;
|
||||
dispc->plane_data[hw_plane].hw_videoport = hw_videoport;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dispc_plane_enable(struct dispc_device *dispc, u32 hw_plane, bool enable)
|
||||
{
|
||||
dispc_ovr_enable_plane(dispc, dispc->plane_data[hw_plane].hw_videoport,
|
||||
dispc->plane_data[hw_plane].zorder, enable);
|
||||
|
||||
VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES, !!enable, 0, 0);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -94,6 +94,11 @@ extern const struct dispc_features dispc_j721e_feats;
|
|||
void dispc_set_irqenable(struct dispc_device *dispc, dispc_irq_t mask);
|
||||
dispc_irq_t dispc_read_and_clear_irqstatus(struct dispc_device *dispc);
|
||||
|
||||
void dispc_ovr_set_plane(struct dispc_device *dispc, u32 hw_plane,
|
||||
u32 hw_videoport, u32 x, u32 y, u32 layer);
|
||||
void dispc_ovr_enable_layer(struct dispc_device *dispc,
|
||||
u32 hw_videoport, u32 layer, bool enable);
|
||||
|
||||
void dispc_vp_prepare(struct dispc_device *dispc, u32 hw_videoport,
|
||||
const struct drm_crtc_state *state);
|
||||
void dispc_vp_enable(struct dispc_device *dispc, u32 hw_videoport,
|
||||
|
|
|
@ -32,7 +32,7 @@ static int tidss_encoder_atomic_check(struct drm_encoder *encoder,
|
|||
* bridge timings, or from the connector's display_info if no
|
||||
* bridge defines the timings.
|
||||
*/
|
||||
list_for_each_entry(bridge, &encoder->bridge_chain, chain_node) {
|
||||
drm_for_each_bridge_in_chain(encoder, bridge) {
|
||||
if (!bridge->timings)
|
||||
continue;
|
||||
|
||||
|
|
|
@ -47,9 +47,59 @@ static const struct drm_mode_config_helper_funcs mode_config_helper_funcs = {
|
|||
.atomic_commit_tail = tidss_atomic_commit_tail,
|
||||
};
|
||||
|
||||
static int tidss_atomic_check(struct drm_device *ddev,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_plane_state *opstate;
|
||||
struct drm_plane_state *npstate;
|
||||
struct drm_plane *plane;
|
||||
struct drm_crtc_state *cstate;
|
||||
struct drm_crtc *crtc;
|
||||
int ret, i;
|
||||
|
||||
ret = drm_atomic_helper_check(ddev, state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Add all active planes on a CRTC to the atomic state, if
|
||||
* x/y/z position or activity of any plane on that CRTC
|
||||
* changes. This is needed for updating the plane positions in
|
||||
* tidss_crtc_position_planes() which is called from
|
||||
* crtc_atomic_enable() and crtc_atomic_flush(). We have an
|
||||
* extra flag to to mark x,y-position changes and together
|
||||
* with zpos_changed the condition recognizes all the above
|
||||
* cases.
|
||||
*/
|
||||
for_each_oldnew_plane_in_state(state, plane, opstate, npstate, i) {
|
||||
if (!npstate->crtc || !npstate->visible)
|
||||
continue;
|
||||
|
||||
if (!opstate->crtc || opstate->crtc_x != npstate->crtc_x ||
|
||||
opstate->crtc_y != npstate->crtc_y) {
|
||||
cstate = drm_atomic_get_crtc_state(state,
|
||||
npstate->crtc);
|
||||
if (IS_ERR(cstate))
|
||||
return PTR_ERR(cstate);
|
||||
to_tidss_crtc_state(cstate)->plane_pos_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
for_each_new_crtc_in_state(state, crtc, cstate, i) {
|
||||
if (to_tidss_crtc_state(cstate)->plane_pos_changed ||
|
||||
cstate->zpos_changed) {
|
||||
ret = drm_atomic_add_affected_planes(state, crtc);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_mode_config_funcs mode_config_funcs = {
|
||||
.fb_create = drm_gem_fb_create,
|
||||
.atomic_check = drm_atomic_helper_check,
|
||||
.atomic_check = tidss_atomic_check,
|
||||
.atomic_commit = drm_atomic_helper_commit,
|
||||
};
|
||||
|
||||
|
|
|
@ -1196,6 +1196,18 @@ int ttm_bo_validate(struct ttm_buffer_object *bo,
|
|||
uint32_t new_flags;
|
||||
|
||||
dma_resv_assert_held(bo->base.resv);
|
||||
|
||||
/*
|
||||
* Remove the backing store if no placement is given.
|
||||
*/
|
||||
if (!placement->num_placement && !placement->num_busy_placement) {
|
||||
ret = ttm_bo_pipeline_gutting(bo);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ttm_tt_create(bo, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether we need to move buffer.
|
||||
*/
|
||||
|
|
|
@ -254,27 +254,42 @@ struct v3d_csd_job {
|
|||
};
|
||||
|
||||
/**
|
||||
* _wait_for - magic (register) wait macro
|
||||
* __wait_for - magic wait macro
|
||||
*
|
||||
* Does the right thing for modeset paths when run under kdgb or similar atomic
|
||||
* contexts. Note that it's important that we check the condition again after
|
||||
* having timed out, since the timeout could be due to preemption or similar and
|
||||
* we've never had a chance to check the condition before the timeout.
|
||||
* Macro to help avoid open coding check/wait/timeout patterns. Note that it's
|
||||
* important that we check the condition again after having timed out, since the
|
||||
* timeout could be due to preemption or similar and we've never had a chance to
|
||||
* check the condition before the timeout.
|
||||
*/
|
||||
#define wait_for(COND, MS) ({ \
|
||||
unsigned long timeout__ = jiffies + msecs_to_jiffies(MS) + 1; \
|
||||
int ret__ = 0; \
|
||||
while (!(COND)) { \
|
||||
if (time_after(jiffies, timeout__)) { \
|
||||
if (!(COND)) \
|
||||
ret__ = -ETIMEDOUT; \
|
||||
#define __wait_for(OP, COND, US, Wmin, Wmax) ({ \
|
||||
const ktime_t end__ = ktime_add_ns(ktime_get_raw(), 1000ll * (US)); \
|
||||
long wait__ = (Wmin); /* recommended min for usleep is 10 us */ \
|
||||
int ret__; \
|
||||
might_sleep(); \
|
||||
for (;;) { \
|
||||
const bool expired__ = ktime_after(ktime_get_raw(), end__); \
|
||||
OP; \
|
||||
/* Guarantee COND check prior to timeout */ \
|
||||
barrier(); \
|
||||
if (COND) { \
|
||||
ret__ = 0; \
|
||||
break; \
|
||||
} \
|
||||
msleep(1); \
|
||||
if (expired__) { \
|
||||
ret__ = -ETIMEDOUT; \
|
||||
break; \
|
||||
} \
|
||||
usleep_range(wait__, wait__ * 2); \
|
||||
if (wait__ < (Wmax)) \
|
||||
wait__ <<= 1; \
|
||||
} \
|
||||
ret__; \
|
||||
})
|
||||
|
||||
#define _wait_for(COND, US, Wmin, Wmax) __wait_for(, (COND), (US), (Wmin), \
|
||||
(Wmax))
|
||||
#define wait_for(COND, MS) _wait_for((COND), (MS) * 1000, 10, 1000)
|
||||
|
||||
static inline unsigned long nsecs_to_jiffies_timeout(const u64 n)
|
||||
{
|
||||
/* nsecs_to_jiffies64() does not guard against overflow */
|
||||
|
|
|
@ -138,7 +138,7 @@ struct vbva_buffer {
|
|||
|
||||
u32 data_len;
|
||||
/* variable size for the rest of the vbva_buffer area in VRAM. */
|
||||
u8 data[0];
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
#define VBVA_MAX_RECORD_SIZE (128 * 1024 * 1024)
|
||||
|
|
|
@ -65,7 +65,7 @@ struct vc4_perfmon {
|
|||
* Note that counter values can't be reset, but you can fake a reset by
|
||||
* destroying the perfmon and creating a new one.
|
||||
*/
|
||||
u64 counters[0];
|
||||
u64 counters[];
|
||||
};
|
||||
|
||||
struct vc4_dev {
|
||||
|
@ -677,32 +677,41 @@ struct vc4_validated_shader_info {
|
|||
};
|
||||
|
||||
/**
|
||||
* _wait_for - magic (register) wait macro
|
||||
* __wait_for - magic wait macro
|
||||
*
|
||||
* Does the right thing for modeset paths when run under kdgb or similar atomic
|
||||
* contexts. Note that it's important that we check the condition again after
|
||||
* having timed out, since the timeout could be due to preemption or similar and
|
||||
* we've never had a chance to check the condition before the timeout.
|
||||
* Macro to help avoid open coding check/wait/timeout patterns. Note that it's
|
||||
* important that we check the condition again after having timed out, since the
|
||||
* timeout could be due to preemption or similar and we've never had a chance to
|
||||
* check the condition before the timeout.
|
||||
*/
|
||||
#define _wait_for(COND, MS, W) ({ \
|
||||
unsigned long timeout__ = jiffies + msecs_to_jiffies(MS) + 1; \
|
||||
int ret__ = 0; \
|
||||
while (!(COND)) { \
|
||||
if (time_after(jiffies, timeout__)) { \
|
||||
if (!(COND)) \
|
||||
ret__ = -ETIMEDOUT; \
|
||||
#define __wait_for(OP, COND, US, Wmin, Wmax) ({ \
|
||||
const ktime_t end__ = ktime_add_ns(ktime_get_raw(), 1000ll * (US)); \
|
||||
long wait__ = (Wmin); /* recommended min for usleep is 10 us */ \
|
||||
int ret__; \
|
||||
might_sleep(); \
|
||||
for (;;) { \
|
||||
const bool expired__ = ktime_after(ktime_get_raw(), end__); \
|
||||
OP; \
|
||||
/* Guarantee COND check prior to timeout */ \
|
||||
barrier(); \
|
||||
if (COND) { \
|
||||
ret__ = 0; \
|
||||
break; \
|
||||
} \
|
||||
if (W && drm_can_sleep()) { \
|
||||
msleep(W); \
|
||||
} else { \
|
||||
cpu_relax(); \
|
||||
if (expired__) { \
|
||||
ret__ = -ETIMEDOUT; \
|
||||
break; \
|
||||
} \
|
||||
usleep_range(wait__, wait__ * 2); \
|
||||
if (wait__ < (Wmax)) \
|
||||
wait__ <<= 1; \
|
||||
} \
|
||||
ret__; \
|
||||
})
|
||||
|
||||
#define wait_for(COND, MS) _wait_for(COND, MS, 1)
|
||||
#define _wait_for(COND, US, Wmin, Wmax) __wait_for(, (COND), (US), (Wmin), \
|
||||
(Wmax))
|
||||
#define wait_for(COND, MS) _wait_for((COND), (MS) * 1000, 10, 1000)
|
||||
|
||||
/* vc4_bo.c */
|
||||
struct drm_gem_object *vc4_create_object(struct drm_device *dev, size_t size);
|
||||
|
|
|
@ -69,16 +69,21 @@ struct virtio_gpu_object_params {
|
|||
struct virtio_gpu_object {
|
||||
struct drm_gem_shmem_object base;
|
||||
uint32_t hw_res_handle;
|
||||
|
||||
struct sg_table *pages;
|
||||
uint32_t mapped;
|
||||
|
||||
bool dumb;
|
||||
bool created;
|
||||
};
|
||||
#define gem_to_virtio_gpu_obj(gobj) \
|
||||
container_of((gobj), struct virtio_gpu_object, base.base)
|
||||
|
||||
struct virtio_gpu_object_shmem {
|
||||
struct virtio_gpu_object base;
|
||||
struct sg_table *pages;
|
||||
uint32_t mapped;
|
||||
};
|
||||
|
||||
#define to_virtio_gpu_shmem(virtio_gpu_object) \
|
||||
container_of((virtio_gpu_object), struct virtio_gpu_object_shmem, base)
|
||||
|
||||
struct virtio_gpu_object_array {
|
||||
struct ww_acquire_ctx ticket;
|
||||
struct list_head next;
|
||||
|
@ -366,7 +371,7 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev,
|
|||
struct virtio_gpu_object **bo_ptr,
|
||||
struct virtio_gpu_fence *fence);
|
||||
|
||||
bool virtio_gpu_is_shmem(struct drm_gem_object *obj);
|
||||
bool virtio_gpu_is_shmem(struct virtio_gpu_object *bo);
|
||||
|
||||
/* virtgpu_prime.c */
|
||||
struct drm_gem_object *virtgpu_gem_prime_import_sg_table(
|
||||
|
|
|
@ -66,19 +66,25 @@ void virtio_gpu_cleanup_object(struct virtio_gpu_object *bo)
|
|||
{
|
||||
struct virtio_gpu_device *vgdev = bo->base.base.dev->dev_private;
|
||||
|
||||
if (bo->pages) {
|
||||
if (bo->mapped) {
|
||||
dma_unmap_sg(vgdev->vdev->dev.parent,
|
||||
bo->pages->sgl, bo->mapped,
|
||||
DMA_TO_DEVICE);
|
||||
bo->mapped = 0;
|
||||
}
|
||||
sg_free_table(bo->pages);
|
||||
bo->pages = NULL;
|
||||
drm_gem_shmem_unpin(&bo->base.base);
|
||||
}
|
||||
virtio_gpu_resource_id_put(vgdev, bo->hw_res_handle);
|
||||
drm_gem_shmem_free_object(&bo->base.base);
|
||||
if (virtio_gpu_is_shmem(bo)) {
|
||||
struct virtio_gpu_object_shmem *shmem = to_virtio_gpu_shmem(bo);
|
||||
|
||||
if (shmem->pages) {
|
||||
if (shmem->mapped) {
|
||||
dma_unmap_sg(vgdev->vdev->dev.parent,
|
||||
shmem->pages->sgl, shmem->mapped,
|
||||
DMA_TO_DEVICE);
|
||||
shmem->mapped = 0;
|
||||
}
|
||||
|
||||
sg_free_table(shmem->pages);
|
||||
shmem->pages = NULL;
|
||||
drm_gem_shmem_unpin(&bo->base.base);
|
||||
}
|
||||
|
||||
drm_gem_shmem_free_object(&bo->base.base);
|
||||
}
|
||||
}
|
||||
|
||||
static void virtio_gpu_free_object(struct drm_gem_object *obj)
|
||||
|
@ -109,9 +115,9 @@ static const struct drm_gem_object_funcs virtio_gpu_shmem_funcs = {
|
|||
.mmap = drm_gem_shmem_mmap,
|
||||
};
|
||||
|
||||
bool virtio_gpu_is_shmem(struct drm_gem_object *obj)
|
||||
bool virtio_gpu_is_shmem(struct virtio_gpu_object *bo)
|
||||
{
|
||||
return obj->funcs == &virtio_gpu_shmem_funcs;
|
||||
return bo->base.base.funcs == &virtio_gpu_shmem_funcs;
|
||||
}
|
||||
|
||||
struct drm_gem_object *virtio_gpu_create_object(struct drm_device *dev,
|
||||
|
@ -134,6 +140,7 @@ static int virtio_gpu_object_shmem_init(struct virtio_gpu_device *vgdev,
|
|||
unsigned int *nents)
|
||||
{
|
||||
bool use_dma_api = !virtio_has_iommu_quirk(vgdev->vdev);
|
||||
struct virtio_gpu_object_shmem *shmem = to_virtio_gpu_shmem(bo);
|
||||
struct scatterlist *sg;
|
||||
int si, ret;
|
||||
|
||||
|
@ -141,19 +148,20 @@ static int virtio_gpu_object_shmem_init(struct virtio_gpu_device *vgdev,
|
|||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
bo->pages = drm_gem_shmem_get_sg_table(&bo->base.base);
|
||||
if (!bo->pages) {
|
||||
shmem->pages = drm_gem_shmem_get_sg_table(&bo->base.base);
|
||||
if (!shmem->pages) {
|
||||
drm_gem_shmem_unpin(&bo->base.base);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (use_dma_api) {
|
||||
bo->mapped = dma_map_sg(vgdev->vdev->dev.parent,
|
||||
bo->pages->sgl, bo->pages->nents,
|
||||
DMA_TO_DEVICE);
|
||||
*nents = bo->mapped;
|
||||
shmem->mapped = dma_map_sg(vgdev->vdev->dev.parent,
|
||||
shmem->pages->sgl,
|
||||
shmem->pages->nents,
|
||||
DMA_TO_DEVICE);
|
||||
*nents = shmem->mapped;
|
||||
} else {
|
||||
*nents = bo->pages->nents;
|
||||
*nents = shmem->pages->nents;
|
||||
}
|
||||
|
||||
*ents = kmalloc_array(*nents, sizeof(struct virtio_gpu_mem_entry),
|
||||
|
@ -163,7 +171,7 @@ static int virtio_gpu_object_shmem_init(struct virtio_gpu_device *vgdev,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for_each_sg(bo->pages->sgl, sg, *nents, si) {
|
||||
for_each_sg(shmem->pages->sgl, sg, *nents, si) {
|
||||
(*ents)[si].addr = cpu_to_le64(use_dma_api
|
||||
? sg_dma_address(sg)
|
||||
: sg_phys(sg));
|
||||
|
|
|
@ -600,10 +600,11 @@ void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev,
|
|||
struct virtio_gpu_transfer_to_host_2d *cmd_p;
|
||||
struct virtio_gpu_vbuffer *vbuf;
|
||||
bool use_dma_api = !virtio_has_iommu_quirk(vgdev->vdev);
|
||||
struct virtio_gpu_object_shmem *shmem = to_virtio_gpu_shmem(bo);
|
||||
|
||||
if (use_dma_api)
|
||||
dma_sync_sg_for_device(vgdev->vdev->dev.parent,
|
||||
bo->pages->sgl, bo->pages->nents,
|
||||
shmem->pages->sgl, shmem->pages->nents,
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
|
||||
|
@ -1015,10 +1016,11 @@ void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev,
|
|||
struct virtio_gpu_transfer_host_3d *cmd_p;
|
||||
struct virtio_gpu_vbuffer *vbuf;
|
||||
bool use_dma_api = !virtio_has_iommu_quirk(vgdev->vdev);
|
||||
struct virtio_gpu_object_shmem *shmem = to_virtio_gpu_shmem(bo);
|
||||
|
||||
if (use_dma_api)
|
||||
dma_sync_sg_for_device(vgdev->vdev->dev.parent,
|
||||
bo->pages->sgl, bo->pages->nents,
|
||||
shmem->pages->sgl, shmem->pages->nents,
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
|
||||
|
|
|
@ -435,7 +435,7 @@ config FB_FM2
|
|||
|
||||
config FB_ARC
|
||||
tristate "Arc Monochrome LCD board support"
|
||||
depends on FB && X86
|
||||
depends on FB && (X86 || COMPILE_TEST)
|
||||
select FB_SYS_FILLRECT
|
||||
select FB_SYS_COPYAREA
|
||||
select FB_SYS_IMAGEBLIT
|
||||
|
@ -1639,7 +1639,7 @@ config FB_VT8500
|
|||
|
||||
config FB_WM8505
|
||||
bool "Wondermedia WM8xxx-series frame buffer support"
|
||||
depends on (FB = y) && ARM && ARCH_VT8500
|
||||
depends on (FB = y) && HAS_IOMEM && (ARCH_VT8500 || COMPILE_TEST)
|
||||
select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS)
|
||||
select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS)
|
||||
select FB_SYS_IMAGEBLIT
|
||||
|
@ -1827,7 +1827,7 @@ config FB_FSL_DIU
|
|||
|
||||
config FB_W100
|
||||
tristate "W100 frame buffer support"
|
||||
depends on FB && ARCH_PXA
|
||||
depends on FB && HAS_IOMEM && (ARCH_PXA || COMPILE_TEST)
|
||||
select FB_CFB_FILLRECT
|
||||
select FB_CFB_COPYAREA
|
||||
select FB_CFB_IMAGEBLIT
|
||||
|
@ -1844,7 +1844,8 @@ config FB_W100
|
|||
|
||||
config FB_SH_MOBILE_LCDC
|
||||
tristate "SuperH Mobile LCDC framebuffer support"
|
||||
depends on FB && (SUPERH || ARCH_RENESAS) && HAVE_CLK
|
||||
depends on FB && HAVE_CLK && HAS_IOMEM
|
||||
depends on SUPERH || ARCH_RENESAS || COMPILE_TEST
|
||||
select FB_SYS_FILLRECT
|
||||
select FB_SYS_COPYAREA
|
||||
select FB_SYS_IMAGEBLIT
|
||||
|
|
|
@ -618,14 +618,13 @@ static int aty_var_to_pll_8398(const struct fb_info *info, u32 vclk_per,
|
|||
u32 mhz100; /* in 0.01 MHz */
|
||||
u32 program_bits;
|
||||
/* u32 post_divider; */
|
||||
u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
|
||||
u32 mach64MinFreq, mach64MaxFreq;
|
||||
u16 m, n, k = 0, save_m, save_n, twoToKth;
|
||||
|
||||
/* Calculate the programming word */
|
||||
mhz100 = 100000000 / vclk_per;
|
||||
mach64MinFreq = MIN_FREQ_2595;
|
||||
mach64MaxFreq = MAX_FREQ_2595;
|
||||
mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */
|
||||
|
||||
save_m = 0;
|
||||
save_n = 0;
|
||||
|
|
|
@ -849,12 +849,6 @@ static int radeonfb_check_var (struct fb_var_screeninfo *var, struct fb_info *in
|
|||
case 9 ... 16:
|
||||
v.bits_per_pixel = 16;
|
||||
break;
|
||||
case 17 ... 24:
|
||||
#if 0 /* Doesn't seem to work */
|
||||
v.bits_per_pixel = 24;
|
||||
break;
|
||||
#endif
|
||||
return -EINVAL;
|
||||
case 25 ... 32:
|
||||
v.bits_per_pixel = 32;
|
||||
break;
|
||||
|
@ -1650,14 +1644,14 @@ static int radeonfb_set_par(struct fb_info *info)
|
|||
struct fb_var_screeninfo *mode = &info->var;
|
||||
struct radeon_regs *newmode;
|
||||
int hTotal, vTotal, hSyncStart, hSyncEnd,
|
||||
hSyncPol, vSyncStart, vSyncEnd, vSyncPol, cSync;
|
||||
vSyncStart, vSyncEnd;
|
||||
u8 hsync_adj_tab[] = {0, 0x12, 9, 9, 6, 5};
|
||||
u8 hsync_fudge_fp[] = {2, 2, 0, 0, 5, 5};
|
||||
u32 sync, h_sync_pol, v_sync_pol, dotClock, pixClock;
|
||||
int i, freq;
|
||||
int format = 0;
|
||||
int nopllcalc = 0;
|
||||
int hsync_start, hsync_fudge, bytpp, hsync_wid, vsync_wid;
|
||||
int hsync_start, hsync_fudge, hsync_wid, vsync_wid;
|
||||
int primary_mon = PRIMARY_MONITOR(rinfo);
|
||||
int depth = var_to_depth(mode);
|
||||
int use_rmx = 0;
|
||||
|
@ -1730,13 +1724,7 @@ static int radeonfb_set_par(struct fb_info *info)
|
|||
else if (vsync_wid > 0x1f) /* max */
|
||||
vsync_wid = 0x1f;
|
||||
|
||||
hSyncPol = mode->sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
|
||||
vSyncPol = mode->sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
|
||||
|
||||
cSync = mode->sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0;
|
||||
|
||||
format = radeon_get_dstbpp(depth);
|
||||
bytpp = mode->bits_per_pixel >> 3;
|
||||
|
||||
if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD))
|
||||
hsync_fudge = hsync_fudge_fp[format-1];
|
||||
|
@ -2548,16 +2536,6 @@ static void radeonfb_pci_unregister(struct pci_dev *pdev)
|
|||
if (rinfo->mon2_EDID)
|
||||
sysfs_remove_bin_file(&rinfo->pdev->dev.kobj, &edid2_attr);
|
||||
|
||||
#if 0
|
||||
/* restore original state
|
||||
*
|
||||
* Doesn't quite work yet, I suspect if we come from a legacy
|
||||
* VGA mode (or worse, text mode), we need to do some VGA black
|
||||
* magic here that I know nothing about. --BenH
|
||||
*/
|
||||
radeon_write_mode (rinfo, &rinfo->init_state, 1);
|
||||
#endif
|
||||
|
||||
del_timer_sync(&rinfo->lvds_timer);
|
||||
arch_phys_wc_del(rinfo->wc_cookie);
|
||||
unregister_framebuffer(info);
|
||||
|
|
|
@ -331,7 +331,7 @@ int SetOverlayViewPort(volatile STG4000REG __iomem *pSTGReg,
|
|||
u32 ulScale;
|
||||
u32 ulLeft, ulRight;
|
||||
u32 ulSrcLeft, ulSrcRight;
|
||||
u32 ulScaleLeft, ulScaleRight;
|
||||
u32 ulScaleLeft;
|
||||
u32 ulhDecim;
|
||||
u32 ulsVal;
|
||||
u32 ulVertDecFactor;
|
||||
|
@ -470,7 +470,6 @@ int SetOverlayViewPort(volatile STG4000REG __iomem *pSTGReg,
|
|||
* round down the pixel pos to the nearest 8 pixels.
|
||||
*/
|
||||
ulScaleLeft = ulSrcLeft;
|
||||
ulScaleRight = ulSrcRight;
|
||||
|
||||
/* shift fxscale until it is in the range of the scaler */
|
||||
ulhDecim = 0;
|
||||
|
|
|
@ -1376,6 +1376,12 @@ static struct video_board vbG200 = {
|
|||
.accelID = FB_ACCEL_MATROX_MGAG200,
|
||||
.lowlevel = &matrox_G100
|
||||
};
|
||||
static struct video_board vbG200eW = {
|
||||
.maxvram = 0x800000,
|
||||
.maxdisplayable = 0x800000,
|
||||
.accelID = FB_ACCEL_MATROX_MGAG200,
|
||||
.lowlevel = &matrox_G100
|
||||
};
|
||||
/* from doc it looks like that accelerator can draw only to low 16MB :-( Direct accesses & displaying are OK for
|
||||
whole 32MB */
|
||||
static struct video_board vbG400 = {
|
||||
|
@ -1494,6 +1500,13 @@ static struct board {
|
|||
MGA_G200,
|
||||
&vbG200,
|
||||
"MGA-G200 (PCI)"},
|
||||
{PCI_VENDOR_ID_MATROX, 0x0532, 0xFF,
|
||||
0, 0,
|
||||
DEVF_G200,
|
||||
250000,
|
||||
MGA_G200,
|
||||
&vbG200eW,
|
||||
"MGA-G200eW (PCI)"},
|
||||
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
|
||||
PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_GENERIC,
|
||||
DEVF_G200,
|
||||
|
@ -2136,6 +2149,8 @@ static const struct pci_device_id matroxfb_devices[] = {
|
|||
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
|
||||
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_PCI,
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
|
||||
{PCI_VENDOR_ID_MATROX, 0x0532,
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
|
||||
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP,
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
|
||||
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400,
|
||||
|
|
|
@ -1406,7 +1406,7 @@ struct mmphw_ctrl {
|
|||
|
||||
/*pathes*/
|
||||
int path_num;
|
||||
struct mmphw_path_plat path_plats[0];
|
||||
struct mmphw_path_plat path_plats[];
|
||||
};
|
||||
|
||||
static inline int overlay_is_vid(struct mmp_overlay *overlay)
|
||||
|
|
|
@ -779,7 +779,6 @@ static int pxa168fb_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct pxa168fb_info *fbi = platform_get_drvdata(pdev);
|
||||
struct fb_info *info;
|
||||
int irq;
|
||||
unsigned int data;
|
||||
|
||||
if (!fbi)
|
||||
|
@ -799,8 +798,6 @@ static int pxa168fb_remove(struct platform_device *pdev)
|
|||
if (info->cmap.len)
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
|
||||
dma_free_wc(fbi->dev, info->fix.smem_len,
|
||||
info->screen_base, info->fix.smem_start);
|
||||
|
||||
|
|
|
@ -1572,7 +1572,7 @@ sh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl)
|
|||
info->flags = FBINFO_FLAG_DEFAULT;
|
||||
info->fbops = &sh_mobile_lcdc_overlay_ops;
|
||||
info->device = priv->dev;
|
||||
info->screen_base = ovl->fb_mem;
|
||||
info->screen_buffer = ovl->fb_mem;
|
||||
info->par = ovl;
|
||||
|
||||
/* Initialize fixed screen information. Restrict pan to 2 lines steps
|
||||
|
@ -2056,7 +2056,7 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
|
|||
info->flags = FBINFO_FLAG_DEFAULT;
|
||||
info->fbops = &sh_mobile_lcdc_ops;
|
||||
info->device = priv->dev;
|
||||
info->screen_base = ch->fb_mem;
|
||||
info->screen_buffer = ch->fb_mem;
|
||||
info->pseudo_palette = &ch->pseudo_palette;
|
||||
info->par = ch;
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ struct ssd1307fb_par {
|
|||
|
||||
struct ssd1307fb_array {
|
||||
u8 type;
|
||||
u8 data[0];
|
||||
u8 data[];
|
||||
};
|
||||
|
||||
static const struct fb_fix_screeninfo ssd1307fb_fix = {
|
||||
|
|
|
@ -61,9 +61,9 @@ struct w100_pll_info *w100_get_xtal_table(unsigned int freq);
|
|||
#define BITS_PER_PIXEL 16
|
||||
|
||||
/* Remapped addresses for base cfg, memmapped regs and the frame buffer itself */
|
||||
static void *remapped_base;
|
||||
static void *remapped_regs;
|
||||
static void *remapped_fbuf;
|
||||
static void __iomem *remapped_base;
|
||||
static void __iomem *remapped_regs;
|
||||
static void __iomem *remapped_fbuf;
|
||||
|
||||
#define REMAPPED_FB_LEN 0x15ffff
|
||||
|
||||
|
@ -635,7 +635,7 @@ static int w100fb_resume(struct platform_device *dev)
|
|||
#endif
|
||||
|
||||
|
||||
int w100fb_probe(struct platform_device *pdev)
|
||||
static int w100fb_probe(struct platform_device *pdev)
|
||||
{
|
||||
int err = -EIO;
|
||||
struct w100fb_mach_info *inf;
|
||||
|
@ -807,10 +807,11 @@ static int w100fb_remove(struct platform_device *pdev)
|
|||
|
||||
static void w100_soft_reset(void)
|
||||
{
|
||||
u16 val = readw((u16 *) remapped_base + cfgSTATUS);
|
||||
writew(val | 0x08, (u16 *) remapped_base + cfgSTATUS);
|
||||
u16 val = readw((u16 __iomem *)remapped_base + cfgSTATUS);
|
||||
|
||||
writew(val | 0x08, (u16 __iomem *)remapped_base + cfgSTATUS);
|
||||
udelay(100);
|
||||
writew(0x00, (u16 *) remapped_base + cfgSTATUS);
|
||||
writew(0x00, (u16 __iomem *)remapped_base + cfgSTATUS);
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
|
@ -1022,7 +1023,8 @@ struct w100_pll_info *w100_get_xtal_table(unsigned int freq)
|
|||
return pll_entry->pll_table;
|
||||
pll_entry++;
|
||||
} while (pll_entry->xtal_freq);
|
||||
return 0;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -339,7 +339,7 @@ static int wm8505fb_probe(struct platform_device *pdev)
|
|||
|
||||
fbi->fb.fix.smem_start = fb_mem_phys;
|
||||
fbi->fb.fix.smem_len = fb_mem_len;
|
||||
fbi->fb.screen_base = fb_mem_virt;
|
||||
fbi->fb.screen_buffer = fb_mem_virt;
|
||||
fbi->fb.screen_size = fb_mem_len;
|
||||
|
||||
fbi->contrast = 0x10;
|
||||
|
|
|
@ -327,13 +327,13 @@ struct mhl_burst_bits_per_pixel_fmt {
|
|||
struct {
|
||||
u8 stream_id;
|
||||
u8 pixel_format;
|
||||
} __packed desc[0];
|
||||
} __packed desc[];
|
||||
} __packed;
|
||||
|
||||
struct mhl_burst_emsc_support {
|
||||
struct mhl3_burst_header hdr;
|
||||
u8 num_entries;
|
||||
__be16 burst_id[0];
|
||||
__be16 burst_id[];
|
||||
} __packed;
|
||||
|
||||
struct mhl_burst_audio_descr {
|
||||
|
|
|
@ -213,8 +213,7 @@ drm_fb_helper_from_client(struct drm_client_dev *client)
|
|||
#ifdef CONFIG_DRM_FBDEV_EMULATION
|
||||
void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
|
||||
const struct drm_fb_helper_funcs *funcs);
|
||||
int drm_fb_helper_init(struct drm_device *dev,
|
||||
struct drm_fb_helper *helper, int max_conn);
|
||||
int drm_fb_helper_init(struct drm_device *dev, struct drm_fb_helper *helper);
|
||||
void drm_fb_helper_fini(struct drm_fb_helper *helper);
|
||||
int drm_fb_helper_blank(int blank, struct fb_info *info);
|
||||
int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
|
||||
|
@ -279,8 +278,7 @@ static inline void drm_fb_helper_prepare(struct drm_device *dev,
|
|||
}
|
||||
|
||||
static inline int drm_fb_helper_init(struct drm_device *dev,
|
||||
struct drm_fb_helper *helper,
|
||||
int max_conn)
|
||||
struct drm_fb_helper *helper)
|
||||
{
|
||||
/* So drivers can use it to free the struct */
|
||||
helper->dev = dev;
|
||||
|
@ -453,27 +451,6 @@ drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
|
|||
|
||||
#endif
|
||||
|
||||
/* TODO: There's a todo entry to remove these three */
|
||||
static inline int
|
||||
drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_fb_helper_remove_conflicting_framebuffers - remove firmware-configured framebuffers
|
||||
* @a: memory range, users of which are to be removed
|
||||
|
|
|
@ -276,7 +276,7 @@ void drm_hdcp_cpu_to_be24(u8 seq_num[HDCP_2_2_SEQ_NUM_LEN], u32 val)
|
|||
#define DRM_HDCP_2_VRL_LENGTH_SIZE 3
|
||||
#define DRM_HDCP_2_DCP_SIG_SIZE 384
|
||||
#define DRM_HDCP_2_NO_OF_DEV_PLUS_RESERVED_SZ 4
|
||||
#define DRM_HDCP_2_KSV_COUNT_2_LSBITS(byte) (((byte) & 0xC) >> 6)
|
||||
#define DRM_HDCP_2_KSV_COUNT_2_LSBITS(byte) (((byte) & 0xC0) >> 6)
|
||||
|
||||
struct hdcp_srm_header {
|
||||
u8 srm_id;
|
||||
|
@ -288,8 +288,8 @@ struct hdcp_srm_header {
|
|||
struct drm_device;
|
||||
struct drm_connector;
|
||||
|
||||
bool drm_hdcp_check_ksvs_revoked(struct drm_device *dev,
|
||||
u8 *ksvs, u32 ksv_count);
|
||||
int drm_hdcp_check_ksvs_revoked(struct drm_device *dev,
|
||||
u8 *ksvs, u32 ksv_count);
|
||||
int drm_connector_attach_content_protection_property(
|
||||
struct drm_connector *connector, bool hdcp_content_type);
|
||||
void drm_hdcp_update_content_protection(struct drm_connector *connector,
|
||||
|
|
|
@ -45,10 +45,6 @@ struct drm_dma_handle *drm_pci_alloc(struct drm_device *dev, size_t size,
|
|||
size_t align);
|
||||
void drm_pci_free(struct drm_device *dev, struct drm_dma_handle * dmah);
|
||||
|
||||
int drm_get_pci_dev(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent,
|
||||
struct drm_driver *driver);
|
||||
|
||||
#else
|
||||
|
||||
static inline struct drm_dma_handle *drm_pci_alloc(struct drm_device *dev,
|
||||
|
@ -62,13 +58,6 @@ static inline void drm_pci_free(struct drm_device *dev,
|
|||
{
|
||||
}
|
||||
|
||||
static inline int drm_get_pci_dev(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent,
|
||||
struct drm_driver *driver)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _DRM_PCI_H_ */
|
||||
|
|
|
@ -181,4 +181,8 @@ int drm_simple_display_pipe_init(struct drm_device *dev,
|
|||
const uint64_t *format_modifiers,
|
||||
struct drm_connector *connector);
|
||||
|
||||
int drm_simple_encoder_init(struct drm_device *dev,
|
||||
struct drm_encoder *encoder,
|
||||
int encoder_type);
|
||||
|
||||
#endif /* __LINUX_DRM_SIMPLE_KMS_HELPER_H */
|
||||
|
|
|
@ -42,18 +42,6 @@ struct dma_buf_ops {
|
|||
*/
|
||||
bool cache_sgt_mapping;
|
||||
|
||||
/**
|
||||
* @dynamic_mapping:
|
||||
*
|
||||
* If true the framework makes sure that the map/unmap_dma_buf
|
||||
* callbacks are always called with the dma_resv object locked.
|
||||
*
|
||||
* If false the framework makes sure that the map/unmap_dma_buf
|
||||
* callbacks are always called without the dma_resv object locked.
|
||||
* Mutual exclusive with @cache_sgt_mapping.
|
||||
*/
|
||||
bool dynamic_mapping;
|
||||
|
||||
/**
|
||||
* @attach:
|
||||
*
|
||||
|
@ -93,14 +81,43 @@ struct dma_buf_ops {
|
|||
*/
|
||||
void (*detach)(struct dma_buf *, struct dma_buf_attachment *);
|
||||
|
||||
/**
|
||||
* @pin:
|
||||
*
|
||||
* This is called by dma_buf_pin and lets the exporter know that the
|
||||
* DMA-buf can't be moved any more.
|
||||
*
|
||||
* This is called with the dmabuf->resv object locked and is mutual
|
||||
* exclusive with @cache_sgt_mapping.
|
||||
*
|
||||
* This callback is optional and should only be used in limited use
|
||||
* cases like scanout and not for temporary pin operations.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* 0 on success, negative error code on failure.
|
||||
*/
|
||||
int (*pin)(struct dma_buf_attachment *attach);
|
||||
|
||||
/**
|
||||
* @unpin:
|
||||
*
|
||||
* This is called by dma_buf_unpin and lets the exporter know that the
|
||||
* DMA-buf can be moved again.
|
||||
*
|
||||
* This is called with the dmabuf->resv object locked and is mutual
|
||||
* exclusive with @cache_sgt_mapping.
|
||||
*
|
||||
* This callback is optional.
|
||||
*/
|
||||
void (*unpin)(struct dma_buf_attachment *attach);
|
||||
|
||||
/**
|
||||
* @map_dma_buf:
|
||||
*
|
||||
* This is called by dma_buf_map_attachment() and is used to map a
|
||||
* shared &dma_buf into device address space, and it is mandatory. It
|
||||
* can only be called if @attach has been called successfully. This
|
||||
* essentially pins the DMA buffer into place, and it cannot be moved
|
||||
* any more
|
||||
* can only be called if @attach has been called successfully.
|
||||
*
|
||||
* This call may sleep, e.g. when the backing storage first needs to be
|
||||
* allocated, or moved to a location suitable for all currently attached
|
||||
|
@ -141,9 +158,8 @@ struct dma_buf_ops {
|
|||
*
|
||||
* This is called by dma_buf_unmap_attachment() and should unmap and
|
||||
* release the &sg_table allocated in @map_dma_buf, and it is mandatory.
|
||||
* It should also unpin the backing storage if this is the last mapping
|
||||
* of the DMA buffer, it the exporter supports backing storage
|
||||
* migration.
|
||||
* For static dma_buf handling this might also unpins the backing
|
||||
* storage if this is the last mapping of the DMA buffer.
|
||||
*/
|
||||
void (*unmap_dma_buf)(struct dma_buf_attachment *,
|
||||
struct sg_table *,
|
||||
|
@ -311,6 +327,34 @@ struct dma_buf {
|
|||
} cb_excl, cb_shared;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dma_buf_attach_ops - importer operations for an attachment
|
||||
* @move_notify: [optional] notification that the DMA-buf is moving
|
||||
*
|
||||
* Attachment operations implemented by the importer.
|
||||
*/
|
||||
struct dma_buf_attach_ops {
|
||||
/**
|
||||
* @move_notify
|
||||
*
|
||||
* If this callback is provided the framework can avoid pinning the
|
||||
* backing store while mappings exists.
|
||||
*
|
||||
* This callback is called with the lock of the reservation object
|
||||
* associated with the dma_buf held and the mapping function must be
|
||||
* called with this lock held as well. This makes sure that no mapping
|
||||
* is created concurrently with an ongoing move operation.
|
||||
*
|
||||
* Mappings stay valid and are not directly affected by this callback.
|
||||
* But the DMA-buf can now be in a different physical location, so all
|
||||
* mappings should be destroyed and re-created as soon as possible.
|
||||
*
|
||||
* New mappings can be created after this callback returns, and will
|
||||
* point to the new location of the DMA-buf.
|
||||
*/
|
||||
void (*move_notify)(struct dma_buf_attachment *attach);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dma_buf_attachment - holds device-buffer attachment data
|
||||
* @dmabuf: buffer for this attachment.
|
||||
|
@ -319,8 +363,9 @@ struct dma_buf {
|
|||
* @sgt: cached mapping.
|
||||
* @dir: direction of cached mapping.
|
||||
* @priv: exporter specific attachment data.
|
||||
* @dynamic_mapping: true if dma_buf_map/unmap_attachment() is called with the
|
||||
* dma_resv lock held.
|
||||
* @importer_ops: importer operations for this attachment, if provided
|
||||
* dma_buf_map/unmap_attachment() must be called with the dma_resv lock held.
|
||||
* @importer_priv: importer specific attachment data.
|
||||
*
|
||||
* This structure holds the attachment information between the dma_buf buffer
|
||||
* and its user device(s). The list contains one attachment struct per device
|
||||
|
@ -337,7 +382,8 @@ struct dma_buf_attachment {
|
|||
struct list_head node;
|
||||
struct sg_table *sgt;
|
||||
enum dma_data_direction dir;
|
||||
bool dynamic_mapping;
|
||||
const struct dma_buf_attach_ops *importer_ops;
|
||||
void *importer_priv;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
|
@ -399,7 +445,7 @@ static inline void get_dma_buf(struct dma_buf *dmabuf)
|
|||
*/
|
||||
static inline bool dma_buf_is_dynamic(struct dma_buf *dmabuf)
|
||||
{
|
||||
return dmabuf->ops->dynamic_mapping;
|
||||
return !!dmabuf->ops->pin;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -413,16 +459,19 @@ static inline bool dma_buf_is_dynamic(struct dma_buf *dmabuf)
|
|||
static inline bool
|
||||
dma_buf_attachment_is_dynamic(struct dma_buf_attachment *attach)
|
||||
{
|
||||
return attach->dynamic_mapping;
|
||||
return !!attach->importer_ops;
|
||||
}
|
||||
|
||||
struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
|
||||
struct device *dev);
|
||||
struct dma_buf_attachment *
|
||||
dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
|
||||
bool dynamic_mapping);
|
||||
const struct dma_buf_attach_ops *importer_ops,
|
||||
void *importer_priv);
|
||||
void dma_buf_detach(struct dma_buf *dmabuf,
|
||||
struct dma_buf_attachment *attach);
|
||||
int dma_buf_pin(struct dma_buf_attachment *attach);
|
||||
void dma_buf_unpin(struct dma_buf_attachment *attach);
|
||||
|
||||
struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info);
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/* format array, use it to initialize a "struct simplefb_format" array */
|
||||
#define SIMPLEFB_FORMATS \
|
||||
|
|
|
@ -231,7 +231,7 @@ struct mmp_path {
|
|||
|
||||
/* layers */
|
||||
int overlay_num;
|
||||
struct mmp_overlay overlays[0];
|
||||
struct mmp_overlay overlays[];
|
||||
};
|
||||
|
||||
extern struct mmp_path *mmp_get_path(const char *name);
|
||||
|
|
Loading…
Reference in New Issue