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:
Dave Airlie 2023-12-19 17:07:25 +10:00
commit 48b272853e
56 changed files with 2568 additions and 386 deletions

View File

@ -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>;
};
};
};
};

View File

@ -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>;
};
};
};
};
...

View File

@ -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

View File

@ -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

View File

@ -27,6 +27,7 @@ properties:
compatible:
items:
- enum:
- anbernic,rg-arc-panel
- densitron,dmt028vghmcmi-1a
- elida,kd50t048a
- techstar,ts8550b

View File

@ -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:

View File

@ -474,6 +474,8 @@ patternProperties:
description: Fairphone B.V.
"^faraday,.*":
description: Faraday Technology Corporation
"^fascontek,.*":
description: Fascontek
"^fastrax,.*":
description: Fastrax Oy
"^fcs,.*":

View File

@ -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

View File

@ -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 ARMs 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 ARMs 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
------------

View File

@ -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

View File

@ -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>

View File

@ -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[] = {

View File

@ -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

View File

@ -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/

View File

@ -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

View File

@ -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/.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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"),

View 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");

View File

@ -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 = &ltk035c5444t_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,
};

View File

@ -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,

View File

@ -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 },

View 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");

View File

@ -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)

View File

@ -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)
{

View File

@ -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

View File

@ -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)

View File

@ -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"

View File

@ -18,7 +18,6 @@
#include "rk3066_hdmi.h"
#include "rockchip_drm_drv.h"
#include "rockchip_drm_vop.h"
#define DEFAULT_PLLA_RATE 30000000

View File

@ -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;

View File

@ -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,

View File

@ -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);
/*
* 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");

View File

@ -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)

View File

@ -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

View File

@ -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 {

View File

@ -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
}, {
},
};

View File

@ -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,
};

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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,

View File

@ -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.

View File

@ -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 */

View File

@ -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

View File

@ -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;