mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
drm-misc-next for $kernel-version:
UAPI Changes: Cross-subsystem Changes: - A few fixes for usb/typec Core Changes: - ci: Updates to the defconfig, igt version, etc. - writeback: Move the atomic_check helper from the encoder to connector Driver Changes: - rockchip: Add support for rk3588 - xe: Update the TODO list - panel: - nv3052c: Register documentation, init sequence improvements and support for the Fascontek FS035VG158 - st7701: Add support for the Anbernic RG-ARC - new driver: Synaptics R63353 panel controller, Ilitek ILI9805 panel controller - new panel: AUO G156HAN04.0 -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQRcEzekXsqa64kGDp7j7w1vZxhRxQUCZXrMAwAKCRDj7w1vZxhR xa+2AP9ZyK/PP5/a1y1PKUQ9IYPjRW0QEda2I7w1XK6hglSWDgD9Hu9Q8YPUtlTT PT0qZ++tdxnCiGgj+yK3Yc1qPcb6+Qw= =o4Gu -----END PGP SIGNATURE----- Merge tag 'drm-misc-next-2023-12-14' of git://anongit.freedesktop.org/drm/drm-misc into drm-next drm-misc-next for $kernel-version: UAPI Changes: Cross-subsystem Changes: - A few fixes for usb/typec Core Changes: - ci: Updates to the defconfig, igt version, etc. - writeback: Move the atomic_check helper from the encoder to connector Driver Changes: - rockchip: Add support for rk3588 - xe: Update the TODO list - panel: - nv3052c: Register documentation, init sequence improvements and support for the Fascontek FS035VG158 - st7701: Add support for the Anbernic RG-ARC - new driver: Synaptics R63353 panel controller, Ilitek ILI9805 panel controller - new panel: AUO G156HAN04.0 Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maxime Ripard <mripard@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/aqpn5miejmkks7pbcfex7b6u63uwsruywxsnr3x5ljs45qatin@nbkkej2elk46
This commit is contained in:
commit
48b272853e
@ -0,0 +1,56 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/fascontek,fs035vg158.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Fascontek FS035VG158 3.5" (640x480 pixels) 24-bit IPS LCD panel
|
||||
|
||||
maintainers:
|
||||
- John Watts <contact@jookia.org>
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fascontek,fs035vg158
|
||||
|
||||
spi-3wire: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- port
|
||||
- power-supply
|
||||
- reset-gpios
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
panel@0 {
|
||||
compatible = "fascontek,fs035vg158";
|
||||
reg = <0>;
|
||||
|
||||
spi-3wire;
|
||||
spi-max-frequency = <3125000>;
|
||||
|
||||
reset-gpios = <&gpe 2 GPIO_ACTIVE_LOW>;
|
||||
|
||||
backlight = <&backlight>;
|
||||
power-supply = <&vcc>;
|
||||
|
||||
port {
|
||||
panel_input: endpoint {
|
||||
remote-endpoint = <&panel_output>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -0,0 +1,62 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/ilitek,ili9805.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Ilitek ILI9805 based MIPI-DSI panels
|
||||
|
||||
maintainers:
|
||||
- Michael Trimarchi <michael@amarulasolutions.com>
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- giantplus,gpm1790a0
|
||||
- tianma,tm041xdhg01
|
||||
- const: ilitek,ili9805
|
||||
|
||||
avdd-supply: true
|
||||
dvdd-supply: true
|
||||
reg: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- avdd-supply
|
||||
- dvdd-supply
|
||||
- reg
|
||||
- reset-gpios
|
||||
- port
|
||||
- backlight
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
dsi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
panel@0 {
|
||||
compatible = "giantplus,gpm1790a0", "ilitek,ili9805";
|
||||
reg = <0>;
|
||||
avdd-supply = <&avdd_display>;
|
||||
dvdd-supply = <&dvdd_display>;
|
||||
reset-gpios = <&r_pio 0 5 GPIO_ACTIVE_LOW>; /* PL05 */
|
||||
backlight = <&backlight>;
|
||||
|
||||
port {
|
||||
panel_in: endpoint {
|
||||
remote-endpoint = <&mipi_dsi_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -18,16 +18,12 @@ properties:
|
||||
compatible:
|
||||
const: leadtek,ltk035c5444t
|
||||
|
||||
backlight: true
|
||||
port: true
|
||||
power-supply: true
|
||||
reg: true
|
||||
reset-gpios: true
|
||||
|
||||
spi-3wire: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- port
|
||||
- power-supply
|
||||
- reset-gpios
|
||||
|
||||
|
@ -33,6 +33,8 @@ properties:
|
||||
|
||||
# AU Optronics Corporation 13.3" FHD (1920x1080) TFT LCD panel
|
||||
- auo,g133han01
|
||||
# AU Optronics Corporation 15.6" FHD (1920x1080) TFT LCD panel
|
||||
- auo,g156han04
|
||||
# AU Optronics Corporation 18.5" FHD (1920x1080) TFT LCD panel
|
||||
- auo,g185han01
|
||||
# AU Optronics Corporation 19.0" (1280x1024) TFT LCD panel
|
||||
|
@ -27,6 +27,7 @@ properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- anbernic,rg-arc-panel
|
||||
- densitron,dmt028vghmcmi-1a
|
||||
- elida,kd50t048a
|
||||
- techstar,ts8550b
|
||||
|
@ -8,8 +8,8 @@ title: Rockchip SoC display controller (VOP2)
|
||||
|
||||
description:
|
||||
VOP2 (Video Output Processor v2) is the display controller for the Rockchip
|
||||
series of SoCs which transfers the image data from a video memory
|
||||
buffer to an external LCD interface.
|
||||
series of SoCs which transfers the image data from a video memory buffer to
|
||||
an external LCD interface.
|
||||
|
||||
maintainers:
|
||||
- Sandy Huang <hjc@rock-chips.com>
|
||||
@ -20,6 +20,7 @@ properties:
|
||||
enum:
|
||||
- rockchip,rk3566-vop
|
||||
- rockchip,rk3568-vop
|
||||
- rockchip,rk3588-vop
|
||||
|
||||
reg:
|
||||
items:
|
||||
@ -27,8 +28,8 @@ properties:
|
||||
Must contain one entry corresponding to the base address and length
|
||||
of the register space.
|
||||
- description:
|
||||
Can optionally contain a second entry corresponding to
|
||||
the CRTC gamma LUT address.
|
||||
Can optionally contain a second entry corresponding to the CRTC gamma
|
||||
LUT address.
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
@ -41,45 +42,63 @@ properties:
|
||||
The VOP interrupt is shared by several interrupt sources, such as
|
||||
frame start (VSYNC), line flag and other status interrupts.
|
||||
|
||||
# See compatible-specific constraints below.
|
||||
clocks:
|
||||
minItems: 5
|
||||
items:
|
||||
- description: Clock for ddr buffer transfer.
|
||||
- description: Clock for the ahb bus to R/W the phy regs.
|
||||
- description: Clock for ddr buffer transfer via axi.
|
||||
- description: Clock for the ahb bus to R/W the regs.
|
||||
- description: Pixel clock for video port 0.
|
||||
- description: Pixel clock for video port 1.
|
||||
- description: Pixel clock for video port 2.
|
||||
- description: Pixel clock for video port 3.
|
||||
- description: Peripheral(vop grf/dsi) clock.
|
||||
|
||||
clock-names:
|
||||
minItems: 5
|
||||
items:
|
||||
- const: aclk
|
||||
- const: hclk
|
||||
- const: dclk_vp0
|
||||
- const: dclk_vp1
|
||||
- const: dclk_vp2
|
||||
- const: dclk_vp3
|
||||
- const: pclk_vop
|
||||
|
||||
rockchip,grf:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
Phandle to GRF regs used for misc control
|
||||
Phandle to GRF regs used for control the polarity of dclk/hsync/vsync of DPI,
|
||||
also used for query vop memory bisr enable status, etc.
|
||||
|
||||
rockchip,vo1-grf:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
Phandle to VO GRF regs used for control the polarity of dclk/hsync/vsync of hdmi
|
||||
on rk3588.
|
||||
|
||||
rockchip,vop-grf:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
Phandle to VOP GRF regs used for control data path between vopr and hdmi/edp.
|
||||
|
||||
rockchip,pmu:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
Phandle to PMU GRF used for query vop memory bisr status on rk3588.
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
patternProperties:
|
||||
"^port@[0-3]$":
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
Output endpoint of VP0
|
||||
description: Output endpoint of VP0/1/2/3.
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
Output endpoint of VP1
|
||||
required:
|
||||
- port@0
|
||||
|
||||
port@2:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
Output endpoint of VP2
|
||||
unevaluatedProperties: false
|
||||
|
||||
iommus:
|
||||
maxItems: 1
|
||||
@ -96,6 +115,49 @@ required:
|
||||
- clock-names
|
||||
- ports
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: rockchip,rk3588-vop
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 7
|
||||
clock-names:
|
||||
minItems: 7
|
||||
|
||||
ports:
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
- port@2
|
||||
- port@3
|
||||
|
||||
required:
|
||||
- rockchip,grf
|
||||
- rockchip,vo1-grf
|
||||
- rockchip,vop-grf
|
||||
- rockchip,pmu
|
||||
|
||||
else:
|
||||
properties:
|
||||
rockchip,vo1-grf: false
|
||||
rockchip,vop-grf: false
|
||||
rockchip,pmu: false
|
||||
|
||||
clocks:
|
||||
maxItems: 5
|
||||
clock-names:
|
||||
maxItems: 5
|
||||
|
||||
ports:
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
- port@2
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
|
@ -474,6 +474,8 @@ patternProperties:
|
||||
description: Fairphone B.V.
|
||||
"^faraday,.*":
|
||||
description: Faraday Technology Corporation
|
||||
"^fascontek,.*":
|
||||
description: Fascontek
|
||||
"^fastrax,.*":
|
||||
description: Fastrax Oy
|
||||
"^fcs,.*":
|
||||
|
@ -69,14 +69,15 @@ the result. They will still be run.
|
||||
|
||||
Each new flake entry must be associated with a link to the email reporting the
|
||||
bug to the author of the affected driver, the board name or Device Tree name of
|
||||
the board, the first kernel version affected, and an approximation of the
|
||||
failure rate.
|
||||
the board, the first kernel version affected, the IGT version used for tests,
|
||||
and an approximation of the failure rate.
|
||||
|
||||
They should be provided under the following format::
|
||||
|
||||
# Bug Report: $LORE_OR_PATCHWORK_URL
|
||||
# Board Name: broken-board.dtb
|
||||
# Version: 6.6-rc1
|
||||
# Linux Version: 6.6-rc1
|
||||
# IGT Version: 1.28-gd2af13d9f
|
||||
# Failure Rate: 100
|
||||
flaky-test
|
||||
|
||||
|
@ -70,35 +70,42 @@ When the time comes for Xe, the protection will be lifted on Xe and kept in i915
|
||||
Xe – Pre-Merge Goals - Work-in-Progress
|
||||
=======================================
|
||||
|
||||
Drm_scheduler
|
||||
-------------
|
||||
Xe primarily uses Firmware based scheduling (GuC FW). However, it will use
|
||||
drm_scheduler as the scheduler ‘frontend’ for userspace submission in order to
|
||||
resolve syncobj and dma-buf implicit sync dependencies. However, drm_scheduler is
|
||||
not yet prepared to handle the 1-to-1 relationship between drm_gpu_scheduler and
|
||||
drm_sched_entity.
|
||||
Display integration with i915
|
||||
-----------------------------
|
||||
In order to share the display code with the i915 driver so that there is maximum
|
||||
reuse, the i915/display/ code is built twice, once for i915.ko and then for
|
||||
xe.ko. Currently, the i915/display code in Xe tree is polluted with many 'ifdefs'
|
||||
depending on the build target. The goal is to refactor both Xe and i915/display
|
||||
code simultaneously in order to get a clean result before they land upstream, so
|
||||
that display can already be part of the initial pull request towards drm-next.
|
||||
|
||||
Deeper changes to drm_scheduler should *not* be required to get Xe accepted, but
|
||||
some consensus needs to be reached between Xe and other community drivers that
|
||||
could also benefit from this work, for coupling FW based/assisted submission such
|
||||
as the ARM’s new Mali GPU driver, and others.
|
||||
However, display code should not gate the acceptance of Xe in upstream. Xe
|
||||
patches will be refactored in a way that display code can be removed, if needed,
|
||||
from the first pull request of Xe towards drm-next. The expectation is that when
|
||||
both drivers are part of the drm-tip, the introduction of cleaner patches will be
|
||||
easier and speed up.
|
||||
|
||||
As a key measurable result, the patch series introducing Xe itself shall not
|
||||
depend on any other patch touching drm_scheduler itself that was not yet merged
|
||||
through drm-misc. This, by itself, already includes the reach of an agreement for
|
||||
uniform 1 to 1 relationship implementation / usage across drivers.
|
||||
Xe – uAPI high level overview
|
||||
=============================
|
||||
|
||||
ASYNC VM_BIND
|
||||
-------------
|
||||
Although having a common DRM level IOCTL for VM_BIND is not a requirement to get
|
||||
Xe merged, it is mandatory to have a consensus with other drivers and Mesa.
|
||||
It needs to be clear how to handle async VM_BIND and interactions with userspace
|
||||
memory fences. Ideally with helper support so people don't get it wrong in all
|
||||
possible ways.
|
||||
...Warning: To be done in follow up patches after/when/where the main consensus in various items are individually reached.
|
||||
|
||||
As a key measurable result, the benefits of ASYNC VM_BIND and a discussion of
|
||||
various flavors, error handling and sample API suggestions are documented in
|
||||
:doc:`The ASYNC VM_BIND document </gpu/drm-vm-bind-async>`.
|
||||
Xe – Pre-Merge Goals - Completed
|
||||
================================
|
||||
|
||||
Drm_exec
|
||||
--------
|
||||
Helper to make dma_resv locking for a big number of buffers is getting removed in
|
||||
the drm_exec series proposed in https://patchwork.freedesktop.org/patch/524376/
|
||||
If that happens, Xe needs to change and incorporate the changes in the driver.
|
||||
The goal is to engage with the Community to understand if the best approach is to
|
||||
move that to the drivers that are using it or if we should keep the helpers in
|
||||
place waiting for Xe to get merged.
|
||||
|
||||
This item ties into the GPUVA, VM_BIND, and even long-running compute support.
|
||||
|
||||
As a key measurable result, we need to have a community consensus documented in
|
||||
this document and the Xe driver prepared for the changes, if necessary.
|
||||
|
||||
Userptr integration and vm_bind
|
||||
-------------------------------
|
||||
@ -132,6 +139,36 @@ the time comes.
|
||||
The DRM GPUVM helpers do not yet include the userptr parts, but discussions
|
||||
about implementing them are ongoing.
|
||||
|
||||
ASYNC VM_BIND
|
||||
-------------
|
||||
Although having a common DRM level IOCTL for VM_BIND is not a requirement to get
|
||||
Xe merged, it is mandatory to have a consensus with other drivers and Mesa.
|
||||
It needs to be clear how to handle async VM_BIND and interactions with userspace
|
||||
memory fences. Ideally with helper support so people don't get it wrong in all
|
||||
possible ways.
|
||||
|
||||
As a key measurable result, the benefits of ASYNC VM_BIND and a discussion of
|
||||
various flavors, error handling and sample API suggestions are documented in
|
||||
:doc:`The ASYNC VM_BIND document </gpu/drm-vm-bind-async>`.
|
||||
|
||||
Drm_scheduler
|
||||
-------------
|
||||
Xe primarily uses Firmware based scheduling (GuC FW). However, it will use
|
||||
drm_scheduler as the scheduler ‘frontend’ for userspace submission in order to
|
||||
resolve syncobj and dma-buf implicit sync dependencies. However, drm_scheduler is
|
||||
not yet prepared to handle the 1-to-1 relationship between drm_gpu_scheduler and
|
||||
drm_sched_entity.
|
||||
|
||||
Deeper changes to drm_scheduler should *not* be required to get Xe accepted, but
|
||||
some consensus needs to be reached between Xe and other community drivers that
|
||||
could also benefit from this work, for coupling FW based/assisted submission such
|
||||
as the ARM’s new Mali GPU driver, and others.
|
||||
|
||||
As a key measurable result, the patch series introducing Xe itself shall not
|
||||
depend on any other patch touching drm_scheduler itself that was not yet merged
|
||||
through drm-misc. This, by itself, already includes the reach of an agreement for
|
||||
uniform 1 to 1 relationship implementation / usage across drivers.
|
||||
|
||||
Long running compute: minimal data structure/scaffolding
|
||||
--------------------------------------------------------
|
||||
The generic scheduler code needs to include the handling of endless compute
|
||||
@ -144,46 +181,6 @@ this minimal drm/scheduler work, if needed, merged to drm-misc in a way that any
|
||||
drm driver, including Xe, could re-use and add their own individual needs on top
|
||||
in a next stage. However, this should not block the initial merge.
|
||||
|
||||
This is a non-blocker item since the driver without the support for the long
|
||||
running compute enabled is not a showstopper.
|
||||
|
||||
Display integration with i915
|
||||
-----------------------------
|
||||
In order to share the display code with the i915 driver so that there is maximum
|
||||
reuse, the i915/display/ code is built twice, once for i915.ko and then for
|
||||
xe.ko. Currently, the i915/display code in Xe tree is polluted with many 'ifdefs'
|
||||
depending on the build target. The goal is to refactor both Xe and i915/display
|
||||
code simultaneously in order to get a clean result before they land upstream, so
|
||||
that display can already be part of the initial pull request towards drm-next.
|
||||
|
||||
However, display code should not gate the acceptance of Xe in upstream. Xe
|
||||
patches will be refactored in a way that display code can be removed, if needed,
|
||||
from the first pull request of Xe towards drm-next. The expectation is that when
|
||||
both drivers are part of the drm-tip, the introduction of cleaner patches will be
|
||||
easier and speed up.
|
||||
|
||||
Drm_exec
|
||||
--------
|
||||
Helper to make dma_resv locking for a big number of buffers is getting removed in
|
||||
the drm_exec series proposed in https://patchwork.freedesktop.org/patch/524376/
|
||||
If that happens, Xe needs to change and incorporate the changes in the driver.
|
||||
The goal is to engage with the Community to understand if the best approach is to
|
||||
move that to the drivers that are using it or if we should keep the helpers in
|
||||
place waiting for Xe to get merged.
|
||||
|
||||
This item ties into the GPUVA, VM_BIND, and even long-running compute support.
|
||||
|
||||
As a key measurable result, we need to have a community consensus documented in
|
||||
this document and the Xe driver prepared for the changes, if necessary.
|
||||
|
||||
Xe – uAPI high level overview
|
||||
=============================
|
||||
|
||||
...Warning: To be done in follow up patches after/when/where the main consensus in various items are individually reached.
|
||||
|
||||
Xe – Pre-Merge Goals - Completed
|
||||
================================
|
||||
|
||||
Dev_coredump
|
||||
------------
|
||||
|
||||
|
13
MAINTAINERS
13
MAINTAINERS
@ -6627,6 +6627,12 @@ T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
F: Documentation/devicetree/bindings/display/ilitek,ili9486.yaml
|
||||
F: drivers/gpu/drm/tiny/ili9486.c
|
||||
|
||||
DRM DRIVER FOR ILITEK ILI9805 PANELS
|
||||
M: Michael Trimarchi <michael@amarulasolutions.com>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/display/panel/ilitek,ili9805.yaml
|
||||
F: drivers/gpu/drm/panel/panel-ilitek-ili9805.c
|
||||
|
||||
DRM DRIVER FOR JADARD JD9365DA-H3 MIPI-DSI LCD PANELS
|
||||
M: Jagan Teki <jagan@edgeble.ai>
|
||||
S: Maintained
|
||||
@ -6855,6 +6861,12 @@ T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
F: Documentation/devicetree/bindings/display/ste,mcde.yaml
|
||||
F: drivers/gpu/drm/mcde/
|
||||
|
||||
DRM DRIVER FOR SYNAPTICS R63353 PANELS
|
||||
M: Michael Trimarchi <michael@amarulasolutions.com>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/display/panel/synaptics,r63353.yaml
|
||||
F: drivers/gpu/drm/panel/panel-synaptics-r63353.c
|
||||
|
||||
DRM DRIVER FOR TI DLPC3433 MIPI DSI TO DMD BRIDGE
|
||||
M: Jagan Teki <jagan@amarulasolutions.com>
|
||||
S: Maintained
|
||||
@ -7139,6 +7151,7 @@ F: include/linux/platform_data/shmob_drm.h
|
||||
DRM DRIVERS FOR ROCKCHIP
|
||||
M: Sandy Huang <hjc@rock-chips.com>
|
||||
M: Heiko Stübner <heiko@sntech.de>
|
||||
M: Andy Yan <andy.yan@rock-chips.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
|
@ -6,7 +6,7 @@
|
||||
*/
|
||||
#include <linux/auxiliary_bus.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/bridge/aux-bridge.h>
|
||||
|
@ -1413,7 +1413,7 @@ static int ti_sn_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
int ret;
|
||||
|
||||
if (!pdata->pwm_enabled) {
|
||||
ret = pm_runtime_resume_and_get(pdata->dev);
|
||||
ret = pm_runtime_resume_and_get(chip->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
@ -1429,7 +1429,7 @@ static int ti_sn_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
SN_GPIO_MUX_MASK << (2 * SN_PWM_GPIO_IDX),
|
||||
SN_GPIO_MUX_SPECIAL << (2 * SN_PWM_GPIO_IDX));
|
||||
if (ret) {
|
||||
dev_err(pdata->dev, "failed to mux in PWM function\n");
|
||||
dev_err(chip->dev, "failed to mux in PWM function\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@ -1505,7 +1505,7 @@ static int ti_sn_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
|
||||
ret = regmap_write(pdata->regmap, SN_PWM_PRE_DIV_REG, pre_div);
|
||||
if (ret) {
|
||||
dev_err(pdata->dev, "failed to update PWM_PRE_DIV\n");
|
||||
dev_err(chip->dev, "failed to update PWM_PRE_DIV\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -1517,7 +1517,7 @@ static int ti_sn_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
FIELD_PREP(SN_PWM_INV_MASK, state->polarity == PWM_POLARITY_INVERSED);
|
||||
ret = regmap_write(pdata->regmap, SN_PWM_EN_INV_REG, pwm_en_inv);
|
||||
if (ret) {
|
||||
dev_err(pdata->dev, "failed to update PWM_EN/PWM_INV\n");
|
||||
dev_err(chip->dev, "failed to update PWM_EN/PWM_INV\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -1525,7 +1525,7 @@ static int ti_sn_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
out:
|
||||
|
||||
if (!pdata->pwm_enabled)
|
||||
pm_runtime_put_sync(pdata->dev);
|
||||
pm_runtime_put_sync(chip->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -1585,12 +1585,14 @@ static int ti_sn_pwm_probe(struct auxiliary_device *adev,
|
||||
{
|
||||
struct ti_sn65dsi86 *pdata = dev_get_drvdata(adev->dev.parent);
|
||||
|
||||
pdata->pchip.dev = pdata->dev;
|
||||
pdata->pchip.dev = &adev->dev;
|
||||
pdata->pchip.ops = &ti_sn_pwm_ops;
|
||||
pdata->pchip.npwm = 1;
|
||||
pdata->pchip.of_xlate = of_pwm_single_xlate;
|
||||
pdata->pchip.of_pwm_n_cells = 1;
|
||||
|
||||
devm_pm_runtime_enable(&adev->dev);
|
||||
|
||||
return pwmchip_add(&pdata->pchip);
|
||||
}
|
||||
|
||||
@ -1601,7 +1603,7 @@ static void ti_sn_pwm_remove(struct auxiliary_device *adev)
|
||||
pwmchip_remove(&pdata->pchip);
|
||||
|
||||
if (pdata->pwm_enabled)
|
||||
pm_runtime_put_sync(pdata->dev);
|
||||
pm_runtime_put_sync(&adev->dev);
|
||||
}
|
||||
|
||||
static const struct auxiliary_device_id ti_sn_pwm_id_table[] = {
|
||||
|
@ -186,6 +186,7 @@ CONFIG_HW_RANDOM_MTK=y
|
||||
CONFIG_MTK_DEVAPC=y
|
||||
CONFIG_PWM_MTK_DISP=y
|
||||
CONFIG_MTK_CMDQ=y
|
||||
CONFIG_REGULATOR_DA9211=y
|
||||
|
||||
# For nouveau. Note that DRM must be a module so that it's loaded after NFS is up to provide the firmware.
|
||||
CONFIG_ARCH_TEGRA=y
|
||||
|
@ -19,7 +19,7 @@ if [[ "$KERNEL_ARCH" = "arm64" ]]; then
|
||||
DEVICE_TREES+=" arch/arm64/boot/dts/amlogic/meson-gxl-s805x-libretech-ac.dtb"
|
||||
DEVICE_TREES+=" arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dtb"
|
||||
DEVICE_TREES+=" arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dtb"
|
||||
DEVICE_TREES+=" arch/arm64/boot/dts/qcom/apq8016-sbc.dtb"
|
||||
DEVICE_TREES+=" arch/arm64/boot/dts/qcom/apq8016-sbc-usb-host.dtb"
|
||||
DEVICE_TREES+=" arch/arm64/boot/dts/qcom/apq8096-db820c.dtb"
|
||||
DEVICE_TREES+=" arch/arm64/boot/dts/amlogic/meson-g12b-a311d-khadas-vim3.dtb"
|
||||
DEVICE_TREES+=" arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtb"
|
||||
@ -75,19 +75,19 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
for opt in $ENABLE_KCONFIGS; do
|
||||
echo CONFIG_$opt=y >> drivers/gpu/drm/ci/${KERNEL_ARCH}.config
|
||||
done
|
||||
for opt in $DISABLE_KCONFIGS; do
|
||||
echo CONFIG_$opt=n >> drivers/gpu/drm/ci/${KERNEL_ARCH}.config
|
||||
done
|
||||
|
||||
if [[ -n "${MERGE_FRAGMENT}" ]]; then
|
||||
./scripts/kconfig/merge_config.sh ${DEFCONFIG} drivers/gpu/drm/ci/${MERGE_FRAGMENT}
|
||||
else
|
||||
make `basename ${DEFCONFIG}`
|
||||
fi
|
||||
|
||||
for opt in $ENABLE_KCONFIGS; do
|
||||
./scripts/config --enable CONFIG_$opt
|
||||
done
|
||||
for opt in $DISABLE_KCONFIGS; do
|
||||
./scripts/config --disable CONFIG_$opt
|
||||
done
|
||||
|
||||
make ${KERNEL_IMAGE_NAME}
|
||||
|
||||
mkdir -p /lava-files/
|
||||
|
@ -5,7 +5,7 @@ variables:
|
||||
UPSTREAM_REPO: git://anongit.freedesktop.org/drm/drm
|
||||
TARGET_BRANCH: drm-next
|
||||
|
||||
IGT_VERSION: d1db7333d9c5fbbb05e50b0804123950d9dc1c46
|
||||
IGT_VERSION: d2af13d9f5be5ce23d996e4afd3e45990f5ab977
|
||||
|
||||
DEQP_RUNNER_GIT_URL: https://gitlab.freedesktop.org/anholt/deqp-runner.git
|
||||
DEQP_RUNNER_GIT_TAG: v0.15.0
|
||||
|
@ -15,15 +15,21 @@ cat /sys/kernel/debug/device_component/*
|
||||
'
|
||||
|
||||
# Dump drm state to confirm that kernel was able to find a connected display:
|
||||
# TODO this path might not exist for all drivers.. maybe run modetest instead?
|
||||
set +e
|
||||
cat /sys/kernel/debug/dri/*/state
|
||||
set -e
|
||||
|
||||
case "$DRIVER_NAME" in
|
||||
rockchip|mediatek|meson)
|
||||
rockchip|meson)
|
||||
export IGT_FORCE_DRIVER="panfrost"
|
||||
;;
|
||||
mediatek)
|
||||
if [ "$GPU_VERSION" = "mt8173" ]; then
|
||||
export IGT_FORCE_DRIVER=${DRIVER_NAME}
|
||||
elif [ "$GPU_VERSION" = "mt8183" ]; then
|
||||
export IGT_FORCE_DRIVER="panfrost"
|
||||
fi
|
||||
;;
|
||||
amdgpu)
|
||||
# Cannot use HWCI_KERNEL_MODULES as at that point we don't have the module in /lib
|
||||
mv /install/modules/lib/modules/* /lib/modules/.
|
||||
|
@ -102,15 +102,12 @@ msm:apq8016:
|
||||
stage: msm
|
||||
variables:
|
||||
DRIVER_NAME: msm
|
||||
BM_DTB: https://${PIPELINE_ARTIFACTS_BASE}/arm64/apq8016-sbc.dtb
|
||||
BM_DTB: https://${PIPELINE_ARTIFACTS_BASE}/arm64/apq8016-sbc-usb-host.dtb
|
||||
GPU_VERSION: apq8016
|
||||
BM_CMDLINE: "ip=dhcp console=ttyMSM0,115200n8 $BM_KERNEL_EXTRA_ARGS root=/dev/nfs rw nfsrootdebug nfsroot=,tcp,nfsvers=4.2 init=/init $BM_KERNELARGS"
|
||||
RUNNER_TAG: google-freedreno-db410c
|
||||
script:
|
||||
- ./install/bare-metal/fastboot.sh
|
||||
rules:
|
||||
# TODO: current issue: it is not fiding the NFS root. Fix and remove this rule.
|
||||
- when: never
|
||||
|
||||
msm:apq8096:
|
||||
extends:
|
||||
@ -280,9 +277,6 @@ mediatek:mt8173:
|
||||
DEVICE_TYPE: mt8173-elm-hana
|
||||
GPU_VERSION: mt8173
|
||||
RUNNER_TAG: mesa-ci-x86-64-lava-mt8173-elm-hana
|
||||
rules:
|
||||
# TODO: current issue: device is hanging. Fix and remove this rule.
|
||||
- when: never
|
||||
|
||||
mediatek:mt8183:
|
||||
extends:
|
||||
@ -335,11 +329,10 @@ virtio_gpu:none:
|
||||
script:
|
||||
- ln -sf $CI_PROJECT_DIR/install /install
|
||||
- mv install/bzImage /lava-files/bzImage
|
||||
- mkdir -p $CI_PROJECT_DIR/results
|
||||
- ln -sf $CI_PROJECT_DIR/results /results
|
||||
- install/crosvm-runner.sh install/igt_runner.sh
|
||||
needs:
|
||||
- debian/x86_64_test-gl
|
||||
- testing:x86_64
|
||||
- igt:x86_64
|
||||
rules:
|
||||
# TODO: current issue: malloc(): corrupted top size. Fix and remove this rule.
|
||||
- when: never
|
@ -1,5 +1,4 @@
|
||||
kms_3d,Fail
|
||||
kms_addfb_basic@addfb25-bad-modifier,Fail
|
||||
kms_bw@linear-tiling-1-displays-1920x1080p,Fail
|
||||
kms_bw@linear-tiling-1-displays-2560x1440p,Fail
|
||||
kms_bw@linear-tiling-1-displays-3840x2160p,Fail
|
||||
@ -9,13 +8,19 @@ kms_bw@linear-tiling-2-displays-3840x2160p,Fail
|
||||
kms_bw@linear-tiling-3-displays-1920x1080p,Fail
|
||||
kms_bw@linear-tiling-3-displays-2560x1440p,Fail
|
||||
kms_bw@linear-tiling-3-displays-3840x2160p,Fail
|
||||
kms_color@invalid-gamma-lut-sizes,Fail
|
||||
kms_color@pipe-A-invalid-gamma-lut-sizes,Fail
|
||||
kms_color@pipe-B-invalid-gamma-lut-sizes,Fail
|
||||
kms_force_connector_basic@force-connector-state,Fail
|
||||
kms_cursor_legacy@cursor-vs-flip-atomic,Fail
|
||||
kms_cursor_legacy@cursor-vs-flip-legacy,Fail
|
||||
kms_flip@flip-vs-modeset-vs-hang,Fail
|
||||
kms_flip@flip-vs-panning-vs-hang,Fail
|
||||
kms_flip@flip-vs-suspend,Fail
|
||||
kms_flip@flip-vs-suspend-interruptible,Fail
|
||||
kms_force_connector_basic@force-edid,Fail
|
||||
kms_force_connector_basic@force-load-detect,Fail
|
||||
kms_force_connector_basic@prune-stale-modes,Fail
|
||||
kms_invalid_mode@int-max-clock,Fail
|
||||
kms_hdmi_inject@inject-4k,Fail
|
||||
kms_plane_scaling@planes-upscale-20x20,Fail
|
||||
kms_plane_scaling@planes-upscale-20x20-downscale-factor-0-25,Fail
|
||||
kms_plane_scaling@planes-upscale-20x20-downscale-factor-0-5,Fail
|
||||
@ -27,3 +32,5 @@ kms_properties@get_properties-sanity-atomic,Fail
|
||||
kms_properties@plane-properties-atomic,Fail
|
||||
kms_properties@plane-properties-legacy,Fail
|
||||
kms_rmfb@close-fd,Fail
|
||||
kms_selftest@drm_format,Timeout
|
||||
kms_selftest@drm_format_helper,Timeout
|
||||
|
@ -6,10 +6,15 @@ kms_cursor_legacy@all-pipes-single-bo,Fail
|
||||
kms_cursor_legacy@all-pipes-single-move,Fail
|
||||
kms_cursor_legacy@all-pipes-torture-bo,Fail
|
||||
kms_cursor_legacy@all-pipes-torture-move,Fail
|
||||
kms_cursor_legacy@forked-bo,Fail
|
||||
kms_cursor_legacy@forked-move,Fail
|
||||
kms_cursor_legacy@pipe-A-forked-bo,Fail
|
||||
kms_cursor_legacy@pipe-A-forked-move,Fail
|
||||
kms_cursor_legacy@pipe-A-single-bo,Fail
|
||||
kms_cursor_legacy@pipe-A-single-move,Fail
|
||||
kms_cursor_legacy@pipe-A-torture-bo,Fail
|
||||
kms_cursor_legacy@pipe-A-torture-move,Fail
|
||||
kms_force_connector_basic@force-edid,Fail
|
||||
kms_hdmi_inject@inject-4k,Fail
|
||||
kms_selftest@drm_format,Timeout
|
||||
kms_selftest@drm_format_helper,Timeout
|
||||
|
@ -10,6 +10,49 @@ kms_bw@linear-tiling-1-displays-3840x2160p,Fail
|
||||
kms_bw@linear-tiling-2-displays-1920x1080p,Fail
|
||||
kms_bw@linear-tiling-2-displays-2560x1440p,Fail
|
||||
kms_bw@linear-tiling-2-displays-3840x2160p,Fail
|
||||
kms_bw@linear-tiling-3-displays-1920x1080p,Fail
|
||||
kms_bw@linear-tiling-3-displays-2560x1440p,Fail
|
||||
kms_bw@linear-tiling-3-displays-3840x2160p,Fail
|
||||
kms_bw@linear-tiling-4-displays-1920x1080p,Fail
|
||||
kms_bw@linear-tiling-4-displays-2560x1440p,Fail
|
||||
kms_bw@linear-tiling-4-displays-3840x2160p,Fail
|
||||
kms_bw@linear-tiling-5-displays-1920x1080p,Fail
|
||||
kms_bw@linear-tiling-5-displays-2560x1440p,Fail
|
||||
kms_bw@linear-tiling-5-displays-3840x2160p,Fail
|
||||
kms_bw@linear-tiling-6-displays-1920x1080p,Fail
|
||||
kms_bw@linear-tiling-6-displays-2560x1440p,Fail
|
||||
kms_bw@linear-tiling-6-displays-3840x2160p,Fail
|
||||
kms_bw@linear-tiling-7-displays-1920x1080p,Fail
|
||||
kms_bw@linear-tiling-7-displays-2560x1440p,Fail
|
||||
kms_bw@linear-tiling-7-displays-3840x2160p,Fail
|
||||
kms_bw@linear-tiling-8-displays-1920x1080p,Fail
|
||||
kms_bw@linear-tiling-8-displays-2560x1440p,Fail
|
||||
kms_bw@linear-tiling-8-displays-3840x2160p,Fail
|
||||
kms_flip@absolute-wf_vblank,Fail
|
||||
kms_flip@absolute-wf_vblank-interruptible,Fail
|
||||
kms_flip@basic-flip-vs-wf_vblank,Fail
|
||||
kms_flip@blocking-absolute-wf_vblank,Fail
|
||||
kms_flip@blocking-absolute-wf_vblank-interruptible,Fail
|
||||
kms_flip@blocking-wf_vblank,Fail
|
||||
kms_flip@busy-flip,Fail
|
||||
kms_flip@dpms-vs-vblank-race,Fail
|
||||
kms_flip@dpms-vs-vblank-race-interruptible,Fail
|
||||
kms_flip@flip-vs-absolute-wf_vblank,Fail
|
||||
kms_flip@flip-vs-absolute-wf_vblank-interruptible,Fail
|
||||
kms_flip@flip-vs-blocking-wf-vblank,Fail
|
||||
kms_flip@flip-vs-expired-vblank,Fail
|
||||
kms_flip@flip-vs-expired-vblank-interruptible,Fail
|
||||
kms_flip@flip-vs-modeset-vs-hang,Fail
|
||||
kms_flip@flip-vs-panning-vs-hang,Fail
|
||||
kms_flip@flip-vs-wf_vblank-interruptible,Fail
|
||||
kms_flip@modeset-vs-vblank-race,Fail
|
||||
kms_flip@modeset-vs-vblank-race-interruptible,Fail
|
||||
kms_flip@plain-flip-fb-recreate,Fail
|
||||
kms_flip@plain-flip-fb-recreate-interruptible,Fail
|
||||
kms_flip@plain-flip-ts-check,Fail
|
||||
kms_flip@plain-flip-ts-check-interruptible,Fail
|
||||
kms_flip@wf_vblank-ts-check,Fail
|
||||
kms_flip@wf_vblank-ts-check-interruptible,Fail
|
||||
kms_invalid_mode@int-max-clock,Fail
|
||||
kms_plane_scaling@downscale-with-modifier-factor-0-25,Fail
|
||||
kms_plane_scaling@downscale-with-rotation-factor-0-25,Fail
|
||||
@ -22,6 +65,9 @@ kms_plane_scaling@upscale-with-modifier-factor-0-25,Fail
|
||||
kms_plane_scaling@upscale-with-pixel-format-20x20,Fail
|
||||
kms_plane_scaling@upscale-with-pixel-format-factor-0-25,Fail
|
||||
kms_plane_scaling@upscale-with-rotation-20x20,Fail
|
||||
kms_selftest@drm_format,Timeout
|
||||
kms_selftest@drm_format_helper,Timeout
|
||||
kms_setmode@basic,Fail
|
||||
kms_vblank@crtc-id,Fail
|
||||
kms_vblank@invalid,Fail
|
||||
kms_vblank@pipe-A-accuracy-idle,Fail
|
||||
|
@ -795,9 +795,9 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
|
||||
EXPORT_SYMBOL(drm_atomic_helper_check_modeset);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_check_wb_encoder_state() - Check writeback encoder state
|
||||
* @encoder: encoder state to check
|
||||
* @conn_state: connector state to check
|
||||
* drm_atomic_helper_check_wb_connector_state() - Check writeback connector state
|
||||
* @connector: corresponding connector
|
||||
* @state: the driver state object
|
||||
*
|
||||
* Checks if the writeback connector state is valid, and returns an error if it
|
||||
* isn't.
|
||||
@ -806,9 +806,11 @@ EXPORT_SYMBOL(drm_atomic_helper_check_modeset);
|
||||
* Zero for success or -errno
|
||||
*/
|
||||
int
|
||||
drm_atomic_helper_check_wb_encoder_state(struct drm_encoder *encoder,
|
||||
struct drm_connector_state *conn_state)
|
||||
drm_atomic_helper_check_wb_connector_state(struct drm_connector *connector,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_connector_state *conn_state =
|
||||
drm_atomic_get_new_connector_state(state, connector);
|
||||
struct drm_writeback_job *wb_job = conn_state->writeback_job;
|
||||
struct drm_property_blob *pixel_format_blob;
|
||||
struct drm_framebuffer *fb;
|
||||
@ -827,11 +829,11 @@ drm_atomic_helper_check_wb_encoder_state(struct drm_encoder *encoder,
|
||||
if (fb->format->format == formats[i])
|
||||
return 0;
|
||||
|
||||
drm_dbg_kms(encoder->dev, "Invalid pixel format %p4cc\n", &fb->format->format);
|
||||
drm_dbg_kms(connector->dev, "Invalid pixel format %p4cc\n", &fb->format->format);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_check_wb_encoder_state);
|
||||
EXPORT_SYMBOL(drm_atomic_helper_check_wb_connector_state);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_check_plane_state() - Check plane state for validity
|
||||
|
@ -638,7 +638,7 @@ void drm_debugfs_encoder_add(struct drm_encoder *encoder)
|
||||
debugfs_create_file("bridges", 0444, root, encoder,
|
||||
&bridges_fops);
|
||||
|
||||
if (encoder->funcs->debugfs_init)
|
||||
if (encoder->funcs && encoder->funcs->debugfs_init)
|
||||
encoder->funcs->debugfs_init(encoder, root);
|
||||
}
|
||||
|
||||
|
@ -248,7 +248,7 @@ static bool fw_trace_get_next(struct pvr_fw_trace_seq_data *trace_seq_data)
|
||||
continue;
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
/* Hit end of trace data. */
|
||||
return false;
|
||||
|
@ -316,12 +316,14 @@ err_free_page:
|
||||
static void
|
||||
pvr_mmu_backing_page_fini(struct pvr_mmu_backing_page *page)
|
||||
{
|
||||
struct device *dev = from_pvr_device(page->pvr_dev)->dev;
|
||||
struct device *dev;
|
||||
|
||||
/* Do nothing if no allocation is present. */
|
||||
if (!page->pvr_dev)
|
||||
return;
|
||||
|
||||
dev = from_pvr_device(page->pvr_dev)->dev;
|
||||
|
||||
dma_unmap_page(dev, page->dma_addr, PVR_MMU_BACKING_PAGE_SIZE,
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
|
@ -225,7 +225,7 @@ pvr_vm_bind_op_map_init(struct pvr_vm_bind_op *bind_op,
|
||||
u64 device_addr, u64 size)
|
||||
{
|
||||
struct drm_gem_object *obj = gem_from_pvr_gem(pvr_obj);
|
||||
const bool is_user = vm_ctx == vm_ctx->pvr_dev->kernel_vm_ctx;
|
||||
const bool is_user = vm_ctx != vm_ctx->pvr_dev->kernel_vm_ctx;
|
||||
const u64 pvr_obj_size = pvr_gem_object_size(pvr_obj);
|
||||
struct sg_table *sgt;
|
||||
u64 offset_plus_size;
|
||||
|
@ -194,6 +194,15 @@ config DRM_PANEL_ILITEK_ILI9341
|
||||
QVGA (240x320) RGB panels. support serial & parallel rgb
|
||||
interface.
|
||||
|
||||
config DRM_PANEL_ILITEK_ILI9805
|
||||
tristate "Ilitek ILI9805-based panels"
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
help
|
||||
Say Y if you want to enable support for panels based on the
|
||||
Ilitek ILI9805 controller.
|
||||
|
||||
config DRM_PANEL_ILITEK_ILI9881C
|
||||
tristate "Ilitek ILI9881C-based panels"
|
||||
depends on OF
|
||||
@ -735,6 +744,15 @@ config DRM_PANEL_SITRONIX_ST7789V
|
||||
Say Y here if you want to enable support for the Sitronix
|
||||
ST7789V controller for 240x320 LCD panels
|
||||
|
||||
config DRM_PANEL_SYNAPTICS_R63353
|
||||
tristate "Synaptics R63353-based panels"
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
help
|
||||
Say Y if you want to enable support for panels based on the
|
||||
Synaptics R63353 controller.
|
||||
|
||||
config DRM_PANEL_SONY_ACX565AKM
|
||||
tristate "Sony ACX565AKM panel"
|
||||
depends on GPIOLIB && OF && SPI
|
||||
|
@ -17,6 +17,7 @@ obj-$(CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D) += panel-feiyang-fy07024di26a30d
|
||||
obj-$(CONFIG_DRM_PANEL_HIMAX_HX8394) += panel-himax-hx8394.o
|
||||
obj-$(CONFIG_DRM_PANEL_ILITEK_IL9322) += panel-ilitek-ili9322.o
|
||||
obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9341) += panel-ilitek-ili9341.o
|
||||
obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9805) += panel-ilitek-ili9805.o
|
||||
obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9881C) += panel-ilitek-ili9881c.o
|
||||
obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9882T) += panel-ilitek-ili9882t.o
|
||||
obj-$(CONFIG_DRM_PANEL_INNOLUX_EJ030NA) += panel-innolux-ej030na.o
|
||||
@ -74,6 +75,7 @@ obj-$(CONFIG_DRM_PANEL_SHARP_LS060T1SX01) += panel-sharp-ls060t1sx01.o
|
||||
obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7701) += panel-sitronix-st7701.o
|
||||
obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7703) += panel-sitronix-st7703.o
|
||||
obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7789V) += panel-sitronix-st7789v.o
|
||||
obj-$(CONFIG_DRM_PANEL_SYNAPTICS_R63353) += panel-synaptics-r63353.o
|
||||
obj-$(CONFIG_DRM_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o
|
||||
obj-$(CONFIG_DRM_PANEL_SONY_TD4353_JDI) += panel-sony-td4353-jdi.o
|
||||
obj-$(CONFIG_DRM_PANEL_SONY_TULIP_TRULY_NT35521) += panel-sony-tulip-truly-nt35521.o
|
||||
|
@ -1980,9 +1980,10 @@ static const struct edp_panel_entry edp_panels[] = {
|
||||
EDP_PANEL_ENTRY('I', 'V', 'O', 0x8c4d, &delay_200_150_e200, "R140NWFM R1"),
|
||||
|
||||
EDP_PANEL_ENTRY('K', 'D', 'B', 0x0624, &kingdisplay_kd116n21_30nv_a010.delay, "116N21-30NV-A010"),
|
||||
EDP_PANEL_ENTRY('K', 'D', 'C', 0x0809, &delay_200_500_e50, "KD116N2930A15"),
|
||||
EDP_PANEL_ENTRY('K', 'D', 'B', 0x1120, &delay_200_500_e80_d50, "116N29-30NK-C007"),
|
||||
|
||||
EDP_PANEL_ENTRY('K', 'D', 'C', 0x0809, &delay_200_500_e50, "KD116N2930A15"),
|
||||
|
||||
EDP_PANEL_ENTRY('S', 'D', 'C', 0x416d, &delay_100_500_e200, "ATNA45AF01"),
|
||||
|
||||
EDP_PANEL_ENTRY('S', 'H', 'P', 0x1511, &delay_200_500_e50, "LQ140M1JW48"),
|
||||
|
405
drivers/gpu/drm/panel/panel-ilitek-ili9805.c
Normal file
405
drivers/gpu/drm/panel/panel-ilitek-ili9805.c
Normal file
@ -0,0 +1,405 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2020 BSH Hausgerate GmbH
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
#define ILI9805_EXTCMD_CMD_SET_ENABLE_REG (0xff)
|
||||
#define ILI9805_SETEXTC_PARAMETER1 (0xff)
|
||||
#define ILI9805_SETEXTC_PARAMETER2 (0x98)
|
||||
#define ILI9805_SETEXTC_PARAMETER3 (0x05)
|
||||
|
||||
#define ILI9805_INSTR(_delay, ...) { \
|
||||
.delay = (_delay), \
|
||||
.len = sizeof((u8[]) {__VA_ARGS__}), \
|
||||
.data = (u8[]){__VA_ARGS__} \
|
||||
}
|
||||
|
||||
struct ili9805_instr {
|
||||
size_t len;
|
||||
const u8 *data;
|
||||
u32 delay;
|
||||
};
|
||||
|
||||
struct ili9805_desc {
|
||||
const char *name;
|
||||
const struct ili9805_instr *init;
|
||||
const size_t init_length;
|
||||
const struct drm_display_mode *mode;
|
||||
u32 width_mm;
|
||||
u32 height_mm;
|
||||
};
|
||||
|
||||
struct ili9805 {
|
||||
struct drm_panel panel;
|
||||
struct mipi_dsi_device *dsi;
|
||||
const struct ili9805_desc *desc;
|
||||
|
||||
struct regulator *dvdd;
|
||||
struct regulator *avdd;
|
||||
struct gpio_desc *reset_gpio;
|
||||
};
|
||||
|
||||
static const struct ili9805_instr gpm1780a0_init[] = {
|
||||
ILI9805_INSTR(100, ILI9805_EXTCMD_CMD_SET_ENABLE_REG, ILI9805_SETEXTC_PARAMETER1,
|
||||
ILI9805_SETEXTC_PARAMETER2, ILI9805_SETEXTC_PARAMETER3),
|
||||
ILI9805_INSTR(100, 0xFD, 0x0F, 0x10, 0x44, 0x00),
|
||||
ILI9805_INSTR(0, 0xf8, 0x18, 0x02, 0x02, 0x18, 0x02, 0x02, 0x30, 0x00,
|
||||
0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00),
|
||||
ILI9805_INSTR(0, 0xB8, 0x62),
|
||||
ILI9805_INSTR(0, 0xF1, 0x00),
|
||||
ILI9805_INSTR(0, 0xF2, 0x00, 0x58, 0x40),
|
||||
ILI9805_INSTR(0, 0xF3, 0x60, 0x83, 0x04),
|
||||
ILI9805_INSTR(0, 0xFC, 0x04, 0x0F, 0x01),
|
||||
ILI9805_INSTR(0, 0xEB, 0x08, 0x0F),
|
||||
ILI9805_INSTR(0, 0xe0, 0x00, 0x08, 0x0d, 0x0e, 0x0e, 0x0d, 0x0a, 0x08, 0x04,
|
||||
0x08, 0x0d, 0x0f, 0x0b, 0x1c, 0x14, 0x0a),
|
||||
ILI9805_INSTR(0, 0xe1, 0x00, 0x08, 0x0d, 0x0e, 0x0e, 0x0d, 0x0a, 0x08, 0x04,
|
||||
0x08, 0x0d, 0x0f, 0x0b, 0x1c, 0x14, 0x0a),
|
||||
ILI9805_INSTR(10, 0xc1, 0x13, 0x39, 0x19, 0x06),
|
||||
ILI9805_INSTR(10, 0xc7, 0xe5),
|
||||
ILI9805_INSTR(10, 0xB1, 0x00, 0x12, 0x14),
|
||||
ILI9805_INSTR(10, 0xB4, 0x02),
|
||||
ILI9805_INSTR(0, 0xBB, 0x14, 0x55),
|
||||
ILI9805_INSTR(0, MIPI_DCS_SET_ADDRESS_MODE, 0x08),
|
||||
ILI9805_INSTR(0, MIPI_DCS_SET_PIXEL_FORMAT, 0x77),
|
||||
ILI9805_INSTR(0, 0x20),
|
||||
ILI9805_INSTR(0, 0xB0, 0x01),
|
||||
ILI9805_INSTR(0, 0xB6, 0x31, 0x00, 0xef),
|
||||
ILI9805_INSTR(0, 0xDF, 0x23),
|
||||
ILI9805_INSTR(0, 0xB9, 0x02, 0x00),
|
||||
};
|
||||
|
||||
static const struct ili9805_instr tm041xdhg01_init[] = {
|
||||
ILI9805_INSTR(100, ILI9805_EXTCMD_CMD_SET_ENABLE_REG, ILI9805_SETEXTC_PARAMETER1,
|
||||
ILI9805_SETEXTC_PARAMETER2, ILI9805_SETEXTC_PARAMETER3),
|
||||
ILI9805_INSTR(100, 0xFD, 0x0F, 0x13, 0x44, 0x00),
|
||||
ILI9805_INSTR(0, 0xf8, 0x18, 0x02, 0x02, 0x18, 0x02, 0x02, 0x30, 0x01,
|
||||
0x01, 0x30, 0x01, 0x01, 0x30, 0x01, 0x01),
|
||||
ILI9805_INSTR(0, 0xB8, 0x74),
|
||||
ILI9805_INSTR(0, 0xF1, 0x00),
|
||||
ILI9805_INSTR(0, 0xF2, 0x00, 0x58, 0x40),
|
||||
ILI9805_INSTR(0, 0xFC, 0x04, 0x0F, 0x01),
|
||||
ILI9805_INSTR(0, 0xEB, 0x08, 0x0F),
|
||||
ILI9805_INSTR(0, 0xe0, 0x01, 0x0d, 0x15, 0x0e, 0x0f, 0x0f, 0x0b, 0x08, 0x04,
|
||||
0x07, 0x0a, 0x0d, 0x0c, 0x15, 0x0f, 0x08),
|
||||
ILI9805_INSTR(0, 0xe1, 0x01, 0x0d, 0x15, 0x0e, 0x0f, 0x0f, 0x0b, 0x08, 0x04,
|
||||
0x07, 0x0a, 0x0d, 0x0c, 0x15, 0x0f, 0x08),
|
||||
ILI9805_INSTR(10, 0xc1, 0x15, 0x03, 0x03, 0x31),
|
||||
ILI9805_INSTR(10, 0xB1, 0x00, 0x12, 0x14),
|
||||
ILI9805_INSTR(10, 0xB4, 0x02),
|
||||
ILI9805_INSTR(0, 0xBB, 0x14, 0x55),
|
||||
ILI9805_INSTR(0, MIPI_DCS_SET_ADDRESS_MODE, 0x0a),
|
||||
ILI9805_INSTR(0, MIPI_DCS_SET_PIXEL_FORMAT, 0x77),
|
||||
ILI9805_INSTR(0, 0x20),
|
||||
ILI9805_INSTR(0, 0xB0, 0x00),
|
||||
ILI9805_INSTR(0, 0xB6, 0x01),
|
||||
ILI9805_INSTR(0, 0xc2, 0x11),
|
||||
ILI9805_INSTR(0, 0x51, 0xFF),
|
||||
ILI9805_INSTR(0, 0x53, 0x24),
|
||||
ILI9805_INSTR(0, 0x55, 0x00),
|
||||
};
|
||||
|
||||
static inline struct ili9805 *panel_to_ili9805(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct ili9805, panel);
|
||||
}
|
||||
|
||||
static int ili9805_power_on(struct ili9805 *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
ret = regulator_enable(ctx->avdd);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to enable avdd regulator (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regulator_enable(ctx->dvdd);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to enable dvdd regulator (%d)\n", ret);
|
||||
regulator_disable(ctx->avdd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
gpiod_set_value(ctx->reset_gpio, 0);
|
||||
usleep_range(5000, 10000);
|
||||
gpiod_set_value(ctx->reset_gpio, 1);
|
||||
msleep(120);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ili9805_power_off(struct ili9805 *ctx)
|
||||
{
|
||||
gpiod_set_value(ctx->reset_gpio, 0);
|
||||
regulator_disable(ctx->dvdd);
|
||||
regulator_disable(ctx->avdd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ili9805_activate(struct ili9805 *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < ctx->desc->init_length; i++) {
|
||||
const struct ili9805_instr *instr = &ctx->desc->init[i];
|
||||
|
||||
ret = mipi_dsi_dcs_write_buffer(ctx->dsi, instr->data, instr->len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (instr->delay > 0)
|
||||
msleep(instr->delay);
|
||||
}
|
||||
|
||||
ret = mipi_dsi_dcs_exit_sleep_mode(ctx->dsi);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to exit sleep mode (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
usleep_range(5000, 6000);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_on(ctx->dsi);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to set display ON (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ili9805_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct ili9805 *ctx = panel_to_ili9805(panel);
|
||||
int ret;
|
||||
|
||||
ret = ili9805_power_on(ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ili9805_activate(ctx);
|
||||
if (ret) {
|
||||
ili9805_power_off(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ili9805_deactivate(struct ili9805 *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_off(ctx->dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display OFF (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
usleep_range(5000, 10000);
|
||||
|
||||
ret = mipi_dsi_dcs_enter_sleep_mode(ctx->dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enter sleep mode (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ili9805_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct ili9805 *ctx = panel_to_ili9805(panel);
|
||||
|
||||
ili9805_deactivate(ctx);
|
||||
ili9805_power_off(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_display_mode gpm1780a0_timing = {
|
||||
.clock = 26227,
|
||||
|
||||
.hdisplay = 480,
|
||||
.hsync_start = 480 + 10,
|
||||
.hsync_end = 480 + 10 + 2,
|
||||
.htotal = 480 + 10 + 2 + 36,
|
||||
|
||||
.vdisplay = 480,
|
||||
.vsync_start = 480 + 2,
|
||||
.vsync_end = 480 + 10 + 4,
|
||||
.vtotal = 480 + 2 + 4 + 10,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode tm041xdhg01_timing = {
|
||||
.clock = 26227,
|
||||
|
||||
.hdisplay = 480,
|
||||
.hsync_start = 480 + 10,
|
||||
.hsync_end = 480 + 10 + 2,
|
||||
.htotal = 480 + 10 + 2 + 36,
|
||||
|
||||
.vdisplay = 768,
|
||||
.vsync_start = 768 + 2,
|
||||
.vsync_end = 768 + 10 + 4,
|
||||
.vtotal = 768 + 2 + 4 + 10,
|
||||
};
|
||||
|
||||
static int ili9805_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct ili9805 *ctx = panel_to_ili9805(panel);
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev, ctx->desc->mode);
|
||||
if (!mode) {
|
||||
dev_err(&ctx->dsi->dev, "failed to add mode %ux%ux@%u\n",
|
||||
ctx->desc->mode->hdisplay,
|
||||
ctx->desc->mode->vdisplay,
|
||||
drm_mode_vrefresh(ctx->desc->mode));
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
drm_mode_set_name(mode);
|
||||
|
||||
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
||||
drm_mode_probed_add(connector, mode);
|
||||
|
||||
connector->display_info.width_mm = mode->width_mm;
|
||||
connector->display_info.height_mm = mode->height_mm;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs ili9805_funcs = {
|
||||
.prepare = ili9805_prepare,
|
||||
.unprepare = ili9805_unprepare,
|
||||
.get_modes = ili9805_get_modes,
|
||||
};
|
||||
|
||||
static int ili9805_dsi_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct ili9805 *ctx;
|
||||
int ret;
|
||||
|
||||
ctx = devm_kzalloc(&dsi->dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
mipi_dsi_set_drvdata(dsi, ctx);
|
||||
ctx->dsi = dsi;
|
||||
ctx->desc = of_device_get_match_data(&dsi->dev);
|
||||
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO |
|
||||
MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM |
|
||||
MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_NO_EOT_PACKET;
|
||||
dsi->lanes = 2;
|
||||
|
||||
drm_panel_init(&ctx->panel, &dsi->dev, &ili9805_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
|
||||
ctx->dvdd = devm_regulator_get(&dsi->dev, "dvdd");
|
||||
if (IS_ERR(ctx->dvdd))
|
||||
return PTR_ERR(ctx->dvdd);
|
||||
ctx->avdd = devm_regulator_get(&dsi->dev, "avdd");
|
||||
if (IS_ERR(ctx->avdd))
|
||||
return PTR_ERR(ctx->avdd);
|
||||
|
||||
ctx->reset_gpio = devm_gpiod_get(&dsi->dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(ctx->reset_gpio)) {
|
||||
dev_err(&dsi->dev, "Couldn't get our reset GPIO\n");
|
||||
return PTR_ERR(ctx->reset_gpio);
|
||||
}
|
||||
|
||||
ctx->panel.prepare_prev_first = true;
|
||||
ret = drm_panel_of_backlight(&ctx->panel);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drm_panel_add(&ctx->panel);
|
||||
|
||||
ret = mipi_dsi_attach(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(&dsi->dev, "mipi_dsi_attach failed: %d\n", ret);
|
||||
drm_panel_remove(&ctx->panel);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ili9805_dsi_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct ili9805 *ctx = mipi_dsi_get_drvdata(dsi);
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_detach(dsi);
|
||||
if (ret < 0)
|
||||
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n",
|
||||
ret);
|
||||
|
||||
drm_panel_remove(&ctx->panel);
|
||||
}
|
||||
|
||||
static const struct ili9805_desc gpm1780a0_desc = {
|
||||
.init = gpm1780a0_init,
|
||||
.init_length = ARRAY_SIZE(gpm1780a0_init),
|
||||
.mode = &gpm1780a0_timing,
|
||||
.width_mm = 65,
|
||||
.height_mm = 65,
|
||||
};
|
||||
|
||||
static const struct ili9805_desc tm041xdhg01_desc = {
|
||||
.init = tm041xdhg01_init,
|
||||
.init_length = ARRAY_SIZE(tm041xdhg01_init),
|
||||
.mode = &tm041xdhg01_timing,
|
||||
.width_mm = 42,
|
||||
.height_mm = 96,
|
||||
};
|
||||
|
||||
static const struct of_device_id ili9805_of_match[] = {
|
||||
{ .compatible = "giantplus,gpm1790a0", .data = &gpm1780a0_desc },
|
||||
{ .compatible = "tianma,tm041xdhg01", .data = &tm041xdhg01_desc },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ili9805_of_match);
|
||||
|
||||
static struct mipi_dsi_driver ili9805_dsi_driver = {
|
||||
.probe = ili9805_dsi_probe,
|
||||
.remove = ili9805_dsi_remove,
|
||||
.driver = {
|
||||
.name = "ili9805-dsi",
|
||||
.of_match_table = ili9805_of_match,
|
||||
},
|
||||
};
|
||||
module_mipi_dsi_driver(ili9805_dsi_driver);
|
||||
|
||||
MODULE_AUTHOR("Matthias Proske <Matthias.Proske@bshg.com>");
|
||||
MODULE_AUTHOR("Michael Trimarchi <michael@amarulasolutions.com>");
|
||||
MODULE_DESCRIPTION("Ilitek ILI9805 Controller Driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -20,11 +20,18 @@
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
struct nv3052c_reg {
|
||||
u8 cmd;
|
||||
u8 val;
|
||||
};
|
||||
|
||||
struct nv3052c_panel_info {
|
||||
const struct drm_display_mode *display_modes;
|
||||
unsigned int num_modes;
|
||||
u16 width_mm, height_mm;
|
||||
u32 bus_format, bus_flags;
|
||||
const struct nv3052c_reg *panel_regs;
|
||||
unsigned int panel_regs_len;
|
||||
};
|
||||
|
||||
struct nv3052c {
|
||||
@ -36,15 +43,10 @@ struct nv3052c {
|
||||
struct gpio_desc *reset_gpio;
|
||||
};
|
||||
|
||||
struct nv3052c_reg {
|
||||
u8 cmd;
|
||||
u8 val;
|
||||
};
|
||||
|
||||
static const struct nv3052c_reg nv3052c_panel_regs[] = {
|
||||
{ 0xff, 0x30 },
|
||||
{ 0xff, 0x52 },
|
||||
{ 0xff, 0x01 },
|
||||
static const struct nv3052c_reg ltk035c5444t_panel_regs[] = {
|
||||
// EXTC Command set enable, select page 1
|
||||
{ 0xff, 0x30 }, { 0xff, 0x52 }, { 0xff, 0x01 },
|
||||
// Mostly unknown registers
|
||||
{ 0xe3, 0x00 },
|
||||
{ 0x40, 0x00 },
|
||||
{ 0x03, 0x40 },
|
||||
@ -62,15 +64,15 @@ static const struct nv3052c_reg nv3052c_panel_regs[] = {
|
||||
{ 0x25, 0x06 },
|
||||
{ 0x26, 0x14 },
|
||||
{ 0x27, 0x14 },
|
||||
{ 0x38, 0xcc },
|
||||
{ 0x39, 0xd7 },
|
||||
{ 0x3a, 0x4a },
|
||||
{ 0x38, 0xcc }, // VCOM_ADJ1
|
||||
{ 0x39, 0xd7 }, // VCOM_ADJ2
|
||||
{ 0x3a, 0x4a }, // VCOM_ADJ3
|
||||
{ 0x28, 0x40 },
|
||||
{ 0x29, 0x01 },
|
||||
{ 0x2a, 0xdf },
|
||||
{ 0x49, 0x3c },
|
||||
{ 0x91, 0x77 },
|
||||
{ 0x92, 0x77 },
|
||||
{ 0x91, 0x77 }, // EXTPW_CTRL2
|
||||
{ 0x92, 0x77 }, // EXTPW_CTRL3
|
||||
{ 0xa0, 0x55 },
|
||||
{ 0xa1, 0x50 },
|
||||
{ 0xa4, 0x9c },
|
||||
@ -94,123 +96,126 @@ static const struct nv3052c_reg nv3052c_panel_regs[] = {
|
||||
{ 0xb8, 0x26 },
|
||||
{ 0xf0, 0x00 },
|
||||
{ 0xf6, 0xc0 },
|
||||
{ 0xff, 0x30 },
|
||||
{ 0xff, 0x52 },
|
||||
{ 0xff, 0x02 },
|
||||
{ 0xb0, 0x0b },
|
||||
{ 0xb1, 0x16 },
|
||||
{ 0xb2, 0x17 },
|
||||
{ 0xb3, 0x2c },
|
||||
{ 0xb4, 0x32 },
|
||||
{ 0xb5, 0x3b },
|
||||
{ 0xb6, 0x29 },
|
||||
{ 0xb7, 0x40 },
|
||||
{ 0xb8, 0x0d },
|
||||
{ 0xb9, 0x05 },
|
||||
{ 0xba, 0x12 },
|
||||
{ 0xbb, 0x10 },
|
||||
{ 0xbc, 0x12 },
|
||||
{ 0xbd, 0x15 },
|
||||
{ 0xbe, 0x19 },
|
||||
{ 0xbf, 0x0e },
|
||||
{ 0xc0, 0x16 },
|
||||
{ 0xc1, 0x0a },
|
||||
{ 0xd0, 0x0c },
|
||||
{ 0xd1, 0x17 },
|
||||
{ 0xd2, 0x14 },
|
||||
{ 0xd3, 0x2e },
|
||||
{ 0xd4, 0x32 },
|
||||
{ 0xd5, 0x3c },
|
||||
{ 0xd6, 0x22 },
|
||||
{ 0xd7, 0x3d },
|
||||
{ 0xd8, 0x0d },
|
||||
{ 0xd9, 0x07 },
|
||||
{ 0xda, 0x13 },
|
||||
{ 0xdb, 0x13 },
|
||||
{ 0xdc, 0x11 },
|
||||
{ 0xdd, 0x15 },
|
||||
{ 0xde, 0x19 },
|
||||
{ 0xdf, 0x10 },
|
||||
{ 0xe0, 0x17 },
|
||||
{ 0xe1, 0x0a },
|
||||
{ 0xff, 0x30 },
|
||||
{ 0xff, 0x52 },
|
||||
{ 0xff, 0x03 },
|
||||
{ 0x00, 0x2a },
|
||||
{ 0x01, 0x2a },
|
||||
{ 0x02, 0x2a },
|
||||
{ 0x03, 0x2a },
|
||||
{ 0x04, 0x61 },
|
||||
{ 0x05, 0x80 },
|
||||
{ 0x06, 0xc7 },
|
||||
{ 0x07, 0x01 },
|
||||
{ 0x08, 0x03 },
|
||||
{ 0x09, 0x04 },
|
||||
{ 0x70, 0x22 },
|
||||
{ 0x71, 0x80 },
|
||||
{ 0x30, 0x2a },
|
||||
{ 0x31, 0x2a },
|
||||
{ 0x32, 0x2a },
|
||||
{ 0x33, 0x2a },
|
||||
{ 0x34, 0x61 },
|
||||
{ 0x35, 0xc5 },
|
||||
{ 0x36, 0x80 },
|
||||
{ 0x37, 0x23 },
|
||||
{ 0x40, 0x03 },
|
||||
{ 0x41, 0x04 },
|
||||
{ 0x42, 0x05 },
|
||||
{ 0x43, 0x06 },
|
||||
{ 0x44, 0x11 },
|
||||
{ 0x45, 0xe8 },
|
||||
{ 0x46, 0xe9 },
|
||||
{ 0x47, 0x11 },
|
||||
{ 0x48, 0xea },
|
||||
{ 0x49, 0xeb },
|
||||
{ 0x50, 0x07 },
|
||||
{ 0x51, 0x08 },
|
||||
{ 0x52, 0x09 },
|
||||
{ 0x53, 0x0a },
|
||||
{ 0x54, 0x11 },
|
||||
{ 0x55, 0xec },
|
||||
{ 0x56, 0xed },
|
||||
{ 0x57, 0x11 },
|
||||
{ 0x58, 0xef },
|
||||
{ 0x59, 0xf0 },
|
||||
{ 0xb1, 0x01 },
|
||||
{ 0xb4, 0x15 },
|
||||
{ 0xb5, 0x16 },
|
||||
{ 0xb6, 0x09 },
|
||||
{ 0xb7, 0x0f },
|
||||
{ 0xb8, 0x0d },
|
||||
{ 0xb9, 0x0b },
|
||||
{ 0xba, 0x00 },
|
||||
{ 0xc7, 0x02 },
|
||||
{ 0xca, 0x17 },
|
||||
{ 0xcb, 0x18 },
|
||||
{ 0xcc, 0x0a },
|
||||
{ 0xcd, 0x10 },
|
||||
{ 0xce, 0x0e },
|
||||
{ 0xcf, 0x0c },
|
||||
{ 0xd0, 0x00 },
|
||||
{ 0x81, 0x00 },
|
||||
{ 0x84, 0x15 },
|
||||
{ 0x85, 0x16 },
|
||||
{ 0x86, 0x10 },
|
||||
{ 0x87, 0x0a },
|
||||
{ 0x88, 0x0c },
|
||||
{ 0x89, 0x0e },
|
||||
{ 0x8a, 0x02 },
|
||||
{ 0x97, 0x00 },
|
||||
{ 0x9a, 0x17 },
|
||||
{ 0x9b, 0x18 },
|
||||
{ 0x9c, 0x0f },
|
||||
{ 0x9d, 0x09 },
|
||||
{ 0x9e, 0x0b },
|
||||
{ 0x9f, 0x0d },
|
||||
{ 0xa0, 0x01 },
|
||||
{ 0xff, 0x30 },
|
||||
{ 0xff, 0x52 },
|
||||
{ 0xff, 0x02 },
|
||||
// EXTC Command set enable, select page 2
|
||||
{ 0xff, 0x30 }, { 0xff, 0x52 }, { 0xff, 0x02 },
|
||||
// Set gray scale voltage to adjust gamma
|
||||
{ 0xb0, 0x0b }, // PGAMVR0
|
||||
{ 0xb1, 0x16 }, // PGAMVR1
|
||||
{ 0xb2, 0x17 }, // PGAMVR2
|
||||
{ 0xb3, 0x2c }, // PGAMVR3
|
||||
{ 0xb4, 0x32 }, // PGAMVR4
|
||||
{ 0xb5, 0x3b }, // PGAMVR5
|
||||
{ 0xb6, 0x29 }, // PGAMPR0
|
||||
{ 0xb7, 0x40 }, // PGAMPR1
|
||||
{ 0xb8, 0x0d }, // PGAMPK0
|
||||
{ 0xb9, 0x05 }, // PGAMPK1
|
||||
{ 0xba, 0x12 }, // PGAMPK2
|
||||
{ 0xbb, 0x10 }, // PGAMPK3
|
||||
{ 0xbc, 0x12 }, // PGAMPK4
|
||||
{ 0xbd, 0x15 }, // PGAMPK5
|
||||
{ 0xbe, 0x19 }, // PGAMPK6
|
||||
{ 0xbf, 0x0e }, // PGAMPK7
|
||||
{ 0xc0, 0x16 }, // PGAMPK8
|
||||
{ 0xc1, 0x0a }, // PGAMPK9
|
||||
// Set gray scale voltage to adjust gamma
|
||||
{ 0xd0, 0x0c }, // NGAMVR0
|
||||
{ 0xd1, 0x17 }, // NGAMVR0
|
||||
{ 0xd2, 0x14 }, // NGAMVR1
|
||||
{ 0xd3, 0x2e }, // NGAMVR2
|
||||
{ 0xd4, 0x32 }, // NGAMVR3
|
||||
{ 0xd5, 0x3c }, // NGAMVR4
|
||||
{ 0xd6, 0x22 }, // NGAMPR0
|
||||
{ 0xd7, 0x3d }, // NGAMPR1
|
||||
{ 0xd8, 0x0d }, // NGAMPK0
|
||||
{ 0xd9, 0x07 }, // NGAMPK1
|
||||
{ 0xda, 0x13 }, // NGAMPK2
|
||||
{ 0xdb, 0x13 }, // NGAMPK3
|
||||
{ 0xdc, 0x11 }, // NGAMPK4
|
||||
{ 0xdd, 0x15 }, // NGAMPK5
|
||||
{ 0xde, 0x19 }, // NGAMPK6
|
||||
{ 0xdf, 0x10 }, // NGAMPK7
|
||||
{ 0xe0, 0x17 }, // NGAMPK8
|
||||
{ 0xe1, 0x0a }, // NGAMPK9
|
||||
// EXTC Command set enable, select page 3
|
||||
{ 0xff, 0x30 }, { 0xff, 0x52 }, { 0xff, 0x03 },
|
||||
// Set various timing settings
|
||||
{ 0x00, 0x2a }, // GIP_VST_1
|
||||
{ 0x01, 0x2a }, // GIP_VST_2
|
||||
{ 0x02, 0x2a }, // GIP_VST_3
|
||||
{ 0x03, 0x2a }, // GIP_VST_4
|
||||
{ 0x04, 0x61 }, // GIP_VST_5
|
||||
{ 0x05, 0x80 }, // GIP_VST_6
|
||||
{ 0x06, 0xc7 }, // GIP_VST_7
|
||||
{ 0x07, 0x01 }, // GIP_VST_8
|
||||
{ 0x08, 0x03 }, // GIP_VST_9
|
||||
{ 0x09, 0x04 }, // GIP_VST_10
|
||||
{ 0x70, 0x22 }, // GIP_ECLK1
|
||||
{ 0x71, 0x80 }, // GIP_ECLK2
|
||||
{ 0x30, 0x2a }, // GIP_CLK_1
|
||||
{ 0x31, 0x2a }, // GIP_CLK_2
|
||||
{ 0x32, 0x2a }, // GIP_CLK_3
|
||||
{ 0x33, 0x2a }, // GIP_CLK_4
|
||||
{ 0x34, 0x61 }, // GIP_CLK_5
|
||||
{ 0x35, 0xc5 }, // GIP_CLK_6
|
||||
{ 0x36, 0x80 }, // GIP_CLK_7
|
||||
{ 0x37, 0x23 }, // GIP_CLK_8
|
||||
{ 0x40, 0x03 }, // GIP_CLKA_1
|
||||
{ 0x41, 0x04 }, // GIP_CLKA_2
|
||||
{ 0x42, 0x05 }, // GIP_CLKA_3
|
||||
{ 0x43, 0x06 }, // GIP_CLKA_4
|
||||
{ 0x44, 0x11 }, // GIP_CLKA_5
|
||||
{ 0x45, 0xe8 }, // GIP_CLKA_6
|
||||
{ 0x46, 0xe9 }, // GIP_CLKA_7
|
||||
{ 0x47, 0x11 }, // GIP_CLKA_8
|
||||
{ 0x48, 0xea }, // GIP_CLKA_9
|
||||
{ 0x49, 0xeb }, // GIP_CLKA_10
|
||||
{ 0x50, 0x07 }, // GIP_CLKB_1
|
||||
{ 0x51, 0x08 }, // GIP_CLKB_2
|
||||
{ 0x52, 0x09 }, // GIP_CLKB_3
|
||||
{ 0x53, 0x0a }, // GIP_CLKB_4
|
||||
{ 0x54, 0x11 }, // GIP_CLKB_5
|
||||
{ 0x55, 0xec }, // GIP_CLKB_6
|
||||
{ 0x56, 0xed }, // GIP_CLKB_7
|
||||
{ 0x57, 0x11 }, // GIP_CLKB_8
|
||||
{ 0x58, 0xef }, // GIP_CLKB_9
|
||||
{ 0x59, 0xf0 }, // GIP_CLKB_10
|
||||
// Map internal GOA signals to GOA output pad
|
||||
{ 0xb1, 0x01 }, // PANELD2U2
|
||||
{ 0xb4, 0x15 }, // PANELD2U5
|
||||
{ 0xb5, 0x16 }, // PANELD2U6
|
||||
{ 0xb6, 0x09 }, // PANELD2U7
|
||||
{ 0xb7, 0x0f }, // PANELD2U8
|
||||
{ 0xb8, 0x0d }, // PANELD2U9
|
||||
{ 0xb9, 0x0b }, // PANELD2U10
|
||||
{ 0xba, 0x00 }, // PANELD2U11
|
||||
{ 0xc7, 0x02 }, // PANELD2U24
|
||||
{ 0xca, 0x17 }, // PANELD2U27
|
||||
{ 0xcb, 0x18 }, // PANELD2U28
|
||||
{ 0xcc, 0x0a }, // PANELD2U29
|
||||
{ 0xcd, 0x10 }, // PANELD2U30
|
||||
{ 0xce, 0x0e }, // PANELD2U31
|
||||
{ 0xcf, 0x0c }, // PANELD2U32
|
||||
{ 0xd0, 0x00 }, // PANELD2U33
|
||||
// Map internal GOA signals to GOA output pad
|
||||
{ 0x81, 0x00 }, // PANELU2D2
|
||||
{ 0x84, 0x15 }, // PANELU2D5
|
||||
{ 0x85, 0x16 }, // PANELU2D6
|
||||
{ 0x86, 0x10 }, // PANELU2D7
|
||||
{ 0x87, 0x0a }, // PANELU2D8
|
||||
{ 0x88, 0x0c }, // PANELU2D9
|
||||
{ 0x89, 0x0e }, // PANELU2D10
|
||||
{ 0x8a, 0x02 }, // PANELU2D11
|
||||
{ 0x97, 0x00 }, // PANELU2D24
|
||||
{ 0x9a, 0x17 }, // PANELU2D27
|
||||
{ 0x9b, 0x18 }, // PANELU2D28
|
||||
{ 0x9c, 0x0f }, // PANELU2D29
|
||||
{ 0x9d, 0x09 }, // PANELU2D30
|
||||
{ 0x9e, 0x0b }, // PANELU2D31
|
||||
{ 0x9f, 0x0d }, // PANELU2D32
|
||||
{ 0xa0, 0x01 }, // PANELU2D33
|
||||
// EXTC Command set enable, select page 2
|
||||
{ 0xff, 0x30 }, { 0xff, 0x52 }, { 0xff, 0x02 },
|
||||
// Unknown registers
|
||||
{ 0x01, 0x01 },
|
||||
{ 0x02, 0xda },
|
||||
{ 0x03, 0xba },
|
||||
@ -227,10 +232,205 @@ static const struct nv3052c_reg nv3052c_panel_regs[] = {
|
||||
{ 0x0e, 0x48 },
|
||||
{ 0x0f, 0x38 },
|
||||
{ 0x10, 0x2b },
|
||||
{ 0xff, 0x30 },
|
||||
{ 0xff, 0x52 },
|
||||
{ 0xff, 0x00 },
|
||||
{ 0x36, 0x0a },
|
||||
// EXTC Command set enable, select page 0
|
||||
{ 0xff, 0x30 }, { 0xff, 0x52 }, { 0xff, 0x00 },
|
||||
// Display Access Control
|
||||
{ 0x36, 0x0a }, // bgr = 1, ss = 1, gs = 0
|
||||
};
|
||||
|
||||
static const struct nv3052c_reg fs035vg158_panel_regs[] = {
|
||||
// EXTC Command set enable, select page 1
|
||||
{ 0xff, 0x30 }, { 0xff, 0x52 }, { 0xff, 0x01 },
|
||||
// Mostly unknown registers
|
||||
{ 0xe3, 0x00 },
|
||||
{ 0x40, 0x00 },
|
||||
{ 0x03, 0x40 },
|
||||
{ 0x04, 0x00 },
|
||||
{ 0x05, 0x03 },
|
||||
{ 0x08, 0x00 },
|
||||
{ 0x09, 0x07 },
|
||||
{ 0x0a, 0x01 },
|
||||
{ 0x0b, 0x32 },
|
||||
{ 0x0c, 0x32 },
|
||||
{ 0x0d, 0x0b },
|
||||
{ 0x0e, 0x00 },
|
||||
{ 0x23, 0x20 }, // RGB interface control: DE MODE PCLK-N
|
||||
{ 0x24, 0x0c },
|
||||
{ 0x25, 0x06 },
|
||||
{ 0x26, 0x14 },
|
||||
{ 0x27, 0x14 },
|
||||
{ 0x38, 0x9c }, //VCOM_ADJ1, different to ltk035c5444t
|
||||
{ 0x39, 0xa7 }, //VCOM_ADJ2, different to ltk035c5444t
|
||||
{ 0x3a, 0x50 }, //VCOM_ADJ3, different to ltk035c5444t
|
||||
{ 0x28, 0x40 },
|
||||
{ 0x29, 0x01 },
|
||||
{ 0x2a, 0xdf },
|
||||
{ 0x49, 0x3c },
|
||||
{ 0x91, 0x57 }, //EXTPW_CTRL2, different to ltk035c5444t
|
||||
{ 0x92, 0x57 }, //EXTPW_CTRL3, different to ltk035c5444t
|
||||
{ 0xa0, 0x55 },
|
||||
{ 0xa1, 0x50 },
|
||||
{ 0xa4, 0x9c },
|
||||
{ 0xa7, 0x02 },
|
||||
{ 0xa8, 0x01 },
|
||||
{ 0xa9, 0x01 },
|
||||
{ 0xaa, 0xfc },
|
||||
{ 0xab, 0x28 },
|
||||
{ 0xac, 0x06 },
|
||||
{ 0xad, 0x06 },
|
||||
{ 0xae, 0x06 },
|
||||
{ 0xaf, 0x03 },
|
||||
{ 0xb0, 0x08 },
|
||||
{ 0xb1, 0x26 },
|
||||
{ 0xb2, 0x28 },
|
||||
{ 0xb3, 0x28 },
|
||||
{ 0xb4, 0x03 }, // Unknown, different to ltk035c5444
|
||||
{ 0xb5, 0x08 },
|
||||
{ 0xb6, 0x26 },
|
||||
{ 0xb7, 0x08 },
|
||||
{ 0xb8, 0x26 },
|
||||
{ 0xf0, 0x00 },
|
||||
{ 0xf6, 0xc0 },
|
||||
// EXTC Command set enable, select page 0
|
||||
{ 0xff, 0x30 }, { 0xff, 0x52 }, { 0xff, 0x02 },
|
||||
// Set gray scale voltage to adjust gamma
|
||||
{ 0xb0, 0x0b }, // PGAMVR0
|
||||
{ 0xb1, 0x16 }, // PGAMVR1
|
||||
{ 0xb2, 0x17 }, // PGAMVR2
|
||||
{ 0xb3, 0x2c }, // PGAMVR3
|
||||
{ 0xb4, 0x32 }, // PGAMVR4
|
||||
{ 0xb5, 0x3b }, // PGAMVR5
|
||||
{ 0xb6, 0x29 }, // PGAMPR0
|
||||
{ 0xb7, 0x40 }, // PGAMPR1
|
||||
{ 0xb8, 0x0d }, // PGAMPK0
|
||||
{ 0xb9, 0x05 }, // PGAMPK1
|
||||
{ 0xba, 0x12 }, // PGAMPK2
|
||||
{ 0xbb, 0x10 }, // PGAMPK3
|
||||
{ 0xbc, 0x12 }, // PGAMPK4
|
||||
{ 0xbd, 0x15 }, // PGAMPK5
|
||||
{ 0xbe, 0x19 }, // PGAMPK6
|
||||
{ 0xbf, 0x0e }, // PGAMPK7
|
||||
{ 0xc0, 0x16 }, // PGAMPK8
|
||||
{ 0xc1, 0x0a }, // PGAMPK9
|
||||
// Set gray scale voltage to adjust gamma
|
||||
{ 0xd0, 0x0c }, // NGAMVR0
|
||||
{ 0xd1, 0x17 }, // NGAMVR0
|
||||
{ 0xd2, 0x14 }, // NGAMVR1
|
||||
{ 0xd3, 0x2e }, // NGAMVR2
|
||||
{ 0xd4, 0x32 }, // NGAMVR3
|
||||
{ 0xd5, 0x3c }, // NGAMVR4
|
||||
{ 0xd6, 0x22 }, // NGAMPR0
|
||||
{ 0xd7, 0x3d }, // NGAMPR1
|
||||
{ 0xd8, 0x0d }, // NGAMPK0
|
||||
{ 0xd9, 0x07 }, // NGAMPK1
|
||||
{ 0xda, 0x13 }, // NGAMPK2
|
||||
{ 0xdb, 0x13 }, // NGAMPK3
|
||||
{ 0xdc, 0x11 }, // NGAMPK4
|
||||
{ 0xdd, 0x15 }, // NGAMPK5
|
||||
{ 0xde, 0x19 }, // NGAMPK6
|
||||
{ 0xdf, 0x10 }, // NGAMPK7
|
||||
{ 0xe0, 0x17 }, // NGAMPK8
|
||||
{ 0xe1, 0x0a }, // NGAMPK9
|
||||
// EXTC Command set enable, select page 3
|
||||
{ 0xff, 0x30 }, { 0xff, 0x52 }, { 0xff, 0x03 },
|
||||
// Set various timing settings
|
||||
{ 0x00, 0x2a }, // GIP_VST_1
|
||||
{ 0x01, 0x2a }, // GIP_VST_2
|
||||
{ 0x02, 0x2a }, // GIP_VST_3
|
||||
{ 0x03, 0x2a }, // GIP_VST_4
|
||||
{ 0x04, 0x61 }, // GIP_VST_5
|
||||
{ 0x05, 0x80 }, // GIP_VST_6
|
||||
{ 0x06, 0xc7 }, // GIP_VST_7
|
||||
{ 0x07, 0x01 }, // GIP_VST_8
|
||||
{ 0x08, 0x03 }, // GIP_VST_9
|
||||
{ 0x09, 0x04 }, // GIP_VST_10
|
||||
{ 0x70, 0x22 }, // GIP_ECLK1
|
||||
{ 0x71, 0x80 }, // GIP_ECLK2
|
||||
{ 0x30, 0x2a }, // GIP_CLK_1
|
||||
{ 0x31, 0x2a }, // GIP_CLK_2
|
||||
{ 0x32, 0x2a }, // GIP_CLK_3
|
||||
{ 0x33, 0x2a }, // GIP_CLK_4
|
||||
{ 0x34, 0x61 }, // GIP_CLK_5
|
||||
{ 0x35, 0xc5 }, // GIP_CLK_6
|
||||
{ 0x36, 0x80 }, // GIP_CLK_7
|
||||
{ 0x37, 0x23 }, // GIP_CLK_8
|
||||
{ 0x40, 0x03 }, // GIP_CLKA_1
|
||||
{ 0x41, 0x04 }, // GIP_CLKA_2
|
||||
{ 0x42, 0x05 }, // GIP_CLKA_3
|
||||
{ 0x43, 0x06 }, // GIP_CLKA_4
|
||||
{ 0x44, 0x11 }, // GIP_CLKA_5
|
||||
{ 0x45, 0xe8 }, // GIP_CLKA_6
|
||||
{ 0x46, 0xe9 }, // GIP_CLKA_7
|
||||
{ 0x47, 0x11 }, // GIP_CLKA_8
|
||||
{ 0x48, 0xea }, // GIP_CLKA_9
|
||||
{ 0x49, 0xeb }, // GIP_CLKA_10
|
||||
{ 0x50, 0x07 }, // GIP_CLKB_1
|
||||
{ 0x51, 0x08 }, // GIP_CLKB_2
|
||||
{ 0x52, 0x09 }, // GIP_CLKB_3
|
||||
{ 0x53, 0x0a }, // GIP_CLKB_4
|
||||
{ 0x54, 0x11 }, // GIP_CLKB_5
|
||||
{ 0x55, 0xec }, // GIP_CLKB_6
|
||||
{ 0x56, 0xed }, // GIP_CLKB_7
|
||||
{ 0x57, 0x11 }, // GIP_CLKB_8
|
||||
{ 0x58, 0xef }, // GIP_CLKB_9
|
||||
{ 0x59, 0xf0 }, // GIP_CLKB_10
|
||||
// Map internal GOA signals to GOA output pad
|
||||
{ 0xb1, 0x01 }, // PANELD2U2
|
||||
{ 0xb4, 0x15 }, // PANELD2U5
|
||||
{ 0xb5, 0x16 }, // PANELD2U6
|
||||
{ 0xb6, 0x09 }, // PANELD2U7
|
||||
{ 0xb7, 0x0f }, // PANELD2U8
|
||||
{ 0xb8, 0x0d }, // PANELD2U9
|
||||
{ 0xb9, 0x0b }, // PANELD2U10
|
||||
{ 0xba, 0x00 }, // PANELD2U11
|
||||
{ 0xc7, 0x02 }, // PANELD2U24
|
||||
{ 0xca, 0x17 }, // PANELD2U27
|
||||
{ 0xcb, 0x18 }, // PANELD2U28
|
||||
{ 0xcc, 0x0a }, // PANELD2U29
|
||||
{ 0xcd, 0x10 }, // PANELD2U30
|
||||
{ 0xce, 0x0e }, // PANELD2U31
|
||||
{ 0xcf, 0x0c }, // PANELD2U32
|
||||
{ 0xd0, 0x00 }, // PANELD2U33
|
||||
// Map internal GOA signals to GOA output pad
|
||||
{ 0x81, 0x00 }, // PANELU2D2
|
||||
{ 0x84, 0x15 }, // PANELU2D5
|
||||
{ 0x85, 0x16 }, // PANELU2D6
|
||||
{ 0x86, 0x10 }, // PANELU2D7
|
||||
{ 0x87, 0x0a }, // PANELU2D8
|
||||
{ 0x88, 0x0c }, // PANELU2D9
|
||||
{ 0x89, 0x0e }, // PANELU2D10
|
||||
{ 0x8a, 0x02 }, // PANELU2D11
|
||||
{ 0x97, 0x00 }, // PANELU2D24
|
||||
{ 0x9a, 0x17 }, // PANELU2D27
|
||||
{ 0x9b, 0x18 }, // PANELU2D28
|
||||
{ 0x9c, 0x0f }, // PANELU2D29
|
||||
{ 0x9d, 0x09 }, // PANELU2D30
|
||||
{ 0x9e, 0x0b }, // PANELU2D31
|
||||
{ 0x9f, 0x0d }, // PANELU2D32
|
||||
{ 0xa0, 0x01 }, // PANELU2D33
|
||||
// EXTC Command set enable, select page 2
|
||||
{ 0xff, 0x30 }, { 0xff, 0x52 }, { 0xff, 0x02 },
|
||||
// Unknown registers
|
||||
{ 0x01, 0x01 },
|
||||
{ 0x02, 0xda },
|
||||
{ 0x03, 0xba },
|
||||
{ 0x04, 0xa8 },
|
||||
{ 0x05, 0x9a },
|
||||
{ 0x06, 0x70 },
|
||||
{ 0x07, 0xff },
|
||||
{ 0x08, 0x91 },
|
||||
{ 0x09, 0x90 },
|
||||
{ 0x0a, 0xff },
|
||||
{ 0x0b, 0x8f },
|
||||
{ 0x0c, 0x60 },
|
||||
{ 0x0d, 0x58 },
|
||||
{ 0x0e, 0x48 },
|
||||
{ 0x0f, 0x38 },
|
||||
{ 0x10, 0x2b },
|
||||
// EXTC Command set enable, select page 0
|
||||
{ 0xff, 0x30 }, { 0xff, 0x52 }, { 0xff, 0x00 },
|
||||
// Display Access Control
|
||||
{ 0x36, 0x0a }, // bgr = 1, ss = 1, gs = 0
|
||||
};
|
||||
|
||||
static inline struct nv3052c *to_nv3052c(struct drm_panel *panel)
|
||||
@ -241,6 +441,8 @@ static inline struct nv3052c *to_nv3052c(struct drm_panel *panel)
|
||||
static int nv3052c_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct nv3052c *priv = to_nv3052c(panel);
|
||||
const struct nv3052c_reg *panel_regs = priv->panel_info->panel_regs;
|
||||
unsigned int panel_regs_len = priv->panel_info->panel_regs_len;
|
||||
struct mipi_dbi *dbi = &priv->dbi;
|
||||
unsigned int i;
|
||||
int err;
|
||||
@ -257,9 +459,9 @@ static int nv3052c_prepare(struct drm_panel *panel)
|
||||
gpiod_set_value_cansleep(priv->reset_gpio, 0);
|
||||
usleep_range(5000, 20000);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(nv3052c_panel_regs); i++) {
|
||||
err = mipi_dbi_command(dbi, nv3052c_panel_regs[i].cmd,
|
||||
nv3052c_panel_regs[i].val);
|
||||
for (i = 0; i < panel_regs_len; i++) {
|
||||
err = mipi_dbi_command(dbi, panel_regs[i].cmd,
|
||||
panel_regs[i].val);
|
||||
|
||||
if (err) {
|
||||
dev_err(priv->dev, "Unable to set register: %d\n", err);
|
||||
@ -453,6 +655,21 @@ static const struct drm_display_mode ltk035c5444t_modes[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct drm_display_mode fs035vg158_modes[] = {
|
||||
{ /* 60 Hz */
|
||||
.clock = 21000,
|
||||
.hdisplay = 640,
|
||||
.hsync_start = 640 + 34,
|
||||
.hsync_end = 640 + 34 + 4,
|
||||
.htotal = 640 + 34 + 4 + 20,
|
||||
.vdisplay = 480,
|
||||
.vsync_start = 480 + 12,
|
||||
.vsync_end = 480 + 12 + 4,
|
||||
.vtotal = 480 + 12 + 4 + 6,
|
||||
.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct nv3052c_panel_info ltk035c5444t_panel_info = {
|
||||
.display_modes = ltk035c5444t_modes,
|
||||
.num_modes = ARRAY_SIZE(ltk035c5444t_modes),
|
||||
@ -460,10 +677,31 @@ static const struct nv3052c_panel_info ltk035c5444t_panel_info = {
|
||||
.height_mm = 64,
|
||||
.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
|
||||
.bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE,
|
||||
.panel_regs = ltk035c5444t_panel_regs,
|
||||
.panel_regs_len = ARRAY_SIZE(ltk035c5444t_panel_regs),
|
||||
};
|
||||
|
||||
static const struct nv3052c_panel_info fs035vg158_panel_info = {
|
||||
.display_modes = fs035vg158_modes,
|
||||
.num_modes = ARRAY_SIZE(fs035vg158_modes),
|
||||
.width_mm = 70,
|
||||
.height_mm = 53,
|
||||
.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
|
||||
.bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE,
|
||||
.panel_regs = fs035vg158_panel_regs,
|
||||
.panel_regs_len = ARRAY_SIZE(fs035vg158_panel_regs),
|
||||
};
|
||||
|
||||
static const struct spi_device_id nv3052c_ids[] = {
|
||||
{ "ltk035c5444t", },
|
||||
{ "fs035vg158", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, nv3052c_ids);
|
||||
|
||||
static const struct of_device_id nv3052c_of_match[] = {
|
||||
{ .compatible = "leadtek,ltk035c5444t", .data = <k035c5444t_panel_info },
|
||||
{ .compatible = "fascontek,fs035vg158", .data = &fs035vg158_panel_info },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, nv3052c_of_match);
|
||||
@ -473,6 +711,7 @@ static struct spi_driver nv3052c_driver = {
|
||||
.name = "nv3052c",
|
||||
.of_match_table = nv3052c_of_match,
|
||||
},
|
||||
.id_table = nv3052c_ids,
|
||||
.probe = nv3052c_probe,
|
||||
.remove = nv3052c_remove,
|
||||
};
|
||||
|
@ -1134,6 +1134,37 @@ static const struct panel_desc auo_g133han01 = {
|
||||
.connector_type = DRM_MODE_CONNECTOR_LVDS,
|
||||
};
|
||||
|
||||
static const struct display_timing auo_g156han04_timings = {
|
||||
.pixelclock = { 137000000, 141000000, 146000000 },
|
||||
.hactive = { 1920, 1920, 1920 },
|
||||
.hfront_porch = { 60, 60, 60 },
|
||||
.hback_porch = { 90, 92, 111 },
|
||||
.hsync_len = { 32, 32, 32 },
|
||||
.vactive = { 1080, 1080, 1080 },
|
||||
.vfront_porch = { 12, 12, 12 },
|
||||
.vback_porch = { 24, 36, 56 },
|
||||
.vsync_len = { 8, 8, 8 },
|
||||
};
|
||||
|
||||
static const struct panel_desc auo_g156han04 = {
|
||||
.timings = &auo_g156han04_timings,
|
||||
.num_timings = 1,
|
||||
.bpc = 8,
|
||||
.size = {
|
||||
.width = 344,
|
||||
.height = 194,
|
||||
},
|
||||
.delay = {
|
||||
.prepare = 50, /* T2 */
|
||||
.enable = 200, /* T3 */
|
||||
.disable = 110, /* T10 */
|
||||
.unprepare = 1000, /* T13 */
|
||||
},
|
||||
.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
|
||||
.bus_flags = DRM_BUS_FLAG_DE_HIGH,
|
||||
.connector_type = DRM_MODE_CONNECTOR_LVDS,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode auo_g156xtn01_mode = {
|
||||
.clock = 76000,
|
||||
.hdisplay = 1366,
|
||||
@ -4288,6 +4319,9 @@ static const struct of_device_id platform_of_match[] = {
|
||||
}, {
|
||||
.compatible = "auo,g133han01",
|
||||
.data = &auo_g133han01,
|
||||
}, {
|
||||
.compatible = "auo,g156han04",
|
||||
.data = &auo_g156han04,
|
||||
}, {
|
||||
.compatible = "auo,g156xtn01",
|
||||
.data = &auo_g156xtn01,
|
||||
|
@ -288,7 +288,7 @@ static void st7701_init_sequence(struct st7701 *st7701)
|
||||
FIELD_PREP(DSI_CMD2_BK1_PWRCTRL2_AVDD_MASK,
|
||||
DIV_ROUND_CLOSEST(desc->avdd_mv - 6200, 200)) |
|
||||
FIELD_PREP(DSI_CMD2_BK1_PWRCTRL2_AVCL_MASK,
|
||||
DIV_ROUND_CLOSEST(-4400 + desc->avcl_mv, 200)));
|
||||
DIV_ROUND_CLOSEST(-4400 - desc->avcl_mv, 200)));
|
||||
|
||||
/* T2D = 0.2us * T2D[3:0] */
|
||||
ST7701_DSI(st7701, DSI_CMD2_BK1_SPD1,
|
||||
@ -423,6 +423,42 @@ static void kd50t048a_gip_sequence(struct st7701 *st7701)
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x10, 0x45, 0x67, 0x98, 0xBA);
|
||||
}
|
||||
|
||||
static void rg_arc_gip_sequence(struct st7701 *st7701)
|
||||
{
|
||||
st7701_switch_cmd_bkx(st7701, true, 3);
|
||||
ST7701_DSI(st7701, 0xEF, 0x08);
|
||||
st7701_switch_cmd_bkx(st7701, true, 0);
|
||||
ST7701_DSI(st7701, 0xC7, 0x04);
|
||||
ST7701_DSI(st7701, 0xCC, 0x38);
|
||||
st7701_switch_cmd_bkx(st7701, true, 1);
|
||||
ST7701_DSI(st7701, 0xB9, 0x10);
|
||||
ST7701_DSI(st7701, 0xBC, 0x03);
|
||||
ST7701_DSI(st7701, 0xC0, 0x89);
|
||||
ST7701_DSI(st7701, 0xE0, 0x00, 0x00, 0x02);
|
||||
ST7701_DSI(st7701, 0xE1, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
|
||||
0x00, 0x00, 0x20, 0x20);
|
||||
ST7701_DSI(st7701, 0xE2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
ST7701_DSI(st7701, 0xE3, 0x00, 0x00, 0x33, 0x00);
|
||||
ST7701_DSI(st7701, 0xE4, 0x22, 0x00);
|
||||
ST7701_DSI(st7701, 0xE5, 0x04, 0x5C, 0xA0, 0xA0, 0x06, 0x5C, 0xA0,
|
||||
0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
ST7701_DSI(st7701, 0xE6, 0x00, 0x00, 0x33, 0x00);
|
||||
ST7701_DSI(st7701, 0xE7, 0x22, 0x00);
|
||||
ST7701_DSI(st7701, 0xE8, 0x05, 0x5C, 0xA0, 0xA0, 0x07, 0x5C, 0xA0,
|
||||
0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
ST7701_DSI(st7701, 0xEB, 0x02, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00);
|
||||
ST7701_DSI(st7701, 0xEC, 0x00, 0x00);
|
||||
ST7701_DSI(st7701, 0xED, 0xFA, 0x45, 0x0B, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB0, 0x54, 0xAF);
|
||||
ST7701_DSI(st7701, 0xEF, 0x08, 0x08, 0x08, 0x45, 0x3F, 0x54);
|
||||
st7701_switch_cmd_bkx(st7701, false, 0);
|
||||
ST7701_DSI(st7701, MIPI_DCS_SET_ADDRESS_MODE, 0x17);
|
||||
ST7701_DSI(st7701, MIPI_DCS_SET_PIXEL_FORMAT, 0x77);
|
||||
ST7701_DSI(st7701, MIPI_DCS_EXIT_SLEEP_MODE, 0x00);
|
||||
msleep(120);
|
||||
}
|
||||
|
||||
static int st7701_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct st7701 *st7701 = panel_to_st7701(panel);
|
||||
@ -839,6 +875,105 @@ static const struct st7701_panel_desc kd50t048a_desc = {
|
||||
.gip_sequence = kd50t048a_gip_sequence,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode rg_arc_mode = {
|
||||
.clock = 25600,
|
||||
|
||||
.hdisplay = 480,
|
||||
.hsync_start = 480 + 60,
|
||||
.hsync_end = 480 + 60 + 42,
|
||||
.htotal = 480 + 60 + 42 + 60,
|
||||
|
||||
.vdisplay = 640,
|
||||
.vsync_start = 640 + 10,
|
||||
.vsync_end = 640 + 10 + 4,
|
||||
.vtotal = 640 + 10 + 4 + 16,
|
||||
|
||||
.width_mm = 63,
|
||||
.height_mm = 84,
|
||||
|
||||
.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
|
||||
};
|
||||
|
||||
static const struct st7701_panel_desc rg_arc_desc = {
|
||||
.mode = &rg_arc_mode,
|
||||
.lanes = 2,
|
||||
.format = MIPI_DSI_FMT_RGB888,
|
||||
.panel_sleep_delay = 80,
|
||||
|
||||
.pv_gamma = {
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0x01) |
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC0_MASK, 0),
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC4_MASK, 0x16),
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC8_MASK, 0x1d),
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC16_MASK, 0x0e),
|
||||
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC24_MASK, 0x12),
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC52_MASK, 0x06),
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC80_MASK, 0x0c),
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC108_MASK, 0x0a),
|
||||
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC147_MASK, 0x09),
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC175_MASK, 0x25),
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC203_MASK, 0x00),
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC231_MASK, 0x03),
|
||||
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC239_MASK, 0x00),
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC247_MASK, 0x3f),
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC251_MASK, 0x3f),
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1c)
|
||||
},
|
||||
.nv_gamma = {
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0x01) |
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC0_MASK, 0),
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC4_MASK, 0x16),
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC8_MASK, 0x1e),
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC16_MASK, 0x0e),
|
||||
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC24_MASK, 0x11),
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC52_MASK, 0x06),
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC80_MASK, 0x0c),
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC108_MASK, 0x08),
|
||||
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC147_MASK, 0x09),
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC175_MASK, 0x26),
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC203_MASK, 0x00),
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC231_MASK, 0x15),
|
||||
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC239_MASK, 0x00),
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC247_MASK, 0x3f),
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC251_MASK, 0x3f),
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
|
||||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1c)
|
||||
},
|
||||
.nlinv = 0,
|
||||
.vop_uv = 4500000,
|
||||
.vcom_uv = 762500,
|
||||
.vgh_mv = 15000,
|
||||
.vgl_mv = -9510,
|
||||
.avdd_mv = 6600,
|
||||
.avcl_mv = -4400,
|
||||
.gamma_op_bias = OP_BIAS_MIDDLE,
|
||||
.input_op_bias = OP_BIAS_MIN,
|
||||
.output_op_bias = OP_BIAS_MIN,
|
||||
.t2d_ns = 1600,
|
||||
.t3d_ns = 10400,
|
||||
.eot_en = true,
|
||||
.gip_sequence = rg_arc_gip_sequence,
|
||||
};
|
||||
|
||||
static int st7701_dsi_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
const struct st7701_panel_desc *desc;
|
||||
@ -917,6 +1052,7 @@ static void st7701_dsi_remove(struct mipi_dsi_device *dsi)
|
||||
}
|
||||
|
||||
static const struct of_device_id st7701_of_match[] = {
|
||||
{ .compatible = "anbernic,rg-arc-panel", .data = &rg_arc_desc },
|
||||
{ .compatible = "densitron,dmt028vghmcmi-1a", .data = &dmt028vghmcmi_1a_desc },
|
||||
{ .compatible = "elida,kd50t048a", .data = &kd50t048a_desc },
|
||||
{ .compatible = "techstar,ts8550b", .data = &ts8550b_desc },
|
||||
|
362
drivers/gpu/drm/panel/panel-synaptics-r63353.c
Normal file
362
drivers/gpu/drm/panel/panel-synaptics-r63353.c
Normal file
@ -0,0 +1,362 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Synaptics R63353 Controller driver
|
||||
*
|
||||
* Copyright (C) 2020 BSH Hausgerate GmbH
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/media-bus-format.h>
|
||||
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
#define R63353_INSTR(...) { \
|
||||
.len = sizeof((u8[]) {__VA_ARGS__}), \
|
||||
.data = (u8[]){__VA_ARGS__} \
|
||||
}
|
||||
|
||||
struct r63353_instr {
|
||||
size_t len;
|
||||
const u8 *data;
|
||||
};
|
||||
|
||||
static const struct r63353_instr sharp_ls068b3sx02_init[] = {
|
||||
R63353_INSTR(0x51, 0xff),
|
||||
R63353_INSTR(0x53, 0x0c),
|
||||
R63353_INSTR(0x55, 0x00),
|
||||
R63353_INSTR(0x84, 0x00),
|
||||
R63353_INSTR(0x29),
|
||||
};
|
||||
|
||||
struct r63353_desc {
|
||||
const char *name;
|
||||
const struct r63353_instr *init;
|
||||
const size_t init_length;
|
||||
const struct drm_display_mode *mode;
|
||||
u32 width_mm;
|
||||
u32 height_mm;
|
||||
};
|
||||
|
||||
struct r63353_panel {
|
||||
struct drm_panel base;
|
||||
struct mipi_dsi_device *dsi;
|
||||
|
||||
struct gpio_desc *reset_gpio;
|
||||
struct regulator *dvdd;
|
||||
struct regulator *avdd;
|
||||
|
||||
struct r63353_desc *pdata;
|
||||
};
|
||||
|
||||
static inline struct r63353_panel *to_r63353_panel(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct r63353_panel, base);
|
||||
}
|
||||
|
||||
static int r63353_panel_power_on(struct r63353_panel *rpanel)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = rpanel->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
ret = regulator_enable(rpanel->avdd);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to enable avdd regulator (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
usleep_range(15000, 25000);
|
||||
|
||||
ret = regulator_enable(rpanel->dvdd);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to enable dvdd regulator (%d)\n", ret);
|
||||
regulator_disable(rpanel->avdd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
usleep_range(300000, 350000);
|
||||
gpiod_set_value(rpanel->reset_gpio, 1);
|
||||
usleep_range(15000, 25000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int r63353_panel_power_off(struct r63353_panel *rpanel)
|
||||
{
|
||||
gpiod_set_value(rpanel->reset_gpio, 0);
|
||||
regulator_disable(rpanel->dvdd);
|
||||
regulator_disable(rpanel->avdd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int r63353_panel_activate(struct r63353_panel *rpanel)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = rpanel->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int i, ret;
|
||||
|
||||
ret = mipi_dsi_dcs_soft_reset(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to do Software Reset (%d)\n", ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
usleep_range(15000, 17000);
|
||||
|
||||
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enter sleep mode (%d)\n", ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (i = 0; i < rpanel->pdata->init_length; i++) {
|
||||
const struct r63353_instr *instr = &rpanel->pdata->init[i];
|
||||
|
||||
ret = mipi_dsi_dcs_write_buffer(dsi, instr->data, instr->len);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
msleep(120);
|
||||
|
||||
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to exit sleep mode (%d)\n", ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
usleep_range(5000, 10000);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_on(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display ON (%d)\n", ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
gpiod_set_value(rpanel->reset_gpio, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int r63353_panel_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct r63353_panel *rpanel = to_r63353_panel(panel);
|
||||
struct mipi_dsi_device *dsi = rpanel->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
dev_dbg(dev, "Preparing\n");
|
||||
|
||||
ret = r63353_panel_power_on(rpanel);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = r63353_panel_activate(rpanel);
|
||||
if (ret) {
|
||||
r63353_panel_power_off(rpanel);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "Prepared\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int r63353_panel_deactivate(struct r63353_panel *rpanel)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = rpanel->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_off(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display OFF (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
usleep_range(5000, 10000);
|
||||
|
||||
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enter sleep mode (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int r63353_panel_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct r63353_panel *rpanel = to_r63353_panel(panel);
|
||||
|
||||
r63353_panel_deactivate(rpanel);
|
||||
r63353_panel_power_off(rpanel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_display_mode sharp_ls068b3sx02_timing = {
|
||||
.clock = 70000,
|
||||
.hdisplay = 640,
|
||||
.hsync_start = 640 + 35,
|
||||
.hsync_end = 640 + 35 + 2,
|
||||
.htotal = 640 + 35 + 2 + 150,
|
||||
.vdisplay = 1280,
|
||||
.vsync_start = 1280 + 2,
|
||||
.vsync_end = 1280 + 2 + 4,
|
||||
.vtotal = 1280 + 2 + 4 + 0,
|
||||
};
|
||||
|
||||
static int r63353_panel_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct r63353_panel *rpanel = to_r63353_panel(panel);
|
||||
struct drm_display_mode *mode;
|
||||
static const u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev, rpanel->pdata->mode);
|
||||
if (!mode)
|
||||
return -ENOMEM;
|
||||
|
||||
drm_mode_set_name(mode);
|
||||
drm_mode_probed_add(connector, mode);
|
||||
|
||||
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
||||
connector->display_info.width_mm = rpanel->pdata->width_mm;
|
||||
connector->display_info.height_mm = rpanel->pdata->height_mm;
|
||||
|
||||
drm_display_info_set_bus_formats(&connector->display_info,
|
||||
&bus_format, 1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs r63353_panel_funcs = {
|
||||
.prepare = r63353_panel_prepare,
|
||||
.unprepare = r63353_panel_unprepare,
|
||||
.get_modes = r63353_panel_get_modes,
|
||||
};
|
||||
|
||||
static int r63353_panel_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
int ret = 0;
|
||||
struct device *dev = &dsi->dev;
|
||||
struct r63353_panel *panel;
|
||||
|
||||
panel = devm_kzalloc(&dsi->dev, sizeof(*panel), GFP_KERNEL);
|
||||
if (!panel)
|
||||
return -ENOMEM;
|
||||
|
||||
mipi_dsi_set_drvdata(dsi, panel);
|
||||
panel->dsi = dsi;
|
||||
panel->pdata = (struct r63353_desc *)of_device_get_match_data(dev);
|
||||
|
||||
dev_info(dev, "Panel %s\n", panel->pdata->name);
|
||||
|
||||
dsi->lanes = 2;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO |
|
||||
MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM |
|
||||
MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_NO_EOT_PACKET;
|
||||
|
||||
panel->dvdd = devm_regulator_get(dev, "dvdd");
|
||||
if (IS_ERR(panel->dvdd))
|
||||
return PTR_ERR(panel->dvdd);
|
||||
panel->avdd = devm_regulator_get(dev, "avdd");
|
||||
if (IS_ERR(panel->avdd))
|
||||
return PTR_ERR(panel->avdd);
|
||||
|
||||
panel->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(panel->reset_gpio)) {
|
||||
dev_err(dev, "failed to get RESET GPIO\n");
|
||||
return PTR_ERR(panel->reset_gpio);
|
||||
}
|
||||
|
||||
drm_panel_init(&panel->base, dev, &r63353_panel_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
|
||||
panel->base.prepare_prev_first = true;
|
||||
ret = drm_panel_of_backlight(&panel->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drm_panel_add(&panel->base);
|
||||
|
||||
ret = mipi_dsi_attach(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "mipi_dsi_attach failed: %d\n", ret);
|
||||
drm_panel_remove(&panel->base);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void r63353_panel_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct r63353_panel *rpanel = mipi_dsi_get_drvdata(dsi);
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_detach(dsi);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "Failed to detach from host (%d)\n", ret);
|
||||
|
||||
drm_panel_remove(&rpanel->base);
|
||||
}
|
||||
|
||||
static void r63353_panel_shutdown(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct r63353_panel *rpanel = mipi_dsi_get_drvdata(dsi);
|
||||
|
||||
r63353_panel_unprepare(&rpanel->base);
|
||||
}
|
||||
|
||||
static const struct r63353_desc sharp_ls068b3sx02_data = {
|
||||
.name = "Sharp LS068B3SX02",
|
||||
.mode = &sharp_ls068b3sx02_timing,
|
||||
.init = sharp_ls068b3sx02_init,
|
||||
.init_length = ARRAY_SIZE(sharp_ls068b3sx02_init),
|
||||
.width_mm = 68,
|
||||
.height_mm = 159,
|
||||
};
|
||||
|
||||
static const struct of_device_id r63353_of_match[] = {
|
||||
{ .compatible = "sharp,ls068b3sx02", .data = &sharp_ls068b3sx02_data },
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, r63353_of_match);
|
||||
|
||||
static struct mipi_dsi_driver r63353_panel_driver = {
|
||||
.driver = {
|
||||
.name = "r63353-dsi",
|
||||
.of_match_table = r63353_of_match,
|
||||
},
|
||||
.probe = r63353_panel_probe,
|
||||
.remove = r63353_panel_remove,
|
||||
.shutdown = r63353_panel_shutdown,
|
||||
};
|
||||
|
||||
module_mipi_dsi_driver(r63353_panel_driver);
|
||||
|
||||
MODULE_AUTHOR("Matthias Proske <Matthias.Proske@bshg.com>");
|
||||
MODULE_AUTHOR("Michael Trimarchi <michael@amarulasolutions.com>");
|
||||
MODULE_DESCRIPTION("Synaptics R63353 Controller Driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -30,7 +30,6 @@
|
||||
#include <drm/drm_simple_kms_helper.h>
|
||||
|
||||
#include "rockchip_drm_drv.h"
|
||||
#include "rockchip_drm_vop.h"
|
||||
|
||||
#define RK3288_GRF_SOC_CON6 0x25c
|
||||
#define RK3288_EDP_LCDC_SEL BIT(5)
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
#include "cdn-dp-core.h"
|
||||
#include "cdn-dp-reg.h"
|
||||
#include "rockchip_drm_vop.h"
|
||||
|
||||
static inline struct cdn_dp_device *connector_to_dp(struct drm_connector *connector)
|
||||
{
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include <drm/drm_simple_kms_helper.h>
|
||||
|
||||
#include "rockchip_drm_drv.h"
|
||||
#include "rockchip_drm_vop.h"
|
||||
|
||||
#define DSI_PHY_RSTZ 0xa0
|
||||
#define PHY_DISFORCEPLL 0
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include <drm/drm_simple_kms_helper.h>
|
||||
|
||||
#include "rockchip_drm_drv.h"
|
||||
#include "rockchip_drm_vop.h"
|
||||
|
||||
#define RK3228_GRF_SOC_CON2 0x0408
|
||||
#define RK3228_HDMI_SDAIN_MSK BIT(14)
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include <drm/drm_simple_kms_helper.h>
|
||||
|
||||
#include "rockchip_drm_drv.h"
|
||||
#include "rockchip_drm_vop.h"
|
||||
|
||||
#include "inno_hdmi.h"
|
||||
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include "rk3066_hdmi.h"
|
||||
|
||||
#include "rockchip_drm_drv.h"
|
||||
#include "rockchip_drm_vop.h"
|
||||
|
||||
#define DEFAULT_PLLA_RATE 30000000
|
||||
|
||||
|
@ -20,6 +20,23 @@
|
||||
#define ROCKCHIP_MAX_CONNECTOR 2
|
||||
#define ROCKCHIP_MAX_CRTC 4
|
||||
|
||||
/*
|
||||
* display output interface supported by rockchip lcdc
|
||||
*/
|
||||
#define ROCKCHIP_OUT_MODE_P888 0
|
||||
#define ROCKCHIP_OUT_MODE_BT1120 0
|
||||
#define ROCKCHIP_OUT_MODE_P666 1
|
||||
#define ROCKCHIP_OUT_MODE_P565 2
|
||||
#define ROCKCHIP_OUT_MODE_BT656 5
|
||||
#define ROCKCHIP_OUT_MODE_S888 8
|
||||
#define ROCKCHIP_OUT_MODE_S888_DUMMY 12
|
||||
#define ROCKCHIP_OUT_MODE_YUV420 14
|
||||
/* for use special outface */
|
||||
#define ROCKCHIP_OUT_MODE_AAAA 15
|
||||
|
||||
/* output flags */
|
||||
#define ROCKCHIP_OUTPUT_DSI_DUAL BIT(0)
|
||||
|
||||
struct drm_device;
|
||||
struct drm_connector;
|
||||
struct iommu_domain;
|
||||
@ -31,6 +48,7 @@ struct rockchip_crtc_state {
|
||||
int output_bpc;
|
||||
int output_flags;
|
||||
bool enable_afbc;
|
||||
bool yuv_overlay;
|
||||
u32 bus_format;
|
||||
u32 bus_flags;
|
||||
int color_space;
|
||||
|
@ -277,18 +277,6 @@ struct vop_data {
|
||||
/* dst alpha ctrl define */
|
||||
#define DST_FACTOR_M0(x) (((x) & 0x7) << 6)
|
||||
|
||||
/*
|
||||
* display output interface supported by rockchip lcdc
|
||||
*/
|
||||
#define ROCKCHIP_OUT_MODE_P888 0
|
||||
#define ROCKCHIP_OUT_MODE_P666 1
|
||||
#define ROCKCHIP_OUT_MODE_P565 2
|
||||
/* for use special outface */
|
||||
#define ROCKCHIP_OUT_MODE_AAAA 15
|
||||
|
||||
/* output flags */
|
||||
#define ROCKCHIP_OUTPUT_DSI_DUAL BIT(0)
|
||||
|
||||
enum alpha_mode {
|
||||
ALPHA_STRAIGHT,
|
||||
ALPHA_INVERSE,
|
||||
|
@ -190,7 +190,10 @@ struct vop2 {
|
||||
void __iomem *regs;
|
||||
struct regmap *map;
|
||||
|
||||
struct regmap *grf;
|
||||
struct regmap *sys_grf;
|
||||
struct regmap *vop_grf;
|
||||
struct regmap *vo1_grf;
|
||||
struct regmap *sys_pmu;
|
||||
|
||||
/* physical map length of vop2 register */
|
||||
u32 len;
|
||||
@ -209,6 +212,7 @@ struct vop2 {
|
||||
unsigned int enable_count;
|
||||
struct clk *hclk;
|
||||
struct clk *aclk;
|
||||
struct clk *pclk;
|
||||
|
||||
/* optional internal rgb encoder */
|
||||
struct rockchip_rgb *rgb;
|
||||
@ -217,6 +221,25 @@ struct vop2 {
|
||||
struct vop2_win win[];
|
||||
};
|
||||
|
||||
#define vop2_output_if_is_hdmi(x) ((x) == ROCKCHIP_VOP2_EP_HDMI0 || \
|
||||
(x) == ROCKCHIP_VOP2_EP_HDMI1)
|
||||
|
||||
#define vop2_output_if_is_dp(x) ((x) == ROCKCHIP_VOP2_EP_DP0 || \
|
||||
(x) == ROCKCHIP_VOP2_EP_DP1)
|
||||
|
||||
#define vop2_output_if_is_edp(x) ((x) == ROCKCHIP_VOP2_EP_EDP0 || \
|
||||
(x) == ROCKCHIP_VOP2_EP_EDP1)
|
||||
|
||||
#define vop2_output_if_is_mipi(x) ((x) == ROCKCHIP_VOP2_EP_MIPI0 || \
|
||||
(x) == ROCKCHIP_VOP2_EP_MIPI1)
|
||||
|
||||
#define vop2_output_if_is_lvds(x) ((x) == ROCKCHIP_VOP2_EP_LVDS0 || \
|
||||
(x) == ROCKCHIP_VOP2_EP_LVDS1)
|
||||
|
||||
#define vop2_output_if_is_dpi(x) ((x) == ROCKCHIP_VOP2_EP_RGB0)
|
||||
|
||||
static const struct regmap_config vop2_regmap_config;
|
||||
|
||||
static struct vop2_video_port *to_vop2_video_port(struct drm_crtc *crtc)
|
||||
{
|
||||
return container_of(crtc, struct vop2_video_port, crtc);
|
||||
@ -266,12 +289,23 @@ static bool vop2_cluster_window(const struct vop2_win *win)
|
||||
return win->data->feature & WIN_FEATURE_CLUSTER;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note:
|
||||
* The write mask function is documented but missing on rk3566/8, writes
|
||||
* to these bits have no effect. For newer soc(rk3588 and following) the
|
||||
* write mask is needed for register writes.
|
||||
*
|
||||
* GLB_CFG_DONE_EN has no write mask bit.
|
||||
*
|
||||
*/
|
||||
static void vop2_cfg_done(struct vop2_video_port *vp)
|
||||
{
|
||||
struct vop2 *vop2 = vp->vop2;
|
||||
u32 val = RK3568_REG_CFG_DONE__GLB_CFG_DONE_EN;
|
||||
|
||||
regmap_set_bits(vop2->map, RK3568_REG_CFG_DONE,
|
||||
BIT(vp->id) | RK3568_REG_CFG_DONE__GLB_CFG_DONE_EN);
|
||||
val |= BIT(vp->id) | (BIT(vp->id) << 16);
|
||||
|
||||
regmap_set_bits(vop2->map, RK3568_REG_CFG_DONE, val);
|
||||
}
|
||||
|
||||
static void vop2_win_disable(struct vop2_win *win)
|
||||
@ -462,6 +496,17 @@ static bool vop2_output_uv_swap(u32 bus_format, u32 output_mode)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool vop2_output_rg_swap(struct vop2 *vop2, u32 bus_format)
|
||||
{
|
||||
if (vop2->data->soc_id == 3588) {
|
||||
if (bus_format == MEDIA_BUS_FMT_YUV8_1X24 ||
|
||||
bus_format == MEDIA_BUS_FMT_YUV10_1X30)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool is_yuv_output(u32 bus_format)
|
||||
{
|
||||
switch (bus_format) {
|
||||
@ -519,6 +564,18 @@ static bool rockchip_vop2_mod_supported(struct drm_plane *plane, u32 format,
|
||||
return vop2_convert_afbc_format(format) >= 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 0: Full mode, 16 lines for one tail
|
||||
* 1: half block mode, 8 lines one tail
|
||||
*/
|
||||
static bool vop2_half_block_enable(struct drm_plane_state *pstate)
|
||||
{
|
||||
if (pstate->rotation & (DRM_MODE_ROTATE_270 | DRM_MODE_ROTATE_90))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
static u32 vop2_afbc_transform_offset(struct drm_plane_state *pstate,
|
||||
bool afbc_half_block_en)
|
||||
{
|
||||
@ -854,13 +911,32 @@ static int vop2_core_clks_prepare_enable(struct vop2 *vop2)
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(vop2->pclk);
|
||||
if (ret < 0) {
|
||||
drm_err(vop2->drm, "failed to enable pclk - %d\n", ret);
|
||||
goto err1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err1:
|
||||
clk_disable_unprepare(vop2->aclk);
|
||||
err:
|
||||
clk_disable_unprepare(vop2->hclk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rk3588_vop2_power_domain_enable_all(struct vop2 *vop2)
|
||||
{
|
||||
u32 pd;
|
||||
|
||||
pd = vop2_readl(vop2, RK3588_SYS_PD_CTRL);
|
||||
pd &= ~(VOP2_PD_CLUSTER0 | VOP2_PD_CLUSTER1 | VOP2_PD_CLUSTER2 |
|
||||
VOP2_PD_CLUSTER3 | VOP2_PD_ESMART);
|
||||
|
||||
vop2_writel(vop2, RK3588_SYS_PD_CTRL, pd);
|
||||
}
|
||||
|
||||
static void vop2_enable(struct vop2 *vop2)
|
||||
{
|
||||
int ret;
|
||||
@ -883,11 +959,18 @@ static void vop2_enable(struct vop2 *vop2)
|
||||
return;
|
||||
}
|
||||
|
||||
regcache_sync(vop2->map);
|
||||
ret = regmap_reinit_cache(vop2->map, &vop2_regmap_config);
|
||||
if (ret) {
|
||||
drm_err(vop2->drm, "failed to reinit cache: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
if (vop2->data->soc_id == 3566)
|
||||
vop2_writel(vop2, RK3568_OTP_WIN_EN, 1);
|
||||
|
||||
if (vop2->data->soc_id == 3588)
|
||||
rk3588_vop2_power_domain_enable_all(vop2);
|
||||
|
||||
vop2_writel(vop2, RK3568_REG_CFG_DONE, RK3568_REG_CFG_DONE__GLB_CFG_DONE_EN);
|
||||
|
||||
/*
|
||||
@ -913,8 +996,7 @@ static void vop2_disable(struct vop2 *vop2)
|
||||
|
||||
pm_runtime_put_sync(vop2->dev);
|
||||
|
||||
regcache_mark_dirty(vop2->map);
|
||||
|
||||
clk_disable_unprepare(vop2->pclk);
|
||||
clk_disable_unprepare(vop2->aclk);
|
||||
clk_disable_unprepare(vop2->hclk);
|
||||
}
|
||||
@ -1140,6 +1222,7 @@ static void vop2_plane_atomic_update(struct drm_plane *plane,
|
||||
bool rotate_90 = pstate->rotation & DRM_MODE_ROTATE_90;
|
||||
struct rockchip_gem_object *rk_obj;
|
||||
unsigned long offset;
|
||||
bool half_block_en;
|
||||
bool afbc_en;
|
||||
dma_addr_t yrgb_mst;
|
||||
dma_addr_t uv_mst;
|
||||
@ -1232,6 +1315,7 @@ static void vop2_plane_atomic_update(struct drm_plane *plane,
|
||||
dsp_info = (dsp_h - 1) << 16 | ((dsp_w - 1) & 0xffff);
|
||||
|
||||
format = vop2_convert_format(fb->format->format);
|
||||
half_block_en = vop2_half_block_enable(pstate);
|
||||
|
||||
drm_dbg(vop2->drm, "vp%d update %s[%dx%d->%dx%d@%dx%d] fmt[%p4cc_%s] addr[%pad]\n",
|
||||
vp->id, win->data->name, actual_w, actual_h, dsp_w, dsp_h,
|
||||
@ -1239,6 +1323,9 @@ static void vop2_plane_atomic_update(struct drm_plane *plane,
|
||||
&fb->format->format,
|
||||
afbc_en ? "AFBC" : "", &yrgb_mst);
|
||||
|
||||
if (vop2_cluster_window(win))
|
||||
vop2_win_write(win, VOP2_WIN_AFBC_HALF_BLOCK_EN, half_block_en);
|
||||
|
||||
if (afbc_en) {
|
||||
u32 stride;
|
||||
|
||||
@ -1277,15 +1364,21 @@ static void vop2_plane_atomic_update(struct drm_plane *plane,
|
||||
vop2_win_write(win, VOP2_WIN_AFBC_ENABLE, 1);
|
||||
vop2_win_write(win, VOP2_WIN_AFBC_FORMAT, afbc_format);
|
||||
vop2_win_write(win, VOP2_WIN_AFBC_UV_SWAP, uv_swap);
|
||||
vop2_win_write(win, VOP2_WIN_AFBC_AUTO_GATING_EN, 0);
|
||||
/*
|
||||
* On rk3566/8, this bit is auto gating enable,
|
||||
* but this function is not work well so we need
|
||||
* to disable it for these two platform.
|
||||
* On rk3588, and the following new soc(rk3528/rk3576),
|
||||
* this bit is gating disable, we should write 1 to
|
||||
* disable gating when enable afbc.
|
||||
*/
|
||||
if (vop2->data->soc_id == 3566 || vop2->data->soc_id == 3568)
|
||||
vop2_win_write(win, VOP2_WIN_AFBC_AUTO_GATING_EN, 0);
|
||||
else
|
||||
vop2_win_write(win, VOP2_WIN_AFBC_AUTO_GATING_EN, 1);
|
||||
|
||||
vop2_win_write(win, VOP2_WIN_AFBC_BLOCK_SPLIT_EN, 0);
|
||||
if (pstate->rotation & (DRM_MODE_ROTATE_270 | DRM_MODE_ROTATE_90)) {
|
||||
vop2_win_write(win, VOP2_WIN_AFBC_HALF_BLOCK_EN, 0);
|
||||
transform_offset = vop2_afbc_transform_offset(pstate, false);
|
||||
} else {
|
||||
vop2_win_write(win, VOP2_WIN_AFBC_HALF_BLOCK_EN, 1);
|
||||
transform_offset = vop2_afbc_transform_offset(pstate, true);
|
||||
}
|
||||
transform_offset = vop2_afbc_transform_offset(pstate, half_block_en);
|
||||
vop2_win_write(win, VOP2_WIN_AFBC_HDR_PTR, yrgb_mst);
|
||||
vop2_win_write(win, VOP2_WIN_AFBC_PIC_SIZE, act_info);
|
||||
vop2_win_write(win, VOP2_WIN_AFBC_TRANSFORM_OFFSET, transform_offset);
|
||||
@ -1297,6 +1390,11 @@ static void vop2_plane_atomic_update(struct drm_plane *plane,
|
||||
vop2_win_write(win, VOP2_WIN_AFBC_ROTATE_270, rotate_270);
|
||||
vop2_win_write(win, VOP2_WIN_AFBC_ROTATE_90, rotate_90);
|
||||
} else {
|
||||
if (vop2_cluster_window(win)) {
|
||||
vop2_win_write(win, VOP2_WIN_AFBC_ENABLE, 0);
|
||||
vop2_win_write(win, VOP2_WIN_AFBC_TRANSFORM_OFFSET, 0);
|
||||
}
|
||||
|
||||
vop2_win_write(win, VOP2_WIN_YRGB_VIR, DIV_ROUND_UP(fb->pitches[0], 4));
|
||||
}
|
||||
|
||||
@ -1429,8 +1527,18 @@ static void vop2_post_config(struct drm_crtc *crtc)
|
||||
u32 top_margin = 100, bottom_margin = 100;
|
||||
u16 hsize = hdisplay * (left_margin + right_margin) / 200;
|
||||
u16 vsize = vdisplay * (top_margin + bottom_margin) / 200;
|
||||
u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
|
||||
u16 hact_end, vact_end;
|
||||
u32 val;
|
||||
u32 bg_dly;
|
||||
u32 pre_scan_dly;
|
||||
|
||||
bg_dly = vp->data->pre_scan_max_dly[3];
|
||||
vop2_writel(vp->vop2, RK3568_VP_BG_MIX_CTRL(vp->id),
|
||||
FIELD_PREP(RK3568_VP_BG_MIX_CTRL__BG_DLY, bg_dly));
|
||||
|
||||
pre_scan_dly = ((bg_dly + (hdisplay >> 1) - 1) << 16) | hsync_len;
|
||||
vop2_vp_write(vp, RK3568_VP_PRE_SCAN_HTIMING, pre_scan_dly);
|
||||
|
||||
vsize = rounddown(vsize, 2);
|
||||
hsize = rounddown(hsize, 2);
|
||||
@ -1466,10 +1574,10 @@ static void vop2_post_config(struct drm_crtc *crtc)
|
||||
vop2_vp_write(vp, RK3568_VP_DSP_BG, 0);
|
||||
}
|
||||
|
||||
static void rk3568_set_intf_mux(struct vop2_video_port *vp, int id,
|
||||
u32 polflags)
|
||||
static unsigned long rk3568_set_intf_mux(struct vop2_video_port *vp, int id, u32 polflags)
|
||||
{
|
||||
struct vop2 *vop2 = vp->vop2;
|
||||
struct drm_crtc *crtc = &vp->crtc;
|
||||
u32 die, dip;
|
||||
|
||||
die = vop2_readl(vop2, RK3568_DSP_IF_EN);
|
||||
@ -1483,9 +1591,9 @@ static void rk3568_set_intf_mux(struct vop2_video_port *vp, int id,
|
||||
dip &= ~RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL;
|
||||
dip |= FIELD_PREP(RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL, polflags);
|
||||
if (polflags & POLFLAG_DCLK_INV)
|
||||
regmap_write(vop2->grf, RK3568_GRF_VO_CON1, BIT(3 + 16) | BIT(3));
|
||||
regmap_write(vop2->sys_grf, RK3568_GRF_VO_CON1, BIT(3 + 16) | BIT(3));
|
||||
else
|
||||
regmap_write(vop2->grf, RK3568_GRF_VO_CON1, BIT(3 + 16));
|
||||
regmap_write(vop2->sys_grf, RK3568_GRF_VO_CON1, BIT(3 + 16));
|
||||
break;
|
||||
case ROCKCHIP_VOP2_EP_HDMI0:
|
||||
die &= ~RK3568_SYS_DSP_INFACE_EN_HDMI_MUX;
|
||||
@ -1531,13 +1639,281 @@ static void rk3568_set_intf_mux(struct vop2_video_port *vp, int id,
|
||||
break;
|
||||
default:
|
||||
drm_err(vop2->drm, "Invalid interface id %d on vp%d\n", id, vp->id);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dip |= RK3568_DSP_IF_POL__CFG_DONE_IMD;
|
||||
|
||||
vop2_writel(vop2, RK3568_DSP_IF_EN, die);
|
||||
vop2_writel(vop2, RK3568_DSP_IF_POL, dip);
|
||||
|
||||
return crtc->state->adjusted_mode.crtc_clock * 1000LL;
|
||||
}
|
||||
|
||||
/*
|
||||
* calc the dclk on rk3588
|
||||
* the available div of dclk is 1, 2, 4
|
||||
*/
|
||||
static unsigned long rk3588_calc_dclk(unsigned long child_clk, unsigned long max_dclk)
|
||||
{
|
||||
if (child_clk * 4 <= max_dclk)
|
||||
return child_clk * 4;
|
||||
else if (child_clk * 2 <= max_dclk)
|
||||
return child_clk * 2;
|
||||
else if (child_clk <= max_dclk)
|
||||
return child_clk;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 4 pixclk/cycle on rk3588
|
||||
* RGB/eDP/HDMI: if_pixclk >= dclk_core
|
||||
* DP: dp_pixclk = dclk_out <= dclk_core
|
||||
* DSI: mipi_pixclk <= dclk_out <= dclk_core
|
||||
*/
|
||||
static unsigned long rk3588_calc_cru_cfg(struct vop2_video_port *vp, int id,
|
||||
int *dclk_core_div, int *dclk_out_div,
|
||||
int *if_pixclk_div, int *if_dclk_div)
|
||||
{
|
||||
struct vop2 *vop2 = vp->vop2;
|
||||
struct drm_crtc *crtc = &vp->crtc;
|
||||
struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
|
||||
struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
|
||||
int output_mode = vcstate->output_mode;
|
||||
unsigned long v_pixclk = adjusted_mode->crtc_clock * 1000LL; /* video timing pixclk */
|
||||
unsigned long dclk_core_rate = v_pixclk >> 2;
|
||||
unsigned long dclk_rate = v_pixclk;
|
||||
unsigned long dclk_out_rate;
|
||||
unsigned long if_dclk_rate;
|
||||
unsigned long if_pixclk_rate;
|
||||
int K = 1;
|
||||
|
||||
if (vop2_output_if_is_hdmi(id)) {
|
||||
/*
|
||||
* K = 2: dclk_core = if_pixclk_rate > if_dclk_rate
|
||||
* K = 1: dclk_core = hdmie_edp_dclk > if_pixclk_rate
|
||||
*/
|
||||
if (output_mode == ROCKCHIP_OUT_MODE_YUV420) {
|
||||
dclk_rate = dclk_rate >> 1;
|
||||
K = 2;
|
||||
}
|
||||
|
||||
if_pixclk_rate = (dclk_core_rate << 1) / K;
|
||||
if_dclk_rate = dclk_core_rate / K;
|
||||
/*
|
||||
* *if_pixclk_div = dclk_rate / if_pixclk_rate;
|
||||
* *if_dclk_div = dclk_rate / if_dclk_rate;
|
||||
*/
|
||||
*if_pixclk_div = 2;
|
||||
*if_dclk_div = 4;
|
||||
} else if (vop2_output_if_is_edp(id)) {
|
||||
/*
|
||||
* edp_pixclk = edp_dclk > dclk_core
|
||||
*/
|
||||
if_pixclk_rate = v_pixclk / K;
|
||||
dclk_rate = if_pixclk_rate * K;
|
||||
/*
|
||||
* *if_pixclk_div = dclk_rate / if_pixclk_rate;
|
||||
* *if_dclk_div = *if_pixclk_div;
|
||||
*/
|
||||
*if_pixclk_div = K;
|
||||
*if_dclk_div = K;
|
||||
} else if (vop2_output_if_is_dp(id)) {
|
||||
if (output_mode == ROCKCHIP_OUT_MODE_YUV420)
|
||||
dclk_out_rate = v_pixclk >> 3;
|
||||
else
|
||||
dclk_out_rate = v_pixclk >> 2;
|
||||
|
||||
dclk_rate = rk3588_calc_dclk(dclk_out_rate, 600000);
|
||||
if (!dclk_rate) {
|
||||
drm_err(vop2->drm, "DP dclk_out_rate out of range, dclk_out_rate: %ld KHZ\n",
|
||||
dclk_out_rate);
|
||||
return 0;
|
||||
}
|
||||
*dclk_out_div = dclk_rate / dclk_out_rate;
|
||||
} else if (vop2_output_if_is_mipi(id)) {
|
||||
if_pixclk_rate = dclk_core_rate / K;
|
||||
/*
|
||||
* dclk_core = dclk_out * K = if_pixclk * K = v_pixclk / 4
|
||||
*/
|
||||
dclk_out_rate = if_pixclk_rate;
|
||||
/*
|
||||
* dclk_rate = N * dclk_core_rate N = (1,2,4 ),
|
||||
* we get a little factor here
|
||||
*/
|
||||
dclk_rate = rk3588_calc_dclk(dclk_out_rate, 600000);
|
||||
if (!dclk_rate) {
|
||||
drm_err(vop2->drm, "MIPI dclk out of range, dclk_out_rate: %ld KHZ\n",
|
||||
dclk_out_rate);
|
||||
return 0;
|
||||
}
|
||||
*dclk_out_div = dclk_rate / dclk_out_rate;
|
||||
/*
|
||||
* mipi pixclk == dclk_out
|
||||
*/
|
||||
*if_pixclk_div = 1;
|
||||
} else if (vop2_output_if_is_dpi(id)) {
|
||||
dclk_rate = v_pixclk;
|
||||
}
|
||||
|
||||
*dclk_core_div = dclk_rate / dclk_core_rate;
|
||||
*if_pixclk_div = ilog2(*if_pixclk_div);
|
||||
*if_dclk_div = ilog2(*if_dclk_div);
|
||||
*dclk_core_div = ilog2(*dclk_core_div);
|
||||
*dclk_out_div = ilog2(*dclk_out_div);
|
||||
|
||||
drm_dbg(vop2->drm, "dclk: %ld, pixclk_div: %d, dclk_div: %d\n",
|
||||
dclk_rate, *if_pixclk_div, *if_dclk_div);
|
||||
|
||||
return dclk_rate;
|
||||
}
|
||||
|
||||
/*
|
||||
* MIPI port mux on rk3588:
|
||||
* 0: Video Port2
|
||||
* 1: Video Port3
|
||||
* 3: Video Port 1(MIPI1 only)
|
||||
*/
|
||||
static u32 rk3588_get_mipi_port_mux(int vp_id)
|
||||
{
|
||||
if (vp_id == 1)
|
||||
return 3;
|
||||
else if (vp_id == 3)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 rk3588_get_hdmi_pol(u32 flags)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = (flags & DRM_MODE_FLAG_NHSYNC) ? BIT(HSYNC_POSITIVE) : 0;
|
||||
val |= (flags & DRM_MODE_FLAG_NVSYNC) ? BIT(VSYNC_POSITIVE) : 0;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static unsigned long rk3588_set_intf_mux(struct vop2_video_port *vp, int id, u32 polflags)
|
||||
{
|
||||
struct vop2 *vop2 = vp->vop2;
|
||||
int dclk_core_div, dclk_out_div, if_pixclk_div, if_dclk_div;
|
||||
unsigned long clock;
|
||||
u32 die, dip, div, vp_clk_div, val;
|
||||
|
||||
clock = rk3588_calc_cru_cfg(vp, id, &dclk_core_div, &dclk_out_div,
|
||||
&if_pixclk_div, &if_dclk_div);
|
||||
if (!clock)
|
||||
return 0;
|
||||
|
||||
vp_clk_div = FIELD_PREP(RK3588_VP_CLK_CTRL__DCLK_CORE_DIV, dclk_core_div);
|
||||
vp_clk_div |= FIELD_PREP(RK3588_VP_CLK_CTRL__DCLK_OUT_DIV, dclk_out_div);
|
||||
|
||||
die = vop2_readl(vop2, RK3568_DSP_IF_EN);
|
||||
dip = vop2_readl(vop2, RK3568_DSP_IF_POL);
|
||||
div = vop2_readl(vop2, RK3568_DSP_IF_CTRL);
|
||||
|
||||
switch (id) {
|
||||
case ROCKCHIP_VOP2_EP_HDMI0:
|
||||
div &= ~RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV;
|
||||
div &= ~RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV;
|
||||
div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV, if_dclk_div);
|
||||
div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV, if_pixclk_div);
|
||||
die &= ~RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX;
|
||||
die |= RK3588_SYS_DSP_INFACE_EN_HDMI0 |
|
||||
FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX, vp->id);
|
||||
val = rk3588_get_hdmi_pol(polflags);
|
||||
regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, HIWORD_UPDATE(1, 1, 1));
|
||||
regmap_write(vop2->vo1_grf, RK3588_GRF_VO1_CON0, HIWORD_UPDATE(val, 6, 5));
|
||||
break;
|
||||
case ROCKCHIP_VOP2_EP_HDMI1:
|
||||
div &= ~RK3588_DSP_IF_EDP_HDMI1_DCLK_DIV;
|
||||
div &= ~RK3588_DSP_IF_EDP_HDMI1_PCLK_DIV;
|
||||
div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI1_DCLK_DIV, if_dclk_div);
|
||||
div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI1_PCLK_DIV, if_pixclk_div);
|
||||
die &= ~RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX;
|
||||
die |= RK3588_SYS_DSP_INFACE_EN_HDMI1 |
|
||||
FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX, vp->id);
|
||||
val = rk3588_get_hdmi_pol(polflags);
|
||||
regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, HIWORD_UPDATE(1, 4, 4));
|
||||
regmap_write(vop2->vo1_grf, RK3588_GRF_VO1_CON0, HIWORD_UPDATE(val, 8, 7));
|
||||
break;
|
||||
case ROCKCHIP_VOP2_EP_EDP0:
|
||||
div &= ~RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV;
|
||||
div &= ~RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV;
|
||||
div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV, if_dclk_div);
|
||||
div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV, if_pixclk_div);
|
||||
die &= ~RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX;
|
||||
die |= RK3588_SYS_DSP_INFACE_EN_EDP0 |
|
||||
FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX, vp->id);
|
||||
regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, HIWORD_UPDATE(1, 0, 0));
|
||||
break;
|
||||
case ROCKCHIP_VOP2_EP_EDP1:
|
||||
div &= ~RK3588_DSP_IF_EDP_HDMI1_DCLK_DIV;
|
||||
div &= ~RK3588_DSP_IF_EDP_HDMI1_PCLK_DIV;
|
||||
div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV, if_dclk_div);
|
||||
div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV, if_pixclk_div);
|
||||
die &= ~RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX;
|
||||
die |= RK3588_SYS_DSP_INFACE_EN_EDP1 |
|
||||
FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX, vp->id);
|
||||
regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, HIWORD_UPDATE(1, 3, 3));
|
||||
break;
|
||||
case ROCKCHIP_VOP2_EP_MIPI0:
|
||||
div &= ~RK3588_DSP_IF_MIPI0_PCLK_DIV;
|
||||
div |= FIELD_PREP(RK3588_DSP_IF_MIPI0_PCLK_DIV, if_pixclk_div);
|
||||
die &= ~RK3588_SYS_DSP_INFACE_EN_MIPI0_MUX;
|
||||
val = rk3588_get_mipi_port_mux(vp->id);
|
||||
die |= RK3588_SYS_DSP_INFACE_EN_MIPI0 |
|
||||
FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_MIPI0_MUX, !!val);
|
||||
break;
|
||||
case ROCKCHIP_VOP2_EP_MIPI1:
|
||||
div &= ~RK3588_DSP_IF_MIPI1_PCLK_DIV;
|
||||
div |= FIELD_PREP(RK3588_DSP_IF_MIPI1_PCLK_DIV, if_pixclk_div);
|
||||
die &= ~RK3588_SYS_DSP_INFACE_EN_MIPI1_MUX;
|
||||
val = rk3588_get_mipi_port_mux(vp->id);
|
||||
die |= RK3588_SYS_DSP_INFACE_EN_MIPI1 |
|
||||
FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_MIPI1_MUX, val);
|
||||
break;
|
||||
case ROCKCHIP_VOP2_EP_DP0:
|
||||
die &= ~RK3588_SYS_DSP_INFACE_EN_DP0_MUX;
|
||||
die |= RK3588_SYS_DSP_INFACE_EN_DP0 |
|
||||
FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_DP0_MUX, vp->id);
|
||||
dip &= ~RK3588_DSP_IF_POL__DP0_PIN_POL;
|
||||
dip |= FIELD_PREP(RK3588_DSP_IF_POL__DP0_PIN_POL, polflags);
|
||||
break;
|
||||
case ROCKCHIP_VOP2_EP_DP1:
|
||||
die &= ~RK3588_SYS_DSP_INFACE_EN_MIPI1_MUX;
|
||||
die |= RK3588_SYS_DSP_INFACE_EN_MIPI1 |
|
||||
FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_MIPI1_MUX, vp->id);
|
||||
dip &= ~RK3588_DSP_IF_POL__DP1_PIN_POL;
|
||||
dip |= FIELD_PREP(RK3588_DSP_IF_POL__DP1_PIN_POL, polflags);
|
||||
break;
|
||||
default:
|
||||
drm_err(vop2->drm, "Invalid interface id %d on vp%d\n", id, vp->id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dip |= RK3568_DSP_IF_POL__CFG_DONE_IMD;
|
||||
|
||||
vop2_vp_write(vp, RK3588_VP_CLK_CTRL, vp_clk_div);
|
||||
vop2_writel(vop2, RK3568_DSP_IF_EN, die);
|
||||
vop2_writel(vop2, RK3568_DSP_IF_CTRL, div);
|
||||
vop2_writel(vop2, RK3568_DSP_IF_POL, dip);
|
||||
|
||||
return clock;
|
||||
}
|
||||
|
||||
static unsigned long vop2_set_intf_mux(struct vop2_video_port *vp, int ep_id, u32 polflags)
|
||||
{
|
||||
struct vop2 *vop2 = vp->vop2;
|
||||
|
||||
if (vop2->data->soc_id == 3566 || vop2->data->soc_id == 3568)
|
||||
return rk3568_set_intf_mux(vp, ep_id, polflags);
|
||||
else if (vop2->data->soc_id == 3588)
|
||||
return rk3588_set_intf_mux(vp, ep_id, polflags);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int us_to_vertical_line(struct drm_display_mode *mode, int us)
|
||||
@ -1592,6 +1968,8 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc,
|
||||
|
||||
vop2->enable_count++;
|
||||
|
||||
vcstate->yuv_overlay = is_yuv_output(vcstate->bus_format);
|
||||
|
||||
vop2_crtc_enable_irq(vp, VP_INT_POST_BUF_EMPTY);
|
||||
|
||||
polflags = 0;
|
||||
@ -1605,11 +1983,19 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc,
|
||||
drm_for_each_encoder_mask(encoder, crtc->dev, crtc_state->encoder_mask) {
|
||||
struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder);
|
||||
|
||||
rk3568_set_intf_mux(vp, rkencoder->crtc_endpoint_id, polflags);
|
||||
/*
|
||||
* for drive a high resolution(4KP120, 8K), vop on rk3588/rk3576 need
|
||||
* process multi(1/2/4/8) pixels per cycle, so the dclk feed by the
|
||||
* system cru may be the 1/2 or 1/4 of mode->clock.
|
||||
*/
|
||||
clock = vop2_set_intf_mux(vp, rkencoder->crtc_endpoint_id, polflags);
|
||||
}
|
||||
|
||||
if (!clock)
|
||||
return;
|
||||
|
||||
if (vcstate->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
|
||||
!(vp_data->feature & VOP_FEATURE_OUTPUT_10BIT))
|
||||
!(vp_data->feature & VOP2_VP_FEATURE_OUTPUT_10BIT))
|
||||
out_mode = ROCKCHIP_OUT_MODE_P888;
|
||||
else
|
||||
out_mode = vcstate->output_mode;
|
||||
@ -1618,8 +2004,10 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc,
|
||||
|
||||
if (vop2_output_uv_swap(vcstate->bus_format, vcstate->output_mode))
|
||||
dsp_ctrl |= RK3568_VP_DSP_CTRL__DSP_RB_SWAP;
|
||||
if (vop2_output_rg_swap(vop2, vcstate->bus_format))
|
||||
dsp_ctrl |= RK3568_VP_DSP_CTRL__DSP_RG_SWAP;
|
||||
|
||||
if (is_yuv_output(vcstate->bus_format))
|
||||
if (vcstate->yuv_overlay)
|
||||
dsp_ctrl |= RK3568_VP_DSP_CTRL__POST_DSP_OUT_R2Y;
|
||||
|
||||
vop2_dither_setup(crtc, &dsp_ctrl);
|
||||
@ -1923,28 +2311,22 @@ static void vop2_setup_layer_mixer(struct vop2_video_port *vp)
|
||||
u32 layer_sel = 0;
|
||||
u32 port_sel;
|
||||
unsigned int nlayer, ofs;
|
||||
struct drm_display_mode *adjusted_mode;
|
||||
u16 hsync_len;
|
||||
u16 hdisplay;
|
||||
u32 bg_dly;
|
||||
u32 pre_scan_dly;
|
||||
u32 ovl_ctrl;
|
||||
int i;
|
||||
struct vop2_video_port *vp0 = &vop2->vps[0];
|
||||
struct vop2_video_port *vp1 = &vop2->vps[1];
|
||||
struct vop2_video_port *vp2 = &vop2->vps[2];
|
||||
struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state);
|
||||
|
||||
adjusted_mode = &vp->crtc.state->adjusted_mode;
|
||||
hsync_len = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
|
||||
hdisplay = adjusted_mode->crtc_hdisplay;
|
||||
ovl_ctrl = vop2_readl(vop2, RK3568_OVL_CTRL);
|
||||
ovl_ctrl |= RK3568_OVL_CTRL__LAYERSEL_REGDONE_IMD;
|
||||
if (vcstate->yuv_overlay)
|
||||
ovl_ctrl |= RK3568_OVL_CTRL__YUV_MODE(vp->id);
|
||||
else
|
||||
ovl_ctrl &= ~RK3568_OVL_CTRL__YUV_MODE(vp->id);
|
||||
|
||||
bg_dly = vp->data->pre_scan_max_dly[3];
|
||||
vop2_writel(vop2, RK3568_VP_BG_MIX_CTRL(vp->id),
|
||||
FIELD_PREP(RK3568_VP_BG_MIX_CTRL__BG_DLY, bg_dly));
|
||||
vop2_writel(vop2, RK3568_OVL_CTRL, ovl_ctrl);
|
||||
|
||||
pre_scan_dly = ((bg_dly + (hdisplay >> 1) - 1) << 16) | hsync_len;
|
||||
vop2_vp_write(vp, RK3568_VP_PRE_SCAN_HTIMING, pre_scan_dly);
|
||||
|
||||
vop2_writel(vop2, RK3568_OVL_CTRL, 0);
|
||||
port_sel = vop2_readl(vop2, RK3568_OVL_PORT_SEL);
|
||||
port_sel &= RK3568_OVL_PORT_SEL__SEL_PORT;
|
||||
|
||||
@ -1985,6 +2367,14 @@ static void vop2_setup_layer_mixer(struct vop2_video_port *vp)
|
||||
port_sel &= ~RK3568_OVL_PORT_SEL__CLUSTER1;
|
||||
port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__CLUSTER1, vp->id);
|
||||
break;
|
||||
case ROCKCHIP_VOP2_CLUSTER2:
|
||||
port_sel &= ~RK3588_OVL_PORT_SEL__CLUSTER2;
|
||||
port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__CLUSTER2, vp->id);
|
||||
break;
|
||||
case ROCKCHIP_VOP2_CLUSTER3:
|
||||
port_sel &= ~RK3588_OVL_PORT_SEL__CLUSTER3;
|
||||
port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__CLUSTER3, vp->id);
|
||||
break;
|
||||
case ROCKCHIP_VOP2_ESMART0:
|
||||
port_sel &= ~RK3568_OVL_PORT_SEL__ESMART0;
|
||||
port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__ESMART0, vp->id);
|
||||
@ -1993,6 +2383,14 @@ static void vop2_setup_layer_mixer(struct vop2_video_port *vp)
|
||||
port_sel &= ~RK3568_OVL_PORT_SEL__ESMART1;
|
||||
port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__ESMART1, vp->id);
|
||||
break;
|
||||
case ROCKCHIP_VOP2_ESMART2:
|
||||
port_sel &= ~RK3588_OVL_PORT_SEL__ESMART2;
|
||||
port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__ESMART2, vp->id);
|
||||
break;
|
||||
case ROCKCHIP_VOP2_ESMART3:
|
||||
port_sel &= ~RK3588_OVL_PORT_SEL__ESMART3;
|
||||
port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__ESMART3, vp->id);
|
||||
break;
|
||||
case ROCKCHIP_VOP2_SMART0:
|
||||
port_sel &= ~RK3568_OVL_PORT_SEL__SMART0;
|
||||
port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__SMART0, vp->id);
|
||||
@ -2018,7 +2416,6 @@ static void vop2_setup_layer_mixer(struct vop2_video_port *vp)
|
||||
|
||||
vop2_writel(vop2, RK3568_OVL_LAYER_SEL, layer_sel);
|
||||
vop2_writel(vop2, RK3568_OVL_PORT_SEL, port_sel);
|
||||
vop2_writel(vop2, RK3568_OVL_CTRL, RK3568_OVL_CTRL__LAYERSEL_REGDONE_IMD);
|
||||
}
|
||||
|
||||
static void vop2_setup_dly_for_windows(struct vop2 *vop2)
|
||||
@ -2730,8 +3127,29 @@ static int vop2_bind(struct device *dev, struct device *master, void *data)
|
||||
if (IS_ERR(vop2->lut_regs))
|
||||
return PTR_ERR(vop2->lut_regs);
|
||||
}
|
||||
if (vop2_data->feature & VOP2_FEATURE_HAS_SYS_GRF) {
|
||||
vop2->sys_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf");
|
||||
if (IS_ERR(vop2->sys_grf))
|
||||
return dev_err_probe(dev, PTR_ERR(vop2->sys_grf), "cannot get sys_grf");
|
||||
}
|
||||
|
||||
vop2->grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf");
|
||||
if (vop2_data->feature & VOP2_FEATURE_HAS_VOP_GRF) {
|
||||
vop2->vop_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,vop-grf");
|
||||
if (IS_ERR(vop2->vop_grf))
|
||||
return dev_err_probe(dev, PTR_ERR(vop2->vop_grf), "cannot get vop_grf");
|
||||
}
|
||||
|
||||
if (vop2_data->feature & VOP2_FEATURE_HAS_VO1_GRF) {
|
||||
vop2->vo1_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,vo1-grf");
|
||||
if (IS_ERR(vop2->vo1_grf))
|
||||
return dev_err_probe(dev, PTR_ERR(vop2->vo1_grf), "cannot get vo1_grf");
|
||||
}
|
||||
|
||||
if (vop2_data->feature & VOP2_FEATURE_HAS_SYS_PMU) {
|
||||
vop2->sys_pmu = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pmu");
|
||||
if (IS_ERR(vop2->sys_pmu))
|
||||
return dev_err_probe(dev, PTR_ERR(vop2->sys_pmu), "cannot get sys_pmu");
|
||||
}
|
||||
|
||||
vop2->hclk = devm_clk_get(vop2->dev, "hclk");
|
||||
if (IS_ERR(vop2->hclk)) {
|
||||
@ -2745,6 +3163,12 @@ static int vop2_bind(struct device *dev, struct device *master, void *data)
|
||||
return PTR_ERR(vop2->aclk);
|
||||
}
|
||||
|
||||
vop2->pclk = devm_clk_get_optional(vop2->dev, "pclk_vop");
|
||||
if (IS_ERR(vop2->pclk)) {
|
||||
drm_err(vop2->drm, "failed to get pclk source\n");
|
||||
return PTR_ERR(vop2->pclk);
|
||||
}
|
||||
|
||||
vop2->irq = platform_get_irq(pdev, 0);
|
||||
if (vop2->irq < 0) {
|
||||
drm_err(vop2->drm, "cannot find irq for vop2\n");
|
||||
|
@ -7,16 +7,22 @@
|
||||
#ifndef _ROCKCHIP_DRM_VOP2_H
|
||||
#define _ROCKCHIP_DRM_VOP2_H
|
||||
|
||||
#include "rockchip_drm_vop.h"
|
||||
|
||||
#include <linux/regmap.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include "rockchip_drm_vop.h"
|
||||
|
||||
#define VOP_FEATURE_OUTPUT_10BIT BIT(0)
|
||||
#define VOP2_VP_FEATURE_OUTPUT_10BIT BIT(0)
|
||||
|
||||
#define VOP2_FEATURE_HAS_SYS_GRF BIT(0)
|
||||
#define VOP2_FEATURE_HAS_VO0_GRF BIT(1)
|
||||
#define VOP2_FEATURE_HAS_VO1_GRF BIT(2)
|
||||
#define VOP2_FEATURE_HAS_VOP_GRF BIT(3)
|
||||
#define VOP2_FEATURE_HAS_SYS_PMU BIT(4)
|
||||
|
||||
#define WIN_FEATURE_AFBDC BIT(0)
|
||||
#define WIN_FEATURE_CLUSTER BIT(1)
|
||||
|
||||
#define HIWORD_UPDATE(v, h, l) ((GENMASK(h, l) << 16) | ((v) << (l)))
|
||||
/*
|
||||
* the delay number of a window in different mode.
|
||||
*/
|
||||
@ -39,6 +45,18 @@ enum vop2_scale_down_mode {
|
||||
VOP2_SCALE_DOWN_AVG,
|
||||
};
|
||||
|
||||
/*
|
||||
* vop2 internal power domain id,
|
||||
* should be all none zero, 0 will be treat as invalid;
|
||||
*/
|
||||
#define VOP2_PD_CLUSTER0 BIT(0)
|
||||
#define VOP2_PD_CLUSTER1 BIT(1)
|
||||
#define VOP2_PD_CLUSTER2 BIT(2)
|
||||
#define VOP2_PD_CLUSTER3 BIT(3)
|
||||
#define VOP2_PD_DSC_8K BIT(5)
|
||||
#define VOP2_PD_DSC_4K BIT(6)
|
||||
#define VOP2_PD_ESMART BIT(7)
|
||||
|
||||
enum vop2_win_regs {
|
||||
VOP2_WIN_ENABLE,
|
||||
VOP2_WIN_FORMAT,
|
||||
@ -139,6 +157,7 @@ struct vop2_video_port_data {
|
||||
|
||||
struct vop2_data {
|
||||
u8 nr_vps;
|
||||
u64 feature;
|
||||
const struct vop2_win_data *win;
|
||||
const struct vop2_video_port_data *vp;
|
||||
struct vop_rect max_input;
|
||||
@ -166,19 +185,6 @@ struct vop2_data {
|
||||
#define WB_YRGB_FIFO_FULL_INTR BIT(18)
|
||||
#define WB_COMPLETE_INTR BIT(19)
|
||||
|
||||
/*
|
||||
* display output interface supported by rockchip lcdc
|
||||
*/
|
||||
#define ROCKCHIP_OUT_MODE_P888 0
|
||||
#define ROCKCHIP_OUT_MODE_BT1120 0
|
||||
#define ROCKCHIP_OUT_MODE_P666 1
|
||||
#define ROCKCHIP_OUT_MODE_P565 2
|
||||
#define ROCKCHIP_OUT_MODE_BT656 5
|
||||
#define ROCKCHIP_OUT_MODE_S888 8
|
||||
#define ROCKCHIP_OUT_MODE_S888_DUMMY 12
|
||||
#define ROCKCHIP_OUT_MODE_YUV420 14
|
||||
/* for use special outface */
|
||||
#define ROCKCHIP_OUT_MODE_AAAA 15
|
||||
|
||||
enum vop_csc_format {
|
||||
CSC_BT601L,
|
||||
@ -206,6 +212,11 @@ enum dst_factor_mode {
|
||||
};
|
||||
|
||||
#define RK3568_GRF_VO_CON1 0x0364
|
||||
|
||||
#define RK3588_GRF_SOC_CON1 0x0304
|
||||
#define RK3588_GRF_VOP_CON2 0x08
|
||||
#define RK3588_GRF_VO1_CON0 0x00
|
||||
|
||||
/* System registers definition */
|
||||
#define RK3568_REG_CFG_DONE 0x000
|
||||
#define RK3568_VERSION_INFO 0x004
|
||||
@ -214,6 +225,7 @@ enum dst_factor_mode {
|
||||
#define RK3568_DSP_IF_EN 0x028
|
||||
#define RK3568_DSP_IF_CTRL 0x02c
|
||||
#define RK3568_DSP_IF_POL 0x030
|
||||
#define RK3588_SYS_PD_CTRL 0x034
|
||||
#define RK3568_WB_CTRL 0x40
|
||||
#define RK3568_WB_XSCAL_FACTOR 0x44
|
||||
#define RK3568_WB_YRGB_MST 0x48
|
||||
@ -234,9 +246,14 @@ enum dst_factor_mode {
|
||||
#define RK3568_VP_INT_RAW_STATUS(vp) (0xAC + (vp) * 0x10)
|
||||
|
||||
/* Video Port registers definition */
|
||||
#define RK3568_VP0_CTRL_BASE 0x0C00
|
||||
#define RK3568_VP1_CTRL_BASE 0x0D00
|
||||
#define RK3568_VP2_CTRL_BASE 0x0E00
|
||||
#define RK3588_VP3_CTRL_BASE 0x0F00
|
||||
#define RK3568_VP_DSP_CTRL 0x00
|
||||
#define RK3568_VP_MIPI_CTRL 0x04
|
||||
#define RK3568_VP_COLOR_BAR_CTRL 0x08
|
||||
#define RK3588_VP_CLK_CTRL 0x0C
|
||||
#define RK3568_VP_3D_LUT_CTRL 0x10
|
||||
#define RK3568_VP_3D_LUT_MST 0x20
|
||||
#define RK3568_VP_DSP_BG 0x2C
|
||||
@ -278,6 +295,17 @@ enum dst_factor_mode {
|
||||
#define RK3568_SMART_DLY_NUM 0x6F8
|
||||
|
||||
/* Cluster register definition, offset relative to window base */
|
||||
#define RK3568_CLUSTER0_CTRL_BASE 0x1000
|
||||
#define RK3568_CLUSTER1_CTRL_BASE 0x1200
|
||||
#define RK3588_CLUSTER2_CTRL_BASE 0x1400
|
||||
#define RK3588_CLUSTER3_CTRL_BASE 0x1600
|
||||
#define RK3568_ESMART0_CTRL_BASE 0x1800
|
||||
#define RK3568_ESMART1_CTRL_BASE 0x1A00
|
||||
#define RK3568_SMART0_CTRL_BASE 0x1C00
|
||||
#define RK3568_SMART1_CTRL_BASE 0x1E00
|
||||
#define RK3588_ESMART2_CTRL_BASE 0x1C00
|
||||
#define RK3588_ESMART3_CTRL_BASE 0x1E00
|
||||
|
||||
#define RK3568_CLUSTER_WIN_CTRL0 0x00
|
||||
#define RK3568_CLUSTER_WIN_CTRL1 0x04
|
||||
#define RK3568_CLUSTER_WIN_YRGB_MST 0x10
|
||||
@ -371,13 +399,18 @@ enum dst_factor_mode {
|
||||
#define RK3568_VP_DSP_CTRL__DITHER_DOWN_EN BIT(17)
|
||||
#define RK3568_VP_DSP_CTRL__PRE_DITHER_DOWN_EN BIT(16)
|
||||
#define RK3568_VP_DSP_CTRL__POST_DSP_OUT_R2Y BIT(15)
|
||||
#define RK3568_VP_DSP_CTRL__DSP_RG_SWAP BIT(10)
|
||||
#define RK3568_VP_DSP_CTRL__DSP_RB_SWAP BIT(9)
|
||||
#define RK3568_VP_DSP_CTRL__DSP_BG_SWAP BIT(8)
|
||||
#define RK3568_VP_DSP_CTRL__DSP_INTERLACE BIT(7)
|
||||
#define RK3568_VP_DSP_CTRL__DSP_FILED_POL BIT(6)
|
||||
#define RK3568_VP_DSP_CTRL__P2I_EN BIT(5)
|
||||
#define RK3568_VP_DSP_CTRL__CORE_DCLK_DIV BIT(4)
|
||||
#define RK3568_VP_DSP_CTRL__OUT_MODE GENMASK(3, 0)
|
||||
|
||||
#define RK3588_VP_CLK_CTRL__DCLK_OUT_DIV GENMASK(3, 2)
|
||||
#define RK3588_VP_CLK_CTRL__DCLK_CORE_DIV GENMASK(1, 0)
|
||||
|
||||
#define RK3568_VP_POST_SCL_CTRL__VSCALEDOWN BIT(1)
|
||||
#define RK3568_VP_POST_SCL_CTRL__HSCALEDOWN BIT(0)
|
||||
|
||||
@ -396,11 +429,37 @@ enum dst_factor_mode {
|
||||
#define RK3568_SYS_DSP_INFACE_EN_HDMI BIT(1)
|
||||
#define RK3568_SYS_DSP_INFACE_EN_RGB BIT(0)
|
||||
|
||||
#define RK3588_SYS_DSP_INFACE_EN_MIPI1_MUX GENMASK(22, 21)
|
||||
#define RK3588_SYS_DSP_INFACE_EN_MIPI0_MUX GENMASK(20, 20)
|
||||
#define RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX GENMASK(19, 18)
|
||||
#define RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX GENMASK(17, 16)
|
||||
#define RK3588_SYS_DSP_INFACE_EN_DP1_MUX GENMASK(15, 14)
|
||||
#define RK3588_SYS_DSP_INFACE_EN_DP0_MUX GENMASK(13, 12)
|
||||
#define RK3588_SYS_DSP_INFACE_EN_DPI GENMASK(9, 8)
|
||||
#define RK3588_SYS_DSP_INFACE_EN_MIPI1 BIT(7)
|
||||
#define RK3588_SYS_DSP_INFACE_EN_MIPI0 BIT(6)
|
||||
#define RK3588_SYS_DSP_INFACE_EN_HDMI1 BIT(5)
|
||||
#define RK3588_SYS_DSP_INFACE_EN_EDP1 BIT(4)
|
||||
#define RK3588_SYS_DSP_INFACE_EN_HDMI0 BIT(3)
|
||||
#define RK3588_SYS_DSP_INFACE_EN_EDP0 BIT(2)
|
||||
#define RK3588_SYS_DSP_INFACE_EN_DP1 BIT(1)
|
||||
#define RK3588_SYS_DSP_INFACE_EN_DP0 BIT(0)
|
||||
|
||||
#define RK3588_DSP_IF_MIPI1_PCLK_DIV GENMASK(27, 26)
|
||||
#define RK3588_DSP_IF_MIPI0_PCLK_DIV GENMASK(25, 24)
|
||||
#define RK3588_DSP_IF_EDP_HDMI1_PCLK_DIV GENMASK(22, 22)
|
||||
#define RK3588_DSP_IF_EDP_HDMI1_DCLK_DIV GENMASK(21, 20)
|
||||
#define RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV GENMASK(18, 18)
|
||||
#define RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV GENMASK(17, 16)
|
||||
|
||||
#define RK3568_DSP_IF_POL__MIPI_PIN_POL GENMASK(19, 16)
|
||||
#define RK3568_DSP_IF_POL__EDP_PIN_POL GENMASK(15, 12)
|
||||
#define RK3568_DSP_IF_POL__HDMI_PIN_POL GENMASK(7, 4)
|
||||
#define RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL GENMASK(3, 0)
|
||||
|
||||
#define RK3588_DSP_IF_POL__DP1_PIN_POL GENMASK(14, 12)
|
||||
#define RK3588_DSP_IF_POL__DP0_PIN_POL GENMASK(10, 8)
|
||||
|
||||
#define RK3568_VP0_MIPI_CTRL__DCLK_DIV2_PHASE_LOCK BIT(5)
|
||||
#define RK3568_VP0_MIPI_CTRL__DCLK_DIV2 BIT(4)
|
||||
|
||||
@ -415,14 +474,19 @@ enum dst_factor_mode {
|
||||
#define VOP2_COLOR_KEY_MASK BIT(31)
|
||||
|
||||
#define RK3568_OVL_CTRL__LAYERSEL_REGDONE_IMD BIT(28)
|
||||
#define RK3568_OVL_CTRL__YUV_MODE(vp) BIT(vp)
|
||||
|
||||
#define RK3568_VP_BG_MIX_CTRL__BG_DLY GENMASK(31, 24)
|
||||
|
||||
#define RK3568_OVL_PORT_SEL__SEL_PORT GENMASK(31, 16)
|
||||
#define RK3568_OVL_PORT_SEL__SMART1 GENMASK(31, 30)
|
||||
#define RK3568_OVL_PORT_SEL__SMART0 GENMASK(29, 28)
|
||||
#define RK3588_OVL_PORT_SEL__ESMART3 GENMASK(31, 30)
|
||||
#define RK3588_OVL_PORT_SEL__ESMART2 GENMASK(29, 28)
|
||||
#define RK3568_OVL_PORT_SEL__ESMART1 GENMASK(27, 26)
|
||||
#define RK3568_OVL_PORT_SEL__ESMART0 GENMASK(25, 24)
|
||||
#define RK3588_OVL_PORT_SEL__CLUSTER3 GENMASK(23, 22)
|
||||
#define RK3588_OVL_PORT_SEL__CLUSTER2 GENMASK(21, 20)
|
||||
#define RK3568_OVL_PORT_SEL__CLUSTER1 GENMASK(19, 18)
|
||||
#define RK3568_OVL_PORT_SEL__CLUSTER0 GENMASK(17, 16)
|
||||
#define RK3568_OVL_PORT_SET__PORT2_MUX GENMASK(11, 8)
|
||||
@ -435,6 +499,10 @@ enum dst_factor_mode {
|
||||
#define RK3568_CLUSTER_DLY_NUM__CLUSTER0_1 GENMASK(15, 8)
|
||||
#define RK3568_CLUSTER_DLY_NUM__CLUSTER0_0 GENMASK(7, 0)
|
||||
|
||||
#define RK3568_CLUSTER_WIN_CTRL0__WIN0_EN BIT(0)
|
||||
|
||||
#define RK3568_SMART_REGION0_CTRL__WIN0_EN BIT(0)
|
||||
|
||||
#define RK3568_SMART_DLY_NUM__SMART1 GENMASK(31, 24)
|
||||
#define RK3568_SMART_DLY_NUM__SMART0 GENMASK(23, 16)
|
||||
#define RK3568_SMART_DLY_NUM__ESMART1 GENMASK(15, 8)
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include <drm/drm_simple_kms_helper.h>
|
||||
|
||||
#include "rockchip_drm_drv.h"
|
||||
#include "rockchip_drm_vop.h"
|
||||
#include "rockchip_lvds.h"
|
||||
|
||||
#define DISPLAY_OUTPUT_RGB 0
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include <drm/drm_simple_kms_helper.h>
|
||||
|
||||
#include "rockchip_drm_drv.h"
|
||||
#include "rockchip_drm_vop.h"
|
||||
#include "rockchip_rgb.h"
|
||||
|
||||
struct rockchip_rgb {
|
||||
|
@ -34,6 +34,30 @@ static const uint32_t formats_cluster[] = {
|
||||
DRM_FORMAT_Y210, /* yuv422_10bit non-Linear mode only */
|
||||
};
|
||||
|
||||
static const uint32_t formats_esmart[] = {
|
||||
DRM_FORMAT_XRGB8888,
|
||||
DRM_FORMAT_ARGB8888,
|
||||
DRM_FORMAT_XBGR8888,
|
||||
DRM_FORMAT_ABGR8888,
|
||||
DRM_FORMAT_RGB888,
|
||||
DRM_FORMAT_BGR888,
|
||||
DRM_FORMAT_RGB565,
|
||||
DRM_FORMAT_BGR565,
|
||||
DRM_FORMAT_NV12, /* yuv420_8bit linear mode, 2 plane */
|
||||
DRM_FORMAT_NV21, /* yvu420_8bit linear mode, 2 plane */
|
||||
DRM_FORMAT_NV16, /* yuv422_8bit linear mode, 2 plane */
|
||||
DRM_FORMAT_NV61, /* yvu422_8bit linear mode, 2 plane */
|
||||
DRM_FORMAT_NV20, /* yuv422_10bit linear mode, 2 plane, no padding */
|
||||
DRM_FORMAT_NV24, /* yuv444_8bit linear mode, 2 plane */
|
||||
DRM_FORMAT_NV42, /* yvu444_8bit linear mode, 2 plane */
|
||||
DRM_FORMAT_NV30, /* yuv444_10bit linear mode, 2 plane, no padding */
|
||||
DRM_FORMAT_NV15, /* yuv420_10bit linear mode, 2 plane, no padding */
|
||||
DRM_FORMAT_YVYU, /* yuv422_8bit[YVYU] linear mode */
|
||||
DRM_FORMAT_VYUY, /* yuv422_8bit[VYUY] linear mode */
|
||||
DRM_FORMAT_YUYV, /* yuv422_8bit[YUYV] linear mode */
|
||||
DRM_FORMAT_UYVY, /* yuv422_8bit[UYVY] linear mode */
|
||||
};
|
||||
|
||||
static const uint32_t formats_rk356x_esmart[] = {
|
||||
DRM_FORMAT_XRGB8888,
|
||||
DRM_FORMAT_ARGB8888,
|
||||
@ -112,7 +136,7 @@ static const uint64_t format_modifiers_afbc[] = {
|
||||
static const struct vop2_video_port_data rk3568_vop_video_ports[] = {
|
||||
{
|
||||
.id = 0,
|
||||
.feature = VOP_FEATURE_OUTPUT_10BIT,
|
||||
.feature = VOP2_VP_FEATURE_OUTPUT_10BIT,
|
||||
.gamma_lut_len = 1024,
|
||||
.cubic_lut_len = 9 * 9 * 9,
|
||||
.max_output = { 4096, 2304 },
|
||||
@ -236,7 +260,188 @@ static const struct vop2_win_data rk3568_vop_win_data[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct vop2_video_port_data rk3588_vop_video_ports[] = {
|
||||
{
|
||||
.id = 0,
|
||||
.feature = VOP2_VP_FEATURE_OUTPUT_10BIT,
|
||||
.gamma_lut_len = 1024,
|
||||
.cubic_lut_len = 9 * 9 * 9, /* 9x9x9 */
|
||||
.max_output = { 4096, 2304 },
|
||||
/* hdr2sdr sdr2hdr hdr2hdr sdr2sdr */
|
||||
.pre_scan_max_dly = { 76, 65, 65, 54 },
|
||||
.offset = 0xc00,
|
||||
}, {
|
||||
.id = 1,
|
||||
.feature = VOP2_VP_FEATURE_OUTPUT_10BIT,
|
||||
.gamma_lut_len = 1024,
|
||||
.cubic_lut_len = 729, /* 9x9x9 */
|
||||
.max_output = { 4096, 2304 },
|
||||
.pre_scan_max_dly = { 76, 65, 65, 54 },
|
||||
.offset = 0xd00,
|
||||
}, {
|
||||
.id = 2,
|
||||
.feature = VOP2_VP_FEATURE_OUTPUT_10BIT,
|
||||
.gamma_lut_len = 1024,
|
||||
.cubic_lut_len = 17 * 17 * 17, /* 17x17x17 */
|
||||
.max_output = { 4096, 2304 },
|
||||
.pre_scan_max_dly = { 52, 52, 52, 52 },
|
||||
.offset = 0xe00,
|
||||
}, {
|
||||
.id = 3,
|
||||
.gamma_lut_len = 1024,
|
||||
.max_output = { 2048, 1536 },
|
||||
.pre_scan_max_dly = { 52, 52, 52, 52 },
|
||||
.offset = 0xf00,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* rk3588 vop with 4 cluster, 4 esmart win.
|
||||
* Every cluster can work as 4K win or split into two win.
|
||||
* All win in cluster support AFBCD.
|
||||
*
|
||||
* Every esmart win and smart win support 4 Multi-region.
|
||||
*
|
||||
* Scale filter mode:
|
||||
*
|
||||
* * Cluster: bicubic for horizontal scale up, others use bilinear
|
||||
* * ESmart:
|
||||
* * nearest-neighbor/bilinear/bicubic for scale up
|
||||
* * nearest-neighbor/bilinear/average for scale down
|
||||
*
|
||||
* AXI Read ID assignment:
|
||||
* Two AXI bus:
|
||||
* AXI0 is a read/write bus with a higher performance.
|
||||
* AXI1 is a read only bus.
|
||||
*
|
||||
* Every window on a AXI bus must assigned two unique
|
||||
* read id(yrgb_id/uv_id, valid id are 0x1~0xe).
|
||||
*
|
||||
* AXI0:
|
||||
* Cluster0/1, Esmart0/1, WriteBack
|
||||
*
|
||||
* AXI 1:
|
||||
* Cluster2/3, Esmart2/3
|
||||
*
|
||||
*/
|
||||
static const struct vop2_win_data rk3588_vop_win_data[] = {
|
||||
{
|
||||
.name = "Cluster0-win0",
|
||||
.phys_id = ROCKCHIP_VOP2_CLUSTER0,
|
||||
.base = 0x1000,
|
||||
.formats = formats_cluster,
|
||||
.nformats = ARRAY_SIZE(formats_cluster),
|
||||
.format_modifiers = format_modifiers_afbc,
|
||||
.layer_sel_id = 0,
|
||||
.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
|
||||
DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
|
||||
.max_upscale_factor = 4,
|
||||
.max_downscale_factor = 4,
|
||||
.dly = { 4, 26, 29 },
|
||||
.type = DRM_PLANE_TYPE_PRIMARY,
|
||||
.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
|
||||
}, {
|
||||
.name = "Cluster1-win0",
|
||||
.phys_id = ROCKCHIP_VOP2_CLUSTER1,
|
||||
.base = 0x1200,
|
||||
.formats = formats_cluster,
|
||||
.nformats = ARRAY_SIZE(formats_cluster),
|
||||
.format_modifiers = format_modifiers_afbc,
|
||||
.layer_sel_id = 1,
|
||||
.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
|
||||
DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
|
||||
.type = DRM_PLANE_TYPE_PRIMARY,
|
||||
.max_upscale_factor = 4,
|
||||
.max_downscale_factor = 4,
|
||||
.dly = { 4, 26, 29 },
|
||||
.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
|
||||
}, {
|
||||
.name = "Cluster2-win0",
|
||||
.phys_id = ROCKCHIP_VOP2_CLUSTER2,
|
||||
.base = 0x1400,
|
||||
.formats = formats_cluster,
|
||||
.nformats = ARRAY_SIZE(formats_cluster),
|
||||
.format_modifiers = format_modifiers_afbc,
|
||||
.layer_sel_id = 4,
|
||||
.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
|
||||
DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
|
||||
.type = DRM_PLANE_TYPE_PRIMARY,
|
||||
.max_upscale_factor = 4,
|
||||
.max_downscale_factor = 4,
|
||||
.dly = { 4, 26, 29 },
|
||||
.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
|
||||
}, {
|
||||
.name = "Cluster3-win0",
|
||||
.phys_id = ROCKCHIP_VOP2_CLUSTER3,
|
||||
.base = 0x1600,
|
||||
.formats = formats_cluster,
|
||||
.nformats = ARRAY_SIZE(formats_cluster),
|
||||
.format_modifiers = format_modifiers_afbc,
|
||||
.layer_sel_id = 5,
|
||||
.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
|
||||
DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
|
||||
.type = DRM_PLANE_TYPE_PRIMARY,
|
||||
.max_upscale_factor = 4,
|
||||
.max_downscale_factor = 4,
|
||||
.dly = { 4, 26, 29 },
|
||||
.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
|
||||
}, {
|
||||
.name = "Esmart0-win0",
|
||||
.phys_id = ROCKCHIP_VOP2_ESMART0,
|
||||
.formats = formats_esmart,
|
||||
.nformats = ARRAY_SIZE(formats_esmart),
|
||||
.format_modifiers = format_modifiers,
|
||||
.base = 0x1800,
|
||||
.layer_sel_id = 2,
|
||||
.supported_rotations = DRM_MODE_REFLECT_Y,
|
||||
.type = DRM_PLANE_TYPE_OVERLAY,
|
||||
.max_upscale_factor = 8,
|
||||
.max_downscale_factor = 8,
|
||||
.dly = { 23, 45, 48 },
|
||||
}, {
|
||||
.name = "Esmart1-win0",
|
||||
.phys_id = ROCKCHIP_VOP2_ESMART1,
|
||||
.formats = formats_esmart,
|
||||
.nformats = ARRAY_SIZE(formats_esmart),
|
||||
.format_modifiers = format_modifiers,
|
||||
.base = 0x1a00,
|
||||
.layer_sel_id = 3,
|
||||
.supported_rotations = DRM_MODE_REFLECT_Y,
|
||||
.type = DRM_PLANE_TYPE_OVERLAY,
|
||||
.max_upscale_factor = 8,
|
||||
.max_downscale_factor = 8,
|
||||
.dly = { 23, 45, 48 },
|
||||
}, {
|
||||
.name = "Esmart2-win0",
|
||||
.phys_id = ROCKCHIP_VOP2_ESMART2,
|
||||
.base = 0x1c00,
|
||||
.formats = formats_esmart,
|
||||
.nformats = ARRAY_SIZE(formats_esmart),
|
||||
.format_modifiers = format_modifiers,
|
||||
.layer_sel_id = 6,
|
||||
.supported_rotations = DRM_MODE_REFLECT_Y,
|
||||
.type = DRM_PLANE_TYPE_OVERLAY,
|
||||
.max_upscale_factor = 8,
|
||||
.max_downscale_factor = 8,
|
||||
.dly = { 23, 45, 48 },
|
||||
}, {
|
||||
.name = "Esmart3-win0",
|
||||
.phys_id = ROCKCHIP_VOP2_ESMART3,
|
||||
.formats = formats_esmart,
|
||||
.nformats = ARRAY_SIZE(formats_esmart),
|
||||
.format_modifiers = format_modifiers,
|
||||
.base = 0x1e00,
|
||||
.layer_sel_id = 7,
|
||||
.supported_rotations = DRM_MODE_REFLECT_Y,
|
||||
.type = DRM_PLANE_TYPE_OVERLAY,
|
||||
.max_upscale_factor = 8,
|
||||
.max_downscale_factor = 8,
|
||||
.dly = { 23, 45, 48 },
|
||||
},
|
||||
};
|
||||
|
||||
static const struct vop2_data rk3566_vop = {
|
||||
.feature = VOP2_FEATURE_HAS_SYS_GRF,
|
||||
.nr_vps = 3,
|
||||
.max_input = { 4096, 2304 },
|
||||
.max_output = { 4096, 2304 },
|
||||
@ -247,6 +452,7 @@ static const struct vop2_data rk3566_vop = {
|
||||
};
|
||||
|
||||
static const struct vop2_data rk3568_vop = {
|
||||
.feature = VOP2_FEATURE_HAS_SYS_GRF,
|
||||
.nr_vps = 3,
|
||||
.max_input = { 4096, 2304 },
|
||||
.max_output = { 4096, 2304 },
|
||||
@ -256,6 +462,18 @@ static const struct vop2_data rk3568_vop = {
|
||||
.soc_id = 3568,
|
||||
};
|
||||
|
||||
static const struct vop2_data rk3588_vop = {
|
||||
.feature = VOP2_FEATURE_HAS_SYS_GRF | VOP2_FEATURE_HAS_VO1_GRF |
|
||||
VOP2_FEATURE_HAS_VOP_GRF | VOP2_FEATURE_HAS_SYS_PMU,
|
||||
.nr_vps = 4,
|
||||
.max_input = { 4096, 4320 },
|
||||
.max_output = { 4096, 4320 },
|
||||
.vp = rk3588_vop_video_ports,
|
||||
.win = rk3588_vop_win_data,
|
||||
.win_size = ARRAY_SIZE(rk3588_vop_win_data),
|
||||
.soc_id = 3588,
|
||||
};
|
||||
|
||||
static const struct of_device_id vop2_dt_match[] = {
|
||||
{
|
||||
.compatible = "rockchip,rk3566-vop",
|
||||
@ -263,6 +481,9 @@ static const struct of_device_id vop2_dt_match[] = {
|
||||
}, {
|
||||
.compatible = "rockchip,rk3568-vop",
|
||||
.data = &rk3568_vop,
|
||||
}, {
|
||||
.compatible = "rockchip,rk3588-vop",
|
||||
.data = &rk3588_vop
|
||||
}, {
|
||||
},
|
||||
};
|
||||
|
@ -672,11 +672,21 @@ vc4_hdmi_connector_duplicate_state(struct drm_connector *connector)
|
||||
return &new_state->base;
|
||||
}
|
||||
|
||||
static void vc4_hdmi_connector_destroy_state(struct drm_connector *connector,
|
||||
struct drm_connector_state *state)
|
||||
{
|
||||
struct vc4_hdmi_connector_state *vc4_state =
|
||||
conn_state_to_vc4_hdmi_conn_state(state);
|
||||
|
||||
__drm_atomic_helper_connector_destroy_state(state);
|
||||
kfree(vc4_state);
|
||||
}
|
||||
|
||||
static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.reset = vc4_hdmi_connector_reset,
|
||||
.atomic_duplicate_state = vc4_hdmi_connector_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
.atomic_destroy_state = vc4_hdmi_connector_destroy_state,
|
||||
.atomic_get_property = vc4_hdmi_connector_get_property,
|
||||
.atomic_set_property = vc4_hdmi_connector_set_property,
|
||||
};
|
||||
|
@ -30,17 +30,25 @@ static const struct drm_connector_funcs vkms_wb_connector_funcs = {
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
};
|
||||
|
||||
static int vkms_wb_encoder_atomic_check(struct drm_encoder *encoder,
|
||||
struct drm_crtc_state *crtc_state,
|
||||
struct drm_connector_state *conn_state)
|
||||
static int vkms_wb_atomic_check(struct drm_connector *connector,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_connector_state *conn_state =
|
||||
drm_atomic_get_new_connector_state(state, connector);
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_framebuffer *fb;
|
||||
const struct drm_display_mode *mode = &crtc_state->mode;
|
||||
const struct drm_display_mode *mode;
|
||||
int ret;
|
||||
|
||||
if (!conn_state->writeback_job || !conn_state->writeback_job->fb)
|
||||
return 0;
|
||||
|
||||
if (!conn_state->crtc)
|
||||
return 0;
|
||||
|
||||
crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
|
||||
mode = &crtc_state->mode;
|
||||
|
||||
fb = conn_state->writeback_job->fb;
|
||||
if (fb->width != mode->hdisplay || fb->height != mode->vdisplay) {
|
||||
DRM_DEBUG_KMS("Invalid framebuffer size %ux%u\n",
|
||||
@ -48,17 +56,13 @@ static int vkms_wb_encoder_atomic_check(struct drm_encoder *encoder,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = drm_atomic_helper_check_wb_encoder_state(encoder, conn_state);
|
||||
ret = drm_atomic_helper_check_wb_connector_state(connector, state);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_encoder_helper_funcs vkms_wb_encoder_helper_funcs = {
|
||||
.atomic_check = vkms_wb_encoder_atomic_check,
|
||||
};
|
||||
|
||||
static int vkms_wb_connector_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
@ -161,6 +165,7 @@ static const struct drm_connector_helper_funcs vkms_wb_conn_helper_funcs = {
|
||||
.prepare_writeback_job = vkms_wb_prepare_job,
|
||||
.cleanup_writeback_job = vkms_wb_cleanup_job,
|
||||
.atomic_commit = vkms_wb_atomic_commit,
|
||||
.atomic_check = vkms_wb_atomic_check,
|
||||
};
|
||||
|
||||
int vkms_enable_writeback_connector(struct vkms_device *vkmsdev)
|
||||
@ -171,7 +176,7 @@ int vkms_enable_writeback_connector(struct vkms_device *vkmsdev)
|
||||
|
||||
return drm_writeback_connector_init(&vkmsdev->drm, wb,
|
||||
&vkms_wb_connector_funcs,
|
||||
&vkms_wb_encoder_helper_funcs,
|
||||
NULL,
|
||||
vkms_wb_formats,
|
||||
ARRAY_SIZE(vkms_wb_formats),
|
||||
1);
|
||||
|
@ -40,7 +40,7 @@ config TYPEC_MUX_NB7VPQ904M
|
||||
tristate "On Semiconductor NB7VPQ904M Type-C redriver driver"
|
||||
depends on I2C
|
||||
depends on DRM || DRM=n
|
||||
select DRM_AUX_BRIDGE if DRM_BRIDGE
|
||||
select DRM_AUX_BRIDGE if DRM_BRIDGE && OF
|
||||
select REGMAP_I2C
|
||||
help
|
||||
Say Y or M if your system has a On Semiconductor NB7VPQ904M Type-C
|
||||
|
@ -80,7 +80,7 @@ config TYPEC_QCOM_PMIC
|
||||
tristate "Qualcomm PMIC USB Type-C Port Controller Manager driver"
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
depends on DRM || DRM=n
|
||||
select DRM_AUX_HPD_BRIDGE if DRM_BRIDGE
|
||||
select DRM_AUX_HPD_BRIDGE if DRM_BRIDGE && OF
|
||||
help
|
||||
A Type-C port and Power Delivery driver which aggregates two
|
||||
discrete pieces of silicon in the PM8150b PMIC block: the
|
||||
|
@ -26,7 +26,7 @@ void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status sta
|
||||
static inline struct device *drm_dp_hpd_bridge_register(struct device *parent,
|
||||
struct device_node *np)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status status)
|
||||
|
@ -49,9 +49,8 @@ struct drm_private_state;
|
||||
|
||||
int drm_atomic_helper_check_modeset(struct drm_device *dev,
|
||||
struct drm_atomic_state *state);
|
||||
int
|
||||
drm_atomic_helper_check_wb_encoder_state(struct drm_encoder *encoder,
|
||||
struct drm_connector_state *conn_state);
|
||||
int drm_atomic_helper_check_wb_connector_state(struct drm_connector *connector,
|
||||
struct drm_atomic_state *state);
|
||||
int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state,
|
||||
const struct drm_crtc_state *crtc_state,
|
||||
int min_scale,
|
||||
|
@ -134,7 +134,7 @@ struct drm_crtc_helper_funcs {
|
||||
* Since this function is both called from the check phase of an atomic
|
||||
* commit, and the mode validation in the probe paths it is not allowed
|
||||
* to look at anything else but the passed-in mode, and validate it
|
||||
* against configuration-invariant hardward constraints. Any further
|
||||
* against configuration-invariant hardware constraints. Any further
|
||||
* limits which depend upon the configuration can only be checked in
|
||||
* @mode_fixup or @atomic_check.
|
||||
*
|
||||
@ -550,7 +550,7 @@ struct drm_encoder_helper_funcs {
|
||||
* Since this function is both called from the check phase of an atomic
|
||||
* commit, and the mode validation in the probe paths it is not allowed
|
||||
* to look at anything else but the passed-in mode, and validate it
|
||||
* against configuration-invariant hardward constraints. Any further
|
||||
* against configuration-invariant hardware constraints. Any further
|
||||
* limits which depend upon the configuration can only be checked in
|
||||
* @mode_fixup or @atomic_check.
|
||||
*
|
||||
@ -1474,7 +1474,7 @@ struct drm_mode_config_helper_funcs {
|
||||
* swapped into the various state pointers. The passed in state
|
||||
* therefore contains copies of the old/previous state. This hook should
|
||||
* commit the new state into hardware. Note that the helpers have
|
||||
* already waited for preceeding atomic commits and fences, but drivers
|
||||
* already waited for preceding atomic commits and fences, but drivers
|
||||
* can add more waiting calls at the start of their implementation, e.g.
|
||||
* to wait for driver-internal request for implicit syncing, before
|
||||
* starting to commit the update to the hardware.
|
||||
|
@ -10,5 +10,9 @@
|
||||
#define ROCKCHIP_VOP2_EP_LVDS0 5
|
||||
#define ROCKCHIP_VOP2_EP_MIPI1 6
|
||||
#define ROCKCHIP_VOP2_EP_LVDS1 7
|
||||
#define ROCKCHIP_VOP2_EP_HDMI1 8
|
||||
#define ROCKCHIP_VOP2_EP_EDP1 9
|
||||
#define ROCKCHIP_VOP2_EP_DP0 10
|
||||
#define ROCKCHIP_VOP2_EP_DP1 11
|
||||
|
||||
#endif /* __DT_BINDINGS_ROCKCHIP_VOP2_H */
|
||||
|
@ -54,7 +54,7 @@ extern "C" {
|
||||
* Format modifiers may change any property of the buffer, including the number
|
||||
* of planes and/or the required allocation size. Format modifiers are
|
||||
* vendor-namespaced, and as such the relationship between a fourcc code and a
|
||||
* modifier is specific to the modifer being used. For example, some modifiers
|
||||
* modifier is specific to the modifier being used. For example, some modifiers
|
||||
* may preserve meaning - such as number of planes - from the fourcc code,
|
||||
* whereas others may not.
|
||||
*
|
||||
@ -79,7 +79,7 @@ extern "C" {
|
||||
* format.
|
||||
* - Higher-level programs interfacing with KMS/GBM/EGL/Vulkan/etc: these users
|
||||
* see modifiers as opaque tokens they can check for equality and intersect.
|
||||
* These users musn't need to know to reason about the modifier value
|
||||
* These users mustn't need to know to reason about the modifier value
|
||||
* (i.e. they are not expected to extract information out of the modifier).
|
||||
*
|
||||
* Vendors should document their modifier usage in as much detail as
|
||||
@ -540,7 +540,7 @@ extern "C" {
|
||||
* This is a tiled layout using 4Kb tiles in row-major layout.
|
||||
* Within the tile pixels are laid out in 16 256 byte units / sub-tiles which
|
||||
* are arranged in four groups (two wide, two high) with column-major layout.
|
||||
* Each group therefore consits out of four 256 byte units, which are also laid
|
||||
* Each group therefore consists out of four 256 byte units, which are also laid
|
||||
* out as 2x2 column-major.
|
||||
* 256 byte units are made out of four 64 byte blocks of pixels, producing
|
||||
* either a square block or a 2:1 unit.
|
||||
@ -1103,7 +1103,7 @@ drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier)
|
||||
*/
|
||||
|
||||
/*
|
||||
* The top 4 bits (out of the 56 bits alloted for specifying vendor specific
|
||||
* The top 4 bits (out of the 56 bits allotted for specifying vendor specific
|
||||
* modifiers) denote the category for modifiers. Currently we have three
|
||||
* categories of modifiers ie AFBC, MISC and AFRC. We can have a maximum of
|
||||
* sixteen different categories.
|
||||
@ -1419,7 +1419,7 @@ drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier)
|
||||
* Amlogic FBC Memory Saving mode
|
||||
*
|
||||
* Indicates the storage is packed when pixel size is multiple of word
|
||||
* boudaries, i.e. 8bit should be stored in this mode to save allocation
|
||||
* boundaries, i.e. 8bit should be stored in this mode to save allocation
|
||||
* memory.
|
||||
*
|
||||
* This mode reduces body layout to 3072 bytes per 64x32 superblock with
|
||||
|
@ -36,10 +36,10 @@ extern "C" {
|
||||
/**
|
||||
* DOC: overview
|
||||
*
|
||||
* DRM exposes many UAPI and structure definition to have a consistent
|
||||
* and standardized interface with user.
|
||||
* DRM exposes many UAPI and structure definitions to have a consistent
|
||||
* and standardized interface with users.
|
||||
* Userspace can refer to these structure definitions and UAPI formats
|
||||
* to communicate to driver
|
||||
* to communicate to drivers.
|
||||
*/
|
||||
|
||||
#define DRM_CONNECTOR_NAME_LEN 32
|
||||
@ -540,7 +540,7 @@ struct drm_mode_get_connector {
|
||||
/* the PROP_ATOMIC flag is used to hide properties from userspace that
|
||||
* is not aware of atomic properties. This is mostly to work around
|
||||
* older userspace (DDX drivers) that read/write each prop they find,
|
||||
* witout being aware that this could be triggering a lengthy modeset.
|
||||
* without being aware that this could be triggering a lengthy modeset.
|
||||
*/
|
||||
#define DRM_MODE_PROP_ATOMIC 0x80000000
|
||||
|
||||
@ -664,7 +664,7 @@ struct drm_mode_fb_cmd {
|
||||
};
|
||||
|
||||
#define DRM_MODE_FB_INTERLACED (1<<0) /* for interlaced framebuffers */
|
||||
#define DRM_MODE_FB_MODIFIERS (1<<1) /* enables ->modifer[] */
|
||||
#define DRM_MODE_FB_MODIFIERS (1<<1) /* enables ->modifier[] */
|
||||
|
||||
/**
|
||||
* struct drm_mode_fb_cmd2 - Frame-buffer metadata.
|
||||
@ -881,8 +881,8 @@ struct hdr_metadata_infoframe {
|
||||
* These are coded as unsigned 16-bit values in units of
|
||||
* 0.00002, where 0x0000 represents zero and 0xC350
|
||||
* represents 1.0000.
|
||||
* @display_primaries.x: X cordinate of color primary.
|
||||
* @display_primaries.y: Y cordinate of color primary.
|
||||
* @display_primaries.x: X coordinate of color primary.
|
||||
* @display_primaries.y: Y coordinate of color primary.
|
||||
*/
|
||||
struct {
|
||||
__u16 x, y;
|
||||
@ -892,8 +892,8 @@ struct hdr_metadata_infoframe {
|
||||
* These are coded as unsigned 16-bit values in units of
|
||||
* 0.00002, where 0x0000 represents zero and 0xC350
|
||||
* represents 1.0000.
|
||||
* @white_point.x: X cordinate of whitepoint of color primary.
|
||||
* @white_point.y: Y cordinate of whitepoint of color primary.
|
||||
* @white_point.x: X coordinate of whitepoint of color primary.
|
||||
* @white_point.y: Y coordinate of whitepoint of color primary.
|
||||
*/
|
||||
struct {
|
||||
__u16 x, y;
|
||||
|
Loading…
Reference in New Issue
Block a user