mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 21:38:32 +08:00
drm-misc-next for 5.8:
UAPI Changes: Cross-subsystem Changes: * MAINTAINERS: restore alphabetical order; update cirrus driver * Dcomuentation: document visionix, chronteli, ite vendor prefices; update documentation for Chrontel CH7033, IT6505, IVO, BOE, Panasonic, Chunghwa, AUO bindings; convert dw_mipi_dsi.txt to YAML; remove todo item for drm_display_mode.hsync removal; Core Changes: * drm: add devm_drm_dev_alloc() for managed allocations of drm_device; use DRM_MODESET_LOCK_ALL_*() in mode-object code; remove drm_display_mode.hsync; small cleanups of unused variables, compiler warnings and static functions * drm/client: dual-lincensing: GPL-2.0 or MIT * drm/mm: optimize tree searches in rb_hole_addr() Driver Changes: * drm/{many}: use devm_drm_dev_alloc(); don't use drm_device.dev_private * drm/ast: don't double-assign to drm_crtc_funcs.set_config; drop drm_connector_register() * drm/bochs: drop drm_connector_register() * drm/bridge: add support for Chrontel ch7033; fix stack usage with old gccs; return error pointer in drm_panel_bridge_add() * drm/cirrus: Move to tiny * drm/dp_mst: don't use 2nd sideband tx slot; revert "Remove single tx msg restriction" * drm/lima: support runtime PM; * drm/meson: limit modes wrt chipset * drm/panel: add support for Visionox rm69299; fix clock on boe-tv101wum-n16; fix panel type for AUO G101EVN10; add support for Ivo M133NFW4 R0; add support for BOE NV133FHM-N61; add support for AUO G121EAN01.4, G156XTN01.0, G190EAN01 * drm/pl111: improve vexpress init; fix module auto-loading * drm/stm: read number of endpoints from device tree * drm/vboxvideo: use managed PCI functions; drop DRM_MTRR_WC * drm/vkms: fix use-after-free in vkms_gem_create(); enable cursor support by default * fbdev: use boolean values in several drivers * fbdev/controlfb: fix COMPILE_TEST * fbdev/w100fb: fix double-free bug -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEchf7rIzpz2NEoWjlaA3BHVMLeiMFAl6ztuYACgkQaA3BHVML eiMWaAgAvYpXvBqBfE/5jOTa1zWQUX9VMbmMDUqSAgec5r/HVHjmlbsDWkLff2XG rH7T2shMNJwluoCleHfRFYUfyUWMmXoMgri1elnf4EgddmekLZ6vNQjtAYMRFUfL 7VegcFw5D5Z28uxK5YGnaaSQob34LvD8UTgvnCVfDQzCjcEzGYi1d9XELm7kTHje dF2FOWPeF8FTqP0XHM8RrHNXW/pUPy9qErpmb2bWYBQp7ebkI2Q4p6IZIpRQm757 bnKPIdMEcy4BWMk1xtzjEYEb4bGSZhozJUWKFwpm/AHNvTrQCt9hn0GSVrXiqBcR UKb42BRxEVR29C/4n10pUcnnQmmi+Q== =yzZ9 -----END PGP SIGNATURE----- Merge tag 'drm-misc-next-2020-05-07' of git://anongit.freedesktop.org/drm/drm-misc into drm-next drm-misc-next for 5.8: UAPI Changes: Cross-subsystem Changes: * MAINTAINERS: restore alphabetical order; update cirrus driver * Dcomuentation: document visionix, chronteli, ite vendor prefices; update documentation for Chrontel CH7033, IT6505, IVO, BOE, Panasonic, Chunghwa, AUO bindings; convert dw_mipi_dsi.txt to YAML; remove todo item for drm_display_mode.hsync removal; Core Changes: * drm: add devm_drm_dev_alloc() for managed allocations of drm_device; use DRM_MODESET_LOCK_ALL_*() in mode-object code; remove drm_display_mode.hsync; small cleanups of unused variables, compiler warnings and static functions * drm/client: dual-lincensing: GPL-2.0 or MIT * drm/mm: optimize tree searches in rb_hole_addr() Driver Changes: * drm/{many}: use devm_drm_dev_alloc(); don't use drm_device.dev_private * drm/ast: don't double-assign to drm_crtc_funcs.set_config; drop drm_connector_register() * drm/bochs: drop drm_connector_register() * drm/bridge: add support for Chrontel ch7033; fix stack usage with old gccs; return error pointer in drm_panel_bridge_add() * drm/cirrus: Move to tiny * drm/dp_mst: don't use 2nd sideband tx slot; revert "Remove single tx msg restriction" * drm/lima: support runtime PM; * drm/meson: limit modes wrt chipset * drm/panel: add support for Visionox rm69299; fix clock on boe-tv101wum-n16; fix panel type for AUO G101EVN10; add support for Ivo M133NFW4 R0; add support for BOE NV133FHM-N61; add support for AUO G121EAN01.4, G156XTN01.0, G190EAN01 * drm/pl111: improve vexpress init; fix module auto-loading * drm/stm: read number of endpoints from device tree * drm/vboxvideo: use managed PCI functions; drop DRM_MTRR_WC * drm/vkms: fix use-after-free in vkms_gem_create(); enable cursor support by default * fbdev: use boolean values in several drivers * fbdev/controlfb: fix COMPILE_TEST * fbdev/w100fb: fix double-free bug Signed-off-by: Dave Airlie <airlied@redhat.com> From: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/20200507072503.GA10979@linux-uq9g
This commit is contained in:
commit
3fd911b69b
@ -0,0 +1,77 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
# Copyright (C) 2019,2020 Lubomir Rintel <lkundrak@v3.sk>
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/bridge/chrontel,ch7033.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Chrontel CH7033 Video Encoder Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Lubomir Rintel <lkundrak@v3.sk>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: chrontel,ch7033
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
description: I2C address of the device
|
||||
|
||||
ports:
|
||||
type: object
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
type: object
|
||||
description: |
|
||||
Video port for RGB input.
|
||||
|
||||
port@1:
|
||||
type: object
|
||||
description: |
|
||||
DVI port, should be connected to a node compatible with the
|
||||
dvi-connector binding.
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- ports
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
vga-dvi-encoder@76 {
|
||||
compatible = "chrontel,ch7033";
|
||||
reg = <0x76>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
endpoint {
|
||||
remote-endpoint = <&lcd0_rgb_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
endpoint {
|
||||
remote-endpoint = <&dvi_in>;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
};
|
@ -1,32 +0,0 @@
|
||||
Synopsys DesignWare MIPI DSI host controller
|
||||
============================================
|
||||
|
||||
This document defines device tree properties for the Synopsys DesignWare MIPI
|
||||
DSI host controller. It doesn't constitue a device tree binding specification
|
||||
by itself but is meant to be referenced by platform-specific device tree
|
||||
bindings.
|
||||
|
||||
When referenced from platform device tree bindings the properties defined in
|
||||
this document are defined as follows. The platform device tree bindings are
|
||||
responsible for defining whether each optional property is used or not.
|
||||
|
||||
- reg: Memory mapped base address and length of the DesignWare MIPI DSI
|
||||
host controller registers. (mandatory)
|
||||
|
||||
- clocks: References to all the clocks specified in the clock-names property
|
||||
as specified in [1]. (mandatory)
|
||||
|
||||
- clock-names:
|
||||
- "pclk" is the peripheral clock for either AHB and APB. (mandatory)
|
||||
- "px_clk" is the pixel clock for the DPI/RGB input. (optional)
|
||||
|
||||
- resets: References to all the resets specified in the reset-names property
|
||||
as specified in [2]. (optional)
|
||||
|
||||
- reset-names: string reset name, must be "apb" if used. (optional)
|
||||
|
||||
- panel or bridge node: see [3]. (mandatory)
|
||||
|
||||
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||
[2] Documentation/devicetree/bindings/reset/reset.txt
|
||||
[3] Documentation/devicetree/bindings/display/mipi-dsi-bus.txt
|
@ -0,0 +1,91 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/bridge/ite,it6505.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ITE it6505 Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Allen Chen <allen.chen@ite.com.tw>
|
||||
|
||||
description: |
|
||||
The IT6505 is a high-performance DisplayPort 1.1a transmitter,
|
||||
fully compliant with DisplayPort 1.1a, HDCP 1.3 specifications.
|
||||
The IT6505 supports color depth of up to 36 bits (12 bits/color)
|
||||
and ensures robust transmission of high-quality uncompressed video
|
||||
content, along with uncompressed and compressed digital audio content.
|
||||
|
||||
Aside from the various video output formats supported, the IT6505
|
||||
also encodes and transmits up to 8 channels of I2S digital audio,
|
||||
with sampling rate up to 192kHz and sample size up to 24 bits.
|
||||
In addition, an S/PDIF input port takes in compressed audio of up to
|
||||
192kHz frame rate.
|
||||
|
||||
Each IT6505 chip comes preprogrammed with an unique HDCP key,
|
||||
in compliance with the HDCP 1.3 standard so as to provide secure
|
||||
transmission of high-definition content. Users of the IT6505 need not
|
||||
purchase any HDCP keys or ROMs.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: ite,it6505
|
||||
|
||||
ovdd-supply:
|
||||
maxItems: 1
|
||||
description: I/O voltage
|
||||
|
||||
pwr18-supply:
|
||||
maxItems: 1
|
||||
description: core voltage
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
description: interrupt specifier of INT pin
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
description: gpio specifier of RESET pin
|
||||
|
||||
extcon:
|
||||
maxItems: 1
|
||||
description: extcon specifier for the Power Delivery
|
||||
|
||||
port:
|
||||
type: object
|
||||
description: A port node pointing to DPI host port node
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- ovdd-supply
|
||||
- pwr18-supply
|
||||
- interrupts
|
||||
- reset-gpios
|
||||
- extcon
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
dp-bridge@5c {
|
||||
compatible = "ite,it6505";
|
||||
interrupts = <152 IRQ_TYPE_EDGE_FALLING 152 0>;
|
||||
reg = <0x5c>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&it6505_pins>;
|
||||
ovdd-supply = <&mt6358_vsim1_reg>;
|
||||
pwr18-supply = <&it6505_pp18_reg>;
|
||||
reset-gpios = <&pio 179 1>;
|
||||
extcon = <&usbc_extcon>;
|
||||
|
||||
port {
|
||||
it6505_in: endpoint {
|
||||
remote-endpoint = <&dpi_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -0,0 +1,68 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/bridge/snps,dw-mipi-dsi.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Synopsys DesignWare MIPI DSI host controller
|
||||
|
||||
maintainers:
|
||||
- Philippe CORNU <philippe.cornu@st.com>
|
||||
|
||||
description: |
|
||||
This document defines device tree properties for the Synopsys DesignWare MIPI
|
||||
DSI host controller. It doesn't constitue a device tree binding specification
|
||||
by itself but is meant to be referenced by platform-specific device tree
|
||||
bindings.
|
||||
|
||||
When referenced from platform device tree bindings the properties defined in
|
||||
this document are defined as follows. The platform device tree bindings are
|
||||
responsible for defining whether each property is required or optional.
|
||||
|
||||
allOf:
|
||||
- $ref: ../dsi-controller.yaml#
|
||||
|
||||
properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Module clock
|
||||
- description: DSI bus clock for either AHB and APB
|
||||
- description: Pixel clock for the DPI/RGB input
|
||||
minItems: 2
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: ref
|
||||
- const: pclk
|
||||
- const: px_clk
|
||||
minItems: 2
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
reset-names:
|
||||
const: apb
|
||||
|
||||
ports:
|
||||
type: object
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
type: object
|
||||
description: Input node to receive pixel data.
|
||||
port@1:
|
||||
type: object
|
||||
description: DSI output node to panel.
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- clock-names
|
||||
- clocks
|
||||
- ports
|
||||
- reg
|
@ -42,6 +42,8 @@ properties:
|
||||
# One Stop Displays OSD101T2587-53TS 10.1" 1920x1200 panel
|
||||
- osddisplays,osd101t2587-53ts
|
||||
# Panasonic 10" WUXGA TFT LCD panel
|
||||
- panasonic,vvx10f004b00
|
||||
# Panasonic 10" WUXGA TFT LCD panel
|
||||
- panasonic,vvx10f034n00
|
||||
|
||||
reg:
|
||||
|
@ -53,10 +53,16 @@ properties:
|
||||
- auo,g101evn010
|
||||
# AU Optronics Corporation 10.4" (800x600) color TFT LCD panel
|
||||
- auo,g104sn02
|
||||
# AU Optronics Corporation 12.1" (1280x800) TFT LCD panel
|
||||
- auo,g121ean01
|
||||
# AU Optronics Corporation 13.3" FHD (1920x1080) TFT LCD panel
|
||||
- auo,g133han01
|
||||
# AU Optronics Corporation 15.6" (1366x768) TFT LCD panel
|
||||
- auo,g156xtn01
|
||||
# AU Optronics Corporation 18.5" FHD (1920x1080) TFT LCD panel
|
||||
- auo,g185han01
|
||||
# AU Optronics Corporation 19.0" (1280x1024) TFT LCD panel
|
||||
- auo,g190ean01
|
||||
# AU Optronics Corporation 31.5" FHD (1920x1080) TFT LCD panel
|
||||
- auo,p320hvn03
|
||||
# AU Optronics Corporation 21.5" FHD (1920x1080) color TFT LCD panel
|
||||
@ -67,6 +73,8 @@ properties:
|
||||
- boe,hv070wsa-100
|
||||
# BOE OPTOELECTRONICS TECHNOLOGY 10.1" WXGA TFT LCD panel
|
||||
- boe,nv101wxmn51
|
||||
# BOE NV133FHM-N61 13.3" FHD (1920x1080) TFT LCD Panel
|
||||
- boe,nv133fhm-n61
|
||||
# BOE NV140FHM-N49 14.0" FHD a-Si FT panel
|
||||
- boe,nv140fhmn49
|
||||
# CDTech(H.K.) Electronics Limited 4.3" 480x272 color TFT-LCD panel
|
||||
@ -78,6 +86,8 @@ properties:
|
||||
# Chunghwa Picture Tubes Ltd. 10.1" WXGA TFT LCD panel
|
||||
- chunghwa,claa101wa01a
|
||||
# Chunghwa Picture Tubes Ltd. 10.1" WXGA TFT LCD panel
|
||||
- chunghwa,claa101wb01
|
||||
# Chunghwa Picture Tubes Ltd. 10.1" WXGA TFT LCD panel
|
||||
- chunghwa,claa101wb03
|
||||
# DataImage, Inc. 7" WVGA (800x480) TFT LCD panel with 24-bit parallel interface.
|
||||
- dataimage,scf0700c48ggu18
|
||||
@ -123,6 +133,8 @@ properties:
|
||||
- hannstar,hsd100pxn1
|
||||
# Hitachi Ltd. Corporation 9" WVGA (800x480) TFT LCD panel
|
||||
- hit,tx23d38vm0caa
|
||||
# InfoVision Optoelectronics M133NWF4 R0 13.3" FHD (1920x1080) TFT LCD panel
|
||||
- ivo,m133nwf4-r0
|
||||
# Innolux AT043TN24 4.3" WQVGA TFT LCD panel
|
||||
- innolux,at043tn24
|
||||
# Innolux AT070TN92 7.0" WQVGA TFT LCD panel
|
||||
|
@ -187,6 +187,8 @@ patternProperties:
|
||||
description: ChipOne
|
||||
"^chipspark,.*":
|
||||
description: ChipSPARK
|
||||
"^chrontel,.*":
|
||||
description: Chrontel, Inc.
|
||||
"^chrp,.*":
|
||||
description: Common Hardware Reference Platform
|
||||
"^chunghwa,.*":
|
||||
@ -463,6 +465,8 @@ patternProperties:
|
||||
description: Infineon Technologies
|
||||
"^inforce,.*":
|
||||
description: Inforce Computing
|
||||
"^ivo,.*":
|
||||
description: InfoVision Optoelectronics Kunshan Co. Ltd.
|
||||
"^ingenic,.*":
|
||||
description: Ingenic Semiconductor
|
||||
"^innolux,.*":
|
||||
@ -488,7 +492,7 @@ patternProperties:
|
||||
"^issi,.*":
|
||||
description: Integrated Silicon Solutions Inc.
|
||||
"^ite,.*":
|
||||
description: ITE Tech, Inc.
|
||||
description: ITE Tech. Inc.
|
||||
"^itead,.*":
|
||||
description: ITEAD Intelligent Systems Co.Ltd
|
||||
"^iwave,.*":
|
||||
@ -1039,6 +1043,8 @@ patternProperties:
|
||||
description: Tronsmart
|
||||
"^truly,.*":
|
||||
description: Truly Semiconductors Limited
|
||||
"^visionox,.*":
|
||||
description: Visionox
|
||||
"^tsd,.*":
|
||||
description: Theobroma Systems Design und Consulting GmbH
|
||||
"^tyan,.*":
|
||||
|
@ -347,18 +347,6 @@ Contact: Sean Paul
|
||||
|
||||
Level: Starter
|
||||
|
||||
Remove drm_display_mode.hsync
|
||||
-----------------------------
|
||||
|
||||
We have drm_mode_hsync() to calculate this from hsync_start/end, since drivers
|
||||
shouldn't/don't use this, remove this member to avoid any temptations to use it
|
||||
in the future. If there is any debug code using drm_display_mode.hsync, convert
|
||||
it to use drm_mode_hsync() instead.
|
||||
|
||||
Contact: Sean Paul
|
||||
|
||||
Level: Starter
|
||||
|
||||
connector register/unregister fixes
|
||||
-----------------------------------
|
||||
|
||||
|
@ -5400,7 +5400,7 @@ L: virtualization@lists.linux-foundation.org
|
||||
S: Obsolete
|
||||
W: https://www.kraxel.org/blog/2014/10/qemu-using-cirrus-considered-harmful/
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
F: drivers/gpu/drm/cirrus/
|
||||
F: drivers/gpu/drm/tiny/cirrus.c
|
||||
|
||||
DRM DRIVER FOR QXL VIRTUAL GPU
|
||||
M: Dave Airlie <airlied@redhat.com>
|
||||
|
@ -310,8 +310,6 @@ source "drivers/gpu/drm/ast/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/mgag200/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/cirrus/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/armada/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/atmel-hlcdc/Kconfig"
|
||||
|
@ -74,7 +74,6 @@ obj-$(CONFIG_DRM_I915) += i915/
|
||||
obj-$(CONFIG_DRM_MGAG200) += mgag200/
|
||||
obj-$(CONFIG_DRM_V3D) += v3d/
|
||||
obj-$(CONFIG_DRM_VC4) += vc4/
|
||||
obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus/
|
||||
obj-$(CONFIG_DRM_SIS) += sis/
|
||||
obj-$(CONFIG_DRM_SAVAGE)+= savage/
|
||||
obj-$(CONFIG_DRM_VMWGFX)+= vmwgfx/
|
||||
|
@ -129,7 +129,7 @@ static bool dsc_line_buff_depth_from_dpcd(int dpcd_line_buff_bit_depth, int *lin
|
||||
static bool dsc_throughput_from_dpcd(int dpcd_throughput, int *throughput)
|
||||
{
|
||||
switch (dpcd_throughput) {
|
||||
case DP_DSC_THROUGHPUT_MODE_0_UPSUPPORTED:
|
||||
case DP_DSC_THROUGHPUT_MODE_0_UNSUPPORTED:
|
||||
*throughput = 0;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_170:
|
||||
|
@ -261,18 +261,16 @@ static void komeda_kms_mode_config_init(struct komeda_kms_dev *kms,
|
||||
|
||||
struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev)
|
||||
{
|
||||
struct komeda_kms_dev *kms = kzalloc(sizeof(*kms), GFP_KERNEL);
|
||||
struct komeda_kms_dev *kms;
|
||||
struct drm_device *drm;
|
||||
int err;
|
||||
|
||||
if (!kms)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
kms = devm_drm_dev_alloc(mdev->dev, &komeda_kms_driver,
|
||||
struct komeda_kms_dev, base);
|
||||
if (IS_ERR(kms))
|
||||
return kms;
|
||||
|
||||
drm = &kms->base;
|
||||
err = drm_dev_init(drm, &komeda_kms_driver, mdev->dev);
|
||||
if (err)
|
||||
goto free_kms;
|
||||
drmm_add_final_kfree(drm, kms);
|
||||
|
||||
drm->dev_private = mdev;
|
||||
|
||||
@ -329,9 +327,6 @@ cleanup_mode_config:
|
||||
drm_mode_config_cleanup(drm);
|
||||
komeda_kms_cleanup_private_objs(kms);
|
||||
drm->dev_private = NULL;
|
||||
drm_dev_put(drm);
|
||||
free_kms:
|
||||
kfree(kms);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
@ -348,5 +343,4 @@ void komeda_kms_detach(struct komeda_kms_dev *kms)
|
||||
drm_mode_config_cleanup(drm);
|
||||
komeda_kms_cleanup_private_objs(kms);
|
||||
drm->dev_private = NULL;
|
||||
drm_dev_put(drm);
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <drm/drm_simple_kms_helper.h>
|
||||
|
||||
struct aspeed_gfx {
|
||||
struct drm_device drm;
|
||||
void __iomem *base;
|
||||
struct clk *clk;
|
||||
struct reset_control *rst;
|
||||
@ -12,8 +13,8 @@ struct aspeed_gfx {
|
||||
|
||||
struct drm_simple_display_pipe pipe;
|
||||
struct drm_connector connector;
|
||||
struct drm_fbdev_cma *fbdev;
|
||||
};
|
||||
#define to_aspeed_gfx(x) container_of(x, struct aspeed_gfx, drm)
|
||||
|
||||
int aspeed_gfx_create_pipe(struct drm_device *drm);
|
||||
int aspeed_gfx_create_output(struct drm_device *drm);
|
||||
|
@ -231,7 +231,7 @@ static const uint32_t aspeed_gfx_formats[] = {
|
||||
|
||||
int aspeed_gfx_create_pipe(struct drm_device *drm)
|
||||
{
|
||||
struct aspeed_gfx *priv = drm->dev_private;
|
||||
struct aspeed_gfx *priv = to_aspeed_gfx(drm);
|
||||
|
||||
return drm_simple_display_pipe_init(drm, &priv->pipe, &aspeed_gfx_funcs,
|
||||
aspeed_gfx_formats,
|
||||
|
@ -77,7 +77,7 @@ static void aspeed_gfx_setup_mode_config(struct drm_device *drm)
|
||||
static irqreturn_t aspeed_gfx_irq_handler(int irq, void *data)
|
||||
{
|
||||
struct drm_device *drm = data;
|
||||
struct aspeed_gfx *priv = drm->dev_private;
|
||||
struct aspeed_gfx *priv = to_aspeed_gfx(drm);
|
||||
u32 reg;
|
||||
|
||||
reg = readl(priv->base + CRT_CTRL1);
|
||||
@ -96,15 +96,10 @@ static irqreturn_t aspeed_gfx_irq_handler(int irq, void *data)
|
||||
static int aspeed_gfx_load(struct drm_device *drm)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(drm->dev);
|
||||
struct aspeed_gfx *priv;
|
||||
struct aspeed_gfx *priv = to_aspeed_gfx(drm);
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
drm->dev_private = priv;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
priv->base = devm_ioremap_resource(drm->dev, res);
|
||||
if (IS_ERR(priv->base))
|
||||
@ -187,8 +182,6 @@ static void aspeed_gfx_unload(struct drm_device *drm)
|
||||
{
|
||||
drm_kms_helper_poll_fini(drm);
|
||||
drm_mode_config_cleanup(drm);
|
||||
|
||||
drm->dev_private = NULL;
|
||||
}
|
||||
|
||||
DEFINE_DRM_GEM_CMA_FOPS(fops);
|
||||
@ -216,27 +209,26 @@ static const struct of_device_id aspeed_gfx_match[] = {
|
||||
|
||||
static int aspeed_gfx_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct drm_device *drm;
|
||||
struct aspeed_gfx *priv;
|
||||
int ret;
|
||||
|
||||
drm = drm_dev_alloc(&aspeed_gfx_driver, &pdev->dev);
|
||||
if (IS_ERR(drm))
|
||||
return PTR_ERR(drm);
|
||||
priv = devm_drm_dev_alloc(&pdev->dev, &aspeed_gfx_driver,
|
||||
struct aspeed_gfx, drm);
|
||||
if (IS_ERR(priv))
|
||||
return PTR_ERR(priv);
|
||||
|
||||
ret = aspeed_gfx_load(drm);
|
||||
ret = aspeed_gfx_load(&priv->drm);
|
||||
if (ret)
|
||||
goto err_free;
|
||||
return ret;
|
||||
|
||||
ret = drm_dev_register(drm, 0);
|
||||
ret = drm_dev_register(&priv->drm, 0);
|
||||
if (ret)
|
||||
goto err_unload;
|
||||
|
||||
return 0;
|
||||
|
||||
err_unload:
|
||||
aspeed_gfx_unload(drm);
|
||||
err_free:
|
||||
drm_dev_put(drm);
|
||||
aspeed_gfx_unload(&priv->drm);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -247,7 +239,6 @@ static int aspeed_gfx_remove(struct platform_device *pdev)
|
||||
|
||||
drm_dev_unregister(drm);
|
||||
aspeed_gfx_unload(drm);
|
||||
drm_dev_put(drm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ static const struct drm_connector_funcs aspeed_gfx_connector_funcs = {
|
||||
|
||||
int aspeed_gfx_create_output(struct drm_device *drm)
|
||||
{
|
||||
struct aspeed_gfx *priv = drm->dev_private;
|
||||
struct aspeed_gfx *priv = to_aspeed_gfx(drm);
|
||||
int ret;
|
||||
|
||||
priv->connector.dpms = DRM_MODE_DPMS_OFF;
|
||||
|
@ -931,7 +931,6 @@ static void ast_crtc_atomic_destroy_state(struct drm_crtc *crtc,
|
||||
|
||||
static const struct drm_crtc_funcs ast_crtc_funcs = {
|
||||
.reset = ast_crtc_reset,
|
||||
.set_config = drm_crtc_helper_set_config,
|
||||
.gamma_set = drm_atomic_helper_legacy_gamma_set,
|
||||
.destroy = ast_crtc_destroy,
|
||||
.set_config = drm_atomic_helper_set_config,
|
||||
@ -1080,7 +1079,6 @@ static void ast_connector_destroy(struct drm_connector *connector)
|
||||
{
|
||||
struct ast_connector *ast_connector = to_ast_connector(connector);
|
||||
ast_i2c_destroy(ast_connector->i2c);
|
||||
drm_connector_unregister(connector);
|
||||
drm_connector_cleanup(connector);
|
||||
kfree(connector);
|
||||
}
|
||||
@ -1123,8 +1121,6 @@ static int ast_connector_init(struct drm_device *dev)
|
||||
connector->interlace_allowed = 0;
|
||||
connector->doublescan_allowed = 0;
|
||||
|
||||
drm_connector_register(connector);
|
||||
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
||||
|
||||
encoder = list_first_entry(&dev->mode_config.encoder_list, struct drm_encoder, head);
|
||||
|
@ -104,7 +104,6 @@ static void bochs_connector_init(struct drm_device *dev)
|
||||
DRM_MODE_CONNECTOR_VIRTUAL);
|
||||
drm_connector_helper_add(connector,
|
||||
&bochs_connector_connector_helper_funcs);
|
||||
drm_connector_register(connector);
|
||||
|
||||
bochs_hw_load_edid(bochs);
|
||||
if (bochs->edid) {
|
||||
|
@ -27,6 +27,16 @@ config DRM_CDNS_DSI
|
||||
Support Cadence DPI to DSI bridge. This is an internal
|
||||
bridge and is meant to be directly embedded in a SoC.
|
||||
|
||||
config DRM_CHRONTEL_CH7033
|
||||
tristate "Chrontel CH7033 Video Encoder"
|
||||
depends on OF
|
||||
select DRM_KMS_HELPER
|
||||
help
|
||||
Enable support for the Chrontel CH7033 VGA/DVI/HDMI Encoder, as
|
||||
found in the Dell Wyse 3020 thin client.
|
||||
|
||||
If in doubt, say "N".
|
||||
|
||||
config DRM_DISPLAY_CONNECTOR
|
||||
tristate "Display connector support"
|
||||
depends on OF
|
||||
|
@ -1,5 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o
|
||||
obj-$(CONFIG_DRM_CHRONTEL_CH7033) += chrontel-ch7033.o
|
||||
obj-$(CONFIG_DRM_DISPLAY_CONNECTOR) += display-connector.o
|
||||
obj-$(CONFIG_DRM_LVDS_CODEC) += lvds-codec.o
|
||||
obj-$(CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW) += megachips-stdpxxxx-ge-b850v3-fw.o
|
||||
|
620
drivers/gpu/drm/bridge/chrontel-ch7033.c
Normal file
620
drivers/gpu/drm/bridge/chrontel-ch7033.c
Normal file
@ -0,0 +1,620 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Chrontel CH7033 Video Encoder Driver
|
||||
*
|
||||
* Copyright (C) 2019,2020 Lubomir Rintel
|
||||
*/
|
||||
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
/* Page 0, Register 0x07 */
|
||||
enum {
|
||||
DRI_PD = BIT(3),
|
||||
IO_PD = BIT(5),
|
||||
};
|
||||
|
||||
/* Page 0, Register 0x08 */
|
||||
enum {
|
||||
DRI_PDDRI = GENMASK(7, 4),
|
||||
PDDAC = GENMASK(3, 1),
|
||||
PANEN = BIT(0),
|
||||
};
|
||||
|
||||
/* Page 0, Register 0x09 */
|
||||
enum {
|
||||
DPD = BIT(7),
|
||||
GCKOFF = BIT(6),
|
||||
TV_BP = BIT(5),
|
||||
SCLPD = BIT(4),
|
||||
SDPD = BIT(3),
|
||||
VGA_PD = BIT(2),
|
||||
HDBKPD = BIT(1),
|
||||
HDMI_PD = BIT(0),
|
||||
};
|
||||
|
||||
/* Page 0, Register 0x0a */
|
||||
enum {
|
||||
MEMINIT = BIT(7),
|
||||
MEMIDLE = BIT(6),
|
||||
MEMPD = BIT(5),
|
||||
STOP = BIT(4),
|
||||
LVDS_PD = BIT(3),
|
||||
HD_DVIB = BIT(2),
|
||||
HDCP_PD = BIT(1),
|
||||
MCU_PD = BIT(0),
|
||||
};
|
||||
|
||||
/* Page 0, Register 0x18 */
|
||||
enum {
|
||||
IDF = GENMASK(7, 4),
|
||||
INTEN = BIT(3),
|
||||
SWAP = GENMASK(2, 0),
|
||||
};
|
||||
|
||||
enum {
|
||||
BYTE_SWAP_RGB = 0,
|
||||
BYTE_SWAP_RBG = 1,
|
||||
BYTE_SWAP_GRB = 2,
|
||||
BYTE_SWAP_GBR = 3,
|
||||
BYTE_SWAP_BRG = 4,
|
||||
BYTE_SWAP_BGR = 5,
|
||||
};
|
||||
|
||||
/* Page 0, Register 0x19 */
|
||||
enum {
|
||||
HPO_I = BIT(5),
|
||||
VPO_I = BIT(4),
|
||||
DEPO_I = BIT(3),
|
||||
CRYS_EN = BIT(2),
|
||||
GCLKFREQ = GENMASK(2, 0),
|
||||
};
|
||||
|
||||
/* Page 0, Register 0x2e */
|
||||
enum {
|
||||
HFLIP = BIT(7),
|
||||
VFLIP = BIT(6),
|
||||
DEPO_O = BIT(5),
|
||||
HPO_O = BIT(4),
|
||||
VPO_O = BIT(3),
|
||||
TE = GENMASK(2, 0),
|
||||
};
|
||||
|
||||
/* Page 0, Register 0x2b */
|
||||
enum {
|
||||
SWAPS = GENMASK(7, 4),
|
||||
VFMT = GENMASK(3, 0),
|
||||
};
|
||||
|
||||
/* Page 0, Register 0x54 */
|
||||
enum {
|
||||
COMP_BP = BIT(7),
|
||||
DAC_EN_T = BIT(6),
|
||||
HWO_HDMI_HI = GENMASK(5, 3),
|
||||
HOO_HDMI_HI = GENMASK(2, 0),
|
||||
};
|
||||
|
||||
/* Page 0, Register 0x57 */
|
||||
enum {
|
||||
FLDSEN = BIT(7),
|
||||
VWO_HDMI_HI = GENMASK(5, 3),
|
||||
VOO_HDMI_HI = GENMASK(2, 0),
|
||||
};
|
||||
|
||||
/* Page 0, Register 0x7e */
|
||||
enum {
|
||||
HDMI_LVDS_SEL = BIT(7),
|
||||
DE_GEN = BIT(6),
|
||||
PWM_INDEX_HI = BIT(5),
|
||||
USE_DE = BIT(4),
|
||||
R_INT = GENMASK(3, 0),
|
||||
};
|
||||
|
||||
/* Page 1, Register 0x07 */
|
||||
enum {
|
||||
BPCKSEL = BIT(7),
|
||||
DRI_CMFB_EN = BIT(6),
|
||||
CEC_PUEN = BIT(5),
|
||||
CEC_T = BIT(3),
|
||||
CKINV = BIT(2),
|
||||
CK_TVINV = BIT(1),
|
||||
DRI_CKS2 = BIT(0),
|
||||
};
|
||||
|
||||
/* Page 1, Register 0x08 */
|
||||
enum {
|
||||
DACG = BIT(6),
|
||||
DACKTST = BIT(5),
|
||||
DEDGEB = BIT(4),
|
||||
SYO = BIT(3),
|
||||
DRI_IT_LVDS = GENMASK(2, 1),
|
||||
DISPON = BIT(0),
|
||||
};
|
||||
|
||||
/* Page 1, Register 0x0c */
|
||||
enum {
|
||||
DRI_PLL_CP = GENMASK(7, 6),
|
||||
DRI_PLL_DIVSEL = BIT(5),
|
||||
DRI_PLL_N1_1 = BIT(4),
|
||||
DRI_PLL_N1_0 = BIT(3),
|
||||
DRI_PLL_N3_1 = BIT(2),
|
||||
DRI_PLL_N3_0 = BIT(1),
|
||||
DRI_PLL_CKTSTEN = BIT(0),
|
||||
};
|
||||
|
||||
/* Page 1, Register 0x6b */
|
||||
enum {
|
||||
VCO3CS = GENMASK(7, 6),
|
||||
ICPGBK2_0 = GENMASK(5, 3),
|
||||
DRI_VCO357SC = BIT(2),
|
||||
PDPLL2 = BIT(1),
|
||||
DRI_PD_SER = BIT(0),
|
||||
};
|
||||
|
||||
/* Page 1, Register 0x6c */
|
||||
enum {
|
||||
PLL2N11 = GENMASK(7, 4),
|
||||
PLL2N5_4 = BIT(3),
|
||||
PLL2N5_TOP = BIT(2),
|
||||
DRI_PLL_PD = BIT(1),
|
||||
PD_I2CM = BIT(0),
|
||||
};
|
||||
|
||||
/* Page 3, Register 0x28 */
|
||||
enum {
|
||||
DIFF_EN = GENMASK(7, 6),
|
||||
CORREC_EN = GENMASK(5, 4),
|
||||
VGACLK_BP = BIT(3),
|
||||
HM_LV_SEL = BIT(2),
|
||||
HD_VGA_SEL = BIT(1),
|
||||
};
|
||||
|
||||
/* Page 3, Register 0x2a */
|
||||
enum {
|
||||
LVDSCLK_BP = BIT(7),
|
||||
HDTVCLK_BP = BIT(6),
|
||||
HDMICLK_BP = BIT(5),
|
||||
HDTV_BP = BIT(4),
|
||||
HDMI_BP = BIT(3),
|
||||
THRWL = GENMASK(2, 0),
|
||||
};
|
||||
|
||||
/* Page 4, Register 0x52 */
|
||||
enum {
|
||||
PGM_ARSTB = BIT(7),
|
||||
MCU_ARSTB = BIT(6),
|
||||
MCU_RETB = BIT(2),
|
||||
RESETIB = BIT(1),
|
||||
RESETDB = BIT(0),
|
||||
};
|
||||
|
||||
struct ch7033_priv {
|
||||
struct regmap *regmap;
|
||||
struct drm_bridge *next_bridge;
|
||||
struct drm_bridge bridge;
|
||||
struct drm_connector connector;
|
||||
};
|
||||
|
||||
#define conn_to_ch7033_priv(x) \
|
||||
container_of(x, struct ch7033_priv, connector)
|
||||
#define bridge_to_ch7033_priv(x) \
|
||||
container_of(x, struct ch7033_priv, bridge)
|
||||
|
||||
|
||||
static enum drm_connector_status ch7033_connector_detect(
|
||||
struct drm_connector *connector, bool force)
|
||||
{
|
||||
struct ch7033_priv *priv = conn_to_ch7033_priv(connector);
|
||||
|
||||
return drm_bridge_detect(priv->next_bridge);
|
||||
}
|
||||
|
||||
static const struct drm_connector_funcs ch7033_connector_funcs = {
|
||||
.reset = drm_atomic_helper_connector_reset,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.detect = ch7033_connector_detect,
|
||||
.destroy = drm_connector_cleanup,
|
||||
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
};
|
||||
|
||||
static int ch7033_connector_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct ch7033_priv *priv = conn_to_ch7033_priv(connector);
|
||||
struct edid *edid;
|
||||
int ret;
|
||||
|
||||
edid = drm_bridge_get_edid(priv->next_bridge, connector);
|
||||
drm_connector_update_edid_property(connector, edid);
|
||||
if (edid) {
|
||||
ret = drm_add_edid_modes(connector, edid);
|
||||
kfree(edid);
|
||||
} else {
|
||||
ret = drm_add_modes_noedid(connector, 1920, 1080);
|
||||
drm_set_preferred_mode(connector, 1024, 768);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct drm_encoder *ch7033_connector_best_encoder(
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct ch7033_priv *priv = conn_to_ch7033_priv(connector);
|
||||
|
||||
return priv->bridge.encoder;
|
||||
}
|
||||
|
||||
static const struct drm_connector_helper_funcs ch7033_connector_helper_funcs = {
|
||||
.get_modes = ch7033_connector_get_modes,
|
||||
.best_encoder = ch7033_connector_best_encoder,
|
||||
};
|
||||
|
||||
static void ch7033_hpd_event(void *arg, enum drm_connector_status status)
|
||||
{
|
||||
struct ch7033_priv *priv = arg;
|
||||
|
||||
if (priv->bridge.dev)
|
||||
drm_helper_hpd_irq_event(priv->connector.dev);
|
||||
}
|
||||
|
||||
static int ch7033_bridge_attach(struct drm_bridge *bridge,
|
||||
enum drm_bridge_attach_flags flags)
|
||||
{
|
||||
struct ch7033_priv *priv = bridge_to_ch7033_priv(bridge);
|
||||
struct drm_connector *connector = &priv->connector;
|
||||
int ret;
|
||||
|
||||
ret = drm_bridge_attach(bridge->encoder, priv->next_bridge, bridge,
|
||||
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
|
||||
return 0;
|
||||
|
||||
if (priv->next_bridge->ops & DRM_BRIDGE_OP_DETECT) {
|
||||
connector->polled = DRM_CONNECTOR_POLL_HPD;
|
||||
} else {
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT |
|
||||
DRM_CONNECTOR_POLL_DISCONNECT;
|
||||
}
|
||||
|
||||
if (priv->next_bridge->ops & DRM_BRIDGE_OP_HPD) {
|
||||
drm_bridge_hpd_enable(priv->next_bridge, ch7033_hpd_event,
|
||||
priv);
|
||||
}
|
||||
|
||||
drm_connector_helper_add(connector,
|
||||
&ch7033_connector_helper_funcs);
|
||||
ret = drm_connector_init_with_ddc(bridge->dev, &priv->connector,
|
||||
&ch7033_connector_funcs,
|
||||
priv->next_bridge->type,
|
||||
priv->next_bridge->ddc);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to initialize connector\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return drm_connector_attach_encoder(&priv->connector, bridge->encoder);
|
||||
}
|
||||
|
||||
static void ch7033_bridge_detach(struct drm_bridge *bridge)
|
||||
{
|
||||
struct ch7033_priv *priv = bridge_to_ch7033_priv(bridge);
|
||||
|
||||
if (priv->next_bridge->ops & DRM_BRIDGE_OP_HPD)
|
||||
drm_bridge_hpd_disable(priv->next_bridge);
|
||||
drm_connector_cleanup(&priv->connector);
|
||||
}
|
||||
|
||||
static enum drm_mode_status ch7033_bridge_mode_valid(struct drm_bridge *bridge,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
if (mode->clock > 165000)
|
||||
return MODE_CLOCK_HIGH;
|
||||
if (mode->hdisplay >= 1920)
|
||||
return MODE_BAD_HVALUE;
|
||||
if (mode->vdisplay >= 1080)
|
||||
return MODE_BAD_VVALUE;
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static void ch7033_bridge_disable(struct drm_bridge *bridge)
|
||||
{
|
||||
struct ch7033_priv *priv = bridge_to_ch7033_priv(bridge);
|
||||
|
||||
regmap_write(priv->regmap, 0x03, 0x04);
|
||||
regmap_update_bits(priv->regmap, 0x52, RESETDB, 0x00);
|
||||
}
|
||||
|
||||
static void ch7033_bridge_enable(struct drm_bridge *bridge)
|
||||
{
|
||||
struct ch7033_priv *priv = bridge_to_ch7033_priv(bridge);
|
||||
|
||||
regmap_write(priv->regmap, 0x03, 0x04);
|
||||
regmap_update_bits(priv->regmap, 0x52, RESETDB, RESETDB);
|
||||
}
|
||||
|
||||
static void ch7033_bridge_mode_set(struct drm_bridge *bridge,
|
||||
const struct drm_display_mode *mode,
|
||||
const struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
struct ch7033_priv *priv = bridge_to_ch7033_priv(bridge);
|
||||
int hbporch = mode->hsync_start - mode->hdisplay;
|
||||
int hsynclen = mode->hsync_end - mode->hsync_start;
|
||||
int vbporch = mode->vsync_start - mode->vdisplay;
|
||||
int vsynclen = mode->vsync_end - mode->vsync_start;
|
||||
|
||||
/*
|
||||
* Page 4
|
||||
*/
|
||||
regmap_write(priv->regmap, 0x03, 0x04);
|
||||
|
||||
/* Turn everything off to set all the registers to their defaults. */
|
||||
regmap_write(priv->regmap, 0x52, 0x00);
|
||||
/* Bring I/O block up. */
|
||||
regmap_write(priv->regmap, 0x52, RESETIB);
|
||||
|
||||
/*
|
||||
* Page 0
|
||||
*/
|
||||
regmap_write(priv->regmap, 0x03, 0x00);
|
||||
|
||||
/* Bring up parts we need from the power down. */
|
||||
regmap_update_bits(priv->regmap, 0x07, DRI_PD | IO_PD, 0);
|
||||
regmap_update_bits(priv->regmap, 0x08, DRI_PDDRI | PDDAC | PANEN, 0);
|
||||
regmap_update_bits(priv->regmap, 0x09, DPD | GCKOFF |
|
||||
HDMI_PD | VGA_PD, 0);
|
||||
regmap_update_bits(priv->regmap, 0x0a, HD_DVIB, 0);
|
||||
|
||||
/* Horizontal input timing. */
|
||||
regmap_write(priv->regmap, 0x0b, (mode->htotal >> 8) << 3 |
|
||||
(mode->hdisplay >> 8));
|
||||
regmap_write(priv->regmap, 0x0c, mode->hdisplay);
|
||||
regmap_write(priv->regmap, 0x0d, mode->htotal);
|
||||
regmap_write(priv->regmap, 0x0e, (hsynclen >> 8) << 3 |
|
||||
(hbporch >> 8));
|
||||
regmap_write(priv->regmap, 0x0f, hbporch);
|
||||
regmap_write(priv->regmap, 0x10, hsynclen);
|
||||
|
||||
/* Vertical input timing. */
|
||||
regmap_write(priv->regmap, 0x11, (mode->vtotal >> 8) << 3 |
|
||||
(mode->vdisplay >> 8));
|
||||
regmap_write(priv->regmap, 0x12, mode->vdisplay);
|
||||
regmap_write(priv->regmap, 0x13, mode->vtotal);
|
||||
regmap_write(priv->regmap, 0x14, ((vsynclen >> 8) << 3) |
|
||||
(vbporch >> 8));
|
||||
regmap_write(priv->regmap, 0x15, vbporch);
|
||||
regmap_write(priv->regmap, 0x16, vsynclen);
|
||||
|
||||
/* Input color swap. */
|
||||
regmap_update_bits(priv->regmap, 0x18, SWAP, BYTE_SWAP_BGR);
|
||||
|
||||
/* Input clock and sync polarity. */
|
||||
regmap_update_bits(priv->regmap, 0x19, 0x1, mode->clock >> 16);
|
||||
regmap_update_bits(priv->regmap, 0x19, HPO_I | VPO_I | GCLKFREQ,
|
||||
(mode->flags & DRM_MODE_FLAG_PHSYNC) ? HPO_I : 0 |
|
||||
(mode->flags & DRM_MODE_FLAG_PVSYNC) ? VPO_I : 0 |
|
||||
mode->clock >> 16);
|
||||
regmap_write(priv->regmap, 0x1a, mode->clock >> 8);
|
||||
regmap_write(priv->regmap, 0x1b, mode->clock);
|
||||
|
||||
/* Horizontal output timing. */
|
||||
regmap_write(priv->regmap, 0x1f, (mode->htotal >> 8) << 3 |
|
||||
(mode->hdisplay >> 8));
|
||||
regmap_write(priv->regmap, 0x20, mode->hdisplay);
|
||||
regmap_write(priv->regmap, 0x21, mode->htotal);
|
||||
|
||||
/* Vertical output timing. */
|
||||
regmap_write(priv->regmap, 0x25, (mode->vtotal >> 8) << 3 |
|
||||
(mode->vdisplay >> 8));
|
||||
regmap_write(priv->regmap, 0x26, mode->vdisplay);
|
||||
regmap_write(priv->regmap, 0x27, mode->vtotal);
|
||||
|
||||
/* VGA channel bypass */
|
||||
regmap_update_bits(priv->regmap, 0x2b, VFMT, 9);
|
||||
|
||||
/* Output sync polarity. */
|
||||
regmap_update_bits(priv->regmap, 0x2e, HPO_O | VPO_O,
|
||||
(mode->flags & DRM_MODE_FLAG_PHSYNC) ? HPO_O : 0 |
|
||||
(mode->flags & DRM_MODE_FLAG_PVSYNC) ? VPO_O : 0);
|
||||
|
||||
/* HDMI horizontal output timing. */
|
||||
regmap_update_bits(priv->regmap, 0x54, HWO_HDMI_HI | HOO_HDMI_HI,
|
||||
(hsynclen >> 8) << 3 |
|
||||
(hbporch >> 8));
|
||||
regmap_write(priv->regmap, 0x55, hbporch);
|
||||
regmap_write(priv->regmap, 0x56, hsynclen);
|
||||
|
||||
/* HDMI vertical output timing. */
|
||||
regmap_update_bits(priv->regmap, 0x57, VWO_HDMI_HI | VOO_HDMI_HI,
|
||||
(vsynclen >> 8) << 3 |
|
||||
(vbporch >> 8));
|
||||
regmap_write(priv->regmap, 0x58, vbporch);
|
||||
regmap_write(priv->regmap, 0x59, vsynclen);
|
||||
|
||||
/* Pick HDMI, not LVDS. */
|
||||
regmap_update_bits(priv->regmap, 0x7e, HDMI_LVDS_SEL, HDMI_LVDS_SEL);
|
||||
|
||||
/*
|
||||
* Page 1
|
||||
*/
|
||||
regmap_write(priv->regmap, 0x03, 0x01);
|
||||
|
||||
/* No idea what these do, but VGA is wobbly and blinky without them. */
|
||||
regmap_update_bits(priv->regmap, 0x07, CKINV, CKINV);
|
||||
regmap_update_bits(priv->regmap, 0x08, DISPON, DISPON);
|
||||
|
||||
/* DRI PLL */
|
||||
regmap_update_bits(priv->regmap, 0x0c, DRI_PLL_DIVSEL, DRI_PLL_DIVSEL);
|
||||
if (mode->clock <= 40000) {
|
||||
regmap_update_bits(priv->regmap, 0x0c, DRI_PLL_N1_1 |
|
||||
DRI_PLL_N1_0 |
|
||||
DRI_PLL_N3_1 |
|
||||
DRI_PLL_N3_0,
|
||||
0);
|
||||
} else if (mode->clock < 80000) {
|
||||
regmap_update_bits(priv->regmap, 0x0c, DRI_PLL_N1_1 |
|
||||
DRI_PLL_N1_0 |
|
||||
DRI_PLL_N3_1 |
|
||||
DRI_PLL_N3_0,
|
||||
DRI_PLL_N3_0 |
|
||||
DRI_PLL_N1_0);
|
||||
} else {
|
||||
regmap_update_bits(priv->regmap, 0x0c, DRI_PLL_N1_1 |
|
||||
DRI_PLL_N1_0 |
|
||||
DRI_PLL_N3_1 |
|
||||
DRI_PLL_N3_0,
|
||||
DRI_PLL_N3_1 |
|
||||
DRI_PLL_N1_1);
|
||||
}
|
||||
|
||||
/* This seems to be color calibration for VGA. */
|
||||
regmap_write(priv->regmap, 0x64, 0x29); /* LSB Blue */
|
||||
regmap_write(priv->regmap, 0x65, 0x29); /* LSB Green */
|
||||
regmap_write(priv->regmap, 0x66, 0x29); /* LSB Red */
|
||||
regmap_write(priv->regmap, 0x67, 0x00); /* MSB Blue */
|
||||
regmap_write(priv->regmap, 0x68, 0x00); /* MSB Green */
|
||||
regmap_write(priv->regmap, 0x69, 0x00); /* MSB Red */
|
||||
|
||||
regmap_update_bits(priv->regmap, 0x6b, DRI_PD_SER, 0x00);
|
||||
regmap_update_bits(priv->regmap, 0x6c, DRI_PLL_PD, 0x00);
|
||||
|
||||
/*
|
||||
* Page 3
|
||||
*/
|
||||
regmap_write(priv->regmap, 0x03, 0x03);
|
||||
|
||||
/* More bypasses and apparently another HDMI/LVDS selector. */
|
||||
regmap_update_bits(priv->regmap, 0x28, VGACLK_BP | HM_LV_SEL,
|
||||
VGACLK_BP | HM_LV_SEL);
|
||||
regmap_update_bits(priv->regmap, 0x2a, HDMICLK_BP | HDMI_BP,
|
||||
HDMICLK_BP | HDMI_BP);
|
||||
|
||||
/*
|
||||
* Page 4
|
||||
*/
|
||||
regmap_write(priv->regmap, 0x03, 0x04);
|
||||
|
||||
/* Output clock. */
|
||||
regmap_write(priv->regmap, 0x10, mode->clock >> 16);
|
||||
regmap_write(priv->regmap, 0x11, mode->clock >> 8);
|
||||
regmap_write(priv->regmap, 0x12, mode->clock);
|
||||
}
|
||||
|
||||
static const struct drm_bridge_funcs ch7033_bridge_funcs = {
|
||||
.attach = ch7033_bridge_attach,
|
||||
.detach = ch7033_bridge_detach,
|
||||
.mode_valid = ch7033_bridge_mode_valid,
|
||||
.disable = ch7033_bridge_disable,
|
||||
.enable = ch7033_bridge_enable,
|
||||
.mode_set = ch7033_bridge_mode_set,
|
||||
};
|
||||
|
||||
static const struct regmap_config ch7033_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = 0x7f,
|
||||
};
|
||||
|
||||
static int ch7033_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct ch7033_priv *priv;
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_set_drvdata(dev, priv);
|
||||
|
||||
ret = drm_of_find_panel_or_bridge(dev->of_node, 1, -1, NULL,
|
||||
&priv->next_bridge);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->regmap = devm_regmap_init_i2c(client, &ch7033_regmap_config);
|
||||
if (IS_ERR(priv->regmap)) {
|
||||
dev_err(&client->dev, "regmap init failed\n");
|
||||
return PTR_ERR(priv->regmap);
|
||||
}
|
||||
|
||||
ret = regmap_read(priv->regmap, 0x00, &val);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev, "error reading the model id: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if ((val & 0xf7) != 0x56) {
|
||||
dev_err(&client->dev, "the device is not a ch7033\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
regmap_write(priv->regmap, 0x03, 0x04);
|
||||
ret = regmap_read(priv->regmap, 0x51, &val);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev, "error reading the model id: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if ((val & 0x0f) != 3) {
|
||||
dev_err(&client->dev, "unknown revision %u\n", val);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&priv->bridge.list);
|
||||
priv->bridge.funcs = &ch7033_bridge_funcs;
|
||||
priv->bridge.of_node = dev->of_node;
|
||||
drm_bridge_add(&priv->bridge);
|
||||
|
||||
dev_info(dev, "Chrontel CH7033 Video Encoder\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ch7033_remove(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct ch7033_priv *priv = dev_get_drvdata(dev);
|
||||
|
||||
drm_bridge_remove(&priv->bridge);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id ch7033_dt_ids[] = {
|
||||
{ .compatible = "chrontel,ch7033", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ch7033_dt_ids);
|
||||
|
||||
static const struct i2c_device_id ch7033_ids[] = {
|
||||
{ "ch7033", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ch7033_ids);
|
||||
|
||||
static struct i2c_driver ch7033_driver = {
|
||||
.probe = ch7033_probe,
|
||||
.remove = ch7033_remove,
|
||||
.driver = {
|
||||
.name = "ch7033",
|
||||
.of_match_table = of_match_ptr(ch7033_dt_ids),
|
||||
},
|
||||
.id_table = ch7033_ids,
|
||||
};
|
||||
|
||||
module_i2c_driver(ch7033_driver);
|
||||
|
||||
MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>");
|
||||
MODULE_DESCRIPTION("Chrontel CH7033 Video Encoder Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -166,7 +166,7 @@ static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
|
||||
*
|
||||
* The connector type is set to @panel->connector_type, which must be set to a
|
||||
* known type. Calling this function with a panel whose connector type is
|
||||
* DRM_MODE_CONNECTOR_Unknown will return NULL.
|
||||
* DRM_MODE_CONNECTOR_Unknown will return ERR_PTR(-EINVAL).
|
||||
*
|
||||
* See devm_drm_panel_bridge_add() for an automatically managed version of this
|
||||
* function.
|
||||
@ -174,7 +174,7 @@ static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
|
||||
struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel)
|
||||
{
|
||||
if (WARN_ON(panel->connector_type == DRM_MODE_CONNECTOR_Unknown))
|
||||
return NULL;
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
return drm_panel_bridge_add_typed(panel, panel->connector_type);
|
||||
}
|
||||
@ -265,7 +265,7 @@ struct drm_bridge *devm_drm_panel_bridge_add(struct device *dev,
|
||||
struct drm_panel *panel)
|
||||
{
|
||||
if (WARN_ON(panel->connector_type == DRM_MODE_CONNECTOR_Unknown))
|
||||
return NULL;
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
return devm_drm_panel_bridge_add_typed(dev, panel,
|
||||
panel->connector_type);
|
||||
|
@ -268,8 +268,6 @@ static int ps8640_probe(struct i2c_client *client)
|
||||
if (!panel)
|
||||
return -ENODEV;
|
||||
|
||||
panel->connector_type = DRM_MODE_CONNECTOR_eDP;
|
||||
|
||||
ps_bridge->panel_bridge = devm_drm_panel_bridge_add(dev, panel);
|
||||
if (IS_ERR(ps_bridge->panel_bridge))
|
||||
return PTR_ERR(ps_bridge->panel_bridge);
|
||||
|
@ -178,6 +178,8 @@ static int tc358768_clear_error(struct tc358768_priv *priv)
|
||||
|
||||
static void tc358768_write(struct tc358768_priv *priv, u32 reg, u32 val)
|
||||
{
|
||||
/* work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
|
||||
int tmpval = val;
|
||||
size_t count = 2;
|
||||
|
||||
if (priv->error)
|
||||
@ -187,7 +189,7 @@ static void tc358768_write(struct tc358768_priv *priv, u32 reg, u32 val)
|
||||
if (reg < 0x100 || reg >= 0x600)
|
||||
count = 1;
|
||||
|
||||
priv->error = regmap_bulk_write(priv->regmap, reg, &val, count);
|
||||
priv->error = regmap_bulk_write(priv->regmap, reg, &tmpval, count);
|
||||
}
|
||||
|
||||
static void tc358768_read(struct tc358768_priv *priv, u32 reg, u32 *val)
|
||||
|
@ -1,19 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
config DRM_CIRRUS_QEMU
|
||||
tristate "Cirrus driver for QEMU emulated device"
|
||||
depends on DRM && PCI && MMU
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_GEM_SHMEM_HELPER
|
||||
help
|
||||
This is a KMS driver for emulated cirrus device in qemu.
|
||||
It is *NOT* intended for real cirrus devices. This requires
|
||||
the modesetting userspace X.org driver.
|
||||
|
||||
Cirrus is obsolete, the hardware was designed in the 90ies
|
||||
and can't keep up with todays needs. More background:
|
||||
https://www.kraxel.org/blog/2014/10/qemu-using-cirrus-considered-harmful/
|
||||
|
||||
Better alternatives are:
|
||||
- stdvga (DRM_BOCHS, qemu -vga std, default in qemu 2.2+)
|
||||
- qxl (DRM_QXL, qemu -vga qxl, works best with spice)
|
||||
- virtio (DRM_VIRTIO_GPU), qemu -vga virtio)
|
@ -1,2 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus.o
|
@ -1197,14 +1197,8 @@ static int drm_dp_mst_wait_tx_reply(struct drm_dp_mst_branch *mstb,
|
||||
|
||||
/* remove from q */
|
||||
if (txmsg->state == DRM_DP_SIDEBAND_TX_QUEUED ||
|
||||
txmsg->state == DRM_DP_SIDEBAND_TX_START_SEND) {
|
||||
txmsg->state == DRM_DP_SIDEBAND_TX_START_SEND)
|
||||
list_del(&txmsg->next);
|
||||
}
|
||||
|
||||
if (txmsg->state == DRM_DP_SIDEBAND_TX_START_SEND ||
|
||||
txmsg->state == DRM_DP_SIDEBAND_TX_SENT) {
|
||||
mstb->tx_slots[txmsg->seqno] = NULL;
|
||||
}
|
||||
}
|
||||
out:
|
||||
if (unlikely(ret == -EIO) && drm_debug_enabled(DRM_UT_DP)) {
|
||||
@ -1214,6 +1208,7 @@ out:
|
||||
}
|
||||
mutex_unlock(&mgr->qlock);
|
||||
|
||||
drm_dp_mst_kick_tx(mgr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2682,22 +2677,6 @@ static int set_hdr_from_dst_qlock(struct drm_dp_sideband_msg_hdr *hdr,
|
||||
struct drm_dp_mst_branch *mstb = txmsg->dst;
|
||||
u8 req_type;
|
||||
|
||||
/* both msg slots are full */
|
||||
if (txmsg->seqno == -1) {
|
||||
if (mstb->tx_slots[0] && mstb->tx_slots[1]) {
|
||||
DRM_DEBUG_KMS("%s: failed to find slot\n", __func__);
|
||||
return -EAGAIN;
|
||||
}
|
||||
if (mstb->tx_slots[0] == NULL && mstb->tx_slots[1] == NULL) {
|
||||
txmsg->seqno = mstb->last_seqno;
|
||||
mstb->last_seqno ^= 1;
|
||||
} else if (mstb->tx_slots[0] == NULL)
|
||||
txmsg->seqno = 0;
|
||||
else
|
||||
txmsg->seqno = 1;
|
||||
mstb->tx_slots[txmsg->seqno] = txmsg;
|
||||
}
|
||||
|
||||
req_type = txmsg->msg[0] & 0x7f;
|
||||
if (req_type == DP_CONNECTION_STATUS_NOTIFY ||
|
||||
req_type == DP_RESOURCE_STATUS_NOTIFY)
|
||||
@ -2709,7 +2688,7 @@ static int set_hdr_from_dst_qlock(struct drm_dp_sideband_msg_hdr *hdr,
|
||||
hdr->lcr = mstb->lct - 1;
|
||||
if (mstb->lct > 1)
|
||||
memcpy(hdr->rad, mstb->rad, mstb->lct / 2);
|
||||
hdr->seqno = txmsg->seqno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
@ -2724,15 +2703,15 @@ static int process_single_tx_qlock(struct drm_dp_mst_topology_mgr *mgr,
|
||||
int len, space, idx, tosend;
|
||||
int ret;
|
||||
|
||||
if (txmsg->state == DRM_DP_SIDEBAND_TX_SENT)
|
||||
return 0;
|
||||
|
||||
memset(&hdr, 0, sizeof(struct drm_dp_sideband_msg_hdr));
|
||||
|
||||
if (txmsg->state == DRM_DP_SIDEBAND_TX_QUEUED) {
|
||||
txmsg->seqno = -1;
|
||||
if (txmsg->state == DRM_DP_SIDEBAND_TX_QUEUED)
|
||||
txmsg->state = DRM_DP_SIDEBAND_TX_START_SEND;
|
||||
}
|
||||
|
||||
/* make hdr from dst mst - for replies use seqno
|
||||
otherwise assign one */
|
||||
/* make hdr from dst mst */
|
||||
ret = set_hdr_from_dst_qlock(&hdr, txmsg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@ -2785,40 +2764,17 @@ static void process_single_down_tx_qlock(struct drm_dp_mst_topology_mgr *mgr)
|
||||
if (list_empty(&mgr->tx_msg_downq))
|
||||
return;
|
||||
|
||||
txmsg = list_first_entry(&mgr->tx_msg_downq, struct drm_dp_sideband_msg_tx, next);
|
||||
txmsg = list_first_entry(&mgr->tx_msg_downq,
|
||||
struct drm_dp_sideband_msg_tx, next);
|
||||
ret = process_single_tx_qlock(mgr, txmsg, false);
|
||||
if (ret == 1) {
|
||||
/* txmsg is sent it should be in the slots now */
|
||||
list_del(&txmsg->next);
|
||||
} else if (ret) {
|
||||
if (ret < 0) {
|
||||
DRM_DEBUG_KMS("failed to send msg in q %d\n", ret);
|
||||
list_del(&txmsg->next);
|
||||
if (txmsg->seqno != -1)
|
||||
txmsg->dst->tx_slots[txmsg->seqno] = NULL;
|
||||
txmsg->state = DRM_DP_SIDEBAND_TX_TIMEOUT;
|
||||
wake_up_all(&mgr->tx_waitq);
|
||||
}
|
||||
}
|
||||
|
||||
/* called holding qlock */
|
||||
static void process_single_up_tx_qlock(struct drm_dp_mst_topology_mgr *mgr,
|
||||
struct drm_dp_sideband_msg_tx *txmsg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* construct a chunk from the first msg in the tx_msg queue */
|
||||
ret = process_single_tx_qlock(mgr, txmsg, true);
|
||||
|
||||
if (ret != 1)
|
||||
DRM_DEBUG_KMS("failed to send msg in q %d\n", ret);
|
||||
|
||||
if (txmsg->seqno != -1) {
|
||||
WARN_ON((unsigned int)txmsg->seqno >
|
||||
ARRAY_SIZE(txmsg->dst->tx_slots));
|
||||
txmsg->dst->tx_slots[txmsg->seqno] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void drm_dp_queue_down_tx(struct drm_dp_mst_topology_mgr *mgr,
|
||||
struct drm_dp_sideband_msg_tx *txmsg)
|
||||
{
|
||||
@ -3451,7 +3407,7 @@ static int drm_dp_encode_up_ack_reply(struct drm_dp_sideband_msg_tx *msg, u8 req
|
||||
|
||||
static int drm_dp_send_up_ack_reply(struct drm_dp_mst_topology_mgr *mgr,
|
||||
struct drm_dp_mst_branch *mstb,
|
||||
int req_type, int seqno, bool broadcast)
|
||||
int req_type, bool broadcast)
|
||||
{
|
||||
struct drm_dp_sideband_msg_tx *txmsg;
|
||||
|
||||
@ -3460,13 +3416,11 @@ static int drm_dp_send_up_ack_reply(struct drm_dp_mst_topology_mgr *mgr,
|
||||
return -ENOMEM;
|
||||
|
||||
txmsg->dst = mstb;
|
||||
txmsg->seqno = seqno;
|
||||
drm_dp_encode_up_ack_reply(txmsg, req_type);
|
||||
|
||||
mutex_lock(&mgr->qlock);
|
||||
|
||||
process_single_up_tx_qlock(mgr, txmsg);
|
||||
|
||||
/* construct a chunk from the first msg in the tx_msg queue */
|
||||
process_single_tx_qlock(mgr, txmsg, true);
|
||||
mutex_unlock(&mgr->qlock);
|
||||
|
||||
kfree(txmsg);
|
||||
@ -3691,8 +3645,9 @@ out_fail:
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dp_mst_topology_mgr_resume);
|
||||
|
||||
static bool drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up,
|
||||
struct drm_dp_mst_branch **mstb, int *seqno)
|
||||
static bool
|
||||
drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up,
|
||||
struct drm_dp_mst_branch **mstb)
|
||||
{
|
||||
int len;
|
||||
u8 replyblock[32];
|
||||
@ -3700,13 +3655,13 @@ static bool drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up,
|
||||
int ret;
|
||||
u8 hdrlen;
|
||||
struct drm_dp_sideband_msg_hdr hdr;
|
||||
struct drm_dp_sideband_msg_rx *msg;
|
||||
struct drm_dp_sideband_msg_rx *msg =
|
||||
up ? &mgr->up_req_recv : &mgr->down_rep_recv;
|
||||
int basereg = up ? DP_SIDEBAND_MSG_UP_REQ_BASE :
|
||||
DP_SIDEBAND_MSG_DOWN_REP_BASE;
|
||||
|
||||
if (!up)
|
||||
*mstb = NULL;
|
||||
*seqno = -1;
|
||||
|
||||
len = min(mgr->max_dpcd_transaction_bytes, 16);
|
||||
ret = drm_dp_dpcd_read(mgr->aux, basereg, replyblock, len);
|
||||
@ -3723,11 +3678,7 @@ static bool drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up,
|
||||
return false;
|
||||
}
|
||||
|
||||
*seqno = hdr.seqno;
|
||||
|
||||
if (up) {
|
||||
msg = &mgr->up_req_recv;
|
||||
} else {
|
||||
if (!up) {
|
||||
/* Caller is responsible for giving back this reference */
|
||||
*mstb = drm_dp_get_mst_branch_device(mgr, hdr.lct, hdr.rad);
|
||||
if (!*mstb) {
|
||||
@ -3735,7 +3686,6 @@ static bool drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up,
|
||||
hdr.lct);
|
||||
return false;
|
||||
}
|
||||
msg = &(*mstb)->down_rep_recv[hdr.seqno];
|
||||
}
|
||||
|
||||
if (!drm_dp_sideband_msg_set_header(msg, &hdr, hdrlen)) {
|
||||
@ -3779,13 +3729,10 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
|
||||
{
|
||||
struct drm_dp_sideband_msg_tx *txmsg;
|
||||
struct drm_dp_mst_branch *mstb = NULL;
|
||||
struct drm_dp_sideband_msg_rx *msg = NULL;
|
||||
int seqno = -1;
|
||||
struct drm_dp_sideband_msg_rx *msg = &mgr->down_rep_recv;
|
||||
|
||||
if (!drm_dp_get_one_sb_msg(mgr, false, &mstb, &seqno))
|
||||
goto out_clear_reply;
|
||||
|
||||
msg = &mstb->down_rep_recv[seqno];
|
||||
if (!drm_dp_get_one_sb_msg(mgr, false, &mstb))
|
||||
goto out;
|
||||
|
||||
/* Multi-packet message transmission, don't clear the reply */
|
||||
if (!msg->have_eomt)
|
||||
@ -3793,11 +3740,12 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
|
||||
|
||||
/* find the message */
|
||||
mutex_lock(&mgr->qlock);
|
||||
txmsg = mstb->tx_slots[seqno];
|
||||
/* remove from slots */
|
||||
txmsg = list_first_entry_or_null(&mgr->tx_msg_downq,
|
||||
struct drm_dp_sideband_msg_tx, next);
|
||||
mutex_unlock(&mgr->qlock);
|
||||
|
||||
if (!txmsg) {
|
||||
/* Were we actually expecting a response, and from this mstb? */
|
||||
if (!txmsg || txmsg->dst != mstb) {
|
||||
struct drm_dp_sideband_msg_hdr *hdr;
|
||||
hdr = &msg->initial_hdr;
|
||||
DRM_DEBUG_KMS("Got MST reply with no msg %p %d %d %02x %02x\n",
|
||||
@ -3822,7 +3770,7 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
|
||||
|
||||
mutex_lock(&mgr->qlock);
|
||||
txmsg->state = DRM_DP_SIDEBAND_TX_RX;
|
||||
mstb->tx_slots[seqno] = NULL;
|
||||
list_del(&txmsg->next);
|
||||
mutex_unlock(&mgr->qlock);
|
||||
|
||||
wake_up_all(&mgr->tx_waitq);
|
||||
@ -3830,8 +3778,7 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
|
||||
return 0;
|
||||
|
||||
out_clear_reply:
|
||||
if (msg)
|
||||
memset(msg, 0, sizeof(struct drm_dp_sideband_msg_rx));
|
||||
memset(msg, 0, sizeof(struct drm_dp_sideband_msg_rx));
|
||||
out:
|
||||
if (mstb)
|
||||
drm_dp_mst_topology_put_mstb(mstb);
|
||||
@ -3911,9 +3858,8 @@ static void drm_dp_mst_up_req_work(struct work_struct *work)
|
||||
static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
|
||||
{
|
||||
struct drm_dp_pending_up_req *up_req;
|
||||
int seqno;
|
||||
|
||||
if (!drm_dp_get_one_sb_msg(mgr, true, NULL, &seqno))
|
||||
if (!drm_dp_get_one_sb_msg(mgr, true, NULL))
|
||||
goto out;
|
||||
|
||||
if (!mgr->up_req_recv.have_eomt)
|
||||
@ -3937,7 +3883,7 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
|
||||
}
|
||||
|
||||
drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, up_req->msg.req_type,
|
||||
seqno, false);
|
||||
false);
|
||||
|
||||
if (up_req->msg.req_type == DP_CONNECTION_STATUS_NOTIFY) {
|
||||
const struct drm_dp_connection_status_notify *conn_stat =
|
||||
@ -4703,26 +4649,25 @@ static inline void
|
||||
drm_dp_delayed_destroy_mstb(struct drm_dp_mst_branch *mstb)
|
||||
{
|
||||
struct drm_dp_mst_topology_mgr *mgr = mstb->mgr;
|
||||
struct drm_dp_mst_port *port, *tmp;
|
||||
struct drm_dp_mst_port *port, *port_tmp;
|
||||
struct drm_dp_sideband_msg_tx *txmsg, *txmsg_tmp;
|
||||
bool wake_tx = false;
|
||||
|
||||
mutex_lock(&mgr->lock);
|
||||
list_for_each_entry_safe(port, tmp, &mstb->ports, next) {
|
||||
list_for_each_entry_safe(port, port_tmp, &mstb->ports, next) {
|
||||
list_del(&port->next);
|
||||
drm_dp_mst_topology_put_port(port);
|
||||
}
|
||||
mutex_unlock(&mgr->lock);
|
||||
|
||||
/* drop any tx slots msg */
|
||||
/* drop any tx slot msg */
|
||||
mutex_lock(&mstb->mgr->qlock);
|
||||
if (mstb->tx_slots[0]) {
|
||||
mstb->tx_slots[0]->state = DRM_DP_SIDEBAND_TX_TIMEOUT;
|
||||
mstb->tx_slots[0] = NULL;
|
||||
wake_tx = true;
|
||||
}
|
||||
if (mstb->tx_slots[1]) {
|
||||
mstb->tx_slots[1]->state = DRM_DP_SIDEBAND_TX_TIMEOUT;
|
||||
mstb->tx_slots[1] = NULL;
|
||||
list_for_each_entry_safe(txmsg, txmsg_tmp, &mgr->tx_msg_downq, next) {
|
||||
if (txmsg->dst != mstb)
|
||||
continue;
|
||||
|
||||
txmsg->state = DRM_DP_SIDEBAND_TX_TIMEOUT;
|
||||
list_del(&txmsg->next);
|
||||
wake_tx = true;
|
||||
}
|
||||
mutex_unlock(&mstb->mgr->qlock);
|
||||
|
@ -739,6 +739,29 @@ int devm_drm_dev_init(struct device *parent,
|
||||
}
|
||||
EXPORT_SYMBOL(devm_drm_dev_init);
|
||||
|
||||
void *__devm_drm_dev_alloc(struct device *parent, struct drm_driver *driver,
|
||||
size_t size, size_t offset)
|
||||
{
|
||||
void *container;
|
||||
struct drm_device *drm;
|
||||
int ret;
|
||||
|
||||
container = kzalloc(size, GFP_KERNEL);
|
||||
if (!container)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
drm = container + offset;
|
||||
ret = devm_drm_dev_init(parent, drm, driver);
|
||||
if (ret) {
|
||||
kfree(container);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
drmm_add_final_kfree(drm, container);
|
||||
|
||||
return container;
|
||||
}
|
||||
EXPORT_SYMBOL(__devm_drm_dev_alloc);
|
||||
|
||||
/**
|
||||
* drm_dev_alloc - Allocate new DRM device
|
||||
* @driver: DRM driver to allocate device for
|
||||
|
@ -2380,6 +2380,14 @@ bad_std_timing(u8 a, u8 b)
|
||||
(a == 0x20 && b == 0x20);
|
||||
}
|
||||
|
||||
static int drm_mode_hsync(const struct drm_display_mode *mode)
|
||||
{
|
||||
if (mode->htotal <= 0)
|
||||
return 0;
|
||||
|
||||
return DIV_ROUND_CLOSEST(mode->clock, mode->htotal);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_mode_std - convert standard mode info (width, height, refresh) into mode
|
||||
* @connector: connector of for the EDID block
|
||||
|
@ -613,7 +613,8 @@ put_back_event:
|
||||
file_priv->event_space -= length;
|
||||
list_add(&e->link, &file_priv->event_list);
|
||||
spin_unlock_irq(&dev->event_lock);
|
||||
wake_up_interruptible(&file_priv->event_wait);
|
||||
wake_up_interruptible_poll(&file_priv->event_wait,
|
||||
EPOLLIN | EPOLLRDNORM);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -809,7 +810,8 @@ void drm_send_event_locked(struct drm_device *dev, struct drm_pending_event *e)
|
||||
list_del(&e->pending_link);
|
||||
list_add_tail(&e->link,
|
||||
&e->file_priv->event_list);
|
||||
wake_up_interruptible(&e->file_priv->event_wait);
|
||||
wake_up_interruptible_poll(&e->file_priv->event_wait,
|
||||
EPOLLIN | EPOLLRDNORM);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_send_event_locked);
|
||||
|
||||
|
@ -212,20 +212,6 @@ static void drm_mm_interval_tree_add_node(struct drm_mm_node *hole_node,
|
||||
&drm_mm_interval_tree_augment);
|
||||
}
|
||||
|
||||
#define RB_INSERT(root, member, expr) do { \
|
||||
struct rb_node **link = &root.rb_node, *rb = NULL; \
|
||||
u64 x = expr(node); \
|
||||
while (*link) { \
|
||||
rb = *link; \
|
||||
if (x < expr(rb_entry(rb, struct drm_mm_node, member))) \
|
||||
link = &rb->rb_left; \
|
||||
else \
|
||||
link = &rb->rb_right; \
|
||||
} \
|
||||
rb_link_node(&node->member, rb, link); \
|
||||
rb_insert_color(&node->member, &root); \
|
||||
} while (0)
|
||||
|
||||
#define HOLE_SIZE(NODE) ((NODE)->hole_size)
|
||||
#define HOLE_ADDR(NODE) (__drm_mm_hole_node_start(NODE))
|
||||
|
||||
@ -255,16 +241,42 @@ static void insert_hole_size(struct rb_root_cached *root,
|
||||
rb_insert_color_cached(&node->rb_hole_size, root, first);
|
||||
}
|
||||
|
||||
RB_DECLARE_CALLBACKS_MAX(static, augment_callbacks,
|
||||
struct drm_mm_node, rb_hole_addr,
|
||||
u64, subtree_max_hole, HOLE_SIZE)
|
||||
|
||||
static void insert_hole_addr(struct rb_root *root, struct drm_mm_node *node)
|
||||
{
|
||||
struct rb_node **link = &root->rb_node, *rb_parent = NULL;
|
||||
u64 start = HOLE_ADDR(node), subtree_max_hole = node->subtree_max_hole;
|
||||
struct drm_mm_node *parent;
|
||||
|
||||
while (*link) {
|
||||
rb_parent = *link;
|
||||
parent = rb_entry(rb_parent, struct drm_mm_node, rb_hole_addr);
|
||||
if (parent->subtree_max_hole < subtree_max_hole)
|
||||
parent->subtree_max_hole = subtree_max_hole;
|
||||
if (start < HOLE_ADDR(parent))
|
||||
link = &parent->rb_hole_addr.rb_left;
|
||||
else
|
||||
link = &parent->rb_hole_addr.rb_right;
|
||||
}
|
||||
|
||||
rb_link_node(&node->rb_hole_addr, rb_parent, link);
|
||||
rb_insert_augmented(&node->rb_hole_addr, root, &augment_callbacks);
|
||||
}
|
||||
|
||||
static void add_hole(struct drm_mm_node *node)
|
||||
{
|
||||
struct drm_mm *mm = node->mm;
|
||||
|
||||
node->hole_size =
|
||||
__drm_mm_hole_node_end(node) - __drm_mm_hole_node_start(node);
|
||||
node->subtree_max_hole = node->hole_size;
|
||||
DRM_MM_BUG_ON(!drm_mm_hole_follows(node));
|
||||
|
||||
insert_hole_size(&mm->holes_size, node);
|
||||
RB_INSERT(mm->holes_addr, rb_hole_addr, HOLE_ADDR);
|
||||
insert_hole_addr(&mm->holes_addr, node);
|
||||
|
||||
list_add(&node->hole_stack, &mm->hole_stack);
|
||||
}
|
||||
@ -275,8 +287,10 @@ static void rm_hole(struct drm_mm_node *node)
|
||||
|
||||
list_del(&node->hole_stack);
|
||||
rb_erase_cached(&node->rb_hole_size, &node->mm->holes_size);
|
||||
rb_erase(&node->rb_hole_addr, &node->mm->holes_addr);
|
||||
rb_erase_augmented(&node->rb_hole_addr, &node->mm->holes_addr,
|
||||
&augment_callbacks);
|
||||
node->hole_size = 0;
|
||||
node->subtree_max_hole = 0;
|
||||
|
||||
DRM_MM_BUG_ON(drm_mm_hole_follows(node));
|
||||
}
|
||||
@ -361,9 +375,90 @@ first_hole(struct drm_mm *mm,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* next_hole_high_addr - returns next hole for a DRM_MM_INSERT_HIGH mode request
|
||||
* @entry: previously selected drm_mm_node
|
||||
* @size: size of the a hole needed for the request
|
||||
*
|
||||
* This function will verify whether left subtree of @entry has hole big enough
|
||||
* to fit the requtested size. If so, it will return previous node of @entry or
|
||||
* else it will return parent node of @entry
|
||||
*
|
||||
* It will also skip the complete left subtree if subtree_max_hole of that
|
||||
* subtree is same as the subtree_max_hole of the @entry.
|
||||
*
|
||||
* Returns:
|
||||
* previous node of @entry if left subtree of @entry can serve the request or
|
||||
* else return parent of @entry
|
||||
*/
|
||||
static struct drm_mm_node *
|
||||
next_hole_high_addr(struct drm_mm_node *entry, u64 size)
|
||||
{
|
||||
struct rb_node *rb_node, *left_rb_node, *parent_rb_node;
|
||||
struct drm_mm_node *left_node;
|
||||
|
||||
if (!entry)
|
||||
return NULL;
|
||||
|
||||
rb_node = &entry->rb_hole_addr;
|
||||
if (rb_node->rb_left) {
|
||||
left_rb_node = rb_node->rb_left;
|
||||
parent_rb_node = rb_parent(rb_node);
|
||||
left_node = rb_entry(left_rb_node,
|
||||
struct drm_mm_node, rb_hole_addr);
|
||||
if ((left_node->subtree_max_hole < size ||
|
||||
entry->size == entry->subtree_max_hole) &&
|
||||
parent_rb_node && parent_rb_node->rb_left != rb_node)
|
||||
return rb_hole_addr_to_node(parent_rb_node);
|
||||
}
|
||||
|
||||
return rb_hole_addr_to_node(rb_prev(rb_node));
|
||||
}
|
||||
|
||||
/**
|
||||
* next_hole_low_addr - returns next hole for a DRM_MM_INSERT_LOW mode request
|
||||
* @entry: previously selected drm_mm_node
|
||||
* @size: size of the a hole needed for the request
|
||||
*
|
||||
* This function will verify whether right subtree of @entry has hole big enough
|
||||
* to fit the requtested size. If so, it will return next node of @entry or
|
||||
* else it will return parent node of @entry
|
||||
*
|
||||
* It will also skip the complete right subtree if subtree_max_hole of that
|
||||
* subtree is same as the subtree_max_hole of the @entry.
|
||||
*
|
||||
* Returns:
|
||||
* next node of @entry if right subtree of @entry can serve the request or
|
||||
* else return parent of @entry
|
||||
*/
|
||||
static struct drm_mm_node *
|
||||
next_hole_low_addr(struct drm_mm_node *entry, u64 size)
|
||||
{
|
||||
struct rb_node *rb_node, *right_rb_node, *parent_rb_node;
|
||||
struct drm_mm_node *right_node;
|
||||
|
||||
if (!entry)
|
||||
return NULL;
|
||||
|
||||
rb_node = &entry->rb_hole_addr;
|
||||
if (rb_node->rb_right) {
|
||||
right_rb_node = rb_node->rb_right;
|
||||
parent_rb_node = rb_parent(rb_node);
|
||||
right_node = rb_entry(right_rb_node,
|
||||
struct drm_mm_node, rb_hole_addr);
|
||||
if ((right_node->subtree_max_hole < size ||
|
||||
entry->size == entry->subtree_max_hole) &&
|
||||
parent_rb_node && parent_rb_node->rb_right != rb_node)
|
||||
return rb_hole_addr_to_node(parent_rb_node);
|
||||
}
|
||||
|
||||
return rb_hole_addr_to_node(rb_next(rb_node));
|
||||
}
|
||||
|
||||
static struct drm_mm_node *
|
||||
next_hole(struct drm_mm *mm,
|
||||
struct drm_mm_node *node,
|
||||
u64 size,
|
||||
enum drm_mm_insert_mode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
@ -372,10 +467,10 @@ next_hole(struct drm_mm *mm,
|
||||
return rb_hole_size_to_node(rb_prev(&node->rb_hole_size));
|
||||
|
||||
case DRM_MM_INSERT_LOW:
|
||||
return rb_hole_addr_to_node(rb_next(&node->rb_hole_addr));
|
||||
return next_hole_low_addr(node, size);
|
||||
|
||||
case DRM_MM_INSERT_HIGH:
|
||||
return rb_hole_addr_to_node(rb_prev(&node->rb_hole_addr));
|
||||
return next_hole_high_addr(node, size);
|
||||
|
||||
case DRM_MM_INSERT_EVICT:
|
||||
node = list_next_entry(node, hole_stack);
|
||||
@ -489,7 +584,7 @@ int drm_mm_insert_node_in_range(struct drm_mm * const mm,
|
||||
remainder_mask = is_power_of_2(alignment) ? alignment - 1 : 0;
|
||||
for (hole = first_hole(mm, range_start, range_end, size, mode);
|
||||
hole;
|
||||
hole = once ? NULL : next_hole(mm, hole, mode)) {
|
||||
hole = once ? NULL : next_hole(mm, hole, size, mode)) {
|
||||
u64 hole_start = __drm_mm_hole_node_start(hole);
|
||||
u64 hole_end = hole_start + hole->hole_size;
|
||||
u64 adj_start, adj_end;
|
||||
|
@ -402,12 +402,13 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
|
||||
{
|
||||
struct drm_mode_obj_get_properties *arg = data;
|
||||
struct drm_mode_object *obj;
|
||||
struct drm_modeset_acquire_ctx ctx;
|
||||
int ret = 0;
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
drm_modeset_lock_all(dev);
|
||||
DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, ret);
|
||||
|
||||
obj = drm_mode_object_find(dev, file_priv, arg->obj_id, arg->obj_type);
|
||||
if (!obj) {
|
||||
@ -427,7 +428,7 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
|
||||
out_unref:
|
||||
drm_mode_object_put(obj);
|
||||
out:
|
||||
drm_modeset_unlock_all(dev);
|
||||
DRM_MODESET_LOCK_ALL_END(ctx, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -449,12 +450,13 @@ static int set_property_legacy(struct drm_mode_object *obj,
|
||||
{
|
||||
struct drm_device *dev = prop->dev;
|
||||
struct drm_mode_object *ref;
|
||||
struct drm_modeset_acquire_ctx ctx;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (!drm_property_change_valid_get(prop, prop_value, &ref))
|
||||
return -EINVAL;
|
||||
|
||||
drm_modeset_lock_all(dev);
|
||||
DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, ret);
|
||||
switch (obj->type) {
|
||||
case DRM_MODE_OBJECT_CONNECTOR:
|
||||
ret = drm_connector_set_obj_prop(obj, prop, prop_value);
|
||||
@ -468,7 +470,7 @@ static int set_property_legacy(struct drm_mode_object *obj,
|
||||
break;
|
||||
}
|
||||
drm_property_change_valid_put(prop, ref);
|
||||
drm_modeset_unlock_all(dev);
|
||||
DRM_MODESET_LOCK_ALL_END(ctx, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -747,32 +747,6 @@ void drm_mode_set_name(struct drm_display_mode *mode)
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_set_name);
|
||||
|
||||
/**
|
||||
* drm_mode_hsync - get the hsync of a mode
|
||||
* @mode: mode
|
||||
*
|
||||
* Returns:
|
||||
* @modes's hsync rate in kHz, rounded to the nearest integer. Calculates the
|
||||
* value first if it is not yet set.
|
||||
*/
|
||||
int drm_mode_hsync(const struct drm_display_mode *mode)
|
||||
{
|
||||
unsigned int calc_val;
|
||||
|
||||
if (mode->hsync)
|
||||
return mode->hsync;
|
||||
|
||||
if (mode->htotal <= 0)
|
||||
return 0;
|
||||
|
||||
calc_val = (mode->clock * 1000) / mode->htotal; /* hsync in Hz */
|
||||
calc_val += 500; /* round to 1000Hz */
|
||||
calc_val /= 1000; /* truncate to kHz */
|
||||
|
||||
return calc_val;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_hsync);
|
||||
|
||||
/**
|
||||
* drm_mode_vrefresh - get the vrefresh of a mode
|
||||
* @mode: mode
|
||||
|
@ -8875,7 +8875,6 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
|
||||
|
||||
mode->clock = pipe_config->hw.adjusted_mode.crtc_clock;
|
||||
|
||||
mode->hsync = drm_mode_hsync(mode);
|
||||
mode->vrefresh = drm_mode_vrefresh(mode);
|
||||
drm_mode_set_name(mode);
|
||||
}
|
||||
|
@ -877,19 +877,11 @@ i915_driver_create(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
(struct intel_device_info *)ent->driver_data;
|
||||
struct intel_device_info *device_info;
|
||||
struct drm_i915_private *i915;
|
||||
int err;
|
||||
|
||||
i915 = kzalloc(sizeof(*i915), GFP_KERNEL);
|
||||
if (!i915)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
err = drm_dev_init(&i915->drm, &driver, &pdev->dev);
|
||||
if (err) {
|
||||
kfree(i915);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
drmm_add_final_kfree(&i915->drm, i915);
|
||||
i915 = devm_drm_dev_alloc(&pdev->dev, &driver,
|
||||
struct drm_i915_private, drm);
|
||||
if (IS_ERR(i915))
|
||||
return i915;
|
||||
|
||||
i915->drm.pdev = pdev;
|
||||
pci_set_drvdata(pdev, i915);
|
||||
@ -1006,7 +998,6 @@ out_pci_disable:
|
||||
pci_disable_device(pdev);
|
||||
out_fini:
|
||||
i915_probe_error(i915, "Device initialization failed (%d)\n", ret);
|
||||
drm_dev_put(&i915->drm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -941,8 +941,6 @@ static void i915_pci_remove(struct pci_dev *pdev)
|
||||
|
||||
i915_driver_remove(i915);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
|
||||
drm_dev_put(&i915->drm);
|
||||
}
|
||||
|
||||
/* is device_id present in comma separated list of ids */
|
||||
|
@ -611,24 +611,17 @@ static int ingenic_drm_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
priv = devm_drm_dev_alloc(dev, &ingenic_drm_driver_data,
|
||||
struct ingenic_drm, drm);
|
||||
if (IS_ERR(priv))
|
||||
return PTR_ERR(priv);
|
||||
|
||||
priv->soc_info = soc_info;
|
||||
priv->dev = dev;
|
||||
drm = &priv->drm;
|
||||
drm->dev_private = priv;
|
||||
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
ret = devm_drm_dev_init(dev, drm, &ingenic_drm_driver_data);
|
||||
if (ret) {
|
||||
kfree(priv);
|
||||
return ret;
|
||||
}
|
||||
drmm_add_final_kfree(drm, priv);
|
||||
|
||||
ret = drmm_mode_config_init(drm);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -26,18 +26,33 @@ void lima_bcast_enable(struct lima_device *dev, int num_pp)
|
||||
bcast_write(LIMA_BCAST_BROADCAST_MASK, mask);
|
||||
}
|
||||
|
||||
static int lima_bcast_hw_init(struct lima_ip *ip)
|
||||
{
|
||||
bcast_write(LIMA_BCAST_BROADCAST_MASK, ip->data.mask << 16);
|
||||
bcast_write(LIMA_BCAST_INTERRUPT_MASK, ip->data.mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lima_bcast_resume(struct lima_ip *ip)
|
||||
{
|
||||
return lima_bcast_hw_init(ip);
|
||||
}
|
||||
|
||||
void lima_bcast_suspend(struct lima_ip *ip)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int lima_bcast_init(struct lima_ip *ip)
|
||||
{
|
||||
int i, mask = 0;
|
||||
int i;
|
||||
|
||||
for (i = lima_ip_pp0; i <= lima_ip_pp7; i++) {
|
||||
if (ip->dev->ip[i].present)
|
||||
mask |= 1 << (i - lima_ip_pp0);
|
||||
ip->data.mask |= 1 << (i - lima_ip_pp0);
|
||||
}
|
||||
|
||||
bcast_write(LIMA_BCAST_BROADCAST_MASK, mask << 16);
|
||||
bcast_write(LIMA_BCAST_INTERRUPT_MASK, mask);
|
||||
return 0;
|
||||
return lima_bcast_hw_init(ip);
|
||||
}
|
||||
|
||||
void lima_bcast_fini(struct lima_ip *ip)
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
struct lima_ip;
|
||||
|
||||
int lima_bcast_resume(struct lima_ip *ip);
|
||||
void lima_bcast_suspend(struct lima_ip *ip);
|
||||
int lima_bcast_init(struct lima_ip *ip);
|
||||
void lima_bcast_fini(struct lima_ip *ip);
|
||||
|
||||
|
@ -101,13 +101,12 @@ void lima_devfreq_fini(struct lima_device *ldev)
|
||||
}
|
||||
|
||||
if (devfreq->devfreq) {
|
||||
devm_devfreq_remove_device(&ldev->pdev->dev,
|
||||
devfreq->devfreq);
|
||||
devm_devfreq_remove_device(ldev->dev, devfreq->devfreq);
|
||||
devfreq->devfreq = NULL;
|
||||
}
|
||||
|
||||
if (devfreq->opp_of_table_added) {
|
||||
dev_pm_opp_of_remove_table(&ldev->pdev->dev);
|
||||
dev_pm_opp_of_remove_table(ldev->dev);
|
||||
devfreq->opp_of_table_added = false;
|
||||
}
|
||||
|
||||
@ -125,7 +124,7 @@ void lima_devfreq_fini(struct lima_device *ldev)
|
||||
int lima_devfreq_init(struct lima_device *ldev)
|
||||
{
|
||||
struct thermal_cooling_device *cooling;
|
||||
struct device *dev = &ldev->pdev->dev;
|
||||
struct device *dev = ldev->dev;
|
||||
struct opp_table *opp_table;
|
||||
struct devfreq *devfreq;
|
||||
struct lima_devfreq *ldevfreq = &ldev->devfreq;
|
||||
@ -232,3 +231,27 @@ void lima_devfreq_record_idle(struct lima_devfreq *devfreq)
|
||||
|
||||
spin_unlock_irqrestore(&devfreq->lock, irqflags);
|
||||
}
|
||||
|
||||
int lima_devfreq_resume(struct lima_devfreq *devfreq)
|
||||
{
|
||||
unsigned long irqflags;
|
||||
|
||||
if (!devfreq->devfreq)
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(&devfreq->lock, irqflags);
|
||||
|
||||
lima_devfreq_reset(devfreq);
|
||||
|
||||
spin_unlock_irqrestore(&devfreq->lock, irqflags);
|
||||
|
||||
return devfreq_resume_device(devfreq->devfreq);
|
||||
}
|
||||
|
||||
int lima_devfreq_suspend(struct lima_devfreq *devfreq)
|
||||
{
|
||||
if (!devfreq->devfreq)
|
||||
return 0;
|
||||
|
||||
return devfreq_suspend_device(devfreq->devfreq);
|
||||
}
|
||||
|
@ -38,4 +38,7 @@ void lima_devfreq_fini(struct lima_device *ldev);
|
||||
void lima_devfreq_record_busy(struct lima_devfreq *devfreq);
|
||||
void lima_devfreq_record_idle(struct lima_devfreq *devfreq);
|
||||
|
||||
int lima_devfreq_resume(struct lima_devfreq *devfreq);
|
||||
int lima_devfreq_suspend(struct lima_devfreq *devfreq);
|
||||
|
||||
#endif
|
||||
|
@ -25,6 +25,8 @@ struct lima_ip_desc {
|
||||
|
||||
int (*init)(struct lima_ip *ip);
|
||||
void (*fini)(struct lima_ip *ip);
|
||||
int (*resume)(struct lima_ip *ip);
|
||||
void (*suspend)(struct lima_ip *ip);
|
||||
};
|
||||
|
||||
#define LIMA_IP_DESC(ipname, mst0, mst1, off0, off1, func, irq) \
|
||||
@ -41,6 +43,8 @@ struct lima_ip_desc {
|
||||
}, \
|
||||
.init = lima_##func##_init, \
|
||||
.fini = lima_##func##_fini, \
|
||||
.resume = lima_##func##_resume, \
|
||||
.suspend = lima_##func##_suspend, \
|
||||
}
|
||||
|
||||
static struct lima_ip_desc lima_ip_desc[lima_ip_num] = {
|
||||
@ -77,26 +81,10 @@ const char *lima_ip_name(struct lima_ip *ip)
|
||||
return lima_ip_desc[ip->id].name;
|
||||
}
|
||||
|
||||
static int lima_clk_init(struct lima_device *dev)
|
||||
static int lima_clk_enable(struct lima_device *dev)
|
||||
{
|
||||
int err;
|
||||
|
||||
dev->clk_bus = devm_clk_get(dev->dev, "bus");
|
||||
if (IS_ERR(dev->clk_bus)) {
|
||||
err = PTR_ERR(dev->clk_bus);
|
||||
if (err != -EPROBE_DEFER)
|
||||
dev_err(dev->dev, "get bus clk failed %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
dev->clk_gpu = devm_clk_get(dev->dev, "core");
|
||||
if (IS_ERR(dev->clk_gpu)) {
|
||||
err = PTR_ERR(dev->clk_gpu);
|
||||
if (err != -EPROBE_DEFER)
|
||||
dev_err(dev->dev, "get core clk failed %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = clk_prepare_enable(dev->clk_bus);
|
||||
if (err)
|
||||
return err;
|
||||
@ -105,15 +93,7 @@ static int lima_clk_init(struct lima_device *dev)
|
||||
if (err)
|
||||
goto error_out0;
|
||||
|
||||
dev->reset = devm_reset_control_array_get_optional_shared(dev->dev);
|
||||
|
||||
if (IS_ERR(dev->reset)) {
|
||||
err = PTR_ERR(dev->reset);
|
||||
if (err != -EPROBE_DEFER)
|
||||
dev_err(dev->dev, "get reset controller failed %d\n",
|
||||
err);
|
||||
goto error_out1;
|
||||
} else if (dev->reset != NULL) {
|
||||
if (dev->reset) {
|
||||
err = reset_control_deassert(dev->reset);
|
||||
if (err) {
|
||||
dev_err(dev->dev,
|
||||
@ -131,14 +111,76 @@ error_out0:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void lima_clk_fini(struct lima_device *dev)
|
||||
static void lima_clk_disable(struct lima_device *dev)
|
||||
{
|
||||
if (dev->reset != NULL)
|
||||
if (dev->reset)
|
||||
reset_control_assert(dev->reset);
|
||||
clk_disable_unprepare(dev->clk_gpu);
|
||||
clk_disable_unprepare(dev->clk_bus);
|
||||
}
|
||||
|
||||
static int lima_clk_init(struct lima_device *dev)
|
||||
{
|
||||
int err;
|
||||
|
||||
dev->clk_bus = devm_clk_get(dev->dev, "bus");
|
||||
if (IS_ERR(dev->clk_bus)) {
|
||||
err = PTR_ERR(dev->clk_bus);
|
||||
if (err != -EPROBE_DEFER)
|
||||
dev_err(dev->dev, "get bus clk failed %d\n", err);
|
||||
dev->clk_bus = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
dev->clk_gpu = devm_clk_get(dev->dev, "core");
|
||||
if (IS_ERR(dev->clk_gpu)) {
|
||||
err = PTR_ERR(dev->clk_gpu);
|
||||
if (err != -EPROBE_DEFER)
|
||||
dev_err(dev->dev, "get core clk failed %d\n", err);
|
||||
dev->clk_gpu = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
dev->reset = devm_reset_control_array_get_optional_shared(dev->dev);
|
||||
if (IS_ERR(dev->reset)) {
|
||||
err = PTR_ERR(dev->reset);
|
||||
if (err != -EPROBE_DEFER)
|
||||
dev_err(dev->dev, "get reset controller failed %d\n",
|
||||
err);
|
||||
dev->reset = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
return lima_clk_enable(dev);
|
||||
}
|
||||
|
||||
static void lima_clk_fini(struct lima_device *dev)
|
||||
{
|
||||
lima_clk_disable(dev);
|
||||
}
|
||||
|
||||
static int lima_regulator_enable(struct lima_device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!dev->regulator)
|
||||
return 0;
|
||||
|
||||
ret = regulator_enable(dev->regulator);
|
||||
if (ret < 0) {
|
||||
dev_err(dev->dev, "failed to enable regulator: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lima_regulator_disable(struct lima_device *dev)
|
||||
{
|
||||
if (dev->regulator)
|
||||
regulator_disable(dev->regulator);
|
||||
}
|
||||
|
||||
static int lima_regulator_init(struct lima_device *dev)
|
||||
{
|
||||
int ret;
|
||||
@ -154,25 +196,20 @@ static int lima_regulator_init(struct lima_device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regulator_enable(dev->regulator);
|
||||
if (ret < 0) {
|
||||
dev_err(dev->dev, "failed to enable regulator: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return lima_regulator_enable(dev);
|
||||
}
|
||||
|
||||
static void lima_regulator_fini(struct lima_device *dev)
|
||||
{
|
||||
if (dev->regulator)
|
||||
regulator_disable(dev->regulator);
|
||||
lima_regulator_disable(dev);
|
||||
}
|
||||
|
||||
static int lima_init_ip(struct lima_device *dev, int index)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev->dev);
|
||||
struct lima_ip_desc *desc = lima_ip_desc + index;
|
||||
struct lima_ip *ip = dev->ip + index;
|
||||
const char *irq_name = desc->irq_name;
|
||||
int offset = desc->offset[dev->id];
|
||||
bool must = desc->must_have[dev->id];
|
||||
int err;
|
||||
@ -183,8 +220,9 @@ static int lima_init_ip(struct lima_device *dev, int index)
|
||||
ip->dev = dev;
|
||||
ip->id = index;
|
||||
ip->iomem = dev->iomem + offset;
|
||||
if (desc->irq_name) {
|
||||
err = platform_get_irq_byname(dev->pdev, desc->irq_name);
|
||||
if (irq_name) {
|
||||
err = must ? platform_get_irq_byname(pdev, irq_name) :
|
||||
platform_get_irq_byname_optional(pdev, irq_name);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
ip->irq = err;
|
||||
@ -209,6 +247,27 @@ static void lima_fini_ip(struct lima_device *ldev, int index)
|
||||
desc->fini(ip);
|
||||
}
|
||||
|
||||
static int lima_resume_ip(struct lima_device *ldev, int index)
|
||||
{
|
||||
struct lima_ip_desc *desc = lima_ip_desc + index;
|
||||
struct lima_ip *ip = ldev->ip + index;
|
||||
int ret = 0;
|
||||
|
||||
if (ip->present)
|
||||
ret = desc->resume(ip);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void lima_suspend_ip(struct lima_device *ldev, int index)
|
||||
{
|
||||
struct lima_ip_desc *desc = lima_ip_desc + index;
|
||||
struct lima_ip *ip = ldev->ip + index;
|
||||
|
||||
if (ip->present)
|
||||
desc->suspend(ip);
|
||||
}
|
||||
|
||||
static int lima_init_gp_pipe(struct lima_device *dev)
|
||||
{
|
||||
struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_gp;
|
||||
@ -294,8 +353,8 @@ static void lima_fini_pp_pipe(struct lima_device *dev)
|
||||
|
||||
int lima_device_init(struct lima_device *ldev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(ldev->dev);
|
||||
int err, i;
|
||||
struct resource *res;
|
||||
|
||||
dma_set_coherent_mask(ldev->dev, DMA_BIT_MASK(32));
|
||||
|
||||
@ -326,8 +385,7 @@ int lima_device_init(struct lima_device *ldev)
|
||||
} else
|
||||
ldev->va_end = LIMA_VA_RESERVE_END;
|
||||
|
||||
res = platform_get_resource(ldev->pdev, IORESOURCE_MEM, 0);
|
||||
ldev->iomem = devm_ioremap_resource(ldev->dev, res);
|
||||
ldev->iomem = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(ldev->iomem)) {
|
||||
dev_err(ldev->dev, "fail to ioremap iomem\n");
|
||||
err = PTR_ERR(ldev->iomem);
|
||||
@ -404,3 +462,72 @@ void lima_device_fini(struct lima_device *ldev)
|
||||
|
||||
lima_clk_fini(ldev);
|
||||
}
|
||||
|
||||
int lima_device_resume(struct device *dev)
|
||||
{
|
||||
struct lima_device *ldev = dev_get_drvdata(dev);
|
||||
int i, err;
|
||||
|
||||
err = lima_clk_enable(ldev);
|
||||
if (err) {
|
||||
dev_err(dev, "resume clk fail %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = lima_regulator_enable(ldev);
|
||||
if (err) {
|
||||
dev_err(dev, "resume regulator fail %d\n", err);
|
||||
goto err_out0;
|
||||
}
|
||||
|
||||
for (i = 0; i < lima_ip_num; i++) {
|
||||
err = lima_resume_ip(ldev, i);
|
||||
if (err) {
|
||||
dev_err(dev, "resume ip %d fail\n", i);
|
||||
goto err_out1;
|
||||
}
|
||||
}
|
||||
|
||||
err = lima_devfreq_resume(&ldev->devfreq);
|
||||
if (err) {
|
||||
dev_err(dev, "devfreq resume fail\n");
|
||||
goto err_out1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_out1:
|
||||
while (--i >= 0)
|
||||
lima_suspend_ip(ldev, i);
|
||||
lima_regulator_disable(ldev);
|
||||
err_out0:
|
||||
lima_clk_disable(ldev);
|
||||
return err;
|
||||
}
|
||||
|
||||
int lima_device_suspend(struct device *dev)
|
||||
{
|
||||
struct lima_device *ldev = dev_get_drvdata(dev);
|
||||
int i, err;
|
||||
|
||||
/* check any task running */
|
||||
for (i = 0; i < lima_pipe_num; i++) {
|
||||
if (atomic_read(&ldev->pipe[i].base.hw_rq_count))
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
err = lima_devfreq_suspend(&ldev->devfreq);
|
||||
if (err) {
|
||||
dev_err(dev, "devfreq suspend fail\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
for (i = lima_ip_num - 1; i >= 0; i--)
|
||||
lima_suspend_ip(ldev, i);
|
||||
|
||||
lima_regulator_disable(ldev);
|
||||
|
||||
lima_clk_disable(ldev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -64,6 +64,8 @@ struct lima_ip {
|
||||
bool async_reset;
|
||||
/* l2 cache */
|
||||
spinlock_t lock;
|
||||
/* pmu/bcast */
|
||||
u32 mask;
|
||||
} data;
|
||||
};
|
||||
|
||||
@ -76,7 +78,6 @@ enum lima_pipe_id {
|
||||
struct lima_device {
|
||||
struct device *dev;
|
||||
struct drm_device *ddev;
|
||||
struct platform_device *pdev;
|
||||
|
||||
enum lima_gpu_id id;
|
||||
u32 gp_version;
|
||||
@ -139,4 +140,7 @@ static inline int lima_poll_timeout(struct lima_ip *ip, lima_poll_func_t func,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lima_device_suspend(struct device *dev);
|
||||
int lima_device_resume(struct device *dev);
|
||||
|
||||
#endif
|
||||
|
@ -42,7 +42,7 @@ void lima_dlbu_set_reg(struct lima_ip *ip, u32 *reg)
|
||||
dlbu_write(LIMA_DLBU_START_TILE_POS, reg[3]);
|
||||
}
|
||||
|
||||
int lima_dlbu_init(struct lima_ip *ip)
|
||||
static int lima_dlbu_hw_init(struct lima_ip *ip)
|
||||
{
|
||||
struct lima_device *dev = ip->dev;
|
||||
|
||||
@ -52,6 +52,21 @@ int lima_dlbu_init(struct lima_ip *ip)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lima_dlbu_resume(struct lima_ip *ip)
|
||||
{
|
||||
return lima_dlbu_hw_init(ip);
|
||||
}
|
||||
|
||||
void lima_dlbu_suspend(struct lima_ip *ip)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int lima_dlbu_init(struct lima_ip *ip)
|
||||
{
|
||||
return lima_dlbu_hw_init(ip);
|
||||
}
|
||||
|
||||
void lima_dlbu_fini(struct lima_ip *ip)
|
||||
{
|
||||
|
||||
|
@ -12,6 +12,8 @@ void lima_dlbu_disable(struct lima_device *dev);
|
||||
|
||||
void lima_dlbu_set_reg(struct lima_ip *ip, u32 *reg);
|
||||
|
||||
int lima_dlbu_resume(struct lima_ip *ip);
|
||||
void lima_dlbu_suspend(struct lima_ip *ip);
|
||||
int lima_dlbu_init(struct lima_ip *ip);
|
||||
void lima_dlbu_fini(struct lima_ip *ip);
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <drm/drm_ioctl.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_prime.h>
|
||||
@ -380,7 +381,6 @@ static int lima_pdev_probe(struct platform_device *pdev)
|
||||
goto err_out0;
|
||||
}
|
||||
|
||||
ldev->pdev = pdev;
|
||||
ldev->dev = &pdev->dev;
|
||||
ldev->id = (enum lima_gpu_id)of_device_get_match_data(&pdev->dev);
|
||||
|
||||
@ -404,6 +404,12 @@ static int lima_pdev_probe(struct platform_device *pdev)
|
||||
goto err_out2;
|
||||
}
|
||||
|
||||
pm_runtime_set_active(ldev->dev);
|
||||
pm_runtime_mark_last_busy(ldev->dev);
|
||||
pm_runtime_set_autosuspend_delay(ldev->dev, 200);
|
||||
pm_runtime_use_autosuspend(ldev->dev);
|
||||
pm_runtime_enable(ldev->dev);
|
||||
|
||||
/*
|
||||
* Register the DRM device with the core and the connectors with
|
||||
* sysfs.
|
||||
@ -412,17 +418,16 @@ static int lima_pdev_probe(struct platform_device *pdev)
|
||||
if (err < 0)
|
||||
goto err_out3;
|
||||
|
||||
platform_set_drvdata(pdev, ldev);
|
||||
|
||||
if (sysfs_create_bin_file(&ldev->dev->kobj, &lima_error_state_attr))
|
||||
dev_warn(ldev->dev, "fail to create error state sysfs\n");
|
||||
|
||||
return 0;
|
||||
|
||||
err_out3:
|
||||
lima_device_fini(ldev);
|
||||
err_out2:
|
||||
pm_runtime_disable(ldev->dev);
|
||||
lima_devfreq_fini(ldev);
|
||||
err_out2:
|
||||
lima_device_fini(ldev);
|
||||
err_out1:
|
||||
drm_dev_put(ddev);
|
||||
err_out0:
|
||||
@ -436,10 +441,16 @@ static int lima_pdev_remove(struct platform_device *pdev)
|
||||
struct drm_device *ddev = ldev->ddev;
|
||||
|
||||
sysfs_remove_bin_file(&ldev->dev->kobj, &lima_error_state_attr);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
drm_dev_unregister(ddev);
|
||||
|
||||
/* stop autosuspend to make sure device is in active state */
|
||||
pm_runtime_set_autosuspend_delay(ldev->dev, -1);
|
||||
pm_runtime_disable(ldev->dev);
|
||||
|
||||
lima_devfreq_fini(ldev);
|
||||
lima_device_fini(ldev);
|
||||
|
||||
drm_dev_put(ddev);
|
||||
lima_sched_slab_fini();
|
||||
return 0;
|
||||
@ -452,26 +463,22 @@ static const struct of_device_id dt_match[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, dt_match);
|
||||
|
||||
static const struct dev_pm_ops lima_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
|
||||
SET_RUNTIME_PM_OPS(lima_device_suspend, lima_device_resume, NULL)
|
||||
};
|
||||
|
||||
static struct platform_driver lima_platform_driver = {
|
||||
.probe = lima_pdev_probe,
|
||||
.remove = lima_pdev_remove,
|
||||
.driver = {
|
||||
.name = "lima",
|
||||
.pm = &lima_pm_ops,
|
||||
.of_match_table = dt_match,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init lima_init(void)
|
||||
{
|
||||
return platform_driver_register(&lima_platform_driver);
|
||||
}
|
||||
module_init(lima_init);
|
||||
|
||||
static void __exit lima_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&lima_platform_driver);
|
||||
}
|
||||
module_exit(lima_exit);
|
||||
module_platform_driver(lima_platform_driver);
|
||||
|
||||
MODULE_AUTHOR("Lima Project Developers");
|
||||
MODULE_DESCRIPTION("Lima DRM Driver");
|
||||
|
@ -274,6 +274,23 @@ static void lima_gp_print_version(struct lima_ip *ip)
|
||||
static struct kmem_cache *lima_gp_task_slab;
|
||||
static int lima_gp_task_slab_refcnt;
|
||||
|
||||
static int lima_gp_hw_init(struct lima_ip *ip)
|
||||
{
|
||||
ip->data.async_reset = false;
|
||||
lima_gp_soft_reset_async(ip);
|
||||
return lima_gp_soft_reset_async_wait(ip);
|
||||
}
|
||||
|
||||
int lima_gp_resume(struct lima_ip *ip)
|
||||
{
|
||||
return lima_gp_hw_init(ip);
|
||||
}
|
||||
|
||||
void lima_gp_suspend(struct lima_ip *ip)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int lima_gp_init(struct lima_ip *ip)
|
||||
{
|
||||
struct lima_device *dev = ip->dev;
|
||||
@ -281,9 +298,7 @@ int lima_gp_init(struct lima_ip *ip)
|
||||
|
||||
lima_gp_print_version(ip);
|
||||
|
||||
ip->data.async_reset = false;
|
||||
lima_gp_soft_reset_async(ip);
|
||||
err = lima_gp_soft_reset_async_wait(ip);
|
||||
err = lima_gp_hw_init(ip);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -7,6 +7,8 @@
|
||||
struct lima_ip;
|
||||
struct lima_device;
|
||||
|
||||
int lima_gp_resume(struct lima_ip *ip);
|
||||
void lima_gp_suspend(struct lima_ip *ip);
|
||||
int lima_gp_init(struct lima_ip *ip);
|
||||
void lima_gp_fini(struct lima_ip *ip);
|
||||
|
||||
|
@ -38,9 +38,35 @@ int lima_l2_cache_flush(struct lima_ip *ip)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lima_l2_cache_hw_init(struct lima_ip *ip)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = lima_l2_cache_flush(ip);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
l2_cache_write(LIMA_L2_CACHE_ENABLE,
|
||||
LIMA_L2_CACHE_ENABLE_ACCESS |
|
||||
LIMA_L2_CACHE_ENABLE_READ_ALLOCATE);
|
||||
l2_cache_write(LIMA_L2_CACHE_MAX_READS, 0x1c);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lima_l2_cache_resume(struct lima_ip *ip)
|
||||
{
|
||||
return lima_l2_cache_hw_init(ip);
|
||||
}
|
||||
|
||||
void lima_l2_cache_suspend(struct lima_ip *ip)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int lima_l2_cache_init(struct lima_ip *ip)
|
||||
{
|
||||
int i, err;
|
||||
int i;
|
||||
u32 size;
|
||||
struct lima_device *dev = ip->dev;
|
||||
|
||||
@ -63,15 +89,7 @@ int lima_l2_cache_init(struct lima_ip *ip)
|
||||
1 << (size & 0xff),
|
||||
1 << ((size >> 24) & 0xff));
|
||||
|
||||
err = lima_l2_cache_flush(ip);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
l2_cache_write(LIMA_L2_CACHE_ENABLE,
|
||||
LIMA_L2_CACHE_ENABLE_ACCESS|LIMA_L2_CACHE_ENABLE_READ_ALLOCATE);
|
||||
l2_cache_write(LIMA_L2_CACHE_MAX_READS, 0x1c);
|
||||
|
||||
return 0;
|
||||
return lima_l2_cache_hw_init(ip);
|
||||
}
|
||||
|
||||
void lima_l2_cache_fini(struct lima_ip *ip)
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
struct lima_ip;
|
||||
|
||||
int lima_l2_cache_resume(struct lima_ip *ip);
|
||||
void lima_l2_cache_suspend(struct lima_ip *ip);
|
||||
int lima_l2_cache_init(struct lima_ip *ip);
|
||||
void lima_l2_cache_fini(struct lima_ip *ip);
|
||||
|
||||
|
@ -59,12 +59,44 @@ static irqreturn_t lima_mmu_irq_handler(int irq, void *data)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
int lima_mmu_init(struct lima_ip *ip)
|
||||
static int lima_mmu_hw_init(struct lima_ip *ip)
|
||||
{
|
||||
struct lima_device *dev = ip->dev;
|
||||
int err;
|
||||
u32 v;
|
||||
|
||||
mmu_write(LIMA_MMU_COMMAND, LIMA_MMU_COMMAND_HARD_RESET);
|
||||
err = lima_mmu_send_command(LIMA_MMU_COMMAND_HARD_RESET,
|
||||
LIMA_MMU_DTE_ADDR, v, v == 0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mmu_write(LIMA_MMU_INT_MASK,
|
||||
LIMA_MMU_INT_PAGE_FAULT | LIMA_MMU_INT_READ_BUS_ERROR);
|
||||
mmu_write(LIMA_MMU_DTE_ADDR, dev->empty_vm->pd.dma);
|
||||
return lima_mmu_send_command(LIMA_MMU_COMMAND_ENABLE_PAGING,
|
||||
LIMA_MMU_STATUS, v,
|
||||
v & LIMA_MMU_STATUS_PAGING_ENABLED);
|
||||
}
|
||||
|
||||
int lima_mmu_resume(struct lima_ip *ip)
|
||||
{
|
||||
if (ip->id == lima_ip_ppmmu_bcast)
|
||||
return 0;
|
||||
|
||||
return lima_mmu_hw_init(ip);
|
||||
}
|
||||
|
||||
void lima_mmu_suspend(struct lima_ip *ip)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int lima_mmu_init(struct lima_ip *ip)
|
||||
{
|
||||
struct lima_device *dev = ip->dev;
|
||||
int err;
|
||||
|
||||
if (ip->id == lima_ip_ppmmu_bcast)
|
||||
return 0;
|
||||
|
||||
@ -74,12 +106,6 @@ int lima_mmu_init(struct lima_ip *ip)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
mmu_write(LIMA_MMU_COMMAND, LIMA_MMU_COMMAND_HARD_RESET);
|
||||
err = lima_mmu_send_command(LIMA_MMU_COMMAND_HARD_RESET,
|
||||
LIMA_MMU_DTE_ADDR, v, v == 0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = devm_request_irq(dev->dev, ip->irq, lima_mmu_irq_handler,
|
||||
IRQF_SHARED, lima_ip_name(ip), ip);
|
||||
if (err) {
|
||||
@ -87,11 +113,7 @@ int lima_mmu_init(struct lima_ip *ip)
|
||||
return err;
|
||||
}
|
||||
|
||||
mmu_write(LIMA_MMU_INT_MASK, LIMA_MMU_INT_PAGE_FAULT | LIMA_MMU_INT_READ_BUS_ERROR);
|
||||
mmu_write(LIMA_MMU_DTE_ADDR, dev->empty_vm->pd.dma);
|
||||
return lima_mmu_send_command(LIMA_MMU_COMMAND_ENABLE_PAGING,
|
||||
LIMA_MMU_STATUS, v,
|
||||
v & LIMA_MMU_STATUS_PAGING_ENABLED);
|
||||
return lima_mmu_hw_init(ip);
|
||||
}
|
||||
|
||||
void lima_mmu_fini(struct lima_ip *ip)
|
||||
@ -113,8 +135,7 @@ void lima_mmu_switch_vm(struct lima_ip *ip, struct lima_vm *vm)
|
||||
LIMA_MMU_STATUS, v,
|
||||
v & LIMA_MMU_STATUS_STALL_ACTIVE);
|
||||
|
||||
if (vm)
|
||||
mmu_write(LIMA_MMU_DTE_ADDR, vm->pd.dma);
|
||||
mmu_write(LIMA_MMU_DTE_ADDR, vm->pd.dma);
|
||||
|
||||
/* flush the TLB */
|
||||
mmu_write(LIMA_MMU_COMMAND, LIMA_MMU_COMMAND_ZAP_CACHE);
|
||||
|
@ -7,6 +7,8 @@
|
||||
struct lima_ip;
|
||||
struct lima_vm;
|
||||
|
||||
int lima_mmu_resume(struct lima_ip *ip);
|
||||
void lima_mmu_suspend(struct lima_ip *ip);
|
||||
int lima_mmu_init(struct lima_ip *ip);
|
||||
void lima_mmu_fini(struct lima_ip *ip);
|
||||
|
||||
|
@ -21,7 +21,7 @@ static int lima_pmu_wait_cmd(struct lima_ip *ip)
|
||||
v, v & LIMA_PMU_INT_CMD_MASK,
|
||||
100, 100000);
|
||||
if (err) {
|
||||
dev_err(dev->dev, "timeout wait pmd cmd\n");
|
||||
dev_err(dev->dev, "timeout wait pmu cmd\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -29,7 +29,41 @@ static int lima_pmu_wait_cmd(struct lima_ip *ip)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lima_pmu_init(struct lima_ip *ip)
|
||||
static u32 lima_pmu_get_ip_mask(struct lima_ip *ip)
|
||||
{
|
||||
struct lima_device *dev = ip->dev;
|
||||
u32 ret = 0;
|
||||
int i;
|
||||
|
||||
ret |= LIMA_PMU_POWER_GP0_MASK;
|
||||
|
||||
if (dev->id == lima_gpu_mali400) {
|
||||
ret |= LIMA_PMU_POWER_L2_MASK;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (dev->ip[lima_ip_pp0 + i].present)
|
||||
ret |= LIMA_PMU_POWER_PP_MASK(i);
|
||||
}
|
||||
} else {
|
||||
if (dev->ip[lima_ip_pp0].present)
|
||||
ret |= LIMA450_PMU_POWER_PP0_MASK;
|
||||
for (i = lima_ip_pp1; i <= lima_ip_pp3; i++) {
|
||||
if (dev->ip[i].present) {
|
||||
ret |= LIMA450_PMU_POWER_PP13_MASK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i = lima_ip_pp4; i <= lima_ip_pp7; i++) {
|
||||
if (dev->ip[i].present) {
|
||||
ret |= LIMA450_PMU_POWER_PP47_MASK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lima_pmu_hw_init(struct lima_ip *ip)
|
||||
{
|
||||
int err;
|
||||
u32 stat;
|
||||
@ -54,7 +88,44 @@ int lima_pmu_init(struct lima_ip *ip)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lima_pmu_hw_fini(struct lima_ip *ip)
|
||||
{
|
||||
u32 stat;
|
||||
|
||||
if (!ip->data.mask)
|
||||
ip->data.mask = lima_pmu_get_ip_mask(ip);
|
||||
|
||||
stat = ~pmu_read(LIMA_PMU_STATUS) & ip->data.mask;
|
||||
if (stat) {
|
||||
pmu_write(LIMA_PMU_POWER_DOWN, stat);
|
||||
|
||||
/* Don't wait for interrupt on Mali400 if all domains are
|
||||
* powered off because the HW won't generate an interrupt
|
||||
* in this case.
|
||||
*/
|
||||
if (ip->dev->id == lima_gpu_mali400)
|
||||
pmu_write(LIMA_PMU_INT_CLEAR, LIMA_PMU_INT_CMD_MASK);
|
||||
else
|
||||
lima_pmu_wait_cmd(ip);
|
||||
}
|
||||
}
|
||||
|
||||
int lima_pmu_resume(struct lima_ip *ip)
|
||||
{
|
||||
return lima_pmu_hw_init(ip);
|
||||
}
|
||||
|
||||
void lima_pmu_suspend(struct lima_ip *ip)
|
||||
{
|
||||
lima_pmu_hw_fini(ip);
|
||||
}
|
||||
|
||||
int lima_pmu_init(struct lima_ip *ip)
|
||||
{
|
||||
return lima_pmu_hw_init(ip);
|
||||
}
|
||||
|
||||
void lima_pmu_fini(struct lima_ip *ip)
|
||||
{
|
||||
|
||||
lima_pmu_hw_fini(ip);
|
||||
}
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
struct lima_ip;
|
||||
|
||||
int lima_pmu_resume(struct lima_ip *ip);
|
||||
void lima_pmu_suspend(struct lima_ip *ip);
|
||||
int lima_pmu_init(struct lima_ip *ip);
|
||||
void lima_pmu_fini(struct lima_ip *ip);
|
||||
|
||||
|
@ -223,6 +223,23 @@ static void lima_pp_print_version(struct lima_ip *ip)
|
||||
lima_ip_name(ip), name, major, minor);
|
||||
}
|
||||
|
||||
static int lima_pp_hw_init(struct lima_ip *ip)
|
||||
{
|
||||
ip->data.async_reset = false;
|
||||
lima_pp_soft_reset_async(ip);
|
||||
return lima_pp_soft_reset_async_wait(ip);
|
||||
}
|
||||
|
||||
int lima_pp_resume(struct lima_ip *ip)
|
||||
{
|
||||
return lima_pp_hw_init(ip);
|
||||
}
|
||||
|
||||
void lima_pp_suspend(struct lima_ip *ip)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int lima_pp_init(struct lima_ip *ip)
|
||||
{
|
||||
struct lima_device *dev = ip->dev;
|
||||
@ -230,9 +247,7 @@ int lima_pp_init(struct lima_ip *ip)
|
||||
|
||||
lima_pp_print_version(ip);
|
||||
|
||||
ip->data.async_reset = false;
|
||||
lima_pp_soft_reset_async(ip);
|
||||
err = lima_pp_soft_reset_async_wait(ip);
|
||||
err = lima_pp_hw_init(ip);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@ -254,6 +269,16 @@ void lima_pp_fini(struct lima_ip *ip)
|
||||
|
||||
}
|
||||
|
||||
int lima_pp_bcast_resume(struct lima_ip *ip)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void lima_pp_bcast_suspend(struct lima_ip *ip)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int lima_pp_bcast_init(struct lima_ip *ip)
|
||||
{
|
||||
struct lima_device *dev = ip->dev;
|
||||
|
@ -7,9 +7,13 @@
|
||||
struct lima_ip;
|
||||
struct lima_device;
|
||||
|
||||
int lima_pp_resume(struct lima_ip *ip);
|
||||
void lima_pp_suspend(struct lima_ip *ip);
|
||||
int lima_pp_init(struct lima_ip *ip);
|
||||
void lima_pp_fini(struct lima_ip *ip);
|
||||
|
||||
int lima_pp_bcast_resume(struct lima_ip *ip);
|
||||
void lima_pp_bcast_suspend(struct lima_ip *ip);
|
||||
int lima_pp_bcast_init(struct lima_ip *ip);
|
||||
void lima_pp_bcast_fini(struct lima_ip *ip);
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include "lima_devfreq.h"
|
||||
#include "lima_drv.h"
|
||||
@ -194,14 +195,36 @@ static struct dma_fence *lima_sched_dependency(struct drm_sched_job *job,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int lima_pm_busy(struct lima_device *ldev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* resume GPU if it has been suspended by runtime PM */
|
||||
ret = pm_runtime_get_sync(ldev->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
lima_devfreq_record_busy(&ldev->devfreq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lima_pm_idle(struct lima_device *ldev)
|
||||
{
|
||||
lima_devfreq_record_idle(&ldev->devfreq);
|
||||
|
||||
/* GPU can do auto runtime suspend */
|
||||
pm_runtime_mark_last_busy(ldev->dev);
|
||||
pm_runtime_put_autosuspend(ldev->dev);
|
||||
}
|
||||
|
||||
static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job)
|
||||
{
|
||||
struct lima_sched_task *task = to_lima_task(job);
|
||||
struct lima_sched_pipe *pipe = to_lima_pipe(job->sched);
|
||||
struct lima_device *ldev = pipe->ldev;
|
||||
struct lima_fence *fence;
|
||||
struct dma_fence *ret;
|
||||
struct lima_vm *vm = NULL, *last_vm = NULL;
|
||||
int i;
|
||||
int i, err;
|
||||
|
||||
/* after GPU reset */
|
||||
if (job->s_fence->finished.error < 0)
|
||||
@ -210,6 +233,13 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job)
|
||||
fence = lima_fence_create(pipe);
|
||||
if (!fence)
|
||||
return NULL;
|
||||
|
||||
err = lima_pm_busy(ldev);
|
||||
if (err < 0) {
|
||||
dma_fence_put(&fence->base);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
task->fence = &fence->base;
|
||||
|
||||
/* for caller usage of the fence, otherwise irq handler
|
||||
@ -217,8 +247,6 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job)
|
||||
*/
|
||||
ret = dma_fence_get(task->fence);
|
||||
|
||||
lima_devfreq_record_busy(&pipe->ldev->devfreq);
|
||||
|
||||
pipe->current_task = task;
|
||||
|
||||
/* this is needed for MMU to work correctly, otherwise GP/PP
|
||||
@ -239,22 +267,16 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job)
|
||||
for (i = 0; i < pipe->num_l2_cache; i++)
|
||||
lima_l2_cache_flush(pipe->l2_cache[i]);
|
||||
|
||||
if (task->vm != pipe->current_vm) {
|
||||
vm = lima_vm_get(task->vm);
|
||||
last_vm = pipe->current_vm;
|
||||
pipe->current_vm = task->vm;
|
||||
}
|
||||
lima_vm_put(pipe->current_vm);
|
||||
pipe->current_vm = lima_vm_get(task->vm);
|
||||
|
||||
if (pipe->bcast_mmu)
|
||||
lima_mmu_switch_vm(pipe->bcast_mmu, vm);
|
||||
lima_mmu_switch_vm(pipe->bcast_mmu, pipe->current_vm);
|
||||
else {
|
||||
for (i = 0; i < pipe->num_mmu; i++)
|
||||
lima_mmu_switch_vm(pipe->mmu[i], vm);
|
||||
lima_mmu_switch_vm(pipe->mmu[i], pipe->current_vm);
|
||||
}
|
||||
|
||||
if (last_vm)
|
||||
lima_vm_put(last_vm);
|
||||
|
||||
trace_lima_task_run(task);
|
||||
|
||||
pipe->error = false;
|
||||
@ -285,7 +307,8 @@ static void lima_sched_build_error_task_list(struct lima_sched_task *task)
|
||||
mutex_lock(&dev->error_task_list_lock);
|
||||
|
||||
if (dev->dump.num_tasks >= lima_max_error_tasks) {
|
||||
dev_info(dev->dev, "fail to save task state: error task list is full\n");
|
||||
dev_info(dev->dev, "fail to save task state from %s pid %d: "
|
||||
"error task list is full\n", ctx->pname, ctx->pid);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -394,6 +417,7 @@ static void lima_sched_timedout_job(struct drm_sched_job *job)
|
||||
{
|
||||
struct lima_sched_pipe *pipe = to_lima_pipe(job->sched);
|
||||
struct lima_sched_task *task = to_lima_task(job);
|
||||
struct lima_device *ldev = pipe->ldev;
|
||||
|
||||
if (!pipe->error)
|
||||
DRM_ERROR("lima job timeout\n");
|
||||
@ -415,13 +439,11 @@ static void lima_sched_timedout_job(struct drm_sched_job *job)
|
||||
lima_mmu_page_fault_resume(pipe->mmu[i]);
|
||||
}
|
||||
|
||||
if (pipe->current_vm)
|
||||
lima_vm_put(pipe->current_vm);
|
||||
|
||||
lima_vm_put(pipe->current_vm);
|
||||
pipe->current_vm = NULL;
|
||||
pipe->current_task = NULL;
|
||||
|
||||
lima_devfreq_record_idle(&pipe->ldev->devfreq);
|
||||
lima_pm_idle(ldev);
|
||||
|
||||
drm_sched_resubmit_jobs(&pipe->base);
|
||||
drm_sched_start(&pipe->base, true);
|
||||
@ -493,6 +515,7 @@ void lima_sched_pipe_fini(struct lima_sched_pipe *pipe)
|
||||
void lima_sched_pipe_task_done(struct lima_sched_pipe *pipe)
|
||||
{
|
||||
struct lima_sched_task *task = pipe->current_task;
|
||||
struct lima_device *ldev = pipe->ldev;
|
||||
|
||||
if (pipe->error) {
|
||||
if (task && task->recoverable)
|
||||
@ -503,6 +526,6 @@ void lima_sched_pipe_task_done(struct lima_sched_pipe *pipe)
|
||||
pipe->task_fini(pipe);
|
||||
dma_fence_signal(task->fence);
|
||||
|
||||
lima_devfreq_record_idle(&pipe->ldev->devfreq);
|
||||
lima_pm_idle(ldev);
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +54,8 @@ static inline struct lima_vm *lima_vm_get(struct lima_vm *vm)
|
||||
|
||||
static inline void lima_vm_put(struct lima_vm *vm)
|
||||
{
|
||||
kref_put(&vm->refcount, lima_vm_release);
|
||||
if (vm)
|
||||
kref_put(&vm->refcount, lima_vm_release);
|
||||
}
|
||||
|
||||
void lima_vm_print(struct lima_vm *vm);
|
||||
|
@ -948,7 +948,7 @@ static void mcde_display_disable(struct drm_simple_display_pipe *pipe)
|
||||
{
|
||||
struct drm_crtc *crtc = &pipe->crtc;
|
||||
struct drm_device *drm = crtc->dev;
|
||||
struct mcde *mcde = drm->dev_private;
|
||||
struct mcde *mcde = to_mcde(drm);
|
||||
struct drm_pending_vblank_event *event;
|
||||
|
||||
drm_crtc_vblank_off(crtc);
|
||||
@ -1020,7 +1020,7 @@ static void mcde_display_update(struct drm_simple_display_pipe *pipe,
|
||||
{
|
||||
struct drm_crtc *crtc = &pipe->crtc;
|
||||
struct drm_device *drm = crtc->dev;
|
||||
struct mcde *mcde = drm->dev_private;
|
||||
struct mcde *mcde = to_mcde(drm);
|
||||
struct drm_pending_vblank_event *event = crtc->state->event;
|
||||
struct drm_plane *plane = &pipe->plane;
|
||||
struct drm_plane_state *pstate = plane->state;
|
||||
@ -1078,7 +1078,7 @@ static int mcde_display_enable_vblank(struct drm_simple_display_pipe *pipe)
|
||||
{
|
||||
struct drm_crtc *crtc = &pipe->crtc;
|
||||
struct drm_device *drm = crtc->dev;
|
||||
struct mcde *mcde = drm->dev_private;
|
||||
struct mcde *mcde = to_mcde(drm);
|
||||
u32 val;
|
||||
|
||||
/* Enable all VBLANK IRQs */
|
||||
@ -1097,7 +1097,7 @@ static void mcde_display_disable_vblank(struct drm_simple_display_pipe *pipe)
|
||||
{
|
||||
struct drm_crtc *crtc = &pipe->crtc;
|
||||
struct drm_device *drm = crtc->dev;
|
||||
struct mcde *mcde = drm->dev_private;
|
||||
struct mcde *mcde = to_mcde(drm);
|
||||
|
||||
/* Disable all VBLANK IRQs */
|
||||
writel(0, mcde->regs + MCDE_IMSCPP);
|
||||
@ -1117,7 +1117,7 @@ static struct drm_simple_display_pipe_funcs mcde_display_funcs = {
|
||||
|
||||
int mcde_display_init(struct drm_device *drm)
|
||||
{
|
||||
struct mcde *mcde = drm->dev_private;
|
||||
struct mcde *mcde = to_mcde(drm);
|
||||
int ret;
|
||||
static const u32 formats[] = {
|
||||
DRM_FORMAT_ARGB8888,
|
||||
|
@ -34,6 +34,8 @@ struct mcde {
|
||||
struct regulator *vana;
|
||||
};
|
||||
|
||||
#define to_mcde(dev) container_of(dev, struct mcde, drm)
|
||||
|
||||
bool mcde_dsi_irq(struct mipi_dsi_device *mdsi);
|
||||
void mcde_dsi_te_request(struct mipi_dsi_device *mdsi);
|
||||
extern struct platform_driver mcde_dsi_driver;
|
||||
|
@ -164,7 +164,7 @@ static irqreturn_t mcde_irq(int irq, void *data)
|
||||
static int mcde_modeset_init(struct drm_device *drm)
|
||||
{
|
||||
struct drm_mode_config *mode_config;
|
||||
struct mcde *mcde = drm->dev_private;
|
||||
struct mcde *mcde = to_mcde(drm);
|
||||
int ret;
|
||||
|
||||
if (!mcde->bridge) {
|
||||
@ -307,24 +307,15 @@ static int mcde_probe(struct platform_device *pdev)
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
mcde = kzalloc(sizeof(*mcde), GFP_KERNEL);
|
||||
if (!mcde)
|
||||
return -ENOMEM;
|
||||
mcde->dev = dev;
|
||||
|
||||
ret = devm_drm_dev_init(dev, &mcde->drm, &mcde_drm_driver);
|
||||
if (ret) {
|
||||
kfree(mcde);
|
||||
return ret;
|
||||
}
|
||||
mcde = devm_drm_dev_alloc(dev, &mcde_drm_driver, struct mcde, drm);
|
||||
if (IS_ERR(mcde))
|
||||
return PTR_ERR(mcde);
|
||||
drm = &mcde->drm;
|
||||
drm->dev_private = mcde;
|
||||
drmm_add_final_kfree(drm, mcde);
|
||||
mcde->dev = dev;
|
||||
platform_set_drvdata(pdev, drm);
|
||||
|
||||
/* Enable continuous updates: this is what Linux' framebuffer expects */
|
||||
mcde->oneshot_mode = false;
|
||||
drm->dev_private = mcde;
|
||||
|
||||
/* First obtain and turn on the main power */
|
||||
mcde->epod = devm_regulator_get(dev, "epod");
|
||||
@ -494,7 +485,7 @@ regulator_epod_off:
|
||||
static int mcde_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct drm_device *drm = platform_get_drvdata(pdev);
|
||||
struct mcde *mcde = drm->dev_private;
|
||||
struct mcde *mcde = to_mcde(drm);
|
||||
|
||||
component_master_del(&pdev->dev, &mcde_drm_comp_ops);
|
||||
clk_disable_unprepare(mcde->mcde_clk);
|
||||
|
@ -1020,7 +1020,7 @@ static int mcde_dsi_bind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
struct drm_device *drm = data;
|
||||
struct mcde *mcde = drm->dev_private;
|
||||
struct mcde *mcde = to_mcde(drm);
|
||||
struct mcde_dsi *d = dev_get_drvdata(dev);
|
||||
struct device_node *child;
|
||||
struct drm_panel *panel = NULL;
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/component.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/sys_soc.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/soc/amlogic/meson-canvas.h>
|
||||
|
||||
@ -183,6 +184,24 @@ static void meson_remove_framebuffers(void)
|
||||
kfree(ap);
|
||||
}
|
||||
|
||||
struct meson_drm_soc_attr {
|
||||
struct meson_drm_soc_limits limits;
|
||||
const struct soc_device_attribute *attrs;
|
||||
};
|
||||
|
||||
static const struct meson_drm_soc_attr meson_drm_soc_attrs[] = {
|
||||
/* S805X/S805Y HDMI PLL won't lock for HDMI PHY freq > 1,65GHz */
|
||||
{
|
||||
.limits = {
|
||||
.max_hdmi_phy_freq = 1650000,
|
||||
},
|
||||
.attrs = (const struct soc_device_attribute []) {
|
||||
{ .soc_id = "GXL (S805*)", },
|
||||
{ /* sentinel */ },
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
static int meson_drv_bind_master(struct device *dev, bool has_components)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
@ -191,7 +210,7 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
|
||||
struct drm_device *drm;
|
||||
struct resource *res;
|
||||
void __iomem *regs;
|
||||
int ret;
|
||||
int ret, i;
|
||||
|
||||
/* Checks if an output connector is available */
|
||||
if (!meson_vpu_has_available_connectors(dev)) {
|
||||
@ -281,6 +300,14 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
|
||||
if (ret)
|
||||
goto free_drm;
|
||||
|
||||
/* Assign limits per soc revision/package */
|
||||
for (i = 0 ; i < ARRAY_SIZE(meson_drm_soc_attrs) ; ++i) {
|
||||
if (soc_device_match(meson_drm_soc_attrs[i].attrs)) {
|
||||
priv->limits = &meson_drm_soc_attrs[i].limits;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove early framebuffers (ie. simplefb) */
|
||||
meson_remove_framebuffers();
|
||||
|
||||
|
@ -30,6 +30,10 @@ struct meson_drm_match_data {
|
||||
struct meson_afbcd_ops *afbcd_ops;
|
||||
};
|
||||
|
||||
struct meson_drm_soc_limits {
|
||||
unsigned int max_hdmi_phy_freq;
|
||||
};
|
||||
|
||||
struct meson_drm {
|
||||
struct device *dev;
|
||||
enum vpu_compatible compat;
|
||||
@ -48,6 +52,8 @@ struct meson_drm {
|
||||
struct drm_plane *primary_plane;
|
||||
struct drm_plane *overlay_plane;
|
||||
|
||||
const struct meson_drm_soc_limits *limits;
|
||||
|
||||
/* Components Data */
|
||||
struct {
|
||||
bool osd1_enabled;
|
||||
|
@ -695,7 +695,7 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
|
||||
dev_dbg(connector->dev->dev, "%s: vclk:%d phy=%d venc=%d hdmi=%d\n",
|
||||
__func__, phy_freq, vclk_freq, venc_freq, hdmi_freq);
|
||||
|
||||
return meson_vclk_vic_supported_freq(phy_freq, vclk_freq);
|
||||
return meson_vclk_vic_supported_freq(priv, phy_freq, vclk_freq);
|
||||
}
|
||||
|
||||
/* Encoder */
|
||||
|
@ -223,7 +223,7 @@ static void meson_plane_atomic_update(struct drm_plane *plane,
|
||||
priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_16 |
|
||||
OSD_COLOR_MATRIX_16_RGB565;
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
switch (fb->format->format) {
|
||||
|
@ -725,6 +725,13 @@ meson_vclk_dmt_supported_freq(struct meson_drm *priv, unsigned int freq)
|
||||
/* In DMT mode, path after PLL is always /10 */
|
||||
freq *= 10;
|
||||
|
||||
/* Check against soc revision/package limits */
|
||||
if (priv->limits) {
|
||||
if (priv->limits->max_hdmi_phy_freq &&
|
||||
freq > priv->limits->max_hdmi_phy_freq)
|
||||
return MODE_CLOCK_HIGH;
|
||||
}
|
||||
|
||||
if (meson_hdmi_pll_find_params(priv, freq, &m, &frac, &od))
|
||||
return MODE_OK;
|
||||
|
||||
@ -762,7 +769,7 @@ static void meson_hdmi_pll_generic_set(struct meson_drm *priv,
|
||||
}
|
||||
|
||||
enum drm_mode_status
|
||||
meson_vclk_vic_supported_freq(unsigned int phy_freq,
|
||||
meson_vclk_vic_supported_freq(struct meson_drm *priv, unsigned int phy_freq,
|
||||
unsigned int vclk_freq)
|
||||
{
|
||||
int i;
|
||||
@ -770,6 +777,13 @@ meson_vclk_vic_supported_freq(unsigned int phy_freq,
|
||||
DRM_DEBUG_DRIVER("phy_freq = %d vclk_freq = %d\n",
|
||||
phy_freq, vclk_freq);
|
||||
|
||||
/* Check against soc revision/package limits */
|
||||
if (priv->limits) {
|
||||
if (priv->limits->max_hdmi_phy_freq &&
|
||||
phy_freq > priv->limits->max_hdmi_phy_freq)
|
||||
return MODE_CLOCK_HIGH;
|
||||
}
|
||||
|
||||
for (i = 0 ; params[i].pixel_freq ; ++i) {
|
||||
DRM_DEBUG_DRIVER("i = %d pixel_freq = %d alt = %d\n",
|
||||
i, params[i].pixel_freq,
|
||||
|
@ -25,7 +25,8 @@ enum {
|
||||
enum drm_mode_status
|
||||
meson_vclk_dmt_supported_freq(struct meson_drm *priv, unsigned int freq);
|
||||
enum drm_mode_status
|
||||
meson_vclk_vic_supported_freq(unsigned int phy_freq, unsigned int vclk_freq);
|
||||
meson_vclk_vic_supported_freq(struct meson_drm *priv, unsigned int phy_freq,
|
||||
unsigned int vclk_freq);
|
||||
|
||||
void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
|
||||
unsigned int phy_freq, unsigned int vclk_freq,
|
||||
|
@ -3137,33 +3137,12 @@ static void _dispc_mgr_set_lcd_timings(struct dispc_device *dispc,
|
||||
dispc_write_reg(dispc, DISPC_TIMING_H(channel), timing_h);
|
||||
dispc_write_reg(dispc, DISPC_TIMING_V(channel), timing_v);
|
||||
|
||||
if (vm->flags & DISPLAY_FLAGS_VSYNC_HIGH)
|
||||
vs = false;
|
||||
else
|
||||
vs = true;
|
||||
|
||||
if (vm->flags & DISPLAY_FLAGS_HSYNC_HIGH)
|
||||
hs = false;
|
||||
else
|
||||
hs = true;
|
||||
|
||||
if (vm->flags & DISPLAY_FLAGS_DE_HIGH)
|
||||
de = false;
|
||||
else
|
||||
de = true;
|
||||
|
||||
if (vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
|
||||
ipc = false;
|
||||
else
|
||||
ipc = true;
|
||||
|
||||
/* always use the 'rf' setting */
|
||||
onoff = true;
|
||||
|
||||
if (vm->flags & DISPLAY_FLAGS_SYNC_POSEDGE)
|
||||
rf = true;
|
||||
else
|
||||
rf = false;
|
||||
vs = !!(vm->flags & DISPLAY_FLAGS_VSYNC_LOW);
|
||||
hs = !!(vm->flags & DISPLAY_FLAGS_HSYNC_LOW);
|
||||
de = !!(vm->flags & DISPLAY_FLAGS_DE_LOW);
|
||||
ipc = !!(vm->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE);
|
||||
onoff = true; /* always use the 'rf' setting */
|
||||
rf = !!(vm->flags & DISPLAY_FLAGS_SYNC_POSEDGE);
|
||||
|
||||
l = FLD_VAL(onoff, 17, 17) |
|
||||
FLD_VAL(rf, 16, 16) |
|
||||
|
@ -208,49 +208,6 @@ static const struct venc_config venc_config_ntsc_trm = {
|
||||
.gen_ctrl = 0x00F90000,
|
||||
};
|
||||
|
||||
static const struct venc_config venc_config_pal_bdghi = {
|
||||
.f_control = 0,
|
||||
.vidout_ctrl = 0,
|
||||
.sync_ctrl = 0,
|
||||
.hfltr_ctrl = 0,
|
||||
.x_color = 0,
|
||||
.line21 = 0,
|
||||
.ln_sel = 21,
|
||||
.htrigger_vtrigger = 0,
|
||||
.tvdetgp_int_start_stop_x = 0x00140001,
|
||||
.tvdetgp_int_start_stop_y = 0x00010001,
|
||||
.gen_ctrl = 0x00FB0000,
|
||||
|
||||
.llen = 864-1,
|
||||
.flens = 625-1,
|
||||
.cc_carr_wss_carr = 0x2F7625ED,
|
||||
.c_phase = 0xDF,
|
||||
.gain_u = 0x111,
|
||||
.gain_v = 0x181,
|
||||
.gain_y = 0x140,
|
||||
.black_level = 0x3e,
|
||||
.blank_level = 0x3e,
|
||||
.m_control = 0<<2 | 1<<1,
|
||||
.bstamp_wss_data = 0x42,
|
||||
.s_carr = 0x2a098acb,
|
||||
.l21__wc_ctl = 0<<13 | 0x16<<8 | 0<<0,
|
||||
.savid__eavid = 0x06A70108,
|
||||
.flen__fal = 23<<16 | 624<<0,
|
||||
.lal__phase_reset = 2<<17 | 310<<0,
|
||||
.hs_int_start_stop_x = 0x00920358,
|
||||
.hs_ext_start_stop_x = 0x000F035F,
|
||||
.vs_int_start_x = 0x1a7<<16,
|
||||
.vs_int_stop_x__vs_int_start_y = 0x000601A7,
|
||||
.vs_int_stop_y__vs_ext_start_x = 0x01AF0036,
|
||||
.vs_ext_stop_x__vs_ext_start_y = 0x27101af,
|
||||
.vs_ext_stop_y = 0x05,
|
||||
.avid_start_stop_x = 0x03530082,
|
||||
.avid_start_stop_y = 0x0270002E,
|
||||
.fid_int_start_x__fid_int_start_y = 0x0005008A,
|
||||
.fid_int_offset_y__fid_ext_start_x = 0x002E0138,
|
||||
.fid_ext_start_y__fid_ext_offset_y = 0x01380005,
|
||||
};
|
||||
|
||||
enum venc_videomode {
|
||||
VENC_MODE_UNKNOWN,
|
||||
VENC_MODE_PAL,
|
||||
|
@ -444,6 +444,14 @@ config DRM_PANEL_TRULY_NT35597_WQXGA
|
||||
Say Y here if you want to enable support for Truly NT35597 WQXGA Dual DSI
|
||||
Video Mode panel
|
||||
|
||||
config DRM_PANEL_VISIONOX_RM69299
|
||||
tristate "Visionox RM69299"
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
help
|
||||
Say Y here if you want to enable support for Visionox
|
||||
RM69299 DSI Video Mode panel.
|
||||
|
||||
config DRM_PANEL_XINPENG_XPP055C272
|
||||
tristate "Xinpeng XPP055C272 panel driver"
|
||||
depends on OF
|
||||
|
@ -47,4 +47,5 @@ obj-$(CONFIG_DRM_PANEL_TPO_TD028TTEC1) += panel-tpo-td028ttec1.o
|
||||
obj-$(CONFIG_DRM_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
|
||||
obj-$(CONFIG_DRM_PANEL_TPO_TPG110) += panel-tpo-tpg110.o
|
||||
obj-$(CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA) += panel-truly-nt35597.o
|
||||
obj-$(CONFIG_DRM_PANEL_VISIONOX_RM69299) += panel-visionox-rm69299.o
|
||||
obj-$(CONFIG_DRM_PANEL_XINPENG_XPP055C272) += panel-xinpeng-xpp055c272.o
|
||||
|
@ -697,15 +697,15 @@ static const struct panel_desc auo_b101uan08_3_desc = {
|
||||
};
|
||||
|
||||
static const struct drm_display_mode boe_tv105wum_nw0_default_mode = {
|
||||
.clock = 159260,
|
||||
.clock = 159916,
|
||||
.hdisplay = 1200,
|
||||
.hsync_start = 1200 + 80,
|
||||
.hsync_end = 1200 + 80 + 24,
|
||||
.htotal = 1200 + 80 + 24 + 60,
|
||||
.vdisplay = 1920,
|
||||
.vsync_start = 1920 + 10,
|
||||
.vsync_end = 1920 + 10 + 2,
|
||||
.vtotal = 1920 + 10 + 2 + 14,
|
||||
.vsync_start = 1920 + 20,
|
||||
.vsync_end = 1920 + 20 + 4,
|
||||
.vtotal = 1920 + 20 + 4 + 10,
|
||||
.vrefresh = 60,
|
||||
.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
|
||||
};
|
||||
|
@ -379,7 +379,7 @@ static int ili9322_init(struct drm_panel *panel, struct ili9322 *ili)
|
||||
"can't set up VCOM amplitude (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (ili->vcom_high != U8_MAX) {
|
||||
ret = regmap_write(ili->regmap, ILI9322_VCOM_HIGH,
|
||||
@ -388,7 +388,7 @@ static int ili9322_init(struct drm_panel *panel, struct ili9322 *ili)
|
||||
dev_err(ili->dev, "can't set up VCOM high (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/* Set up gamma correction */
|
||||
for (i = 0; i < ARRAY_SIZE(ili->gamma); i++) {
|
||||
|
@ -836,7 +836,8 @@ static const struct panel_desc auo_g101evn010 = {
|
||||
.width = 216,
|
||||
.height = 135,
|
||||
},
|
||||
.bus_format = MEDIA_BUS_FMT_RGB666_1X18,
|
||||
.bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG,
|
||||
.connector_type = DRM_MODE_CONNECTOR_LVDS,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode auo_g104sn02_mode = {
|
||||
@ -862,6 +863,31 @@ static const struct panel_desc auo_g104sn02 = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct drm_display_mode auo_g121ean01_mode = {
|
||||
.clock = 66700,
|
||||
.hdisplay = 1280,
|
||||
.hsync_start = 1280 + 58,
|
||||
.hsync_end = 1280 + 58 + 8,
|
||||
.htotal = 1280 + 58 + 8 + 70,
|
||||
.vdisplay = 800,
|
||||
.vsync_start = 800 + 6,
|
||||
.vsync_end = 800 + 6 + 4,
|
||||
.vtotal = 800 + 6 + 4 + 10,
|
||||
.vrefresh = 60,
|
||||
};
|
||||
|
||||
static const struct panel_desc auo_g121ean01 = {
|
||||
.modes = &auo_g121ean01_mode,
|
||||
.num_modes = 1,
|
||||
.bpc = 8,
|
||||
.size = {
|
||||
.width = 261,
|
||||
.height = 163,
|
||||
},
|
||||
.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
|
||||
.connector_type = DRM_MODE_CONNECTOR_LVDS,
|
||||
};
|
||||
|
||||
static const struct display_timing auo_g133han01_timings = {
|
||||
.pixelclock = { 134000000, 141200000, 149000000 },
|
||||
.hactive = { 1920, 1920, 1920 },
|
||||
@ -892,6 +918,31 @@ static const struct panel_desc auo_g133han01 = {
|
||||
.connector_type = DRM_MODE_CONNECTOR_LVDS,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode auo_g156xtn01_mode = {
|
||||
.clock = 76000,
|
||||
.hdisplay = 1366,
|
||||
.hsync_start = 1366 + 33,
|
||||
.hsync_end = 1366 + 33 + 67,
|
||||
.htotal = 1560,
|
||||
.vdisplay = 768,
|
||||
.vsync_start = 768 + 4,
|
||||
.vsync_end = 768 + 4 + 4,
|
||||
.vtotal = 806,
|
||||
.vrefresh = 60,
|
||||
};
|
||||
|
||||
static const struct panel_desc auo_g156xtn01 = {
|
||||
.modes = &auo_g156xtn01_mode,
|
||||
.num_modes = 1,
|
||||
.bpc = 8,
|
||||
.size = {
|
||||
.width = 344,
|
||||
.height = 194,
|
||||
},
|
||||
.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
|
||||
.connector_type = DRM_MODE_CONNECTOR_LVDS,
|
||||
};
|
||||
|
||||
static const struct display_timing auo_g185han01_timings = {
|
||||
.pixelclock = { 120000000, 144000000, 175000000 },
|
||||
.hactive = { 1920, 1920, 1920 },
|
||||
@ -922,6 +973,36 @@ static const struct panel_desc auo_g185han01 = {
|
||||
.connector_type = DRM_MODE_CONNECTOR_LVDS,
|
||||
};
|
||||
|
||||
static const struct display_timing auo_g190ean01_timings = {
|
||||
.pixelclock = { 90000000, 108000000, 135000000 },
|
||||
.hactive = { 1280, 1280, 1280 },
|
||||
.hfront_porch = { 126, 184, 1266 },
|
||||
.hback_porch = { 84, 122, 844 },
|
||||
.hsync_len = { 70, 102, 704 },
|
||||
.vactive = { 1024, 1024, 1024 },
|
||||
.vfront_porch = { 4, 26, 76 },
|
||||
.vback_porch = { 2, 8, 25 },
|
||||
.vsync_len = { 2, 8, 25 },
|
||||
};
|
||||
|
||||
static const struct panel_desc auo_g190ean01 = {
|
||||
.timings = &auo_g190ean01_timings,
|
||||
.num_timings = 1,
|
||||
.bpc = 8,
|
||||
.size = {
|
||||
.width = 376,
|
||||
.height = 301,
|
||||
},
|
||||
.delay = {
|
||||
.prepare = 50,
|
||||
.enable = 200,
|
||||
.disable = 110,
|
||||
.unprepare = 1000,
|
||||
},
|
||||
.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
|
||||
.connector_type = DRM_MODE_CONNECTOR_LVDS,
|
||||
};
|
||||
|
||||
static const struct display_timing auo_p320hvn03_timings = {
|
||||
.pixelclock = { 106000000, 148500000, 164000000 },
|
||||
.hactive = { 1920, 1920, 1920 },
|
||||
@ -1092,6 +1173,36 @@ static const struct panel_desc boe_nv101wxmn51 = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct drm_display_mode boe_nv133fhm_n61_modes = {
|
||||
.clock = 147840,
|
||||
.hdisplay = 1920,
|
||||
.hsync_start = 1920 + 48,
|
||||
.hsync_end = 1920 + 48 + 32,
|
||||
.htotal = 1920 + 48 + 32 + 200,
|
||||
.vdisplay = 1080,
|
||||
.vsync_start = 1080 + 3,
|
||||
.vsync_end = 1080 + 3 + 6,
|
||||
.vtotal = 1080 + 3 + 6 + 31,
|
||||
.vrefresh = 60,
|
||||
};
|
||||
|
||||
static const struct panel_desc boe_nv133fhm_n61 = {
|
||||
.modes = &boe_nv133fhm_n61_modes,
|
||||
.num_modes = 1,
|
||||
.bpc = 8,
|
||||
.size = {
|
||||
.width = 300,
|
||||
.height = 187,
|
||||
},
|
||||
.delay = {
|
||||
.hpd_absent_delay = 200,
|
||||
.unprepare = 500,
|
||||
},
|
||||
.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
|
||||
.bus_flags = DRM_BUS_FLAG_DATA_MSB_TO_LSB,
|
||||
.connector_type = DRM_MODE_CONNECTOR_eDP,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode boe_nv140fhmn49_modes[] = {
|
||||
{
|
||||
.clock = 148500,
|
||||
@ -1980,6 +2091,37 @@ static const struct panel_desc innolux_zj070na_01p = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct drm_display_mode ivo_m133nwf4_r0_mode = {
|
||||
.clock = 138778,
|
||||
.hdisplay = 1920,
|
||||
.hsync_start = 1920 + 24,
|
||||
.hsync_end = 1920 + 24 + 48,
|
||||
.htotal = 1920 + 24 + 48 + 88,
|
||||
.vdisplay = 1080,
|
||||
.vsync_start = 1080 + 3,
|
||||
.vsync_end = 1080 + 3 + 12,
|
||||
.vtotal = 1080 + 3 + 12 + 17,
|
||||
.vrefresh = 60,
|
||||
.flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC,
|
||||
};
|
||||
|
||||
static const struct panel_desc ivo_m133nwf4_r0 = {
|
||||
.modes = &ivo_m133nwf4_r0_mode,
|
||||
.num_modes = 1,
|
||||
.bpc = 8,
|
||||
.size = {
|
||||
.width = 294,
|
||||
.height = 165,
|
||||
},
|
||||
.delay = {
|
||||
.hpd_absent_delay = 200,
|
||||
.unprepare = 500,
|
||||
},
|
||||
.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
|
||||
.bus_flags = DRM_BUS_FLAG_DATA_MSB_TO_LSB,
|
||||
.connector_type = DRM_MODE_CONNECTOR_eDP,
|
||||
};
|
||||
|
||||
static const struct display_timing koe_tx14d24vm1bpa_timing = {
|
||||
.pixelclock = { 5580000, 5850000, 6200000 },
|
||||
.hactive = { 320, 320, 320 },
|
||||
@ -2168,6 +2310,7 @@ static const struct panel_desc lg_lp120up1 = {
|
||||
.width = 267,
|
||||
.height = 183,
|
||||
},
|
||||
.connector_type = DRM_MODE_CONNECTOR_eDP,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode lg_lp129qe_mode = {
|
||||
@ -3480,12 +3623,21 @@ static const struct of_device_id platform_of_match[] = {
|
||||
}, {
|
||||
.compatible = "auo,g104sn02",
|
||||
.data = &auo_g104sn02,
|
||||
}, {
|
||||
.compatible = "auo,g121ean01",
|
||||
.data = &auo_g121ean01,
|
||||
}, {
|
||||
.compatible = "auo,g133han01",
|
||||
.data = &auo_g133han01,
|
||||
}, {
|
||||
.compatible = "auo,g156xtn01",
|
||||
.data = &auo_g156xtn01,
|
||||
}, {
|
||||
.compatible = "auo,g185han01",
|
||||
.data = &auo_g185han01,
|
||||
}, {
|
||||
.compatible = "auo,g190ean01",
|
||||
.data = &auo_g190ean01,
|
||||
}, {
|
||||
.compatible = "auo,p320hvn03",
|
||||
.data = &auo_p320hvn03,
|
||||
@ -3504,6 +3656,9 @@ static const struct of_device_id platform_of_match[] = {
|
||||
}, {
|
||||
.compatible = "boe,nv101wxmn51",
|
||||
.data = &boe_nv101wxmn51,
|
||||
}, {
|
||||
.compatible = "boe,nv133fhm-n61",
|
||||
.data = &boe_nv133fhm_n61,
|
||||
}, {
|
||||
.compatible = "boe,nv140fhmn49",
|
||||
.data = &boe_nv140fhmn49,
|
||||
@ -3612,6 +3767,9 @@ static const struct of_device_id platform_of_match[] = {
|
||||
}, {
|
||||
.compatible = "innolux,zj070na-01p",
|
||||
.data = &innolux_zj070na_01p,
|
||||
}, {
|
||||
.compatible = "ivo,m133nwf4-r0",
|
||||
.data = &ivo_m133nwf4_r0,
|
||||
}, {
|
||||
.compatible = "koe,tx14d24vm1bpa",
|
||||
.data = &koe_tx14d24vm1bpa,
|
||||
|
@ -490,9 +490,7 @@ static int truly_nt35597_panel_add(struct truly_nt35597 *ctx)
|
||||
{
|
||||
struct device *dev = ctx->dev;
|
||||
int ret, i;
|
||||
const struct nt35597_config *config;
|
||||
|
||||
config = ctx->config;
|
||||
for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++)
|
||||
ctx->supplies[i].supply = regulator_names[i];
|
||||
|
||||
|
302
drivers/gpu/drm/panel/panel-visionox-rm69299.c
Normal file
302
drivers/gpu/drm/panel/panel-visionox-rm69299.c
Normal file
@ -0,0 +1,302 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/gpio/consumer.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_print.h>
|
||||
|
||||
struct visionox_rm69299 {
|
||||
struct drm_panel panel;
|
||||
struct regulator_bulk_data supplies[2];
|
||||
struct gpio_desc *reset_gpio;
|
||||
struct mipi_dsi_device *dsi;
|
||||
bool prepared;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
static inline struct visionox_rm69299 *panel_to_ctx(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct visionox_rm69299, panel);
|
||||
}
|
||||
|
||||
static int visionox_rm69299_power_on(struct visionox_rm69299 *ctx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Reset sequence of visionox panel requires the panel to be
|
||||
* out of reset for 10ms, followed by being held in reset
|
||||
* for 10ms and then out again
|
||||
*/
|
||||
gpiod_set_value(ctx->reset_gpio, 1);
|
||||
usleep_range(10000, 20000);
|
||||
gpiod_set_value(ctx->reset_gpio, 0);
|
||||
usleep_range(10000, 20000);
|
||||
gpiod_set_value(ctx->reset_gpio, 1);
|
||||
usleep_range(10000, 20000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int visionox_rm69299_power_off(struct visionox_rm69299 *ctx)
|
||||
{
|
||||
gpiod_set_value(ctx->reset_gpio, 0);
|
||||
|
||||
return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
|
||||
}
|
||||
|
||||
static int visionox_rm69299_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct visionox_rm69299 *ctx = panel_to_ctx(panel);
|
||||
int ret;
|
||||
|
||||
ctx->dsi->mode_flags = 0;
|
||||
|
||||
ret = mipi_dsi_dcs_write(ctx->dsi, MIPI_DCS_SET_DISPLAY_OFF, NULL, 0);
|
||||
if (ret < 0)
|
||||
DRM_DEV_ERROR(ctx->panel.dev,
|
||||
"set_display_off cmd failed ret = %d\n", ret);
|
||||
|
||||
/* 120ms delay required here as per DCS spec */
|
||||
msleep(120);
|
||||
|
||||
ret = mipi_dsi_dcs_write(ctx->dsi, MIPI_DCS_ENTER_SLEEP_MODE, NULL, 0);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(ctx->panel.dev,
|
||||
"enter_sleep cmd failed ret = %d\n", ret);
|
||||
}
|
||||
|
||||
ret = visionox_rm69299_power_off(ctx);
|
||||
|
||||
ctx->prepared = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int visionox_rm69299_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct visionox_rm69299 *ctx = panel_to_ctx(panel);
|
||||
int ret;
|
||||
|
||||
if (ctx->prepared)
|
||||
return 0;
|
||||
|
||||
ret = visionox_rm69299_power_on(ctx);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ctx->dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = mipi_dsi_dcs_write_buffer(ctx->dsi, (u8[]) { 0xfe, 0x00 }, 2);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(ctx->panel.dev,
|
||||
"cmd set tx 0 failed, ret = %d\n", ret);
|
||||
goto power_off;
|
||||
}
|
||||
|
||||
ret = mipi_dsi_dcs_write_buffer(ctx->dsi, (u8[]) { 0xc2, 0x08 }, 2);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(ctx->panel.dev,
|
||||
"cmd set tx 1 failed, ret = %d\n", ret);
|
||||
goto power_off;
|
||||
}
|
||||
|
||||
ret = mipi_dsi_dcs_write_buffer(ctx->dsi, (u8[]) { 0x35, 0x00 }, 2);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(ctx->panel.dev,
|
||||
"cmd set tx 2 failed, ret = %d\n", ret);
|
||||
goto power_off;
|
||||
}
|
||||
|
||||
ret = mipi_dsi_dcs_write_buffer(ctx->dsi, (u8[]) { 0x51, 0xff }, 2);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(ctx->panel.dev,
|
||||
"cmd set tx 3 failed, ret = %d\n", ret);
|
||||
goto power_off;
|
||||
}
|
||||
|
||||
ret = mipi_dsi_dcs_write(ctx->dsi, MIPI_DCS_EXIT_SLEEP_MODE, NULL, 0);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(ctx->panel.dev,
|
||||
"exit_sleep_mode cmd failed ret = %d\n", ret);
|
||||
goto power_off;
|
||||
}
|
||||
|
||||
/* Per DSI spec wait 120ms after sending exit sleep DCS command */
|
||||
msleep(120);
|
||||
|
||||
ret = mipi_dsi_dcs_write(ctx->dsi, MIPI_DCS_SET_DISPLAY_ON, NULL, 0);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(ctx->panel.dev,
|
||||
"set_display_on cmd failed ret = %d\n", ret);
|
||||
goto power_off;
|
||||
}
|
||||
|
||||
/* Per DSI spec wait 120ms after sending set_display_on DCS command */
|
||||
msleep(120);
|
||||
|
||||
ctx->prepared = true;
|
||||
|
||||
return 0;
|
||||
|
||||
power_off:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct drm_display_mode visionox_rm69299_1080x2248_60hz = {
|
||||
.name = "1080x2248",
|
||||
.clock = 158695,
|
||||
.hdisplay = 1080,
|
||||
.hsync_start = 1080 + 26,
|
||||
.hsync_end = 1080 + 26 + 2,
|
||||
.htotal = 1080 + 26 + 2 + 36,
|
||||
.vdisplay = 2248,
|
||||
.vsync_start = 2248 + 56,
|
||||
.vsync_end = 2248 + 56 + 4,
|
||||
.vtotal = 2248 + 56 + 4 + 4,
|
||||
.vrefresh = 60,
|
||||
.flags = 0,
|
||||
};
|
||||
|
||||
static int visionox_rm69299_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct visionox_rm69299 *ctx = panel_to_ctx(panel);
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mode = drm_mode_create(connector->dev);
|
||||
if (!mode) {
|
||||
DRM_DEV_ERROR(ctx->panel.dev,
|
||||
"failed to create a new display mode\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
connector->display_info.width_mm = 74;
|
||||
connector->display_info.height_mm = 131;
|
||||
drm_mode_copy(mode, &visionox_rm69299_1080x2248_60hz);
|
||||
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
||||
drm_mode_probed_add(connector, mode);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs visionox_rm69299_drm_funcs = {
|
||||
.unprepare = visionox_rm69299_unprepare,
|
||||
.prepare = visionox_rm69299_prepare,
|
||||
.get_modes = visionox_rm69299_get_modes,
|
||||
};
|
||||
|
||||
static int visionox_rm69299_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
struct visionox_rm69299 *ctx;
|
||||
int ret;
|
||||
|
||||
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
mipi_dsi_set_drvdata(dsi, ctx);
|
||||
|
||||
ctx->panel.dev = dev;
|
||||
ctx->dsi = dsi;
|
||||
|
||||
ctx->supplies[0].supply = "vdda";
|
||||
ctx->supplies[1].supply = "vdd3p3";
|
||||
|
||||
ret = devm_regulator_bulk_get(ctx->panel.dev, ARRAY_SIZE(ctx->supplies),
|
||||
ctx->supplies);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ctx->reset_gpio = devm_gpiod_get(ctx->panel.dev,
|
||||
"reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(ctx->reset_gpio)) {
|
||||
DRM_DEV_ERROR(dev, "cannot get reset gpio %ld\n",
|
||||
PTR_ERR(ctx->reset_gpio));
|
||||
return PTR_ERR(ctx->reset_gpio);
|
||||
}
|
||||
|
||||
drm_panel_init(&ctx->panel, dev, &visionox_rm69299_drm_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
ctx->panel.dev = dev;
|
||||
ctx->panel.funcs = &visionox_rm69299_drm_funcs;
|
||||
drm_panel_add(&ctx->panel);
|
||||
|
||||
dsi->lanes = 4;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM |
|
||||
MIPI_DSI_CLOCK_NON_CONTINUOUS;
|
||||
ret = mipi_dsi_attach(dsi);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(dev, "dsi attach failed ret = %d\n", ret);
|
||||
goto err_dsi_attach;
|
||||
}
|
||||
|
||||
ret = regulator_set_load(ctx->supplies[0].consumer, 32000);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dev,
|
||||
"regulator set load failed for vdda supply ret = %d\n",
|
||||
ret);
|
||||
goto err_set_load;
|
||||
}
|
||||
|
||||
ret = regulator_set_load(ctx->supplies[1].consumer, 13200);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dev,
|
||||
"regulator set load failed for vdd3p3 supply ret = %d\n",
|
||||
ret);
|
||||
goto err_set_load;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_set_load:
|
||||
mipi_dsi_detach(dsi);
|
||||
err_dsi_attach:
|
||||
drm_panel_remove(&ctx->panel);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int visionox_rm69299_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct visionox_rm69299 *ctx = mipi_dsi_get_drvdata(dsi);
|
||||
|
||||
mipi_dsi_detach(ctx->dsi);
|
||||
mipi_dsi_device_unregister(ctx->dsi);
|
||||
|
||||
drm_panel_remove(&ctx->panel);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id visionox_rm69299_of_match[] = {
|
||||
{ .compatible = "visionox,rm69299-1080p-display", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, visionox_rm69299_of_match);
|
||||
|
||||
static struct mipi_dsi_driver visionox_rm69299_driver = {
|
||||
.driver = {
|
||||
.name = "panel-visionox-rm69299",
|
||||
.of_match_table = visionox_rm69299_of_match,
|
||||
},
|
||||
.probe = visionox_rm69299_probe,
|
||||
.remove = visionox_rm69299_remove,
|
||||
};
|
||||
module_mipi_dsi_driver(visionox_rm69299_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Visionox RM69299 DSI Panel Driver");
|
@ -3,7 +3,6 @@ pl111_drm-y += pl111_display.o \
|
||||
pl111_versatile.o \
|
||||
pl111_drv.o
|
||||
|
||||
pl111_drm-$(CONFIG_ARCH_VEXPRESS) += pl111_vexpress.o
|
||||
pl111_drm-$(CONFIG_ARCH_NOMADIK) += pl111_nomadik.o
|
||||
pl111_drm-$(CONFIG_DEBUG_FS) += pl111_debugfs.o
|
||||
|
||||
|
@ -444,6 +444,7 @@ static const struct amba_id pl111_id_table[] = {
|
||||
},
|
||||
{0, 0},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(amba, pl111_id_table);
|
||||
|
||||
static struct amba_driver pl111_amba_driver __maybe_unused = {
|
||||
.drv = {
|
||||
|
@ -8,9 +8,9 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/vexpress.h>
|
||||
|
||||
#include "pl111_versatile.h"
|
||||
#include "pl111_vexpress.h"
|
||||
#include "pl111_drm.h"
|
||||
|
||||
static struct regmap *versatile_syscon_map;
|
||||
@ -361,13 +361,110 @@ static const struct pl111_variant_data pl111_vexpress = {
|
||||
.broken_clockdivider = true,
|
||||
};
|
||||
|
||||
#define VEXPRESS_FPGAMUX_MOTHERBOARD 0x00
|
||||
#define VEXPRESS_FPGAMUX_DAUGHTERBOARD_1 0x01
|
||||
#define VEXPRESS_FPGAMUX_DAUGHTERBOARD_2 0x02
|
||||
|
||||
static int pl111_vexpress_clcd_init(struct device *dev, struct device_node *np,
|
||||
struct pl111_drm_dev_private *priv)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
struct device_node *root;
|
||||
struct device_node *child;
|
||||
struct device_node *ct_clcd = NULL;
|
||||
struct regmap *map;
|
||||
bool has_coretile_clcd = false;
|
||||
bool has_coretile_hdlcd = false;
|
||||
bool mux_motherboard = true;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_VEXPRESS_CONFIG))
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* Check if we have a CLCD or HDLCD on the core tile by checking if a
|
||||
* CLCD or HDLCD is available in the root of the device tree.
|
||||
*/
|
||||
root = of_find_node_by_path("/");
|
||||
if (!root)
|
||||
return -EINVAL;
|
||||
|
||||
for_each_available_child_of_node(root, child) {
|
||||
if (of_device_is_compatible(child, "arm,pl111")) {
|
||||
has_coretile_clcd = true;
|
||||
ct_clcd = child;
|
||||
break;
|
||||
}
|
||||
if (of_device_is_compatible(child, "arm,hdlcd")) {
|
||||
has_coretile_hdlcd = true;
|
||||
of_node_put(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
of_node_put(root);
|
||||
|
||||
/*
|
||||
* If there is a coretile HDLCD and it has a driver,
|
||||
* do not mux the CLCD on the motherboard to the DVI.
|
||||
*/
|
||||
if (has_coretile_hdlcd && IS_ENABLED(CONFIG_DRM_HDLCD))
|
||||
mux_motherboard = false;
|
||||
|
||||
/*
|
||||
* On the Vexpress CA9 we let the CLCD on the coretile
|
||||
* take precedence, so also in this case do not mux the
|
||||
* motherboard to the DVI.
|
||||
*/
|
||||
if (has_coretile_clcd)
|
||||
mux_motherboard = false;
|
||||
|
||||
if (mux_motherboard) {
|
||||
dev_info(dev, "DVI muxed to motherboard CLCD\n");
|
||||
val = VEXPRESS_FPGAMUX_MOTHERBOARD;
|
||||
} else if (ct_clcd == dev->of_node) {
|
||||
dev_info(dev,
|
||||
"DVI muxed to daughterboard 1 (core tile) CLCD\n");
|
||||
val = VEXPRESS_FPGAMUX_DAUGHTERBOARD_1;
|
||||
} else {
|
||||
dev_info(dev, "core tile graphics present\n");
|
||||
dev_info(dev, "this device will be deactivated\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Call into deep Vexpress configuration API */
|
||||
pdev = of_find_device_by_node(np);
|
||||
if (!pdev) {
|
||||
dev_err(dev, "can't find the sysreg device, deferring\n");
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
map = devm_regmap_init_vexpress_config(&pdev->dev);
|
||||
if (IS_ERR(map)) {
|
||||
platform_device_put(pdev);
|
||||
return PTR_ERR(map);
|
||||
}
|
||||
|
||||
ret = regmap_write(map, 0, val);
|
||||
platform_device_put(pdev);
|
||||
if (ret) {
|
||||
dev_err(dev, "error setting DVI muxmode\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
priv->variant = &pl111_vexpress;
|
||||
dev_info(dev, "initializing Versatile Express PL111\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv)
|
||||
{
|
||||
const struct of_device_id *clcd_id;
|
||||
enum versatile_clcd versatile_clcd_type;
|
||||
struct device_node *np;
|
||||
struct regmap *map;
|
||||
int ret;
|
||||
|
||||
np = of_find_matching_node_and_match(NULL, versatile_clcd_of_match,
|
||||
&clcd_id);
|
||||
@ -378,6 +475,15 @@ int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv)
|
||||
|
||||
versatile_clcd_type = (enum versatile_clcd)clcd_id->data;
|
||||
|
||||
/* Versatile Express special handling */
|
||||
if (versatile_clcd_type == VEXPRESS_CLCD_V2M) {
|
||||
int ret = pl111_vexpress_clcd_init(dev, np, priv);
|
||||
of_node_put(np);
|
||||
if (ret)
|
||||
dev_err(dev, "Versatile Express init failed - %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* On the Integrator, check if we should use the IM-PD1 instead,
|
||||
* if we find it, it will take precedence. This is on the Integrator/AP
|
||||
@ -390,37 +496,8 @@ int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv)
|
||||
versatile_clcd_type = (enum versatile_clcd)clcd_id->data;
|
||||
}
|
||||
|
||||
/* Versatile Express special handling */
|
||||
if (versatile_clcd_type == VEXPRESS_CLCD_V2M) {
|
||||
struct platform_device *pdev;
|
||||
|
||||
/* Registers a driver for the muxfpga */
|
||||
ret = vexpress_muxfpga_init();
|
||||
if (ret) {
|
||||
dev_err(dev, "unable to initialize muxfpga driver\n");
|
||||
of_node_put(np);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Call into deep Vexpress configuration API */
|
||||
pdev = of_find_device_by_node(np);
|
||||
if (!pdev) {
|
||||
dev_err(dev, "can't find the sysreg device, deferring\n");
|
||||
of_node_put(np);
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
map = dev_get_drvdata(&pdev->dev);
|
||||
if (!map) {
|
||||
dev_err(dev, "sysreg has not yet probed\n");
|
||||
platform_device_put(pdev);
|
||||
of_node_put(np);
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
} else {
|
||||
map = syscon_node_to_regmap(np);
|
||||
}
|
||||
map = syscon_node_to_regmap(np);
|
||||
of_node_put(np);
|
||||
|
||||
if (IS_ERR(map)) {
|
||||
dev_err(dev, "no Versatile syscon regmap\n");
|
||||
return PTR_ERR(map);
|
||||
@ -466,13 +543,6 @@ int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv)
|
||||
priv->variant_display_disable = pl111_realview_clcd_disable;
|
||||
dev_info(dev, "set up callbacks for RealView PL111\n");
|
||||
break;
|
||||
case VEXPRESS_CLCD_V2M:
|
||||
priv->variant = &pl111_vexpress;
|
||||
dev_info(dev, "initializing Versatile Express PL111\n");
|
||||
ret = pl111_vexpress_clcd_init(dev, priv, map);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
dev_info(dev, "unknown Versatile system controller\n");
|
||||
break;
|
||||
|
@ -1,138 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Versatile Express PL111 handling
|
||||
* Copyright (C) 2018 Linus Walleij
|
||||
*
|
||||
* This module binds to the "arm,vexpress-muxfpga" device on the
|
||||
* Versatile Express configuration bus and sets up which CLCD instance
|
||||
* gets muxed out on the DVI bridge.
|
||||
*/
|
||||
#include <linux/device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/vexpress.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include "pl111_drm.h"
|
||||
#include "pl111_vexpress.h"
|
||||
|
||||
#define VEXPRESS_FPGAMUX_MOTHERBOARD 0x00
|
||||
#define VEXPRESS_FPGAMUX_DAUGHTERBOARD_1 0x01
|
||||
#define VEXPRESS_FPGAMUX_DAUGHTERBOARD_2 0x02
|
||||
|
||||
int pl111_vexpress_clcd_init(struct device *dev,
|
||||
struct pl111_drm_dev_private *priv,
|
||||
struct regmap *map)
|
||||
{
|
||||
struct device_node *root;
|
||||
struct device_node *child;
|
||||
struct device_node *ct_clcd = NULL;
|
||||
bool has_coretile_clcd = false;
|
||||
bool has_coretile_hdlcd = false;
|
||||
bool mux_motherboard = true;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Check if we have a CLCD or HDLCD on the core tile by checking if a
|
||||
* CLCD or HDLCD is available in the root of the device tree.
|
||||
*/
|
||||
root = of_find_node_by_path("/");
|
||||
if (!root)
|
||||
return -EINVAL;
|
||||
|
||||
for_each_available_child_of_node(root, child) {
|
||||
if (of_device_is_compatible(child, "arm,pl111")) {
|
||||
has_coretile_clcd = true;
|
||||
ct_clcd = child;
|
||||
break;
|
||||
}
|
||||
if (of_device_is_compatible(child, "arm,hdlcd")) {
|
||||
has_coretile_hdlcd = true;
|
||||
of_node_put(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
of_node_put(root);
|
||||
|
||||
/*
|
||||
* If there is a coretile HDLCD and it has a driver,
|
||||
* do not mux the CLCD on the motherboard to the DVI.
|
||||
*/
|
||||
if (has_coretile_hdlcd && IS_ENABLED(CONFIG_DRM_HDLCD))
|
||||
mux_motherboard = false;
|
||||
|
||||
/*
|
||||
* On the Vexpress CA9 we let the CLCD on the coretile
|
||||
* take precedence, so also in this case do not mux the
|
||||
* motherboard to the DVI.
|
||||
*/
|
||||
if (has_coretile_clcd)
|
||||
mux_motherboard = false;
|
||||
|
||||
if (mux_motherboard) {
|
||||
dev_info(dev, "DVI muxed to motherboard CLCD\n");
|
||||
val = VEXPRESS_FPGAMUX_MOTHERBOARD;
|
||||
} else if (ct_clcd == dev->of_node) {
|
||||
dev_info(dev,
|
||||
"DVI muxed to daughterboard 1 (core tile) CLCD\n");
|
||||
val = VEXPRESS_FPGAMUX_DAUGHTERBOARD_1;
|
||||
} else {
|
||||
dev_info(dev, "core tile graphics present\n");
|
||||
dev_info(dev, "this device will be deactivated\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = regmap_write(map, 0, val);
|
||||
if (ret) {
|
||||
dev_err(dev, "error setting DVI muxmode\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This sets up the regmap pointer that will then be retrieved by
|
||||
* the detection code in pl111_versatile.c and passed in to the
|
||||
* pl111_vexpress_clcd_init() function above.
|
||||
*/
|
||||
static int vexpress_muxfpga_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct regmap *map;
|
||||
|
||||
map = devm_regmap_init_vexpress_config(&pdev->dev);
|
||||
if (IS_ERR(map))
|
||||
return PTR_ERR(map);
|
||||
dev_set_drvdata(dev, map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id vexpress_muxfpga_match[] = {
|
||||
{ .compatible = "arm,vexpress-muxfpga", },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver vexpress_muxfpga_driver = {
|
||||
.driver = {
|
||||
.name = "vexpress-muxfpga",
|
||||
.of_match_table = of_match_ptr(vexpress_muxfpga_match),
|
||||
},
|
||||
.probe = vexpress_muxfpga_probe,
|
||||
};
|
||||
|
||||
int vexpress_muxfpga_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = platform_driver_register(&vexpress_muxfpga_driver);
|
||||
/* -EBUSY just means this driver is already registered */
|
||||
if (ret == -EBUSY)
|
||||
ret = 0;
|
||||
return ret;
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
struct device;
|
||||
struct pl111_drm_dev_private;
|
||||
struct regmap;
|
||||
|
||||
#ifdef CONFIG_ARCH_VEXPRESS
|
||||
|
||||
int pl111_vexpress_clcd_init(struct device *dev,
|
||||
struct pl111_drm_dev_private *priv,
|
||||
struct regmap *map);
|
||||
|
||||
int vexpress_muxfpga_init(void);
|
||||
|
||||
#else
|
||||
|
||||
static inline int pl111_vexpress_clcd_init(struct device *dev,
|
||||
struct pl111_drm_dev_private *priv,
|
||||
struct regmap *map)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int vexpress_muxfpga_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
@ -39,7 +39,7 @@ static int
|
||||
qxl_debugfs_irq_received(struct seq_file *m, void *data)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct qxl_device *qdev = node->minor->dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(node->minor->dev);
|
||||
|
||||
seq_printf(m, "%d\n", atomic_read(&qdev->irq_received));
|
||||
seq_printf(m, "%d\n", atomic_read(&qdev->irq_received_display));
|
||||
@ -53,7 +53,7 @@ static int
|
||||
qxl_debugfs_buffers_info(struct seq_file *m, void *data)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct qxl_device *qdev = node->minor->dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(node->minor->dev);
|
||||
struct qxl_bo *bo;
|
||||
|
||||
list_for_each_entry(bo, &qdev->gem.objects, list) {
|
||||
@ -83,8 +83,7 @@ void
|
||||
qxl_debugfs_init(struct drm_minor *minor)
|
||||
{
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
struct qxl_device *dev =
|
||||
(struct qxl_device *) minor->dev->dev_private;
|
||||
struct qxl_device *dev = to_qxl(minor->dev);
|
||||
|
||||
drm_debugfs_create_files(qxl_debugfs_list, QXL_DEBUGFS_ENTRIES,
|
||||
minor->debugfs_root, minor);
|
||||
|
@ -221,7 +221,7 @@ static int qxl_add_mode(struct drm_connector *connector,
|
||||
bool preferred)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct qxl_device *qdev = dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(dev);
|
||||
struct drm_display_mode *mode = NULL;
|
||||
int rc;
|
||||
|
||||
@ -242,7 +242,7 @@ static int qxl_add_mode(struct drm_connector *connector,
|
||||
static int qxl_add_monitors_config_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct qxl_device *qdev = dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(dev);
|
||||
struct qxl_output *output = drm_connector_to_qxl_output(connector);
|
||||
int h = output->index;
|
||||
struct qxl_head *head;
|
||||
@ -310,7 +310,7 @@ static void qxl_crtc_update_monitors_config(struct drm_crtc *crtc,
|
||||
const char *reason)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct qxl_device *qdev = dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(dev);
|
||||
struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
|
||||
struct qxl_head head;
|
||||
int oldcount, i = qcrtc->index;
|
||||
@ -400,7 +400,7 @@ static int qxl_framebuffer_surface_dirty(struct drm_framebuffer *fb,
|
||||
unsigned int num_clips)
|
||||
{
|
||||
/* TODO: vmwgfx where this was cribbed from had locking. Why? */
|
||||
struct qxl_device *qdev = fb->dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(fb->dev);
|
||||
struct drm_clip_rect norect;
|
||||
struct qxl_bo *qobj;
|
||||
bool is_primary;
|
||||
@ -462,7 +462,7 @@ static const struct drm_crtc_helper_funcs qxl_crtc_helper_funcs = {
|
||||
static int qxl_primary_atomic_check(struct drm_plane *plane,
|
||||
struct drm_plane_state *state)
|
||||
{
|
||||
struct qxl_device *qdev = plane->dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(plane->dev);
|
||||
struct qxl_bo *bo;
|
||||
|
||||
if (!state->crtc || !state->fb)
|
||||
@ -476,7 +476,7 @@ static int qxl_primary_atomic_check(struct drm_plane *plane,
|
||||
static int qxl_primary_apply_cursor(struct drm_plane *plane)
|
||||
{
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct qxl_device *qdev = dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(dev);
|
||||
struct drm_framebuffer *fb = plane->state->fb;
|
||||
struct qxl_crtc *qcrtc = to_qxl_crtc(plane->state->crtc);
|
||||
struct qxl_cursor_cmd *cmd;
|
||||
@ -523,7 +523,7 @@ out_free_release:
|
||||
static void qxl_primary_atomic_update(struct drm_plane *plane,
|
||||
struct drm_plane_state *old_state)
|
||||
{
|
||||
struct qxl_device *qdev = plane->dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(plane->dev);
|
||||
struct qxl_bo *bo = gem_to_qxl_bo(plane->state->fb->obj[0]);
|
||||
struct qxl_bo *primary;
|
||||
struct drm_clip_rect norect = {
|
||||
@ -554,7 +554,7 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
|
||||
static void qxl_primary_atomic_disable(struct drm_plane *plane,
|
||||
struct drm_plane_state *old_state)
|
||||
{
|
||||
struct qxl_device *qdev = plane->dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(plane->dev);
|
||||
|
||||
if (old_state->fb) {
|
||||
struct qxl_bo *bo = gem_to_qxl_bo(old_state->fb->obj[0]);
|
||||
@ -570,7 +570,7 @@ static void qxl_cursor_atomic_update(struct drm_plane *plane,
|
||||
struct drm_plane_state *old_state)
|
||||
{
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct qxl_device *qdev = dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(dev);
|
||||
struct drm_framebuffer *fb = plane->state->fb;
|
||||
struct qxl_crtc *qcrtc = to_qxl_crtc(plane->state->crtc);
|
||||
struct qxl_release *release;
|
||||
@ -679,7 +679,7 @@ out_free_release:
|
||||
static void qxl_cursor_atomic_disable(struct drm_plane *plane,
|
||||
struct drm_plane_state *old_state)
|
||||
{
|
||||
struct qxl_device *qdev = plane->dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(plane->dev);
|
||||
struct qxl_release *release;
|
||||
struct qxl_cursor_cmd *cmd;
|
||||
int ret;
|
||||
@ -762,7 +762,7 @@ static void qxl_calc_dumb_shadow(struct qxl_device *qdev,
|
||||
static int qxl_plane_prepare_fb(struct drm_plane *plane,
|
||||
struct drm_plane_state *new_state)
|
||||
{
|
||||
struct qxl_device *qdev = plane->dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(plane->dev);
|
||||
struct drm_gem_object *obj;
|
||||
struct qxl_bo *user_bo;
|
||||
struct qxl_surface surf;
|
||||
@ -923,7 +923,7 @@ static int qdev_crtc_init(struct drm_device *dev, int crtc_id)
|
||||
{
|
||||
struct qxl_crtc *qxl_crtc;
|
||||
struct drm_plane *primary, *cursor;
|
||||
struct qxl_device *qdev = dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(dev);
|
||||
int r;
|
||||
|
||||
qxl_crtc = kzalloc(sizeof(struct qxl_crtc), GFP_KERNEL);
|
||||
@ -965,7 +965,7 @@ free_mem:
|
||||
static int qxl_conn_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct qxl_device *qdev = dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(dev);
|
||||
struct qxl_output *output = drm_connector_to_qxl_output(connector);
|
||||
unsigned int pwidth = 1024;
|
||||
unsigned int pheight = 768;
|
||||
@ -991,7 +991,7 @@ static enum drm_mode_status qxl_conn_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct drm_device *ddev = connector->dev;
|
||||
struct qxl_device *qdev = ddev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(ddev);
|
||||
|
||||
if (qxl_check_mode(qdev, mode->hdisplay, mode->vdisplay) != 0)
|
||||
return MODE_BAD;
|
||||
@ -1021,7 +1021,7 @@ static enum drm_connector_status qxl_conn_detect(
|
||||
struct qxl_output *output =
|
||||
drm_connector_to_qxl_output(connector);
|
||||
struct drm_device *ddev = connector->dev;
|
||||
struct qxl_device *qdev = ddev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(ddev);
|
||||
bool connected = false;
|
||||
|
||||
/* The first monitor is always connected */
|
||||
@ -1071,7 +1071,7 @@ static int qxl_mode_create_hotplug_mode_update_property(struct qxl_device *qdev)
|
||||
|
||||
static int qdev_output_init(struct drm_device *dev, int num_output)
|
||||
{
|
||||
struct qxl_device *qdev = dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(dev);
|
||||
struct qxl_output *qxl_output;
|
||||
struct drm_connector *connector;
|
||||
struct drm_encoder *encoder;
|
||||
|
@ -81,13 +81,16 @@ qxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
return -EINVAL; /* TODO: ENODEV ? */
|
||||
}
|
||||
|
||||
qdev = kzalloc(sizeof(struct qxl_device), GFP_KERNEL);
|
||||
if (!qdev)
|
||||
qdev = devm_drm_dev_alloc(&pdev->dev, &qxl_driver,
|
||||
struct qxl_device, ddev);
|
||||
if (IS_ERR(qdev)) {
|
||||
pr_err("Unable to init drm dev");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = pci_enable_device(pdev);
|
||||
if (ret)
|
||||
goto free_dev;
|
||||
return ret;
|
||||
|
||||
ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, "qxl");
|
||||
if (ret)
|
||||
@ -101,7 +104,7 @@ qxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
}
|
||||
}
|
||||
|
||||
ret = qxl_device_init(qdev, &qxl_driver, pdev);
|
||||
ret = qxl_device_init(qdev, pdev);
|
||||
if (ret)
|
||||
goto put_vga;
|
||||
|
||||
@ -128,14 +131,13 @@ put_vga:
|
||||
vga_put(pdev, VGA_RSRC_LEGACY_IO);
|
||||
disable_pci:
|
||||
pci_disable_device(pdev);
|
||||
free_dev:
|
||||
kfree(qdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void qxl_drm_release(struct drm_device *dev)
|
||||
{
|
||||
struct qxl_device *qdev = dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(dev);
|
||||
|
||||
/*
|
||||
* TODO: qxl_device_fini() call should be in qxl_pci_remove(),
|
||||
@ -155,7 +157,6 @@ qxl_pci_remove(struct pci_dev *pdev)
|
||||
drm_atomic_helper_shutdown(dev);
|
||||
if (is_vga(pdev))
|
||||
vga_put(pdev, VGA_RSRC_LEGACY_IO);
|
||||
drm_dev_put(dev);
|
||||
}
|
||||
|
||||
DEFINE_DRM_GEM_FOPS(qxl_fops);
|
||||
@ -163,7 +164,7 @@ DEFINE_DRM_GEM_FOPS(qxl_fops);
|
||||
static int qxl_drm_freeze(struct drm_device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = dev->pdev;
|
||||
struct qxl_device *qdev = dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(dev);
|
||||
int ret;
|
||||
|
||||
ret = drm_mode_config_helper_suspend(dev);
|
||||
@ -185,7 +186,7 @@ static int qxl_drm_freeze(struct drm_device *dev)
|
||||
|
||||
static int qxl_drm_resume(struct drm_device *dev, bool thaw)
|
||||
{
|
||||
struct qxl_device *qdev = dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(dev);
|
||||
|
||||
qdev->ram_header->int_mask = QXL_INTERRUPT_MASK;
|
||||
if (!thaw) {
|
||||
@ -244,7 +245,7 @@ static int qxl_pm_restore(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct drm_device *drm_dev = pci_get_drvdata(pdev);
|
||||
struct qxl_device *qdev = drm_dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(drm_dev);
|
||||
|
||||
qxl_io_reset(qdev);
|
||||
return qxl_drm_resume(drm_dev, false);
|
||||
|
@ -192,8 +192,6 @@ struct qxl_debugfs {
|
||||
|
||||
int qxl_debugfs_fence_init(struct qxl_device *rdev);
|
||||
|
||||
struct qxl_device;
|
||||
|
||||
struct qxl_device {
|
||||
struct drm_device ddev;
|
||||
|
||||
@ -273,11 +271,12 @@ struct qxl_device {
|
||||
int monitors_config_height;
|
||||
};
|
||||
|
||||
#define to_qxl(dev) container_of(dev, struct qxl_device, ddev)
|
||||
|
||||
extern const struct drm_ioctl_desc qxl_ioctls[];
|
||||
extern int qxl_max_ioctl;
|
||||
|
||||
int qxl_device_init(struct qxl_device *qdev, struct drm_driver *drv,
|
||||
struct pci_dev *pdev);
|
||||
int qxl_device_init(struct qxl_device *qdev, struct pci_dev *pdev);
|
||||
void qxl_device_fini(struct qxl_device *qdev);
|
||||
|
||||
int qxl_modeset_init(struct qxl_device *qdev);
|
||||
|
@ -32,7 +32,7 @@ int qxl_mode_dumb_create(struct drm_file *file_priv,
|
||||
struct drm_device *dev,
|
||||
struct drm_mode_create_dumb *args)
|
||||
{
|
||||
struct qxl_device *qdev = dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(dev);
|
||||
struct qxl_bo *qobj;
|
||||
uint32_t handle;
|
||||
int r;
|
||||
|
@ -34,7 +34,7 @@ void qxl_gem_object_free(struct drm_gem_object *gobj)
|
||||
struct qxl_device *qdev;
|
||||
struct ttm_buffer_object *tbo;
|
||||
|
||||
qdev = (struct qxl_device *)gobj->dev->dev_private;
|
||||
qdev = to_qxl(gobj->dev);
|
||||
|
||||
qxl_surface_evict(qdev, qobj, false);
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
static int qxl_alloc_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct qxl_device *qdev = dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(dev);
|
||||
struct drm_qxl_alloc *qxl_alloc = data;
|
||||
int ret;
|
||||
struct qxl_bo *qobj;
|
||||
@ -64,7 +64,7 @@ static int qxl_alloc_ioctl(struct drm_device *dev, void *data,
|
||||
static int qxl_map_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct qxl_device *qdev = dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(dev);
|
||||
struct drm_qxl_map *qxl_map = data;
|
||||
|
||||
return qxl_mode_dumb_mmap(file_priv, &qdev->ddev, qxl_map->handle,
|
||||
@ -279,7 +279,7 @@ out_free_reloc:
|
||||
static int qxl_execbuffer_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct qxl_device *qdev = dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(dev);
|
||||
struct drm_qxl_execbuffer *execbuffer = data;
|
||||
struct drm_qxl_command user_cmd;
|
||||
int cmd_num;
|
||||
@ -304,7 +304,7 @@ static int qxl_execbuffer_ioctl(struct drm_device *dev, void *data,
|
||||
static int qxl_update_area_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file)
|
||||
{
|
||||
struct qxl_device *qdev = dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(dev);
|
||||
struct drm_qxl_update_area *update_area = data;
|
||||
struct qxl_rect area = {.left = update_area->left,
|
||||
.top = update_area->top,
|
||||
@ -354,7 +354,7 @@ out:
|
||||
static int qxl_getparam_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct qxl_device *qdev = dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(dev);
|
||||
struct drm_qxl_getparam *param = data;
|
||||
|
||||
switch (param->param) {
|
||||
@ -373,7 +373,7 @@ static int qxl_getparam_ioctl(struct drm_device *dev, void *data,
|
||||
static int qxl_clientcap_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct qxl_device *qdev = dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(dev);
|
||||
struct drm_qxl_clientcap *param = data;
|
||||
int byte, idx;
|
||||
|
||||
@ -394,7 +394,7 @@ static int qxl_clientcap_ioctl(struct drm_device *dev, void *data,
|
||||
static int qxl_alloc_surf_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file)
|
||||
{
|
||||
struct qxl_device *qdev = dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(dev);
|
||||
struct drm_qxl_alloc_surf *param = data;
|
||||
struct qxl_bo *qobj;
|
||||
int handle;
|
||||
|
@ -32,7 +32,7 @@
|
||||
irqreturn_t qxl_irq_handler(int irq, void *arg)
|
||||
{
|
||||
struct drm_device *dev = (struct drm_device *) arg;
|
||||
struct qxl_device *qdev = (struct qxl_device *)dev->dev_private;
|
||||
struct qxl_device *qdev = to_qxl(dev);
|
||||
uint32_t pending;
|
||||
|
||||
pending = xchg(&qdev->ram_header->int_pending, 0);
|
||||
|
@ -108,21 +108,12 @@ static void qxl_gc_work(struct work_struct *work)
|
||||
}
|
||||
|
||||
int qxl_device_init(struct qxl_device *qdev,
|
||||
struct drm_driver *drv,
|
||||
struct pci_dev *pdev)
|
||||
{
|
||||
int r, sb;
|
||||
|
||||
r = drm_dev_init(&qdev->ddev, drv, &pdev->dev);
|
||||
if (r) {
|
||||
pr_err("Unable to init drm dev");
|
||||
goto error;
|
||||
}
|
||||
|
||||
qdev->ddev.pdev = pdev;
|
||||
pci_set_drvdata(pdev, &qdev->ddev);
|
||||
qdev->ddev.dev_private = qdev;
|
||||
drmm_add_final_kfree(&qdev->ddev, qdev);
|
||||
|
||||
mutex_init(&qdev->gem.mutex);
|
||||
mutex_init(&qdev->update_area_mutex);
|
||||
@ -138,8 +129,7 @@ int qxl_device_init(struct qxl_device *qdev,
|
||||
qdev->vram_mapping = io_mapping_create_wc(qdev->vram_base, pci_resource_len(pdev, 0));
|
||||
if (!qdev->vram_mapping) {
|
||||
pr_err("Unable to create vram_mapping");
|
||||
r = -ENOMEM;
|
||||
goto error;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (pci_resource_len(pdev, 4) > 0) {
|
||||
@ -293,7 +283,6 @@ surface_mapping_free:
|
||||
io_mapping_free(qdev->surface_mapping);
|
||||
vram_mapping_free:
|
||||
io_mapping_free(qdev->vram_mapping);
|
||||
error:
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ static void qxl_ttm_bo_destroy(struct ttm_buffer_object *tbo)
|
||||
struct qxl_device *qdev;
|
||||
|
||||
bo = to_qxl_bo(tbo);
|
||||
qdev = (struct qxl_device *)bo->tbo.base.dev->dev_private;
|
||||
qdev = to_qxl(bo->tbo.base.dev);
|
||||
|
||||
qxl_surface_evict(qdev, bo, false);
|
||||
WARN_ON_ONCE(bo->map_count > 0);
|
||||
|
@ -243,7 +243,7 @@ static int qxl_release_validate_bo(struct qxl_bo *bo)
|
||||
return ret;
|
||||
|
||||
/* allocate a surface for reserved + validated buffers */
|
||||
ret = qxl_bo_check_id(bo->tbo.base.dev->dev_private, bo);
|
||||
ret = qxl_bo_check_id(to_qxl(bo->tbo.base.dev), bo);
|
||||
if (ret)
|
||||
return ret;
|
||||
return 0;
|
||||
|
@ -243,7 +243,7 @@ static void qxl_bo_move_notify(struct ttm_buffer_object *bo,
|
||||
if (!qxl_ttm_bo_is_qxl_bo(bo))
|
||||
return;
|
||||
qbo = to_qxl_bo(bo);
|
||||
qdev = qbo->tbo.base.dev->dev_private;
|
||||
qdev = to_qxl(qbo->tbo.base.dev);
|
||||
|
||||
if (bo->mem.mem_type == TTM_PL_PRIV && qbo->surface_id)
|
||||
qxl_surface_evict(qdev, qbo, new_mem ? true : false);
|
||||
|
@ -1106,7 +1106,7 @@ static const struct component_ops cdn_dp_component_ops = {
|
||||
.unbind = cdn_dp_unbind,
|
||||
};
|
||||
|
||||
int cdn_dp_suspend(struct device *dev)
|
||||
static int cdn_dp_suspend(struct device *dev)
|
||||
{
|
||||
struct cdn_dp_device *dp = dev_get_drvdata(dev);
|
||||
int ret = 0;
|
||||
@ -1120,7 +1120,7 @@ int cdn_dp_suspend(struct device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cdn_dp_resume(struct device *dev)
|
||||
static int cdn_dp_resume(struct device *dev)
|
||||
{
|
||||
struct cdn_dp_device *dp = dev_get_drvdata(dev);
|
||||
|
||||
|
@ -601,7 +601,7 @@ static int cdn_dp_get_msa_misc(struct video_info *video,
|
||||
case YCBCR_4_2_0:
|
||||
val[0] = 5;
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
switch (video->color_depth) {
|
||||
case 6:
|
||||
@ -619,7 +619,7 @@ static int cdn_dp_get_msa_misc(struct video_info *video,
|
||||
case 16:
|
||||
val[1] = 4;
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
msa_misc = 2 * val[0] + 32 * val[1] +
|
||||
((video->color_fmt == Y_ONLY) ? (1 << 14) : 0);
|
||||
@ -700,7 +700,7 @@ int cdn_dp_config_video(struct cdn_dp_device *dp)
|
||||
case 16:
|
||||
val = BCS_16;
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
val += video->color_fmt << 8;
|
||||
ret = cdn_dp_reg_write(dp, DP_FRAMER_PXL_REPR, val);
|
||||
|
@ -42,8 +42,6 @@
|
||||
|
||||
#define MAX_IRQ 4
|
||||
|
||||
#define MAX_ENDPOINTS 2
|
||||
|
||||
#define HWVER_10200 0x010200
|
||||
#define HWVER_10300 0x010300
|
||||
#define HWVER_20101 0x020101
|
||||
@ -1201,36 +1199,20 @@ int ltdc_load(struct drm_device *ddev)
|
||||
struct ltdc_device *ldev = ddev->dev_private;
|
||||
struct device *dev = ddev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct drm_bridge *bridge[MAX_ENDPOINTS] = {NULL};
|
||||
struct drm_panel *panel[MAX_ENDPOINTS] = {NULL};
|
||||
struct drm_bridge *bridge;
|
||||
struct drm_panel *panel;
|
||||
struct drm_crtc *crtc;
|
||||
struct reset_control *rstc;
|
||||
struct resource *res;
|
||||
int irq, ret, i, endpoint_not_ready = -ENODEV;
|
||||
int irq, i, nb_endpoints;
|
||||
int ret = -ENODEV;
|
||||
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
|
||||
/* Get endpoints if any */
|
||||
for (i = 0; i < MAX_ENDPOINTS; i++) {
|
||||
ret = drm_of_find_panel_or_bridge(np, 0, i, &panel[i],
|
||||
&bridge[i]);
|
||||
|
||||
/*
|
||||
* If at least one endpoint is -EPROBE_DEFER, defer probing,
|
||||
* else if at least one endpoint is ready, continue probing.
|
||||
*/
|
||||
if (ret == -EPROBE_DEFER)
|
||||
return ret;
|
||||
else if (!ret)
|
||||
endpoint_not_ready = 0;
|
||||
}
|
||||
|
||||
if (endpoint_not_ready)
|
||||
return endpoint_not_ready;
|
||||
|
||||
rstc = devm_reset_control_get_exclusive(dev, NULL);
|
||||
|
||||
mutex_init(&ldev->err_lock);
|
||||
/* Get number of endpoints */
|
||||
nb_endpoints = of_graph_get_endpoint_count(np);
|
||||
if (!nb_endpoints)
|
||||
return -ENODEV;
|
||||
|
||||
ldev->pixel_clk = devm_clk_get(dev, "lcd");
|
||||
if (IS_ERR(ldev->pixel_clk)) {
|
||||
@ -1244,6 +1226,43 @@ int ltdc_load(struct drm_device *ddev)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Get endpoints if any */
|
||||
for (i = 0; i < nb_endpoints; i++) {
|
||||
ret = drm_of_find_panel_or_bridge(np, 0, i, &panel, &bridge);
|
||||
|
||||
/*
|
||||
* If at least one endpoint is -ENODEV, continue probing,
|
||||
* else if at least one endpoint returned an error
|
||||
* (ie -EPROBE_DEFER) then stop probing.
|
||||
*/
|
||||
if (ret == -ENODEV)
|
||||
continue;
|
||||
else if (ret)
|
||||
goto err;
|
||||
|
||||
if (panel) {
|
||||
bridge = drm_panel_bridge_add_typed(panel,
|
||||
DRM_MODE_CONNECTOR_DPI);
|
||||
if (IS_ERR(bridge)) {
|
||||
DRM_ERROR("panel-bridge endpoint %d\n", i);
|
||||
ret = PTR_ERR(bridge);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (bridge) {
|
||||
ret = ltdc_encoder_init(ddev, bridge);
|
||||
if (ret) {
|
||||
DRM_ERROR("init encoder endpoint %d\n", i);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rstc = devm_reset_control_get_exclusive(dev, NULL);
|
||||
|
||||
mutex_init(&ldev->err_lock);
|
||||
|
||||
if (!IS_ERR(rstc)) {
|
||||
reset_control_assert(rstc);
|
||||
usleep_range(10, 20);
|
||||
@ -1285,27 +1304,7 @@ int ltdc_load(struct drm_device *ddev)
|
||||
DRM_ERROR("Failed to register LTDC interrupt\n");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add endpoints panels or bridges if any */
|
||||
for (i = 0; i < MAX_ENDPOINTS; i++) {
|
||||
if (panel[i]) {
|
||||
bridge[i] = drm_panel_bridge_add_typed(panel[i],
|
||||
DRM_MODE_CONNECTOR_DPI);
|
||||
if (IS_ERR(bridge[i])) {
|
||||
DRM_ERROR("panel-bridge endpoint %d\n", i);
|
||||
ret = PTR_ERR(bridge[i]);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (bridge[i]) {
|
||||
ret = ltdc_encoder_init(ddev, bridge[i]);
|
||||
if (ret) {
|
||||
DRM_ERROR("init encoder endpoint %d\n", i);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
crtc = devm_kzalloc(dev, sizeof(*crtc), GFP_KERNEL);
|
||||
@ -1340,8 +1339,8 @@ int ltdc_load(struct drm_device *ddev)
|
||||
|
||||
return 0;
|
||||
err:
|
||||
for (i = 0; i < MAX_ENDPOINTS; i++)
|
||||
drm_panel_bridge_remove(bridge[i]);
|
||||
for (i = 0; i < nb_endpoints; i++)
|
||||
drm_of_panel_bridge_remove(ddev->dev->of_node, 0, i);
|
||||
|
||||
clk_disable_unprepare(ldev->pixel_clk);
|
||||
|
||||
@ -1350,11 +1349,14 @@ err:
|
||||
|
||||
void ltdc_unload(struct drm_device *ddev)
|
||||
{
|
||||
int i;
|
||||
struct device *dev = ddev->dev;
|
||||
int nb_endpoints, i;
|
||||
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
|
||||
for (i = 0; i < MAX_ENDPOINTS; i++)
|
||||
nb_endpoints = of_graph_get_endpoint_count(dev->of_node);
|
||||
|
||||
for (i = 0; i < nb_endpoints; i++)
|
||||
drm_of_panel_bridge_remove(ddev->dev->of_node, 0, i);
|
||||
|
||||
pm_runtime_disable(ddev->dev);
|
||||
|
@ -24,7 +24,7 @@
|
||||
static void tidss_crtc_finish_page_flip(struct tidss_crtc *tcrtc)
|
||||
{
|
||||
struct drm_device *ddev = tcrtc->crtc.dev;
|
||||
struct tidss_device *tidss = ddev->dev_private;
|
||||
struct tidss_device *tidss = to_tidss(ddev);
|
||||
struct drm_pending_vblank_event *event;
|
||||
unsigned long flags;
|
||||
bool busy;
|
||||
@ -88,7 +88,7 @@ static int tidss_crtc_atomic_check(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *state)
|
||||
{
|
||||
struct drm_device *ddev = crtc->dev;
|
||||
struct tidss_device *tidss = ddev->dev_private;
|
||||
struct tidss_device *tidss = to_tidss(ddev);
|
||||
struct dispc_device *dispc = tidss->dispc;
|
||||
struct tidss_crtc *tcrtc = to_tidss_crtc(crtc);
|
||||
u32 hw_videoport = tcrtc->hw_videoport;
|
||||
@ -165,7 +165,7 @@ static void tidss_crtc_atomic_flush(struct drm_crtc *crtc,
|
||||
{
|
||||
struct tidss_crtc *tcrtc = to_tidss_crtc(crtc);
|
||||
struct drm_device *ddev = crtc->dev;
|
||||
struct tidss_device *tidss = ddev->dev_private;
|
||||
struct tidss_device *tidss = to_tidss(ddev);
|
||||
unsigned long flags;
|
||||
|
||||
dev_dbg(ddev->dev,
|
||||
@ -216,7 +216,7 @@ static void tidss_crtc_atomic_enable(struct drm_crtc *crtc,
|
||||
{
|
||||
struct tidss_crtc *tcrtc = to_tidss_crtc(crtc);
|
||||
struct drm_device *ddev = crtc->dev;
|
||||
struct tidss_device *tidss = ddev->dev_private;
|
||||
struct tidss_device *tidss = to_tidss(ddev);
|
||||
const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
|
||||
unsigned long flags;
|
||||
int r;
|
||||
@ -259,7 +259,7 @@ static void tidss_crtc_atomic_disable(struct drm_crtc *crtc,
|
||||
{
|
||||
struct tidss_crtc *tcrtc = to_tidss_crtc(crtc);
|
||||
struct drm_device *ddev = crtc->dev;
|
||||
struct tidss_device *tidss = ddev->dev_private;
|
||||
struct tidss_device *tidss = to_tidss(ddev);
|
||||
unsigned long flags;
|
||||
|
||||
dev_dbg(ddev->dev, "%s, event %p\n", __func__, crtc->state->event);
|
||||
@ -295,7 +295,7 @@ enum drm_mode_status tidss_crtc_mode_valid(struct drm_crtc *crtc,
|
||||
{
|
||||
struct tidss_crtc *tcrtc = to_tidss_crtc(crtc);
|
||||
struct drm_device *ddev = crtc->dev;
|
||||
struct tidss_device *tidss = ddev->dev_private;
|
||||
struct tidss_device *tidss = to_tidss(ddev);
|
||||
|
||||
return dispc_vp_mode_valid(tidss->dispc, tcrtc->hw_videoport, mode);
|
||||
}
|
||||
@ -314,7 +314,7 @@ static const struct drm_crtc_helper_funcs tidss_crtc_helper_funcs = {
|
||||
static int tidss_crtc_enable_vblank(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *ddev = crtc->dev;
|
||||
struct tidss_device *tidss = ddev->dev_private;
|
||||
struct tidss_device *tidss = to_tidss(ddev);
|
||||
|
||||
dev_dbg(ddev->dev, "%s\n", __func__);
|
||||
|
||||
@ -328,7 +328,7 @@ static int tidss_crtc_enable_vblank(struct drm_crtc *crtc)
|
||||
static void tidss_crtc_disable_vblank(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *ddev = crtc->dev;
|
||||
struct tidss_device *tidss = ddev->dev_private;
|
||||
struct tidss_device *tidss = to_tidss(ddev);
|
||||
|
||||
dev_dbg(ddev->dev, "%s\n", __func__);
|
||||
|
||||
|
@ -181,10 +181,6 @@ const struct dispc_features dispc_am65x_feats = {
|
||||
.vid_name = { "vid", "vidl1" },
|
||||
.vid_lite = { false, true, },
|
||||
.vid_order = { 1, 0 },
|
||||
|
||||
.errata = {
|
||||
.i2000 = true,
|
||||
},
|
||||
};
|
||||
|
||||
static const u16 tidss_j721e_common_regs[DISPC_COMMON_REG_TABLE_LEN] = {
|
||||
@ -2674,12 +2670,9 @@ int dispc_init(struct tidss_device *tidss)
|
||||
return -ENOMEM;
|
||||
|
||||
num_fourccs = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(dispc_color_formats); ++i) {
|
||||
if (feat->errata.i2000 &&
|
||||
dispc_fourcc_is_yuv(dispc_color_formats[i].fourcc))
|
||||
continue;
|
||||
for (i = 0; i < ARRAY_SIZE(dispc_color_formats); ++i)
|
||||
dispc->fourccs[num_fourccs++] = dispc_color_formats[i].fourcc;
|
||||
}
|
||||
|
||||
dispc->num_fourccs = num_fourccs;
|
||||
dispc->tidss = tidss;
|
||||
dispc->dev = dev;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user