mirror of
https://github.com/torvalds/linux.git
synced 2026-05-26 16:12:59 +02:00
drm-misc-next for v7.1:
UAPI Changes: amdxdna: - Add sensors ioctls Cross-subsystem Changes: dma-buf: - clean pages with helpers Documenatation: - devicetree: Add lxd vendor prefix Core Changes: buddy: - improve aligned allocations gem-shmem: - Track page accessed/dirty status across mmap/vmap ttm: - fix fence signalling Driver Changes: amdxdna: - provide NPU power estimate - support sensor for column utilization bridge: - anx7625: Fix USB Type-C handling - cdns-mhdp8546-core: Handle HDCP state in bridge atomic_check ivpu: - fixes loongson: - replace custom code with drm_gem_ttm_dumb_map_offset() mxsfb: - lcdif: report probing errors with dev_err_probe() panel: - ilitek-ili9882t: Allow GPIO calls to sleep - jadard: Support TAIGUAN XTI05101-01A - lxd: Support LXD M9189A plus DT bindings - mantix: Fix pixel clock; Clean up - motorola: Support Motorola Atrix 4G and Droid X2 plus DT bindings - novatek: Support Novatek/Tianma NT37700F plus DT bindings - renesas: Clean up - simple: Support EDT ET057023UDBA plus DT bindings; Support Powertip PH800480T032-ZHC19 plus DT bindings; Support Waveshare 13.3" - clean up DT bindings of various drivers panthor: - fix fence handling vc4: - check return value of platform_get_irq_byname() -----BEGIN PGP SIGNATURE----- iQFPBAABCgA5FiEEchf7rIzpz2NEoWjlaA3BHVMLeiMFAmmycX0bFIAAAAAABAAO bWFudTIsMi41KzEuMTIsMiwyAAoJEGgNwR1TC3ojt1cH/1OoLz0cc0wZ0VM/f8t/ Ha81Ff4mVOS5j2x3V0m+SZrljKl4qgfTka6CYfhHn9aqVS27pkB2My4vtq6h3EXQ apfKIqhgMjVpJxin9fbSb29JGt+/NtuUEFbq+s356SF2L5RZ8fGEWmdETsNfItvj lLZOkvys/9MWRyCjO4pOD6kyJul2Bg+79hJ1H3IdE62WNyVM1FNVcMWIBsWdigBG o5wJv+RQ9sffD7zNiw122AI+Zr+elCeXekqMZghIP8Su+JkjfEMsr0AGpsqpvFbJ TsdFR52ZZR4fEzwZZnrn4gTGN3xPSUIpWcSXrOkm7gp5d4ZVE/X9diavrzJFb0vg uM8= =TJlw -----END PGP SIGNATURE----- Merge tag 'drm-misc-next-2026-03-12' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next drm-misc-next for v7.1: UAPI Changes: amdxdna: - Add sensors ioctls Cross-subsystem Changes: dma-buf: - clean pages with helpers Documenatation: - devicetree: Add lxd vendor prefix Core Changes: buddy: - improve aligned allocations gem-shmem: - Track page accessed/dirty status across mmap/vmap ttm: - fix fence signalling Driver Changes: amdxdna: - provide NPU power estimate - support sensor for column utilization bridge: - anx7625: Fix USB Type-C handling - cdns-mhdp8546-core: Handle HDCP state in bridge atomic_check ivpu: - fixes loongson: - replace custom code with drm_gem_ttm_dumb_map_offset() mxsfb: - lcdif: report probing errors with dev_err_probe() panel: - ilitek-ili9882t: Allow GPIO calls to sleep - jadard: Support TAIGUAN XTI05101-01A - lxd: Support LXD M9189A plus DT bindings - mantix: Fix pixel clock; Clean up - motorola: Support Motorola Atrix 4G and Droid X2 plus DT bindings - novatek: Support Novatek/Tianma NT37700F plus DT bindings - renesas: Clean up - simple: Support EDT ET057023UDBA plus DT bindings; Support Powertip PH800480T032-ZHC19 plus DT bindings; Support Waveshare 13.3" - clean up DT bindings of various drivers panthor: - fix fence handling vc4: - check return value of platform_get_irq_byname() Signed-off-by: Dave Airlie <airlied@redhat.com> From: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patch.msgid.link/20260312075629.GA21234@linux.fritz.box
This commit is contained in:
commit
d9a4a2021d
|
|
@ -844,6 +844,12 @@ properties:
|
|||
- google,sargo
|
||||
- const: qcom,sdm670
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
- google,bonito-tianma
|
||||
- const: google,bonito
|
||||
- const: qcom,sdm670
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,sdx55-mtp
|
||||
|
|
|
|||
|
|
@ -20,11 +20,6 @@ properties:
|
|||
reg:
|
||||
maxItems: 1
|
||||
|
||||
backlight: true
|
||||
port: true
|
||||
power-supply: true
|
||||
reset-gpios: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
|||
|
|
@ -41,8 +41,6 @@ properties:
|
|||
panel-timing: true
|
||||
port: true
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- data-mapping
|
||||
|
|
@ -51,6 +49,8 @@ required:
|
|||
- panel-timing
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |+
|
||||
panel {
|
||||
|
|
|
|||
|
|
@ -56,8 +56,6 @@ properties:
|
|||
- port@0
|
||||
- port@1
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- width-mm
|
||||
|
|
@ -65,6 +63,8 @@ required:
|
|||
- data-mapping
|
||||
- panel-timing
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |+
|
||||
panel-lvds {
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@ properties:
|
|||
enable-gpios: true
|
||||
port: true
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- power-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
...
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@ properties:
|
|||
backlight: true
|
||||
port: true
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- power-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
...
|
||||
|
|
|
|||
|
|
@ -33,8 +33,6 @@ properties:
|
|||
vsp-supply:
|
||||
description: Negative source voltage rail
|
||||
|
||||
port: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
|||
|
|
@ -54,8 +54,6 @@ required:
|
|||
- vcc-supply
|
||||
- iovcc-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
- if:
|
||||
|
|
@ -68,6 +66,8 @@ allOf:
|
|||
required:
|
||||
- reset-gpios
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
|
|
|||
|
|
@ -34,10 +34,6 @@ properties:
|
|||
maxItems: 1
|
||||
description: Display data/command selection (D/CX)
|
||||
|
||||
backlight: true
|
||||
reset-gpios: true
|
||||
rotation: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
|||
|
|
@ -29,9 +29,6 @@ properties:
|
|||
reg:
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios: true
|
||||
port: true
|
||||
|
||||
vcc-supply:
|
||||
description: Core voltage supply
|
||||
|
||||
|
|
|
|||
|
|
@ -40,8 +40,6 @@ properties:
|
|||
spi-max-frequency:
|
||||
const: 10000000
|
||||
|
||||
port: true
|
||||
|
||||
vci-supply:
|
||||
description: Analog voltage supply (2.5 .. 3.3V)
|
||||
|
||||
|
|
@ -51,8 +49,6 @@ properties:
|
|||
vddi-led-supply:
|
||||
description: Voltage supply for the LED driver (1.65 .. 3.3 V)
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
@ -68,6 +64,8 @@ then:
|
|||
required:
|
||||
- port
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |+
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
|
|
|||
|
|
@ -20,11 +20,6 @@ properties:
|
|||
reg:
|
||||
maxItems: 1
|
||||
|
||||
backlight: true
|
||||
port: true
|
||||
power-supply: true
|
||||
reset-gpios: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ maintainers:
|
|||
- Lin Huang <hl@rock-chips.com>
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
- $ref: panel-common-dual.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -28,6 +28,9 @@ properties:
|
|||
avee-supply:
|
||||
description: The regulator that provides negative voltage
|
||||
|
||||
port: true
|
||||
ports: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
@ -52,6 +55,27 @@ examples:
|
|||
avee-supply = <&avee>;
|
||||
backlight = <&backlight>;
|
||||
enable-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
mipi_in_panel: endpoint {
|
||||
remote-endpoint = <&mipi_out_panel>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
mipi1_in_panel: endpoint {
|
||||
remote-endpoint = <&mipi1_out_panel>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ properties:
|
|||
- melfas,lmfbx101117480
|
||||
- radxa,display-10hd-ad001
|
||||
- radxa,display-8hd-ad002
|
||||
- taiguanck,xti05101-01a
|
||||
- const: jadard,jd9365da-h3
|
||||
|
||||
reg:
|
||||
|
|
@ -35,9 +36,8 @@ properties:
|
|||
description: supply regulator for VCCIO, usually 1.8V
|
||||
|
||||
reset-gpios: true
|
||||
|
||||
backlight: true
|
||||
|
||||
rotation: true
|
||||
port: true
|
||||
|
||||
required:
|
||||
|
|
|
|||
|
|
@ -20,11 +20,6 @@ properties:
|
|||
reg:
|
||||
maxItems: 1
|
||||
|
||||
backlight: true
|
||||
port: true
|
||||
power-supply: true
|
||||
reset-gpios: true
|
||||
|
||||
spi-3wire: true
|
||||
|
||||
required:
|
||||
|
|
|
|||
|
|
@ -20,10 +20,6 @@ properties:
|
|||
reg:
|
||||
maxItems: 1
|
||||
|
||||
label: true
|
||||
enable-gpios: true
|
||||
port: true
|
||||
|
||||
spi-cpha: true
|
||||
spi-cpol: true
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/lxd,m9189a.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: LXD M9189A DSI Display Panel
|
||||
|
||||
maintainers:
|
||||
- Michael Tretter <m.tretter@pengutronix.de>
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: lxd,m9189a
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
standby-gpios:
|
||||
description: GPIO used for the standby pin
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios: true
|
||||
power-supply: true
|
||||
backlight: true
|
||||
port: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- standby-gpios
|
||||
- reset-gpios
|
||||
- power-supply
|
||||
- backlight
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
dsi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
panel@0 {
|
||||
compatible = "lxd,m9189a";
|
||||
reg = <0>;
|
||||
backlight = <&backlight>;
|
||||
reset-gpios = <&gpio3 25 GPIO_ACTIVE_LOW>;
|
||||
standby-gpios = <&gpio5 22 GPIO_ACTIVE_LOW>;
|
||||
power-supply = <®_display_3v3>;
|
||||
|
||||
port {
|
||||
mipi_panel_in: endpoint {
|
||||
remote-endpoint = <&mipi_dsi_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -47,8 +47,6 @@ properties:
|
|||
panel-timing: true
|
||||
port: true
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- data-mapping
|
||||
|
|
@ -57,6 +55,8 @@ required:
|
|||
- panel-timing
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |+
|
||||
|
||||
|
|
|
|||
|
|
@ -44,8 +44,6 @@ properties:
|
|||
panel-timing: true
|
||||
port: true
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- vcc-supply
|
||||
|
|
@ -55,6 +53,8 @@ required:
|
|||
- panel-timing
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |+
|
||||
panel {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/motorola,mot-panel.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Atrix 4G and Droid X2 DSI Display Panel
|
||||
|
||||
maintainers:
|
||||
- Svyatoslav Ryhel <clamor95@gmail.com>
|
||||
|
||||
description:
|
||||
Atrix 4G and Droid X2 use the same 540x960 DSI video mode panel. Exact
|
||||
panel vendor and model are unknown hence generic compatible based on the
|
||||
board name "Mot" is used.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- const: motorola,mot-panel
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply:
|
||||
description: Regulator for main power supply.
|
||||
|
||||
vddio-supply:
|
||||
description: Regulator for 1.8V IO power supply.
|
||||
|
||||
backlight: true
|
||||
reset-gpios: true
|
||||
port: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
dsi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
panel@0 {
|
||||
compatible = "motorola,mot-panel";
|
||||
reg = <0>;
|
||||
|
||||
reset-gpios = <&gpio 35 GPIO_ACTIVE_LOW>;
|
||||
|
||||
vdd-supply = <&vdd_5v0_panel>;
|
||||
vddio-supply = <&vdd_1v8_vio>;
|
||||
|
||||
backlight = <&backlight>;
|
||||
|
||||
port {
|
||||
panel_in: endpoint {
|
||||
remote-endpoint = <&dsi_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -24,10 +24,6 @@ properties:
|
|||
reg:
|
||||
maxItems: 1
|
||||
|
||||
label: true
|
||||
port: true
|
||||
reset-gpios: true
|
||||
|
||||
spi-max-frequency:
|
||||
maximum: 10000000
|
||||
|
||||
|
|
|
|||
|
|
@ -37,9 +37,6 @@ properties:
|
|||
vddio-supply:
|
||||
description: regulator that supplies the I/O voltage
|
||||
|
||||
rotation: true
|
||||
backlight: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
|||
|
|
@ -47,9 +47,6 @@ properties:
|
|||
vddneg-supply:
|
||||
description: phandle of the negative boost supply regulator
|
||||
|
||||
port: true
|
||||
backlight: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
|||
|
|
@ -31,12 +31,12 @@ properties:
|
|||
reset-gpios:
|
||||
maxItems: 1
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
dsi {
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ properties:
|
|||
- lg,lh500wx1-sd03
|
||||
# Lincoln LCD197 5" 1080x1920 LCD panel
|
||||
- lincolntech,lcd197
|
||||
# Novatek NT37700F 1080x2160 AMOLED panel
|
||||
- novatek,nt37700f
|
||||
# One Stop Displays OSD101T2587-53TS 10.1" 1920x1200 panel
|
||||
- osddisplays,osd101t2587-53ts
|
||||
# Panasonic 10" WUXGA TFT LCD panel
|
||||
|
|
|
|||
|
|
@ -103,6 +103,8 @@ properties:
|
|||
- dlc,dlc1010gig
|
||||
# Emerging Display Technology Corp. 3.5" QVGA TFT LCD panel
|
||||
- edt,et035012dm6
|
||||
# Emerging Display Technology Corp. 5.7" 24-bit VGA TFT LCD panel
|
||||
- edt,et057023udba
|
||||
# Emerging Display Technology Corp. 5.7" VGA TFT LCD panel
|
||||
- edt,et057090dhu
|
||||
- edt,et070080dh6
|
||||
|
|
@ -266,6 +268,8 @@ properties:
|
|||
- powertip,ph128800t006-zhc01
|
||||
# POWERTIP PH800480T013-IDF2 7.0" WVGA TFT LCD panel
|
||||
- powertip,ph800480t013-idf02
|
||||
# POWERTIP PH800480T032-ZHC19 7.0" WVGA TFT LCD panel
|
||||
- powertip,ph800480t032-zhc19
|
||||
# PrimeView PM070WL4 7.0" 800x480 TFT LCD panel
|
||||
- primeview,pm070wl4
|
||||
# QiaoDian XianShi Corporation 4"3 TFT LCD panel
|
||||
|
|
|
|||
|
|
@ -21,11 +21,11 @@ properties:
|
|||
backlight: true
|
||||
port: true
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- power-supply
|
||||
- backlight
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
...
|
||||
|
|
|
|||
|
|
@ -33,13 +33,13 @@ properties:
|
|||
reset-gpios:
|
||||
maxItems: 1
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- power-supply
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
dsi {
|
||||
|
|
|
|||
|
|
@ -34,8 +34,6 @@ properties:
|
|||
vddio-supply:
|
||||
description: I/O voltage rail
|
||||
|
||||
port: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
|||
|
|
@ -43,13 +43,13 @@ properties:
|
|||
no-hpd: true
|
||||
hpd-gpios: true
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- enable-gpios
|
||||
- power-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,rpmh.h>
|
||||
|
|
|
|||
|
|
@ -20,10 +20,6 @@ properties:
|
|||
reg:
|
||||
maxItems: 1
|
||||
|
||||
display-timings: true
|
||||
port: true
|
||||
reset-gpios: true
|
||||
|
||||
vdd3-supply:
|
||||
description: core voltage supply
|
||||
|
||||
|
|
|
|||
|
|
@ -31,8 +31,6 @@ properties:
|
|||
configuration.
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios: true
|
||||
|
||||
vci-supply:
|
||||
description: regulator that supplies the VCI analog voltage
|
||||
usually around 3.0 V
|
||||
|
|
@ -41,8 +39,6 @@ properties:
|
|||
description: regulator that supplies the VCCIO voltage usually
|
||||
around 1.8 V
|
||||
|
||||
backlight: true
|
||||
|
||||
spi-cpha: true
|
||||
|
||||
spi-cpol: true
|
||||
|
|
@ -50,8 +46,6 @@ properties:
|
|||
spi-max-frequency:
|
||||
maximum: 1200000
|
||||
|
||||
port: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
|||
|
|
@ -23,8 +23,6 @@ properties:
|
|||
reg:
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios: true
|
||||
|
||||
vci-supply:
|
||||
description: regulator that supplies the VCI analog voltage
|
||||
usually around 3.0 V
|
||||
|
|
@ -33,8 +31,6 @@ properties:
|
|||
description: regulator that supplies the VCCIO voltage usually
|
||||
around 1.8 V
|
||||
|
||||
backlight: true
|
||||
|
||||
spi-cpha: true
|
||||
|
||||
spi-cpol: true
|
||||
|
|
@ -44,8 +40,6 @@ properties:
|
|||
maximum 300 ns minimum cycle which gives around 3 MHz max frequency
|
||||
maximum: 3000000
|
||||
|
||||
port: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@ properties:
|
|||
configuration.
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios: true
|
||||
|
||||
vci-supply:
|
||||
description: regulator that supplies the VCI analog voltage
|
||||
usually around 3.0 V
|
||||
|
|
@ -40,8 +38,6 @@ properties:
|
|||
description: regulator that supplies the VCCIO voltage usually
|
||||
around 1.8 V
|
||||
|
||||
backlight: true
|
||||
|
||||
spi-cpha: true
|
||||
|
||||
spi-cpol: true
|
||||
|
|
@ -49,8 +45,6 @@ properties:
|
|||
spi-max-frequency:
|
||||
maximum: 1200000
|
||||
|
||||
port: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@ properties:
|
|||
vmipi-supply:
|
||||
description: VMIPI supply, usually 1.8v.
|
||||
|
||||
port: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
@ -65,6 +67,12 @@ examples:
|
|||
power-supply = <&display_3v3_supply>;
|
||||
reset-gpios = <&gpf0 4 GPIO_ACTIVE_LOW>;
|
||||
backlight = <&backlight>;
|
||||
|
||||
port {
|
||||
panel_in: endpoint {
|
||||
remote-endpoint = <&mdss_dsi0_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -22,10 +22,6 @@ properties:
|
|||
reg:
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios: true
|
||||
|
||||
port: true
|
||||
|
||||
vdd3-supply:
|
||||
description: VDD regulator
|
||||
|
||||
|
|
|
|||
|
|
@ -21,8 +21,6 @@ properties:
|
|||
reg:
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios: true
|
||||
port: true
|
||||
default-brightness: true
|
||||
max-brightness: true
|
||||
|
||||
|
|
|
|||
|
|
@ -41,8 +41,6 @@ properties:
|
|||
panel-timing: true
|
||||
port: true
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- port
|
||||
|
|
@ -51,6 +49,8 @@ required:
|
|||
- height-mm
|
||||
- panel-timing
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |+
|
||||
panel {
|
||||
|
|
|
|||
|
|
@ -49,12 +49,6 @@ properties:
|
|||
If not set, the controller is in 3-line SPI mode.
|
||||
Disallowed for DSI.
|
||||
|
||||
port: true
|
||||
reset-gpios: true
|
||||
rotation: true
|
||||
|
||||
backlight: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
|||
|
|
@ -24,12 +24,6 @@ properties:
|
|||
reg:
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios: true
|
||||
power-supply: true
|
||||
backlight: true
|
||||
port: true
|
||||
rotation: true
|
||||
|
||||
spi-cpha: true
|
||||
spi-cpol: true
|
||||
|
||||
|
|
|
|||
|
|
@ -20,10 +20,6 @@ properties:
|
|||
reg:
|
||||
maxItems: 1
|
||||
|
||||
label: true
|
||||
reset-gpios: true
|
||||
port: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- port
|
||||
|
|
|
|||
|
|
@ -31,8 +31,6 @@ properties:
|
|||
|
||||
power-supply: true
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- enable-gpios
|
||||
|
|
@ -42,6 +40,8 @@ required:
|
|||
- port
|
||||
- power-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
|
|
|||
|
|
@ -25,11 +25,6 @@ properties:
|
|||
reg:
|
||||
maxItems: 1
|
||||
|
||||
label: true
|
||||
reset-gpios: true
|
||||
backlight: true
|
||||
port: true
|
||||
|
||||
spi-cpha: true
|
||||
spi-cpol: true
|
||||
|
||||
|
|
|
|||
|
|
@ -25,8 +25,6 @@ properties:
|
|||
port: true
|
||||
reset-gpios: true
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
@ -35,6 +33,8 @@ required:
|
|||
- reset-gpios
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
|
|
|||
|
|
@ -36,8 +36,6 @@ properties:
|
|||
port: true
|
||||
reset-gpios: true
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
@ -46,6 +44,8 @@ required:
|
|||
- reset-gpios
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
dsi {
|
||||
|
|
|
|||
|
|
@ -26,8 +26,6 @@ properties:
|
|||
port: true
|
||||
reset-gpios: true
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
@ -37,6 +35,8 @@ required:
|
|||
- reset-gpios
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
|
|
|||
|
|
@ -973,6 +973,8 @@ patternProperties:
|
|||
description: Liebherr-Werk Nenzing GmbH
|
||||
"^lxa,.*":
|
||||
description: Linux Automation GmbH
|
||||
"^lxd,.*":
|
||||
description: LXD Research & Display, LLC
|
||||
"^m5stack,.*":
|
||||
description: M5Stack
|
||||
"^macnica,.*":
|
||||
|
|
@ -1610,6 +1612,8 @@ patternProperties:
|
|||
"^synopsys,.*":
|
||||
description: Synopsys, Inc. (deprecated, use snps)
|
||||
deprecated: true
|
||||
"^taiguanck,.*":
|
||||
description: Shenzhen Top Group Technology Co., Ltd.
|
||||
"^taos,.*":
|
||||
description: Texas Advanced Optoelectronic Solutions Inc.
|
||||
"^tbs,.*":
|
||||
|
|
|
|||
11
MAINTAINERS
11
MAINTAINERS
|
|
@ -8059,6 +8059,12 @@ F: Documentation/devicetree/bindings/display/lvds.yaml
|
|||
F: Documentation/devicetree/bindings/display/panel/panel-lvds.yaml
|
||||
F: drivers/gpu/drm/panel/panel-lvds.c
|
||||
|
||||
DRM DRIVER FOR LXD M9189A PANELS
|
||||
M: Michael Tretter <m.tretter@pengutronix.de>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/display/panel/lxd,m9189a.yaml
|
||||
F: drivers/gpu/drm/panel/panel-lxd-m9189a.c
|
||||
|
||||
DRM DRIVER FOR MANTIX MLAF057WE51 PANELS
|
||||
M: Guido Günther <agx@sigxcpu.org>
|
||||
R: Purism Kernel Team <kernel@puri.sm>
|
||||
|
|
@ -8916,11 +8922,11 @@ R: Christian Koenig <christian.koenig@amd.com>
|
|||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm_buddy.c
|
||||
F: drivers/gpu/buddy.c
|
||||
F: drivers/gpu/drm/drm_buddy.c
|
||||
F: drivers/gpu/tests/gpu_buddy_test.c
|
||||
F: include/linux/gpu_buddy.h
|
||||
F: include/drm/drm_buddy.h
|
||||
F: include/linux/gpu_buddy.h
|
||||
|
||||
DRM AUTOMATED TESTING
|
||||
M: Helen Koike <helen.fornazier@gmail.com>
|
||||
|
|
@ -12985,7 +12991,6 @@ F: drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c
|
|||
|
||||
INTEL KEEM BAY DRM DRIVER
|
||||
M: Anitha Chrisanthus <anitha.chrisanthus@intel.com>
|
||||
M: Edmund Dea <edmund.j.dea@intel.com>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/display/intel,keembay-display.yaml
|
||||
F: drivers/gpu/drm/kmb/
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <drm/drm_managed.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/gpu_scheduler.h>
|
||||
#include <linux/amd-pmf-io.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/firmware.h>
|
||||
|
|
@ -791,6 +792,55 @@ static int aie2_get_clock_metadata(struct amdxdna_client *client,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int aie2_get_sensors(struct amdxdna_client *client,
|
||||
struct amdxdna_drm_get_info *args)
|
||||
{
|
||||
struct amdxdna_dev_hdl *ndev = client->xdna->dev_handle;
|
||||
struct amdxdna_drm_query_sensor sensor = {};
|
||||
struct amd_pmf_npu_metrics npu_metrics;
|
||||
u32 sensors_count = 0, i;
|
||||
int ret;
|
||||
|
||||
ret = AIE2_GET_PMF_NPU_METRICS(&npu_metrics);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
sensor.type = AMDXDNA_SENSOR_TYPE_POWER;
|
||||
sensor.input = npu_metrics.npu_power;
|
||||
sensor.unitm = -3;
|
||||
scnprintf(sensor.label, sizeof(sensor.label), "Total Power");
|
||||
scnprintf(sensor.units, sizeof(sensor.units), "mW");
|
||||
|
||||
if (copy_to_user(u64_to_user_ptr(args->buffer), &sensor, sizeof(sensor)))
|
||||
return -EFAULT;
|
||||
|
||||
sensors_count++;
|
||||
if (args->buffer_size <= sensors_count * sizeof(sensor))
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < min_t(u32, ndev->total_col, 8); i++) {
|
||||
memset(&sensor, 0, sizeof(sensor));
|
||||
sensor.input = npu_metrics.npu_busy[i];
|
||||
sensor.type = AMDXDNA_SENSOR_TYPE_COLUMN_UTILIZATION;
|
||||
sensor.unitm = 0;
|
||||
scnprintf(sensor.label, sizeof(sensor.label), "Column %d Utilization", i);
|
||||
scnprintf(sensor.units, sizeof(sensor.units), "%%");
|
||||
|
||||
if (copy_to_user(u64_to_user_ptr(args->buffer) + sensors_count * sizeof(sensor),
|
||||
&sensor, sizeof(sensor)))
|
||||
return -EFAULT;
|
||||
|
||||
sensors_count++;
|
||||
if (args->buffer_size <= sensors_count * sizeof(sensor))
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
args->buffer_size = sensors_count * sizeof(sensor);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aie2_hwctx_status_cb(struct amdxdna_hwctx *hwctx, void *arg)
|
||||
{
|
||||
struct amdxdna_drm_hwctx_entry *tmp __free(kfree) = NULL;
|
||||
|
|
@ -994,6 +1044,9 @@ static int aie2_get_info(struct amdxdna_client *client, struct amdxdna_drm_get_i
|
|||
case DRM_AMDXDNA_QUERY_CLOCK_METADATA:
|
||||
ret = aie2_get_clock_metadata(client, args);
|
||||
break;
|
||||
case DRM_AMDXDNA_QUERY_SENSORS:
|
||||
ret = aie2_get_sensors(client, args);
|
||||
break;
|
||||
case DRM_AMDXDNA_QUERY_HW_CONTEXTS:
|
||||
ret = aie2_get_hwctx_status(client, args);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#define _AIE2_PCI_H_
|
||||
|
||||
#include <drm/amdxdna_accel.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/semaphore.h>
|
||||
|
||||
#include "amdxdna_mailbox.h"
|
||||
|
|
@ -46,6 +47,33 @@
|
|||
pci_resource_len(NDEV2PDEV(_ndev), (_ndev)->xdna->dev_info->mbox_bar); \
|
||||
})
|
||||
|
||||
#if IS_ENABLED(CONFIG_AMD_PMF)
|
||||
#define AIE2_GET_PMF_NPU_METRICS(metrics) amd_pmf_get_npu_data(metrics)
|
||||
#define AIE2_GET_PMF_NPU_DATA(field, val) \
|
||||
({ \
|
||||
struct amd_pmf_npu_metrics _npu_metrics; \
|
||||
int _ret; \
|
||||
\
|
||||
_ret = amd_pmf_get_npu_data(&_npu_metrics); \
|
||||
val = _ret ? U32_MAX : _npu_metrics.field; \
|
||||
(_ret); \
|
||||
})
|
||||
#else
|
||||
#define AIE2_GET_PMF_NPU_METRICS(metrics) \
|
||||
({ \
|
||||
typeof(metrics) _m = metrics; \
|
||||
memset(_m, 0xff, sizeof(*_m)); \
|
||||
(-EOPNOTSUPP); \
|
||||
})
|
||||
|
||||
#define SENSOR_DEFAULT_npu_power U32_MAX
|
||||
#define AIE2_GET_PMF_NPU_DATA(field, val) \
|
||||
({ \
|
||||
val = SENSOR_DEFAULT_##field; \
|
||||
(-EOPNOTSUPP); \
|
||||
})
|
||||
#endif
|
||||
|
||||
enum aie2_smu_reg_idx {
|
||||
SMU_CMD_REG = 0,
|
||||
SMU_ARG_REG,
|
||||
|
|
|
|||
|
|
@ -35,9 +35,10 @@ MODULE_FIRMWARE("amdnpu/17f0_11/npu_7.sbin");
|
|||
* 0.4: Support getting resource information
|
||||
* 0.5: Support getting telemetry data
|
||||
* 0.6: Support preemption
|
||||
* 0.7: Support getting power and utilization data
|
||||
*/
|
||||
#define AMDXDNA_DRIVER_MAJOR 0
|
||||
#define AMDXDNA_DRIVER_MINOR 6
|
||||
#define AMDXDNA_DRIVER_MINOR 7
|
||||
|
||||
/*
|
||||
* Bind the driver base on (vendor_id, device_id) pair and later use the
|
||||
|
|
@ -358,5 +359,6 @@ static struct pci_driver amdxdna_pci_driver = {
|
|||
module_pci_driver(amdxdna_pci_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_IMPORT_NS("AMD_PMF");
|
||||
MODULE_AUTHOR("XRT Team <runtimeca39d@amd.com>");
|
||||
MODULE_DESCRIPTION("amdxdna driver");
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2020-2023 Intel Corporation
|
||||
* Copyright (C) 2020-2026 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/dma-buf.h>
|
||||
|
|
@ -31,7 +31,7 @@ static inline void ivpu_dbg_bo(struct ivpu_device *vdev, struct ivpu_bo *bo, con
|
|||
"%6s: bo %8p size %9zu ctx %d vpu_addr %9llx pages %d sgt %d mmu_mapped %d wc %d imported %d\n",
|
||||
action, bo, ivpu_bo_size(bo), bo->ctx_id, bo->vpu_addr,
|
||||
(bool)bo->base.pages, (bool)bo->base.sgt, bo->mmu_mapped, bo->base.map_wc,
|
||||
(bool)drm_gem_is_imported(&bo->base.base));
|
||||
drm_gem_is_imported(&bo->base.base));
|
||||
}
|
||||
|
||||
static inline int ivpu_bo_lock(struct ivpu_bo *bo)
|
||||
|
|
@ -48,7 +48,7 @@ static struct sg_table *ivpu_bo_map_attachment(struct ivpu_device *vdev, struct
|
|||
{
|
||||
struct sg_table *sgt;
|
||||
|
||||
drm_WARN_ON(&vdev->drm, !bo->base.base.import_attach);
|
||||
drm_WARN_ON(&vdev->drm, !drm_gem_is_imported(&bo->base.base));
|
||||
|
||||
ivpu_bo_lock(bo);
|
||||
|
||||
|
|
@ -81,7 +81,7 @@ int __must_check ivpu_bo_bind(struct ivpu_bo *bo)
|
|||
|
||||
ivpu_dbg_bo(vdev, bo, "bind");
|
||||
|
||||
if (bo->base.base.import_attach)
|
||||
if (drm_gem_is_imported(&bo->base.base))
|
||||
sgt = ivpu_bo_map_attachment(vdev, bo);
|
||||
else
|
||||
sgt = drm_gem_shmem_get_pages_sgt(&bo->base);
|
||||
|
|
@ -157,7 +157,7 @@ static void ivpu_bo_unbind_locked(struct ivpu_bo *bo)
|
|||
}
|
||||
|
||||
if (bo->base.sgt) {
|
||||
if (bo->base.base.import_attach) {
|
||||
if (drm_gem_is_imported(&bo->base.base)) {
|
||||
dma_buf_unmap_attachment(bo->base.base.import_attach,
|
||||
bo->base.sgt, DMA_BIDIRECTIONAL);
|
||||
} else {
|
||||
|
|
@ -195,7 +195,7 @@ struct drm_gem_object *ivpu_gem_create_object(struct drm_device *dev, size_t siz
|
|||
if (size == 0 || !PAGE_ALIGNED(size))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
bo = kzalloc(sizeof(*bo), GFP_KERNEL);
|
||||
bo = kzalloc_obj(*bo);
|
||||
if (!bo)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
|
|
|
|||
|
|
@ -121,12 +121,6 @@
|
|||
#define VPU_50XX_HOST_SS_AON_PWR_ISLAND_STATUS_DLY 0x0003006cu
|
||||
#define VPU_50XX_HOST_SS_AON_PWR_ISLAND_STATUS_DLY_STATUS_DLY_MASK GENMASK(7, 0)
|
||||
|
||||
#define VPU_40XX_HOST_SS_AON_RETENTION0 0x0003000cu
|
||||
#define VPU_40XX_HOST_SS_AON_RETENTION1 0x00030010u
|
||||
#define VPU_40XX_HOST_SS_AON_RETENTION2 0x00030014u
|
||||
#define VPU_40XX_HOST_SS_AON_RETENTION3 0x00030018u
|
||||
#define VPU_40XX_HOST_SS_AON_RETENTION4 0x0003001cu
|
||||
|
||||
#define VPU_40XX_HOST_SS_AON_IDLE_GEN 0x00030200u
|
||||
#define VPU_40XX_HOST_SS_AON_IDLE_GEN_EN_MASK BIT_MASK(0)
|
||||
#define VPU_40XX_HOST_SS_AON_IDLE_GEN_HW_PG_EN_MASK BIT_MASK(1)
|
||||
|
|
|
|||
|
|
@ -931,7 +931,6 @@ static int soc_cpu_boot_40xx(struct ivpu_device *vdev)
|
|||
|
||||
static int soc_cpu_boot_60xx(struct ivpu_device *vdev)
|
||||
{
|
||||
REGV_WR64(VPU_40XX_HOST_SS_AON_RETENTION1, vdev->fw->mem_bp->vpu_addr);
|
||||
soc_cpu_set_entry_point_40xx(vdev, vdev->fw->cold_boot_entry_point);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -329,10 +329,7 @@ static struct dma_buf *cma_heap_allocate(struct dma_heap *heap,
|
|||
struct page *page = cma_pages;
|
||||
|
||||
while (nr_clear_pages > 0) {
|
||||
void *vaddr = kmap_local_page(page);
|
||||
|
||||
clear_page(vaddr);
|
||||
kunmap_local(vaddr);
|
||||
clear_highpage(page);
|
||||
/*
|
||||
* Avoid wasting time zeroing memory if the process
|
||||
* has been killed by SIGKILL.
|
||||
|
|
@ -343,7 +340,7 @@ static struct dma_buf *cma_heap_allocate(struct dma_heap *heap,
|
|||
nr_clear_pages--;
|
||||
}
|
||||
} else {
|
||||
memset(page_address(cma_pages), 0, size);
|
||||
clear_pages(page_address(cma_pages), pagecount);
|
||||
}
|
||||
|
||||
buffer->pages = kmalloc_objs(*buffer->pages, pagecount);
|
||||
|
|
|
|||
|
|
@ -53,6 +53,25 @@ gpu_buddy_block_is_split(struct gpu_buddy_block *block)
|
|||
return gpu_buddy_block_state(block) == GPU_BUDDY_SPLIT;
|
||||
}
|
||||
|
||||
static unsigned int gpu_buddy_block_offset_alignment(struct gpu_buddy_block *block)
|
||||
{
|
||||
u64 offset = gpu_buddy_block_offset(block);
|
||||
|
||||
if (!offset)
|
||||
/*
|
||||
* __ffs64(0) is undefined; offset 0 is maximally aligned, so return
|
||||
* a value greater than any possible alignment.
|
||||
*/
|
||||
return 64 + 1;
|
||||
|
||||
return __ffs64(offset);
|
||||
}
|
||||
|
||||
RB_DECLARE_CALLBACKS_MAX(static, gpu_buddy_augment_cb,
|
||||
struct gpu_buddy_block, rb,
|
||||
unsigned int, subtree_max_alignment,
|
||||
gpu_buddy_block_offset_alignment);
|
||||
|
||||
static struct gpu_buddy_block *gpu_block_alloc(struct gpu_buddy *mm,
|
||||
struct gpu_buddy_block *parent,
|
||||
unsigned int order,
|
||||
|
|
@ -106,26 +125,42 @@ static bool rbtree_is_empty(struct rb_root *root)
|
|||
return RB_EMPTY_ROOT(root);
|
||||
}
|
||||
|
||||
static bool gpu_buddy_block_offset_less(const struct gpu_buddy_block *block,
|
||||
const struct gpu_buddy_block *node)
|
||||
{
|
||||
return gpu_buddy_block_offset(block) < gpu_buddy_block_offset(node);
|
||||
}
|
||||
|
||||
static bool rbtree_block_offset_less(struct rb_node *block,
|
||||
const struct rb_node *node)
|
||||
{
|
||||
return gpu_buddy_block_offset_less(rbtree_get_free_block(block),
|
||||
rbtree_get_free_block(node));
|
||||
}
|
||||
|
||||
static void rbtree_insert(struct gpu_buddy *mm,
|
||||
struct gpu_buddy_block *block,
|
||||
enum gpu_buddy_free_tree tree)
|
||||
{
|
||||
rb_add(&block->rb,
|
||||
&mm->free_trees[tree][gpu_buddy_block_order(block)],
|
||||
rbtree_block_offset_less);
|
||||
struct rb_node **link, *parent = NULL;
|
||||
unsigned int block_alignment, order;
|
||||
struct gpu_buddy_block *node;
|
||||
struct rb_root *root;
|
||||
|
||||
order = gpu_buddy_block_order(block);
|
||||
block_alignment = gpu_buddy_block_offset_alignment(block);
|
||||
|
||||
root = &mm->free_trees[tree][order];
|
||||
link = &root->rb_node;
|
||||
|
||||
while (*link) {
|
||||
parent = *link;
|
||||
node = rbtree_get_free_block(parent);
|
||||
/*
|
||||
* Manual augmentation update during insertion traversal. Required
|
||||
* because rb_insert_augmented() only calls rotate callback during
|
||||
* rotations. This ensures all ancestors on the insertion path have
|
||||
* correct subtree_max_alignment values.
|
||||
*/
|
||||
if (node->subtree_max_alignment < block_alignment)
|
||||
node->subtree_max_alignment = block_alignment;
|
||||
|
||||
if (gpu_buddy_block_offset(block) < gpu_buddy_block_offset(node))
|
||||
link = &parent->rb_left;
|
||||
else
|
||||
link = &parent->rb_right;
|
||||
}
|
||||
|
||||
block->subtree_max_alignment = block_alignment;
|
||||
rb_link_node(&block->rb, parent, link);
|
||||
rb_insert_augmented(&block->rb, root, &gpu_buddy_augment_cb);
|
||||
}
|
||||
|
||||
static void rbtree_remove(struct gpu_buddy *mm,
|
||||
|
|
@ -138,7 +173,7 @@ static void rbtree_remove(struct gpu_buddy *mm,
|
|||
tree = get_block_tree(block);
|
||||
root = &mm->free_trees[tree][order];
|
||||
|
||||
rb_erase(&block->rb, root);
|
||||
rb_erase_augmented(&block->rb, root, &gpu_buddy_augment_cb);
|
||||
RB_CLEAR_NODE(&block->rb);
|
||||
}
|
||||
|
||||
|
|
@ -811,6 +846,127 @@ alloc_from_freetree(struct gpu_buddy *mm,
|
|||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
static bool
|
||||
gpu_buddy_can_offset_align(u64 size, u64 min_block_size)
|
||||
{
|
||||
return size < min_block_size && is_power_of_2(size);
|
||||
}
|
||||
|
||||
static bool gpu_buddy_subtree_can_satisfy(struct rb_node *node,
|
||||
unsigned int alignment)
|
||||
{
|
||||
struct gpu_buddy_block *block;
|
||||
|
||||
block = rbtree_get_free_block(node);
|
||||
return block->subtree_max_alignment >= alignment;
|
||||
}
|
||||
|
||||
static struct gpu_buddy_block *
|
||||
gpu_buddy_find_block_aligned(struct gpu_buddy *mm,
|
||||
enum gpu_buddy_free_tree tree,
|
||||
unsigned int order,
|
||||
unsigned int alignment,
|
||||
unsigned long flags)
|
||||
{
|
||||
struct rb_root *root = &mm->free_trees[tree][order];
|
||||
struct rb_node *rb = root->rb_node;
|
||||
|
||||
while (rb) {
|
||||
struct gpu_buddy_block *block = rbtree_get_free_block(rb);
|
||||
struct rb_node *left_node = rb->rb_left, *right_node = rb->rb_right;
|
||||
|
||||
if (right_node) {
|
||||
if (gpu_buddy_subtree_can_satisfy(right_node, alignment)) {
|
||||
rb = right_node;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (gpu_buddy_block_offset_alignment(block) >= alignment)
|
||||
return block;
|
||||
|
||||
if (left_node) {
|
||||
if (gpu_buddy_subtree_can_satisfy(left_node, alignment)) {
|
||||
rb = left_node;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct gpu_buddy_block *
|
||||
gpu_buddy_offset_aligned_allocation(struct gpu_buddy *mm,
|
||||
u64 size,
|
||||
u64 min_block_size,
|
||||
unsigned long flags)
|
||||
{
|
||||
struct gpu_buddy_block *block = NULL;
|
||||
unsigned int order, tmp, alignment;
|
||||
struct gpu_buddy_block *buddy;
|
||||
enum gpu_buddy_free_tree tree;
|
||||
unsigned long pages;
|
||||
int err;
|
||||
|
||||
alignment = ilog2(min_block_size);
|
||||
pages = size >> ilog2(mm->chunk_size);
|
||||
order = fls(pages) - 1;
|
||||
|
||||
tree = (flags & GPU_BUDDY_CLEAR_ALLOCATION) ?
|
||||
GPU_BUDDY_CLEAR_TREE : GPU_BUDDY_DIRTY_TREE;
|
||||
|
||||
for (tmp = order; tmp <= mm->max_order; ++tmp) {
|
||||
block = gpu_buddy_find_block_aligned(mm, tree, tmp,
|
||||
alignment, flags);
|
||||
if (!block) {
|
||||
tree = (tree == GPU_BUDDY_CLEAR_TREE) ?
|
||||
GPU_BUDDY_DIRTY_TREE : GPU_BUDDY_CLEAR_TREE;
|
||||
block = gpu_buddy_find_block_aligned(mm, tree, tmp,
|
||||
alignment, flags);
|
||||
}
|
||||
|
||||
if (block)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!block)
|
||||
return ERR_PTR(-ENOSPC);
|
||||
|
||||
while (gpu_buddy_block_order(block) > order) {
|
||||
struct gpu_buddy_block *left, *right;
|
||||
|
||||
err = split_block(mm, block);
|
||||
if (unlikely(err))
|
||||
goto err_undo;
|
||||
|
||||
left = block->left;
|
||||
right = block->right;
|
||||
|
||||
if (gpu_buddy_block_offset_alignment(right) >= alignment)
|
||||
block = right;
|
||||
else
|
||||
block = left;
|
||||
}
|
||||
|
||||
return block;
|
||||
|
||||
err_undo:
|
||||
/*
|
||||
* We really don't want to leave around a bunch of split blocks, since
|
||||
* bigger is better, so make sure we merge everything back before we
|
||||
* free the allocated blocks.
|
||||
*/
|
||||
buddy = __get_buddy(block);
|
||||
if (buddy &&
|
||||
(gpu_buddy_block_is_free(block) &&
|
||||
gpu_buddy_block_is_free(buddy)))
|
||||
__gpu_buddy_free(mm, block, false);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
static int __alloc_range(struct gpu_buddy *mm,
|
||||
struct list_head *dfs,
|
||||
u64 start, u64 size,
|
||||
|
|
@ -1080,6 +1236,7 @@ EXPORT_SYMBOL(gpu_buddy_block_trim);
|
|||
static struct gpu_buddy_block *
|
||||
__gpu_buddy_alloc_blocks(struct gpu_buddy *mm,
|
||||
u64 start, u64 end,
|
||||
u64 size, u64 min_block_size,
|
||||
unsigned int order,
|
||||
unsigned long flags)
|
||||
{
|
||||
|
|
@ -1087,6 +1244,11 @@ __gpu_buddy_alloc_blocks(struct gpu_buddy *mm,
|
|||
/* Allocate traversing within the range */
|
||||
return __gpu_buddy_alloc_range_bias(mm, start, end,
|
||||
order, flags);
|
||||
else if (size < min_block_size)
|
||||
/* Allocate from an offset-aligned region without size rounding */
|
||||
return gpu_buddy_offset_aligned_allocation(mm, size,
|
||||
min_block_size,
|
||||
flags);
|
||||
else
|
||||
/* Allocate from freetree */
|
||||
return alloc_from_freetree(mm, order, flags);
|
||||
|
|
@ -1158,8 +1320,11 @@ int gpu_buddy_alloc_blocks(struct gpu_buddy *mm,
|
|||
if (flags & GPU_BUDDY_CONTIGUOUS_ALLOCATION) {
|
||||
size = roundup_pow_of_two(size);
|
||||
min_block_size = size;
|
||||
/* Align size value to min_block_size */
|
||||
} else if (!IS_ALIGNED(size, min_block_size)) {
|
||||
/*
|
||||
* Normalize the requested size to min_block_size for regular allocations.
|
||||
* Offset-aligned allocations intentionally skip size rounding.
|
||||
*/
|
||||
} else if (!gpu_buddy_can_offset_align(size, min_block_size)) {
|
||||
size = round_up(size, min_block_size);
|
||||
}
|
||||
|
||||
|
|
@ -1179,43 +1344,60 @@ int gpu_buddy_alloc_blocks(struct gpu_buddy *mm,
|
|||
do {
|
||||
order = min(order, (unsigned int)fls(pages) - 1);
|
||||
BUG_ON(order > mm->max_order);
|
||||
BUG_ON(order < min_order);
|
||||
/*
|
||||
* Regular allocations must not allocate blocks smaller than min_block_size.
|
||||
* Offset-aligned allocations deliberately bypass this constraint.
|
||||
*/
|
||||
BUG_ON(size >= min_block_size && order < min_order);
|
||||
|
||||
do {
|
||||
unsigned int fallback_order;
|
||||
|
||||
block = __gpu_buddy_alloc_blocks(mm, start,
|
||||
end,
|
||||
size,
|
||||
min_block_size,
|
||||
order,
|
||||
flags);
|
||||
if (!IS_ERR(block))
|
||||
break;
|
||||
|
||||
if (order-- == min_order) {
|
||||
/* Try allocation through force merge method */
|
||||
if (mm->clear_avail &&
|
||||
!__force_merge(mm, start, end, min_order)) {
|
||||
block = __gpu_buddy_alloc_blocks(mm, start,
|
||||
end,
|
||||
min_order,
|
||||
flags);
|
||||
if (!IS_ERR(block)) {
|
||||
order = min_order;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Try contiguous block allocation through
|
||||
* try harder method.
|
||||
*/
|
||||
if (flags & GPU_BUDDY_CONTIGUOUS_ALLOCATION &&
|
||||
!(flags & GPU_BUDDY_RANGE_ALLOCATION))
|
||||
return __alloc_contig_try_harder(mm,
|
||||
original_size,
|
||||
original_min_size,
|
||||
blocks);
|
||||
err = -ENOSPC;
|
||||
goto err_free;
|
||||
if (size < min_block_size) {
|
||||
fallback_order = order;
|
||||
} else if (order == min_order) {
|
||||
fallback_order = min_order;
|
||||
} else {
|
||||
order--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Try allocation through force merge method */
|
||||
if (mm->clear_avail &&
|
||||
!__force_merge(mm, start, end, fallback_order)) {
|
||||
block = __gpu_buddy_alloc_blocks(mm, start,
|
||||
end,
|
||||
size,
|
||||
min_block_size,
|
||||
fallback_order,
|
||||
flags);
|
||||
if (!IS_ERR(block)) {
|
||||
order = fallback_order;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Try contiguous block allocation through
|
||||
* try harder method.
|
||||
*/
|
||||
if (flags & GPU_BUDDY_CONTIGUOUS_ALLOCATION &&
|
||||
!(flags & GPU_BUDDY_RANGE_ALLOCATION))
|
||||
return __alloc_contig_try_harder(mm,
|
||||
original_size,
|
||||
original_min_size,
|
||||
blocks);
|
||||
err = -ENOSPC;
|
||||
goto err_free;
|
||||
} while (1);
|
||||
|
||||
mark_allocated(mm, block);
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@ config DRM_ANALOGIX_ANX7625
|
|||
tristate "Analogix Anx7625 MIPI to DP interface support"
|
||||
depends on DRM
|
||||
depends on OF
|
||||
depends on TYPEC || !TYPEC
|
||||
depends on TYPEC
|
||||
depends on USB_ROLE_SWITCH
|
||||
select DRM_DISPLAY_DP_HELPER
|
||||
select DRM_DISPLAY_HDCP_HELPER
|
||||
select DRM_DISPLAY_HELPER
|
||||
|
|
|
|||
|
|
@ -1363,6 +1363,18 @@ static void anx7625_configure_hpd(struct anx7625_data *ctx)
|
|||
anx7625_hpd_timer_config(ctx);
|
||||
}
|
||||
|
||||
static bool anx7625_need_pd(struct anx7625_data *ctx)
|
||||
{
|
||||
struct fwnode_handle *fwnode;
|
||||
|
||||
fwnode = device_get_named_child_node(ctx->dev, "connector");
|
||||
if (!fwnode)
|
||||
return false;
|
||||
|
||||
fwnode_handle_put(fwnode);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int anx7625_ocm_loading_check(struct anx7625_data *ctx)
|
||||
{
|
||||
int ret;
|
||||
|
|
@ -1378,7 +1390,7 @@ static int anx7625_ocm_loading_check(struct anx7625_data *ctx)
|
|||
if ((ret & FLASH_LOAD_STA_CHK) != FLASH_LOAD_STA_CHK)
|
||||
return -ENODEV;
|
||||
|
||||
if (!ctx->typec_port)
|
||||
if (!anx7625_need_pd(ctx))
|
||||
anx7625_disable_pd_protocol(ctx);
|
||||
anx7625_configure_hpd(ctx);
|
||||
|
||||
|
|
@ -1483,7 +1495,6 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx)
|
|||
DRM_DEV_DEBUG_DRIVER(dev, "Secure OCM version=%02x\n", ret);
|
||||
}
|
||||
|
||||
#if IS_REACHABLE(CONFIG_TYPEC)
|
||||
static u8 anx7625_checksum(u8 *buf, u8 len)
|
||||
{
|
||||
u8 ret = 0;
|
||||
|
|
@ -1567,6 +1578,9 @@ static void anx7625_typec_set_status(struct anx7625_data *ctx,
|
|||
unsigned int intr_status,
|
||||
unsigned int intr_vector)
|
||||
{
|
||||
if (!ctx->typec_port)
|
||||
return;
|
||||
|
||||
if (intr_vector & CC_STATUS)
|
||||
anx7625_typec_set_orientation(ctx);
|
||||
if (intr_vector & DATA_ROLE_STATUS) {
|
||||
|
|
@ -1635,22 +1649,6 @@ static void anx7625_typec_unregister(struct anx7625_data *ctx)
|
|||
usb_role_switch_put(ctx->role_sw);
|
||||
typec_unregister_port(ctx->typec_port);
|
||||
}
|
||||
#else
|
||||
static void anx7625_typec_set_status(struct anx7625_data *ctx,
|
||||
unsigned int intr_status,
|
||||
unsigned int intr_vector)
|
||||
{
|
||||
}
|
||||
|
||||
static int anx7625_typec_register(struct anx7625_data *ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void anx7625_typec_unregister(struct anx7625_data *ctx)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static int anx7625_read_hpd_status_p0(struct anx7625_data *ctx)
|
||||
{
|
||||
|
|
@ -2924,12 +2922,7 @@ static int anx7625_i2c_probe(struct i2c_client *client)
|
|||
}
|
||||
|
||||
if (!platform->pdata.low_power_mode) {
|
||||
struct fwnode_handle *fwnode;
|
||||
|
||||
fwnode = device_get_named_child_node(dev, "connector");
|
||||
if (fwnode)
|
||||
fwnode_handle_put(fwnode);
|
||||
else
|
||||
if (!anx7625_need_pd(platform))
|
||||
anx7625_disable_pd_protocol(platform);
|
||||
|
||||
anx7625_configure_hpd(platform);
|
||||
|
|
|
|||
|
|
@ -739,12 +739,8 @@ static void cdns_mhdp_fw_cb(const struct firmware *fw, void *context)
|
|||
spin_lock(&mhdp->start_lock);
|
||||
bridge_attached = mhdp->bridge_attached;
|
||||
spin_unlock(&mhdp->start_lock);
|
||||
if (bridge_attached) {
|
||||
if (mhdp->connector.dev)
|
||||
drm_kms_helper_hotplug_event(mhdp->bridge.dev);
|
||||
else
|
||||
drm_bridge_hpd_notify(&mhdp->bridge, cdns_mhdp_detect(mhdp));
|
||||
}
|
||||
if (bridge_attached)
|
||||
drm_bridge_hpd_notify(&mhdp->bridge, cdns_mhdp_detect(mhdp));
|
||||
}
|
||||
|
||||
static int cdns_mhdp_load_firmware(struct cdns_mhdp_device *mhdp)
|
||||
|
|
@ -782,7 +778,7 @@ static ssize_t cdns_mhdp_transfer(struct drm_dp_aux *aux,
|
|||
if (!ret)
|
||||
continue;
|
||||
|
||||
dev_err(mhdp->dev,
|
||||
dev_dbg(mhdp->dev,
|
||||
"Failed to write DPCD addr %u\n",
|
||||
msg->address + i);
|
||||
|
||||
|
|
@ -792,7 +788,7 @@ static ssize_t cdns_mhdp_transfer(struct drm_dp_aux *aux,
|
|||
ret = cdns_mhdp_dpcd_read(mhdp, msg->address,
|
||||
msg->buffer, msg->size);
|
||||
if (ret) {
|
||||
dev_err(mhdp->dev,
|
||||
dev_dbg(mhdp->dev,
|
||||
"Failed to read DPCD addr %u\n",
|
||||
msg->address);
|
||||
|
||||
|
|
@ -1444,56 +1440,6 @@ static const struct drm_edid *cdns_mhdp_edid_read(struct cdns_mhdp_device *mhdp,
|
|||
return drm_edid_read_custom(connector, cdns_mhdp_get_edid_block, mhdp);
|
||||
}
|
||||
|
||||
static int cdns_mhdp_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct cdns_mhdp_device *mhdp = connector_to_mhdp(connector);
|
||||
const struct drm_edid *drm_edid;
|
||||
int num_modes;
|
||||
|
||||
if (!mhdp->plugged)
|
||||
return 0;
|
||||
|
||||
drm_edid = cdns_mhdp_edid_read(mhdp, connector);
|
||||
|
||||
drm_edid_connector_update(connector, drm_edid);
|
||||
|
||||
if (!drm_edid) {
|
||||
dev_err(mhdp->dev, "Failed to read EDID\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
num_modes = drm_edid_connector_add_modes(connector);
|
||||
drm_edid_free(drm_edid);
|
||||
|
||||
/*
|
||||
* HACK: Warn about unsupported display formats until we deal
|
||||
* with them correctly.
|
||||
*/
|
||||
if (connector->display_info.color_formats &&
|
||||
!(connector->display_info.color_formats &
|
||||
mhdp->display_fmt.color_format))
|
||||
dev_warn(mhdp->dev,
|
||||
"%s: No supported color_format found (0x%08x)\n",
|
||||
__func__, connector->display_info.color_formats);
|
||||
|
||||
if (connector->display_info.bpc &&
|
||||
connector->display_info.bpc < mhdp->display_fmt.bpc)
|
||||
dev_warn(mhdp->dev, "%s: Display bpc only %d < %d\n",
|
||||
__func__, connector->display_info.bpc,
|
||||
mhdp->display_fmt.bpc);
|
||||
|
||||
return num_modes;
|
||||
}
|
||||
|
||||
static int cdns_mhdp_connector_detect(struct drm_connector *conn,
|
||||
struct drm_modeset_acquire_ctx *ctx,
|
||||
bool force)
|
||||
{
|
||||
struct cdns_mhdp_device *mhdp = connector_to_mhdp(conn);
|
||||
|
||||
return cdns_mhdp_detect(mhdp);
|
||||
}
|
||||
|
||||
static u32 cdns_mhdp_get_bpp(struct cdns_mhdp_display_fmt *fmt)
|
||||
{
|
||||
u32 bpp;
|
||||
|
|
@ -1547,114 +1493,6 @@ bool cdns_mhdp_bandwidth_ok(struct cdns_mhdp_device *mhdp,
|
|||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
enum drm_mode_status cdns_mhdp_mode_valid(struct drm_connector *conn,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
struct cdns_mhdp_device *mhdp = connector_to_mhdp(conn);
|
||||
|
||||
mutex_lock(&mhdp->link_mutex);
|
||||
|
||||
if (!cdns_mhdp_bandwidth_ok(mhdp, mode, mhdp->link.num_lanes,
|
||||
mhdp->link.rate)) {
|
||||
mutex_unlock(&mhdp->link_mutex);
|
||||
return MODE_CLOCK_HIGH;
|
||||
}
|
||||
|
||||
mutex_unlock(&mhdp->link_mutex);
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static int cdns_mhdp_connector_atomic_check(struct drm_connector *conn,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct cdns_mhdp_device *mhdp = connector_to_mhdp(conn);
|
||||
struct drm_connector_state *old_state, *new_state;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
u64 old_cp, new_cp;
|
||||
|
||||
if (!mhdp->hdcp_supported)
|
||||
return 0;
|
||||
|
||||
old_state = drm_atomic_get_old_connector_state(state, conn);
|
||||
new_state = drm_atomic_get_new_connector_state(state, conn);
|
||||
old_cp = old_state->content_protection;
|
||||
new_cp = new_state->content_protection;
|
||||
|
||||
if (old_state->hdcp_content_type != new_state->hdcp_content_type &&
|
||||
new_cp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
|
||||
new_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
|
||||
goto mode_changed;
|
||||
}
|
||||
|
||||
if (!new_state->crtc) {
|
||||
if (old_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED)
|
||||
new_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (old_cp == new_cp ||
|
||||
(old_cp == DRM_MODE_CONTENT_PROTECTION_DESIRED &&
|
||||
new_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED))
|
||||
return 0;
|
||||
|
||||
mode_changed:
|
||||
crtc_state = drm_atomic_get_new_crtc_state(state, new_state->crtc);
|
||||
crtc_state->mode_changed = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_connector_helper_funcs cdns_mhdp_conn_helper_funcs = {
|
||||
.detect_ctx = cdns_mhdp_connector_detect,
|
||||
.get_modes = cdns_mhdp_get_modes,
|
||||
.mode_valid = cdns_mhdp_mode_valid,
|
||||
.atomic_check = cdns_mhdp_connector_atomic_check,
|
||||
};
|
||||
|
||||
static const struct drm_connector_funcs cdns_mhdp_conn_funcs = {
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
.reset = drm_atomic_helper_connector_reset,
|
||||
.destroy = drm_connector_cleanup,
|
||||
};
|
||||
|
||||
static int cdns_mhdp_connector_init(struct cdns_mhdp_device *mhdp)
|
||||
{
|
||||
u32 bus_format = MEDIA_BUS_FMT_RGB121212_1X36;
|
||||
struct drm_connector *conn = &mhdp->connector;
|
||||
struct drm_bridge *bridge = &mhdp->bridge;
|
||||
int ret;
|
||||
|
||||
conn->polled = DRM_CONNECTOR_POLL_HPD;
|
||||
|
||||
ret = drm_connector_init(bridge->dev, conn, &cdns_mhdp_conn_funcs,
|
||||
DRM_MODE_CONNECTOR_DisplayPort);
|
||||
if (ret) {
|
||||
dev_err(mhdp->dev, "Failed to initialize connector with drm\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
drm_connector_helper_add(conn, &cdns_mhdp_conn_helper_funcs);
|
||||
|
||||
ret = drm_display_info_set_bus_formats(&conn->display_info,
|
||||
&bus_format, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = drm_connector_attach_encoder(conn, bridge->encoder);
|
||||
if (ret) {
|
||||
dev_err(mhdp->dev, "Failed to attach connector to encoder\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (mhdp->hdcp_supported)
|
||||
ret = drm_connector_attach_content_protection_property(conn, true);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cdns_mhdp_attach(struct drm_bridge *bridge,
|
||||
struct drm_encoder *encoder,
|
||||
enum drm_bridge_attach_flags flags)
|
||||
|
|
@ -1671,9 +1509,11 @@ static int cdns_mhdp_attach(struct drm_bridge *bridge,
|
|||
return ret;
|
||||
|
||||
if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) {
|
||||
ret = cdns_mhdp_connector_init(mhdp);
|
||||
if (ret)
|
||||
goto aux_unregister;
|
||||
ret = -EINVAL;
|
||||
dev_err(mhdp->dev,
|
||||
"Connector initialisation not supported in bridge_attach %d\n",
|
||||
ret);
|
||||
goto aux_unregister;
|
||||
}
|
||||
|
||||
spin_lock(&mhdp->start_lock);
|
||||
|
|
@ -1915,17 +1755,25 @@ static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge,
|
|||
struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge);
|
||||
struct cdns_mhdp_bridge_state *mhdp_state;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_state *conn_state;
|
||||
struct drm_bridge_state *new_state;
|
||||
const struct drm_display_mode *mode;
|
||||
u32 resp;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
dev_dbg(mhdp->dev, "bridge enable\n");
|
||||
|
||||
mutex_lock(&mhdp->link_mutex);
|
||||
|
||||
mhdp->connector = drm_atomic_get_new_connector_for_encoder(state,
|
||||
bridge->encoder);
|
||||
if (WARN_ON(!mhdp->connector))
|
||||
goto out;
|
||||
|
||||
conn_state = drm_atomic_get_new_connector_state(state, mhdp->connector);
|
||||
if (WARN_ON(!conn_state))
|
||||
goto out;
|
||||
|
||||
if (mhdp->plugged && !mhdp->link_up) {
|
||||
ret = cdns_mhdp_link_up(mhdp);
|
||||
if (ret < 0)
|
||||
|
|
@ -1945,15 +1793,6 @@ static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge,
|
|||
cdns_mhdp_reg_write(mhdp, CDNS_DPTX_CAR,
|
||||
resp | CDNS_VIF_CLK_EN | CDNS_VIF_CLK_RSTN);
|
||||
|
||||
connector = drm_atomic_get_new_connector_for_encoder(state,
|
||||
bridge->encoder);
|
||||
if (WARN_ON(!connector))
|
||||
goto out;
|
||||
|
||||
conn_state = drm_atomic_get_new_connector_state(state, connector);
|
||||
if (WARN_ON(!conn_state))
|
||||
goto out;
|
||||
|
||||
if (mhdp->hdcp_supported &&
|
||||
mhdp->hw_state == MHDP_HW_READY &&
|
||||
conn_state->content_protection ==
|
||||
|
|
@ -2030,6 +1869,7 @@ static void cdns_mhdp_atomic_disable(struct drm_bridge *bridge,
|
|||
if (mhdp->info && mhdp->info->ops && mhdp->info->ops->disable)
|
||||
mhdp->info->ops->disable(mhdp);
|
||||
|
||||
mhdp->connector = NULL;
|
||||
mutex_unlock(&mhdp->link_mutex);
|
||||
}
|
||||
|
||||
|
|
@ -2122,6 +1962,10 @@ static int cdns_mhdp_atomic_check(struct drm_bridge *bridge,
|
|||
{
|
||||
struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge);
|
||||
const struct drm_display_mode *mode = &crtc_state->adjusted_mode;
|
||||
struct drm_connector_state *old_state, *new_state;
|
||||
struct drm_atomic_state *state = crtc_state->state;
|
||||
struct drm_connector *conn = mhdp->connector;
|
||||
u64 old_cp, new_cp;
|
||||
|
||||
mutex_lock(&mhdp->link_mutex);
|
||||
|
||||
|
|
@ -2141,6 +1985,25 @@ static int cdns_mhdp_atomic_check(struct drm_bridge *bridge,
|
|||
if (mhdp->info)
|
||||
bridge_state->input_bus_cfg.flags = *mhdp->info->input_bus_flags;
|
||||
|
||||
if (conn && mhdp->hdcp_supported) {
|
||||
old_state = drm_atomic_get_old_connector_state(state, conn);
|
||||
new_state = drm_atomic_get_new_connector_state(state, conn);
|
||||
old_cp = old_state->content_protection;
|
||||
new_cp = new_state->content_protection;
|
||||
|
||||
if (old_state->hdcp_content_type != new_state->hdcp_content_type &&
|
||||
new_cp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
|
||||
new_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
|
||||
crtc_state = drm_atomic_get_new_crtc_state(state, new_state->crtc);
|
||||
crtc_state->mode_changed = true;
|
||||
}
|
||||
|
||||
if (!new_state->crtc) {
|
||||
if (old_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED)
|
||||
new_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&mhdp->link_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2161,6 +2024,25 @@ static const struct drm_edid *cdns_mhdp_bridge_edid_read(struct drm_bridge *brid
|
|||
return cdns_mhdp_edid_read(mhdp, connector);
|
||||
}
|
||||
|
||||
static enum drm_mode_status
|
||||
cdns_mhdp_bridge_mode_valid(struct drm_bridge *bridge,
|
||||
const struct drm_display_info *info,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge);
|
||||
|
||||
mutex_lock(&mhdp->link_mutex);
|
||||
|
||||
if (!cdns_mhdp_bandwidth_ok(mhdp, mode, mhdp->link.num_lanes,
|
||||
mhdp->link.rate)) {
|
||||
mutex_unlock(&mhdp->link_mutex);
|
||||
return MODE_CLOCK_HIGH;
|
||||
}
|
||||
|
||||
mutex_unlock(&mhdp->link_mutex);
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static const struct drm_bridge_funcs cdns_mhdp_bridge_funcs = {
|
||||
.atomic_enable = cdns_mhdp_atomic_enable,
|
||||
.atomic_disable = cdns_mhdp_atomic_disable,
|
||||
|
|
@ -2175,6 +2057,7 @@ static const struct drm_bridge_funcs cdns_mhdp_bridge_funcs = {
|
|||
.edid_read = cdns_mhdp_bridge_edid_read,
|
||||
.hpd_enable = cdns_mhdp_bridge_hpd_enable,
|
||||
.hpd_disable = cdns_mhdp_bridge_hpd_disable,
|
||||
.mode_valid = cdns_mhdp_bridge_mode_valid,
|
||||
};
|
||||
|
||||
static bool cdns_mhdp_detect_hpd(struct cdns_mhdp_device *mhdp, bool *hpd_pulse)
|
||||
|
|
@ -2296,7 +2179,7 @@ static void cdns_mhdp_modeset_retry_fn(struct work_struct *work)
|
|||
|
||||
mhdp = container_of(work, typeof(*mhdp), modeset_retry_work);
|
||||
|
||||
conn = &mhdp->connector;
|
||||
conn = mhdp->connector;
|
||||
|
||||
/* Grab the locks before changing connector property */
|
||||
mutex_lock(&conn->dev->mode_config.mutex);
|
||||
|
|
@ -2370,17 +2253,9 @@ static void cdns_mhdp_hpd_work(struct work_struct *work)
|
|||
struct cdns_mhdp_device *mhdp = container_of(work,
|
||||
struct cdns_mhdp_device,
|
||||
hpd_work);
|
||||
int ret;
|
||||
cdns_mhdp_update_link_status(mhdp);
|
||||
|
||||
ret = cdns_mhdp_update_link_status(mhdp);
|
||||
if (mhdp->connector.dev) {
|
||||
if (ret < 0)
|
||||
schedule_work(&mhdp->modeset_retry_work);
|
||||
else
|
||||
drm_kms_helper_hotplug_event(mhdp->bridge.dev);
|
||||
} else {
|
||||
drm_bridge_hpd_notify(&mhdp->bridge, cdns_mhdp_detect(mhdp));
|
||||
}
|
||||
drm_bridge_hpd_notify(&mhdp->bridge, cdns_mhdp_detect(mhdp));
|
||||
}
|
||||
|
||||
static int cdns_mhdp_probe(struct platform_device *pdev)
|
||||
|
|
|
|||
|
|
@ -375,7 +375,7 @@ struct cdns_mhdp_device {
|
|||
*/
|
||||
struct mutex link_mutex;
|
||||
|
||||
struct drm_connector connector;
|
||||
struct drm_connector *connector;
|
||||
struct drm_bridge bridge;
|
||||
|
||||
struct cdns_mhdp_link link;
|
||||
|
|
|
|||
|
|
@ -394,7 +394,7 @@ static int _cdns_mhdp_hdcp_disable(struct cdns_mhdp_device *mhdp)
|
|||
int ret;
|
||||
|
||||
dev_dbg(mhdp->dev, "[%s:%d] HDCP is being disabled...\n",
|
||||
mhdp->connector.name, mhdp->connector.base.id);
|
||||
mhdp->connector->name, mhdp->connector->base.id);
|
||||
|
||||
ret = cdns_mhdp_hdcp_set_config(mhdp, 0, false);
|
||||
|
||||
|
|
@ -436,6 +436,10 @@ static int cdns_mhdp_hdcp_check_link(struct cdns_mhdp_device *mhdp)
|
|||
int ret = 0;
|
||||
|
||||
mutex_lock(&mhdp->hdcp.mutex);
|
||||
|
||||
if (!mhdp->connector)
|
||||
goto out;
|
||||
|
||||
if (mhdp->hdcp.value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
|
||||
goto out;
|
||||
|
||||
|
|
@ -445,7 +449,7 @@ static int cdns_mhdp_hdcp_check_link(struct cdns_mhdp_device *mhdp)
|
|||
|
||||
dev_err(mhdp->dev,
|
||||
"[%s:%d] HDCP link failed, retrying authentication\n",
|
||||
mhdp->connector.name, mhdp->connector.base.id);
|
||||
mhdp->connector->name, mhdp->connector->base.id);
|
||||
|
||||
ret = _cdns_mhdp_hdcp_disable(mhdp);
|
||||
if (ret) {
|
||||
|
|
@ -487,13 +491,19 @@ static void cdns_mhdp_hdcp_prop_work(struct work_struct *work)
|
|||
struct cdns_mhdp_device *mhdp = container_of(hdcp,
|
||||
struct cdns_mhdp_device,
|
||||
hdcp);
|
||||
struct drm_device *dev = mhdp->connector.dev;
|
||||
struct drm_device *dev = NULL;
|
||||
struct drm_connector_state *state;
|
||||
|
||||
if (mhdp->connector)
|
||||
dev = mhdp->connector->dev;
|
||||
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
|
||||
mutex_lock(&mhdp->hdcp.mutex);
|
||||
if (mhdp->hdcp.value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
|
||||
state = mhdp->connector.state;
|
||||
state = mhdp->connector->state;
|
||||
state->content_protection = mhdp->hdcp.value;
|
||||
}
|
||||
mutex_unlock(&mhdp->hdcp.mutex);
|
||||
|
|
|
|||
|
|
@ -265,6 +265,8 @@ void drm_gem_shmem_put_pages_locked(struct drm_gem_shmem_object *shmem)
|
|||
shmem->pages_mark_dirty_on_put,
|
||||
shmem->pages_mark_accessed_on_put);
|
||||
shmem->pages = NULL;
|
||||
shmem->pages_mark_accessed_on_put = false;
|
||||
shmem->pages_mark_dirty_on_put = false;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_shmem_put_pages_locked);
|
||||
|
|
@ -397,6 +399,8 @@ int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem,
|
|||
} else {
|
||||
iosys_map_set_vaddr(map, shmem->vaddr);
|
||||
refcount_set(&shmem->vmap_use_count, 1);
|
||||
shmem->pages_mark_accessed_on_put = true;
|
||||
shmem->pages_mark_dirty_on_put = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -550,59 +554,59 @@ int drm_gem_shmem_dumb_create(struct drm_file *file, struct drm_device *dev,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_shmem_dumb_create);
|
||||
|
||||
static bool drm_gem_shmem_try_map_pmd(struct vm_fault *vmf, unsigned long addr,
|
||||
struct page *page)
|
||||
static vm_fault_t drm_gem_shmem_try_insert_pfn_pmd(struct vm_fault *vmf, unsigned long pfn)
|
||||
{
|
||||
#ifdef CONFIG_ARCH_SUPPORTS_PMD_PFNMAP
|
||||
unsigned long pfn = page_to_pfn(page);
|
||||
unsigned long paddr = pfn << PAGE_SHIFT;
|
||||
bool aligned = (addr & ~PMD_MASK) == (paddr & ~PMD_MASK);
|
||||
bool aligned = (vmf->address & ~PMD_MASK) == (paddr & ~PMD_MASK);
|
||||
|
||||
if (aligned &&
|
||||
pmd_none(*vmf->pmd) &&
|
||||
folio_test_pmd_mappable(page_folio(page))) {
|
||||
if (aligned && pmd_none(*vmf->pmd)) {
|
||||
/* Read-only mapping; split upon write fault */
|
||||
pfn &= PMD_MASK >> PAGE_SHIFT;
|
||||
if (vmf_insert_pfn_pmd(vmf, pfn, false) == VM_FAULT_NOPAGE)
|
||||
return true;
|
||||
return vmf_insert_pfn_pmd(vmf, pfn, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf)
|
||||
{
|
||||
struct vm_area_struct *vma = vmf->vma;
|
||||
struct drm_gem_object *obj = vma->vm_private_data;
|
||||
struct drm_device *dev = obj->dev;
|
||||
struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
|
||||
loff_t num_pages = obj->size >> PAGE_SHIFT;
|
||||
vm_fault_t ret;
|
||||
vm_fault_t ret = VM_FAULT_SIGBUS;
|
||||
struct page **pages = shmem->pages;
|
||||
pgoff_t page_offset;
|
||||
pgoff_t page_offset = vmf->pgoff - vma->vm_pgoff; /* page offset within VMA */
|
||||
struct page *page;
|
||||
struct folio *folio;
|
||||
unsigned long pfn;
|
||||
|
||||
/* Offset to faulty address in the VMA. */
|
||||
page_offset = vmf->pgoff - vma->vm_pgoff;
|
||||
dma_resv_lock(obj->resv, NULL);
|
||||
|
||||
dma_resv_lock(shmem->base.resv, NULL);
|
||||
|
||||
if (page_offset >= num_pages ||
|
||||
drm_WARN_ON_ONCE(obj->dev, !shmem->pages) ||
|
||||
shmem->madv < 0) {
|
||||
ret = VM_FAULT_SIGBUS;
|
||||
if (page_offset >= num_pages || drm_WARN_ON_ONCE(dev, !shmem->pages) ||
|
||||
shmem->madv < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (drm_gem_shmem_try_map_pmd(vmf, vmf->address, pages[page_offset])) {
|
||||
ret = VM_FAULT_NOPAGE;
|
||||
page = pages[page_offset];
|
||||
if (drm_WARN_ON_ONCE(dev, !page))
|
||||
goto out;
|
||||
}
|
||||
folio = page_folio(page);
|
||||
|
||||
pfn = page_to_pfn(pages[page_offset]);
|
||||
ret = vmf_insert_pfn(vma, vmf->address, pfn);
|
||||
pfn = page_to_pfn(page);
|
||||
|
||||
out:
|
||||
dma_resv_unlock(shmem->base.resv);
|
||||
if (folio_test_pmd_mappable(folio))
|
||||
ret = drm_gem_shmem_try_insert_pfn_pmd(vmf, pfn);
|
||||
if (ret != VM_FAULT_NOPAGE)
|
||||
ret = vmf_insert_pfn(vma, vmf->address, pfn);
|
||||
|
||||
if (ret == VM_FAULT_NOPAGE)
|
||||
folio_mark_accessed(folio);
|
||||
|
||||
out:
|
||||
dma_resv_unlock(obj->resv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -641,10 +645,29 @@ static void drm_gem_shmem_vm_close(struct vm_area_struct *vma)
|
|||
drm_gem_vm_close(vma);
|
||||
}
|
||||
|
||||
static vm_fault_t drm_gem_shmem_pfn_mkwrite(struct vm_fault *vmf)
|
||||
{
|
||||
struct vm_area_struct *vma = vmf->vma;
|
||||
struct drm_gem_object *obj = vma->vm_private_data;
|
||||
struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
|
||||
loff_t num_pages = obj->size >> PAGE_SHIFT;
|
||||
pgoff_t page_offset = vmf->pgoff - vma->vm_pgoff; /* page offset within VMA */
|
||||
|
||||
if (drm_WARN_ON(obj->dev, !shmem->pages || page_offset >= num_pages))
|
||||
return VM_FAULT_SIGBUS;
|
||||
|
||||
file_update_time(vma->vm_file);
|
||||
|
||||
folio_mark_dirty(page_folio(shmem->pages[page_offset]));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct vm_operations_struct drm_gem_shmem_vm_ops = {
|
||||
.fault = drm_gem_shmem_fault,
|
||||
.open = drm_gem_shmem_vm_open,
|
||||
.close = drm_gem_shmem_vm_close,
|
||||
.pfn_mkwrite = drm_gem_shmem_pfn_mkwrite,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(drm_gem_shmem_vm_ops);
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,10 @@
|
|||
|
||||
static void pvr_gem_object_free(struct drm_gem_object *obj)
|
||||
{
|
||||
drm_gem_shmem_object_free(obj);
|
||||
struct drm_gem_shmem_object *shmem_obj = to_drm_gem_shmem_obj(obj);
|
||||
|
||||
shmem_obj->pages_mark_dirty_on_put = true;
|
||||
drm_gem_shmem_free(shmem_obj);
|
||||
}
|
||||
|
||||
static struct dma_buf *pvr_gem_export(struct drm_gem_object *obj, int flags)
|
||||
|
|
@ -363,7 +366,6 @@ pvr_gem_object_create(struct pvr_device *pvr_dev, size_t size, u64 flags)
|
|||
if (IS_ERR(shmem_obj))
|
||||
return ERR_CAST(shmem_obj);
|
||||
|
||||
shmem_obj->pages_mark_dirty_on_put = true;
|
||||
shmem_obj->map_wc = !(flags & PVR_BO_CPU_CACHED);
|
||||
pvr_obj = shmem_gem_to_pvr_gem(shmem_obj);
|
||||
pvr_obj->flags = flags;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_fbdev_ttm.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_gem_ttm_helper.h>
|
||||
#include <drm/drm_ioctl.h>
|
||||
#include <drm/drm_modeset_helper.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
|
@ -45,7 +46,7 @@ static const struct drm_driver lsdc_drm_driver = {
|
|||
|
||||
.debugfs_init = lsdc_debugfs_init,
|
||||
.dumb_create = lsdc_dumb_create,
|
||||
.dumb_map_offset = lsdc_dumb_map_offset,
|
||||
.dumb_map_offset = drm_gem_ttm_dumb_map_offset,
|
||||
.gem_prime_import_sg_table = lsdc_prime_import_sg_table,
|
||||
DRM_FBDEV_TTM_DRIVER_OPS,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -234,21 +234,6 @@ int lsdc_dumb_create(struct drm_file *file, struct drm_device *ddev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int lsdc_dumb_map_offset(struct drm_file *filp, struct drm_device *ddev,
|
||||
u32 handle, uint64_t *offset)
|
||||
{
|
||||
struct drm_gem_object *gobj;
|
||||
|
||||
gobj = drm_gem_object_lookup(filp, handle);
|
||||
if (!gobj)
|
||||
return -ENOENT;
|
||||
|
||||
*offset = drm_vma_node_offset_addr(&gobj->vma_node);
|
||||
|
||||
drm_gem_object_put(gobj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void lsdc_gem_init(struct drm_device *ddev)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -14,10 +14,6 @@ lsdc_prime_import_sg_table(struct drm_device *ddev,
|
|||
struct dma_buf_attachment *attach,
|
||||
struct sg_table *sg);
|
||||
|
||||
int lsdc_dumb_map_offset(struct drm_file *file,
|
||||
struct drm_device *dev,
|
||||
u32 handle,
|
||||
uint64_t *offset);
|
||||
|
||||
int lsdc_dumb_create(struct drm_file *file,
|
||||
struct drm_device *ddev,
|
||||
|
|
|
|||
|
|
@ -149,15 +149,17 @@ static int lcdif_load(struct drm_device *drm)
|
|||
|
||||
lcdif->clk = devm_clk_get(drm->dev, "pix");
|
||||
if (IS_ERR(lcdif->clk))
|
||||
return PTR_ERR(lcdif->clk);
|
||||
return dev_err_probe(drm->dev, PTR_ERR(lcdif->clk), "Failed to get pix clock\n");
|
||||
|
||||
lcdif->clk_axi = devm_clk_get(drm->dev, "axi");
|
||||
if (IS_ERR(lcdif->clk_axi))
|
||||
return PTR_ERR(lcdif->clk_axi);
|
||||
return dev_err_probe(drm->dev, PTR_ERR(lcdif->clk_axi),
|
||||
"Failed to get axi clock\n");
|
||||
|
||||
lcdif->clk_disp_axi = devm_clk_get(drm->dev, "disp_axi");
|
||||
if (IS_ERR(lcdif->clk_disp_axi))
|
||||
return PTR_ERR(lcdif->clk_disp_axi);
|
||||
return dev_err_probe(drm->dev, PTR_ERR(lcdif->clk_disp_axi),
|
||||
"Failed to get disp_axi clock\n");
|
||||
|
||||
platform_set_drvdata(pdev, drm);
|
||||
|
||||
|
|
|
|||
|
|
@ -443,6 +443,15 @@ config DRM_PANEL_LG_SW43408
|
|||
pixel. It provides a MIPI DSI interface to the host and has a
|
||||
built-in LED backlight.
|
||||
|
||||
config DRM_PANEL_LXD_M9189A
|
||||
tristate "LXD M9189A MIPI-DSI LCD panel"
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
help
|
||||
Say Y if you want to enable support for the LXD M9189A 4-Lane
|
||||
1024x600 MIPI DSI panel.
|
||||
|
||||
config DRM_PANEL_MAGNACHIP_D53E6EA8966
|
||||
tristate "Magnachip D53E6EA8966 DSI panel"
|
||||
depends on OF && SPI
|
||||
|
|
@ -465,6 +474,18 @@ config DRM_PANEL_MANTIX_MLAF057WE51
|
|||
has a resolution of 720x1440 pixels, a built in backlight and touch
|
||||
controller.
|
||||
|
||||
config DRM_PANEL_MOTOROLA_MOT
|
||||
tristate "Atrix 4G and Droid X2 540x960 DSI video mode panel"
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
select VIDEOMODE_HELPERS
|
||||
help
|
||||
Say Y here if you want to enable support for the LCD panel module
|
||||
for Motorola Atrix 4G or Droid X2. Exact panel vendor and model are
|
||||
unknown. The panel has a 540x960 resolution and uses 24 bit RGB per
|
||||
pixel.
|
||||
|
||||
config DRM_PANEL_NEC_NL8048HL11
|
||||
tristate "NEC NL8048HL11 RGB panel"
|
||||
depends on GPIOLIB && OF && SPI
|
||||
|
|
@ -554,6 +575,15 @@ config DRM_PANEL_NOVATEK_NT36672E
|
|||
LCD panel module. The panel has a resolution of 1080x2408 and uses 24 bit
|
||||
RGB per pixel.
|
||||
|
||||
config DRM_PANEL_NOVATEK_NT37700F
|
||||
tristate "Novatek NT37700F DSI panel"
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
help
|
||||
Say Y here if you want to enable support for Novatek NT37700F DSI
|
||||
panel module. The panel has a resolution of 1080x2160.
|
||||
|
||||
config DRM_PANEL_NOVATEK_NT37801
|
||||
tristate "Novatek NT37801/NT37810 AMOLED DSI panel"
|
||||
depends on OF
|
||||
|
|
@ -689,6 +719,7 @@ config DRM_PANEL_RENESAS_R61307
|
|||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
select VIDEOMODE_HELPERS
|
||||
help
|
||||
Say Y here if you want to enable support for KOE tx13d100vm0eaa
|
||||
IPS-LCD module with Renesas R69328 IC. The panel has a 1024x768
|
||||
|
|
@ -702,6 +733,7 @@ config DRM_PANEL_RENESAS_R69328
|
|||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
select VIDEOMODE_HELPERS
|
||||
help
|
||||
Say Y here if you want to enable support for JDI dx12d100vm0eaa
|
||||
IPS-LCD module with Renesas R69328 IC. The panel has a 720x1280
|
||||
|
|
|
|||
|
|
@ -44,7 +44,9 @@ obj-$(CONFIG_DRM_PANEL_LG_LB035Q02) += panel-lg-lb035q02.o
|
|||
obj-$(CONFIG_DRM_PANEL_LG_LD070WX3) += panel-lg-ld070wx3.o
|
||||
obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
|
||||
obj-$(CONFIG_DRM_PANEL_LG_SW43408) += panel-lg-sw43408.o
|
||||
obj-$(CONFIG_DRM_PANEL_LXD_M9189A) += panel-lxd-m9189a.o
|
||||
obj-$(CONFIG_DRM_PANEL_MAGNACHIP_D53E6EA8966) += panel-magnachip-d53e6ea8966.o
|
||||
obj-$(CONFIG_DRM_PANEL_MOTOROLA_MOT) += panel-motorola-mot.o
|
||||
obj-$(CONFIG_DRM_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o
|
||||
obj-$(CONFIG_DRM_PANEL_NEWVISION_NV3051D) += panel-newvision-nv3051d.o
|
||||
obj-$(CONFIG_DRM_PANEL_NEWVISION_NV3052C) += panel-newvision-nv3052c.o
|
||||
|
|
@ -54,6 +56,7 @@ obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35950) += panel-novatek-nt35950.o
|
|||
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36523) += panel-novatek-nt36523.o
|
||||
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36672A) += panel-novatek-nt36672a.o
|
||||
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36672E) += panel-novatek-nt36672e.o
|
||||
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT37700F) += panel-novatek-nt37700f.o
|
||||
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT37801) += panel-novatek-nt37801.o
|
||||
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT39016) += panel-novatek-nt39016.o
|
||||
obj-$(CONFIG_DRM_PANEL_MANTIX_MLAF057WE51) += panel-mantix-mlaf057we51.o
|
||||
|
|
|
|||
|
|
@ -592,7 +592,7 @@ static int ili9882t_unprepare(struct drm_panel *panel)
|
|||
{
|
||||
struct ili9882t *ili = to_ili9882t(panel);
|
||||
|
||||
gpiod_set_value(ili->enable_gpio, 0);
|
||||
gpiod_set_value_cansleep(ili->enable_gpio, 0);
|
||||
usleep_range(1000, 2000);
|
||||
regulator_disable(ili->avee);
|
||||
regulator_disable(ili->avdd);
|
||||
|
|
@ -608,7 +608,7 @@ static int ili9882t_prepare(struct drm_panel *panel)
|
|||
struct ili9882t *ili = to_ili9882t(panel);
|
||||
int ret;
|
||||
|
||||
gpiod_set_value(ili->enable_gpio, 0);
|
||||
gpiod_set_value_cansleep(ili->enable_gpio, 0);
|
||||
usleep_range(1000, 1500);
|
||||
|
||||
ret = regulator_enable(ili->pp3300);
|
||||
|
|
@ -638,11 +638,11 @@ static int ili9882t_prepare(struct drm_panel *panel)
|
|||
}
|
||||
usleep_range(1000, 2000);
|
||||
|
||||
gpiod_set_value(ili->enable_gpio, 1);
|
||||
gpiod_set_value_cansleep(ili->enable_gpio, 1);
|
||||
usleep_range(1000, 2000);
|
||||
gpiod_set_value(ili->enable_gpio, 0);
|
||||
gpiod_set_value_cansleep(ili->enable_gpio, 0);
|
||||
msleep(50);
|
||||
gpiod_set_value(ili->enable_gpio, 1);
|
||||
gpiod_set_value_cansleep(ili->enable_gpio, 1);
|
||||
usleep_range(6000, 10000);
|
||||
|
||||
ret = ili->desc->init(ili);
|
||||
|
|
@ -652,7 +652,7 @@ static int ili9882t_prepare(struct drm_panel *panel)
|
|||
return 0;
|
||||
|
||||
poweroff:
|
||||
gpiod_set_value(ili->enable_gpio, 0);
|
||||
gpiod_set_value_cansleep(ili->enable_gpio, 0);
|
||||
regulator_disable(ili->avee);
|
||||
poweroffavdd:
|
||||
regulator_disable(ili->avdd);
|
||||
|
|
@ -793,7 +793,7 @@ static int ili9882t_add(struct ili9882t *ili)
|
|||
return PTR_ERR(ili->enable_gpio);
|
||||
}
|
||||
|
||||
gpiod_set_value(ili->enable_gpio, 0);
|
||||
gpiod_set_value_cansleep(ili->enable_gpio, 0);
|
||||
|
||||
err = of_drm_get_panel_orientation(dev->of_node, &ili->orientation);
|
||||
if (err < 0) {
|
||||
|
|
|
|||
|
|
@ -1366,6 +1366,246 @@ static const struct jadard_panel_desc anbernic_rgds_display_desc = {
|
|||
MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM,
|
||||
};
|
||||
|
||||
static int taiguan_xti05101_01a_init_cmds(struct jadard *jadard)
|
||||
{
|
||||
struct mipi_dsi_multi_context dsi_ctx = { .dsi = jadard->dsi };
|
||||
|
||||
jd9365da_switch_page(&dsi_ctx, 0x00);
|
||||
jadard_enable_standard_cmds(&dsi_ctx);
|
||||
|
||||
jd9365da_switch_page(&dsi_ctx, 0x01);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x74);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0xd7);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x01);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0xd7);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x01);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0xfe);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x19);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x28);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x05);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x08);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x12);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x78);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0xff);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0xff);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0x7f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x06);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0xa0);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x1e);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x0b);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x02);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x6a);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x0a);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0x2e);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x1a);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x15);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x7f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x58);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x46);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x39);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x35);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x27);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x2b);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x16);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x30);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x2e);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x2f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x4d);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x3c);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x43);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x36);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x31);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x24);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x14);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x02);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x70, 0x7f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x71, 0x58);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x72, 0x46);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x73, 0x39);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x74, 0x35);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0x27);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x2b);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x16);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x30);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x79, 0x2e);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7a, 0x2f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7b, 0x4d);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7c, 0x3c);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7d, 0x43);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7e, 0x36);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7f, 0x31);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x24);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x81, 0x14);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x82, 0x02);
|
||||
|
||||
jd9365da_switch_page(&dsi_ctx, 0x02);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x52);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x5f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0x5f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x50);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x77);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x05, 0x57);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x06, 0x5f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x07, 0x4e);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x08, 0x4c);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x5f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0a, 0x4a);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0b, 0x48);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x5f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0d, 0x46);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x44);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0f, 0x40);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x10, 0x5f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x11, 0x5f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x12, 0x5f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x13, 0x5f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x14, 0x5f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x15, 0x5f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x16, 0x53);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x5f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0x5f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x51);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x77);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0x57);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x5f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1d, 0x4f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1e, 0x4d);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1f, 0x5f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x20, 0x4b);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x21, 0x49);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x22, 0x5f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x23, 0x47);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0x45);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x25, 0x41);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x26, 0x5f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x27, 0x5f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x28, 0x5f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x29, 0x5f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2a, 0x5f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x5f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2c, 0x13);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2d, 0x1f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2e, 0x1f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2f, 0x01);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x30, 0x17);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x31, 0x17);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x32, 0x1f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x33, 0x0d);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x34, 0x0f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x1f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x36, 0x05);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x07);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x1f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x09);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x0b);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3b, 0x11);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x1f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0x1f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0x1f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0x1f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x1f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0x1f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x42, 0x12);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x1f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x1f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x45, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x46, 0x17);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x47, 0x17);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x48, 0x1f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x49, 0x0c);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4a, 0x0e);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4b, 0x1f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4c, 0x04);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4d, 0x06);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4e, 0x1f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4f, 0x08);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x50, 0x0a);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x51, 0x10);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x52, 0x1f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x53, 0x1f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x54, 0x1f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x1f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x56, 0x1f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x1f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x58, 0x40);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x10);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x06);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x40);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x40);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x03);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x04);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x6c);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x6c);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x75);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x08);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0xb4);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x08);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x6c);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x6c);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x0c);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x88);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0xbb);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x05);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x2a);
|
||||
|
||||
jd9365da_switch_page(&dsi_ctx, 0x04);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x0e);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0xb3);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x61);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x48);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x0f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x58);
|
||||
|
||||
jd9365da_switch_page(&dsi_ctx, 0x00);
|
||||
|
||||
mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
|
||||
|
||||
mipi_dsi_msleep(&dsi_ctx, 120);
|
||||
|
||||
mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
|
||||
|
||||
mipi_dsi_msleep(&dsi_ctx, 20);
|
||||
|
||||
return dsi_ctx.accum_err;
|
||||
};
|
||||
|
||||
static const struct jadard_panel_desc taiguan_xti05101_01a_desc = {
|
||||
.mode = {
|
||||
.clock = (800 + 24 + 24 + 24) * (1280 + 30 + 4 + 8) * 60 / 1000,
|
||||
|
||||
.hdisplay = 800,
|
||||
.hsync_start = 800 + 24,
|
||||
.hsync_end = 800 + 24 + 24,
|
||||
.htotal = 800 + 24 + 24 + 24,
|
||||
|
||||
.vdisplay = 1280,
|
||||
.vsync_start = 1280 + 30,
|
||||
.vsync_end = 1280 + 30 + 4,
|
||||
.vtotal = 1280 + 30 + 4 + 8,
|
||||
|
||||
.width_mm = 135,
|
||||
.height_mm = 216,
|
||||
.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
|
||||
},
|
||||
.lanes = 4,
|
||||
.format = MIPI_DSI_FMT_RGB888,
|
||||
.init = taiguan_xti05101_01a_init_cmds,
|
||||
.lp11_before_reset = true,
|
||||
.reset_before_power_off_vcioo = true,
|
||||
.vcioo_to_lp11_delay_ms = 5,
|
||||
.lp11_to_reset_delay_ms = 10,
|
||||
.backlight_off_to_display_off_delay_ms = 3,
|
||||
.display_off_to_enter_sleep_delay_ms = 50,
|
||||
.enter_sleep_to_reset_down_delay_ms = 100,
|
||||
};
|
||||
|
||||
static int jadard_dsi_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
|
|
@ -1463,6 +1703,10 @@ static const struct of_device_id jadard_of_match[] = {
|
|||
.compatible = "radxa,display-8hd-ad002",
|
||||
.data = &radxa_display_8hd_ad002_desc
|
||||
},
|
||||
{
|
||||
.compatible = "taiguanck,xti05101-01a",
|
||||
.data = &taiguan_xti05101_01a_desc
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, jadard_of_match);
|
||||
|
|
|
|||
243
drivers/gpu/drm/panel/panel-lxd-m9189a.c
Normal file
243
drivers/gpu/drm/panel/panel-lxd-m9189a.c
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree.
|
||||
* Copyright (c) 2024 Luca Weiss <luca.weiss@fairphone.com>
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_panel.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
/* Manufacturer specific DSI commands */
|
||||
#define EK79007AD3_GAMMA1 0x80
|
||||
#define EK79007AD3_GAMMA2 0x81
|
||||
#define EK79007AD3_GAMMA3 0x82
|
||||
#define EK79007AD3_GAMMA4 0x83
|
||||
#define EK79007AD3_GAMMA5 0x84
|
||||
#define EK79007AD3_GAMMA6 0x85
|
||||
#define EK79007AD3_GAMMA7 0x86
|
||||
#define EK79007AD3_PANEL_CTRL3 0xB2
|
||||
|
||||
struct m9189_panel {
|
||||
struct drm_panel panel;
|
||||
struct mipi_dsi_device *dsi;
|
||||
struct regulator *supply;
|
||||
struct gpio_desc *reset_gpio;
|
||||
struct gpio_desc *standby_gpio;
|
||||
};
|
||||
|
||||
static inline struct m9189_panel *to_m9189_panel(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct m9189_panel, panel);
|
||||
}
|
||||
|
||||
static void m9189_reset(struct m9189_panel *m9189)
|
||||
{
|
||||
gpiod_set_value_cansleep(m9189->reset_gpio, 0);
|
||||
msleep(20);
|
||||
gpiod_set_value_cansleep(m9189->reset_gpio, 1);
|
||||
msleep(30);
|
||||
gpiod_set_value_cansleep(m9189->reset_gpio, 0);
|
||||
msleep(55);
|
||||
}
|
||||
|
||||
static int m9189_on(struct m9189_panel *m9189)
|
||||
{
|
||||
struct mipi_dsi_multi_context ctx = { .dsi = m9189->dsi };
|
||||
|
||||
ctx.dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
/* Gamma 2.2 */
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA1, 0x48);
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA2, 0xB8);
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA3, 0x88);
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA4, 0x88);
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA5, 0x58);
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA6, 0xD2);
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA7, 0x88);
|
||||
mipi_dsi_msleep(&ctx, 50);
|
||||
|
||||
/* 4 Lanes */
|
||||
mipi_dsi_generic_write_multi(&ctx, (u8[]){ EK79007AD3_PANEL_CTRL3, 0x70 }, 2);
|
||||
|
||||
mipi_dsi_dcs_exit_sleep_mode_multi(&ctx);
|
||||
mipi_dsi_msleep(&ctx, 120);
|
||||
|
||||
mipi_dsi_dcs_set_display_on_multi(&ctx);
|
||||
mipi_dsi_msleep(&ctx, 120);
|
||||
|
||||
return ctx.accum_err;
|
||||
}
|
||||
|
||||
static int m9189_disable(struct drm_panel *panel)
|
||||
{
|
||||
struct m9189_panel *m9189 = to_m9189_panel(panel);
|
||||
struct mipi_dsi_multi_context ctx = { .dsi = m9189->dsi };
|
||||
|
||||
ctx.dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
mipi_dsi_dcs_enter_sleep_mode_multi(&ctx);
|
||||
mipi_dsi_msleep(&ctx, 120);
|
||||
|
||||
gpiod_set_value_cansleep(m9189->standby_gpio, 1);
|
||||
|
||||
return ctx.accum_err;
|
||||
}
|
||||
|
||||
static int m9189_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct m9189_panel *m9189 = to_m9189_panel(panel);
|
||||
struct device *dev = &m9189->dsi->dev;
|
||||
int ret;
|
||||
|
||||
ret = regulator_enable(m9189->supply);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enable regulators: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
gpiod_set_value_cansleep(m9189->standby_gpio, 0);
|
||||
msleep(20);
|
||||
m9189_reset(m9189);
|
||||
|
||||
ret = m9189_on(m9189);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to initialize panel: %d\n", ret);
|
||||
gpiod_set_value_cansleep(m9189->reset_gpio, 1);
|
||||
regulator_disable(m9189->supply);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int m9189_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct m9189_panel *m9189 = to_m9189_panel(panel);
|
||||
|
||||
gpiod_set_value_cansleep(m9189->standby_gpio, 1);
|
||||
msleep(50);
|
||||
|
||||
gpiod_set_value_cansleep(m9189->reset_gpio, 1);
|
||||
regulator_disable(m9189->supply);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_display_mode m9189_mode = {
|
||||
.clock = (1024 + 160 + 160 + 10) * (600 + 12 + 23 + 1) * 60 / 1000,
|
||||
.hdisplay = 1024,
|
||||
.hsync_start = 1024 + 160,
|
||||
.hsync_end = 1024 + 160 + 160,
|
||||
.htotal = 1024 + 160 + 160 + 10,
|
||||
.vdisplay = 600,
|
||||
.vsync_start = 600 + 12,
|
||||
.vsync_end = 600 + 12 + 23,
|
||||
.vtotal = 600 + 12 + 23 + 1,
|
||||
.width_mm = 154,
|
||||
.height_mm = 86,
|
||||
};
|
||||
|
||||
static int m9189_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
return drm_connector_helper_get_modes_fixed(connector, &m9189_mode);
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs m9189_panel_funcs = {
|
||||
.prepare = m9189_prepare,
|
||||
.unprepare = m9189_unprepare,
|
||||
.disable = m9189_disable,
|
||||
.get_modes = m9189_get_modes,
|
||||
};
|
||||
|
||||
static int lxd_m9189_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
struct m9189_panel *m9189;
|
||||
int ret;
|
||||
|
||||
m9189 = devm_kzalloc(dev, sizeof(*m9189), GFP_KERNEL);
|
||||
if (!m9189)
|
||||
return -ENOMEM;
|
||||
|
||||
m9189->supply = devm_regulator_get(dev, "power");
|
||||
if (IS_ERR(m9189->supply))
|
||||
return dev_err_probe(dev, PTR_ERR(m9189->supply),
|
||||
"Failed to get power-supply\n");
|
||||
|
||||
m9189->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(m9189->reset_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(m9189->reset_gpio),
|
||||
"Failed to get reset-gpios\n");
|
||||
|
||||
m9189->standby_gpio = devm_gpiod_get(dev, "standby", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(m9189->standby_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(m9189->standby_gpio),
|
||||
"Failed to get standby-gpios\n");
|
||||
|
||||
m9189->dsi = dsi;
|
||||
mipi_dsi_set_drvdata(dsi, m9189);
|
||||
|
||||
dsi->lanes = 4;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST;
|
||||
|
||||
drm_panel_init(&m9189->panel, dev, &m9189_panel_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
m9189->panel.prepare_prev_first = true;
|
||||
|
||||
ret = drm_panel_of_backlight(&m9189->panel);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to get backlight\n");
|
||||
|
||||
drm_panel_add(&m9189->panel);
|
||||
|
||||
ret = mipi_dsi_attach(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err_probe(dev, ret, "Failed to attach to DSI host\n");
|
||||
drm_panel_remove(&m9189->panel);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lxd_m9189_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct m9189_panel *m9189 = mipi_dsi_get_drvdata(dsi);
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_detach(dsi);
|
||||
if (ret < 0)
|
||||
dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
|
||||
|
||||
drm_panel_remove(&m9189->panel);
|
||||
}
|
||||
|
||||
static const struct of_device_id lxd_m9189_of_match[] = {
|
||||
{ .compatible = "lxd,m9189a" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lxd_m9189_of_match);
|
||||
|
||||
static struct mipi_dsi_driver lxd_m9189_driver = {
|
||||
.probe = lxd_m9189_probe,
|
||||
.remove = lxd_m9189_remove,
|
||||
.driver = {
|
||||
.name = "panel-lxd-m9189a",
|
||||
.of_match_table = lxd_m9189_of_match,
|
||||
},
|
||||
};
|
||||
module_mipi_dsi_driver(lxd_m9189_driver);
|
||||
|
||||
MODULE_DESCRIPTION("DRM driver for LXD M9189A MIPI-DSI panels");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -168,7 +168,7 @@ static const struct drm_display_mode default_mode_mantix = {
|
|||
.vsync_start = 1440 + 130,
|
||||
.vsync_end = 1440 + 130 + 8,
|
||||
.vtotal = 1440 + 130 + 8 + 106,
|
||||
.clock = 85298,
|
||||
.clock = 81237,
|
||||
.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
|
||||
.width_mm = 65,
|
||||
.height_mm = 130,
|
||||
|
|
@ -183,7 +183,7 @@ static const struct drm_display_mode default_mode_ys = {
|
|||
.vsync_start = 1440 + 175,
|
||||
.vsync_end = 1440 + 175 + 8,
|
||||
.vtotal = 1440 + 175 + 8 + 50,
|
||||
.clock = 85298,
|
||||
.clock = 80706,
|
||||
.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
|
||||
.width_mm = 65,
|
||||
.height_mm = 130,
|
||||
|
|
@ -295,20 +295,10 @@ static int mantix_probe(struct mipi_dsi_device *dsi)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void mantix_shutdown(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct mantix *ctx = mipi_dsi_get_drvdata(dsi);
|
||||
|
||||
drm_panel_unprepare(&ctx->panel);
|
||||
drm_panel_disable(&ctx->panel);
|
||||
}
|
||||
|
||||
static void mantix_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct mantix *ctx = mipi_dsi_get_drvdata(dsi);
|
||||
|
||||
mantix_shutdown(dsi);
|
||||
|
||||
mipi_dsi_detach(dsi);
|
||||
drm_panel_remove(&ctx->panel);
|
||||
}
|
||||
|
|
@ -323,7 +313,6 @@ MODULE_DEVICE_TABLE(of, mantix_of_match);
|
|||
static struct mipi_dsi_driver mantix_driver = {
|
||||
.probe = mantix_probe,
|
||||
.remove = mantix_remove,
|
||||
.shutdown = mantix_shutdown,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = mantix_of_match,
|
||||
|
|
|
|||
244
drivers/gpu/drm/panel/panel-motorola-mot.c
Normal file
244
drivers/gpu/drm/panel/panel-motorola-mot.c
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/array_size.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regulator/consumer.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_probe_helper.h>
|
||||
|
||||
static const struct regulator_bulk_data mot_panel_supplies[] = {
|
||||
{ .supply = "vddio" }, { .supply = "vdd" },
|
||||
};
|
||||
|
||||
struct mot_panel {
|
||||
struct drm_panel panel;
|
||||
struct mipi_dsi_device *dsi;
|
||||
|
||||
struct gpio_desc *reset_gpio;
|
||||
|
||||
struct regulator_bulk_data *supplies;
|
||||
};
|
||||
|
||||
static inline struct mot_panel *to_mot_panel(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct mot_panel, panel);
|
||||
}
|
||||
|
||||
static void mot_panel_reset(struct mot_panel *priv)
|
||||
{
|
||||
gpiod_set_value_cansleep(priv->reset_gpio, 1);
|
||||
usleep_range(50000, 51000);
|
||||
gpiod_set_value_cansleep(priv->reset_gpio, 0);
|
||||
usleep_range(10000, 11000);
|
||||
}
|
||||
|
||||
static void mot_es2(struct mipi_dsi_multi_context *ctx)
|
||||
{
|
||||
mipi_dsi_generic_write_seq_multi(ctx, 0x55, 0x01);
|
||||
|
||||
mipi_dsi_dcs_exit_sleep_mode_multi(ctx);
|
||||
mipi_dsi_msleep(ctx, 120);
|
||||
|
||||
mipi_dsi_generic_write_seq_multi(ctx, 0xf4, 0x00, 0xbb, 0x46, 0x53, 0x0c, 0x49,
|
||||
0x74, 0x29, 0x12, 0x15, 0x2f, 0x2f, 0x04);
|
||||
mipi_dsi_generic_write_seq_multi(ctx, 0xf8, 0x4b, 0x04, 0x10, 0x1a, 0x2c, 0x2c,
|
||||
0x2c, 0x2c, 0x14, 0x12);
|
||||
|
||||
mipi_dsi_generic_write_seq_multi(ctx, 0xb5, 0x03, 0x7f, 0x00, 0x80, 0xc7, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(ctx, 0xb7, 0x66, 0xf6, 0x46, 0x9f, 0x90, 0x99,
|
||||
0xff, 0x80, 0x6d, 0x01);
|
||||
|
||||
/* Gamma R */
|
||||
mipi_dsi_generic_write_seq_multi(ctx, 0xf9, 0x04);
|
||||
mipi_dsi_generic_write_seq_multi(ctx, 0xfa, 0x00, 0x2f, 0x30, 0x12, 0x0e, 0x0c,
|
||||
0x22, 0x27, 0x31, 0x2e, 0x07, 0x0f);
|
||||
mipi_dsi_generic_write_seq_multi(ctx, 0xfb, 0x00, 0x2f, 0x30, 0x12, 0x0e, 0x0c,
|
||||
0x22, 0x27, 0x31, 0x2e, 0x07, 0x0f);
|
||||
|
||||
/* Gamma G */
|
||||
mipi_dsi_generic_write_seq_multi(ctx, 0xf9, 0x02);
|
||||
mipi_dsi_generic_write_seq_multi(ctx, 0xfa, 0x00, 0x2f, 0x37, 0x15, 0x15, 0x11,
|
||||
0x1f, 0x25, 0x2d, 0x2a, 0x05, 0x0f);
|
||||
mipi_dsi_generic_write_seq_multi(ctx, 0xfb, 0x00, 0x2f, 0x37, 0x15, 0x15, 0x11,
|
||||
0x1f, 0x25, 0x2d, 0x2a, 0x05, 0x0f);
|
||||
|
||||
/* Gamma B */
|
||||
mipi_dsi_generic_write_seq_multi(ctx, 0xf9, 0x01);
|
||||
mipi_dsi_generic_write_seq_multi(ctx, 0xfa, 0x00, 0x2f, 0x3f, 0x16, 0x1f, 0x15,
|
||||
0x1f, 0x25, 0x2d, 0x2b, 0x06, 0x0b);
|
||||
mipi_dsi_generic_write_seq_multi(ctx, 0xfb, 0x00, 0x2f, 0x3f, 0x16, 0x1f, 0x15,
|
||||
0x1f, 0x25, 0x2d, 0x2b, 0x06, 0x0b);
|
||||
|
||||
/* Gamma W */
|
||||
mipi_dsi_generic_write_seq_multi(ctx, 0xf9, 0x20);
|
||||
mipi_dsi_generic_write_seq_multi(ctx, 0xfa, 0x00, 0x2f, 0x34, 0x15, 0x1a, 0x11,
|
||||
0x1f, 0x23, 0x2d, 0x29, 0x02, 0x08);
|
||||
mipi_dsi_generic_write_seq_multi(ctx, 0xfb, 0x00, 0x2f, 0x34, 0x15, 0x1a, 0x11,
|
||||
0x1f, 0x23, 0x2d, 0x29, 0x02, 0x08);
|
||||
|
||||
mipi_dsi_generic_write_seq_multi(ctx, 0x53, 0x2c);
|
||||
mipi_dsi_generic_write_seq_multi(ctx, 0x35, 0x00);
|
||||
}
|
||||
|
||||
static int mot_panel_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct mot_panel *priv = to_mot_panel(panel);
|
||||
struct mipi_dsi_multi_context ctx = { .dsi = priv->dsi };
|
||||
struct device *dev = panel->dev;
|
||||
int ret;
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(mot_panel_supplies), priv->supplies);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to enable power supplies: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mot_panel_reset(priv);
|
||||
|
||||
mipi_dsi_generic_write_seq_multi(&ctx, 0xf0, 0x5a, 0x5a);
|
||||
mipi_dsi_generic_write_seq_multi(&ctx, 0xf1, 0x5a, 0x5a);
|
||||
mipi_dsi_generic_write_seq_multi(&ctx, 0xd0, 0x8e);
|
||||
|
||||
mot_es2(&ctx);
|
||||
|
||||
mipi_dsi_dcs_set_display_on_multi(&ctx);
|
||||
mipi_dsi_msleep(&ctx, 20);
|
||||
|
||||
return ctx.accum_err;
|
||||
}
|
||||
|
||||
static int mot_panel_disable(struct drm_panel *panel)
|
||||
{
|
||||
struct mot_panel *priv = to_mot_panel(panel);
|
||||
struct mipi_dsi_multi_context ctx = { .dsi = priv->dsi };
|
||||
|
||||
mipi_dsi_dcs_set_display_off_multi(&ctx);
|
||||
mipi_dsi_dcs_enter_sleep_mode_multi(&ctx);
|
||||
mipi_dsi_msleep(&ctx, 70);
|
||||
|
||||
return ctx.accum_err;
|
||||
}
|
||||
|
||||
static int mot_panel_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct mot_panel *priv = to_mot_panel(panel);
|
||||
|
||||
usleep_range(10000, 11000);
|
||||
|
||||
gpiod_set_value_cansleep(priv->reset_gpio, 1);
|
||||
usleep_range(5000, 6000);
|
||||
|
||||
regulator_bulk_disable(ARRAY_SIZE(mot_panel_supplies), priv->supplies);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_display_mode mot_panel_mode = {
|
||||
.clock = (540 + 32 + 32 + 16) * (960 + 12 + 12 + 8) * 60 / 1000,
|
||||
.hdisplay = 540,
|
||||
.hsync_start = 540 + 32,
|
||||
.hsync_end = 540 + 32 + 32,
|
||||
.htotal = 540 + 32 + 32 + 16,
|
||||
.vdisplay = 960,
|
||||
.vsync_start = 960 + 12,
|
||||
.vsync_end = 960 + 12 + 12,
|
||||
.vtotal = 960 + 12 + 12 + 8,
|
||||
.width_mm = 51,
|
||||
.height_mm = 91,
|
||||
.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
|
||||
};
|
||||
|
||||
static int mot_panel_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
return drm_connector_helper_get_modes_fixed(connector, &mot_panel_mode);
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs mot_panel_panel_funcs = {
|
||||
.prepare = mot_panel_prepare,
|
||||
.disable = mot_panel_disable,
|
||||
.unprepare = mot_panel_unprepare,
|
||||
.get_modes = mot_panel_get_modes,
|
||||
};
|
||||
|
||||
static int mot_panel_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
struct mot_panel *priv;
|
||||
int ret;
|
||||
|
||||
priv = devm_drm_panel_alloc(dev, struct mot_panel, panel,
|
||||
&mot_panel_panel_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
if (IS_ERR(priv))
|
||||
return PTR_ERR(priv);
|
||||
|
||||
ret = devm_regulator_bulk_get_const(dev, ARRAY_SIZE(mot_panel_supplies),
|
||||
mot_panel_supplies, &priv->supplies);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "failed to get supplies\n");
|
||||
|
||||
priv->reset_gpio = devm_gpiod_get_optional(dev, "reset",
|
||||
GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(priv->reset_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(priv->reset_gpio),
|
||||
"failed to get reset gpios\n");
|
||||
|
||||
priv->dsi = dsi;
|
||||
mipi_dsi_set_drvdata(dsi, priv);
|
||||
|
||||
dsi->lanes = 2;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = drm_panel_of_backlight(&priv->panel);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "failed to get backlight\n");
|
||||
|
||||
drm_panel_add(&priv->panel);
|
||||
|
||||
ret = devm_mipi_dsi_attach(dev, dsi);
|
||||
if (ret < 0) {
|
||||
drm_panel_remove(&priv->panel);
|
||||
return dev_err_probe(dev, ret, "failed to attach to DSI host\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mot_panel_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct mot_panel *priv = mipi_dsi_get_drvdata(dsi);
|
||||
|
||||
drm_panel_remove(&priv->panel);
|
||||
}
|
||||
|
||||
static const struct of_device_id mot_panel_of_match[] = {
|
||||
{ .compatible = "motorola,mot-panel" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mot_panel_of_match);
|
||||
|
||||
static struct mipi_dsi_driver mot_panel_driver = {
|
||||
.driver = {
|
||||
.name = "panel-motorola-mot",
|
||||
.of_match_table = mot_panel_of_match,
|
||||
},
|
||||
.probe = mot_panel_probe,
|
||||
.remove = mot_panel_remove,
|
||||
};
|
||||
module_mipi_dsi_driver(mot_panel_driver);
|
||||
|
||||
MODULE_AUTHOR("Svyatoslav Ryhel <clamor95@gmail.com>");
|
||||
MODULE_DESCRIPTION("Motorola MOT panel driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
299
drivers/gpu/drm/panel/panel-novatek-nt37700f.c
Normal file
299
drivers/gpu/drm/panel/panel-novatek-nt37700f.c
Normal file
|
|
@ -0,0 +1,299 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2024, The Linux Foundation. All rights reserved.
|
||||
* Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
|
||||
* Copyright (c) 2013, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/of.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_probe_helper.h>
|
||||
|
||||
struct nt37700f_tianma {
|
||||
struct drm_panel panel;
|
||||
struct mipi_dsi_device *dsi;
|
||||
struct regulator *supply;
|
||||
struct gpio_desc *reset_gpio;
|
||||
};
|
||||
|
||||
static inline
|
||||
struct nt37700f_tianma *to_nt37700f_tianma(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct nt37700f_tianma, panel);
|
||||
}
|
||||
|
||||
static void nt37700f_tianma_reset(struct nt37700f_tianma *ctx)
|
||||
{
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
usleep_range(1000, 2000);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
usleep_range(10000, 11000);
|
||||
}
|
||||
|
||||
#define nt37700f_tianma_panel_switch_page(ctx, page) \
|
||||
mipi_dsi_dcs_write_seq_multi((ctx), 0xf0, 0x55, 0xaa, 0x52, 0x08, (page))
|
||||
|
||||
static int nt37700f_tianma_on(struct nt37700f_tianma *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
|
||||
|
||||
nt37700f_tianma_panel_switch_page(&dsi_ctx, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc0, 0x56);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xca, 0x52);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x06);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb5, 0x2b, 0x1a);
|
||||
nt37700f_tianma_panel_switch_page(&dsi_ctx, 0x01);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcd, 0x04, 0x82);
|
||||
nt37700f_tianma_panel_switch_page(&dsi_ctx, 0x02);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcc, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0xaa, 0x55, 0xa5, 0x80);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x55);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf6, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x56);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf6, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0xaa, 0x55, 0xa5, 0x81);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x07);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf3, 0x07);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x05);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf3, 0x25);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x90, 0x01);
|
||||
|
||||
mipi_dsi_dcs_set_column_address_multi(&dsi_ctx, 0x0000, 1080 - 1);
|
||||
mipi_dsi_dcs_set_page_address_multi(&dsi_ctx, 0x0000, 2160 - 1);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x20);
|
||||
mipi_dsi_dcs_set_tear_on_multi(&dsi_ctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
|
||||
|
||||
nt37700f_tianma_panel_switch_page(&dsi_ctx, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc0, 0x56);
|
||||
nt37700f_tianma_panel_switch_page(&dsi_ctx, 0x02);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcd, 0x00);
|
||||
nt37700f_tianma_panel_switch_page(&dsi_ctx, 0x04);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd0, 0x11, 0x64);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x09);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb1, 0x20);
|
||||
|
||||
mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
|
||||
mipi_dsi_msleep(&dsi_ctx, 120);
|
||||
mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
|
||||
|
||||
return dsi_ctx.accum_err;
|
||||
}
|
||||
|
||||
static int nt37700f_tianma_disable(struct drm_panel *panel)
|
||||
{
|
||||
struct nt37700f_tianma *ctx = to_nt37700f_tianma(panel);
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
|
||||
|
||||
mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
|
||||
mipi_dsi_msleep(&dsi_ctx, 50);
|
||||
mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
|
||||
mipi_dsi_msleep(&dsi_ctx, 100);
|
||||
|
||||
return dsi_ctx.accum_err;
|
||||
}
|
||||
|
||||
static int nt37700f_tianma_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct nt37700f_tianma *ctx = to_nt37700f_tianma(panel);
|
||||
struct device *dev = &ctx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
ret = regulator_enable(ctx->supply);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enable power supply: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
nt37700f_tianma_reset(ctx);
|
||||
|
||||
ret = nt37700f_tianma_on(ctx);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to initialize panel: %d\n", ret);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nt37700f_tianma_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct nt37700f_tianma *ctx = to_nt37700f_tianma(panel);
|
||||
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
regulator_disable(ctx->supply);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_display_mode nt37700f_tianma_mode = {
|
||||
.clock = (1080 + 32 + 32 + 98) * (2160 + 32 + 4 + 98) * 60 / 1000,
|
||||
.hdisplay = 1080,
|
||||
.hsync_start = 1080 + 32,
|
||||
.hsync_end = 1080 + 32 + 32,
|
||||
.htotal = 1080 + 32 + 32 + 98,
|
||||
.vdisplay = 2160,
|
||||
.vsync_start = 2160 + 32,
|
||||
.vsync_end = 2160 + 32 + 4,
|
||||
.vtotal = 2160 + 32 + 4 + 98,
|
||||
.width_mm = 69,
|
||||
.height_mm = 137,
|
||||
.type = DRM_MODE_TYPE_DRIVER,
|
||||
};
|
||||
|
||||
static int nt37700f_tianma_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
return drm_connector_helper_get_modes_fixed(connector, &nt37700f_tianma_mode);
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs nt37700f_tianma_panel_funcs = {
|
||||
.prepare = nt37700f_tianma_prepare,
|
||||
.unprepare = nt37700f_tianma_unprepare,
|
||||
.disable = nt37700f_tianma_disable,
|
||||
.get_modes = nt37700f_tianma_get_modes,
|
||||
};
|
||||
|
||||
static int nt37700f_tianma_bl_update_status(struct backlight_device *bl)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = bl_get_data(bl);
|
||||
u16 brightness = backlight_get_brightness(bl);
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_brightness_large(dsi, brightness);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nt37700f_tianma_bl_get_brightness(struct backlight_device *bl)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = bl_get_data(bl);
|
||||
u16 brightness;
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = mipi_dsi_dcs_get_display_brightness_large(dsi, &brightness);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
return brightness;
|
||||
}
|
||||
|
||||
static const struct backlight_ops nt37700f_tianma_bl_ops = {
|
||||
.update_status = nt37700f_tianma_bl_update_status,
|
||||
.get_brightness = nt37700f_tianma_bl_get_brightness,
|
||||
};
|
||||
|
||||
static struct backlight_device *
|
||||
nt37700f_tianma_create_backlight(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
const struct backlight_properties props = {
|
||||
.type = BACKLIGHT_RAW,
|
||||
.brightness = 2047,
|
||||
.max_brightness = 2047,
|
||||
};
|
||||
|
||||
return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
|
||||
&nt37700f_tianma_bl_ops, &props);
|
||||
}
|
||||
|
||||
static int nt37700f_tianma_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
struct nt37700f_tianma *ctx;
|
||||
int ret;
|
||||
|
||||
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
ctx->supply = devm_regulator_get(dev, "power");
|
||||
if (IS_ERR(ctx->supply))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx->supply),
|
||||
"Failed to get power-supply\n");
|
||||
|
||||
ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(ctx->reset_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
|
||||
"Failed to get reset-gpios\n");
|
||||
|
||||
ctx->dsi = dsi;
|
||||
mipi_dsi_set_drvdata(dsi, ctx);
|
||||
|
||||
dsi->lanes = 4;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO_BURST |
|
||||
MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM;
|
||||
|
||||
drm_panel_init(&ctx->panel, dev, &nt37700f_tianma_panel_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
ctx->panel.prepare_prev_first = true;
|
||||
|
||||
ctx->panel.backlight = nt37700f_tianma_create_backlight(dsi);
|
||||
if (IS_ERR(ctx->panel.backlight))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
|
||||
"Failed to create backlight\n");
|
||||
|
||||
drm_panel_add(&ctx->panel);
|
||||
|
||||
ret = mipi_dsi_attach(dsi);
|
||||
if (ret < 0) {
|
||||
drm_panel_remove(&ctx->panel);
|
||||
return dev_err_probe(dev, ret, "Failed to attach to DSI host\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nt37700f_tianma_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct nt37700f_tianma *ctx = mipi_dsi_get_drvdata(dsi);
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_detach(dsi);
|
||||
if (ret < 0)
|
||||
dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
|
||||
|
||||
drm_panel_remove(&ctx->panel);
|
||||
}
|
||||
|
||||
static const struct of_device_id nt37700f_tianma_of_match[] = {
|
||||
{ .compatible = "novatek,nt37700f" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, nt37700f_tianma_of_match);
|
||||
|
||||
static struct mipi_dsi_driver nt37700f_tianma_driver = {
|
||||
.probe = nt37700f_tianma_probe,
|
||||
.remove = nt37700f_tianma_remove,
|
||||
.driver = {
|
||||
.name = "panel-novatek-nt37700f",
|
||||
.of_match_table = nt37700f_tianma_of_match,
|
||||
},
|
||||
};
|
||||
module_mipi_dsi_driver(nt37700f_tianma_driver);
|
||||
|
||||
MODULE_DESCRIPTION("DRM driver for nt37700f cmd mode dsi tianma panel");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -14,6 +14,7 @@
|
|||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_panel.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
#define R61307_MACP 0xb0 /* Manufacturer CMD Protect */
|
||||
#define R61307_MACP_ON 0x03
|
||||
|
|
@ -34,8 +35,6 @@ struct renesas_r61307 {
|
|||
|
||||
struct gpio_desc *reset_gpio;
|
||||
|
||||
bool prepared;
|
||||
|
||||
bool dig_cont_adj;
|
||||
bool inversion;
|
||||
u32 gamma;
|
||||
|
|
@ -91,9 +90,6 @@ static int renesas_r61307_prepare(struct drm_panel *panel)
|
|||
struct device *dev = &priv->dsi->dev;
|
||||
int ret;
|
||||
|
||||
if (priv->prepared)
|
||||
return 0;
|
||||
|
||||
ret = regulator_enable(priv->vcc_supply);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable vcc power supply\n");
|
||||
|
|
@ -112,7 +108,6 @@ static int renesas_r61307_prepare(struct drm_panel *panel)
|
|||
|
||||
renesas_r61307_reset(priv);
|
||||
|
||||
priv->prepared = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -155,7 +150,7 @@ static int renesas_r61307_enable(struct drm_panel *panel)
|
|||
mipi_dsi_dcs_set_display_on_multi(&ctx);
|
||||
mipi_dsi_msleep(&ctx, 50);
|
||||
|
||||
return 0;
|
||||
return ctx.accum_err;
|
||||
}
|
||||
|
||||
static int renesas_r61307_disable(struct drm_panel *panel)
|
||||
|
|
@ -167,16 +162,13 @@ static int renesas_r61307_disable(struct drm_panel *panel)
|
|||
mipi_dsi_msleep(&ctx, 100);
|
||||
mipi_dsi_dcs_enter_sleep_mode_multi(&ctx);
|
||||
|
||||
return 0;
|
||||
return ctx.accum_err;
|
||||
}
|
||||
|
||||
static int renesas_r61307_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct renesas_r61307 *priv = to_renesas_r61307(panel);
|
||||
|
||||
if (!priv->prepared)
|
||||
return 0;
|
||||
|
||||
usleep_range(10000, 11000);
|
||||
|
||||
gpiod_set_value_cansleep(priv->reset_gpio, 1);
|
||||
|
|
@ -186,7 +178,6 @@ static int renesas_r61307_unprepare(struct drm_panel *panel)
|
|||
usleep_range(2000, 3000);
|
||||
regulator_disable(priv->vcc_supply);
|
||||
|
||||
priv->prepared = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -202,25 +193,13 @@ static const struct drm_display_mode renesas_r61307_mode = {
|
|||
.vtotal = 1024 + 24 + 8 + 2,
|
||||
.width_mm = 76,
|
||||
.height_mm = 101,
|
||||
.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
|
||||
};
|
||||
|
||||
static int renesas_r61307_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev, &renesas_r61307_mode);
|
||||
if (!mode)
|
||||
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;
|
||||
return drm_connector_helper_get_modes_fixed(connector, &renesas_r61307_mode);
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs renesas_r61307_panel_funcs = {
|
||||
|
|
@ -259,7 +238,7 @@ static int renesas_r61307_probe(struct mipi_dsi_device *dsi)
|
|||
return dev_err_probe(dev, PTR_ERR(priv->reset_gpio),
|
||||
"Failed to get reset gpios\n");
|
||||
|
||||
if (device_property_read_bool(dev, "renesas,inversion"))
|
||||
if (device_property_read_bool(dev, "renesas,column-inversion"))
|
||||
priv->inversion = true;
|
||||
|
||||
if (device_property_read_bool(dev, "renesas,contrast"))
|
||||
|
|
@ -282,7 +261,7 @@ static int renesas_r61307_probe(struct mipi_dsi_device *dsi)
|
|||
|
||||
drm_panel_add(&priv->panel);
|
||||
|
||||
ret = mipi_dsi_attach(dsi);
|
||||
ret = devm_mipi_dsi_attach(dev, dsi);
|
||||
if (ret) {
|
||||
drm_panel_remove(&priv->panel);
|
||||
return dev_err_probe(dev, ret, "Failed to attach to DSI host\n");
|
||||
|
|
@ -294,11 +273,6 @@ static int renesas_r61307_probe(struct mipi_dsi_device *dsi)
|
|||
static void renesas_r61307_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct renesas_r61307 *priv = mipi_dsi_get_drvdata(dsi);
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_detach(dsi);
|
||||
if (ret)
|
||||
dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
|
||||
|
||||
drm_panel_remove(&priv->panel);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_panel.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
#define R69328_MACP 0xb0 /* Manufacturer Access CMD Protect */
|
||||
#define R69328_MACP_ON 0x03
|
||||
|
|
@ -32,8 +33,6 @@ struct renesas_r69328 {
|
|||
struct regulator *vdd_supply;
|
||||
struct regulator *vddio_supply;
|
||||
struct gpio_desc *reset_gpio;
|
||||
|
||||
bool prepared;
|
||||
};
|
||||
|
||||
static inline struct renesas_r69328 *to_renesas_r69328(struct drm_panel *panel)
|
||||
|
|
@ -55,9 +54,6 @@ static int renesas_r69328_prepare(struct drm_panel *panel)
|
|||
struct device *dev = &priv->dsi->dev;
|
||||
int ret;
|
||||
|
||||
if (priv->prepared)
|
||||
return 0;
|
||||
|
||||
ret = regulator_enable(priv->vdd_supply);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable vdd power supply\n");
|
||||
|
|
@ -76,7 +72,6 @@ static int renesas_r69328_prepare(struct drm_panel *panel)
|
|||
|
||||
renesas_r69328_reset(priv);
|
||||
|
||||
priv->prepared = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -122,7 +117,7 @@ static int renesas_r69328_enable(struct drm_panel *panel)
|
|||
mipi_dsi_dcs_set_display_on_multi(&ctx);
|
||||
mipi_dsi_msleep(&ctx, 50);
|
||||
|
||||
return 0;
|
||||
return ctx.accum_err;
|
||||
}
|
||||
|
||||
static int renesas_r69328_disable(struct drm_panel *panel)
|
||||
|
|
@ -134,16 +129,13 @@ static int renesas_r69328_disable(struct drm_panel *panel)
|
|||
mipi_dsi_msleep(&ctx, 60);
|
||||
mipi_dsi_dcs_enter_sleep_mode_multi(&ctx);
|
||||
|
||||
return 0;
|
||||
return ctx.accum_err;
|
||||
}
|
||||
|
||||
static int renesas_r69328_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct renesas_r69328 *priv = to_renesas_r69328(panel);
|
||||
|
||||
if (!priv->prepared)
|
||||
return 0;
|
||||
|
||||
gpiod_set_value_cansleep(priv->reset_gpio, 1);
|
||||
|
||||
usleep_range(5000, 6000);
|
||||
|
|
@ -151,7 +143,6 @@ static int renesas_r69328_unprepare(struct drm_panel *panel)
|
|||
regulator_disable(priv->vddio_supply);
|
||||
regulator_disable(priv->vdd_supply);
|
||||
|
||||
priv->prepared = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -167,25 +158,13 @@ static const struct drm_display_mode renesas_r69328_mode = {
|
|||
.vtotal = 1280 + 6 + 3 + 1,
|
||||
.width_mm = 59,
|
||||
.height_mm = 105,
|
||||
.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
|
||||
};
|
||||
|
||||
static int renesas_r69328_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev, &renesas_r69328_mode);
|
||||
if (!mode)
|
||||
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;
|
||||
return drm_connector_helper_get_modes_fixed(connector, &renesas_r69328_mode);
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs renesas_r69328_panel_funcs = {
|
||||
|
|
@ -238,7 +217,7 @@ static int renesas_r69328_probe(struct mipi_dsi_device *dsi)
|
|||
|
||||
drm_panel_add(&priv->panel);
|
||||
|
||||
ret = mipi_dsi_attach(dsi);
|
||||
ret = devm_mipi_dsi_attach(dev, dsi);
|
||||
if (ret) {
|
||||
drm_panel_remove(&priv->panel);
|
||||
return dev_err_probe(dev, ret, "Failed to attach to DSI host\n");
|
||||
|
|
@ -250,11 +229,6 @@ static int renesas_r69328_probe(struct mipi_dsi_device *dsi)
|
|||
static void renesas_r69328_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct renesas_r69328 *priv = mipi_dsi_get_drvdata(dsi);
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_detach(dsi);
|
||||
if (ret)
|
||||
dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
|
||||
|
||||
drm_panel_remove(&priv->panel);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2096,6 +2096,35 @@ static const struct panel_desc edt_et057090dhu = {
|
|||
.connector_type = DRM_MODE_CONNECTOR_DPI,
|
||||
};
|
||||
|
||||
static const struct display_timing edt_et057023udba_timing = {
|
||||
.pixelclock = { 23200000, 24190000, 39640000 },
|
||||
.hactive = { 640, 640, 640 },
|
||||
.hfront_porch = { 20, 40, 200 },
|
||||
.hback_porch = { 87, 40, 1 },
|
||||
.hsync_len = { 1, 48, 87 },
|
||||
.vactive = { 480, 480, 480 },
|
||||
.vfront_porch = { 5, 13, 200 },
|
||||
.vback_porch = { 31, 31, 29 },
|
||||
.vsync_len = { 1, 1, 3 },
|
||||
.flags = DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_HSYNC_LOW |
|
||||
DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE |
|
||||
DISPLAY_FLAGS_SYNC_POSEDGE,
|
||||
};
|
||||
|
||||
static const struct panel_desc edt_et057023udba = {
|
||||
.timings = &edt_et057023udba_timing,
|
||||
.num_timings = 1,
|
||||
.bpc = 8,
|
||||
.size = {
|
||||
.width = 115,
|
||||
.height = 86,
|
||||
},
|
||||
.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
|
||||
.bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE |
|
||||
DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE,
|
||||
.connector_type = DRM_MODE_CONNECTOR_DPI,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode edt_etm0700g0dh6_mode = {
|
||||
.clock = 33260,
|
||||
.hdisplay = 800,
|
||||
|
|
@ -4046,6 +4075,33 @@ static const struct panel_desc powertip_ph800480t013_idf02 = {
|
|||
.connector_type = DRM_MODE_CONNECTOR_DPI,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode powertip_ph800480t032_zhc19_mode = {
|
||||
.clock = 27200,
|
||||
.hdisplay = 800,
|
||||
.hsync_start = 800 + 52,
|
||||
.hsync_end = 800 + 52 + 2,
|
||||
.htotal = 800 + 52 + 2 + 44,
|
||||
.vdisplay = 480,
|
||||
.vsync_start = 480 + 7,
|
||||
.vsync_end = 480 + 7 + 2,
|
||||
.vtotal = 480 + 7 + 2 + 2,
|
||||
};
|
||||
|
||||
static const struct panel_desc powertip_ph800480t032_zhc19 = {
|
||||
.modes = &powertip_ph800480t032_zhc19_mode,
|
||||
.num_modes = 1,
|
||||
.bpc = 8,
|
||||
.size = {
|
||||
.width = 152,
|
||||
.height = 91,
|
||||
},
|
||||
.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
|
||||
.bus_flags = DRM_BUS_FLAG_DE_HIGH |
|
||||
DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE |
|
||||
DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE,
|
||||
.connector_type = DRM_MODE_CONNECTOR_DPI,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode primeview_pm070wl4_mode = {
|
||||
.clock = 32000,
|
||||
.hdisplay = 800,
|
||||
|
|
@ -4976,6 +5032,33 @@ static const struct panel_desc vl050_8048nt_c01 = {
|
|||
.bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode waveshare_133inch_mode = {
|
||||
.clock = 148500,
|
||||
.hdisplay = 1920,
|
||||
.hsync_start = 1920 + 88,
|
||||
.hsync_end = 1920 + 88 + 44,
|
||||
.htotal = 1920 + 88 + 44 + 148,
|
||||
.vdisplay = 1080,
|
||||
.vsync_start = 1080 + 4,
|
||||
.vsync_end = 1080 + 4 + 5,
|
||||
.vtotal = 1080 + 4 + 5 + 36,
|
||||
.flags = DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_PHSYNC,
|
||||
};
|
||||
|
||||
static const struct panel_desc waveshare_133inch = {
|
||||
.modes = &waveshare_133inch_mode,
|
||||
.num_modes = 1,
|
||||
.bpc = 8,
|
||||
.size = {
|
||||
.width = 293,
|
||||
.height = 163,
|
||||
},
|
||||
.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
|
||||
.connector_type = DRM_MODE_CONNECTOR_DPI,
|
||||
.bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE |
|
||||
DRM_BUS_FLAG_SYNC_SAMPLE_POSEDGE,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode winstar_wf35ltiacd_mode = {
|
||||
.clock = 6410,
|
||||
.hdisplay = 320,
|
||||
|
|
@ -5225,6 +5308,9 @@ static const struct of_device_id platform_of_match[] = {
|
|||
}, {
|
||||
.compatible = "edt,etm0430g0dh6",
|
||||
.data = &edt_etm0430g0dh6,
|
||||
}, {
|
||||
.compatible = "edt,et057023udba",
|
||||
.data = &edt_et057023udba,
|
||||
}, {
|
||||
.compatible = "edt,et057090dhu",
|
||||
.data = &edt_et057090dhu,
|
||||
|
|
@ -5456,6 +5542,9 @@ static const struct of_device_id platform_of_match[] = {
|
|||
}, {
|
||||
.compatible = "powertip,ph800480t013-idf02",
|
||||
.data = &powertip_ph800480t013_idf02,
|
||||
}, {
|
||||
.compatible = "powertip,ph800480t032-zhc19",
|
||||
.data = &powertip_ph800480t032_zhc19,
|
||||
}, {
|
||||
.compatible = "primeview,pm070wl4",
|
||||
.data = &primeview_pm070wl4,
|
||||
|
|
@ -5573,6 +5662,9 @@ static const struct of_device_id platform_of_match[] = {
|
|||
}, {
|
||||
.compatible = "vxt,vl050-8048nt-c01",
|
||||
.data = &vl050_8048nt_c01,
|
||||
}, {
|
||||
.compatible = "waveshare,13.3inch-panel",
|
||||
.data = &waveshare_133inch,
|
||||
}, {
|
||||
.compatible = "winstar,wf35ltiacd",
|
||||
.data = &winstar_wf35ltiacd,
|
||||
|
|
|
|||
|
|
@ -3916,7 +3916,7 @@ static void job_release(struct kref *ref)
|
|||
if (job->base.s_fence)
|
||||
drm_sched_job_cleanup(&job->base);
|
||||
|
||||
if (job->done_fence && job->done_fence->ops)
|
||||
if (dma_fence_was_initialized(job->done_fence))
|
||||
dma_fence_put(job->done_fence);
|
||||
else
|
||||
dma_fence_free(job->done_fence);
|
||||
|
|
|
|||
|
|
@ -222,10 +222,8 @@ static void ttm_bo_flush_all_fences(struct ttm_buffer_object *bo)
|
|||
struct dma_fence *fence;
|
||||
|
||||
dma_resv_iter_begin(&cursor, resv, DMA_RESV_USAGE_BOOKKEEP);
|
||||
dma_resv_for_each_fence_unlocked(&cursor, fence) {
|
||||
if (!fence->ops->signaled)
|
||||
dma_fence_enable_sw_signaling(fence);
|
||||
}
|
||||
dma_resv_for_each_fence_unlocked(&cursor, fence)
|
||||
dma_fence_enable_sw_signaling(fence);
|
||||
dma_resv_iter_end(&cursor);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2449,17 +2449,23 @@ static int vc4_hdmi_hotplug_init(struct vc4_hdmi *vc4_hdmi)
|
|||
int ret;
|
||||
|
||||
if (vc4_hdmi->variant->external_irq_controller) {
|
||||
unsigned int hpd_con = platform_get_irq_byname(pdev, "hpd-connected");
|
||||
unsigned int hpd_rm = platform_get_irq_byname(pdev, "hpd-removed");
|
||||
int hpd = platform_get_irq_byname(pdev, "hpd-connected");
|
||||
|
||||
ret = devm_request_threaded_irq(&pdev->dev, hpd_con,
|
||||
if (hpd < 0)
|
||||
return hpd;
|
||||
|
||||
ret = devm_request_threaded_irq(&pdev->dev, hpd,
|
||||
NULL,
|
||||
vc4_hdmi_hpd_irq_thread, IRQF_ONESHOT,
|
||||
"vc4 hdmi hpd connected", vc4_hdmi);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_request_threaded_irq(&pdev->dev, hpd_rm,
|
||||
hpd = platform_get_irq_byname(pdev, "hpd-removed");
|
||||
if (hpd < 0)
|
||||
return hpd;
|
||||
|
||||
ret = devm_request_threaded_irq(&pdev->dev, hpd,
|
||||
NULL,
|
||||
vc4_hdmi_hpd_irq_thread, IRQF_ONESHOT,
|
||||
"vc4 hdmi hpd disconnected", vc4_hdmi);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,170 @@ static inline u64 get_size(int order, u64 chunk_size)
|
|||
return (1 << order) * chunk_size;
|
||||
}
|
||||
|
||||
static void gpu_test_buddy_subtree_offset_alignment_stress(struct kunit *test)
|
||||
{
|
||||
struct gpu_buddy_block *block;
|
||||
struct rb_node *node = NULL;
|
||||
const u64 mm_size = SZ_2M;
|
||||
const u64 alignments[] = {
|
||||
SZ_1M,
|
||||
SZ_512K,
|
||||
SZ_256K,
|
||||
SZ_128K,
|
||||
SZ_64K,
|
||||
SZ_32K,
|
||||
SZ_16K,
|
||||
SZ_8K,
|
||||
};
|
||||
struct list_head allocated[ARRAY_SIZE(alignments)];
|
||||
unsigned int i, max_subtree_align = 0;
|
||||
int ret, tree, order;
|
||||
struct gpu_buddy mm;
|
||||
|
||||
KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, SZ_4K),
|
||||
"buddy_init failed\n");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(allocated); i++)
|
||||
INIT_LIST_HEAD(&allocated[i]);
|
||||
|
||||
/*
|
||||
* Exercise subtree_max_alignment tracking by allocating blocks with descending
|
||||
* alignment constraints and freeing them in reverse order. This verifies that
|
||||
* free-tree augmentation correctly propagates the maximum offset alignment
|
||||
* present in each subtree at every stage.
|
||||
*/
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(alignments); i++) {
|
||||
struct gpu_buddy_block *root = NULL;
|
||||
unsigned int expected;
|
||||
u64 align;
|
||||
|
||||
align = alignments[i];
|
||||
expected = ilog2(align) - 1;
|
||||
|
||||
for (;;) {
|
||||
ret = gpu_buddy_alloc_blocks(&mm,
|
||||
0, mm_size,
|
||||
SZ_4K, align,
|
||||
&allocated[i],
|
||||
0);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
block = list_last_entry(&allocated[i],
|
||||
struct gpu_buddy_block,
|
||||
link);
|
||||
KUNIT_EXPECT_TRUE(test, IS_ALIGNED(gpu_buddy_block_offset(block), align));
|
||||
}
|
||||
|
||||
for (order = mm.max_order; order >= 0 && !root; order--) {
|
||||
for (tree = 0; tree < 2; tree++) {
|
||||
node = mm.free_trees[tree][order].rb_node;
|
||||
if (node) {
|
||||
root = container_of(node,
|
||||
struct gpu_buddy_block,
|
||||
rb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KUNIT_ASSERT_NOT_NULL(test, root);
|
||||
KUNIT_EXPECT_EQ(test, root->subtree_max_alignment, expected);
|
||||
}
|
||||
|
||||
for (i = ARRAY_SIZE(alignments); i-- > 0; ) {
|
||||
gpu_buddy_free_list(&mm, &allocated[i], 0);
|
||||
|
||||
for (order = 0; order <= mm.max_order; order++) {
|
||||
for (tree = 0; tree < 2; tree++) {
|
||||
node = mm.free_trees[tree][order].rb_node;
|
||||
if (!node)
|
||||
continue;
|
||||
|
||||
block = container_of(node, struct gpu_buddy_block, rb);
|
||||
max_subtree_align = max(max_subtree_align,
|
||||
block->subtree_max_alignment);
|
||||
}
|
||||
}
|
||||
|
||||
KUNIT_EXPECT_GE(test, max_subtree_align, ilog2(alignments[i]));
|
||||
}
|
||||
|
||||
gpu_buddy_fini(&mm);
|
||||
}
|
||||
|
||||
static void gpu_test_buddy_offset_aligned_allocation(struct kunit *test)
|
||||
{
|
||||
struct gpu_buddy_block *block, *tmp;
|
||||
int num_blocks, i, count = 0;
|
||||
LIST_HEAD(allocated);
|
||||
struct gpu_buddy mm;
|
||||
u64 mm_size = SZ_4M;
|
||||
LIST_HEAD(freed);
|
||||
|
||||
KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, SZ_4K),
|
||||
"buddy_init failed\n");
|
||||
|
||||
num_blocks = mm_size / SZ_256K;
|
||||
/*
|
||||
* Allocate multiple sizes under a fixed offset alignment.
|
||||
* Ensures alignment handling is independent of allocation size and
|
||||
* exercises subtree max-alignment pruning for small requests.
|
||||
*/
|
||||
for (i = 0; i < num_blocks; i++)
|
||||
KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, SZ_8K, SZ_256K,
|
||||
&allocated, 0),
|
||||
"buddy_alloc hit an error size=%u\n", SZ_8K);
|
||||
|
||||
list_for_each_entry(block, &allocated, link) {
|
||||
/* Ensure the allocated block uses the expected 8 KB size */
|
||||
KUNIT_EXPECT_EQ(test, gpu_buddy_block_size(&mm, block), SZ_8K);
|
||||
/* Ensure the block starts at a 256 KB-aligned offset for proper alignment */
|
||||
KUNIT_EXPECT_TRUE(test, IS_ALIGNED(gpu_buddy_block_offset(block), SZ_256K));
|
||||
}
|
||||
gpu_buddy_free_list(&mm, &allocated, 0);
|
||||
|
||||
for (i = 0; i < num_blocks; i++)
|
||||
KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, SZ_16K, SZ_256K,
|
||||
&allocated, 0),
|
||||
"buddy_alloc hit an error size=%u\n", SZ_16K);
|
||||
|
||||
list_for_each_entry(block, &allocated, link) {
|
||||
/* Ensure the allocated block uses the expected 16 KB size */
|
||||
KUNIT_EXPECT_EQ(test, gpu_buddy_block_size(&mm, block), SZ_16K);
|
||||
/* Ensure the block starts at a 256 KB-aligned offset for proper alignment */
|
||||
KUNIT_EXPECT_TRUE(test, IS_ALIGNED(gpu_buddy_block_offset(block), SZ_256K));
|
||||
}
|
||||
|
||||
/*
|
||||
* Free alternating aligned blocks to introduce fragmentation.
|
||||
* Ensures offset-aligned allocations remain valid after frees and
|
||||
* verifies subtree max-alignment metadata is correctly maintained.
|
||||
*/
|
||||
list_for_each_entry_safe(block, tmp, &allocated, link) {
|
||||
if (count % 2 == 0)
|
||||
list_move_tail(&block->link, &freed);
|
||||
count++;
|
||||
}
|
||||
gpu_buddy_free_list(&mm, &freed, 0);
|
||||
|
||||
for (i = 0; i < num_blocks / 2; i++)
|
||||
KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, SZ_16K, SZ_256K,
|
||||
&allocated, 0),
|
||||
"buddy_alloc hit an error size=%u\n", SZ_16K);
|
||||
|
||||
/*
|
||||
* Allocate with offset alignment after all slots are used; must fail.
|
||||
* Confirms that no aligned offsets remain.
|
||||
*/
|
||||
KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, SZ_16K, SZ_256K,
|
||||
&allocated, 0),
|
||||
"buddy_alloc hit an error size=%u\n", SZ_16K);
|
||||
gpu_buddy_free_list(&mm, &allocated, 0);
|
||||
gpu_buddy_fini(&mm);
|
||||
}
|
||||
|
||||
static void gpu_test_buddy_fragmentation_performance(struct kunit *test)
|
||||
{
|
||||
struct gpu_buddy_block *block, *tmp;
|
||||
|
|
@ -362,6 +526,332 @@ static void gpu_test_buddy_alloc_range_bias(struct kunit *test)
|
|||
gpu_buddy_fini(&mm);
|
||||
}
|
||||
|
||||
static void gpu_test_buddy_alloc_range(struct kunit *test)
|
||||
{
|
||||
GPU_RND_STATE(prng, random_seed);
|
||||
struct gpu_buddy_block *block;
|
||||
struct gpu_buddy mm;
|
||||
u32 mm_size, total;
|
||||
LIST_HEAD(blocks);
|
||||
LIST_HEAD(tmp);
|
||||
u32 ps = SZ_4K;
|
||||
int ret;
|
||||
|
||||
mm_size = SZ_16M;
|
||||
|
||||
KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, ps),
|
||||
"buddy_init failed\n");
|
||||
|
||||
/*
|
||||
* Basic exact-range allocation.
|
||||
* Allocate the entire mm as one exact range (start + size == end).
|
||||
* This is the simplest case exercising __gpu_buddy_alloc_range.
|
||||
*/
|
||||
ret = gpu_buddy_alloc_blocks(&mm, 0, mm_size, mm_size, ps, &blocks, 0);
|
||||
KUNIT_ASSERT_EQ_MSG(test, ret, 0,
|
||||
"exact-range alloc of full mm failed\n");
|
||||
|
||||
total = 0;
|
||||
list_for_each_entry(block, &blocks, link) {
|
||||
u64 offset = gpu_buddy_block_offset(block);
|
||||
u64 bsize = gpu_buddy_block_size(&mm, block);
|
||||
|
||||
KUNIT_EXPECT_TRUE_MSG(test, offset + bsize <= (u64)mm_size,
|
||||
"block [%llx, %llx) outside mm\n", offset, offset + bsize);
|
||||
total += (u32)bsize;
|
||||
}
|
||||
KUNIT_EXPECT_EQ(test, total, mm_size);
|
||||
KUNIT_EXPECT_EQ(test, mm.avail, 0ULL);
|
||||
|
||||
/* Full mm should be exhausted */
|
||||
ret = gpu_buddy_alloc_blocks(&mm, 0, ps, ps, ps, &tmp, 0);
|
||||
KUNIT_EXPECT_NE_MSG(test, ret, 0, "alloc should fail when mm is full\n");
|
||||
|
||||
gpu_buddy_free_list(&mm, &blocks, 0);
|
||||
KUNIT_EXPECT_EQ(test, mm.avail, (u64)mm_size);
|
||||
gpu_buddy_fini(&mm);
|
||||
|
||||
/*
|
||||
* Exact-range allocation of sub-ranges.
|
||||
* Split the mm into four equal quarters and allocate each as an exact
|
||||
* range. Validates splitting and non-overlapping exact allocations.
|
||||
*/
|
||||
KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
|
||||
|
||||
{
|
||||
u32 quarter = mm_size / 4;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
u32 start = i * quarter;
|
||||
u32 end = start + quarter;
|
||||
|
||||
ret = gpu_buddy_alloc_blocks(&mm, start, end, quarter, ps, &blocks, 0);
|
||||
KUNIT_ASSERT_EQ_MSG(test, ret, 0,
|
||||
"exact-range alloc quarter %d [%x, %x) failed\n",
|
||||
i, start, end);
|
||||
}
|
||||
KUNIT_EXPECT_EQ(test, mm.avail, 0ULL);
|
||||
gpu_buddy_free_list(&mm, &blocks, 0);
|
||||
}
|
||||
|
||||
gpu_buddy_fini(&mm);
|
||||
|
||||
/*
|
||||
* Minimum chunk-size exact range at various offsets.
|
||||
* Allocate single-page exact ranges at the start, middle and end.
|
||||
*/
|
||||
KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
|
||||
|
||||
ret = gpu_buddy_alloc_blocks(&mm, 0, ps, ps, ps, &blocks, 0);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
ret = gpu_buddy_alloc_blocks(&mm, mm_size / 2, mm_size / 2 + ps, ps, ps, &blocks, 0);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
ret = gpu_buddy_alloc_blocks(&mm, mm_size - ps, mm_size, ps, ps, &blocks, 0);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
total = 0;
|
||||
list_for_each_entry(block, &blocks, link)
|
||||
total += (u32)gpu_buddy_block_size(&mm, block);
|
||||
KUNIT_EXPECT_EQ(test, total, 3 * ps);
|
||||
|
||||
gpu_buddy_free_list(&mm, &blocks, 0);
|
||||
gpu_buddy_fini(&mm);
|
||||
|
||||
/*
|
||||
* Non power-of-two mm size (multiple roots).
|
||||
* Exact-range allocations that span root boundaries must still work.
|
||||
*/
|
||||
mm_size = SZ_4M + SZ_2M + SZ_1M; /* 7 MiB, three roots */
|
||||
|
||||
KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
|
||||
KUNIT_EXPECT_GT(test, mm.n_roots, 1U);
|
||||
|
||||
/* Allocate first 4M root exactly */
|
||||
ret = gpu_buddy_alloc_blocks(&mm, 0, SZ_4M, SZ_4M, ps, &blocks, 0);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
/* Allocate second root (4M-6M) exactly */
|
||||
ret = gpu_buddy_alloc_blocks(&mm, SZ_4M, SZ_4M + SZ_2M, SZ_2M, ps, &blocks, 0);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
/* Allocate third root (6M-7M) exactly */
|
||||
ret = gpu_buddy_alloc_blocks(&mm, SZ_4M + SZ_2M, mm_size, SZ_1M, ps, &blocks, 0);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, mm.avail, 0ULL);
|
||||
gpu_buddy_free_list(&mm, &blocks, 0);
|
||||
|
||||
/* Cross-root exact-range: the entire non-pot mm */
|
||||
ret = gpu_buddy_alloc_blocks(&mm, 0, mm_size, mm_size, ps, &blocks, 0);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
KUNIT_EXPECT_EQ(test, mm.avail, 0ULL);
|
||||
|
||||
gpu_buddy_free_list(&mm, &blocks, 0);
|
||||
gpu_buddy_fini(&mm);
|
||||
|
||||
/*
|
||||
* Randomized exact-range allocations.
|
||||
* Divide the mm into N random-sized, contiguous, page-aligned slices
|
||||
* and allocate each as an exact range in random order.
|
||||
*/
|
||||
mm_size = SZ_16M;
|
||||
KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
|
||||
|
||||
{
|
||||
#define N_RAND_RANGES 16
|
||||
u32 ranges[N_RAND_RANGES + 1]; /* boundaries */
|
||||
u32 order_arr[N_RAND_RANGES];
|
||||
u32 remaining = mm_size;
|
||||
int i;
|
||||
|
||||
ranges[0] = 0;
|
||||
for (i = 0; i < N_RAND_RANGES - 1; i++) {
|
||||
u32 max_chunk = remaining - (N_RAND_RANGES - 1 - i) * ps;
|
||||
u32 sz = max(round_up(prandom_u32_state(&prng) % max_chunk, ps), ps);
|
||||
|
||||
ranges[i + 1] = ranges[i] + sz;
|
||||
remaining -= sz;
|
||||
}
|
||||
ranges[N_RAND_RANGES] = mm_size;
|
||||
|
||||
/* Create a random order */
|
||||
for (i = 0; i < N_RAND_RANGES; i++)
|
||||
order_arr[i] = i;
|
||||
for (i = N_RAND_RANGES - 1; i > 0; i--) {
|
||||
u32 j = prandom_u32_state(&prng) % (i + 1);
|
||||
u32 tmp_val = order_arr[i];
|
||||
|
||||
order_arr[i] = order_arr[j];
|
||||
order_arr[j] = tmp_val;
|
||||
}
|
||||
|
||||
for (i = 0; i < N_RAND_RANGES; i++) {
|
||||
u32 idx = order_arr[i];
|
||||
u32 start = ranges[idx];
|
||||
u32 end = ranges[idx + 1];
|
||||
u32 sz = end - start;
|
||||
|
||||
ret = gpu_buddy_alloc_blocks(&mm, start, end, sz, ps, &blocks, 0);
|
||||
KUNIT_ASSERT_EQ_MSG(test, ret, 0,
|
||||
"random exact-range [%x, %x) sz=%x failed\n",
|
||||
start, end, sz);
|
||||
}
|
||||
|
||||
KUNIT_EXPECT_EQ(test, mm.avail, 0ULL);
|
||||
gpu_buddy_free_list(&mm, &blocks, 0);
|
||||
#undef N_RAND_RANGES
|
||||
}
|
||||
|
||||
gpu_buddy_fini(&mm);
|
||||
|
||||
/*
|
||||
* Negative case - partially allocated range.
|
||||
* Allocate the first half, then try to exact-range allocate the full
|
||||
* mm. This must fail because the first half is already occupied.
|
||||
*/
|
||||
mm_size = SZ_16M;
|
||||
KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
|
||||
|
||||
ret = gpu_buddy_alloc_blocks(&mm, 0, mm_size / 2, mm_size / 2, ps, &blocks, 0);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
ret = gpu_buddy_alloc_blocks(&mm, 0, mm_size, mm_size, ps, &tmp, 0);
|
||||
KUNIT_EXPECT_NE_MSG(test, ret, 0,
|
||||
"exact-range alloc should fail when range is partially used\n");
|
||||
|
||||
/* Also try the already-occupied sub-range directly */
|
||||
ret = gpu_buddy_alloc_blocks(&mm, 0, mm_size / 2, mm_size / 2, ps, &tmp, 0);
|
||||
KUNIT_EXPECT_NE_MSG(test, ret, 0,
|
||||
"double alloc of same exact range should fail\n");
|
||||
|
||||
/* The free second half should still be allocatable */
|
||||
ret = gpu_buddy_alloc_blocks(&mm, mm_size / 2, mm_size, mm_size / 2, ps, &blocks, 0);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, mm.avail, 0ULL);
|
||||
gpu_buddy_free_list(&mm, &blocks, 0);
|
||||
gpu_buddy_fini(&mm);
|
||||
|
||||
/*
|
||||
* Negative case - checkerboard partial allocation.
|
||||
* Allocate every other page-sized chunk in a small mm, then try to
|
||||
* exact-range allocate a range covering two pages (one allocated, one
|
||||
* free). This must fail.
|
||||
*/
|
||||
mm_size = SZ_64K;
|
||||
KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
|
||||
|
||||
{
|
||||
u32 off;
|
||||
|
||||
for (off = 0; off < mm_size; off += 2 * ps) {
|
||||
ret = gpu_buddy_alloc_blocks(&mm, off, off + ps, ps, ps, &blocks, 0);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
}
|
||||
|
||||
/* Try exact range over a pair [allocated, free] */
|
||||
ret = gpu_buddy_alloc_blocks(&mm, 0, 2 * ps, 2 * ps, ps, &tmp, 0);
|
||||
KUNIT_EXPECT_NE_MSG(test, ret, 0,
|
||||
"exact-range over partially allocated pair should fail\n");
|
||||
|
||||
/* The free pages individually should still work */
|
||||
ret = gpu_buddy_alloc_blocks(&mm, ps, 2 * ps, ps, ps, &blocks, 0);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
gpu_buddy_free_list(&mm, &blocks, 0);
|
||||
}
|
||||
|
||||
gpu_buddy_fini(&mm);
|
||||
|
||||
/* Negative case - misaligned start/end/size */
|
||||
mm_size = SZ_16M;
|
||||
KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
|
||||
|
||||
/* start not aligned to chunk_size */
|
||||
ret = gpu_buddy_alloc_blocks(&mm, ps / 2, ps / 2 + ps, ps, ps, &tmp, 0);
|
||||
KUNIT_EXPECT_NE(test, ret, 0);
|
||||
|
||||
/* size not aligned */
|
||||
ret = gpu_buddy_alloc_blocks(&mm, 0, ps + 1, ps + 1, ps, &tmp, 0);
|
||||
KUNIT_EXPECT_NE(test, ret, 0);
|
||||
|
||||
/* end exceeds mm size */
|
||||
ret = gpu_buddy_alloc_blocks(&mm, mm_size, mm_size + ps, ps, ps, &tmp, 0);
|
||||
KUNIT_EXPECT_NE(test, ret, 0);
|
||||
|
||||
gpu_buddy_fini(&mm);
|
||||
|
||||
/*
|
||||
* Free and re-allocate the same exact range.
|
||||
* This exercises merge-on-free followed by exact-range re-split.
|
||||
*/
|
||||
mm_size = SZ_16M;
|
||||
KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
|
||||
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
ret = gpu_buddy_alloc_blocks(&mm, SZ_4M, SZ_4M + SZ_2M,
|
||||
SZ_2M, ps, &blocks, 0);
|
||||
KUNIT_ASSERT_EQ_MSG(test, ret, 0,
|
||||
"re-alloc iteration %d failed\n", i);
|
||||
|
||||
total = 0;
|
||||
list_for_each_entry(block, &blocks, link) {
|
||||
u64 offset = gpu_buddy_block_offset(block);
|
||||
u64 bsize = gpu_buddy_block_size(&mm, block);
|
||||
|
||||
KUNIT_EXPECT_GE(test, offset, (u64)SZ_4M);
|
||||
KUNIT_EXPECT_LE(test, offset + bsize, (u64)(SZ_4M + SZ_2M));
|
||||
total += (u32)bsize;
|
||||
}
|
||||
KUNIT_EXPECT_EQ(test, total, SZ_2M);
|
||||
|
||||
gpu_buddy_free_list(&mm, &blocks, 0);
|
||||
}
|
||||
|
||||
KUNIT_EXPECT_EQ(test, mm.avail, (u64)mm_size);
|
||||
}
|
||||
|
||||
gpu_buddy_fini(&mm);
|
||||
|
||||
/*
|
||||
* Various power-of-two exact ranges within a large mm.
|
||||
* Allocate non-overlapping power-of-two exact ranges at their natural
|
||||
* alignment, validating that the allocator handles different orders.
|
||||
*/
|
||||
mm_size = SZ_16M;
|
||||
KUNIT_ASSERT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
|
||||
|
||||
/* Allocate 4K at offset 0 */
|
||||
ret = gpu_buddy_alloc_blocks(&mm, 0, SZ_4K, SZ_4K, ps, &blocks, 0);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
/* Allocate 64K at offset 64K */
|
||||
ret = gpu_buddy_alloc_blocks(&mm, SZ_64K, SZ_64K + SZ_64K, SZ_64K, ps, &blocks, 0);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
/* Allocate 1M at offset 1M */
|
||||
ret = gpu_buddy_alloc_blocks(&mm, SZ_1M, SZ_1M + SZ_1M, SZ_1M, ps, &blocks, 0);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
/* Allocate 4M at offset 4M */
|
||||
ret = gpu_buddy_alloc_blocks(&mm, SZ_4M, SZ_4M + SZ_4M, SZ_4M, ps, &blocks, 0);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
total = 0;
|
||||
list_for_each_entry(block, &blocks, link)
|
||||
total += (u32)gpu_buddy_block_size(&mm, block);
|
||||
KUNIT_EXPECT_EQ(test, total, SZ_4K + SZ_64K + SZ_1M + SZ_4M);
|
||||
|
||||
gpu_buddy_free_list(&mm, &blocks, 0);
|
||||
gpu_buddy_fini(&mm);
|
||||
}
|
||||
|
||||
static void gpu_test_buddy_alloc_clear(struct kunit *test)
|
||||
{
|
||||
unsigned long n_pages, total, i = 0;
|
||||
|
|
@ -909,9 +1399,12 @@ static struct kunit_case gpu_buddy_tests[] = {
|
|||
KUNIT_CASE(gpu_test_buddy_alloc_pathological),
|
||||
KUNIT_CASE(gpu_test_buddy_alloc_contiguous),
|
||||
KUNIT_CASE(gpu_test_buddy_alloc_clear),
|
||||
KUNIT_CASE(gpu_test_buddy_alloc_range),
|
||||
KUNIT_CASE(gpu_test_buddy_alloc_range_bias),
|
||||
KUNIT_CASE_SLOW(gpu_test_buddy_fragmentation_performance),
|
||||
KUNIT_CASE(gpu_test_buddy_alloc_exceeds_max_order),
|
||||
KUNIT_CASE(gpu_test_buddy_offset_aligned_allocation),
|
||||
KUNIT_CASE(gpu_test_buddy_subtree_offset_alignment_stress),
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/rbtree.h>
|
||||
#include <linux/rbtree_augmented.h>
|
||||
|
||||
/**
|
||||
* GPU_BUDDY_RANGE_ALLOCATION - Allocate within a specific address range
|
||||
|
|
@ -128,6 +129,7 @@ struct gpu_buddy_block {
|
|||
};
|
||||
/* private: */
|
||||
struct list_head tmp_link;
|
||||
unsigned int subtree_max_alignment;
|
||||
};
|
||||
|
||||
/* Order-zero must be at least SZ_4K */
|
||||
|
|
|
|||
|
|
@ -353,7 +353,8 @@ struct amdxdna_drm_query_clock_metadata {
|
|||
};
|
||||
|
||||
enum amdxdna_sensor_type {
|
||||
AMDXDNA_SENSOR_TYPE_POWER
|
||||
AMDXDNA_SENSOR_TYPE_POWER,
|
||||
AMDXDNA_SENSOR_TYPE_COLUMN_UTILIZATION
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user