aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/display/panel/boe,tv101wum-nl6.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/panel/himax,hx83102.yaml77
-rw-r--r--Documentation/devicetree/bindings/display/panel/panel-edp-legacy.yaml127
-rw-r--r--Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml6
-rw-r--r--Documentation/devicetree/bindings/display/panel/panel-simple.yaml56
-rw-r--r--Documentation/devicetree/bindings/display/panel/samsung,atna33xc20.yaml95
-rw-r--r--Documentation/devicetree/bindings/display/panel/sharp,ld-d5116z01b.yaml30
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.yaml4
-rw-r--r--Documentation/gpu/drm-internals.rst10
-rw-r--r--Documentation/gpu/drm-kms-helpers.rst12
-rw-r--r--Documentation/gpu/todo.rst31
-rw-r--r--MAINTAINERS2
-rw-r--r--drivers/accel/ivpu/Makefile11
-rw-r--r--drivers/accel/ivpu/ivpu_debugfs.c52
-rw-r--r--drivers/accel/ivpu/ivpu_drv.c76
-rw-r--r--drivers/accel/ivpu/ivpu_drv.h56
-rw-r--r--drivers/accel/ivpu/ivpu_fw.c30
-rw-r--r--drivers/accel/ivpu/ivpu_fw.h2
-rw-r--r--drivers/accel/ivpu/ivpu_gem.h11
-rw-r--r--drivers/accel/ivpu/ivpu_hw.c313
-rw-r--r--drivers/accel/ivpu/ivpu_hw.h197
-rw-r--r--drivers/accel/ivpu/ivpu_hw_37xx.c1065
-rw-r--r--drivers/accel/ivpu/ivpu_hw_37xx_reg.h72
-rw-r--r--drivers/accel/ivpu/ivpu_hw_40xx.c1250
-rw-r--r--drivers/accel/ivpu/ivpu_hw_40xx_reg.h94
-rw-r--r--drivers/accel/ivpu/ivpu_hw_btrs.c881
-rw-r--r--drivers/accel/ivpu/ivpu_hw_btrs.h46
-rw-r--r--drivers/accel/ivpu/ivpu_hw_btrs_lnl_reg.h108
-rw-r--r--drivers/accel/ivpu/ivpu_hw_btrs_mtl_reg.h83
-rw-r--r--drivers/accel/ivpu/ivpu_hw_ip.c1174
-rw-r--r--drivers/accel/ivpu/ivpu_hw_ip.h36
-rw-r--r--drivers/accel/ivpu/ivpu_ipc.c17
-rw-r--r--drivers/accel/ivpu/ivpu_ipc.h4
-rw-r--r--drivers/accel/ivpu/ivpu_job.c297
-rw-r--r--drivers/accel/ivpu/ivpu_job.h2
-rw-r--r--drivers/accel/ivpu/ivpu_jsm_msg.c259
-rw-r--r--drivers/accel/ivpu/ivpu_jsm_msg.h20
-rw-r--r--drivers/accel/ivpu/ivpu_mmu.c12
-rw-r--r--drivers/accel/ivpu/ivpu_ms.c309
-rw-r--r--drivers/accel/ivpu/ivpu_ms.h36
-rw-r--r--drivers/accel/ivpu/ivpu_pm.c5
-rw-r--r--drivers/accel/ivpu/ivpu_sysfs.c58
-rw-r--r--drivers/accel/ivpu/ivpu_sysfs.h13
-rw-r--r--drivers/accel/ivpu/vpu_jsm_api.h14
-rw-r--r--drivers/dma-buf/dma-fence-array.c10
-rw-r--r--drivers/gpu/drm/Makefile6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v10_0.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v11_0.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v6_0.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v8_0.c4
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c2
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_crtc.c49
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_drv.c8
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_kms.h1
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c4
-rw-r--r--drivers/gpu/drm/ast/ast_drv.c4
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/Kconfig2
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7511_drv.c5
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix-anx6345.c20
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c28
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix_dp_core.c5
-rw-r--r--drivers/gpu/drm/bridge/analogix/anx7625.c36
-rw-r--r--drivers/gpu/drm/bridge/analogix/anx7625.h10
-rw-r--r--drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c5
-rw-r--r--drivers/gpu/drm/bridge/imx/imx-ldb-helper.c5
-rw-r--r--drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c5
-rw-r--r--drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c5
-rw-r--r--drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c5
-rw-r--r--drivers/gpu/drm/bridge/ite-it6505.c78
-rw-r--r--drivers/gpu/drm/bridge/lontium-lt9611uxc.c5
-rw-r--r--drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c5
-rw-r--r--drivers/gpu/drm/bridge/nxp-ptn3460.c5
-rw-r--r--drivers/gpu/drm/bridge/panel.c5
-rw-r--r--drivers/gpu/drm/bridge/simple-bridge.c5
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c5
-rw-r--r--drivers/gpu/drm/bridge/tc358767.c23
-rw-r--r--drivers/gpu/drm/bridge/ti-tfp410.c5
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt13
-rw-r--r--drivers/gpu/drm/drm_bridge.c5
-rw-r--r--drivers/gpu/drm/drm_crtc_internal.h2
-rw-r--r--drivers/gpu/drm/drm_debugfs.c4
-rw-r--r--drivers/gpu/drm/drm_drv.c6
-rw-r--r--drivers/gpu/drm/drm_edid.c61
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c11
-rw-r--r--drivers/gpu/drm/drm_fbdev_dma.c66
-rw-r--r--drivers/gpu/drm/drm_fbdev_shmem.c317
-rw-r--r--drivers/gpu/drm/drm_fbdev_ttm.c (renamed from drivers/gpu/drm/drm_fbdev_generic.c)80
-rw-r--r--drivers/gpu/drm/drm_ioctl.c5
-rw-r--r--drivers/gpu/drm/drm_mipi_dsi.c322
-rw-r--r--drivers/gpu/drm/drm_probe_helper.c8
-rw-r--r--drivers/gpu/drm/drm_sysfs.c24
-rw-r--r--drivers/gpu/drm/gma500/cdv_intel_dp.c2
-rw-r--r--drivers/gpu/drm/gud/gud_drv.c4
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c4
-rw-r--r--drivers/gpu/drm/hisilicon/kirin/Kconfig2
-rw-r--r--drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c11
-rw-r--r--drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h2
-rw-r--r--drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h2
-rw-r--r--drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c4
-rw-r--r--drivers/gpu/drm/hyperv/hyperv_drm_drv.c4
-rw-r--r--drivers/gpu/drm/i2c/tda998x_drv.c19
-rw-r--r--drivers/gpu/drm/imx/lcdc/imx-lcdc.c4
-rw-r--r--drivers/gpu/drm/ingenic/ingenic-drm-drv.c4
-rw-r--r--drivers/gpu/drm/loongson/Kconfig1
-rw-r--r--drivers/gpu/drm/loongson/lsdc_drv.c4
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_drv.c4
-rw-r--r--drivers/gpu/drm/mgag200/Kconfig18
-rw-r--r--drivers/gpu/drm/mgag200/Makefile2
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_ddc.c179
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_ddc.h11
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_drv.c27
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_drv.h18
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_g200.c11
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_g200eh.c11
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_g200eh3.c11
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_g200er.c11
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_g200ev.c11
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_g200ew3.c11
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_g200se.c11
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_g200wb.c11
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_i2c.c129
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_mode.c35
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/disp.c8
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/head.c8
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h6
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c362
-rw-r--r--drivers/gpu/drm/omapdrm/Kconfig2
-rw-r--r--drivers/gpu/drm/omapdrm/omap_gem.c4
-rw-r--r--drivers/gpu/drm/panel/Kconfig9
-rw-r--r--drivers/gpu/drm/panel/Makefile1
-rw-r--r--drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c2734
-rw-r--r--drivers/gpu/drm/panel/panel-edp.c2
-rw-r--r--drivers/gpu/drm/panel/panel-himax-hx83102.c706
-rw-r--r--drivers/gpu/drm/panel/panel-himax-hx8394.c3
-rw-r--r--drivers/gpu/drm/panel/panel-ilitek-ili9341.c7
-rw-r--r--drivers/gpu/drm/panel/panel-ilitek-ili9882t.c830
-rw-r--r--drivers/gpu/drm/panel/panel-innolux-p079zca.c277
-rw-r--r--drivers/gpu/drm/panel/panel-lg-sw43408.c74
-rw-r--r--drivers/gpu/drm/panel/panel-novatek-nt36672e.c647
-rw-r--r--drivers/gpu/drm/panel/panel-simple.c96
-rw-r--r--drivers/gpu/drm/qxl/qxl_drv.c4
-rw-r--r--drivers/gpu/drm/radeon/atombios_encoders.c10
-rw-r--r--drivers/gpu/drm/radeon/evergreen_hdmi.c5
-rw-r--r--drivers/gpu/drm/radeon/radeon_audio.c13
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c27
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_encoders.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h2
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/Kconfig2
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c4
-rw-r--r--drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.c4
-rw-r--r--drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c4
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.c4
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop2.c2
-rw-r--r--drivers/gpu/drm/solomon/ssd130x.c4
-rw-r--r--drivers/gpu/drm/stm/Kconfig2
-rw-r--r--drivers/gpu/drm/tiny/bochs.c27
-rw-r--r--drivers/gpu/drm/tiny/cirrus.c4
-rw-r--r--drivers/gpu/drm/tiny/gm12u320.c4
-rw-r--r--drivers/gpu/drm/tiny/hx8357d.c4
-rw-r--r--drivers/gpu/drm/tiny/ili9163.c4
-rw-r--r--drivers/gpu/drm/tiny/ili9225.c5
-rw-r--r--drivers/gpu/drm/tiny/ili9341.c4
-rw-r--r--drivers/gpu/drm/tiny/ili9486.c4
-rw-r--r--drivers/gpu/drm/tiny/mi0283qt.c5
-rw-r--r--drivers/gpu/drm/tiny/ofdrm.c4
-rw-r--r--drivers/gpu/drm/tiny/panel-mipi-dbi.c5
-rw-r--r--drivers/gpu/drm/tiny/repaper.c4
-rw-r--r--drivers/gpu/drm/tiny/simpledrm.c4
-rw-r--r--drivers/gpu/drm/tiny/st7586.c5
-rw-r--r--drivers/gpu/drm/tiny/st7735r.c4
-rw-r--r--drivers/gpu/drm/udl/Makefile8
-rw-r--r--drivers/gpu/drm/udl/udl_drv.c4
-rw-r--r--drivers/gpu/drm/udl/udl_drv.h12
-rw-r--r--drivers/gpu/drm/udl/udl_edid.c80
-rw-r--r--drivers/gpu/drm/udl/udl_edid.h15
-rw-r--r--drivers/gpu/drm/udl/udl_modeset.c138
-rw-r--r--drivers/gpu/drm/v3d/v3d_drv.c11
-rw-r--r--drivers/gpu/drm/v3d/v3d_drv.h14
-rw-r--r--drivers/gpu/drm/v3d/v3d_perfmon.c36
-rw-r--r--drivers/gpu/drm/v3d/v3d_performance_counters.h208
-rw-r--r--drivers/gpu/drm/v3d/v3d_sched.c2
-rw-r--r--drivers/gpu/drm/vboxvideo/vbox_drv.c4
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_display.c10
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.c4
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.h2
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_vq.c12
-rw-r--r--drivers/gpu/drm/vkms/vkms_drv.c4
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c4
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c1
-rw-r--r--drivers/gpu/drm/xlnx/zynqmp_disp.c44
-rw-r--r--drivers/gpu/drm/xlnx/zynqmp_dp.c25
-rw-r--r--drivers/gpu/drm/xlnx/zynqmp_dpsub.h1
-rw-r--r--drivers/gpu/drm/xlnx/zynqmp_kms.h4
-rw-r--r--drivers/video/fbdev/core/fb_defio.c82
-rw-r--r--include/drm/drm_connector.h6
-rw-r--r--include/drm/drm_drv.h2
-rw-r--r--include/drm/drm_edid.h4
-rw-r--r--include/drm/drm_fbdev_generic.h15
-rw-r--r--include/drm/drm_fbdev_shmem.h15
-rw-r--r--include/drm/drm_fbdev_ttm.h15
-rw-r--r--include/drm/drm_mipi_dsi.h122
-rw-r--r--include/drm/drm_mode_config.h4
-rw-r--r--include/linux/dma-fence-array.h3
-rw-r--r--include/linux/fb.h1
-rw-r--r--include/uapi/drm/amdgpu_drm.h9
-rw-r--r--include/uapi/drm/drm_mode.h8
-rw-r--r--include/uapi/drm/ivpu_accel.h69
-rw-r--r--include/uapi/drm/v3d_drm.h48
-rw-r--r--lib/fonts/Kconfig20
216 files changed, 9704 insertions, 6281 deletions
diff --git a/Documentation/devicetree/bindings/display/panel/boe,tv101wum-nl6.yaml b/Documentation/devicetree/bindings/display/panel/boe,tv101wum-nl6.yaml
index 9e603cad1348..7a9f49e40e75 100644
--- a/Documentation/devicetree/bindings/display/panel/boe,tv101wum-nl6.yaml
+++ b/Documentation/devicetree/bindings/display/panel/boe,tv101wum-nl6.yaml
@@ -32,8 +32,6 @@ properties:
- innolux,hj110iz-01a
# STARRY 2081101QFH032011-53G 10.1" WUXGA TFT LCD panel
- starry,2081101qfh032011-53g
- # STARRY himax83102-j02 10.51" WUXGA TFT LCD panel
- - starry,himax83102-j02
# STARRY ili9882t 10.51" WUXGA TFT LCD panel
- starry,ili9882t
diff --git a/Documentation/devicetree/bindings/display/panel/himax,hx83102.yaml b/Documentation/devicetree/bindings/display/panel/himax,hx83102.yaml
new file mode 100644
index 000000000000..c649fb085833
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/himax,hx83102.yaml
@@ -0,0 +1,77 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/himax,hx83102.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Himax HX83102 MIPI-DSI LCD panel controller
+
+maintainers:
+ - Cong Yang <[email protected]>
+
+allOf:
+ - $ref: panel-common.yaml#
+
+properties:
+ compatible:
+ items:
+ - enum:
+ # Boe nv110wum-l60 11.0" WUXGA TFT LCD panel
+ - boe,nv110wum-l60
+ # IVO t109nw41 11.0" WUXGA TFT LCD panel
+ - ivo,t109nw41
+ # STARRY himax83102-j02 10.51" WUXGA TFT LCD panel
+ - starry,himax83102-j02
+ - const: himax,hx83102
+
+ reg:
+ description: the virtual channel number of a DSI peripheral
+
+ enable-gpios:
+ description: a GPIO spec for the enable pin
+
+ pp1800-supply:
+ description: core voltage supply
+
+ avdd-supply:
+ description: phandle of the regulator that provides positive voltage
+
+ avee-supply:
+ description: phandle of the regulator that provides negative voltage
+
+ backlight: true
+ port: true
+ rotation: true
+
+required:
+ - compatible
+ - reg
+ - enable-gpios
+ - pp1800-supply
+ - avdd-supply
+ - avee-supply
+
+additionalProperties: false
+
+examples:
+ - |
+ dsi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ panel@0 {
+ compatible = "starry,himax83102-j02", "himax,hx83102";
+ reg = <0>;
+ enable-gpios = <&pio 45 0>;
+ avdd-supply = <&ppvarn_lcd>;
+ avee-supply = <&ppvarp_lcd>;
+ pp1800-supply = <&pp1800_lcd>;
+ backlight = <&backlight_lcd0>;
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&dsi_out>;
+ };
+ };
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/display/panel/panel-edp-legacy.yaml b/Documentation/devicetree/bindings/display/panel/panel-edp-legacy.yaml
new file mode 100644
index 000000000000..9e5864de49e7
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/panel-edp-legacy.yaml
@@ -0,0 +1,127 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/panel-edp-legacy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Legacy eDP panels from before the "edp-panel" compatible
+
+maintainers:
+ - Douglas Anderson <[email protected]>
+
+description: |
+ This binding file is a collection of eDP panels from before the generic
+ "edp-panel" compatible was introduced. It is kept around to support old
+ dts files. The only reason one might add a new panel here instead of using
+ the generic "edp-panel" is if it needed to be used on an eDP controller
+ that doesn't support the generic "edp-panel" compatible, but it should be
+ a strong preference to add the generic "edp-panel" compatible instead.
+
+allOf:
+ - $ref: panel-common.yaml#
+
+properties:
+ compatible:
+ enum:
+ # compatible must be listed in alphabetical order, ordered by compatible.
+ # The description in the comment is mandatory for each compatible.
+
+ # AU Optronics Corporation 10.1" WSVGA TFT LCD panel
+ - auo,b101ean01
+ # AUO B116XAK01 eDP TFT LCD panel
+ - auo,b116xa01
+ # AU Optronics Corporation 13.3" FHD (1920x1080) color TFT-LCD panel
+ - auo,b133han05
+ # AU Optronics Corporation 13.3" FHD (1920x1080) color TFT-LCD panel
+ - auo,b133htn01
+ # AU Optronics Corporation 13.3" WXGA (1366x768) TFT LCD panel
+ - auo,b133xtn01
+ # AU Optronics Corporation 14.0" FHD (1920x1080) color TFT-LCD panel
+ - auo,b140han06
+ # BOE OPTOELECTRONICS TECHNOLOGY 10.1" WXGA TFT LCD panel
+ - boe,nv101wxmn51
+ # BOE NV133FHM-N61 13.3" FHD (1920x1080) TFT LCD Panel
+ - boe,nv110wtm-n61
+ # BOE NV110WTM-N61 11.0" 2160x1440 TFT LCD Panel
+ - boe,nv133fhm-n61
+ # BOE NV133FHM-N62 13.3" FHD (1920x1080) TFT LCD Panel
+ - boe,nv133fhm-n62
+ # BOE NV140FHM-N49 14.0" FHD a-Si FT panel
+ - boe,nv140fhmn49
+ # Innolux Corporation 11.6" WXGA (1366x768) TFT LCD panel
+ - innolux,n116bca-ea1
+ # Innolux Corporation 11.6" WXGA (1366x768) TFT LCD panel
+ - innolux,n116bge
+ # InnoLux 13.3" FHD (1920x1080) eDP TFT LCD panel
+ - innolux,n125hce-gn1
+ # Innolux P120ZDG-BF1 12.02 inch eDP 2K display panel
+ - innolux,p120zdg-bf1
+ # InfoVision Optoelectronics M133NWF4 R0 13.3" FHD (1920x1080) TFT LCD panel
+ - ivo,m133nwf4-r0
+ # King & Display KD116N21-30NV-A010 eDP TFT LCD panel
+ - kingdisplay,kd116n21-30nv-a010
+ # LG LP079QX1-SP0V 7.9" (1536x2048 pixels) TFT LCD panel
+ - lg,lp079qx1-sp0v
+ # LG 9.7" (2048x1536 pixels) TFT LCD panel
+ - lg,lp097qx1-spa1
+ # LG 12.0" (1920x1280 pixels) TFT LCD panel
+ - lg,lp120up1
+ # LG 12.9" (2560x1700 pixels) TFT LCD panel
+ - lg,lp129qe
+ # NewEast Optoelectronics CO., LTD WJFH116008A eDP TFT LCD panel
+ - neweast,wjfh116008a
+ # Samsung 12.2" (2560x1600 pixels) TFT LCD panel
+ - samsung,lsn122dl01-c01
+ # Samsung Electronics 14" WXGA (1366x768) TFT LCD panel
+ - samsung,ltn140at29-301
+ # Sharp LD-D5116Z01B 12.3" WUXGA+ eDP panel
+ - sharp,ld-d5116z01b
+ # Sharp 12.3" (2400x1600 pixels) TFT LCD panel
+ - sharp,lq123p1jx31
+ # Sharp 14" (1920x1080 pixels) TFT LCD panel
+ - sharp,lq140m1jw46
+ # Starry 12.2" (1920x1200 pixels) TFT LCD panel
+ - starry,kr122ea0sra
+
+ backlight: true
+ ddc-i2c-bus: true
+ enable-gpios: true
+ panel-timing: true
+ port: true
+ power-supply: true
+ no-hpd: true
+ hpd-gpios: true
+
+additionalProperties: false
+
+required:
+ - compatible
+ - power-supply
+
+examples:
+ - |
+ panel: panel {
+ compatible = "innolux,n116bge";
+ power-supply = <&panel_regulator>;
+ backlight = <&backlight>;
+
+ panel-timing {
+ clock-frequency = <74250000>;
+ hactive = <1366>;
+ hfront-porch = <136>;
+ hback-porch = <60>;
+ hsync-len = <30>;
+ hsync-active = <0>;
+ vactive = <768>;
+ vfront-porch = <8>;
+ vback-porch = <12>;
+ vsync-len = <12>;
+ vsync-active = <0>;
+ };
+
+ port {
+ panel_in_edp: endpoint {
+ remote-endpoint = <&edp_out_panel>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml
index 716ece5f3978..e78160d1aa24 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml
+++ b/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml
@@ -41,6 +41,12 @@ properties:
- auo,g190ean01
# Kaohsiung Opto-Electronics Inc. 10.1" WUXGA (1920 x 1200) LVDS TFT LCD panel
- koe,tx26d202vm0bwa
+ # Lincoln Technology Solutions, LCD185-101CT 10.1" TFT 1920x1200
+ - lincolntech,lcd185-101ct
+ # Microtips Technology MF-101HIEBCAF0 10.1" WUXGA (1920x1200) TFT LCD panel
+ - microtips,mf-101hiebcaf0
+ # Microtips Technology MF-103HIEB0GA0 10.25" 1920x720 TFT LCD panel
+ - microtips,mf-103hieb0ga0
# NLT Technologies, Ltd. 15.6" FHD (1920x1080) LVDS TFT LCD panel
- nlt,nl192108ac18-02d
diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
index 5067f5c0a272..54651a5c9a8d 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
+++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
@@ -41,22 +41,10 @@ properties:
- ampire,am800600p5tmqw-tb8h
# AU Optronics Corporation 10.1" WSVGA TFT LCD panel
- auo,b101aw03
- # AU Optronics Corporation 10.1" WSVGA TFT LCD panel
- - auo,b101ean01
# AU Optronics Corporation 10.1" WXGA TFT LCD panel
- auo,b101xtn01
- # AUO B116XAK01 eDP TFT LCD panel
- - auo,b116xa01
# AU Optronics Corporation 11.6" HD (1366x768) color TFT-LCD panel
- auo,b116xw03
- # AU Optronics Corporation 13.3" FHD (1920x1080) color TFT-LCD panel
- - auo,b133han05
- # AU Optronics Corporation 13.3" FHD (1920x1080) color TFT-LCD panel
- - auo,b133htn01
- # AU Optronics Corporation 13.3" WXGA (1366x768) TFT LCD panel
- - auo,b133xtn01
- # AU Optronics Corporation 14.0" FHD (1920x1080) color TFT-LCD panel
- - auo,b140han06
# AU Optronics Corporation 7.0" FHD (800 x 480) TFT LCD panel
- auo,g070vvn01
# AU Optronics Corporation 10.1" (1280x800) color TFT LCD panel
@@ -81,16 +69,6 @@ properties:
- boe,ev121wxm-n10-1850
# BOE HV070WSA-100 7.01" WSVGA TFT LCD panel
- boe,hv070wsa-100
- # BOE OPTOELECTRONICS TECHNOLOGY 10.1" WXGA TFT LCD panel
- - boe,nv101wxmn51
- # BOE NV133FHM-N61 13.3" FHD (1920x1080) TFT LCD Panel
- - boe,nv110wtm-n61
- # BOE NV110WTM-N61 11.0" 2160x1440 TFT LCD Panel
- - boe,nv133fhm-n61
- # BOE NV133FHM-N62 13.3" FHD (1920x1080) TFT LCD Panel
- - boe,nv133fhm-n62
- # BOE NV140FHM-N49 14.0" FHD a-Si FT panel
- - boe,nv140fhmn49
# Crystal Clear Technology CMT430B19N00 4.3" 480x272 TFT-LCD panel
- cct,cmt430b19n00
# CDTech(H.K.) Electronics Limited 4.3" 480x272 color TFT-LCD panel
@@ -172,8 +150,6 @@ properties:
- hannstar,hsd100pxn1
# Hitachi Ltd. Corporation 9" WVGA (800x480) TFT LCD panel
- hit,tx23d38vm0caa
- # InfoVision Optoelectronics M133NWF4 R0 13.3" FHD (1920x1080) TFT LCD panel
- - ivo,m133nwf4-r0
# Innolux AT043TN24 4.3" WQVGA TFT LCD panel
- innolux,at043tn24
# Innolux AT070TN92 7.0" WQVGA TFT LCD panel
@@ -192,22 +168,12 @@ properties:
- innolux,g121x1-l03
# Innolux Corporation 12.1" G121XCE-L01 XGA (1024x768) TFT LCD panel
- innolux,g121xce-l01
- # Innolux Corporation 11.6" WXGA (1366x768) TFT LCD panel
- - innolux,n116bca-ea1
- # Innolux Corporation 11.6" WXGA (1366x768) TFT LCD panel
- - innolux,n116bge
- # InnoLux 13.3" FHD (1920x1080) eDP TFT LCD panel
- - innolux,n125hce-gn1
# InnoLux 15.6" FHD (1920x1080) TFT LCD panel
- innolux,g156hce-l01
# InnoLux 15.6" WXGA TFT LCD panel
- innolux,n156bge-l21
- # Innolux P120ZDG-BF1 12.02 inch eDP 2K display panel
- - innolux,p120zdg-bf1
# Innolux Corporation 7.0" WSVGA (1024x600) TFT LCD panel
- innolux,zj070na-01p
- # King & Display KD116N21-30NV-A010 eDP TFT LCD panel
- - kingdisplay,kd116n21-30nv-a010
# Kaohsiung Opto-Electronics Inc. 5.7" QVGA (320 x 240) TFT LCD panel
- koe,tx14d24vm1bpa
# Kaohsiung Opto-Electronics. TX31D200VM0BAA 12.3" HSXGA LVDS panel
@@ -220,14 +186,6 @@ properties:
- lemaker,bl035-rgb-002
# LG 7" (800x480 pixels) TFT LCD panel
- lg,lb070wv8
- # LG LP079QX1-SP0V 7.9" (1536x2048 pixels) TFT LCD panel
- - lg,lp079qx1-sp0v
- # LG 9.7" (2048x1536 pixels) TFT LCD panel
- - lg,lp097qx1-spa1
- # LG 12.0" (1920x1280 pixels) TFT LCD panel
- - lg,lp120up1
- # LG 12.9" (2560x1700 pixels) TFT LCD panel
- - lg,lp129qe
# Logic Technologies LT161010-2NHC 7" WVGA TFT Cap Touch Module
- logictechno,lt161010-2nhc
# Logic Technologies LT161010-2NHR 7" WVGA TFT Resistive Touch Module
@@ -254,8 +212,6 @@ properties:
- nec,nl4827hc19-05b
# Netron-DY E231732 7.0" WSVGA TFT LCD panel
- netron-dy,e231732
- # NewEast Optoelectronics CO., LTD WJFH116008A eDP TFT LCD panel
- - neweast,wjfh116008a
# Newhaven Display International 480 x 272 TFT LCD panel
- newhaven,nhd-4.3-480272ef-atxl
# New Vision Display 7.0" 800 RGB x 480 TFT LCD panel
@@ -290,16 +246,10 @@ properties:
- rocktech,rk070er9427
# Rocktech Display Ltd. RK043FN48H 4.3" 480x272 LCD-TFT panel
- rocktech,rk043fn48h
- # Samsung 13.3" FHD (1920x1080 pixels) eDP AMOLED panel
- - samsung,atna33xc20
- # Samsung 12.2" (2560x1600 pixels) TFT LCD panel
- - samsung,lsn122dl01-c01
# Samsung Electronics 10.1" WXGA (1280x800) TFT LCD panel
- samsung,ltl101al01
# Samsung Electronics 10.1" WSVGA TFT LCD panel
- samsung,ltn101nt05
- # Samsung Electronics 14" WXGA (1366x768) TFT LCD panel
- - samsung,ltn140at29-301
# Satoz SAT050AT40H12R2 5.0" WVGA TFT LCD panel
- satoz,sat050at40h12r2
# Sharp LQ035Q7DB03 3.5" QVGA TFT LCD panel
@@ -308,18 +258,12 @@ properties:
- sharp,lq070y3dg3b
# Sharp Display Corp. LQ101K1LY04 10.07" WXGA TFT LCD panel
- sharp,lq101k1ly04
- # Sharp 12.3" (2400x1600 pixels) TFT LCD panel
- - sharp,lq123p1jx31
- # Sharp 14" (1920x1080 pixels) TFT LCD panel
- - sharp,lq140m1jw46
# Sharp LS020B1DD01D 2.0" HQVGA TFT LCD panel
- sharp,ls020b1dd01d
# Shelly SCA07010-BFN-LNN 7.0" WVGA TFT LCD panel
- shelly,sca07010-bfn-lnn
# Starry KR070PE2T 7" WVGA TFT LCD panel
- starry,kr070pe2t
- # Starry 12.2" (1920x1200 pixels) TFT LCD panel
- - starry,kr122ea0sra
# Startek KD070WVFPA043-C069A 7" TFT LCD panel
- startek,kd070wvfpa
# Team Source Display Technology TST043015CMHX 4.3" WQVGA TFT LCD panel
diff --git a/Documentation/devicetree/bindings/display/panel/samsung,atna33xc20.yaml b/Documentation/devicetree/bindings/display/panel/samsung,atna33xc20.yaml
new file mode 100644
index 000000000000..765ca155c83a
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/samsung,atna33xc20.yaml
@@ -0,0 +1,95 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/samsung,atna33xc20.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung 13.3" FHD (1920x1080 pixels) eDP AMOLED panel
+
+maintainers:
+ - Douglas Anderson <[email protected]>
+
+allOf:
+ - $ref: panel-common.yaml#
+
+properties:
+ compatible:
+ const: samsung,atna33xc20
+
+ enable-gpios: true
+ port: true
+ power-supply: true
+ no-hpd: true
+ hpd-gpios: true
+
+additionalProperties: false
+
+required:
+ - compatible
+ - enable-gpios
+ - power-supply
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,rpmh.h>
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ bridge@2d {
+ compatible = "ti,sn65dsi86";
+ reg = <0x2d>;
+
+ interrupt-parent = <&tlmm>;
+ interrupts = <10 IRQ_TYPE_LEVEL_HIGH>;
+
+ enable-gpios = <&tlmm 102 GPIO_ACTIVE_HIGH>;
+
+ vpll-supply = <&src_pp1800_s4a>;
+ vccio-supply = <&src_pp1800_s4a>;
+ vcca-supply = <&src_pp1200_l2a>;
+ vcc-supply = <&src_pp1200_l2a>;
+
+ clocks = <&rpmhcc RPMH_LN_BB_CLK2>;
+ clock-names = "refclk";
+
+ no-hpd;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ endpoint {
+ remote-endpoint = <&dsi0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ sn65dsi86_out: endpoint {
+ remote-endpoint = <&panel_in_edp>;
+ };
+ };
+ };
+
+ aux-bus {
+ panel {
+ compatible = "samsung,atna33xc20";
+ enable-gpios = <&tlmm 12 GPIO_ACTIVE_HIGH>;
+ power-supply = <&pp3300_dx_edp>;
+ hpd-gpios = <&sn65dsi86_bridge 2 GPIO_ACTIVE_HIGH>;
+
+ port {
+ panel_in_edp: endpoint {
+ remote-endpoint = <&sn65dsi86_out>;
+ };
+ };
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/display/panel/sharp,ld-d5116z01b.yaml b/Documentation/devicetree/bindings/display/panel/sharp,ld-d5116z01b.yaml
deleted file mode 100644
index fbb647eb33c9..000000000000
--- a/Documentation/devicetree/bindings/display/panel/sharp,ld-d5116z01b.yaml
+++ /dev/null
@@ -1,30 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/display/panel/sharp,ld-d5116z01b.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: Sharp LD-D5116Z01B 12.3" WUXGA+ eDP panel
-
-maintainers:
- - Jeffrey Hugo <[email protected]>
-
-allOf:
- - $ref: panel-common.yaml#
-
-properties:
- compatible:
- const: sharp,ld-d5116z01b
-
- power-supply: true
- backlight: true
- port: true
- no-hpd: true
-
-additionalProperties: false
-
-required:
- - compatible
- - power-supply
-
-...
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index fbf47f0bacf1..51ca841db26e 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -820,6 +820,8 @@ patternProperties:
description: Lichee Pi
"^linaro,.*":
description: Linaro Limited
+ "^lincolntech,.*":
+ description: Lincoln Technology Solutions
"^lineartechnology,.*":
description: Linear Technology
"^linksprite,.*":
@@ -924,6 +926,8 @@ patternProperties:
description: Microsoft Corporation
"^microsys,.*":
description: MicroSys Electronics GmbH
+ "^microtips,.*":
+ description: Microtips Technology USA
"^mikroe,.*":
description: MikroElektronika d.o.o.
"^mikrotik,.*":
diff --git a/Documentation/gpu/drm-internals.rst b/Documentation/gpu/drm-internals.rst
index 335de7fcddee..11d9a5730fb2 100644
--- a/Documentation/gpu/drm-internals.rst
+++ b/Documentation/gpu/drm-internals.rst
@@ -57,8 +57,8 @@ is larger than the driver minor, the DRM_IOCTL_SET_VERSION call will
return an error. Otherwise the driver's set_version() method will be
called with the requested version.
-Name, Description and Date
-~~~~~~~~~~~~~~~~~~~~~~~~~~
+Name and Description
+~~~~~~~~~~~~~~~~~~~~
char \*name; char \*desc; char \*date;
The driver name is printed to the kernel log at initialization time,
@@ -69,12 +69,6 @@ The driver description is a purely informative string passed to
userspace through the DRM_IOCTL_VERSION ioctl and otherwise unused by
the kernel.
-The driver date, formatted as YYYYMMDD, is meant to identify the date of
-the latest modification to the driver. However, as most drivers fail to
-update it, its value is mostly useless. The DRM core prints it to the
-kernel log at initialization time and passes it to userspace through the
-DRM_IOCTL_VERSION ioctl.
-
Module Initialization
---------------------
diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst
index 59cfe8a7a8ba..8435e8621cc0 100644
--- a/Documentation/gpu/drm-kms-helpers.rst
+++ b/Documentation/gpu/drm-kms-helpers.rst
@@ -110,15 +110,21 @@ fbdev Helper Functions Reference
.. kernel-doc:: drivers/gpu/drm/drm_fb_helper.c
:doc: fbdev helpers
+.. kernel-doc:: drivers/gpu/drm/drm_fbdev_dma.c
+ :export:
+
+.. kernel-doc:: drivers/gpu/drm/drm_fbdev_shmem.c
+ :export:
+
+.. kernel-doc:: drivers/gpu/drm/drm_fbdev_ttm.c
+ :export:
+
.. kernel-doc:: include/drm/drm_fb_helper.h
:internal:
.. kernel-doc:: drivers/gpu/drm/drm_fb_helper.c
:export:
-.. kernel-doc:: drivers/gpu/drm/drm_fbdev_generic.c
- :export:
-
format Helper Functions Reference
=================================
diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
index fb9ad120b141..2734b8a34541 100644
--- a/Documentation/gpu/todo.rst
+++ b/Documentation/gpu/todo.rst
@@ -243,19 +243,6 @@ Contact: Maintainer of the driver you plan to convert
Level: Intermediate
-Convert drivers to use drm_fbdev_generic_setup()
-------------------------------------------------
-
-Most drivers can use drm_fbdev_generic_setup(). Driver have to implement
-atomic modesetting and GEM vmap support. Historically, generic fbdev emulation
-expected the framebuffer in system memory or system-like memory. By employing
-struct iosys_map, drivers with frambuffers in I/O memory can be supported
-as well.
-
-Contact: Maintainer of the driver you plan to convert
-
-Level: Intermediate
-
Reimplement functions in drm_fbdev_fb_ops without fbdev
-------------------------------------------------------
@@ -507,6 +494,24 @@ Contact: Douglas Anderson <[email protected]>
Level: Starter/Intermediate
+Transition away from using mipi_dsi_*_write_seq()
+-------------------------------------------------
+
+The macros mipi_dsi_generic_write_seq() and mipi_dsi_dcs_write_seq() are
+non-intuitive because, if there are errors, they return out of the *caller's*
+function. We should move all callers to use mipi_dsi_generic_write_seq_multi()
+and mipi_dsi_dcs_write_seq_multi() macros instead.
+
+Once all callers are transitioned, the macros and the functions that they call,
+mipi_dsi_generic_write_chatty() and mipi_dsi_dcs_write_buffer_chatty(), can
+probably be removed. Alternatively, if people feel like the _multi() variants
+are overkill for some use cases, we could keep the mipi_dsi_*_write_seq()
+variants but change them not to return out of the caller.
+
+Contact: Douglas Anderson <[email protected]>
+
+Level: Starter
+
Core refactorings
=================
diff --git a/MAINTAINERS b/MAINTAINERS
index d6c90161c7bf..ac285040578e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6910,7 +6910,7 @@ DRM DRIVER FOR LG SW43408 PANELS
M: Sumit Semwal <[email protected]>
M: Caleb Connolly <[email protected]>
S: Maintained
-T: git git://anongit.freedesktop.org/drm/drm-misc
+T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
F: Documentation/devicetree/bindings/display/panel/lg,sw43408.yaml
F: drivers/gpu/drm/panel/panel-lg-sw43408.c
diff --git a/drivers/accel/ivpu/Makefile b/drivers/accel/ivpu/Makefile
index 95ff7ad16338..ebd682a42eb1 100644
--- a/drivers/accel/ivpu/Makefile
+++ b/drivers/accel/ivpu/Makefile
@@ -1,19 +1,22 @@
# SPDX-License-Identifier: GPL-2.0-only
-# Copyright (C) 2023 Intel Corporation
+# Copyright (C) 2023-2024 Intel Corporation
intel_vpu-y := \
ivpu_drv.o \
ivpu_fw.o \
ivpu_fw_log.o \
ivpu_gem.o \
- ivpu_hw_37xx.o \
- ivpu_hw_40xx.o \
+ ivpu_hw.o \
+ ivpu_hw_btrs.o \
+ ivpu_hw_ip.o \
ivpu_ipc.o \
ivpu_job.o \
ivpu_jsm_msg.o \
ivpu_mmu.o \
ivpu_mmu_context.o \
- ivpu_pm.o
+ ivpu_ms.o \
+ ivpu_pm.o \
+ ivpu_sysfs.o
intel_vpu-$(CONFIG_DEBUG_FS) += ivpu_debugfs.o
diff --git a/drivers/accel/ivpu/ivpu_debugfs.c b/drivers/accel/ivpu/ivpu_debugfs.c
index e07e447d08d1..10d6408c9831 100644
--- a/drivers/accel/ivpu/ivpu_debugfs.c
+++ b/drivers/accel/ivpu/ivpu_debugfs.c
@@ -145,6 +145,30 @@ static const struct file_operations dvfs_mode_fops = {
.write = dvfs_mode_fops_write,
};
+static ssize_t
+fw_dyndbg_fops_write(struct file *file, const char __user *user_buf, size_t size, loff_t *pos)
+{
+ struct ivpu_device *vdev = file->private_data;
+ char buffer[VPU_DYNDBG_CMD_MAX_LEN] = {};
+ int ret;
+
+ if (size >= VPU_DYNDBG_CMD_MAX_LEN)
+ return -EINVAL;
+
+ ret = strncpy_from_user(buffer, user_buf, size);
+ if (ret < 0)
+ return ret;
+
+ ivpu_jsm_dyndbg_control(vdev, buffer, size);
+ return size;
+}
+
+static const struct file_operations fw_dyndbg_fops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .write = fw_dyndbg_fops_write,
+};
+
static int fw_log_show(struct seq_file *s, void *v)
{
struct ivpu_device *vdev = s->private;
@@ -335,6 +359,28 @@ static const struct file_operations ivpu_reset_engine_fops = {
.write = ivpu_reset_engine_fn,
};
+static ssize_t
+ivpu_resume_engine_fn(struct file *file, const char __user *user_buf, size_t size, loff_t *pos)
+{
+ struct ivpu_device *vdev = file->private_data;
+
+ if (!size)
+ return -EINVAL;
+
+ if (ivpu_jsm_hws_resume_engine(vdev, DRM_IVPU_ENGINE_COMPUTE))
+ return -ENODEV;
+ if (ivpu_jsm_hws_resume_engine(vdev, DRM_IVPU_ENGINE_COPY))
+ return -ENODEV;
+
+ return size;
+}
+
+static const struct file_operations ivpu_resume_engine_fops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .write = ivpu_resume_engine_fn,
+};
+
void ivpu_debugfs_init(struct ivpu_device *vdev)
{
struct dentry *debugfs_root = vdev->drm.debugfs_root;
@@ -347,6 +393,8 @@ void ivpu_debugfs_init(struct ivpu_device *vdev)
debugfs_create_file("dvfs_mode", 0200, debugfs_root, vdev,
&dvfs_mode_fops);
+ debugfs_create_file("fw_dyndbg", 0200, debugfs_root, vdev,
+ &fw_dyndbg_fops);
debugfs_create_file("fw_log", 0644, debugfs_root, vdev,
&fw_log_fops);
debugfs_create_file("fw_trace_destination_mask", 0200, debugfs_root, vdev,
@@ -358,8 +406,10 @@ void ivpu_debugfs_init(struct ivpu_device *vdev)
debugfs_create_file("reset_engine", 0200, debugfs_root, vdev,
&ivpu_reset_engine_fops);
+ debugfs_create_file("resume_engine", 0200, debugfs_root, vdev,
+ &ivpu_resume_engine_fops);
- if (ivpu_hw_gen(vdev) >= IVPU_HW_40XX)
+ if (ivpu_hw_ip_gen(vdev) >= IVPU_HW_IP_40XX)
debugfs_create_file("fw_profiling_freq_drive", 0200,
debugfs_root, vdev, &fw_profiling_freq_fops);
}
diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c
index 51d3f1a55d02..f3e0d55f4adb 100644
--- a/drivers/accel/ivpu/ivpu_drv.c
+++ b/drivers/accel/ivpu/ivpu_drv.c
@@ -26,7 +26,9 @@
#include "ivpu_jsm_msg.h"
#include "ivpu_mmu.h"
#include "ivpu_mmu_context.h"
+#include "ivpu_ms.h"
#include "ivpu_pm.h"
+#include "ivpu_sysfs.h"
#ifndef DRIVER_VERSION_STR
#define DRIVER_VERSION_STR __stringify(DRM_IVPU_DRIVER_MAJOR) "." \
@@ -51,10 +53,18 @@ u8 ivpu_pll_max_ratio = U8_MAX;
module_param_named(pll_max_ratio, ivpu_pll_max_ratio, byte, 0644);
MODULE_PARM_DESC(pll_max_ratio, "Maximum PLL ratio used to set NPU frequency");
+int ivpu_sched_mode;
+module_param_named(sched_mode, ivpu_sched_mode, int, 0444);
+MODULE_PARM_DESC(sched_mode, "Scheduler mode: 0 - Default scheduler, 1 - Force HW scheduler");
+
bool ivpu_disable_mmu_cont_pages;
module_param_named(disable_mmu_cont_pages, ivpu_disable_mmu_cont_pages, bool, 0644);
MODULE_PARM_DESC(disable_mmu_cont_pages, "Disable MMU contiguous pages optimization");
+bool ivpu_force_snoop;
+module_param_named(force_snoop, ivpu_force_snoop, bool, 0644);
+MODULE_PARM_DESC(force_snoop, "Force snooping for NPU host memory access");
+
struct ivpu_file_priv *ivpu_file_priv_get(struct ivpu_file_priv *file_priv)
{
struct ivpu_device *vdev = file_priv->vdev;
@@ -74,7 +84,6 @@ static void file_priv_unbind(struct ivpu_device *vdev, struct ivpu_file_priv *fi
ivpu_dbg(vdev, FILE, "file_priv unbind: ctx %u\n", file_priv->ctx.id);
ivpu_cmdq_release_all_locked(file_priv);
- ivpu_jsm_context_release(vdev, file_priv->ctx.id);
ivpu_bo_unbind_all_bos_from_context(vdev, &file_priv->ctx);
ivpu_mmu_user_context_fini(vdev, &file_priv->ctx);
file_priv->bound = false;
@@ -97,6 +106,7 @@ static void file_priv_release(struct kref *ref)
mutex_unlock(&vdev->context_list_lock);
pm_runtime_put_autosuspend(vdev->drm.dev);
+ mutex_destroy(&file_priv->ms_lock);
mutex_destroy(&file_priv->lock);
kfree(file_priv);
}
@@ -119,7 +129,7 @@ static int ivpu_get_capabilities(struct ivpu_device *vdev, struct drm_ivpu_param
{
switch (args->index) {
case DRM_IVPU_CAP_METRIC_STREAMER:
- args->value = 0;
+ args->value = 1;
break;
case DRM_IVPU_CAP_DMA_MEMORY_RANGE:
args->value = 1;
@@ -228,10 +238,13 @@ static int ivpu_open(struct drm_device *dev, struct drm_file *file)
goto err_dev_exit;
}
+ INIT_LIST_HEAD(&file_priv->ms_instance_list);
+
file_priv->vdev = vdev;
file_priv->bound = true;
kref_init(&file_priv->ref);
mutex_init(&file_priv->lock);
+ mutex_init(&file_priv->ms_lock);
mutex_lock(&vdev->context_list_lock);
@@ -260,6 +273,7 @@ err_xa_erase:
xa_erase_irq(&vdev->context_xa, ctx_id);
err_unlock:
mutex_unlock(&vdev->context_list_lock);
+ mutex_destroy(&file_priv->ms_lock);
mutex_destroy(&file_priv->lock);
kfree(file_priv);
err_dev_exit:
@@ -275,6 +289,7 @@ static void ivpu_postclose(struct drm_device *dev, struct drm_file *file)
ivpu_dbg(vdev, FILE, "file_priv close: ctx %u process %s pid %d\n",
file_priv->ctx.id, current->comm, task_pid_nr(current));
+ ivpu_ms_cleanup(file_priv);
ivpu_file_priv_put(&file_priv);
}
@@ -285,6 +300,10 @@ static const struct drm_ioctl_desc ivpu_drm_ioctls[] = {
DRM_IOCTL_DEF_DRV(IVPU_BO_INFO, ivpu_bo_info_ioctl, 0),
DRM_IOCTL_DEF_DRV(IVPU_SUBMIT, ivpu_submit_ioctl, 0),
DRM_IOCTL_DEF_DRV(IVPU_BO_WAIT, ivpu_bo_wait_ioctl, 0),
+ DRM_IOCTL_DEF_DRV(IVPU_METRIC_STREAMER_START, ivpu_ms_start_ioctl, 0),
+ DRM_IOCTL_DEF_DRV(IVPU_METRIC_STREAMER_GET_DATA, ivpu_ms_get_data_ioctl, 0),
+ DRM_IOCTL_DEF_DRV(IVPU_METRIC_STREAMER_STOP, ivpu_ms_stop_ioctl, 0),
+ DRM_IOCTL_DEF_DRV(IVPU_METRIC_STREAMER_GET_INFO, ivpu_ms_get_info_ioctl, 0),
};
static int ivpu_wait_for_ready(struct ivpu_device *vdev)
@@ -301,7 +320,7 @@ static int ivpu_wait_for_ready(struct ivpu_device *vdev)
timeout = jiffies + msecs_to_jiffies(vdev->timeout.boot);
while (1) {
- ivpu_ipc_irq_handler(vdev, NULL);
+ ivpu_ipc_irq_handler(vdev);
ret = ivpu_ipc_receive(vdev, &cons, &ipc_hdr, NULL, 0);
if (ret != -ETIMEDOUT || time_after_eq(jiffies, timeout))
break;
@@ -323,6 +342,21 @@ static int ivpu_wait_for_ready(struct ivpu_device *vdev)
return ret;
}
+static int ivpu_hw_sched_init(struct ivpu_device *vdev)
+{
+ int ret = 0;
+
+ if (vdev->hw->sched_mode == VPU_SCHEDULING_MODE_HW) {
+ ret = ivpu_jsm_hws_setup_priority_bands(vdev);
+ if (ret) {
+ ivpu_err(vdev, "Failed to enable hw scheduler: %d", ret);
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
/**
* ivpu_boot() - Start VPU firmware
* @vdev: VPU device
@@ -356,6 +390,10 @@ int ivpu_boot(struct ivpu_device *vdev)
enable_irq(vdev->irq);
ivpu_hw_irq_enable(vdev);
ivpu_ipc_enable(vdev);
+
+ if (ivpu_fw_is_cold_boot(vdev))
+ return ivpu_hw_sched_init(vdev);
+
return 0;
}
@@ -411,8 +449,23 @@ static const struct drm_driver driver = {
static irqreturn_t ivpu_irq_thread_handler(int irq, void *arg)
{
struct ivpu_device *vdev = arg;
+ u8 irq_src;
- return ivpu_ipc_irq_thread_handler(vdev);
+ if (kfifo_is_empty(&vdev->hw->irq.fifo))
+ return IRQ_NONE;
+
+ while (kfifo_get(&vdev->hw->irq.fifo, &irq_src)) {
+ switch (irq_src) {
+ case IVPU_HW_IRQ_SRC_IPC:
+ ivpu_ipc_irq_thread_handler(vdev);
+ break;
+ default:
+ ivpu_err_ratelimited(vdev, "Unknown IRQ source: %u\n", irq_src);
+ break;
+ }
+ }
+
+ return IRQ_HANDLED;
}
static int ivpu_irq_init(struct ivpu_device *vdev)
@@ -426,9 +479,11 @@ static int ivpu_irq_init(struct ivpu_device *vdev)
return ret;
}
+ ivpu_irq_handlers_init(vdev);
+
vdev->irq = pci_irq_vector(pdev, 0);
- ret = devm_request_threaded_irq(vdev->drm.dev, vdev->irq, vdev->hw->ops->irq_handler,
+ ret = devm_request_threaded_irq(vdev->drm.dev, vdev->irq, ivpu_hw_irq_handler,
ivpu_irq_thread_handler, IRQF_NO_AUTOEN, DRIVER_NAME, vdev);
if (ret)
ivpu_err(vdev, "Failed to request an IRQ %d\n", ret);
@@ -505,13 +560,10 @@ static int ivpu_dev_init(struct ivpu_device *vdev)
if (!vdev->pm)
return -ENOMEM;
- if (ivpu_hw_gen(vdev) >= IVPU_HW_40XX) {
- vdev->hw->ops = &ivpu_hw_40xx_ops;
+ if (ivpu_hw_ip_gen(vdev) >= IVPU_HW_IP_40XX)
vdev->hw->dma_bits = 48;
- } else {
- vdev->hw->ops = &ivpu_hw_37xx_ops;
+ else
vdev->hw->dma_bits = 38;
- }
vdev->platform = IVPU_PLATFORM_INVALID;
vdev->context_xa_limit.min = IVPU_USER_CONTEXT_MIN_SSID;
@@ -540,7 +592,7 @@ static int ivpu_dev_init(struct ivpu_device *vdev)
goto err_xa_destroy;
/* Init basic HW info based on buttress registers which are accessible before power up */
- ret = ivpu_hw_info_init(vdev);
+ ret = ivpu_hw_init(vdev);
if (ret)
goto err_xa_destroy;
@@ -616,6 +668,7 @@ static void ivpu_dev_fini(struct ivpu_device *vdev)
ivpu_prepare_for_reset(vdev);
ivpu_shutdown(vdev);
+ ivpu_ms_cleanup_all(vdev);
ivpu_jobs_abort_all(vdev);
ivpu_job_done_consumer_fini(vdev);
ivpu_pm_cancel_recovery(vdev);
@@ -658,6 +711,7 @@ static int ivpu_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return ret;
ivpu_debugfs_init(vdev);
+ ivpu_sysfs_init(vdev);
ret = drm_dev_register(&vdev->drm, 0);
if (ret) {
diff --git a/drivers/accel/ivpu/ivpu_drv.h b/drivers/accel/ivpu/ivpu_drv.h
index bb4374d0eaec..39df96a7623b 100644
--- a/drivers/accel/ivpu/ivpu_drv.h
+++ b/drivers/accel/ivpu/ivpu_drv.h
@@ -27,8 +27,13 @@
#define PCI_DEVICE_ID_ARL 0xad1d
#define PCI_DEVICE_ID_LNL 0x643e
-#define IVPU_HW_37XX 37
-#define IVPU_HW_40XX 40
+#define IVPU_HW_IP_37XX 37
+#define IVPU_HW_IP_40XX 40
+#define IVPU_HW_IP_50XX 50
+#define IVPU_HW_IP_60XX 60
+
+#define IVPU_HW_BTRS_MTL 1
+#define IVPU_HW_BTRS_LNL 2
#define IVPU_GLOBAL_CONTEXT_MMU_SSID 0
/* SSID 1 is used by the VPU to represent reserved context */
@@ -39,7 +44,11 @@
#define IVPU_MIN_DB 1
#define IVPU_MAX_DB 255
-#define IVPU_NUM_ENGINES 2
+#define IVPU_NUM_ENGINES 2
+#define IVPU_NUM_PRIORITIES 4
+#define IVPU_NUM_CMDQS_PER_CTX (IVPU_NUM_ENGINES * IVPU_NUM_PRIORITIES)
+
+#define IVPU_CMDQ_INDEX(engine, priority) ((engine) * IVPU_NUM_PRIORITIES + (priority))
#define IVPU_PLATFORM_SILICON 0
#define IVPU_PLATFORM_SIMICS 2
@@ -131,6 +140,9 @@ struct ivpu_device {
atomic64_t unique_id_counter;
+ ktime_t busy_start_ts;
+ ktime_t busy_time;
+
struct {
int boot;
int jsm;
@@ -149,8 +161,11 @@ struct ivpu_file_priv {
struct kref ref;
struct ivpu_device *vdev;
struct mutex lock; /* Protects cmdq */
- struct ivpu_cmdq *cmdq[IVPU_NUM_ENGINES];
+ struct ivpu_cmdq *cmdq[IVPU_NUM_CMDQS_PER_CTX];
struct ivpu_mmu_context ctx;
+ struct mutex ms_lock; /* Protects ms_instance_list, ms_info_bo */
+ struct list_head ms_instance_list;
+ struct ivpu_bo *ms_info_bo;
bool has_mmu_faults;
bool bound;
};
@@ -158,13 +173,17 @@ struct ivpu_file_priv {
extern int ivpu_dbg_mask;
extern u8 ivpu_pll_min_ratio;
extern u8 ivpu_pll_max_ratio;
+extern int ivpu_sched_mode;
extern bool ivpu_disable_mmu_cont_pages;
+extern bool ivpu_force_snoop;
#define IVPU_TEST_MODE_FW_TEST BIT(0)
#define IVPU_TEST_MODE_NULL_HW BIT(1)
#define IVPU_TEST_MODE_NULL_SUBMISSION BIT(2)
#define IVPU_TEST_MODE_D0I3_MSG_DISABLE BIT(4)
#define IVPU_TEST_MODE_D0I3_MSG_ENABLE BIT(5)
+#define IVPU_TEST_MODE_PREEMPTION_DISABLE BIT(6)
+#define IVPU_TEST_MODE_HWS_EXTRA_EVENTS BIT(7)
extern int ivpu_test_mode;
struct ivpu_file_priv *ivpu_file_priv_get(struct ivpu_file_priv *file_priv);
@@ -184,16 +203,32 @@ static inline u16 ivpu_device_id(struct ivpu_device *vdev)
return to_pci_dev(vdev->drm.dev)->device;
}
-static inline int ivpu_hw_gen(struct ivpu_device *vdev)
+static inline int ivpu_hw_ip_gen(struct ivpu_device *vdev)
+{
+ switch (ivpu_device_id(vdev)) {
+ case PCI_DEVICE_ID_MTL:
+ case PCI_DEVICE_ID_ARL:
+ return IVPU_HW_IP_37XX;
+ case PCI_DEVICE_ID_LNL:
+ return IVPU_HW_IP_40XX;
+ default:
+ dump_stack();
+ ivpu_err(vdev, "Unknown NPU IP generation\n");
+ return 0;
+ }
+}
+
+static inline int ivpu_hw_btrs_gen(struct ivpu_device *vdev)
{
switch (ivpu_device_id(vdev)) {
case PCI_DEVICE_ID_MTL:
case PCI_DEVICE_ID_ARL:
- return IVPU_HW_37XX;
+ return IVPU_HW_BTRS_MTL;
case PCI_DEVICE_ID_LNL:
- return IVPU_HW_40XX;
+ return IVPU_HW_BTRS_LNL;
default:
- ivpu_err(vdev, "Unknown NPU device\n");
+ dump_stack();
+ ivpu_err(vdev, "Unknown buttress generation\n");
return 0;
}
}
@@ -231,4 +266,9 @@ static inline bool ivpu_is_fpga(struct ivpu_device *vdev)
return ivpu_get_platform(vdev) == IVPU_PLATFORM_FPGA;
}
+static inline bool ivpu_is_force_snoop_enabled(struct ivpu_device *vdev)
+{
+ return ivpu_force_snoop;
+}
+
#endif /* __IVPU_DRV_H__ */
diff --git a/drivers/accel/ivpu/ivpu_fw.c b/drivers/accel/ivpu/ivpu_fw.c
index 1457300828bf..1fc4befe7461 100644
--- a/drivers/accel/ivpu/ivpu_fw.c
+++ b/drivers/accel/ivpu/ivpu_fw.c
@@ -44,6 +44,8 @@
#define IVPU_FW_CHECK_API_VER_LT(vdev, fw_hdr, name, major, minor) \
ivpu_fw_check_api_ver_lt(vdev, fw_hdr, #name, VPU_##name##_API_VER_INDEX, major, minor)
+#define IVPU_FOCUS_PRESENT_TIMER_MS 1000
+
static char *ivpu_firmware;
module_param_named_unsafe(firmware, ivpu_firmware, charp, 0644);
MODULE_PARM_DESC(firmware, "NPU firmware binary in /lib/firmware/..");
@@ -52,10 +54,10 @@ static struct {
int gen;
const char *name;
} fw_names[] = {
- { IVPU_HW_37XX, "vpu_37xx.bin" },
- { IVPU_HW_37XX, "intel/vpu/vpu_37xx_v0.0.bin" },
- { IVPU_HW_40XX, "vpu_40xx.bin" },
- { IVPU_HW_40XX, "intel/vpu/vpu_40xx_v0.0.bin" },
+ { IVPU_HW_IP_37XX, "vpu_37xx.bin" },
+ { IVPU_HW_IP_37XX, "intel/vpu/vpu_37xx_v0.0.bin" },
+ { IVPU_HW_IP_40XX, "vpu_40xx.bin" },
+ { IVPU_HW_IP_40XX, "intel/vpu/vpu_40xx_v0.0.bin" },
};
static int ivpu_fw_request(struct ivpu_device *vdev)
@@ -71,7 +73,7 @@ static int ivpu_fw_request(struct ivpu_device *vdev)
}
for (i = 0; i < ARRAY_SIZE(fw_names); i++) {
- if (fw_names[i].gen != ivpu_hw_gen(vdev))
+ if (fw_names[i].gen != ivpu_hw_ip_gen(vdev))
continue;
ret = firmware_request_nowarn(&vdev->fw->file, fw_names[i].name, vdev->drm.dev);
@@ -200,6 +202,9 @@ static int ivpu_fw_parse(struct ivpu_device *vdev)
fw->dvfs_mode = 0;
+ fw->primary_preempt_buf_size = fw_hdr->preemption_buffer_1_size;
+ fw->secondary_preempt_buf_size = fw_hdr->preemption_buffer_2_size;
+
ivpu_dbg(vdev, FW_BOOT, "Size: file %lu image %u runtime %u shavenn %u\n",
fw->file->size, fw->image_size, fw->runtime_size, fw->shave_nn_size);
ivpu_dbg(vdev, FW_BOOT, "Address: runtime 0x%llx, load 0x%llx, entry point 0x%llx\n",
@@ -241,7 +246,7 @@ static int ivpu_fw_update_global_range(struct ivpu_device *vdev)
return -EINVAL;
}
- ivpu_hw_init_range(&vdev->hw->ranges.global, start, size);
+ ivpu_hw_range_init(&vdev->hw->ranges.global, start, size);
return 0;
}
@@ -464,6 +469,8 @@ static void ivpu_fw_boot_params_print(struct ivpu_device *vdev, struct vpu_boot_
boot_params->punit_telemetry_sram_size);
ivpu_dbg(vdev, FW_BOOT, "boot_params.vpu_telemetry_enable = 0x%x\n",
boot_params->vpu_telemetry_enable);
+ ivpu_dbg(vdev, FW_BOOT, "boot_params.vpu_scheduling_mode = 0x%x\n",
+ boot_params->vpu_scheduling_mode);
ivpu_dbg(vdev, FW_BOOT, "boot_params.dvfs_mode = %u\n",
boot_params->dvfs_mode);
ivpu_dbg(vdev, FW_BOOT, "boot_params.d0i3_delayed_entry = %d\n",
@@ -504,7 +511,7 @@ void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params
boot_params->magic = VPU_BOOT_PARAMS_MAGIC;
boot_params->vpu_id = to_pci_dev(vdev->drm.dev)->bus->number;
- boot_params->frequency = ivpu_hw_reg_pll_freq_get(vdev);
+ boot_params->frequency = ivpu_hw_pll_freq_get(vdev);
/*
* This param is a debug firmware feature. It switches default clock
@@ -561,9 +568,12 @@ void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params
boot_params->verbose_tracing_buff_addr = vdev->fw->mem_log_verb->vpu_addr;
boot_params->verbose_tracing_buff_size = ivpu_bo_size(vdev->fw->mem_log_verb);
- boot_params->punit_telemetry_sram_base = ivpu_hw_reg_telemetry_offset_get(vdev);
- boot_params->punit_telemetry_sram_size = ivpu_hw_reg_telemetry_size_get(vdev);
- boot_params->vpu_telemetry_enable = ivpu_hw_reg_telemetry_enable_get(vdev);
+ boot_params->punit_telemetry_sram_base = ivpu_hw_telemetry_offset_get(vdev);
+ boot_params->punit_telemetry_sram_size = ivpu_hw_telemetry_size_get(vdev);
+ boot_params->vpu_telemetry_enable = ivpu_hw_telemetry_enable_get(vdev);
+ boot_params->vpu_scheduling_mode = vdev->hw->sched_mode;
+ if (vdev->hw->sched_mode == VPU_SCHEDULING_MODE_HW)
+ boot_params->vpu_focus_present_timer_ms = IVPU_FOCUS_PRESENT_TIMER_MS;
boot_params->dvfs_mode = vdev->fw->dvfs_mode;
if (!IVPU_WA(disable_d0i3_msg))
boot_params->d0i3_delayed_entry = 1;
diff --git a/drivers/accel/ivpu/ivpu_fw.h b/drivers/accel/ivpu/ivpu_fw.h
index 66b60fa161b5..66fc7da3ab0f 100644
--- a/drivers/accel/ivpu/ivpu_fw.h
+++ b/drivers/accel/ivpu/ivpu_fw.h
@@ -28,6 +28,8 @@ struct ivpu_fw_info {
u32 trace_destination_mask;
u64 trace_hw_component_mask;
u32 dvfs_mode;
+ u32 primary_preempt_buf_size;
+ u32 secondary_preempt_buf_size;
};
int ivpu_fw_init(struct ivpu_device *vdev);
diff --git a/drivers/accel/ivpu/ivpu_gem.h b/drivers/accel/ivpu/ivpu_gem.h
index fb7117c13eec..d975000abd78 100644
--- a/drivers/accel/ivpu/ivpu_gem.h
+++ b/drivers/accel/ivpu/ivpu_gem.h
@@ -60,14 +60,17 @@ static inline u32 ivpu_bo_cache_mode(struct ivpu_bo *bo)
return bo->flags & DRM_IVPU_BO_CACHE_MASK;
}
-static inline bool ivpu_bo_is_snooped(struct ivpu_bo *bo)
+static inline struct ivpu_device *ivpu_bo_to_vdev(struct ivpu_bo *bo)
{
- return ivpu_bo_cache_mode(bo) == DRM_IVPU_BO_CACHED;
+ return to_ivpu_device(bo->base.base.dev);
}
-static inline struct ivpu_device *ivpu_bo_to_vdev(struct ivpu_bo *bo)
+static inline bool ivpu_bo_is_snooped(struct ivpu_bo *bo)
{
- return to_ivpu_device(bo->base.base.dev);
+ if (ivpu_is_force_snoop_enabled(ivpu_bo_to_vdev(bo)))
+ return true;
+
+ return ivpu_bo_cache_mode(bo) == DRM_IVPU_BO_CACHED;
}
static inline void *ivpu_to_cpu_addr(struct ivpu_bo *bo, u32 vpu_addr)
diff --git a/drivers/accel/ivpu/ivpu_hw.c b/drivers/accel/ivpu/ivpu_hw.c
new file mode 100644
index 000000000000..9f5e3875baf1
--- /dev/null
+++ b/drivers/accel/ivpu/ivpu_hw.c
@@ -0,0 +1,313 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2020 - 2024 Intel Corporation
+ */
+
+#include "ivpu_drv.h"
+#include "ivpu_hw.h"
+#include "ivpu_hw_btrs.h"
+#include "ivpu_hw_ip.h"
+
+#include <linux/dmi.h>
+
+static char *platform_to_str(u32 platform)
+{
+ switch (platform) {
+ case IVPU_PLATFORM_SILICON:
+ return "SILICON";
+ case IVPU_PLATFORM_SIMICS:
+ return "SIMICS";
+ case IVPU_PLATFORM_FPGA:
+ return "FPGA";
+ default:
+ return "Invalid platform";
+ }
+}
+
+static const struct dmi_system_id dmi_platform_simulation[] = {
+ {
+ .ident = "Intel Simics",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "lnlrvp"),
+ DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
+ DMI_MATCH(DMI_BOARD_SERIAL, "123456789"),
+ },
+ },
+ {
+ .ident = "Intel Simics",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "Simics"),
+ },
+ },
+ { }
+};
+
+static void platform_init(struct ivpu_device *vdev)
+{
+ if (dmi_check_system(dmi_platform_simulation))
+ vdev->platform = IVPU_PLATFORM_SIMICS;
+ else
+ vdev->platform = IVPU_PLATFORM_SILICON;
+
+ ivpu_dbg(vdev, MISC, "Platform type: %s (%d)\n",
+ platform_to_str(vdev->platform), vdev->platform);
+}
+
+static void wa_init(struct ivpu_device *vdev)
+{
+ vdev->wa.punit_disabled = ivpu_is_fpga(vdev);
+ vdev->wa.clear_runtime_mem = false;
+
+ if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
+ vdev->wa.interrupt_clear_with_0 = ivpu_hw_btrs_irqs_clear_with_0_mtl(vdev);
+
+ if (ivpu_device_id(vdev) == PCI_DEVICE_ID_LNL)
+ vdev->wa.disable_clock_relinquish = true;
+
+ IVPU_PRINT_WA(punit_disabled);
+ IVPU_PRINT_WA(clear_runtime_mem);
+ IVPU_PRINT_WA(interrupt_clear_with_0);
+ IVPU_PRINT_WA(disable_clock_relinquish);
+}
+
+static void timeouts_init(struct ivpu_device *vdev)
+{
+ if (ivpu_is_fpga(vdev)) {
+ vdev->timeout.boot = 100000;
+ vdev->timeout.jsm = 50000;
+ vdev->timeout.tdr = 2000000;
+ vdev->timeout.reschedule_suspend = 1000;
+ vdev->timeout.autosuspend = -1;
+ vdev->timeout.d0i3_entry_msg = 500;
+ } else if (ivpu_is_simics(vdev)) {
+ vdev->timeout.boot = 50;
+ vdev->timeout.jsm = 500;
+ vdev->timeout.tdr = 10000;
+ vdev->timeout.reschedule_suspend = 10;
+ vdev->timeout.autosuspend = -1;
+ vdev->timeout.d0i3_entry_msg = 100;
+ } else {
+ vdev->timeout.boot = 1000;
+ vdev->timeout.jsm = 500;
+ vdev->timeout.tdr = 2000;
+ vdev->timeout.reschedule_suspend = 10;
+ vdev->timeout.autosuspend = 10;
+ vdev->timeout.d0i3_entry_msg = 5;
+ }
+}
+
+static void memory_ranges_init(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) {
+ ivpu_hw_range_init(&vdev->hw->ranges.global, 0x80000000, SZ_512M);
+ ivpu_hw_range_init(&vdev->hw->ranges.user, 0xc0000000, 255 * SZ_1M);
+ ivpu_hw_range_init(&vdev->hw->ranges.shave, 0x180000000, SZ_2G);
+ ivpu_hw_range_init(&vdev->hw->ranges.dma, 0x200000000, SZ_8G);
+ } else {
+ ivpu_hw_range_init(&vdev->hw->ranges.global, 0x80000000, SZ_512M);
+ ivpu_hw_range_init(&vdev->hw->ranges.user, 0x80000000, SZ_256M);
+ ivpu_hw_range_init(&vdev->hw->ranges.shave, 0x80000000 + SZ_256M, SZ_2G - SZ_256M);
+ ivpu_hw_range_init(&vdev->hw->ranges.dma, 0x200000000, SZ_8G);
+ }
+}
+
+static int wp_enable(struct ivpu_device *vdev)
+{
+ return ivpu_hw_btrs_wp_drive(vdev, true);
+}
+
+static int wp_disable(struct ivpu_device *vdev)
+{
+ return ivpu_hw_btrs_wp_drive(vdev, false);
+}
+
+int ivpu_hw_power_up(struct ivpu_device *vdev)
+{
+ int ret;
+
+ ret = ivpu_hw_btrs_d0i3_disable(vdev);
+ if (ret)
+ ivpu_warn(vdev, "Failed to disable D0I3: %d\n", ret);
+
+ ret = wp_enable(vdev);
+ if (ret) {
+ ivpu_err(vdev, "Failed to enable workpoint: %d\n", ret);
+ return ret;
+ }
+
+ if (ivpu_hw_btrs_gen(vdev) >= IVPU_HW_BTRS_LNL) {
+ if (IVPU_WA(disable_clock_relinquish))
+ ivpu_hw_btrs_clock_relinquish_disable_lnl(vdev);
+ ivpu_hw_btrs_profiling_freq_reg_set_lnl(vdev);
+ ivpu_hw_btrs_ats_print_lnl(vdev);
+ }
+
+ ret = ivpu_hw_ip_host_ss_configure(vdev);
+ if (ret) {
+ ivpu_err(vdev, "Failed to configure host SS: %d\n", ret);
+ return ret;
+ }
+
+ ivpu_hw_ip_idle_gen_disable(vdev);
+
+ ret = ivpu_hw_btrs_wait_for_clock_res_own_ack(vdev);
+ if (ret) {
+ ivpu_err(vdev, "Timed out waiting for clock resource own ACK\n");
+ return ret;
+ }
+
+ ret = ivpu_hw_ip_pwr_domain_enable(vdev);
+ if (ret) {
+ ivpu_err(vdev, "Failed to enable power domain: %d\n", ret);
+ return ret;
+ }
+
+ ret = ivpu_hw_ip_host_ss_axi_enable(vdev);
+ if (ret) {
+ ivpu_err(vdev, "Failed to enable AXI: %d\n", ret);
+ return ret;
+ }
+
+ if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_LNL)
+ ivpu_hw_btrs_set_port_arbitration_weights_lnl(vdev);
+
+ ret = ivpu_hw_ip_top_noc_enable(vdev);
+ if (ret)
+ ivpu_err(vdev, "Failed to enable TOP NOC: %d\n", ret);
+
+ return ret;
+}
+
+static void save_d0i3_entry_timestamp(struct ivpu_device *vdev)
+{
+ vdev->hw->d0i3_entry_host_ts = ktime_get_boottime();
+ vdev->hw->d0i3_entry_vpu_ts = ivpu_hw_ip_read_perf_timer_counter(vdev);
+}
+
+int ivpu_hw_reset(struct ivpu_device *vdev)
+{
+ int ret = 0;
+
+ if (ivpu_hw_btrs_ip_reset(vdev)) {
+ ivpu_err(vdev, "Failed to reset NPU IP\n");
+ ret = -EIO;
+ }
+
+ if (wp_disable(vdev)) {
+ ivpu_err(vdev, "Failed to disable workpoint\n");
+ ret = -EIO;
+ }
+
+ return ret;
+}
+
+int ivpu_hw_power_down(struct ivpu_device *vdev)
+{
+ int ret = 0;
+
+ save_d0i3_entry_timestamp(vdev);
+
+ if (!ivpu_hw_is_idle(vdev))
+ ivpu_warn(vdev, "NPU not idle during power down\n");
+
+ if (ivpu_hw_reset(vdev)) {
+ ivpu_err(vdev, "Failed to reset NPU\n");
+ ret = -EIO;
+ }
+
+ if (ivpu_hw_btrs_d0i3_enable(vdev)) {
+ ivpu_err(vdev, "Failed to enter D0I3\n");
+ ret = -EIO;
+ }
+
+ return ret;
+}
+
+int ivpu_hw_init(struct ivpu_device *vdev)
+{
+ ivpu_hw_btrs_info_init(vdev);
+ ivpu_hw_btrs_freq_ratios_init(vdev);
+ memory_ranges_init(vdev);
+ platform_init(vdev);
+ wa_init(vdev);
+ timeouts_init(vdev);
+
+ return 0;
+}
+
+int ivpu_hw_boot_fw(struct ivpu_device *vdev)
+{
+ int ret;
+
+ ivpu_hw_ip_snoop_disable(vdev);
+ ivpu_hw_ip_tbu_mmu_enable(vdev);
+ ret = ivpu_hw_ip_soc_cpu_boot(vdev);
+ if (ret)
+ ivpu_err(vdev, "Failed to boot SOC CPU: %d\n", ret);
+
+ return ret;
+}
+
+void ivpu_hw_profiling_freq_drive(struct ivpu_device *vdev, bool enable)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) {
+ vdev->hw->pll.profiling_freq = PLL_PROFILING_FREQ_DEFAULT;
+ return;
+ }
+
+ if (enable)
+ vdev->hw->pll.profiling_freq = PLL_PROFILING_FREQ_HIGH;
+ else
+ vdev->hw->pll.profiling_freq = PLL_PROFILING_FREQ_DEFAULT;
+}
+
+void ivpu_irq_handlers_init(struct ivpu_device *vdev)
+{
+ INIT_KFIFO(vdev->hw->irq.fifo);
+
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ vdev->hw->irq.ip_irq_handler = ivpu_hw_ip_irq_handler_37xx;
+ else
+ vdev->hw->irq.ip_irq_handler = ivpu_hw_ip_irq_handler_40xx;
+
+ if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
+ vdev->hw->irq.btrs_irq_handler = ivpu_hw_btrs_irq_handler_mtl;
+ else
+ vdev->hw->irq.btrs_irq_handler = ivpu_hw_btrs_irq_handler_lnl;
+}
+
+void ivpu_hw_irq_enable(struct ivpu_device *vdev)
+{
+ kfifo_reset(&vdev->hw->irq.fifo);
+ ivpu_hw_ip_irq_enable(vdev);
+ ivpu_hw_btrs_irq_enable(vdev);
+}
+
+void ivpu_hw_irq_disable(struct ivpu_device *vdev)
+{
+ ivpu_hw_btrs_irq_disable(vdev);
+ ivpu_hw_ip_irq_disable(vdev);
+}
+
+irqreturn_t ivpu_hw_irq_handler(int irq, void *ptr)
+{
+ struct ivpu_device *vdev = ptr;
+ bool ip_handled, btrs_handled;
+
+ ivpu_hw_btrs_global_int_disable(vdev);
+
+ btrs_handled = ivpu_hw_btrs_irq_handler(vdev, irq);
+ if (!ivpu_hw_is_idle((vdev)) || !btrs_handled)
+ ip_handled = ivpu_hw_ip_irq_handler(vdev, irq);
+ else
+ ip_handled = false;
+
+ /* Re-enable global interrupts to re-trigger MSI for pending interrupts */
+ ivpu_hw_btrs_global_int_enable(vdev);
+
+ if (!kfifo_is_empty(&vdev->hw->irq.fifo))
+ return IRQ_WAKE_THREAD;
+ if (ip_handled || btrs_handled)
+ return IRQ_HANDLED;
+ return IRQ_NONE;
+}
diff --git a/drivers/accel/ivpu/ivpu_hw.h b/drivers/accel/ivpu/ivpu_hw.h
index 094c659d2800..8ddf9f93189d 100644
--- a/drivers/accel/ivpu/ivpu_hw.h
+++ b/drivers/accel/ivpu/ivpu_hw.h
@@ -1,39 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * Copyright (C) 2020-2023 Intel Corporation
+ * Copyright (C) 2020 - 2024 Intel Corporation
*/
#ifndef __IVPU_HW_H__
#define __IVPU_HW_H__
+#include <linux/kfifo.h>
+
#include "ivpu_drv.h"
+#include "ivpu_hw_btrs.h"
+#include "ivpu_hw_ip.h"
-struct ivpu_hw_ops {
- int (*info_init)(struct ivpu_device *vdev);
- int (*power_up)(struct ivpu_device *vdev);
- int (*boot_fw)(struct ivpu_device *vdev);
- int (*power_down)(struct ivpu_device *vdev);
- int (*reset)(struct ivpu_device *vdev);
- bool (*is_idle)(struct ivpu_device *vdev);
- int (*wait_for_idle)(struct ivpu_device *vdev);
- void (*wdt_disable)(struct ivpu_device *vdev);
- void (*diagnose_failure)(struct ivpu_device *vdev);
- u32 (*profiling_freq_get)(struct ivpu_device *vdev);
- void (*profiling_freq_drive)(struct ivpu_device *vdev, bool enable);
- u32 (*reg_pll_freq_get)(struct ivpu_device *vdev);
- u32 (*ratio_to_freq)(struct ivpu_device *vdev, u32 ratio);
- u32 (*reg_telemetry_offset_get)(struct ivpu_device *vdev);
- u32 (*reg_telemetry_size_get)(struct ivpu_device *vdev);
- u32 (*reg_telemetry_enable_get)(struct ivpu_device *vdev);
- void (*reg_db_set)(struct ivpu_device *vdev, u32 db_id);
- u32 (*reg_ipc_rx_addr_get)(struct ivpu_device *vdev);
- u32 (*reg_ipc_rx_count_get)(struct ivpu_device *vdev);
- void (*reg_ipc_tx_set)(struct ivpu_device *vdev, u32 vpu_addr);
- void (*irq_clear)(struct ivpu_device *vdev);
- void (*irq_enable)(struct ivpu_device *vdev);
- void (*irq_disable)(struct ivpu_device *vdev);
- irqreturn_t (*irq_handler)(int irq, void *ptr);
-};
+#define IVPU_HW_IRQ_FIFO_LENGTH 1024
+
+#define IVPU_HW_IRQ_SRC_IPC 1
struct ivpu_addr_range {
resource_size_t start;
@@ -41,7 +22,11 @@ struct ivpu_addr_range {
};
struct ivpu_hw_info {
- const struct ivpu_hw_ops *ops;
+ struct {
+ bool (*btrs_irq_handler)(struct ivpu_device *vdev, int irq);
+ bool (*ip_irq_handler)(struct ivpu_device *vdev, int irq);
+ DECLARE_KFIFO(fifo, u8, IVPU_HW_IRQ_FIFO_LENGTH);
+ } irq;
struct {
struct ivpu_addr_range global;
struct ivpu_addr_range user;
@@ -59,6 +44,7 @@ struct ivpu_hw_info {
u32 profiling_freq;
} pll;
u32 tile_fuse;
+ u32 sched_mode;
u32 sku;
u16 config;
int dma_bits;
@@ -66,140 +52,107 @@ struct ivpu_hw_info {
u64 d0i3_entry_vpu_ts;
};
-extern const struct ivpu_hw_ops ivpu_hw_37xx_ops;
-extern const struct ivpu_hw_ops ivpu_hw_40xx_ops;
-
-static inline int ivpu_hw_info_init(struct ivpu_device *vdev)
-{
- return vdev->hw->ops->info_init(vdev);
-};
-
-static inline int ivpu_hw_power_up(struct ivpu_device *vdev)
-{
- ivpu_dbg(vdev, PM, "HW power up\n");
+int ivpu_hw_init(struct ivpu_device *vdev);
+int ivpu_hw_power_up(struct ivpu_device *vdev);
+int ivpu_hw_power_down(struct ivpu_device *vdev);
+int ivpu_hw_reset(struct ivpu_device *vdev);
+int ivpu_hw_boot_fw(struct ivpu_device *vdev);
+void ivpu_hw_profiling_freq_drive(struct ivpu_device *vdev, bool enable);
+void ivpu_irq_handlers_init(struct ivpu_device *vdev);
+void ivpu_hw_irq_enable(struct ivpu_device *vdev);
+void ivpu_hw_irq_disable(struct ivpu_device *vdev);
+irqreturn_t ivpu_hw_irq_handler(int irq, void *ptr);
- return vdev->hw->ops->power_up(vdev);
-};
-
-static inline int ivpu_hw_boot_fw(struct ivpu_device *vdev)
-{
- return vdev->hw->ops->boot_fw(vdev);
-};
-
-static inline bool ivpu_hw_is_idle(struct ivpu_device *vdev)
-{
- return vdev->hw->ops->is_idle(vdev);
-};
-
-static inline int ivpu_hw_wait_for_idle(struct ivpu_device *vdev)
+static inline u32 ivpu_hw_btrs_irq_handler(struct ivpu_device *vdev, int irq)
{
- return vdev->hw->ops->wait_for_idle(vdev);
-};
-
-static inline int ivpu_hw_power_down(struct ivpu_device *vdev)
-{
- ivpu_dbg(vdev, PM, "HW power down\n");
-
- return vdev->hw->ops->power_down(vdev);
-};
-
-static inline int ivpu_hw_reset(struct ivpu_device *vdev)
-{
- ivpu_dbg(vdev, PM, "HW reset\n");
-
- return vdev->hw->ops->reset(vdev);
-};
-
-static inline void ivpu_hw_wdt_disable(struct ivpu_device *vdev)
-{
- vdev->hw->ops->wdt_disable(vdev);
-};
+ return vdev->hw->irq.btrs_irq_handler(vdev, irq);
+}
-static inline u32 ivpu_hw_profiling_freq_get(struct ivpu_device *vdev)
+static inline u32 ivpu_hw_ip_irq_handler(struct ivpu_device *vdev, int irq)
{
- return vdev->hw->ops->profiling_freq_get(vdev);
-};
+ return vdev->hw->irq.ip_irq_handler(vdev, irq);
+}
-static inline void ivpu_hw_profiling_freq_drive(struct ivpu_device *vdev, bool enable)
+static inline void ivpu_hw_range_init(struct ivpu_addr_range *range, u64 start, u64 size)
{
- return vdev->hw->ops->profiling_freq_drive(vdev, enable);
-};
+ range->start = start;
+ range->end = start + size;
+}
-/* Register indirect accesses */
-static inline u32 ivpu_hw_reg_pll_freq_get(struct ivpu_device *vdev)
+static inline u64 ivpu_hw_range_size(const struct ivpu_addr_range *range)
{
- return vdev->hw->ops->reg_pll_freq_get(vdev);
-};
+ return range->end - range->start;
+}
static inline u32 ivpu_hw_ratio_to_freq(struct ivpu_device *vdev, u32 ratio)
{
- return vdev->hw->ops->ratio_to_freq(vdev, ratio);
+ return ivpu_hw_btrs_ratio_to_freq(vdev, ratio);
}
-static inline u32 ivpu_hw_reg_telemetry_offset_get(struct ivpu_device *vdev)
+static inline void ivpu_hw_irq_clear(struct ivpu_device *vdev)
{
- return vdev->hw->ops->reg_telemetry_offset_get(vdev);
-};
+ ivpu_hw_ip_irq_clear(vdev);
+}
-static inline u32 ivpu_hw_reg_telemetry_size_get(struct ivpu_device *vdev)
+static inline u32 ivpu_hw_pll_freq_get(struct ivpu_device *vdev)
{
- return vdev->hw->ops->reg_telemetry_size_get(vdev);
-};
+ return ivpu_hw_btrs_pll_freq_get(vdev);
+}
-static inline u32 ivpu_hw_reg_telemetry_enable_get(struct ivpu_device *vdev)
+static inline u32 ivpu_hw_profiling_freq_get(struct ivpu_device *vdev)
{
- return vdev->hw->ops->reg_telemetry_enable_get(vdev);
-};
+ return vdev->hw->pll.profiling_freq;
+}
-static inline void ivpu_hw_reg_db_set(struct ivpu_device *vdev, u32 db_id)
+static inline void ivpu_hw_diagnose_failure(struct ivpu_device *vdev)
{
- vdev->hw->ops->reg_db_set(vdev, db_id);
-};
+ ivpu_hw_ip_diagnose_failure(vdev);
+ ivpu_hw_btrs_diagnose_failure(vdev);
+}
-static inline u32 ivpu_hw_reg_ipc_rx_addr_get(struct ivpu_device *vdev)
+static inline u32 ivpu_hw_telemetry_offset_get(struct ivpu_device *vdev)
{
- return vdev->hw->ops->reg_ipc_rx_addr_get(vdev);
-};
+ return ivpu_hw_btrs_telemetry_offset_get(vdev);
+}
-static inline u32 ivpu_hw_reg_ipc_rx_count_get(struct ivpu_device *vdev)
+static inline u32 ivpu_hw_telemetry_size_get(struct ivpu_device *vdev)
{
- return vdev->hw->ops->reg_ipc_rx_count_get(vdev);
-};
+ return ivpu_hw_btrs_telemetry_size_get(vdev);
+}
-static inline void ivpu_hw_reg_ipc_tx_set(struct ivpu_device *vdev, u32 vpu_addr)
+static inline u32 ivpu_hw_telemetry_enable_get(struct ivpu_device *vdev)
{
- vdev->hw->ops->reg_ipc_tx_set(vdev, vpu_addr);
-};
+ return ivpu_hw_btrs_telemetry_enable_get(vdev);
+}
-static inline void ivpu_hw_irq_clear(struct ivpu_device *vdev)
+static inline bool ivpu_hw_is_idle(struct ivpu_device *vdev)
{
- vdev->hw->ops->irq_clear(vdev);
-};
+ return ivpu_hw_btrs_is_idle(vdev);
+}
-static inline void ivpu_hw_irq_enable(struct ivpu_device *vdev)
+static inline int ivpu_hw_wait_for_idle(struct ivpu_device *vdev)
{
- vdev->hw->ops->irq_enable(vdev);
-};
+ return ivpu_hw_btrs_wait_for_idle(vdev);
+}
-static inline void ivpu_hw_irq_disable(struct ivpu_device *vdev)
+static inline void ivpu_hw_ipc_tx_set(struct ivpu_device *vdev, u32 vpu_addr)
{
- vdev->hw->ops->irq_disable(vdev);
-};
+ ivpu_hw_ip_ipc_tx_set(vdev, vpu_addr);
+}
-static inline void ivpu_hw_init_range(struct ivpu_addr_range *range, u64 start, u64 size)
+static inline void ivpu_hw_db_set(struct ivpu_device *vdev, u32 db_id)
{
- range->start = start;
- range->end = start + size;
+ ivpu_hw_ip_db_set(vdev, db_id);
}
-static inline u64 ivpu_hw_range_size(const struct ivpu_addr_range *range)
+static inline u32 ivpu_hw_ipc_rx_addr_get(struct ivpu_device *vdev)
{
- return range->end - range->start;
+ return ivpu_hw_ip_ipc_rx_addr_get(vdev);
}
-static inline void ivpu_hw_diagnose_failure(struct ivpu_device *vdev)
+static inline u32 ivpu_hw_ipc_rx_count_get(struct ivpu_device *vdev)
{
- vdev->hw->ops->diagnose_failure(vdev);
+ return ivpu_hw_ip_ipc_rx_count_get(vdev);
}
#endif /* __IVPU_HW_H__ */
diff --git a/drivers/accel/ivpu/ivpu_hw_37xx.c b/drivers/accel/ivpu/ivpu_hw_37xx.c
deleted file mode 100644
index bd25e2d9fb0f..000000000000
--- a/drivers/accel/ivpu/ivpu_hw_37xx.c
+++ /dev/null
@@ -1,1065 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2020-2024 Intel Corporation
- */
-
-#include "ivpu_drv.h"
-#include "ivpu_fw.h"
-#include "ivpu_hw_37xx_reg.h"
-#include "ivpu_hw_reg_io.h"
-#include "ivpu_hw.h"
-#include "ivpu_ipc.h"
-#include "ivpu_mmu.h"
-#include "ivpu_pm.h"
-
-#define TILE_FUSE_ENABLE_BOTH 0x0
-#define TILE_SKU_BOTH 0x3630
-
-/* Work point configuration values */
-#define CONFIG_1_TILE 0x01
-#define CONFIG_2_TILE 0x02
-#define PLL_RATIO_5_3 0x01
-#define PLL_RATIO_4_3 0x02
-#define WP_CONFIG(tile, ratio) (((tile) << 8) | (ratio))
-#define WP_CONFIG_1_TILE_5_3_RATIO WP_CONFIG(CONFIG_1_TILE, PLL_RATIO_5_3)
-#define WP_CONFIG_1_TILE_4_3_RATIO WP_CONFIG(CONFIG_1_TILE, PLL_RATIO_4_3)
-#define WP_CONFIG_2_TILE_5_3_RATIO WP_CONFIG(CONFIG_2_TILE, PLL_RATIO_5_3)
-#define WP_CONFIG_2_TILE_4_3_RATIO WP_CONFIG(CONFIG_2_TILE, PLL_RATIO_4_3)
-#define WP_CONFIG_0_TILE_PLL_OFF WP_CONFIG(0, 0)
-
-#define PLL_REF_CLK_FREQ (50 * 1000000)
-#define PLL_SIMULATION_FREQ (10 * 1000000)
-#define PLL_PROF_CLK_FREQ (38400 * 1000)
-#define PLL_DEFAULT_EPP_VALUE 0x80
-
-#define TIM_SAFE_ENABLE 0xf1d0dead
-#define TIM_WATCHDOG_RESET_VALUE 0xffffffff
-
-#define TIMEOUT_US (150 * USEC_PER_MSEC)
-#define PWR_ISLAND_STATUS_TIMEOUT_US (5 * USEC_PER_MSEC)
-#define PLL_TIMEOUT_US (1500 * USEC_PER_MSEC)
-#define IDLE_TIMEOUT_US (5 * USEC_PER_MSEC)
-
-#define ICB_0_IRQ_MASK ((REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, HOST_IPC_FIFO_INT)) | \
- (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_0_INT)) | \
- (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_1_INT)) | \
- (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_2_INT)) | \
- (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT)) | \
- (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT)) | \
- (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT)))
-
-#define ICB_1_IRQ_MASK ((REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_2_INT)) | \
- (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_3_INT)) | \
- (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_4_INT)))
-
-#define ICB_0_1_IRQ_MASK ((((u64)ICB_1_IRQ_MASK) << 32) | ICB_0_IRQ_MASK)
-
-#define BUTTRESS_IRQ_MASK ((REG_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, ATS_ERR)) | \
- (REG_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, UFI_ERR)))
-
-#define BUTTRESS_ALL_IRQ_MASK (BUTTRESS_IRQ_MASK | \
- (REG_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, FREQ_CHANGE)))
-
-#define BUTTRESS_IRQ_ENABLE_MASK ((u32)~BUTTRESS_IRQ_MASK)
-#define BUTTRESS_IRQ_DISABLE_MASK ((u32)-1)
-
-#define ITF_FIREWALL_VIOLATION_MASK ((REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, CSS_ROM_CMX)) | \
- (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, CSS_DBG)) | \
- (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, CSS_CTRL)) | \
- (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, DEC400)) | \
- (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, MSS_NCE)) | \
- (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, MSS_MBI)) | \
- (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, MSS_MBI_CMX)))
-
-static void ivpu_hw_wa_init(struct ivpu_device *vdev)
-{
- vdev->wa.punit_disabled = false;
- vdev->wa.clear_runtime_mem = false;
-
- REGB_WR32(VPU_37XX_BUTTRESS_INTERRUPT_STAT, BUTTRESS_ALL_IRQ_MASK);
- if (REGB_RD32(VPU_37XX_BUTTRESS_INTERRUPT_STAT) == BUTTRESS_ALL_IRQ_MASK) {
- /* Writing 1s does not clear the interrupt status register */
- vdev->wa.interrupt_clear_with_0 = true;
- REGB_WR32(VPU_37XX_BUTTRESS_INTERRUPT_STAT, 0x0);
- }
-
- IVPU_PRINT_WA(punit_disabled);
- IVPU_PRINT_WA(clear_runtime_mem);
- IVPU_PRINT_WA(interrupt_clear_with_0);
-}
-
-static void ivpu_hw_timeouts_init(struct ivpu_device *vdev)
-{
- vdev->timeout.boot = 1000;
- vdev->timeout.jsm = 500;
- vdev->timeout.tdr = 2000;
- vdev->timeout.reschedule_suspend = 10;
- vdev->timeout.autosuspend = 10;
- vdev->timeout.d0i3_entry_msg = 5;
-}
-
-static int ivpu_pll_wait_for_cmd_send(struct ivpu_device *vdev)
-{
- return REGB_POLL_FLD(VPU_37XX_BUTTRESS_WP_REQ_CMD, SEND, 0, PLL_TIMEOUT_US);
-}
-
-/* Send KMD initiated workpoint change */
-static int ivpu_pll_cmd_send(struct ivpu_device *vdev, u16 min_ratio, u16 max_ratio,
- u16 target_ratio, u16 config)
-{
- int ret;
- u32 val;
-
- ret = ivpu_pll_wait_for_cmd_send(vdev);
- if (ret) {
- ivpu_err(vdev, "Failed to sync before WP request: %d\n", ret);
- return ret;
- }
-
- val = REGB_RD32(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0);
- val = REG_SET_FLD_NUM(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0, MIN_RATIO, min_ratio, val);
- val = REG_SET_FLD_NUM(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0, MAX_RATIO, max_ratio, val);
- REGB_WR32(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0, val);
-
- val = REGB_RD32(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1);
- val = REG_SET_FLD_NUM(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1, TARGET_RATIO, target_ratio, val);
- val = REG_SET_FLD_NUM(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1, EPP, PLL_DEFAULT_EPP_VALUE, val);
- REGB_WR32(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1, val);
-
- val = REGB_RD32(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD2);
- val = REG_SET_FLD_NUM(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD2, CONFIG, config, val);
- REGB_WR32(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD2, val);
-
- val = REGB_RD32(VPU_37XX_BUTTRESS_WP_REQ_CMD);
- val = REG_SET_FLD(VPU_37XX_BUTTRESS_WP_REQ_CMD, SEND, val);
- REGB_WR32(VPU_37XX_BUTTRESS_WP_REQ_CMD, val);
-
- ret = ivpu_pll_wait_for_cmd_send(vdev);
- if (ret)
- ivpu_err(vdev, "Failed to sync after WP request: %d\n", ret);
-
- return ret;
-}
-
-static int ivpu_pll_wait_for_lock(struct ivpu_device *vdev, bool enable)
-{
- u32 exp_val = enable ? 0x1 : 0x0;
-
- if (IVPU_WA(punit_disabled))
- return 0;
-
- return REGB_POLL_FLD(VPU_37XX_BUTTRESS_PLL_STATUS, LOCK, exp_val, PLL_TIMEOUT_US);
-}
-
-static int ivpu_pll_wait_for_status_ready(struct ivpu_device *vdev)
-{
- if (IVPU_WA(punit_disabled))
- return 0;
-
- return REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_STATUS, READY, 1, PLL_TIMEOUT_US);
-}
-
-static void ivpu_pll_init_frequency_ratios(struct ivpu_device *vdev)
-{
- struct ivpu_hw_info *hw = vdev->hw;
- u8 fuse_min_ratio, fuse_max_ratio, fuse_pn_ratio;
- u32 fmin_fuse, fmax_fuse;
-
- fmin_fuse = REGB_RD32(VPU_37XX_BUTTRESS_FMIN_FUSE);
- fuse_min_ratio = REG_GET_FLD(VPU_37XX_BUTTRESS_FMIN_FUSE, MIN_RATIO, fmin_fuse);
- fuse_pn_ratio = REG_GET_FLD(VPU_37XX_BUTTRESS_FMIN_FUSE, PN_RATIO, fmin_fuse);
-
- fmax_fuse = REGB_RD32(VPU_37XX_BUTTRESS_FMAX_FUSE);
- fuse_max_ratio = REG_GET_FLD(VPU_37XX_BUTTRESS_FMAX_FUSE, MAX_RATIO, fmax_fuse);
-
- hw->pll.min_ratio = clamp_t(u8, ivpu_pll_min_ratio, fuse_min_ratio, fuse_max_ratio);
- hw->pll.max_ratio = clamp_t(u8, ivpu_pll_max_ratio, hw->pll.min_ratio, fuse_max_ratio);
- hw->pll.pn_ratio = clamp_t(u8, fuse_pn_ratio, hw->pll.min_ratio, hw->pll.max_ratio);
-}
-
-static int ivpu_hw_37xx_wait_for_vpuip_bar(struct ivpu_device *vdev)
-{
- return REGV_POLL_FLD(VPU_37XX_HOST_SS_CPR_RST_CLR, AON, 0, 100);
-}
-
-static int ivpu_pll_drive(struct ivpu_device *vdev, bool enable)
-{
- struct ivpu_hw_info *hw = vdev->hw;
- u16 target_ratio;
- u16 config;
- int ret;
-
- if (IVPU_WA(punit_disabled)) {
- ivpu_dbg(vdev, PM, "Skipping PLL request\n");
- return 0;
- }
-
- if (enable) {
- target_ratio = hw->pll.pn_ratio;
- config = hw->config;
- } else {
- target_ratio = 0;
- config = 0;
- }
-
- ivpu_dbg(vdev, PM, "PLL workpoint request: config 0x%04x pll ratio 0x%x\n",
- config, target_ratio);
-
- ret = ivpu_pll_cmd_send(vdev, hw->pll.min_ratio, hw->pll.max_ratio, target_ratio, config);
- if (ret) {
- ivpu_err(vdev, "Failed to send PLL workpoint request: %d\n", ret);
- return ret;
- }
-
- ret = ivpu_pll_wait_for_lock(vdev, enable);
- if (ret) {
- ivpu_err(vdev, "Timed out waiting for PLL lock\n");
- return ret;
- }
-
- if (enable) {
- ret = ivpu_pll_wait_for_status_ready(vdev);
- if (ret) {
- ivpu_err(vdev, "Timed out waiting for PLL ready status\n");
- return ret;
- }
-
- ret = ivpu_hw_37xx_wait_for_vpuip_bar(vdev);
- if (ret) {
- ivpu_err(vdev, "Timed out waiting for NPU IP bar\n");
- return ret;
- }
- }
-
- return 0;
-}
-
-static int ivpu_pll_enable(struct ivpu_device *vdev)
-{
- return ivpu_pll_drive(vdev, true);
-}
-
-static int ivpu_pll_disable(struct ivpu_device *vdev)
-{
- return ivpu_pll_drive(vdev, false);
-}
-
-static void ivpu_boot_host_ss_rst_clr_assert(struct ivpu_device *vdev)
-{
- u32 val = 0;
-
- val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_CLR, TOP_NOC, val);
- val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_CLR, DSS_MAS, val);
- val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_CLR, MSS_MAS, val);
-
- REGV_WR32(VPU_37XX_HOST_SS_CPR_RST_CLR, val);
-}
-
-static void ivpu_boot_host_ss_rst_drive(struct ivpu_device *vdev, bool enable)
-{
- u32 val = REGV_RD32(VPU_37XX_HOST_SS_CPR_RST_SET);
-
- if (enable) {
- val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, TOP_NOC, val);
- val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, DSS_MAS, val);
- val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, MSS_MAS, val);
- } else {
- val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, TOP_NOC, val);
- val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, DSS_MAS, val);
- val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, MSS_MAS, val);
- }
-
- REGV_WR32(VPU_37XX_HOST_SS_CPR_RST_SET, val);
-}
-
-static void ivpu_boot_host_ss_clk_drive(struct ivpu_device *vdev, bool enable)
-{
- u32 val = REGV_RD32(VPU_37XX_HOST_SS_CPR_CLK_SET);
-
- if (enable) {
- val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, TOP_NOC, val);
- val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, DSS_MAS, val);
- val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, MSS_MAS, val);
- } else {
- val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, TOP_NOC, val);
- val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, DSS_MAS, val);
- val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, MSS_MAS, val);
- }
-
- REGV_WR32(VPU_37XX_HOST_SS_CPR_CLK_SET, val);
-}
-
-static int ivpu_boot_noc_qreqn_check(struct ivpu_device *vdev, u32 exp_val)
-{
- u32 val = REGV_RD32(VPU_37XX_HOST_SS_NOC_QREQN);
-
- if (!REG_TEST_FLD_NUM(VPU_37XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, exp_val, val))
- return -EIO;
-
- return 0;
-}
-
-static int ivpu_boot_noc_qacceptn_check(struct ivpu_device *vdev, u32 exp_val)
-{
- u32 val = REGV_RD32(VPU_37XX_HOST_SS_NOC_QACCEPTN);
-
- if (!REG_TEST_FLD_NUM(VPU_37XX_HOST_SS_NOC_QACCEPTN, TOP_SOCMMIO, exp_val, val))
- return -EIO;
-
- return 0;
-}
-
-static int ivpu_boot_noc_qdeny_check(struct ivpu_device *vdev, u32 exp_val)
-{
- u32 val = REGV_RD32(VPU_37XX_HOST_SS_NOC_QDENY);
-
- if (!REG_TEST_FLD_NUM(VPU_37XX_HOST_SS_NOC_QDENY, TOP_SOCMMIO, exp_val, val))
- return -EIO;
-
- return 0;
-}
-
-static int ivpu_boot_top_noc_qrenqn_check(struct ivpu_device *vdev, u32 exp_val)
-{
- u32 val = REGV_RD32(VPU_37XX_TOP_NOC_QREQN);
-
- if (!REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QREQN, CPU_CTRL, exp_val, val) ||
- !REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, exp_val, val))
- return -EIO;
-
- return 0;
-}
-
-static int ivpu_boot_top_noc_qacceptn_check(struct ivpu_device *vdev, u32 exp_val)
-{
- u32 val = REGV_RD32(VPU_37XX_TOP_NOC_QACCEPTN);
-
- if (!REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QACCEPTN, CPU_CTRL, exp_val, val) ||
- !REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QACCEPTN, HOSTIF_L2CACHE, exp_val, val))
- return -EIO;
-
- return 0;
-}
-
-static int ivpu_boot_top_noc_qdeny_check(struct ivpu_device *vdev, u32 exp_val)
-{
- u32 val = REGV_RD32(VPU_37XX_TOP_NOC_QDENY);
-
- if (!REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QDENY, CPU_CTRL, exp_val, val) ||
- !REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QDENY, HOSTIF_L2CACHE, exp_val, val))
- return -EIO;
-
- return 0;
-}
-
-static int ivpu_boot_host_ss_configure(struct ivpu_device *vdev)
-{
- ivpu_boot_host_ss_rst_clr_assert(vdev);
-
- return ivpu_boot_noc_qreqn_check(vdev, 0x0);
-}
-
-static void ivpu_boot_vpu_idle_gen_disable(struct ivpu_device *vdev)
-{
- REGV_WR32(VPU_37XX_HOST_SS_AON_VPU_IDLE_GEN, 0x0);
-}
-
-static int ivpu_boot_host_ss_axi_drive(struct ivpu_device *vdev, bool enable)
-{
- int ret;
- u32 val;
-
- val = REGV_RD32(VPU_37XX_HOST_SS_NOC_QREQN);
- if (enable)
- val = REG_SET_FLD(VPU_37XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, val);
- else
- val = REG_CLR_FLD(VPU_37XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, val);
- REGV_WR32(VPU_37XX_HOST_SS_NOC_QREQN, val);
-
- ret = ivpu_boot_noc_qacceptn_check(vdev, enable ? 0x1 : 0x0);
- if (ret) {
- ivpu_err(vdev, "Failed qacceptn check: %d\n", ret);
- return ret;
- }
-
- ret = ivpu_boot_noc_qdeny_check(vdev, 0x0);
- if (ret)
- ivpu_err(vdev, "Failed qdeny check: %d\n", ret);
-
- return ret;
-}
-
-static int ivpu_boot_host_ss_axi_enable(struct ivpu_device *vdev)
-{
- return ivpu_boot_host_ss_axi_drive(vdev, true);
-}
-
-static int ivpu_boot_host_ss_top_noc_drive(struct ivpu_device *vdev, bool enable)
-{
- int ret;
- u32 val;
-
- val = REGV_RD32(VPU_37XX_TOP_NOC_QREQN);
- if (enable) {
- val = REG_SET_FLD(VPU_37XX_TOP_NOC_QREQN, CPU_CTRL, val);
- val = REG_SET_FLD(VPU_37XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, val);
- } else {
- val = REG_CLR_FLD(VPU_37XX_TOP_NOC_QREQN, CPU_CTRL, val);
- val = REG_CLR_FLD(VPU_37XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, val);
- }
- REGV_WR32(VPU_37XX_TOP_NOC_QREQN, val);
-
- ret = ivpu_boot_top_noc_qacceptn_check(vdev, enable ? 0x1 : 0x0);
- if (ret) {
- ivpu_err(vdev, "Failed qacceptn check: %d\n", ret);
- return ret;
- }
-
- ret = ivpu_boot_top_noc_qdeny_check(vdev, 0x0);
- if (ret)
- ivpu_err(vdev, "Failed qdeny check: %d\n", ret);
-
- return ret;
-}
-
-static int ivpu_boot_host_ss_top_noc_enable(struct ivpu_device *vdev)
-{
- return ivpu_boot_host_ss_top_noc_drive(vdev, true);
-}
-
-static void ivpu_boot_pwr_island_trickle_drive(struct ivpu_device *vdev, bool enable)
-{
- u32 val = REGV_RD32(VPU_37XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0);
-
- if (enable)
- val = REG_SET_FLD(VPU_37XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, MSS_CPU, val);
- else
- val = REG_CLR_FLD(VPU_37XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, MSS_CPU, val);
-
- REGV_WR32(VPU_37XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, val);
-}
-
-static void ivpu_boot_pwr_island_drive(struct ivpu_device *vdev, bool enable)
-{
- u32 val = REGV_RD32(VPU_37XX_HOST_SS_AON_PWR_ISLAND_EN0);
-
- if (enable)
- val = REG_SET_FLD(VPU_37XX_HOST_SS_AON_PWR_ISLAND_EN0, MSS_CPU, val);
- else
- val = REG_CLR_FLD(VPU_37XX_HOST_SS_AON_PWR_ISLAND_EN0, MSS_CPU, val);
-
- REGV_WR32(VPU_37XX_HOST_SS_AON_PWR_ISLAND_EN0, val);
-}
-
-static int ivpu_boot_wait_for_pwr_island_status(struct ivpu_device *vdev, u32 exp_val)
-{
- return REGV_POLL_FLD(VPU_37XX_HOST_SS_AON_PWR_ISLAND_STATUS0, MSS_CPU,
- exp_val, PWR_ISLAND_STATUS_TIMEOUT_US);
-}
-
-static void ivpu_boot_pwr_island_isolation_drive(struct ivpu_device *vdev, bool enable)
-{
- u32 val = REGV_RD32(VPU_37XX_HOST_SS_AON_PWR_ISO_EN0);
-
- if (enable)
- val = REG_SET_FLD(VPU_37XX_HOST_SS_AON_PWR_ISO_EN0, MSS_CPU, val);
- else
- val = REG_CLR_FLD(VPU_37XX_HOST_SS_AON_PWR_ISO_EN0, MSS_CPU, val);
-
- REGV_WR32(VPU_37XX_HOST_SS_AON_PWR_ISO_EN0, val);
-}
-
-static void ivpu_boot_dpu_active_drive(struct ivpu_device *vdev, bool enable)
-{
- u32 val = REGV_RD32(VPU_37XX_HOST_SS_AON_DPU_ACTIVE);
-
- if (enable)
- val = REG_SET_FLD(VPU_37XX_HOST_SS_AON_DPU_ACTIVE, DPU_ACTIVE, val);
- else
- val = REG_CLR_FLD(VPU_37XX_HOST_SS_AON_DPU_ACTIVE, DPU_ACTIVE, val);
-
- REGV_WR32(VPU_37XX_HOST_SS_AON_DPU_ACTIVE, val);
-}
-
-static int ivpu_boot_pwr_domain_enable(struct ivpu_device *vdev)
-{
- int ret;
-
- ivpu_boot_pwr_island_trickle_drive(vdev, true);
- ivpu_boot_pwr_island_drive(vdev, true);
-
- ret = ivpu_boot_wait_for_pwr_island_status(vdev, 0x1);
- if (ret) {
- ivpu_err(vdev, "Timed out waiting for power island status\n");
- return ret;
- }
-
- ret = ivpu_boot_top_noc_qrenqn_check(vdev, 0x0);
- if (ret) {
- ivpu_err(vdev, "Failed qrenqn check %d\n", ret);
- return ret;
- }
-
- ivpu_boot_host_ss_clk_drive(vdev, true);
- ivpu_boot_pwr_island_isolation_drive(vdev, false);
- ivpu_boot_host_ss_rst_drive(vdev, true);
- ivpu_boot_dpu_active_drive(vdev, true);
-
- return ret;
-}
-
-static void ivpu_boot_no_snoop_enable(struct ivpu_device *vdev)
-{
- u32 val = REGV_RD32(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES);
-
- val = REG_SET_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, NOSNOOP_OVERRIDE_EN, val);
- val = REG_CLR_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, AW_NOSNOOP_OVERRIDE, val);
- val = REG_SET_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, AR_NOSNOOP_OVERRIDE, val);
-
- REGV_WR32(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, val);
-}
-
-static void ivpu_boot_tbu_mmu_enable(struct ivpu_device *vdev)
-{
- u32 val = REGV_RD32(VPU_37XX_HOST_IF_TBU_MMUSSIDV);
-
- val = REG_SET_FLD(VPU_37XX_HOST_IF_TBU_MMUSSIDV, TBU0_AWMMUSSIDV, val);
- val = REG_SET_FLD(VPU_37XX_HOST_IF_TBU_MMUSSIDV, TBU0_ARMMUSSIDV, val);
- val = REG_SET_FLD(VPU_37XX_HOST_IF_TBU_MMUSSIDV, TBU2_AWMMUSSIDV, val);
- val = REG_SET_FLD(VPU_37XX_HOST_IF_TBU_MMUSSIDV, TBU2_ARMMUSSIDV, val);
-
- REGV_WR32(VPU_37XX_HOST_IF_TBU_MMUSSIDV, val);
-}
-
-static void ivpu_boot_soc_cpu_boot(struct ivpu_device *vdev)
-{
- u32 val;
-
- val = REGV_RD32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC);
- val = REG_SET_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RSTRUN0, val);
-
- val = REG_CLR_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RSTVEC, val);
- REGV_WR32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val);
-
- val = REG_SET_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RESUME0, val);
- REGV_WR32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val);
-
- val = REG_CLR_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RESUME0, val);
- REGV_WR32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val);
-
- val = vdev->fw->entry_point >> 9;
- REGV_WR32(VPU_37XX_HOST_SS_LOADING_ADDRESS_LO, val);
-
- val = REG_SET_FLD(VPU_37XX_HOST_SS_LOADING_ADDRESS_LO, DONE, val);
- REGV_WR32(VPU_37XX_HOST_SS_LOADING_ADDRESS_LO, val);
-
- ivpu_dbg(vdev, PM, "Booting firmware, mode: %s\n",
- vdev->fw->entry_point == vdev->fw->cold_boot_entry_point ? "cold boot" : "resume");
-}
-
-static int ivpu_boot_d0i3_drive(struct ivpu_device *vdev, bool enable)
-{
- int ret;
- u32 val;
-
- ret = REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL, INPROGRESS, 0, TIMEOUT_US);
- if (ret) {
- ivpu_err(vdev, "Failed to sync before D0i3 transition: %d\n", ret);
- return ret;
- }
-
- val = REGB_RD32(VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL);
- if (enable)
- val = REG_SET_FLD(VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL, I3, val);
- else
- val = REG_CLR_FLD(VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL, I3, val);
- REGB_WR32(VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL, val);
-
- ret = REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL, INPROGRESS, 0, TIMEOUT_US);
- if (ret)
- ivpu_err(vdev, "Failed to sync after D0i3 transition: %d\n", ret);
-
- return ret;
-}
-
-static int ivpu_hw_37xx_info_init(struct ivpu_device *vdev)
-{
- struct ivpu_hw_info *hw = vdev->hw;
-
- hw->tile_fuse = TILE_FUSE_ENABLE_BOTH;
- hw->sku = TILE_SKU_BOTH;
- hw->config = WP_CONFIG_2_TILE_4_3_RATIO;
-
- ivpu_pll_init_frequency_ratios(vdev);
-
- ivpu_hw_init_range(&hw->ranges.global, 0x80000000, SZ_512M);
- ivpu_hw_init_range(&hw->ranges.user, 0xc0000000, 255 * SZ_1M);
- ivpu_hw_init_range(&hw->ranges.shave, 0x180000000, SZ_2G);
- ivpu_hw_init_range(&hw->ranges.dma, 0x200000000, SZ_8G);
-
- vdev->platform = IVPU_PLATFORM_SILICON;
- ivpu_hw_wa_init(vdev);
- ivpu_hw_timeouts_init(vdev);
-
- return 0;
-}
-
-static int ivpu_hw_37xx_ip_reset(struct ivpu_device *vdev)
-{
- int ret;
- u32 val;
-
- if (IVPU_WA(punit_disabled))
- return 0;
-
- ret = REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_IP_RESET, TRIGGER, 0, TIMEOUT_US);
- if (ret) {
- ivpu_err(vdev, "Timed out waiting for TRIGGER bit\n");
- return ret;
- }
-
- val = REGB_RD32(VPU_37XX_BUTTRESS_VPU_IP_RESET);
- val = REG_SET_FLD(VPU_37XX_BUTTRESS_VPU_IP_RESET, TRIGGER, val);
- REGB_WR32(VPU_37XX_BUTTRESS_VPU_IP_RESET, val);
-
- ret = REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_IP_RESET, TRIGGER, 0, TIMEOUT_US);
- if (ret)
- ivpu_err(vdev, "Timed out waiting for RESET completion\n");
-
- return ret;
-}
-
-static int ivpu_hw_37xx_reset(struct ivpu_device *vdev)
-{
- int ret = 0;
-
- if (ivpu_hw_37xx_ip_reset(vdev)) {
- ivpu_err(vdev, "Failed to reset NPU\n");
- ret = -EIO;
- }
-
- if (ivpu_pll_disable(vdev)) {
- ivpu_err(vdev, "Failed to disable PLL\n");
- ret = -EIO;
- }
-
- return ret;
-}
-
-static int ivpu_hw_37xx_d0i3_enable(struct ivpu_device *vdev)
-{
- int ret;
-
- ret = ivpu_boot_d0i3_drive(vdev, true);
- if (ret)
- ivpu_err(vdev, "Failed to enable D0i3: %d\n", ret);
-
- udelay(5); /* VPU requires 5 us to complete the transition */
-
- return ret;
-}
-
-static int ivpu_hw_37xx_d0i3_disable(struct ivpu_device *vdev)
-{
- int ret;
-
- ret = ivpu_boot_d0i3_drive(vdev, false);
- if (ret)
- ivpu_err(vdev, "Failed to disable D0i3: %d\n", ret);
-
- return ret;
-}
-
-static int ivpu_hw_37xx_power_up(struct ivpu_device *vdev)
-{
- int ret;
-
- /* PLL requests may fail when powering down, so issue WP 0 here */
- ret = ivpu_pll_disable(vdev);
- if (ret)
- ivpu_warn(vdev, "Failed to disable PLL: %d\n", ret);
-
- ret = ivpu_hw_37xx_d0i3_disable(vdev);
- if (ret)
- ivpu_warn(vdev, "Failed to disable D0I3: %d\n", ret);
-
- ret = ivpu_pll_enable(vdev);
- if (ret) {
- ivpu_err(vdev, "Failed to enable PLL: %d\n", ret);
- return ret;
- }
-
- ret = ivpu_boot_host_ss_configure(vdev);
- if (ret) {
- ivpu_err(vdev, "Failed to configure host SS: %d\n", ret);
- return ret;
- }
-
- /*
- * The control circuitry for vpu_idle indication logic powers up active.
- * To ensure unnecessary low power mode signal from LRT during bring up,
- * KMD disables the circuitry prior to bringing up the Main Power island.
- */
- ivpu_boot_vpu_idle_gen_disable(vdev);
-
- ret = ivpu_boot_pwr_domain_enable(vdev);
- if (ret) {
- ivpu_err(vdev, "Failed to enable power domain: %d\n", ret);
- return ret;
- }
-
- ret = ivpu_boot_host_ss_axi_enable(vdev);
- if (ret) {
- ivpu_err(vdev, "Failed to enable AXI: %d\n", ret);
- return ret;
- }
-
- ret = ivpu_boot_host_ss_top_noc_enable(vdev);
- if (ret)
- ivpu_err(vdev, "Failed to enable TOP NOC: %d\n", ret);
-
- return ret;
-}
-
-static int ivpu_hw_37xx_boot_fw(struct ivpu_device *vdev)
-{
- ivpu_boot_no_snoop_enable(vdev);
- ivpu_boot_tbu_mmu_enable(vdev);
- ivpu_boot_soc_cpu_boot(vdev);
-
- return 0;
-}
-
-static bool ivpu_hw_37xx_is_idle(struct ivpu_device *vdev)
-{
- u32 val;
-
- if (IVPU_WA(punit_disabled))
- return true;
-
- val = REGB_RD32(VPU_37XX_BUTTRESS_VPU_STATUS);
- return REG_TEST_FLD(VPU_37XX_BUTTRESS_VPU_STATUS, READY, val) &&
- REG_TEST_FLD(VPU_37XX_BUTTRESS_VPU_STATUS, IDLE, val);
-}
-
-static int ivpu_hw_37xx_wait_for_idle(struct ivpu_device *vdev)
-{
- return REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_STATUS, IDLE, 0x1, IDLE_TIMEOUT_US);
-}
-
-static void ivpu_hw_37xx_save_d0i3_entry_timestamp(struct ivpu_device *vdev)
-{
- vdev->hw->d0i3_entry_host_ts = ktime_get_boottime();
- vdev->hw->d0i3_entry_vpu_ts = REGV_RD64(VPU_37XX_CPU_SS_TIM_PERF_FREE_CNT);
-}
-
-static int ivpu_hw_37xx_power_down(struct ivpu_device *vdev)
-{
- int ret = 0;
-
- ivpu_hw_37xx_save_d0i3_entry_timestamp(vdev);
-
- if (!ivpu_hw_37xx_is_idle(vdev))
- ivpu_warn(vdev, "NPU not idle during power down\n");
-
- if (ivpu_hw_37xx_reset(vdev)) {
- ivpu_err(vdev, "Failed to reset NPU\n");
- ret = -EIO;
- }
-
- if (ivpu_hw_37xx_d0i3_enable(vdev)) {
- ivpu_err(vdev, "Failed to enter D0I3\n");
- ret = -EIO;
- }
-
- return ret;
-}
-
-static void ivpu_hw_37xx_wdt_disable(struct ivpu_device *vdev)
-{
- u32 val;
-
- /* Enable writing and set non-zero WDT value */
- REGV_WR32(VPU_37XX_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE);
- REGV_WR32(VPU_37XX_CPU_SS_TIM_WATCHDOG, TIM_WATCHDOG_RESET_VALUE);
-
- /* Enable writing and disable watchdog timer */
- REGV_WR32(VPU_37XX_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE);
- REGV_WR32(VPU_37XX_CPU_SS_TIM_WDOG_EN, 0);
-
- /* Now clear the timeout interrupt */
- val = REGV_RD32(VPU_37XX_CPU_SS_TIM_GEN_CONFIG);
- val = REG_CLR_FLD(VPU_37XX_CPU_SS_TIM_GEN_CONFIG, WDOG_TO_INT_CLR, val);
- REGV_WR32(VPU_37XX_CPU_SS_TIM_GEN_CONFIG, val);
-}
-
-static u32 ivpu_hw_37xx_profiling_freq_get(struct ivpu_device *vdev)
-{
- return PLL_PROF_CLK_FREQ;
-}
-
-static void ivpu_hw_37xx_profiling_freq_drive(struct ivpu_device *vdev, bool enable)
-{
- /* Profiling freq - is a debug feature. Unavailable on VPU 37XX. */
-}
-
-static u32 ivpu_hw_37xx_ratio_to_freq(struct ivpu_device *vdev, u32 ratio)
-{
- u32 pll_clock = PLL_REF_CLK_FREQ * ratio;
- u32 cpu_clock;
-
- if ((vdev->hw->config & 0xff) == PLL_RATIO_4_3)
- cpu_clock = pll_clock * 2 / 4;
- else
- cpu_clock = pll_clock * 2 / 5;
-
- return cpu_clock;
-}
-
-/* Register indirect accesses */
-static u32 ivpu_hw_37xx_reg_pll_freq_get(struct ivpu_device *vdev)
-{
- u32 pll_curr_ratio;
-
- pll_curr_ratio = REGB_RD32(VPU_37XX_BUTTRESS_CURRENT_PLL);
- pll_curr_ratio &= VPU_37XX_BUTTRESS_CURRENT_PLL_RATIO_MASK;
-
- if (!ivpu_is_silicon(vdev))
- return PLL_SIMULATION_FREQ;
-
- return ivpu_hw_37xx_ratio_to_freq(vdev, pll_curr_ratio);
-}
-
-static u32 ivpu_hw_37xx_reg_telemetry_offset_get(struct ivpu_device *vdev)
-{
- return REGB_RD32(VPU_37XX_BUTTRESS_VPU_TELEMETRY_OFFSET);
-}
-
-static u32 ivpu_hw_37xx_reg_telemetry_size_get(struct ivpu_device *vdev)
-{
- return REGB_RD32(VPU_37XX_BUTTRESS_VPU_TELEMETRY_SIZE);
-}
-
-static u32 ivpu_hw_37xx_reg_telemetry_enable_get(struct ivpu_device *vdev)
-{
- return REGB_RD32(VPU_37XX_BUTTRESS_VPU_TELEMETRY_ENABLE);
-}
-
-static void ivpu_hw_37xx_reg_db_set(struct ivpu_device *vdev, u32 db_id)
-{
- u32 reg_stride = VPU_37XX_CPU_SS_DOORBELL_1 - VPU_37XX_CPU_SS_DOORBELL_0;
- u32 val = REG_FLD(VPU_37XX_CPU_SS_DOORBELL_0, SET);
-
- REGV_WR32I(VPU_37XX_CPU_SS_DOORBELL_0, reg_stride, db_id, val);
-}
-
-static u32 ivpu_hw_37xx_reg_ipc_rx_addr_get(struct ivpu_device *vdev)
-{
- return REGV_RD32(VPU_37XX_HOST_SS_TIM_IPC_FIFO_ATM);
-}
-
-static u32 ivpu_hw_37xx_reg_ipc_rx_count_get(struct ivpu_device *vdev)
-{
- u32 count = REGV_RD32_SILENT(VPU_37XX_HOST_SS_TIM_IPC_FIFO_STAT);
-
- return REG_GET_FLD(VPU_37XX_HOST_SS_TIM_IPC_FIFO_STAT, FILL_LEVEL, count);
-}
-
-static void ivpu_hw_37xx_reg_ipc_tx_set(struct ivpu_device *vdev, u32 vpu_addr)
-{
- REGV_WR32(VPU_37XX_CPU_SS_TIM_IPC_FIFO, vpu_addr);
-}
-
-static void ivpu_hw_37xx_irq_clear(struct ivpu_device *vdev)
-{
- REGV_WR64(VPU_37XX_HOST_SS_ICB_CLEAR_0, ICB_0_1_IRQ_MASK);
-}
-
-static void ivpu_hw_37xx_irq_enable(struct ivpu_device *vdev)
-{
- REGV_WR32(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, ITF_FIREWALL_VIOLATION_MASK);
- REGV_WR64(VPU_37XX_HOST_SS_ICB_ENABLE_0, ICB_0_1_IRQ_MASK);
- REGB_WR32(VPU_37XX_BUTTRESS_LOCAL_INT_MASK, BUTTRESS_IRQ_ENABLE_MASK);
- REGB_WR32(VPU_37XX_BUTTRESS_GLOBAL_INT_MASK, 0x0);
-}
-
-static void ivpu_hw_37xx_irq_disable(struct ivpu_device *vdev)
-{
- REGB_WR32(VPU_37XX_BUTTRESS_GLOBAL_INT_MASK, 0x1);
- REGB_WR32(VPU_37XX_BUTTRESS_LOCAL_INT_MASK, BUTTRESS_IRQ_DISABLE_MASK);
- REGV_WR64(VPU_37XX_HOST_SS_ICB_ENABLE_0, 0x0ull);
- REGV_WR32(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, 0x0);
-}
-
-static void ivpu_hw_37xx_irq_wdt_nce_handler(struct ivpu_device *vdev)
-{
- ivpu_pm_trigger_recovery(vdev, "WDT NCE IRQ");
-}
-
-static void ivpu_hw_37xx_irq_wdt_mss_handler(struct ivpu_device *vdev)
-{
- ivpu_hw_wdt_disable(vdev);
- ivpu_pm_trigger_recovery(vdev, "WDT MSS IRQ");
-}
-
-static void ivpu_hw_37xx_irq_noc_firewall_handler(struct ivpu_device *vdev)
-{
- ivpu_pm_trigger_recovery(vdev, "NOC Firewall IRQ");
-}
-
-/* Handler for IRQs from VPU core (irqV) */
-static bool ivpu_hw_37xx_irqv_handler(struct ivpu_device *vdev, int irq, bool *wake_thread)
-{
- u32 status = REGV_RD32(VPU_37XX_HOST_SS_ICB_STATUS_0) & ICB_0_IRQ_MASK;
-
- if (!status)
- return false;
-
- REGV_WR32(VPU_37XX_HOST_SS_ICB_CLEAR_0, status);
-
- if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_0_INT, status))
- ivpu_mmu_irq_evtq_handler(vdev);
-
- if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, HOST_IPC_FIFO_INT, status))
- ivpu_ipc_irq_handler(vdev, wake_thread);
-
- if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_1_INT, status))
- ivpu_dbg(vdev, IRQ, "MMU sync complete\n");
-
- if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_2_INT, status))
- ivpu_mmu_irq_gerr_handler(vdev);
-
- if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT, status))
- ivpu_hw_37xx_irq_wdt_mss_handler(vdev);
-
- if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT, status))
- ivpu_hw_37xx_irq_wdt_nce_handler(vdev);
-
- if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT, status))
- ivpu_hw_37xx_irq_noc_firewall_handler(vdev);
-
- return true;
-}
-
-/* Handler for IRQs from Buttress core (irqB) */
-static bool ivpu_hw_37xx_irqb_handler(struct ivpu_device *vdev, int irq)
-{
- u32 status = REGB_RD32(VPU_37XX_BUTTRESS_INTERRUPT_STAT) & BUTTRESS_IRQ_MASK;
- bool schedule_recovery = false;
-
- if (!status)
- return false;
-
- if (REG_TEST_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, FREQ_CHANGE, status))
- ivpu_dbg(vdev, IRQ, "FREQ_CHANGE irq: %08x",
- REGB_RD32(VPU_37XX_BUTTRESS_CURRENT_PLL));
-
- if (REG_TEST_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, ATS_ERR, status)) {
- ivpu_err(vdev, "ATS_ERR irq 0x%016llx", REGB_RD64(VPU_37XX_BUTTRESS_ATS_ERR_LOG_0));
- REGB_WR32(VPU_37XX_BUTTRESS_ATS_ERR_CLEAR, 0x1);
- schedule_recovery = true;
- }
-
- if (REG_TEST_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, UFI_ERR, status)) {
- u32 ufi_log = REGB_RD32(VPU_37XX_BUTTRESS_UFI_ERR_LOG);
-
- ivpu_err(vdev, "UFI_ERR irq (0x%08x) opcode: 0x%02lx axi_id: 0x%02lx cq_id: 0x%03lx",
- ufi_log, REG_GET_FLD(VPU_37XX_BUTTRESS_UFI_ERR_LOG, OPCODE, ufi_log),
- REG_GET_FLD(VPU_37XX_BUTTRESS_UFI_ERR_LOG, AXI_ID, ufi_log),
- REG_GET_FLD(VPU_37XX_BUTTRESS_UFI_ERR_LOG, CQ_ID, ufi_log));
- REGB_WR32(VPU_37XX_BUTTRESS_UFI_ERR_CLEAR, 0x1);
- schedule_recovery = true;
- }
-
- /* This must be done after interrupts are cleared at the source. */
- if (IVPU_WA(interrupt_clear_with_0))
- /*
- * Writing 1 triggers an interrupt, so we can't perform read update write.
- * Clear local interrupt status by writing 0 to all bits.
- */
- REGB_WR32(VPU_37XX_BUTTRESS_INTERRUPT_STAT, 0x0);
- else
- REGB_WR32(VPU_37XX_BUTTRESS_INTERRUPT_STAT, status);
-
- if (schedule_recovery)
- ivpu_pm_trigger_recovery(vdev, "Buttress IRQ");
-
- return true;
-}
-
-static irqreturn_t ivpu_hw_37xx_irq_handler(int irq, void *ptr)
-{
- struct ivpu_device *vdev = ptr;
- bool irqv_handled, irqb_handled, wake_thread = false;
-
- REGB_WR32(VPU_37XX_BUTTRESS_GLOBAL_INT_MASK, 0x1);
-
- irqv_handled = ivpu_hw_37xx_irqv_handler(vdev, irq, &wake_thread);
- irqb_handled = ivpu_hw_37xx_irqb_handler(vdev, irq);
-
- /* Re-enable global interrupts to re-trigger MSI for pending interrupts */
- REGB_WR32(VPU_37XX_BUTTRESS_GLOBAL_INT_MASK, 0x0);
-
- if (wake_thread)
- return IRQ_WAKE_THREAD;
- if (irqv_handled || irqb_handled)
- return IRQ_HANDLED;
- return IRQ_NONE;
-}
-
-static void ivpu_hw_37xx_diagnose_failure(struct ivpu_device *vdev)
-{
- u32 irqv = REGV_RD32(VPU_37XX_HOST_SS_ICB_STATUS_0) & ICB_0_IRQ_MASK;
- u32 irqb = REGB_RD32(VPU_37XX_BUTTRESS_INTERRUPT_STAT) & BUTTRESS_IRQ_MASK;
-
- if (ivpu_hw_37xx_reg_ipc_rx_count_get(vdev))
- ivpu_err(vdev, "IPC FIFO queue not empty, missed IPC IRQ");
-
- if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT, irqv))
- ivpu_err(vdev, "WDT MSS timeout detected\n");
-
- if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT, irqv))
- ivpu_err(vdev, "WDT NCE timeout detected\n");
-
- if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT, irqv))
- ivpu_err(vdev, "NOC Firewall irq detected\n");
-
- if (REG_TEST_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, ATS_ERR, irqb))
- ivpu_err(vdev, "ATS_ERR irq 0x%016llx", REGB_RD64(VPU_37XX_BUTTRESS_ATS_ERR_LOG_0));
-
- if (REG_TEST_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, UFI_ERR, irqb)) {
- u32 ufi_log = REGB_RD32(VPU_37XX_BUTTRESS_UFI_ERR_LOG);
-
- ivpu_err(vdev, "UFI_ERR irq (0x%08x) opcode: 0x%02lx axi_id: 0x%02lx cq_id: 0x%03lx",
- ufi_log, REG_GET_FLD(VPU_37XX_BUTTRESS_UFI_ERR_LOG, OPCODE, ufi_log),
- REG_GET_FLD(VPU_37XX_BUTTRESS_UFI_ERR_LOG, AXI_ID, ufi_log),
- REG_GET_FLD(VPU_37XX_BUTTRESS_UFI_ERR_LOG, CQ_ID, ufi_log));
- }
-}
-
-const struct ivpu_hw_ops ivpu_hw_37xx_ops = {
- .info_init = ivpu_hw_37xx_info_init,
- .power_up = ivpu_hw_37xx_power_up,
- .is_idle = ivpu_hw_37xx_is_idle,
- .wait_for_idle = ivpu_hw_37xx_wait_for_idle,
- .power_down = ivpu_hw_37xx_power_down,
- .reset = ivpu_hw_37xx_reset,
- .boot_fw = ivpu_hw_37xx_boot_fw,
- .wdt_disable = ivpu_hw_37xx_wdt_disable,
- .diagnose_failure = ivpu_hw_37xx_diagnose_failure,
- .profiling_freq_get = ivpu_hw_37xx_profiling_freq_get,
- .profiling_freq_drive = ivpu_hw_37xx_profiling_freq_drive,
- .reg_pll_freq_get = ivpu_hw_37xx_reg_pll_freq_get,
- .ratio_to_freq = ivpu_hw_37xx_ratio_to_freq,
- .reg_telemetry_offset_get = ivpu_hw_37xx_reg_telemetry_offset_get,
- .reg_telemetry_size_get = ivpu_hw_37xx_reg_telemetry_size_get,
- .reg_telemetry_enable_get = ivpu_hw_37xx_reg_telemetry_enable_get,
- .reg_db_set = ivpu_hw_37xx_reg_db_set,
- .reg_ipc_rx_addr_get = ivpu_hw_37xx_reg_ipc_rx_addr_get,
- .reg_ipc_rx_count_get = ivpu_hw_37xx_reg_ipc_rx_count_get,
- .reg_ipc_tx_set = ivpu_hw_37xx_reg_ipc_tx_set,
- .irq_clear = ivpu_hw_37xx_irq_clear,
- .irq_enable = ivpu_hw_37xx_irq_enable,
- .irq_disable = ivpu_hw_37xx_irq_disable,
- .irq_handler = ivpu_hw_37xx_irq_handler,
-};
diff --git a/drivers/accel/ivpu/ivpu_hw_37xx_reg.h b/drivers/accel/ivpu/ivpu_hw_37xx_reg.h
index f6fec1919202..cf5e2f01049c 100644
--- a/drivers/accel/ivpu/ivpu_hw_37xx_reg.h
+++ b/drivers/accel/ivpu/ivpu_hw_37xx_reg.h
@@ -8,78 +8,6 @@
#include <linux/bits.h>
-#define VPU_37XX_BUTTRESS_INTERRUPT_TYPE 0x00000000u
-
-#define VPU_37XX_BUTTRESS_INTERRUPT_STAT 0x00000004u
-#define VPU_37XX_BUTTRESS_INTERRUPT_STAT_FREQ_CHANGE_MASK BIT_MASK(0)
-#define VPU_37XX_BUTTRESS_INTERRUPT_STAT_ATS_ERR_MASK BIT_MASK(1)
-#define VPU_37XX_BUTTRESS_INTERRUPT_STAT_UFI_ERR_MASK BIT_MASK(2)
-
-#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0 0x00000008u
-#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0_MIN_RATIO_MASK GENMASK(15, 0)
-#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0_MAX_RATIO_MASK GENMASK(31, 16)
-
-#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1 0x0000000cu
-#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1_TARGET_RATIO_MASK GENMASK(15, 0)
-#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1_EPP_MASK GENMASK(31, 16)
-
-#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD2 0x00000010u
-#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD2_CONFIG_MASK GENMASK(15, 0)
-
-#define VPU_37XX_BUTTRESS_WP_REQ_CMD 0x00000014u
-#define VPU_37XX_BUTTRESS_WP_REQ_CMD_SEND_MASK BIT_MASK(0)
-
-#define VPU_37XX_BUTTRESS_WP_DOWNLOAD 0x00000018u
-#define VPU_37XX_BUTTRESS_WP_DOWNLOAD_TARGET_RATIO_MASK GENMASK(15, 0)
-
-#define VPU_37XX_BUTTRESS_CURRENT_PLL 0x0000001cu
-#define VPU_37XX_BUTTRESS_CURRENT_PLL_RATIO_MASK GENMASK(15, 0)
-
-#define VPU_37XX_BUTTRESS_PLL_ENABLE 0x00000020u
-
-#define VPU_37XX_BUTTRESS_FMIN_FUSE 0x00000024u
-#define VPU_37XX_BUTTRESS_FMIN_FUSE_MIN_RATIO_MASK GENMASK(7, 0)
-#define VPU_37XX_BUTTRESS_FMIN_FUSE_PN_RATIO_MASK GENMASK(15, 8)
-
-#define VPU_37XX_BUTTRESS_FMAX_FUSE 0x00000028u
-#define VPU_37XX_BUTTRESS_FMAX_FUSE_MAX_RATIO_MASK GENMASK(7, 0)
-
-#define VPU_37XX_BUTTRESS_TILE_FUSE 0x0000002cu
-#define VPU_37XX_BUTTRESS_TILE_FUSE_VALID_MASK BIT_MASK(0)
-#define VPU_37XX_BUTTRESS_TILE_FUSE_SKU_MASK GENMASK(3, 2)
-
-#define VPU_37XX_BUTTRESS_LOCAL_INT_MASK 0x00000030u
-#define VPU_37XX_BUTTRESS_GLOBAL_INT_MASK 0x00000034u
-
-#define VPU_37XX_BUTTRESS_PLL_STATUS 0x00000040u
-#define VPU_37XX_BUTTRESS_PLL_STATUS_LOCK_MASK BIT_MASK(1)
-
-#define VPU_37XX_BUTTRESS_VPU_STATUS 0x00000044u
-#define VPU_37XX_BUTTRESS_VPU_STATUS_READY_MASK BIT_MASK(0)
-#define VPU_37XX_BUTTRESS_VPU_STATUS_IDLE_MASK BIT_MASK(1)
-
-#define VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL 0x00000060u
-#define VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL_INPROGRESS_MASK BIT_MASK(0)
-#define VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL_I3_MASK BIT_MASK(2)
-
-#define VPU_37XX_BUTTRESS_VPU_IP_RESET 0x00000050u
-#define VPU_37XX_BUTTRESS_VPU_IP_RESET_TRIGGER_MASK BIT_MASK(0)
-
-#define VPU_37XX_BUTTRESS_VPU_TELEMETRY_OFFSET 0x00000080u
-#define VPU_37XX_BUTTRESS_VPU_TELEMETRY_SIZE 0x00000084u
-#define VPU_37XX_BUTTRESS_VPU_TELEMETRY_ENABLE 0x00000088u
-
-#define VPU_37XX_BUTTRESS_ATS_ERR_LOG_0 0x000000a0u
-#define VPU_37XX_BUTTRESS_ATS_ERR_LOG_1 0x000000a4u
-#define VPU_37XX_BUTTRESS_ATS_ERR_CLEAR 0x000000a8u
-
-#define VPU_37XX_BUTTRESS_UFI_ERR_LOG 0x000000b0u
-#define VPU_37XX_BUTTRESS_UFI_ERR_LOG_CQ_ID_MASK GENMASK(11, 0)
-#define VPU_37XX_BUTTRESS_UFI_ERR_LOG_AXI_ID_MASK GENMASK(19, 12)
-#define VPU_37XX_BUTTRESS_UFI_ERR_LOG_OPCODE_MASK GENMASK(24, 20)
-
-#define VPU_37XX_BUTTRESS_UFI_ERR_CLEAR 0x000000b4u
-
#define VPU_37XX_HOST_SS_CPR_CLK_SET 0x00000084u
#define VPU_37XX_HOST_SS_CPR_CLK_SET_TOP_NOC_MASK BIT_MASK(1)
#define VPU_37XX_HOST_SS_CPR_CLK_SET_DSS_MAS_MASK BIT_MASK(10)
diff --git a/drivers/accel/ivpu/ivpu_hw_40xx.c b/drivers/accel/ivpu/ivpu_hw_40xx.c
deleted file mode 100644
index b0b88d4c8926..000000000000
--- a/drivers/accel/ivpu/ivpu_hw_40xx.c
+++ /dev/null
@@ -1,1250 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2020-2023 Intel Corporation
- */
-
-#include "ivpu_drv.h"
-#include "ivpu_fw.h"
-#include "ivpu_hw.h"
-#include "ivpu_hw_40xx_reg.h"
-#include "ivpu_hw_reg_io.h"
-#include "ivpu_ipc.h"
-#include "ivpu_mmu.h"
-#include "ivpu_pm.h"
-
-#include <linux/dmi.h>
-
-#define TILE_MAX_NUM 6
-#define TILE_MAX_MASK 0x3f
-
-#define LNL_HW_ID 0x4040
-
-#define SKU_TILE_SHIFT 0u
-#define SKU_TILE_MASK 0x0000ffffu
-#define SKU_HW_ID_SHIFT 16u
-#define SKU_HW_ID_MASK 0xffff0000u
-
-#define PLL_CONFIG_DEFAULT 0x0
-#define PLL_CDYN_DEFAULT 0x80
-#define PLL_EPP_DEFAULT 0x80
-#define PLL_REF_CLK_FREQ (50 * 1000000)
-#define PLL_RATIO_TO_FREQ(x) ((x) * PLL_REF_CLK_FREQ)
-
-#define PLL_PROFILING_FREQ_DEFAULT 38400000
-#define PLL_PROFILING_FREQ_HIGH 400000000
-
-#define TIM_SAFE_ENABLE 0xf1d0dead
-#define TIM_WATCHDOG_RESET_VALUE 0xffffffff
-
-#define TIMEOUT_US (150 * USEC_PER_MSEC)
-#define PWR_ISLAND_STATUS_TIMEOUT_US (5 * USEC_PER_MSEC)
-#define PLL_TIMEOUT_US (1500 * USEC_PER_MSEC)
-#define IDLE_TIMEOUT_US (5 * USEC_PER_MSEC)
-
-#define WEIGHTS_DEFAULT 0xf711f711u
-#define WEIGHTS_ATS_DEFAULT 0x0000f711u
-
-#define ICB_0_IRQ_MASK ((REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, HOST_IPC_FIFO_INT)) | \
- (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_0_INT)) | \
- (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_1_INT)) | \
- (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_2_INT)) | \
- (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT)) | \
- (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT)) | \
- (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT)))
-
-#define ICB_1_IRQ_MASK ((REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_2_INT)) | \
- (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_3_INT)) | \
- (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_4_INT)))
-
-#define ICB_0_1_IRQ_MASK ((((u64)ICB_1_IRQ_MASK) << 32) | ICB_0_IRQ_MASK)
-
-#define BUTTRESS_IRQ_MASK ((REG_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, ATS_ERR)) | \
- (REG_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, CFI0_ERR)) | \
- (REG_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, CFI1_ERR)) | \
- (REG_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, IMR0_ERR)) | \
- (REG_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, IMR1_ERR)) | \
- (REG_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, SURV_ERR)))
-
-#define BUTTRESS_IRQ_ENABLE_MASK ((u32)~BUTTRESS_IRQ_MASK)
-#define BUTTRESS_IRQ_DISABLE_MASK ((u32)-1)
-
-#define ITF_FIREWALL_VIOLATION_MASK ((REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, CSS_ROM_CMX)) | \
- (REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, CSS_DBG)) | \
- (REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, CSS_CTRL)) | \
- (REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, DEC400)) | \
- (REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, MSS_NCE)) | \
- (REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, MSS_MBI)) | \
- (REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, MSS_MBI_CMX)))
-
-static char *ivpu_platform_to_str(u32 platform)
-{
- switch (platform) {
- case IVPU_PLATFORM_SILICON:
- return "SILICON";
- case IVPU_PLATFORM_SIMICS:
- return "SIMICS";
- case IVPU_PLATFORM_FPGA:
- return "FPGA";
- default:
- return "Invalid platform";
- }
-}
-
-static const struct dmi_system_id ivpu_dmi_platform_simulation[] = {
- {
- .ident = "Intel Simics",
- .matches = {
- DMI_MATCH(DMI_BOARD_NAME, "lnlrvp"),
- DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
- DMI_MATCH(DMI_BOARD_SERIAL, "123456789"),
- },
- },
- {
- .ident = "Intel Simics",
- .matches = {
- DMI_MATCH(DMI_BOARD_NAME, "Simics"),
- },
- },
- { }
-};
-
-static void ivpu_hw_read_platform(struct ivpu_device *vdev)
-{
- if (dmi_check_system(ivpu_dmi_platform_simulation))
- vdev->platform = IVPU_PLATFORM_SIMICS;
- else
- vdev->platform = IVPU_PLATFORM_SILICON;
-
- ivpu_dbg(vdev, MISC, "Platform type: %s (%d)\n",
- ivpu_platform_to_str(vdev->platform), vdev->platform);
-}
-
-static void ivpu_hw_wa_init(struct ivpu_device *vdev)
-{
- vdev->wa.punit_disabled = ivpu_is_fpga(vdev);
- vdev->wa.clear_runtime_mem = false;
-
- if (ivpu_hw_gen(vdev) == IVPU_HW_40XX)
- vdev->wa.disable_clock_relinquish = true;
-
- IVPU_PRINT_WA(punit_disabled);
- IVPU_PRINT_WA(clear_runtime_mem);
- IVPU_PRINT_WA(disable_clock_relinquish);
-}
-
-static void ivpu_hw_timeouts_init(struct ivpu_device *vdev)
-{
- if (ivpu_is_fpga(vdev)) {
- vdev->timeout.boot = 100000;
- vdev->timeout.jsm = 50000;
- vdev->timeout.tdr = 2000000;
- vdev->timeout.reschedule_suspend = 1000;
- vdev->timeout.autosuspend = -1;
- vdev->timeout.d0i3_entry_msg = 500;
- } else if (ivpu_is_simics(vdev)) {
- vdev->timeout.boot = 50;
- vdev->timeout.jsm = 500;
- vdev->timeout.tdr = 10000;
- vdev->timeout.reschedule_suspend = 10;
- vdev->timeout.autosuspend = -1;
- vdev->timeout.d0i3_entry_msg = 100;
- } else {
- vdev->timeout.boot = 1000;
- vdev->timeout.jsm = 500;
- vdev->timeout.tdr = 2000;
- vdev->timeout.reschedule_suspend = 10;
- vdev->timeout.autosuspend = 10;
- vdev->timeout.d0i3_entry_msg = 5;
- }
-}
-
-static int ivpu_pll_wait_for_cmd_send(struct ivpu_device *vdev)
-{
- return REGB_POLL_FLD(VPU_40XX_BUTTRESS_WP_REQ_CMD, SEND, 0, PLL_TIMEOUT_US);
-}
-
-static int ivpu_pll_cmd_send(struct ivpu_device *vdev, u16 min_ratio, u16 max_ratio,
- u16 target_ratio, u16 epp, u16 config, u16 cdyn)
-{
- int ret;
- u32 val;
-
- ret = ivpu_pll_wait_for_cmd_send(vdev);
- if (ret) {
- ivpu_err(vdev, "Failed to sync before WP request: %d\n", ret);
- return ret;
- }
-
- val = REGB_RD32(VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD0);
- val = REG_SET_FLD_NUM(VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD0, MIN_RATIO, min_ratio, val);
- val = REG_SET_FLD_NUM(VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD0, MAX_RATIO, max_ratio, val);
- REGB_WR32(VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD0, val);
-
- val = REGB_RD32(VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD1);
- val = REG_SET_FLD_NUM(VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD1, TARGET_RATIO, target_ratio, val);
- val = REG_SET_FLD_NUM(VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD1, EPP, epp, val);
- REGB_WR32(VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD1, val);
-
- val = REGB_RD32(VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD2);
- val = REG_SET_FLD_NUM(VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD2, CONFIG, config, val);
- val = REG_SET_FLD_NUM(VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD2, CDYN, cdyn, val);
- REGB_WR32(VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD2, val);
-
- val = REGB_RD32(VPU_40XX_BUTTRESS_WP_REQ_CMD);
- val = REG_SET_FLD(VPU_40XX_BUTTRESS_WP_REQ_CMD, SEND, val);
- REGB_WR32(VPU_40XX_BUTTRESS_WP_REQ_CMD, val);
-
- ret = ivpu_pll_wait_for_cmd_send(vdev);
- if (ret)
- ivpu_err(vdev, "Failed to sync after WP request: %d\n", ret);
-
- return ret;
-}
-
-static int ivpu_pll_wait_for_status_ready(struct ivpu_device *vdev)
-{
- return REGB_POLL_FLD(VPU_40XX_BUTTRESS_VPU_STATUS, READY, 1, PLL_TIMEOUT_US);
-}
-
-static int ivpu_wait_for_clock_own_resource_ack(struct ivpu_device *vdev)
-{
- if (ivpu_is_simics(vdev))
- return 0;
-
- return REGB_POLL_FLD(VPU_40XX_BUTTRESS_VPU_STATUS, CLOCK_RESOURCE_OWN_ACK, 1, TIMEOUT_US);
-}
-
-static void ivpu_pll_init_frequency_ratios(struct ivpu_device *vdev)
-{
- struct ivpu_hw_info *hw = vdev->hw;
- u8 fuse_min_ratio, fuse_pn_ratio, fuse_max_ratio;
- u32 fmin_fuse, fmax_fuse;
-
- fmin_fuse = REGB_RD32(VPU_40XX_BUTTRESS_FMIN_FUSE);
- fuse_min_ratio = REG_GET_FLD(VPU_40XX_BUTTRESS_FMIN_FUSE, MIN_RATIO, fmin_fuse);
- fuse_pn_ratio = REG_GET_FLD(VPU_40XX_BUTTRESS_FMIN_FUSE, PN_RATIO, fmin_fuse);
-
- fmax_fuse = REGB_RD32(VPU_40XX_BUTTRESS_FMAX_FUSE);
- fuse_max_ratio = REG_GET_FLD(VPU_40XX_BUTTRESS_FMAX_FUSE, MAX_RATIO, fmax_fuse);
-
- hw->pll.min_ratio = clamp_t(u8, ivpu_pll_min_ratio, fuse_min_ratio, fuse_max_ratio);
- hw->pll.max_ratio = clamp_t(u8, ivpu_pll_max_ratio, hw->pll.min_ratio, fuse_max_ratio);
- hw->pll.pn_ratio = clamp_t(u8, fuse_pn_ratio, hw->pll.min_ratio, hw->pll.max_ratio);
-}
-
-static int ivpu_pll_drive(struct ivpu_device *vdev, bool enable)
-{
- u16 config = enable ? PLL_CONFIG_DEFAULT : 0;
- u16 cdyn = enable ? PLL_CDYN_DEFAULT : 0;
- u16 epp = enable ? PLL_EPP_DEFAULT : 0;
- struct ivpu_hw_info *hw = vdev->hw;
- u16 target_ratio = hw->pll.pn_ratio;
- int ret;
-
- ivpu_dbg(vdev, PM, "PLL workpoint request: %u Hz, epp: 0x%x, config: 0x%x, cdyn: 0x%x\n",
- PLL_RATIO_TO_FREQ(target_ratio), epp, config, cdyn);
-
- ret = ivpu_pll_cmd_send(vdev, hw->pll.min_ratio, hw->pll.max_ratio,
- target_ratio, epp, config, cdyn);
- if (ret) {
- ivpu_err(vdev, "Failed to send PLL workpoint request: %d\n", ret);
- return ret;
- }
-
- if (enable) {
- ret = ivpu_pll_wait_for_status_ready(vdev);
- if (ret) {
- ivpu_err(vdev, "Timed out waiting for PLL ready status\n");
- return ret;
- }
- }
-
- return 0;
-}
-
-static int ivpu_pll_enable(struct ivpu_device *vdev)
-{
- return ivpu_pll_drive(vdev, true);
-}
-
-static int ivpu_pll_disable(struct ivpu_device *vdev)
-{
- return ivpu_pll_drive(vdev, false);
-}
-
-static void ivpu_boot_host_ss_rst_drive(struct ivpu_device *vdev, bool enable)
-{
- u32 val = REGV_RD32(VPU_40XX_HOST_SS_CPR_RST_EN);
-
- if (enable) {
- val = REG_SET_FLD(VPU_40XX_HOST_SS_CPR_RST_EN, TOP_NOC, val);
- val = REG_SET_FLD(VPU_40XX_HOST_SS_CPR_RST_EN, DSS_MAS, val);
- val = REG_SET_FLD(VPU_40XX_HOST_SS_CPR_RST_EN, CSS_MAS, val);
- } else {
- val = REG_CLR_FLD(VPU_40XX_HOST_SS_CPR_RST_EN, TOP_NOC, val);
- val = REG_CLR_FLD(VPU_40XX_HOST_SS_CPR_RST_EN, DSS_MAS, val);
- val = REG_CLR_FLD(VPU_40XX_HOST_SS_CPR_RST_EN, CSS_MAS, val);
- }
-
- REGV_WR32(VPU_40XX_HOST_SS_CPR_RST_EN, val);
-}
-
-static void ivpu_boot_host_ss_clk_drive(struct ivpu_device *vdev, bool enable)
-{
- u32 val = REGV_RD32(VPU_40XX_HOST_SS_CPR_CLK_EN);
-
- if (enable) {
- val = REG_SET_FLD(VPU_40XX_HOST_SS_CPR_CLK_EN, TOP_NOC, val);
- val = REG_SET_FLD(VPU_40XX_HOST_SS_CPR_CLK_EN, DSS_MAS, val);
- val = REG_SET_FLD(VPU_40XX_HOST_SS_CPR_CLK_EN, CSS_MAS, val);
- } else {
- val = REG_CLR_FLD(VPU_40XX_HOST_SS_CPR_CLK_EN, TOP_NOC, val);
- val = REG_CLR_FLD(VPU_40XX_HOST_SS_CPR_CLK_EN, DSS_MAS, val);
- val = REG_CLR_FLD(VPU_40XX_HOST_SS_CPR_CLK_EN, CSS_MAS, val);
- }
-
- REGV_WR32(VPU_40XX_HOST_SS_CPR_CLK_EN, val);
-}
-
-static int ivpu_boot_noc_qreqn_check(struct ivpu_device *vdev, u32 exp_val)
-{
- u32 val = REGV_RD32(VPU_40XX_HOST_SS_NOC_QREQN);
-
- if (!REG_TEST_FLD_NUM(VPU_40XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, exp_val, val))
- return -EIO;
-
- return 0;
-}
-
-static int ivpu_boot_noc_qacceptn_check(struct ivpu_device *vdev, u32 exp_val)
-{
- u32 val = REGV_RD32(VPU_40XX_HOST_SS_NOC_QACCEPTN);
-
- if (!REG_TEST_FLD_NUM(VPU_40XX_HOST_SS_NOC_QACCEPTN, TOP_SOCMMIO, exp_val, val))
- return -EIO;
-
- return 0;
-}
-
-static int ivpu_boot_noc_qdeny_check(struct ivpu_device *vdev, u32 exp_val)
-{
- u32 val = REGV_RD32(VPU_40XX_HOST_SS_NOC_QDENY);
-
- if (!REG_TEST_FLD_NUM(VPU_40XX_HOST_SS_NOC_QDENY, TOP_SOCMMIO, exp_val, val))
- return -EIO;
-
- return 0;
-}
-
-static int ivpu_boot_top_noc_qrenqn_check(struct ivpu_device *vdev, u32 exp_val)
-{
- u32 val = REGV_RD32(VPU_40XX_TOP_NOC_QREQN);
-
- if (!REG_TEST_FLD_NUM(VPU_40XX_TOP_NOC_QREQN, CPU_CTRL, exp_val, val) ||
- !REG_TEST_FLD_NUM(VPU_40XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, exp_val, val))
- return -EIO;
-
- return 0;
-}
-
-static int ivpu_boot_top_noc_qacceptn_check(struct ivpu_device *vdev, u32 exp_val)
-{
- u32 val = REGV_RD32(VPU_40XX_TOP_NOC_QACCEPTN);
-
- if (!REG_TEST_FLD_NUM(VPU_40XX_TOP_NOC_QACCEPTN, CPU_CTRL, exp_val, val) ||
- !REG_TEST_FLD_NUM(VPU_40XX_TOP_NOC_QACCEPTN, HOSTIF_L2CACHE, exp_val, val))
- return -EIO;
-
- return 0;
-}
-
-static int ivpu_boot_top_noc_qdeny_check(struct ivpu_device *vdev, u32 exp_val)
-{
- u32 val = REGV_RD32(VPU_40XX_TOP_NOC_QDENY);
-
- if (!REG_TEST_FLD_NUM(VPU_40XX_TOP_NOC_QDENY, CPU_CTRL, exp_val, val) ||
- !REG_TEST_FLD_NUM(VPU_40XX_TOP_NOC_QDENY, HOSTIF_L2CACHE, exp_val, val))
- return -EIO;
-
- return 0;
-}
-
-static void ivpu_boot_idle_gen_drive(struct ivpu_device *vdev, bool enable)
-{
- u32 val = REGV_RD32(VPU_40XX_HOST_SS_AON_IDLE_GEN);
-
- if (enable)
- val = REG_SET_FLD(VPU_40XX_HOST_SS_AON_IDLE_GEN, EN, val);
- else
- val = REG_CLR_FLD(VPU_40XX_HOST_SS_AON_IDLE_GEN, EN, val);
-
- REGV_WR32(VPU_40XX_HOST_SS_AON_IDLE_GEN, val);
-}
-
-static int ivpu_boot_host_ss_check(struct ivpu_device *vdev)
-{
- int ret;
-
- ret = ivpu_boot_noc_qreqn_check(vdev, 0x0);
- if (ret) {
- ivpu_err(vdev, "Failed qreqn check: %d\n", ret);
- return ret;
- }
-
- ret = ivpu_boot_noc_qacceptn_check(vdev, 0x0);
- if (ret) {
- ivpu_err(vdev, "Failed qacceptn check: %d\n", ret);
- return ret;
- }
-
- ret = ivpu_boot_noc_qdeny_check(vdev, 0x0);
- if (ret)
- ivpu_err(vdev, "Failed qdeny check %d\n", ret);
-
- return ret;
-}
-
-static int ivpu_boot_host_ss_axi_drive(struct ivpu_device *vdev, bool enable)
-{
- int ret;
- u32 val;
-
- val = REGV_RD32(VPU_40XX_HOST_SS_NOC_QREQN);
- if (enable)
- val = REG_SET_FLD(VPU_40XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, val);
- else
- val = REG_CLR_FLD(VPU_40XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, val);
- REGV_WR32(VPU_40XX_HOST_SS_NOC_QREQN, val);
-
- ret = ivpu_boot_noc_qacceptn_check(vdev, enable ? 0x1 : 0x0);
- if (ret) {
- ivpu_err(vdev, "Failed qacceptn check: %d\n", ret);
- return ret;
- }
-
- ret = ivpu_boot_noc_qdeny_check(vdev, 0x0);
- if (ret) {
- ivpu_err(vdev, "Failed qdeny check: %d\n", ret);
- return ret;
- }
-
- if (enable) {
- REGB_WR32(VPU_40XX_BUTTRESS_PORT_ARBITRATION_WEIGHTS, WEIGHTS_DEFAULT);
- REGB_WR32(VPU_40XX_BUTTRESS_PORT_ARBITRATION_WEIGHTS_ATS, WEIGHTS_ATS_DEFAULT);
- }
-
- return ret;
-}
-
-static int ivpu_boot_host_ss_axi_enable(struct ivpu_device *vdev)
-{
- return ivpu_boot_host_ss_axi_drive(vdev, true);
-}
-
-static int ivpu_boot_host_ss_top_noc_drive(struct ivpu_device *vdev, bool enable)
-{
- int ret;
- u32 val;
-
- val = REGV_RD32(VPU_40XX_TOP_NOC_QREQN);
- if (enable) {
- val = REG_SET_FLD(VPU_40XX_TOP_NOC_QREQN, CPU_CTRL, val);
- val = REG_SET_FLD(VPU_40XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, val);
- } else {
- val = REG_CLR_FLD(VPU_40XX_TOP_NOC_QREQN, CPU_CTRL, val);
- val = REG_CLR_FLD(VPU_40XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, val);
- }
- REGV_WR32(VPU_40XX_TOP_NOC_QREQN, val);
-
- ret = ivpu_boot_top_noc_qacceptn_check(vdev, enable ? 0x1 : 0x0);
- if (ret) {
- ivpu_err(vdev, "Failed qacceptn check: %d\n", ret);
- return ret;
- }
-
- ret = ivpu_boot_top_noc_qdeny_check(vdev, 0x0);
- if (ret)
- ivpu_err(vdev, "Failed qdeny check: %d\n", ret);
-
- return ret;
-}
-
-static int ivpu_boot_host_ss_top_noc_enable(struct ivpu_device *vdev)
-{
- return ivpu_boot_host_ss_top_noc_drive(vdev, true);
-}
-
-static void ivpu_boot_pwr_island_trickle_drive(struct ivpu_device *vdev, bool enable)
-{
- u32 val = REGV_RD32(VPU_40XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0);
-
- if (enable)
- val = REG_SET_FLD(VPU_40XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, CSS_CPU, val);
- else
- val = REG_CLR_FLD(VPU_40XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, CSS_CPU, val);
-
- REGV_WR32(VPU_40XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, val);
-
- if (enable)
- ndelay(500);
-}
-
-static void ivpu_boot_pwr_island_drive(struct ivpu_device *vdev, bool enable)
-{
- u32 val = REGV_RD32(VPU_40XX_HOST_SS_AON_PWR_ISLAND_EN0);
-
- if (enable)
- val = REG_SET_FLD(VPU_40XX_HOST_SS_AON_PWR_ISLAND_EN0, CSS_CPU, val);
- else
- val = REG_CLR_FLD(VPU_40XX_HOST_SS_AON_PWR_ISLAND_EN0, CSS_CPU, val);
-
- REGV_WR32(VPU_40XX_HOST_SS_AON_PWR_ISLAND_EN0, val);
-
- if (!enable)
- ndelay(500);
-}
-
-static int ivpu_boot_wait_for_pwr_island_status(struct ivpu_device *vdev, u32 exp_val)
-{
- if (ivpu_is_fpga(vdev))
- return 0;
-
- return REGV_POLL_FLD(VPU_40XX_HOST_SS_AON_PWR_ISLAND_STATUS0, CSS_CPU,
- exp_val, PWR_ISLAND_STATUS_TIMEOUT_US);
-}
-
-static void ivpu_boot_pwr_island_isolation_drive(struct ivpu_device *vdev, bool enable)
-{
- u32 val = REGV_RD32(VPU_40XX_HOST_SS_AON_PWR_ISO_EN0);
-
- if (enable)
- val = REG_SET_FLD(VPU_40XX_HOST_SS_AON_PWR_ISO_EN0, CSS_CPU, val);
- else
- val = REG_CLR_FLD(VPU_40XX_HOST_SS_AON_PWR_ISO_EN0, CSS_CPU, val);
-
- REGV_WR32(VPU_40XX_HOST_SS_AON_PWR_ISO_EN0, val);
-}
-
-static void ivpu_boot_no_snoop_enable(struct ivpu_device *vdev)
-{
- u32 val = REGV_RD32(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES);
-
- val = REG_SET_FLD(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, SNOOP_OVERRIDE_EN, val);
- val = REG_SET_FLD(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, AW_SNOOP_OVERRIDE, val);
- val = REG_CLR_FLD(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, AR_SNOOP_OVERRIDE, val);
-
- REGV_WR32(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, val);
-}
-
-static void ivpu_boot_tbu_mmu_enable(struct ivpu_device *vdev)
-{
- u32 val = REGV_RD32(VPU_40XX_HOST_IF_TBU_MMUSSIDV);
-
- val = REG_SET_FLD(VPU_40XX_HOST_IF_TBU_MMUSSIDV, TBU0_AWMMUSSIDV, val);
- val = REG_SET_FLD(VPU_40XX_HOST_IF_TBU_MMUSSIDV, TBU0_ARMMUSSIDV, val);
- val = REG_SET_FLD(VPU_40XX_HOST_IF_TBU_MMUSSIDV, TBU1_AWMMUSSIDV, val);
- val = REG_SET_FLD(VPU_40XX_HOST_IF_TBU_MMUSSIDV, TBU1_ARMMUSSIDV, val);
- val = REG_SET_FLD(VPU_40XX_HOST_IF_TBU_MMUSSIDV, TBU2_AWMMUSSIDV, val);
- val = REG_SET_FLD(VPU_40XX_HOST_IF_TBU_MMUSSIDV, TBU2_ARMMUSSIDV, val);
-
- REGV_WR32(VPU_40XX_HOST_IF_TBU_MMUSSIDV, val);
-}
-
-static int ivpu_boot_cpu_noc_qacceptn_check(struct ivpu_device *vdev, u32 exp_val)
-{
- u32 val = REGV_RD32(VPU_40XX_CPU_SS_CPR_NOC_QACCEPTN);
-
- if (!REG_TEST_FLD_NUM(VPU_40XX_CPU_SS_CPR_NOC_QACCEPTN, TOP_MMIO, exp_val, val))
- return -EIO;
-
- return 0;
-}
-
-static int ivpu_boot_cpu_noc_qdeny_check(struct ivpu_device *vdev, u32 exp_val)
-{
- u32 val = REGV_RD32(VPU_40XX_CPU_SS_CPR_NOC_QDENY);
-
- if (!REG_TEST_FLD_NUM(VPU_40XX_CPU_SS_CPR_NOC_QDENY, TOP_MMIO, exp_val, val))
- return -EIO;
-
- return 0;
-}
-
-static int ivpu_boot_pwr_domain_enable(struct ivpu_device *vdev)
-{
- int ret;
-
- ret = ivpu_wait_for_clock_own_resource_ack(vdev);
- if (ret) {
- ivpu_err(vdev, "Timed out waiting for clock own resource ACK\n");
- return ret;
- }
-
- ivpu_boot_pwr_island_trickle_drive(vdev, true);
- ivpu_boot_pwr_island_drive(vdev, true);
-
- ret = ivpu_boot_wait_for_pwr_island_status(vdev, 0x1);
- if (ret) {
- ivpu_err(vdev, "Timed out waiting for power island status\n");
- return ret;
- }
-
- ret = ivpu_boot_top_noc_qrenqn_check(vdev, 0x0);
- if (ret) {
- ivpu_err(vdev, "Failed qrenqn check %d\n", ret);
- return ret;
- }
-
- ivpu_boot_host_ss_clk_drive(vdev, true);
- ivpu_boot_host_ss_rst_drive(vdev, true);
- ivpu_boot_pwr_island_isolation_drive(vdev, false);
-
- return ret;
-}
-
-static int ivpu_boot_soc_cpu_drive(struct ivpu_device *vdev, bool enable)
-{
- int ret;
- u32 val;
-
- val = REGV_RD32(VPU_40XX_CPU_SS_CPR_NOC_QREQN);
- if (enable)
- val = REG_SET_FLD(VPU_40XX_CPU_SS_CPR_NOC_QREQN, TOP_MMIO, val);
- else
- val = REG_CLR_FLD(VPU_40XX_CPU_SS_CPR_NOC_QREQN, TOP_MMIO, val);
- REGV_WR32(VPU_40XX_CPU_SS_CPR_NOC_QREQN, val);
-
- ret = ivpu_boot_cpu_noc_qacceptn_check(vdev, enable ? 0x1 : 0x0);
- if (ret) {
- ivpu_err(vdev, "Failed qacceptn check: %d\n", ret);
- return ret;
- }
-
- ret = ivpu_boot_cpu_noc_qdeny_check(vdev, 0x0);
- if (ret)
- ivpu_err(vdev, "Failed qdeny check: %d\n", ret);
-
- return ret;
-}
-
-static int ivpu_boot_soc_cpu_enable(struct ivpu_device *vdev)
-{
- return ivpu_boot_soc_cpu_drive(vdev, true);
-}
-
-static int ivpu_boot_soc_cpu_boot(struct ivpu_device *vdev)
-{
- int ret;
- u32 val;
- u64 val64;
-
- ret = ivpu_boot_soc_cpu_enable(vdev);
- if (ret) {
- ivpu_err(vdev, "Failed to enable SOC CPU: %d\n", ret);
- return ret;
- }
-
- val64 = vdev->fw->entry_point;
- val64 <<= ffs(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO_IMAGE_LOCATION_MASK) - 1;
- REGV_WR64(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO, val64);
-
- val = REGV_RD32(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO);
- val = REG_SET_FLD(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO, DONE, val);
- REGV_WR32(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO, val);
-
- ivpu_dbg(vdev, PM, "Booting firmware, mode: %s\n",
- ivpu_fw_is_cold_boot(vdev) ? "cold boot" : "resume");
-
- return 0;
-}
-
-static int ivpu_boot_d0i3_drive(struct ivpu_device *vdev, bool enable)
-{
- int ret;
- u32 val;
-
- ret = REGB_POLL_FLD(VPU_40XX_BUTTRESS_D0I3_CONTROL, INPROGRESS, 0, TIMEOUT_US);
- if (ret) {
- ivpu_err(vdev, "Failed to sync before D0i3 transition: %d\n", ret);
- return ret;
- }
-
- val = REGB_RD32(VPU_40XX_BUTTRESS_D0I3_CONTROL);
- if (enable)
- val = REG_SET_FLD(VPU_40XX_BUTTRESS_D0I3_CONTROL, I3, val);
- else
- val = REG_CLR_FLD(VPU_40XX_BUTTRESS_D0I3_CONTROL, I3, val);
- REGB_WR32(VPU_40XX_BUTTRESS_D0I3_CONTROL, val);
-
- ret = REGB_POLL_FLD(VPU_40XX_BUTTRESS_D0I3_CONTROL, INPROGRESS, 0, TIMEOUT_US);
- if (ret) {
- ivpu_err(vdev, "Failed to sync after D0i3 transition: %d\n", ret);
- return ret;
- }
-
- return 0;
-}
-
-static bool ivpu_tile_disable_check(u32 config)
-{
- /* Allowed values: 0 or one bit from range 0-5 (6 tiles) */
- if (config == 0)
- return true;
-
- if (config > BIT(TILE_MAX_NUM - 1))
- return false;
-
- if ((config & (config - 1)) == 0)
- return true;
-
- return false;
-}
-
-static int ivpu_hw_40xx_info_init(struct ivpu_device *vdev)
-{
- struct ivpu_hw_info *hw = vdev->hw;
- u32 tile_disable;
- u32 fuse;
-
- fuse = REGB_RD32(VPU_40XX_BUTTRESS_TILE_FUSE);
- if (!REG_TEST_FLD(VPU_40XX_BUTTRESS_TILE_FUSE, VALID, fuse)) {
- ivpu_err(vdev, "Fuse: invalid (0x%x)\n", fuse);
- return -EIO;
- }
-
- tile_disable = REG_GET_FLD(VPU_40XX_BUTTRESS_TILE_FUSE, CONFIG, fuse);
- if (!ivpu_tile_disable_check(tile_disable)) {
- ivpu_err(vdev, "Fuse: Invalid tile disable config (0x%x)\n", tile_disable);
- return -EIO;
- }
-
- if (tile_disable)
- ivpu_dbg(vdev, MISC, "Fuse: %d tiles enabled. Tile number %d disabled\n",
- TILE_MAX_NUM - 1, ffs(tile_disable) - 1);
- else
- ivpu_dbg(vdev, MISC, "Fuse: All %d tiles enabled\n", TILE_MAX_NUM);
-
- hw->tile_fuse = tile_disable;
- hw->pll.profiling_freq = PLL_PROFILING_FREQ_DEFAULT;
-
- ivpu_pll_init_frequency_ratios(vdev);
-
- ivpu_hw_init_range(&vdev->hw->ranges.global, 0x80000000, SZ_512M);
- ivpu_hw_init_range(&vdev->hw->ranges.user, 0x80000000, SZ_256M);
- ivpu_hw_init_range(&vdev->hw->ranges.shave, 0x80000000 + SZ_256M, SZ_2G - SZ_256M);
- ivpu_hw_init_range(&vdev->hw->ranges.dma, 0x200000000, SZ_8G);
-
- ivpu_hw_read_platform(vdev);
- ivpu_hw_wa_init(vdev);
- ivpu_hw_timeouts_init(vdev);
-
- return 0;
-}
-
-static int ivpu_hw_40xx_ip_reset(struct ivpu_device *vdev)
-{
- int ret;
- u32 val;
-
- ret = REGB_POLL_FLD(VPU_40XX_BUTTRESS_IP_RESET, TRIGGER, 0, TIMEOUT_US);
- if (ret) {
- ivpu_err(vdev, "Wait for *_TRIGGER timed out\n");
- return ret;
- }
-
- val = REGB_RD32(VPU_40XX_BUTTRESS_IP_RESET);
- val = REG_SET_FLD(VPU_40XX_BUTTRESS_IP_RESET, TRIGGER, val);
- REGB_WR32(VPU_40XX_BUTTRESS_IP_RESET, val);
-
- ret = REGB_POLL_FLD(VPU_40XX_BUTTRESS_IP_RESET, TRIGGER, 0, TIMEOUT_US);
- if (ret)
- ivpu_err(vdev, "Timed out waiting for RESET completion\n");
-
- return ret;
-}
-
-static int ivpu_hw_40xx_reset(struct ivpu_device *vdev)
-{
- int ret = 0;
-
- if (ivpu_hw_40xx_ip_reset(vdev)) {
- ivpu_err(vdev, "Failed to reset NPU IP\n");
- ret = -EIO;
- }
-
- if (ivpu_pll_disable(vdev)) {
- ivpu_err(vdev, "Failed to disable PLL\n");
- ret = -EIO;
- }
-
- return ret;
-}
-
-static int ivpu_hw_40xx_d0i3_enable(struct ivpu_device *vdev)
-{
- int ret;
-
- if (IVPU_WA(punit_disabled))
- return 0;
-
- ret = ivpu_boot_d0i3_drive(vdev, true);
- if (ret)
- ivpu_err(vdev, "Failed to enable D0i3: %d\n", ret);
-
- udelay(5); /* VPU requires 5 us to complete the transition */
-
- return ret;
-}
-
-static int ivpu_hw_40xx_d0i3_disable(struct ivpu_device *vdev)
-{
- int ret;
-
- if (IVPU_WA(punit_disabled))
- return 0;
-
- ret = ivpu_boot_d0i3_drive(vdev, false);
- if (ret)
- ivpu_err(vdev, "Failed to disable D0i3: %d\n", ret);
-
- return ret;
-}
-
-static void ivpu_hw_40xx_profiling_freq_reg_set(struct ivpu_device *vdev)
-{
- u32 val = REGB_RD32(VPU_40XX_BUTTRESS_VPU_STATUS);
-
- if (vdev->hw->pll.profiling_freq == PLL_PROFILING_FREQ_DEFAULT)
- val = REG_CLR_FLD(VPU_40XX_BUTTRESS_VPU_STATUS, PERF_CLK, val);
- else
- val = REG_SET_FLD(VPU_40XX_BUTTRESS_VPU_STATUS, PERF_CLK, val);
-
- REGB_WR32(VPU_40XX_BUTTRESS_VPU_STATUS, val);
-}
-
-static void ivpu_hw_40xx_ats_print(struct ivpu_device *vdev)
-{
- ivpu_dbg(vdev, MISC, "Buttress ATS: %s\n",
- REGB_RD32(VPU_40XX_BUTTRESS_HM_ATS) ? "Enable" : "Disable");
-}
-
-static void ivpu_hw_40xx_clock_relinquish_disable(struct ivpu_device *vdev)
-{
- u32 val = REGB_RD32(VPU_40XX_BUTTRESS_VPU_STATUS);
-
- val = REG_SET_FLD(VPU_40XX_BUTTRESS_VPU_STATUS, DISABLE_CLK_RELINQUISH, val);
- REGB_WR32(VPU_40XX_BUTTRESS_VPU_STATUS, val);
-}
-
-static int ivpu_hw_40xx_power_up(struct ivpu_device *vdev)
-{
- int ret;
-
- ret = ivpu_hw_40xx_d0i3_disable(vdev);
- if (ret)
- ivpu_warn(vdev, "Failed to disable D0I3: %d\n", ret);
-
- ret = ivpu_pll_enable(vdev);
- if (ret) {
- ivpu_err(vdev, "Failed to enable PLL: %d\n", ret);
- return ret;
- }
-
- if (IVPU_WA(disable_clock_relinquish))
- ivpu_hw_40xx_clock_relinquish_disable(vdev);
- ivpu_hw_40xx_profiling_freq_reg_set(vdev);
- ivpu_hw_40xx_ats_print(vdev);
-
- ret = ivpu_boot_host_ss_check(vdev);
- if (ret) {
- ivpu_err(vdev, "Failed to configure host SS: %d\n", ret);
- return ret;
- }
-
- ivpu_boot_idle_gen_drive(vdev, false);
-
- ret = ivpu_boot_pwr_domain_enable(vdev);
- if (ret) {
- ivpu_err(vdev, "Failed to enable power domain: %d\n", ret);
- return ret;
- }
-
- ret = ivpu_boot_host_ss_axi_enable(vdev);
- if (ret) {
- ivpu_err(vdev, "Failed to enable AXI: %d\n", ret);
- return ret;
- }
-
- ret = ivpu_boot_host_ss_top_noc_enable(vdev);
- if (ret)
- ivpu_err(vdev, "Failed to enable TOP NOC: %d\n", ret);
-
- return ret;
-}
-
-static int ivpu_hw_40xx_boot_fw(struct ivpu_device *vdev)
-{
- int ret;
-
- ivpu_boot_no_snoop_enable(vdev);
- ivpu_boot_tbu_mmu_enable(vdev);
-
- ret = ivpu_boot_soc_cpu_boot(vdev);
- if (ret)
- ivpu_err(vdev, "Failed to boot SOC CPU: %d\n", ret);
-
- return ret;
-}
-
-static bool ivpu_hw_40xx_is_idle(struct ivpu_device *vdev)
-{
- u32 val;
-
- if (IVPU_WA(punit_disabled))
- return true;
-
- val = REGB_RD32(VPU_40XX_BUTTRESS_VPU_STATUS);
- return REG_TEST_FLD(VPU_40XX_BUTTRESS_VPU_STATUS, READY, val) &&
- REG_TEST_FLD(VPU_40XX_BUTTRESS_VPU_STATUS, IDLE, val);
-}
-
-static int ivpu_hw_40xx_wait_for_idle(struct ivpu_device *vdev)
-{
- return REGB_POLL_FLD(VPU_40XX_BUTTRESS_VPU_STATUS, IDLE, 0x1, IDLE_TIMEOUT_US);
-}
-
-static void ivpu_hw_40xx_save_d0i3_entry_timestamp(struct ivpu_device *vdev)
-{
- vdev->hw->d0i3_entry_host_ts = ktime_get_boottime();
- vdev->hw->d0i3_entry_vpu_ts = REGV_RD64(VPU_40XX_CPU_SS_TIM_PERF_EXT_FREE_CNT);
-}
-
-static int ivpu_hw_40xx_power_down(struct ivpu_device *vdev)
-{
- int ret = 0;
-
- ivpu_hw_40xx_save_d0i3_entry_timestamp(vdev);
-
- if (!ivpu_hw_40xx_is_idle(vdev) && ivpu_hw_40xx_ip_reset(vdev))
- ivpu_warn(vdev, "Failed to reset the NPU\n");
-
- if (ivpu_pll_disable(vdev)) {
- ivpu_err(vdev, "Failed to disable PLL\n");
- ret = -EIO;
- }
-
- if (ivpu_hw_40xx_d0i3_enable(vdev)) {
- ivpu_err(vdev, "Failed to enter D0I3\n");
- ret = -EIO;
- }
-
- return ret;
-}
-
-static void ivpu_hw_40xx_wdt_disable(struct ivpu_device *vdev)
-{
- u32 val;
-
- REGV_WR32(VPU_40XX_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE);
- REGV_WR32(VPU_40XX_CPU_SS_TIM_WATCHDOG, TIM_WATCHDOG_RESET_VALUE);
-
- REGV_WR32(VPU_40XX_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE);
- REGV_WR32(VPU_40XX_CPU_SS_TIM_WDOG_EN, 0);
-
- val = REGV_RD32(VPU_40XX_CPU_SS_TIM_GEN_CONFIG);
- val = REG_CLR_FLD(VPU_40XX_CPU_SS_TIM_GEN_CONFIG, WDOG_TO_INT_CLR, val);
- REGV_WR32(VPU_40XX_CPU_SS_TIM_GEN_CONFIG, val);
-}
-
-static u32 ivpu_hw_40xx_profiling_freq_get(struct ivpu_device *vdev)
-{
- return vdev->hw->pll.profiling_freq;
-}
-
-static void ivpu_hw_40xx_profiling_freq_drive(struct ivpu_device *vdev, bool enable)
-{
- if (enable)
- vdev->hw->pll.profiling_freq = PLL_PROFILING_FREQ_HIGH;
- else
- vdev->hw->pll.profiling_freq = PLL_PROFILING_FREQ_DEFAULT;
-}
-
-/* Register indirect accesses */
-static u32 ivpu_hw_40xx_reg_pll_freq_get(struct ivpu_device *vdev)
-{
- u32 pll_curr_ratio;
-
- pll_curr_ratio = REGB_RD32(VPU_40XX_BUTTRESS_PLL_FREQ);
- pll_curr_ratio &= VPU_40XX_BUTTRESS_PLL_FREQ_RATIO_MASK;
-
- return PLL_RATIO_TO_FREQ(pll_curr_ratio);
-}
-
-static u32 ivpu_hw_40xx_ratio_to_freq(struct ivpu_device *vdev, u32 ratio)
-{
- return PLL_RATIO_TO_FREQ(ratio);
-}
-
-static u32 ivpu_hw_40xx_reg_telemetry_offset_get(struct ivpu_device *vdev)
-{
- return REGB_RD32(VPU_40XX_BUTTRESS_VPU_TELEMETRY_OFFSET);
-}
-
-static u32 ivpu_hw_40xx_reg_telemetry_size_get(struct ivpu_device *vdev)
-{
- return REGB_RD32(VPU_40XX_BUTTRESS_VPU_TELEMETRY_SIZE);
-}
-
-static u32 ivpu_hw_40xx_reg_telemetry_enable_get(struct ivpu_device *vdev)
-{
- return REGB_RD32(VPU_40XX_BUTTRESS_VPU_TELEMETRY_ENABLE);
-}
-
-static void ivpu_hw_40xx_reg_db_set(struct ivpu_device *vdev, u32 db_id)
-{
- u32 reg_stride = VPU_40XX_CPU_SS_DOORBELL_1 - VPU_40XX_CPU_SS_DOORBELL_0;
- u32 val = REG_FLD(VPU_40XX_CPU_SS_DOORBELL_0, SET);
-
- REGV_WR32I(VPU_40XX_CPU_SS_DOORBELL_0, reg_stride, db_id, val);
-}
-
-static u32 ivpu_hw_40xx_reg_ipc_rx_addr_get(struct ivpu_device *vdev)
-{
- return REGV_RD32(VPU_40XX_HOST_SS_TIM_IPC_FIFO_ATM);
-}
-
-static u32 ivpu_hw_40xx_reg_ipc_rx_count_get(struct ivpu_device *vdev)
-{
- u32 count = REGV_RD32_SILENT(VPU_40XX_HOST_SS_TIM_IPC_FIFO_STAT);
-
- return REG_GET_FLD(VPU_40XX_HOST_SS_TIM_IPC_FIFO_STAT, FILL_LEVEL, count);
-}
-
-static void ivpu_hw_40xx_reg_ipc_tx_set(struct ivpu_device *vdev, u32 vpu_addr)
-{
- REGV_WR32(VPU_40XX_CPU_SS_TIM_IPC_FIFO, vpu_addr);
-}
-
-static void ivpu_hw_40xx_irq_clear(struct ivpu_device *vdev)
-{
- REGV_WR64(VPU_40XX_HOST_SS_ICB_CLEAR_0, ICB_0_1_IRQ_MASK);
-}
-
-static void ivpu_hw_40xx_irq_enable(struct ivpu_device *vdev)
-{
- REGV_WR32(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, ITF_FIREWALL_VIOLATION_MASK);
- REGV_WR64(VPU_40XX_HOST_SS_ICB_ENABLE_0, ICB_0_1_IRQ_MASK);
- REGB_WR32(VPU_40XX_BUTTRESS_LOCAL_INT_MASK, BUTTRESS_IRQ_ENABLE_MASK);
- REGB_WR32(VPU_40XX_BUTTRESS_GLOBAL_INT_MASK, 0x0);
-}
-
-static void ivpu_hw_40xx_irq_disable(struct ivpu_device *vdev)
-{
- REGB_WR32(VPU_40XX_BUTTRESS_GLOBAL_INT_MASK, 0x1);
- REGB_WR32(VPU_40XX_BUTTRESS_LOCAL_INT_MASK, BUTTRESS_IRQ_DISABLE_MASK);
- REGV_WR64(VPU_40XX_HOST_SS_ICB_ENABLE_0, 0x0ull);
- REGV_WR32(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, 0x0ul);
-}
-
-static void ivpu_hw_40xx_irq_wdt_nce_handler(struct ivpu_device *vdev)
-{
- /* TODO: For LNN hang consider engine reset instead of full recovery */
- ivpu_pm_trigger_recovery(vdev, "WDT NCE IRQ");
-}
-
-static void ivpu_hw_40xx_irq_wdt_mss_handler(struct ivpu_device *vdev)
-{
- ivpu_hw_wdt_disable(vdev);
- ivpu_pm_trigger_recovery(vdev, "WDT MSS IRQ");
-}
-
-static void ivpu_hw_40xx_irq_noc_firewall_handler(struct ivpu_device *vdev)
-{
- ivpu_pm_trigger_recovery(vdev, "NOC Firewall IRQ");
-}
-
-/* Handler for IRQs from VPU core (irqV) */
-static bool ivpu_hw_40xx_irqv_handler(struct ivpu_device *vdev, int irq, bool *wake_thread)
-{
- u32 status = REGV_RD32(VPU_40XX_HOST_SS_ICB_STATUS_0) & ICB_0_IRQ_MASK;
-
- if (!status)
- return false;
-
- REGV_WR32(VPU_40XX_HOST_SS_ICB_CLEAR_0, status);
-
- if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_0_INT, status))
- ivpu_mmu_irq_evtq_handler(vdev);
-
- if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, HOST_IPC_FIFO_INT, status))
- ivpu_ipc_irq_handler(vdev, wake_thread);
-
- if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_1_INT, status))
- ivpu_dbg(vdev, IRQ, "MMU sync complete\n");
-
- if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_2_INT, status))
- ivpu_mmu_irq_gerr_handler(vdev);
-
- if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT, status))
- ivpu_hw_40xx_irq_wdt_mss_handler(vdev);
-
- if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT, status))
- ivpu_hw_40xx_irq_wdt_nce_handler(vdev);
-
- if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT, status))
- ivpu_hw_40xx_irq_noc_firewall_handler(vdev);
-
- return true;
-}
-
-/* Handler for IRQs from Buttress core (irqB) */
-static bool ivpu_hw_40xx_irqb_handler(struct ivpu_device *vdev, int irq)
-{
- bool schedule_recovery = false;
- u32 status = REGB_RD32(VPU_40XX_BUTTRESS_INTERRUPT_STAT) & BUTTRESS_IRQ_MASK;
-
- if (!status)
- return false;
-
- if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, FREQ_CHANGE, status))
- ivpu_dbg(vdev, IRQ, "FREQ_CHANGE");
-
- if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, ATS_ERR, status)) {
- ivpu_err(vdev, "ATS_ERR LOG1 0x%08x ATS_ERR_LOG2 0x%08x\n",
- REGB_RD32(VPU_40XX_BUTTRESS_ATS_ERR_LOG1),
- REGB_RD32(VPU_40XX_BUTTRESS_ATS_ERR_LOG2));
- REGB_WR32(VPU_40XX_BUTTRESS_ATS_ERR_CLEAR, 0x1);
- schedule_recovery = true;
- }
-
- if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, CFI0_ERR, status)) {
- ivpu_err(vdev, "CFI0_ERR 0x%08x", REGB_RD32(VPU_40XX_BUTTRESS_CFI0_ERR_LOG));
- REGB_WR32(VPU_40XX_BUTTRESS_CFI0_ERR_CLEAR, 0x1);
- schedule_recovery = true;
- }
-
- if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, CFI1_ERR, status)) {
- ivpu_err(vdev, "CFI1_ERR 0x%08x", REGB_RD32(VPU_40XX_BUTTRESS_CFI1_ERR_LOG));
- REGB_WR32(VPU_40XX_BUTTRESS_CFI1_ERR_CLEAR, 0x1);
- schedule_recovery = true;
- }
-
- if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, IMR0_ERR, status)) {
- ivpu_err(vdev, "IMR_ERR_CFI0 LOW: 0x%08x HIGH: 0x%08x",
- REGB_RD32(VPU_40XX_BUTTRESS_IMR_ERR_CFI0_LOW),
- REGB_RD32(VPU_40XX_BUTTRESS_IMR_ERR_CFI0_HIGH));
- REGB_WR32(VPU_40XX_BUTTRESS_IMR_ERR_CFI0_CLEAR, 0x1);
- schedule_recovery = true;
- }
-
- if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, IMR1_ERR, status)) {
- ivpu_err(vdev, "IMR_ERR_CFI1 LOW: 0x%08x HIGH: 0x%08x",
- REGB_RD32(VPU_40XX_BUTTRESS_IMR_ERR_CFI1_LOW),
- REGB_RD32(VPU_40XX_BUTTRESS_IMR_ERR_CFI1_HIGH));
- REGB_WR32(VPU_40XX_BUTTRESS_IMR_ERR_CFI1_CLEAR, 0x1);
- schedule_recovery = true;
- }
-
- if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, SURV_ERR, status)) {
- ivpu_err(vdev, "Survivability error detected\n");
- schedule_recovery = true;
- }
-
- /* This must be done after interrupts are cleared at the source. */
- REGB_WR32(VPU_40XX_BUTTRESS_INTERRUPT_STAT, status);
-
- if (schedule_recovery)
- ivpu_pm_trigger_recovery(vdev, "Buttress IRQ");
-
- return true;
-}
-
-static irqreturn_t ivpu_hw_40xx_irq_handler(int irq, void *ptr)
-{
- bool irqv_handled, irqb_handled, wake_thread = false;
- struct ivpu_device *vdev = ptr;
-
- REGB_WR32(VPU_40XX_BUTTRESS_GLOBAL_INT_MASK, 0x1);
-
- irqv_handled = ivpu_hw_40xx_irqv_handler(vdev, irq, &wake_thread);
- irqb_handled = ivpu_hw_40xx_irqb_handler(vdev, irq);
-
- /* Re-enable global interrupts to re-trigger MSI for pending interrupts */
- REGB_WR32(VPU_40XX_BUTTRESS_GLOBAL_INT_MASK, 0x0);
-
- if (wake_thread)
- return IRQ_WAKE_THREAD;
- if (irqv_handled || irqb_handled)
- return IRQ_HANDLED;
- return IRQ_NONE;
-}
-
-static void ivpu_hw_40xx_diagnose_failure(struct ivpu_device *vdev)
-{
- u32 irqv = REGV_RD32(VPU_40XX_HOST_SS_ICB_STATUS_0) & ICB_0_IRQ_MASK;
- u32 irqb = REGB_RD32(VPU_40XX_BUTTRESS_INTERRUPT_STAT) & BUTTRESS_IRQ_MASK;
-
- if (ivpu_hw_40xx_reg_ipc_rx_count_get(vdev))
- ivpu_err(vdev, "IPC FIFO queue not empty, missed IPC IRQ");
-
- if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT, irqv))
- ivpu_err(vdev, "WDT MSS timeout detected\n");
-
- if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT, irqv))
- ivpu_err(vdev, "WDT NCE timeout detected\n");
-
- if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT, irqv))
- ivpu_err(vdev, "NOC Firewall irq detected\n");
-
- if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, ATS_ERR, irqb)) {
- ivpu_err(vdev, "ATS_ERR_LOG1 0x%08x ATS_ERR_LOG2 0x%08x\n",
- REGB_RD32(VPU_40XX_BUTTRESS_ATS_ERR_LOG1),
- REGB_RD32(VPU_40XX_BUTTRESS_ATS_ERR_LOG2));
- }
-
- if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, CFI0_ERR, irqb))
- ivpu_err(vdev, "CFI0_ERR_LOG 0x%08x\n", REGB_RD32(VPU_40XX_BUTTRESS_CFI0_ERR_LOG));
-
- if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, CFI1_ERR, irqb))
- ivpu_err(vdev, "CFI1_ERR_LOG 0x%08x\n", REGB_RD32(VPU_40XX_BUTTRESS_CFI1_ERR_LOG));
-
- if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, IMR0_ERR, irqb))
- ivpu_err(vdev, "IMR_ERR_CFI0 LOW: 0x%08x HIGH: 0x%08x\n",
- REGB_RD32(VPU_40XX_BUTTRESS_IMR_ERR_CFI0_LOW),
- REGB_RD32(VPU_40XX_BUTTRESS_IMR_ERR_CFI0_HIGH));
-
- if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, IMR1_ERR, irqb))
- ivpu_err(vdev, "IMR_ERR_CFI1 LOW: 0x%08x HIGH: 0x%08x\n",
- REGB_RD32(VPU_40XX_BUTTRESS_IMR_ERR_CFI1_LOW),
- REGB_RD32(VPU_40XX_BUTTRESS_IMR_ERR_CFI1_HIGH));
-
- if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, SURV_ERR, irqb))
- ivpu_err(vdev, "Survivability error detected\n");
-}
-
-const struct ivpu_hw_ops ivpu_hw_40xx_ops = {
- .info_init = ivpu_hw_40xx_info_init,
- .power_up = ivpu_hw_40xx_power_up,
- .is_idle = ivpu_hw_40xx_is_idle,
- .wait_for_idle = ivpu_hw_40xx_wait_for_idle,
- .power_down = ivpu_hw_40xx_power_down,
- .reset = ivpu_hw_40xx_reset,
- .boot_fw = ivpu_hw_40xx_boot_fw,
- .wdt_disable = ivpu_hw_40xx_wdt_disable,
- .diagnose_failure = ivpu_hw_40xx_diagnose_failure,
- .profiling_freq_get = ivpu_hw_40xx_profiling_freq_get,
- .profiling_freq_drive = ivpu_hw_40xx_profiling_freq_drive,
- .reg_pll_freq_get = ivpu_hw_40xx_reg_pll_freq_get,
- .ratio_to_freq = ivpu_hw_40xx_ratio_to_freq,
- .reg_telemetry_offset_get = ivpu_hw_40xx_reg_telemetry_offset_get,
- .reg_telemetry_size_get = ivpu_hw_40xx_reg_telemetry_size_get,
- .reg_telemetry_enable_get = ivpu_hw_40xx_reg_telemetry_enable_get,
- .reg_db_set = ivpu_hw_40xx_reg_db_set,
- .reg_ipc_rx_addr_get = ivpu_hw_40xx_reg_ipc_rx_addr_get,
- .reg_ipc_rx_count_get = ivpu_hw_40xx_reg_ipc_rx_count_get,
- .reg_ipc_tx_set = ivpu_hw_40xx_reg_ipc_tx_set,
- .irq_clear = ivpu_hw_40xx_irq_clear,
- .irq_enable = ivpu_hw_40xx_irq_enable,
- .irq_disable = ivpu_hw_40xx_irq_disable,
- .irq_handler = ivpu_hw_40xx_irq_handler,
-};
diff --git a/drivers/accel/ivpu/ivpu_hw_40xx_reg.h b/drivers/accel/ivpu/ivpu_hw_40xx_reg.h
index ff4a5d4f5821..d0b795b344c7 100644
--- a/drivers/accel/ivpu/ivpu_hw_40xx_reg.h
+++ b/drivers/accel/ivpu/ivpu_hw_40xx_reg.h
@@ -8,91 +8,6 @@
#include <linux/bits.h>
-#define VPU_40XX_BUTTRESS_INTERRUPT_STAT 0x00000000u
-#define VPU_40XX_BUTTRESS_INTERRUPT_STAT_FREQ_CHANGE_MASK BIT_MASK(0)
-#define VPU_40XX_BUTTRESS_INTERRUPT_STAT_ATS_ERR_MASK BIT_MASK(1)
-#define VPU_40XX_BUTTRESS_INTERRUPT_STAT_CFI0_ERR_MASK BIT_MASK(2)
-#define VPU_40XX_BUTTRESS_INTERRUPT_STAT_CFI1_ERR_MASK BIT_MASK(3)
-#define VPU_40XX_BUTTRESS_INTERRUPT_STAT_IMR0_ERR_MASK BIT_MASK(4)
-#define VPU_40XX_BUTTRESS_INTERRUPT_STAT_IMR1_ERR_MASK BIT_MASK(5)
-#define VPU_40XX_BUTTRESS_INTERRUPT_STAT_SURV_ERR_MASK BIT_MASK(6)
-
-#define VPU_40XX_BUTTRESS_LOCAL_INT_MASK 0x00000004u
-#define VPU_40XX_BUTTRESS_GLOBAL_INT_MASK 0x00000008u
-
-#define VPU_40XX_BUTTRESS_HM_ATS 0x0000000cu
-
-#define VPU_40XX_BUTTRESS_ATS_ERR_LOG1 0x00000010u
-#define VPU_40XX_BUTTRESS_ATS_ERR_LOG2 0x00000014u
-#define VPU_40XX_BUTTRESS_ATS_ERR_CLEAR 0x00000018u
-
-#define VPU_40XX_BUTTRESS_CFI0_ERR_LOG 0x0000001cu
-#define VPU_40XX_BUTTRESS_CFI0_ERR_CLEAR 0x00000020u
-
-#define VPU_40XX_BUTTRESS_PORT_ARBITRATION_WEIGHTS_ATS 0x00000024u
-
-#define VPU_40XX_BUTTRESS_CFI1_ERR_LOG 0x00000040u
-#define VPU_40XX_BUTTRESS_CFI1_ERR_CLEAR 0x00000044u
-
-#define VPU_40XX_BUTTRESS_IMR_ERR_CFI0_LOW 0x00000048u
-#define VPU_40XX_BUTTRESS_IMR_ERR_CFI0_HIGH 0x0000004cu
-#define VPU_40XX_BUTTRESS_IMR_ERR_CFI0_CLEAR 0x00000050u
-
-#define VPU_40XX_BUTTRESS_PORT_ARBITRATION_WEIGHTS 0x00000054u
-
-#define VPU_40XX_BUTTRESS_IMR_ERR_CFI1_LOW 0x00000058u
-#define VPU_40XX_BUTTRESS_IMR_ERR_CFI1_HIGH 0x0000005cu
-#define VPU_40XX_BUTTRESS_IMR_ERR_CFI1_CLEAR 0x00000060u
-
-#define VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD0 0x00000130u
-#define VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD0_MIN_RATIO_MASK GENMASK(15, 0)
-#define VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD0_MAX_RATIO_MASK GENMASK(31, 16)
-
-#define VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD1 0x00000134u
-#define VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD1_TARGET_RATIO_MASK GENMASK(15, 0)
-#define VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD1_EPP_MASK GENMASK(31, 16)
-
-#define VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD2 0x00000138u
-#define VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD2_CONFIG_MASK GENMASK(15, 0)
-#define VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD2_CDYN_MASK GENMASK(31, 16)
-
-#define VPU_40XX_BUTTRESS_WP_REQ_CMD 0x0000013cu
-#define VPU_40XX_BUTTRESS_WP_REQ_CMD_SEND_MASK BIT_MASK(0)
-
-#define VPU_40XX_BUTTRESS_PLL_FREQ 0x00000148u
-#define VPU_40XX_BUTTRESS_PLL_FREQ_RATIO_MASK GENMASK(15, 0)
-
-#define VPU_40XX_BUTTRESS_TILE_FUSE 0x00000150u
-#define VPU_40XX_BUTTRESS_TILE_FUSE_VALID_MASK BIT_MASK(0)
-#define VPU_40XX_BUTTRESS_TILE_FUSE_CONFIG_MASK GENMASK(6, 1)
-
-#define VPU_40XX_BUTTRESS_VPU_STATUS 0x00000154u
-#define VPU_40XX_BUTTRESS_VPU_STATUS_READY_MASK BIT_MASK(0)
-#define VPU_40XX_BUTTRESS_VPU_STATUS_IDLE_MASK BIT_MASK(1)
-#define VPU_40XX_BUTTRESS_VPU_STATUS_DUP_IDLE_MASK BIT_MASK(2)
-#define VPU_40XX_BUTTRESS_VPU_STATUS_CLOCK_RESOURCE_OWN_ACK_MASK BIT_MASK(6)
-#define VPU_40XX_BUTTRESS_VPU_STATUS_POWER_RESOURCE_OWN_ACK_MASK BIT_MASK(7)
-#define VPU_40XX_BUTTRESS_VPU_STATUS_PERF_CLK_MASK BIT_MASK(11)
-#define VPU_40XX_BUTTRESS_VPU_STATUS_DISABLE_CLK_RELINQUISH_MASK BIT_MASK(12)
-
-#define VPU_40XX_BUTTRESS_IP_RESET 0x00000160u
-#define VPU_40XX_BUTTRESS_IP_RESET_TRIGGER_MASK BIT_MASK(0)
-
-#define VPU_40XX_BUTTRESS_D0I3_CONTROL 0x00000164u
-#define VPU_40XX_BUTTRESS_D0I3_CONTROL_INPROGRESS_MASK BIT_MASK(0)
-#define VPU_40XX_BUTTRESS_D0I3_CONTROL_I3_MASK BIT_MASK(2)
-
-#define VPU_40XX_BUTTRESS_VPU_TELEMETRY_OFFSET 0x00000168u
-#define VPU_40XX_BUTTRESS_VPU_TELEMETRY_SIZE 0x0000016cu
-#define VPU_40XX_BUTTRESS_VPU_TELEMETRY_ENABLE 0x00000170u
-
-#define VPU_40XX_BUTTRESS_FMIN_FUSE 0x00000174u
-#define VPU_40XX_BUTTRESS_FMIN_FUSE_MIN_RATIO_MASK GENMASK(7, 0)
-#define VPU_40XX_BUTTRESS_FMIN_FUSE_PN_RATIO_MASK GENMASK(15, 8)
-
-#define VPU_40XX_BUTTRESS_FMAX_FUSE 0x00000178u
-#define VPU_40XX_BUTTRESS_FMAX_FUSE_MAX_RATIO_MASK GENMASK(7, 0)
-
#define VPU_40XX_HOST_SS_CPR_CLK_EN 0x00000080u
#define VPU_40XX_HOST_SS_CPR_CLK_EN_TOP_NOC_MASK BIT_MASK(1)
#define VPU_40XX_HOST_SS_CPR_CLK_EN_DSS_MAS_MASK BIT_MASK(10)
@@ -198,6 +113,12 @@
#define VPU_40XX_HOST_SS_AON_PWR_ISLAND_STATUS0 0x0003002cu
#define VPU_40XX_HOST_SS_AON_PWR_ISLAND_STATUS0_CSS_CPU_MASK BIT_MASK(3)
+#define VPU_50XX_HOST_SS_AON_PWR_ISLAND_EN_POST_DLY 0x00030068u
+#define VPU_50XX_HOST_SS_AON_PWR_ISLAND_EN_POST_DLY_POST_DLY_MASK GENMASK(7, 0)
+
+#define VPU_50XX_HOST_SS_AON_PWR_ISLAND_STATUS_DLY 0x0003006cu
+#define VPU_50XX_HOST_SS_AON_PWR_ISLAND_STATUS_DLY_STATUS_DLY_MASK GENMASK(7, 0)
+
#define VPU_40XX_HOST_SS_AON_IDLE_GEN 0x00030200u
#define VPU_40XX_HOST_SS_AON_IDLE_GEN_EN_MASK BIT_MASK(0)
#define VPU_40XX_HOST_SS_AON_IDLE_GEN_HW_PG_EN_MASK BIT_MASK(1)
@@ -205,6 +126,9 @@
#define VPU_40XX_HOST_SS_AON_DPU_ACTIVE 0x00030204u
#define VPU_40XX_HOST_SS_AON_DPU_ACTIVE_DPU_ACTIVE_MASK BIT_MASK(0)
+#define VPU_50XX_HOST_SS_AON_FABRIC_REQ_OVERRIDE 0x00030210u
+#define VPU_50XX_HOST_SS_AON_FABRIC_REQ_OVERRIDE_REQ_OVERRIDE_MASK BIT_MASK(0)
+
#define VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO 0x00040040u
#define VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO_DONE_MASK BIT_MASK(0)
#define VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO_IOSF_RS_ID_MASK GENMASK(2, 1)
diff --git a/drivers/accel/ivpu/ivpu_hw_btrs.c b/drivers/accel/ivpu/ivpu_hw_btrs.c
new file mode 100644
index 000000000000..13734d1abc7d
--- /dev/null
+++ b/drivers/accel/ivpu/ivpu_hw_btrs.c
@@ -0,0 +1,881 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2020-2024 Intel Corporation
+ */
+
+#include "ivpu_drv.h"
+#include "ivpu_hw.h"
+#include "ivpu_hw_btrs.h"
+#include "ivpu_hw_btrs_lnl_reg.h"
+#include "ivpu_hw_btrs_mtl_reg.h"
+#include "ivpu_hw_reg_io.h"
+#include "ivpu_pm.h"
+
+#define BTRS_MTL_IRQ_MASK ((REG_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, ATS_ERR)) | \
+ (REG_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, UFI_ERR)))
+
+#define BTRS_LNL_IRQ_MASK ((REG_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, ATS_ERR)) | \
+ (REG_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, CFI0_ERR)) | \
+ (REG_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, CFI1_ERR)) | \
+ (REG_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, IMR0_ERR)) | \
+ (REG_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, IMR1_ERR)) | \
+ (REG_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, SURV_ERR)))
+
+#define BTRS_MTL_ALL_IRQ_MASK (BTRS_MTL_IRQ_MASK | (REG_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, \
+ FREQ_CHANGE)))
+
+#define BTRS_IRQ_DISABLE_MASK ((u32)-1)
+
+#define BTRS_LNL_ALL_IRQ_MASK ((u32)-1)
+
+#define BTRS_MTL_WP_CONFIG_1_TILE_5_3_RATIO WP_CONFIG(MTL_CONFIG_1_TILE, MTL_PLL_RATIO_5_3)
+#define BTRS_MTL_WP_CONFIG_1_TILE_4_3_RATIO WP_CONFIG(MTL_CONFIG_1_TILE, MTL_PLL_RATIO_4_3)
+#define BTRS_MTL_WP_CONFIG_2_TILE_5_3_RATIO WP_CONFIG(MTL_CONFIG_2_TILE, MTL_PLL_RATIO_5_3)
+#define BTRS_MTL_WP_CONFIG_2_TILE_4_3_RATIO WP_CONFIG(MTL_CONFIG_2_TILE, MTL_PLL_RATIO_4_3)
+#define BTRS_MTL_WP_CONFIG_0_TILE_PLL_OFF WP_CONFIG(0, 0)
+
+#define PLL_CDYN_DEFAULT 0x80
+#define PLL_EPP_DEFAULT 0x80
+#define PLL_CONFIG_DEFAULT 0x0
+#define PLL_SIMULATION_FREQ 10000000
+#define PLL_REF_CLK_FREQ 50000000
+#define PLL_TIMEOUT_US (1500 * USEC_PER_MSEC)
+#define IDLE_TIMEOUT_US (5 * USEC_PER_MSEC)
+#define TIMEOUT_US (150 * USEC_PER_MSEC)
+
+/* Work point configuration values */
+#define WP_CONFIG(tile, ratio) (((tile) << 8) | (ratio))
+#define MTL_CONFIG_1_TILE 0x01
+#define MTL_CONFIG_2_TILE 0x02
+#define MTL_PLL_RATIO_5_3 0x01
+#define MTL_PLL_RATIO_4_3 0x02
+#define BTRS_MTL_TILE_FUSE_ENABLE_BOTH 0x0
+#define BTRS_MTL_TILE_SKU_BOTH 0x3630
+
+#define BTRS_LNL_TILE_MAX_NUM 6
+#define BTRS_LNL_TILE_MAX_MASK 0x3f
+
+#define WEIGHTS_DEFAULT 0xf711f711u
+#define WEIGHTS_ATS_DEFAULT 0x0000f711u
+
+#define DCT_REQ 0x2
+#define DCT_ENABLE 0x1
+#define DCT_DISABLE 0x0
+
+int ivpu_hw_btrs_irqs_clear_with_0_mtl(struct ivpu_device *vdev)
+{
+ REGB_WR32(VPU_HW_BTRS_MTL_INTERRUPT_STAT, BTRS_MTL_ALL_IRQ_MASK);
+ if (REGB_RD32(VPU_HW_BTRS_MTL_INTERRUPT_STAT) == BTRS_MTL_ALL_IRQ_MASK) {
+ /* Writing 1s does not clear the interrupt status register */
+ REGB_WR32(VPU_HW_BTRS_MTL_INTERRUPT_STAT, 0x0);
+ return true;
+ }
+
+ return false;
+}
+
+static void freq_ratios_init_mtl(struct ivpu_device *vdev)
+{
+ struct ivpu_hw_info *hw = vdev->hw;
+ u32 fmin_fuse, fmax_fuse;
+
+ fmin_fuse = REGB_RD32(VPU_HW_BTRS_MTL_FMIN_FUSE);
+ hw->pll.min_ratio = REG_GET_FLD(VPU_HW_BTRS_MTL_FMIN_FUSE, MIN_RATIO, fmin_fuse);
+ hw->pll.pn_ratio = REG_GET_FLD(VPU_HW_BTRS_MTL_FMIN_FUSE, PN_RATIO, fmin_fuse);
+
+ fmax_fuse = REGB_RD32(VPU_HW_BTRS_MTL_FMAX_FUSE);
+ hw->pll.max_ratio = REG_GET_FLD(VPU_HW_BTRS_MTL_FMAX_FUSE, MAX_RATIO, fmax_fuse);
+}
+
+static void freq_ratios_init_lnl(struct ivpu_device *vdev)
+{
+ struct ivpu_hw_info *hw = vdev->hw;
+ u32 fmin_fuse, fmax_fuse;
+
+ fmin_fuse = REGB_RD32(VPU_HW_BTRS_LNL_FMIN_FUSE);
+ hw->pll.min_ratio = REG_GET_FLD(VPU_HW_BTRS_LNL_FMIN_FUSE, MIN_RATIO, fmin_fuse);
+ hw->pll.pn_ratio = REG_GET_FLD(VPU_HW_BTRS_LNL_FMIN_FUSE, PN_RATIO, fmin_fuse);
+
+ fmax_fuse = REGB_RD32(VPU_HW_BTRS_LNL_FMAX_FUSE);
+ hw->pll.max_ratio = REG_GET_FLD(VPU_HW_BTRS_LNL_FMAX_FUSE, MAX_RATIO, fmax_fuse);
+}
+
+void ivpu_hw_btrs_freq_ratios_init(struct ivpu_device *vdev)
+{
+ struct ivpu_hw_info *hw = vdev->hw;
+
+ if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
+ freq_ratios_init_mtl(vdev);
+ else
+ freq_ratios_init_lnl(vdev);
+
+ hw->pll.min_ratio = clamp_t(u8, ivpu_pll_min_ratio, hw->pll.min_ratio, hw->pll.max_ratio);
+ hw->pll.max_ratio = clamp_t(u8, ivpu_pll_max_ratio, hw->pll.min_ratio, hw->pll.max_ratio);
+ hw->pll.pn_ratio = clamp_t(u8, hw->pll.pn_ratio, hw->pll.min_ratio, hw->pll.max_ratio);
+}
+
+static bool tile_disable_check(u32 config)
+{
+ /* Allowed values: 0 or one bit from range 0-5 (6 tiles) */
+ if (config == 0)
+ return true;
+
+ if (config > BIT(BTRS_LNL_TILE_MAX_NUM - 1))
+ return false;
+
+ if ((config & (config - 1)) == 0)
+ return true;
+
+ return false;
+}
+
+static int read_tile_config_fuse(struct ivpu_device *vdev, u32 *tile_fuse_config)
+{
+ u32 fuse;
+ u32 config;
+
+ fuse = REGB_RD32(VPU_HW_BTRS_LNL_TILE_FUSE);
+ if (!REG_TEST_FLD(VPU_HW_BTRS_LNL_TILE_FUSE, VALID, fuse)) {
+ ivpu_err(vdev, "Fuse: invalid (0x%x)\n", fuse);
+ return -EIO;
+ }
+
+ config = REG_GET_FLD(VPU_HW_BTRS_LNL_TILE_FUSE, CONFIG, fuse);
+ if (!tile_disable_check(config)) {
+ ivpu_err(vdev, "Fuse: Invalid tile disable config (0x%x)\n", config);
+ return -EIO;
+ }
+
+ if (config)
+ ivpu_dbg(vdev, MISC, "Fuse: %d tiles enabled. Tile number %d disabled\n",
+ BTRS_LNL_TILE_MAX_NUM - 1, ffs(config) - 1);
+ else
+ ivpu_dbg(vdev, MISC, "Fuse: All %d tiles enabled\n", BTRS_LNL_TILE_MAX_NUM);
+
+ *tile_fuse_config = config;
+ return 0;
+}
+
+static int info_init_mtl(struct ivpu_device *vdev)
+{
+ struct ivpu_hw_info *hw = vdev->hw;
+
+ hw->tile_fuse = BTRS_MTL_TILE_FUSE_ENABLE_BOTH;
+ hw->sku = BTRS_MTL_TILE_SKU_BOTH;
+ hw->config = BTRS_MTL_WP_CONFIG_2_TILE_4_3_RATIO;
+ hw->sched_mode = ivpu_sched_mode;
+
+ return 0;
+}
+
+static int info_init_lnl(struct ivpu_device *vdev)
+{
+ struct ivpu_hw_info *hw = vdev->hw;
+ u32 tile_fuse_config;
+ int ret;
+
+ ret = read_tile_config_fuse(vdev, &tile_fuse_config);
+ if (ret)
+ return ret;
+
+ hw->sched_mode = ivpu_sched_mode;
+ hw->tile_fuse = tile_fuse_config;
+ hw->pll.profiling_freq = PLL_PROFILING_FREQ_DEFAULT;
+
+ return 0;
+}
+
+int ivpu_hw_btrs_info_init(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
+ return info_init_mtl(vdev);
+ else
+ return info_init_lnl(vdev);
+}
+
+static int wp_request_sync(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
+ return REGB_POLL_FLD(VPU_HW_BTRS_MTL_WP_REQ_CMD, SEND, 0, PLL_TIMEOUT_US);
+ else
+ return REGB_POLL_FLD(VPU_HW_BTRS_LNL_WP_REQ_CMD, SEND, 0, PLL_TIMEOUT_US);
+}
+
+static int wait_for_status_ready(struct ivpu_device *vdev, bool enable)
+{
+ u32 exp_val = enable ? 0x1 : 0x0;
+
+ if (IVPU_WA(punit_disabled))
+ return 0;
+
+ if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
+ return REGB_POLL_FLD(VPU_HW_BTRS_MTL_VPU_STATUS, READY, exp_val, PLL_TIMEOUT_US);
+ else
+ return REGB_POLL_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, READY, exp_val, PLL_TIMEOUT_US);
+}
+
+struct wp_request {
+ u16 min;
+ u16 max;
+ u16 target;
+ u16 cfg;
+ u16 epp;
+ u16 cdyn;
+};
+
+static void wp_request_mtl(struct ivpu_device *vdev, struct wp_request *wp)
+{
+ u32 val;
+
+ val = REGB_RD32(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD0);
+ val = REG_SET_FLD_NUM(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD0, MIN_RATIO, wp->min, val);
+ val = REG_SET_FLD_NUM(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD0, MAX_RATIO, wp->max, val);
+ REGB_WR32(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD0, val);
+
+ val = REGB_RD32(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD1);
+ val = REG_SET_FLD_NUM(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD1, TARGET_RATIO, wp->target, val);
+ val = REG_SET_FLD_NUM(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD1, EPP, PLL_EPP_DEFAULT, val);
+ REGB_WR32(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD1, val);
+
+ val = REGB_RD32(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD2);
+ val = REG_SET_FLD_NUM(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD2, CONFIG, wp->cfg, val);
+ REGB_WR32(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD2, val);
+
+ val = REGB_RD32(VPU_HW_BTRS_MTL_WP_REQ_CMD);
+ val = REG_SET_FLD(VPU_HW_BTRS_MTL_WP_REQ_CMD, SEND, val);
+ REGB_WR32(VPU_HW_BTRS_MTL_WP_REQ_CMD, val);
+}
+
+static void wp_request_lnl(struct ivpu_device *vdev, struct wp_request *wp)
+{
+ u32 val;
+
+ val = REGB_RD32(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD0);
+ val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD0, MIN_RATIO, wp->min, val);
+ val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD0, MAX_RATIO, wp->max, val);
+ REGB_WR32(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD0, val);
+
+ val = REGB_RD32(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD1);
+ val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD1, TARGET_RATIO, wp->target, val);
+ val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD1, EPP, wp->epp, val);
+ REGB_WR32(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD1, val);
+
+ val = REGB_RD32(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD2);
+ val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD2, CONFIG, wp->cfg, val);
+ val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD2, CDYN, wp->cdyn, val);
+ REGB_WR32(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD2, val);
+
+ val = REGB_RD32(VPU_HW_BTRS_LNL_WP_REQ_CMD);
+ val = REG_SET_FLD(VPU_HW_BTRS_LNL_WP_REQ_CMD, SEND, val);
+ REGB_WR32(VPU_HW_BTRS_LNL_WP_REQ_CMD, val);
+}
+
+static void wp_request(struct ivpu_device *vdev, struct wp_request *wp)
+{
+ if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
+ wp_request_mtl(vdev, wp);
+ else
+ wp_request_lnl(vdev, wp);
+}
+
+static int wp_request_send(struct ivpu_device *vdev, struct wp_request *wp)
+{
+ int ret;
+
+ ret = wp_request_sync(vdev);
+ if (ret) {
+ ivpu_err(vdev, "Failed to sync before workpoint request: %d\n", ret);
+ return ret;
+ }
+
+ wp_request(vdev, wp);
+
+ ret = wp_request_sync(vdev);
+ if (ret)
+ ivpu_err(vdev, "Failed to sync after workpoint request: %d\n", ret);
+
+ return ret;
+}
+
+static void prepare_wp_request(struct ivpu_device *vdev, struct wp_request *wp, bool enable)
+{
+ struct ivpu_hw_info *hw = vdev->hw;
+
+ wp->min = hw->pll.min_ratio;
+ wp->max = hw->pll.max_ratio;
+
+ if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) {
+ wp->target = enable ? hw->pll.pn_ratio : 0;
+ wp->cfg = enable ? hw->config : 0;
+ wp->cdyn = 0;
+ wp->epp = 0;
+ } else {
+ wp->target = hw->pll.pn_ratio;
+ wp->cfg = enable ? PLL_CONFIG_DEFAULT : 0;
+ wp->cdyn = enable ? PLL_CDYN_DEFAULT : 0;
+ wp->epp = enable ? PLL_EPP_DEFAULT : 0;
+ }
+
+ /* Simics cannot start without at least one tile */
+ if (enable && ivpu_is_simics(vdev))
+ wp->cfg = 1;
+}
+
+static int wait_for_pll_lock(struct ivpu_device *vdev, bool enable)
+{
+ u32 exp_val = enable ? 0x1 : 0x0;
+
+ if (ivpu_hw_btrs_gen(vdev) != IVPU_HW_BTRS_MTL)
+ return 0;
+
+ if (IVPU_WA(punit_disabled))
+ return 0;
+
+ return REGB_POLL_FLD(VPU_HW_BTRS_MTL_PLL_STATUS, LOCK, exp_val, PLL_TIMEOUT_US);
+}
+
+int ivpu_hw_btrs_wp_drive(struct ivpu_device *vdev, bool enable)
+{
+ struct wp_request wp;
+ int ret;
+
+ if (IVPU_WA(punit_disabled)) {
+ ivpu_dbg(vdev, PM, "Skipping workpoint request\n");
+ return 0;
+ }
+
+ prepare_wp_request(vdev, &wp, enable);
+
+ ivpu_dbg(vdev, PM, "PLL workpoint request: %u Hz, config: 0x%x, epp: 0x%x, cdyn: 0x%x\n",
+ PLL_RATIO_TO_FREQ(wp.target), wp.cfg, wp.epp, wp.cdyn);
+
+ ret = wp_request_send(vdev, &wp);
+ if (ret) {
+ ivpu_err(vdev, "Failed to send workpoint request: %d\n", ret);
+ return ret;
+ }
+
+ ret = wait_for_pll_lock(vdev, enable);
+ if (ret) {
+ ivpu_err(vdev, "Timed out waiting for PLL lock\n");
+ return ret;
+ }
+
+ ret = wait_for_status_ready(vdev, enable);
+ if (ret) {
+ ivpu_err(vdev, "Timed out waiting for NPU ready status\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int d0i3_drive_mtl(struct ivpu_device *vdev, bool enable)
+{
+ int ret;
+ u32 val;
+
+ ret = REGB_POLL_FLD(VPU_HW_BTRS_MTL_VPU_D0I3_CONTROL, INPROGRESS, 0, TIMEOUT_US);
+ if (ret) {
+ ivpu_err(vdev, "Failed to sync before D0i3 transition: %d\n", ret);
+ return ret;
+ }
+
+ val = REGB_RD32(VPU_HW_BTRS_MTL_VPU_D0I3_CONTROL);
+ if (enable)
+ val = REG_SET_FLD(VPU_HW_BTRS_MTL_VPU_D0I3_CONTROL, I3, val);
+ else
+ val = REG_CLR_FLD(VPU_HW_BTRS_MTL_VPU_D0I3_CONTROL, I3, val);
+ REGB_WR32(VPU_HW_BTRS_MTL_VPU_D0I3_CONTROL, val);
+
+ ret = REGB_POLL_FLD(VPU_HW_BTRS_MTL_VPU_D0I3_CONTROL, INPROGRESS, 0, TIMEOUT_US);
+ if (ret)
+ ivpu_err(vdev, "Failed to sync after D0i3 transition: %d\n", ret);
+
+ return ret;
+}
+
+static int d0i3_drive_lnl(struct ivpu_device *vdev, bool enable)
+{
+ int ret;
+ u32 val;
+
+ ret = REGB_POLL_FLD(VPU_HW_BTRS_LNL_D0I3_CONTROL, INPROGRESS, 0, TIMEOUT_US);
+ if (ret) {
+ ivpu_err(vdev, "Failed to sync before D0i3 transition: %d\n", ret);
+ return ret;
+ }
+
+ val = REGB_RD32(VPU_HW_BTRS_LNL_D0I3_CONTROL);
+ if (enable)
+ val = REG_SET_FLD(VPU_HW_BTRS_LNL_D0I3_CONTROL, I3, val);
+ else
+ val = REG_CLR_FLD(VPU_HW_BTRS_LNL_D0I3_CONTROL, I3, val);
+ REGB_WR32(VPU_HW_BTRS_LNL_D0I3_CONTROL, val);
+
+ ret = REGB_POLL_FLD(VPU_HW_BTRS_LNL_D0I3_CONTROL, INPROGRESS, 0, TIMEOUT_US);
+ if (ret) {
+ ivpu_err(vdev, "Failed to sync after D0i3 transition: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int d0i3_drive(struct ivpu_device *vdev, bool enable)
+{
+ if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
+ return d0i3_drive_mtl(vdev, enable);
+ else
+ return d0i3_drive_lnl(vdev, enable);
+}
+
+int ivpu_hw_btrs_d0i3_enable(struct ivpu_device *vdev)
+{
+ int ret;
+
+ if (IVPU_WA(punit_disabled))
+ return 0;
+
+ ret = d0i3_drive(vdev, true);
+ if (ret)
+ ivpu_err(vdev, "Failed to enable D0i3: %d\n", ret);
+
+ udelay(5); /* VPU requires 5 us to complete the transition */
+
+ return ret;
+}
+
+int ivpu_hw_btrs_d0i3_disable(struct ivpu_device *vdev)
+{
+ int ret;
+
+ if (IVPU_WA(punit_disabled))
+ return 0;
+
+ ret = d0i3_drive(vdev, false);
+ if (ret)
+ ivpu_err(vdev, "Failed to disable D0i3: %d\n", ret);
+
+ return ret;
+}
+
+int ivpu_hw_btrs_wait_for_clock_res_own_ack(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
+ return 0;
+
+ if (ivpu_is_simics(vdev))
+ return 0;
+
+ return REGB_POLL_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, CLOCK_RESOURCE_OWN_ACK, 1, TIMEOUT_US);
+}
+
+void ivpu_hw_btrs_set_port_arbitration_weights_lnl(struct ivpu_device *vdev)
+{
+ REGB_WR32(VPU_HW_BTRS_LNL_PORT_ARBITRATION_WEIGHTS, WEIGHTS_DEFAULT);
+ REGB_WR32(VPU_HW_BTRS_LNL_PORT_ARBITRATION_WEIGHTS_ATS, WEIGHTS_ATS_DEFAULT);
+}
+
+static int ip_reset_mtl(struct ivpu_device *vdev)
+{
+ int ret;
+ u32 val;
+
+ ret = REGB_POLL_FLD(VPU_HW_BTRS_MTL_VPU_IP_RESET, TRIGGER, 0, TIMEOUT_US);
+ if (ret) {
+ ivpu_err(vdev, "Timed out waiting for TRIGGER bit\n");
+ return ret;
+ }
+
+ val = REGB_RD32(VPU_HW_BTRS_MTL_VPU_IP_RESET);
+ val = REG_SET_FLD(VPU_HW_BTRS_MTL_VPU_IP_RESET, TRIGGER, val);
+ REGB_WR32(VPU_HW_BTRS_MTL_VPU_IP_RESET, val);
+
+ ret = REGB_POLL_FLD(VPU_HW_BTRS_MTL_VPU_IP_RESET, TRIGGER, 0, TIMEOUT_US);
+ if (ret)
+ ivpu_err(vdev, "Timed out waiting for RESET completion\n");
+
+ return ret;
+}
+
+static int ip_reset_lnl(struct ivpu_device *vdev)
+{
+ int ret;
+ u32 val;
+
+ ret = REGB_POLL_FLD(VPU_HW_BTRS_LNL_IP_RESET, TRIGGER, 0, TIMEOUT_US);
+ if (ret) {
+ ivpu_err(vdev, "Wait for *_TRIGGER timed out\n");
+ return ret;
+ }
+
+ val = REGB_RD32(VPU_HW_BTRS_LNL_IP_RESET);
+ val = REG_SET_FLD(VPU_HW_BTRS_LNL_IP_RESET, TRIGGER, val);
+ REGB_WR32(VPU_HW_BTRS_LNL_IP_RESET, val);
+
+ ret = REGB_POLL_FLD(VPU_HW_BTRS_LNL_IP_RESET, TRIGGER, 0, TIMEOUT_US);
+ if (ret)
+ ivpu_err(vdev, "Timed out waiting for RESET completion\n");
+
+ return ret;
+}
+
+int ivpu_hw_btrs_ip_reset(struct ivpu_device *vdev)
+{
+ if (IVPU_WA(punit_disabled))
+ return 0;
+
+ if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
+ return ip_reset_mtl(vdev);
+ else
+ return ip_reset_lnl(vdev);
+}
+
+void ivpu_hw_btrs_profiling_freq_reg_set_lnl(struct ivpu_device *vdev)
+{
+ u32 val = REGB_RD32(VPU_HW_BTRS_LNL_VPU_STATUS);
+
+ if (vdev->hw->pll.profiling_freq == PLL_PROFILING_FREQ_DEFAULT)
+ val = REG_CLR_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, PERF_CLK, val);
+ else
+ val = REG_SET_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, PERF_CLK, val);
+
+ REGB_WR32(VPU_HW_BTRS_LNL_VPU_STATUS, val);
+}
+
+void ivpu_hw_btrs_ats_print_lnl(struct ivpu_device *vdev)
+{
+ ivpu_dbg(vdev, MISC, "Buttress ATS: %s\n",
+ REGB_RD32(VPU_HW_BTRS_LNL_HM_ATS) ? "Enable" : "Disable");
+}
+
+void ivpu_hw_btrs_clock_relinquish_disable_lnl(struct ivpu_device *vdev)
+{
+ u32 val = REGB_RD32(VPU_HW_BTRS_LNL_VPU_STATUS);
+
+ val = REG_SET_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, DISABLE_CLK_RELINQUISH, val);
+ REGB_WR32(VPU_HW_BTRS_LNL_VPU_STATUS, val);
+}
+
+bool ivpu_hw_btrs_is_idle(struct ivpu_device *vdev)
+{
+ u32 val;
+
+ if (IVPU_WA(punit_disabled))
+ return true;
+
+ if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) {
+ val = REGB_RD32(VPU_HW_BTRS_MTL_VPU_STATUS);
+
+ return REG_TEST_FLD(VPU_HW_BTRS_MTL_VPU_STATUS, READY, val) &&
+ REG_TEST_FLD(VPU_HW_BTRS_MTL_VPU_STATUS, IDLE, val);
+ } else {
+ val = REGB_RD32(VPU_HW_BTRS_LNL_VPU_STATUS);
+
+ return REG_TEST_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, READY, val) &&
+ REG_TEST_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, IDLE, val);
+ }
+}
+
+int ivpu_hw_btrs_wait_for_idle(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
+ return REGB_POLL_FLD(VPU_HW_BTRS_MTL_VPU_STATUS, IDLE, 0x1, IDLE_TIMEOUT_US);
+ else
+ return REGB_POLL_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, IDLE, 0x1, IDLE_TIMEOUT_US);
+}
+
+/* Handler for IRQs from Buttress core (irqB) */
+bool ivpu_hw_btrs_irq_handler_mtl(struct ivpu_device *vdev, int irq)
+{
+ u32 status = REGB_RD32(VPU_HW_BTRS_MTL_INTERRUPT_STAT) & BTRS_MTL_IRQ_MASK;
+ bool schedule_recovery = false;
+
+ if (!status)
+ return false;
+
+ if (REG_TEST_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, FREQ_CHANGE, status))
+ ivpu_dbg(vdev, IRQ, "FREQ_CHANGE irq: %08x",
+ REGB_RD32(VPU_HW_BTRS_MTL_CURRENT_PLL));
+
+ if (REG_TEST_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, ATS_ERR, status)) {
+ ivpu_err(vdev, "ATS_ERR irq 0x%016llx", REGB_RD64(VPU_HW_BTRS_MTL_ATS_ERR_LOG_0));
+ REGB_WR32(VPU_HW_BTRS_MTL_ATS_ERR_CLEAR, 0x1);
+ schedule_recovery = true;
+ }
+
+ if (REG_TEST_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, UFI_ERR, status)) {
+ u32 ufi_log = REGB_RD32(VPU_HW_BTRS_MTL_UFI_ERR_LOG);
+
+ ivpu_err(vdev, "UFI_ERR irq (0x%08x) opcode: 0x%02lx axi_id: 0x%02lx cq_id: 0x%03lx",
+ ufi_log, REG_GET_FLD(VPU_HW_BTRS_MTL_UFI_ERR_LOG, OPCODE, ufi_log),
+ REG_GET_FLD(VPU_HW_BTRS_MTL_UFI_ERR_LOG, AXI_ID, ufi_log),
+ REG_GET_FLD(VPU_HW_BTRS_MTL_UFI_ERR_LOG, CQ_ID, ufi_log));
+ REGB_WR32(VPU_HW_BTRS_MTL_UFI_ERR_CLEAR, 0x1);
+ schedule_recovery = true;
+ }
+
+ /* This must be done after interrupts are cleared at the source. */
+ if (IVPU_WA(interrupt_clear_with_0))
+ /*
+ * Writing 1 triggers an interrupt, so we can't perform read update write.
+ * Clear local interrupt status by writing 0 to all bits.
+ */
+ REGB_WR32(VPU_HW_BTRS_MTL_INTERRUPT_STAT, 0x0);
+ else
+ REGB_WR32(VPU_HW_BTRS_MTL_INTERRUPT_STAT, status);
+
+ if (schedule_recovery)
+ ivpu_pm_trigger_recovery(vdev, "Buttress IRQ");
+
+ return true;
+}
+
+/* Handler for IRQs from Buttress core (irqB) */
+bool ivpu_hw_btrs_irq_handler_lnl(struct ivpu_device *vdev, int irq)
+{
+ u32 status = REGB_RD32(VPU_HW_BTRS_LNL_INTERRUPT_STAT) & BTRS_LNL_IRQ_MASK;
+ bool schedule_recovery = false;
+
+ if (!status)
+ return false;
+
+ if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, SURV_ERR, status))
+ ivpu_dbg(vdev, IRQ, "Survivability IRQ\n");
+
+ if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, FREQ_CHANGE, status))
+ ivpu_dbg(vdev, IRQ, "FREQ_CHANGE irq: %08x", REGB_RD32(VPU_HW_BTRS_LNL_PLL_FREQ));
+
+ if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, ATS_ERR, status)) {
+ ivpu_err(vdev, "ATS_ERR LOG1 0x%08x ATS_ERR_LOG2 0x%08x\n",
+ REGB_RD32(VPU_HW_BTRS_LNL_ATS_ERR_LOG1),
+ REGB_RD32(VPU_HW_BTRS_LNL_ATS_ERR_LOG2));
+ REGB_WR32(VPU_HW_BTRS_LNL_ATS_ERR_CLEAR, 0x1);
+ schedule_recovery = true;
+ }
+
+ if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, CFI0_ERR, status)) {
+ ivpu_err(vdev, "CFI0_ERR 0x%08x", REGB_RD32(VPU_HW_BTRS_LNL_CFI0_ERR_LOG));
+ REGB_WR32(VPU_HW_BTRS_LNL_CFI0_ERR_CLEAR, 0x1);
+ schedule_recovery = true;
+ }
+
+ if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, CFI1_ERR, status)) {
+ ivpu_err(vdev, "CFI1_ERR 0x%08x", REGB_RD32(VPU_HW_BTRS_LNL_CFI1_ERR_LOG));
+ REGB_WR32(VPU_HW_BTRS_LNL_CFI1_ERR_CLEAR, 0x1);
+ schedule_recovery = true;
+ }
+
+ if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, IMR0_ERR, status)) {
+ ivpu_err(vdev, "IMR_ERR_CFI0 LOW: 0x%08x HIGH: 0x%08x",
+ REGB_RD32(VPU_HW_BTRS_LNL_IMR_ERR_CFI0_LOW),
+ REGB_RD32(VPU_HW_BTRS_LNL_IMR_ERR_CFI0_HIGH));
+ REGB_WR32(VPU_HW_BTRS_LNL_IMR_ERR_CFI0_CLEAR, 0x1);
+ schedule_recovery = true;
+ }
+
+ if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, IMR1_ERR, status)) {
+ ivpu_err(vdev, "IMR_ERR_CFI1 LOW: 0x%08x HIGH: 0x%08x",
+ REGB_RD32(VPU_HW_BTRS_LNL_IMR_ERR_CFI1_LOW),
+ REGB_RD32(VPU_HW_BTRS_LNL_IMR_ERR_CFI1_HIGH));
+ REGB_WR32(VPU_HW_BTRS_LNL_IMR_ERR_CFI1_CLEAR, 0x1);
+ schedule_recovery = true;
+ }
+
+ /* This must be done after interrupts are cleared at the source. */
+ REGB_WR32(VPU_HW_BTRS_LNL_INTERRUPT_STAT, status);
+
+ if (schedule_recovery)
+ ivpu_pm_trigger_recovery(vdev, "Buttress IRQ");
+
+ return true;
+}
+
+static void dct_drive_40xx(struct ivpu_device *vdev, u32 dct_val)
+{
+ u32 val = REGB_RD32(VPU_HW_BTRS_LNL_PCODE_MAILBOX);
+
+ val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_PCODE_MAILBOX, CMD, DCT_REQ, val);
+ val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_PCODE_MAILBOX, PARAM1,
+ dct_val ? DCT_ENABLE : DCT_DISABLE, val);
+ val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_PCODE_MAILBOX, PARAM2, dct_val, val);
+
+ REGB_WR32(VPU_HW_BTRS_LNL_PCODE_MAILBOX, val);
+}
+
+void ivpu_hw_btrs_dct_drive(struct ivpu_device *vdev, u32 dct_val)
+{
+ return dct_drive_40xx(vdev, dct_val);
+}
+
+static u32 pll_ratio_to_freq_mtl(u32 ratio, u32 config)
+{
+ u32 pll_clock = PLL_REF_CLK_FREQ * ratio;
+ u32 cpu_clock;
+
+ if ((config & 0xff) == MTL_PLL_RATIO_4_3)
+ cpu_clock = pll_clock * 2 / 4;
+ else
+ cpu_clock = pll_clock * 2 / 5;
+
+ return cpu_clock;
+}
+
+u32 ivpu_hw_btrs_ratio_to_freq(struct ivpu_device *vdev, u32 ratio)
+{
+ struct ivpu_hw_info *hw = vdev->hw;
+
+ if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
+ return pll_ratio_to_freq_mtl(ratio, hw->config);
+ else
+ return PLL_RATIO_TO_FREQ(ratio);
+}
+
+static u32 pll_freq_get_mtl(struct ivpu_device *vdev)
+{
+ u32 pll_curr_ratio;
+
+ pll_curr_ratio = REGB_RD32(VPU_HW_BTRS_MTL_CURRENT_PLL);
+ pll_curr_ratio &= VPU_HW_BTRS_MTL_CURRENT_PLL_RATIO_MASK;
+
+ if (!ivpu_is_silicon(vdev))
+ return PLL_SIMULATION_FREQ;
+
+ return pll_ratio_to_freq_mtl(pll_curr_ratio, vdev->hw->config);
+}
+
+static u32 pll_freq_get_lnl(struct ivpu_device *vdev)
+{
+ u32 pll_curr_ratio;
+
+ pll_curr_ratio = REGB_RD32(VPU_HW_BTRS_LNL_PLL_FREQ);
+ pll_curr_ratio &= VPU_HW_BTRS_LNL_PLL_FREQ_RATIO_MASK;
+
+ return PLL_RATIO_TO_FREQ(pll_curr_ratio);
+}
+
+u32 ivpu_hw_btrs_pll_freq_get(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
+ return pll_freq_get_mtl(vdev);
+ else
+ return pll_freq_get_lnl(vdev);
+}
+
+u32 ivpu_hw_btrs_telemetry_offset_get(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
+ return REGB_RD32(VPU_HW_BTRS_MTL_VPU_TELEMETRY_OFFSET);
+ else
+ return REGB_RD32(VPU_HW_BTRS_LNL_VPU_TELEMETRY_OFFSET);
+}
+
+u32 ivpu_hw_btrs_telemetry_size_get(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
+ return REGB_RD32(VPU_HW_BTRS_MTL_VPU_TELEMETRY_SIZE);
+ else
+ return REGB_RD32(VPU_HW_BTRS_LNL_VPU_TELEMETRY_SIZE);
+}
+
+u32 ivpu_hw_btrs_telemetry_enable_get(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
+ return REGB_RD32(VPU_HW_BTRS_MTL_VPU_TELEMETRY_ENABLE);
+ else
+ return REGB_RD32(VPU_HW_BTRS_LNL_VPU_TELEMETRY_ENABLE);
+}
+
+void ivpu_hw_btrs_global_int_disable(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
+ REGB_WR32(VPU_HW_BTRS_MTL_GLOBAL_INT_MASK, 0x1);
+ else
+ REGB_WR32(VPU_HW_BTRS_LNL_GLOBAL_INT_MASK, 0x1);
+}
+
+void ivpu_hw_btrs_global_int_enable(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
+ REGB_WR32(VPU_HW_BTRS_MTL_GLOBAL_INT_MASK, 0x0);
+ else
+ REGB_WR32(VPU_HW_BTRS_LNL_GLOBAL_INT_MASK, 0x0);
+}
+
+void ivpu_hw_btrs_irq_enable(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) {
+ REGB_WR32(VPU_HW_BTRS_MTL_LOCAL_INT_MASK, (u32)(~BTRS_MTL_IRQ_MASK));
+ REGB_WR32(VPU_HW_BTRS_MTL_GLOBAL_INT_MASK, 0x0);
+ } else {
+ REGB_WR32(VPU_HW_BTRS_LNL_LOCAL_INT_MASK, (u32)(~BTRS_LNL_IRQ_MASK));
+ REGB_WR32(VPU_HW_BTRS_LNL_GLOBAL_INT_MASK, 0x0);
+ }
+}
+
+void ivpu_hw_btrs_irq_disable(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) {
+ REGB_WR32(VPU_HW_BTRS_MTL_GLOBAL_INT_MASK, 0x1);
+ REGB_WR32(VPU_HW_BTRS_MTL_LOCAL_INT_MASK, BTRS_IRQ_DISABLE_MASK);
+ } else {
+ REGB_WR32(VPU_HW_BTRS_LNL_GLOBAL_INT_MASK, 0x1);
+ REGB_WR32(VPU_HW_BTRS_LNL_LOCAL_INT_MASK, BTRS_IRQ_DISABLE_MASK);
+ }
+}
+
+static void diagnose_failure_mtl(struct ivpu_device *vdev)
+{
+ u32 reg = REGB_RD32(VPU_HW_BTRS_MTL_INTERRUPT_STAT) & BTRS_MTL_IRQ_MASK;
+
+ if (REG_TEST_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, ATS_ERR, reg))
+ ivpu_err(vdev, "ATS_ERR irq 0x%016llx", REGB_RD64(VPU_HW_BTRS_MTL_ATS_ERR_LOG_0));
+
+ if (REG_TEST_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, UFI_ERR, reg)) {
+ u32 log = REGB_RD32(VPU_HW_BTRS_MTL_UFI_ERR_LOG);
+
+ ivpu_err(vdev, "UFI_ERR irq (0x%08x) opcode: 0x%02lx axi_id: 0x%02lx cq_id: 0x%03lx",
+ log, REG_GET_FLD(VPU_HW_BTRS_MTL_UFI_ERR_LOG, OPCODE, log),
+ REG_GET_FLD(VPU_HW_BTRS_MTL_UFI_ERR_LOG, AXI_ID, log),
+ REG_GET_FLD(VPU_HW_BTRS_MTL_UFI_ERR_LOG, CQ_ID, log));
+ }
+}
+
+static void diagnose_failure_lnl(struct ivpu_device *vdev)
+{
+ u32 reg = REGB_RD32(VPU_HW_BTRS_MTL_INTERRUPT_STAT) & BTRS_LNL_IRQ_MASK;
+
+ if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, ATS_ERR, reg)) {
+ ivpu_err(vdev, "ATS_ERR_LOG1 0x%08x ATS_ERR_LOG2 0x%08x\n",
+ REGB_RD32(VPU_HW_BTRS_LNL_ATS_ERR_LOG1),
+ REGB_RD32(VPU_HW_BTRS_LNL_ATS_ERR_LOG2));
+ }
+
+ if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, CFI0_ERR, reg))
+ ivpu_err(vdev, "CFI0_ERR_LOG 0x%08x\n", REGB_RD32(VPU_HW_BTRS_LNL_CFI0_ERR_LOG));
+
+ if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, CFI1_ERR, reg))
+ ivpu_err(vdev, "CFI1_ERR_LOG 0x%08x\n", REGB_RD32(VPU_HW_BTRS_LNL_CFI1_ERR_LOG));
+
+ if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, IMR0_ERR, reg))
+ ivpu_err(vdev, "IMR_ERR_CFI0 LOW: 0x%08x HIGH: 0x%08x\n",
+ REGB_RD32(VPU_HW_BTRS_LNL_IMR_ERR_CFI0_LOW),
+ REGB_RD32(VPU_HW_BTRS_LNL_IMR_ERR_CFI0_HIGH));
+
+ if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, IMR1_ERR, reg))
+ ivpu_err(vdev, "IMR_ERR_CFI1 LOW: 0x%08x HIGH: 0x%08x\n",
+ REGB_RD32(VPU_HW_BTRS_LNL_IMR_ERR_CFI1_LOW),
+ REGB_RD32(VPU_HW_BTRS_LNL_IMR_ERR_CFI1_HIGH));
+
+ if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, SURV_ERR, reg))
+ ivpu_err(vdev, "Survivability IRQ\n");
+}
+
+void ivpu_hw_btrs_diagnose_failure(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
+ return diagnose_failure_mtl(vdev);
+ else
+ return diagnose_failure_lnl(vdev);
+}
diff --git a/drivers/accel/ivpu/ivpu_hw_btrs.h b/drivers/accel/ivpu/ivpu_hw_btrs.h
new file mode 100644
index 000000000000..b3e3ae2aa578
--- /dev/null
+++ b/drivers/accel/ivpu/ivpu_hw_btrs.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2020-2024 Intel Corporation
+ */
+
+#ifndef __IVPU_HW_BTRS_H__
+#define __IVPU_HW_BTRS_H__
+
+#include "ivpu_drv.h"
+#include "ivpu_hw_37xx_reg.h"
+#include "ivpu_hw_40xx_reg.h"
+#include "ivpu_hw_reg_io.h"
+
+#define PLL_PROFILING_FREQ_DEFAULT 38400000
+#define PLL_PROFILING_FREQ_HIGH 400000000
+#define PLL_RATIO_TO_FREQ(x) ((x) * PLL_REF_CLK_FREQ)
+
+int ivpu_hw_btrs_info_init(struct ivpu_device *vdev);
+void ivpu_hw_btrs_freq_ratios_init(struct ivpu_device *vdev);
+int ivpu_hw_btrs_irqs_clear_with_0_mtl(struct ivpu_device *vdev);
+int ivpu_hw_btrs_wp_drive(struct ivpu_device *vdev, bool enable);
+int ivpu_hw_btrs_wait_for_clock_res_own_ack(struct ivpu_device *vdev);
+int ivpu_hw_btrs_d0i3_enable(struct ivpu_device *vdev);
+int ivpu_hw_btrs_d0i3_disable(struct ivpu_device *vdev);
+void ivpu_hw_btrs_set_port_arbitration_weights_lnl(struct ivpu_device *vdev);
+bool ivpu_hw_btrs_is_idle(struct ivpu_device *vdev);
+int ivpu_hw_btrs_wait_for_idle(struct ivpu_device *vdev);
+int ivpu_hw_btrs_ip_reset(struct ivpu_device *vdev);
+void ivpu_hw_btrs_profiling_freq_reg_set_lnl(struct ivpu_device *vdev);
+void ivpu_hw_btrs_ats_print_lnl(struct ivpu_device *vdev);
+void ivpu_hw_btrs_clock_relinquish_disable_lnl(struct ivpu_device *vdev);
+bool ivpu_hw_btrs_irq_handler_mtl(struct ivpu_device *vdev, int irq);
+bool ivpu_hw_btrs_irq_handler_lnl(struct ivpu_device *vdev, int irq);
+void ivpu_hw_btrs_dct_drive(struct ivpu_device *vdev, u32 dct_val);
+u32 ivpu_hw_btrs_pll_freq_get(struct ivpu_device *vdev);
+u32 ivpu_hw_btrs_ratio_to_freq(struct ivpu_device *vdev, u32 ratio);
+u32 ivpu_hw_btrs_telemetry_offset_get(struct ivpu_device *vdev);
+u32 ivpu_hw_btrs_telemetry_size_get(struct ivpu_device *vdev);
+u32 ivpu_hw_btrs_telemetry_enable_get(struct ivpu_device *vdev);
+void ivpu_hw_btrs_global_int_enable(struct ivpu_device *vdev);
+void ivpu_hw_btrs_global_int_disable(struct ivpu_device *vdev);
+void ivpu_hw_btrs_irq_enable(struct ivpu_device *vdev);
+void ivpu_hw_btrs_irq_disable(struct ivpu_device *vdev);
+void ivpu_hw_btrs_diagnose_failure(struct ivpu_device *vdev);
+
+#endif /* __IVPU_HW_BTRS_H__ */
diff --git a/drivers/accel/ivpu/ivpu_hw_btrs_lnl_reg.h b/drivers/accel/ivpu/ivpu_hw_btrs_lnl_reg.h
new file mode 100644
index 000000000000..93733bde02b0
--- /dev/null
+++ b/drivers/accel/ivpu/ivpu_hw_btrs_lnl_reg.h
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2020-2024 Intel Corporation
+ */
+
+#ifndef __IVPU_HW_BTRS_LNL_REG_H__
+#define __IVPU_HW_BTRS_LNL_REG_H__
+
+#include <linux/bits.h>
+
+#define VPU_HW_BTRS_LNL_INTERRUPT_STAT 0x00000000u
+#define VPU_HW_BTRS_LNL_INTERRUPT_STAT_FREQ_CHANGE_MASK BIT_MASK(0)
+#define VPU_HW_BTRS_LNL_INTERRUPT_STAT_ATS_ERR_MASK BIT_MASK(1)
+#define VPU_HW_BTRS_LNL_INTERRUPT_STAT_CFI0_ERR_MASK BIT_MASK(2)
+#define VPU_HW_BTRS_LNL_INTERRUPT_STAT_CFI1_ERR_MASK BIT_MASK(3)
+#define VPU_HW_BTRS_LNL_INTERRUPT_STAT_IMR0_ERR_MASK BIT_MASK(4)
+#define VPU_HW_BTRS_LNL_INTERRUPT_STAT_IMR1_ERR_MASK BIT_MASK(5)
+#define VPU_HW_BTRS_LNL_INTERRUPT_STAT_SURV_ERR_MASK BIT_MASK(6)
+
+#define VPU_HW_BTRS_LNL_LOCAL_INT_MASK 0x00000004u
+#define VPU_HW_BTRS_LNL_GLOBAL_INT_MASK 0x00000008u
+
+#define VPU_HW_BTRS_LNL_HM_ATS 0x0000000cu
+
+#define VPU_HW_BTRS_LNL_ATS_ERR_LOG1 0x00000010u
+#define VPU_HW_BTRS_LNL_ATS_ERR_LOG2 0x00000014u
+#define VPU_HW_BTRS_LNL_ATS_ERR_CLEAR 0x00000018u
+
+#define VPU_HW_BTRS_LNL_CFI0_ERR_LOG 0x0000001cu
+#define VPU_HW_BTRS_LNL_CFI0_ERR_CLEAR 0x00000020u
+
+#define VPU_HW_BTRS_LNL_PORT_ARBITRATION_WEIGHTS_ATS 0x00000024u
+
+#define VPU_HW_BTRS_LNL_CFI1_ERR_LOG 0x00000040u
+#define VPU_HW_BTRS_LNL_CFI1_ERR_CLEAR 0x00000044u
+
+#define VPU_HW_BTRS_LNL_IMR_ERR_CFI0_LOW 0x00000048u
+#define VPU_HW_BTRS_LNL_IMR_ERR_CFI0_HIGH 0x0000004cu
+#define VPU_HW_BTRS_LNL_IMR_ERR_CFI0_CLEAR 0x00000050u
+
+#define VPU_HW_BTRS_LNL_PORT_ARBITRATION_WEIGHTS 0x00000054u
+
+#define VPU_HW_BTRS_LNL_IMR_ERR_CFI1_LOW 0x00000058u
+#define VPU_HW_BTRS_LNL_IMR_ERR_CFI1_HIGH 0x0000005cu
+#define VPU_HW_BTRS_LNL_IMR_ERR_CFI1_CLEAR 0x00000060u
+
+#define VPU_HW_BTRS_LNL_PCODE_MAILBOX 0x00000070u
+#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_CMD_MASK GENMASK(7, 0)
+#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_PARAM1_MASK GENMASK(15, 8)
+#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_PARAM2_MASK GENMASK(23, 16)
+#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_PARAM3_MASK GENMASK(31, 24)
+
+#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_SHADOW 0x00000074u
+#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_SHADOW_CMD_MASK GENMASK(7, 0)
+#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_SHADOW_PARAM1_MASK GENMASK(15, 8)
+#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_SHADOW_PARAM2_MASK GENMASK(23, 16)
+#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_SHADOW_PARAM3_MASK GENMASK(31, 24)
+
+#define VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD0 0x00000130u
+#define VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD0_MIN_RATIO_MASK GENMASK(15, 0)
+#define VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD0_MAX_RATIO_MASK GENMASK(31, 16)
+
+#define VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD1 0x00000134u
+#define VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD1_TARGET_RATIO_MASK GENMASK(15, 0)
+#define VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD1_EPP_MASK GENMASK(31, 16)
+
+#define VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD2 0x00000138u
+#define VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD2_CONFIG_MASK GENMASK(15, 0)
+#define VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD2_CDYN_MASK GENMASK(31, 16)
+
+#define VPU_HW_BTRS_LNL_WP_REQ_CMD 0x0000013cu
+#define VPU_HW_BTRS_LNL_WP_REQ_CMD_SEND_MASK BIT_MASK(0)
+
+#define VPU_HW_BTRS_LNL_PLL_FREQ 0x00000148u
+#define VPU_HW_BTRS_LNL_PLL_FREQ_RATIO_MASK GENMASK(15, 0)
+
+#define VPU_HW_BTRS_LNL_TILE_FUSE 0x00000150u
+#define VPU_HW_BTRS_LNL_TILE_FUSE_VALID_MASK BIT_MASK(0)
+#define VPU_HW_BTRS_LNL_TILE_FUSE_CONFIG_MASK GENMASK(6, 1)
+
+#define VPU_HW_BTRS_LNL_VPU_STATUS 0x00000154u
+#define VPU_HW_BTRS_LNL_VPU_STATUS_READY_MASK BIT_MASK(0)
+#define VPU_HW_BTRS_LNL_VPU_STATUS_IDLE_MASK BIT_MASK(1)
+#define VPU_HW_BTRS_LNL_VPU_STATUS_DUP_IDLE_MASK BIT_MASK(2)
+#define VPU_HW_BTRS_LNL_VPU_STATUS_CLOCK_RESOURCE_OWN_ACK_MASK BIT_MASK(6)
+#define VPU_HW_BTRS_LNL_VPU_STATUS_POWER_RESOURCE_OWN_ACK_MASK BIT_MASK(7)
+#define VPU_HW_BTRS_LNL_VPU_STATUS_PERF_CLK_MASK BIT_MASK(11)
+#define VPU_HW_BTRS_LNL_VPU_STATUS_DISABLE_CLK_RELINQUISH_MASK BIT_MASK(12)
+
+#define VPU_HW_BTRS_LNL_IP_RESET 0x00000160u
+#define VPU_HW_BTRS_LNL_IP_RESET_TRIGGER_MASK BIT_MASK(0)
+
+#define VPU_HW_BTRS_LNL_D0I3_CONTROL 0x00000164u
+#define VPU_HW_BTRS_LNL_D0I3_CONTROL_INPROGRESS_MASK BIT_MASK(0)
+#define VPU_HW_BTRS_LNL_D0I3_CONTROL_I3_MASK BIT_MASK(2)
+
+#define VPU_HW_BTRS_LNL_VPU_TELEMETRY_OFFSET 0x00000168u
+#define VPU_HW_BTRS_LNL_VPU_TELEMETRY_SIZE 0x0000016cu
+#define VPU_HW_BTRS_LNL_VPU_TELEMETRY_ENABLE 0x00000170u
+
+#define VPU_HW_BTRS_LNL_FMIN_FUSE 0x00000174u
+#define VPU_HW_BTRS_LNL_FMIN_FUSE_MIN_RATIO_MASK GENMASK(7, 0)
+#define VPU_HW_BTRS_LNL_FMIN_FUSE_PN_RATIO_MASK GENMASK(15, 8)
+
+#define VPU_HW_BTRS_LNL_FMAX_FUSE 0x00000178u
+#define VPU_HW_BTRS_LNL_FMAX_FUSE_MAX_RATIO_MASK GENMASK(7, 0)
+
+#endif /* __IVPU_HW_BTRS_LNL_REG_H__ */
diff --git a/drivers/accel/ivpu/ivpu_hw_btrs_mtl_reg.h b/drivers/accel/ivpu/ivpu_hw_btrs_mtl_reg.h
new file mode 100644
index 000000000000..e93d539e066f
--- /dev/null
+++ b/drivers/accel/ivpu/ivpu_hw_btrs_mtl_reg.h
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2020-2023 Intel Corporation
+ */
+
+#ifndef __IVPU_HW_BTRS_MTL_REG_H__
+#define __IVPU_HW_BTRS_MTL_REG_H__
+
+#include <linux/bits.h>
+
+#define VPU_HW_BTRS_MTL_INTERRUPT_TYPE 0x00000000u
+
+#define VPU_HW_BTRS_MTL_INTERRUPT_STAT 0x00000004u
+#define VPU_HW_BTRS_MTL_INTERRUPT_STAT_FREQ_CHANGE_MASK BIT_MASK(0)
+#define VPU_HW_BTRS_MTL_INTERRUPT_STAT_ATS_ERR_MASK BIT_MASK(1)
+#define VPU_HW_BTRS_MTL_INTERRUPT_STAT_UFI_ERR_MASK BIT_MASK(2)
+
+#define VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD0 0x00000008u
+#define VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD0_MIN_RATIO_MASK GENMASK(15, 0)
+#define VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD0_MAX_RATIO_MASK GENMASK(31, 16)
+
+#define VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD1 0x0000000cu
+#define VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD1_TARGET_RATIO_MASK GENMASK(15, 0)
+#define VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD1_EPP_MASK GENMASK(31, 16)
+
+#define VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD2 0x00000010u
+#define VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD2_CONFIG_MASK GENMASK(15, 0)
+
+#define VPU_HW_BTRS_MTL_WP_REQ_CMD 0x00000014u
+#define VPU_HW_BTRS_MTL_WP_REQ_CMD_SEND_MASK BIT_MASK(0)
+
+#define VPU_HW_BTRS_MTL_WP_DOWNLOAD 0x00000018u
+#define VPU_HW_BTRS_MTL_WP_DOWNLOAD_TARGET_RATIO_MASK GENMASK(15, 0)
+
+#define VPU_HW_BTRS_MTL_CURRENT_PLL 0x0000001cu
+#define VPU_HW_BTRS_MTL_CURRENT_PLL_RATIO_MASK GENMASK(15, 0)
+
+#define VPU_HW_BTRS_MTL_PLL_ENABLE 0x00000020u
+
+#define VPU_HW_BTRS_MTL_FMIN_FUSE 0x00000024u
+#define VPU_HW_BTRS_MTL_FMIN_FUSE_MIN_RATIO_MASK GENMASK(7, 0)
+#define VPU_HW_BTRS_MTL_FMIN_FUSE_PN_RATIO_MASK GENMASK(15, 8)
+
+#define VPU_HW_BTRS_MTL_FMAX_FUSE 0x00000028u
+#define VPU_HW_BTRS_MTL_FMAX_FUSE_MAX_RATIO_MASK GENMASK(7, 0)
+
+#define VPU_HW_BTRS_MTL_TILE_FUSE 0x0000002cu
+#define VPU_HW_BTRS_MTL_TILE_FUSE_VALID_MASK BIT_MASK(0)
+#define VPU_HW_BTRS_MTL_TILE_FUSE_SKU_MASK GENMASK(3, 2)
+
+#define VPU_HW_BTRS_MTL_LOCAL_INT_MASK 0x00000030u
+#define VPU_HW_BTRS_MTL_GLOBAL_INT_MASK 0x00000034u
+
+#define VPU_HW_BTRS_MTL_PLL_STATUS 0x00000040u
+#define VPU_HW_BTRS_MTL_PLL_STATUS_LOCK_MASK BIT_MASK(1)
+
+#define VPU_HW_BTRS_MTL_VPU_STATUS 0x00000044u
+#define VPU_HW_BTRS_MTL_VPU_STATUS_READY_MASK BIT_MASK(0)
+#define VPU_HW_BTRS_MTL_VPU_STATUS_IDLE_MASK BIT_MASK(1)
+
+#define VPU_HW_BTRS_MTL_VPU_D0I3_CONTROL 0x00000060u
+#define VPU_HW_BTRS_MTL_VPU_D0I3_CONTROL_INPROGRESS_MASK BIT_MASK(0)
+#define VPU_HW_BTRS_MTL_VPU_D0I3_CONTROL_I3_MASK BIT_MASK(2)
+
+#define VPU_HW_BTRS_MTL_VPU_IP_RESET 0x00000050u
+#define VPU_HW_BTRS_MTL_VPU_IP_RESET_TRIGGER_MASK BIT_MASK(0)
+
+#define VPU_HW_BTRS_MTL_VPU_TELEMETRY_OFFSET 0x00000080u
+#define VPU_HW_BTRS_MTL_VPU_TELEMETRY_SIZE 0x00000084u
+#define VPU_HW_BTRS_MTL_VPU_TELEMETRY_ENABLE 0x00000088u
+
+#define VPU_HW_BTRS_MTL_ATS_ERR_LOG_0 0x000000a0u
+#define VPU_HW_BTRS_MTL_ATS_ERR_LOG_1 0x000000a4u
+#define VPU_HW_BTRS_MTL_ATS_ERR_CLEAR 0x000000a8u
+
+#define VPU_HW_BTRS_MTL_UFI_ERR_LOG 0x000000b0u
+#define VPU_HW_BTRS_MTL_UFI_ERR_LOG_CQ_ID_MASK GENMASK(11, 0)
+#define VPU_HW_BTRS_MTL_UFI_ERR_LOG_AXI_ID_MASK GENMASK(19, 12)
+#define VPU_HW_BTRS_MTL_UFI_ERR_LOG_OPCODE_MASK GENMASK(24, 20)
+
+#define VPU_HW_BTRS_MTL_UFI_ERR_CLEAR 0x000000b4u
+
+#endif /* __IVPU_HW_BTRS_MTL_REG_H__ */
diff --git a/drivers/accel/ivpu/ivpu_hw_ip.c b/drivers/accel/ivpu/ivpu_hw_ip.c
new file mode 100644
index 000000000000..dfd2f4a5b526
--- /dev/null
+++ b/drivers/accel/ivpu/ivpu_hw_ip.c
@@ -0,0 +1,1174 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2020-2024 Intel Corporation
+ */
+
+#include "ivpu_drv.h"
+#include "ivpu_fw.h"
+#include "ivpu_hw.h"
+#include "ivpu_hw_37xx_reg.h"
+#include "ivpu_hw_40xx_reg.h"
+#include "ivpu_hw_ip.h"
+#include "ivpu_hw_reg_io.h"
+#include "ivpu_mmu.h"
+#include "ivpu_pm.h"
+
+#define PWR_ISLAND_EN_POST_DLY_FREQ_DEFAULT 0
+#define PWR_ISLAND_EN_POST_DLY_FREQ_HIGH 18
+#define PWR_ISLAND_STATUS_DLY_FREQ_DEFAULT 3
+#define PWR_ISLAND_STATUS_DLY_FREQ_HIGH 46
+#define PWR_ISLAND_STATUS_TIMEOUT_US (5 * USEC_PER_MSEC)
+
+#define TIM_SAFE_ENABLE 0xf1d0dead
+#define TIM_WATCHDOG_RESET_VALUE 0xffffffff
+
+#define ICB_0_IRQ_MASK_37XX ((REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, HOST_IPC_FIFO_INT)) | \
+ (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_0_INT)) | \
+ (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_1_INT)) | \
+ (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_2_INT)) | \
+ (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT)) | \
+ (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT)) | \
+ (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT)))
+
+#define ICB_1_IRQ_MASK_37XX ((REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_2_INT)) | \
+ (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_3_INT)) | \
+ (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_4_INT)))
+
+#define ICB_0_1_IRQ_MASK_37XX ((((u64)ICB_1_IRQ_MASK_37XX) << 32) | ICB_0_IRQ_MASK_37XX)
+
+#define ICB_0_IRQ_MASK_40XX ((REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, HOST_IPC_FIFO_INT)) | \
+ (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_0_INT)) | \
+ (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_1_INT)) | \
+ (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_2_INT)) | \
+ (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT)) | \
+ (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT)) | \
+ (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT)))
+
+#define ICB_1_IRQ_MASK_40XX ((REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_2_INT)) | \
+ (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_3_INT)) | \
+ (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_4_INT)))
+
+#define ICB_0_1_IRQ_MASK_40XX ((((u64)ICB_1_IRQ_MASK_40XX) << 32) | ICB_0_IRQ_MASK_40XX)
+
+#define ITF_FIREWALL_VIOLATION_MASK_37XX ((REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, CSS_ROM_CMX)) | \
+ (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, CSS_DBG)) | \
+ (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, CSS_CTRL)) | \
+ (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, DEC400)) | \
+ (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, MSS_NCE)) | \
+ (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, MSS_MBI)) | \
+ (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, MSS_MBI_CMX)))
+
+#define ITF_FIREWALL_VIOLATION_MASK_40XX ((REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, CSS_ROM_CMX)) | \
+ (REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, CSS_DBG)) | \
+ (REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, CSS_CTRL)) | \
+ (REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, DEC400)) | \
+ (REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, MSS_NCE)) | \
+ (REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, MSS_MBI)) | \
+ (REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, MSS_MBI_CMX)))
+
+static int wait_for_ip_bar(struct ivpu_device *vdev)
+{
+ return REGV_POLL_FLD(VPU_37XX_HOST_SS_CPR_RST_CLR, AON, 0, 100);
+}
+
+static void host_ss_rst_clr(struct ivpu_device *vdev)
+{
+ u32 val = 0;
+
+ val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_CLR, TOP_NOC, val);
+ val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_CLR, DSS_MAS, val);
+ val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_CLR, MSS_MAS, val);
+
+ REGV_WR32(VPU_37XX_HOST_SS_CPR_RST_CLR, val);
+}
+
+static int host_ss_noc_qreqn_check_37xx(struct ivpu_device *vdev, u32 exp_val)
+{
+ u32 val = REGV_RD32(VPU_37XX_HOST_SS_NOC_QREQN);
+
+ if (!REG_TEST_FLD_NUM(VPU_37XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, exp_val, val))
+ return -EIO;
+
+ return 0;
+}
+
+static int host_ss_noc_qreqn_check_40xx(struct ivpu_device *vdev, u32 exp_val)
+{
+ u32 val = REGV_RD32(VPU_40XX_HOST_SS_NOC_QREQN);
+
+ if (!REG_TEST_FLD_NUM(VPU_40XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, exp_val, val))
+ return -EIO;
+
+ return 0;
+}
+
+static int host_ss_noc_qreqn_check(struct ivpu_device *vdev, u32 exp_val)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ return host_ss_noc_qreqn_check_37xx(vdev, exp_val);
+ else
+ return host_ss_noc_qreqn_check_40xx(vdev, exp_val);
+}
+
+static int host_ss_noc_qacceptn_check_37xx(struct ivpu_device *vdev, u32 exp_val)
+{
+ u32 val = REGV_RD32(VPU_37XX_HOST_SS_NOC_QACCEPTN);
+
+ if (!REG_TEST_FLD_NUM(VPU_37XX_HOST_SS_NOC_QACCEPTN, TOP_SOCMMIO, exp_val, val))
+ return -EIO;
+
+ return 0;
+}
+
+static int host_ss_noc_qacceptn_check_40xx(struct ivpu_device *vdev, u32 exp_val)
+{
+ u32 val = REGV_RD32(VPU_40XX_HOST_SS_NOC_QACCEPTN);
+
+ if (!REG_TEST_FLD_NUM(VPU_40XX_HOST_SS_NOC_QACCEPTN, TOP_SOCMMIO, exp_val, val))
+ return -EIO;
+
+ return 0;
+}
+
+static int host_ss_noc_qacceptn_check(struct ivpu_device *vdev, u32 exp_val)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ return host_ss_noc_qacceptn_check_37xx(vdev, exp_val);
+ else
+ return host_ss_noc_qacceptn_check_40xx(vdev, exp_val);
+}
+
+static int host_ss_noc_qdeny_check_37xx(struct ivpu_device *vdev, u32 exp_val)
+{
+ u32 val = REGV_RD32(VPU_37XX_HOST_SS_NOC_QDENY);
+
+ if (!REG_TEST_FLD_NUM(VPU_37XX_HOST_SS_NOC_QDENY, TOP_SOCMMIO, exp_val, val))
+ return -EIO;
+
+ return 0;
+}
+
+static int host_ss_noc_qdeny_check_40xx(struct ivpu_device *vdev, u32 exp_val)
+{
+ u32 val = REGV_RD32(VPU_40XX_HOST_SS_NOC_QDENY);
+
+ if (!REG_TEST_FLD_NUM(VPU_40XX_HOST_SS_NOC_QDENY, TOP_SOCMMIO, exp_val, val))
+ return -EIO;
+
+ return 0;
+}
+
+static int host_ss_noc_qdeny_check(struct ivpu_device *vdev, u32 exp_val)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ return host_ss_noc_qdeny_check_37xx(vdev, exp_val);
+ else
+ return host_ss_noc_qdeny_check_40xx(vdev, exp_val);
+}
+
+static int top_noc_qrenqn_check_37xx(struct ivpu_device *vdev, u32 exp_val)
+{
+ u32 val = REGV_RD32(VPU_37XX_TOP_NOC_QREQN);
+
+ if (!REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QREQN, CPU_CTRL, exp_val, val) ||
+ !REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, exp_val, val))
+ return -EIO;
+
+ return 0;
+}
+
+static int top_noc_qrenqn_check_40xx(struct ivpu_device *vdev, u32 exp_val)
+{
+ u32 val = REGV_RD32(VPU_40XX_TOP_NOC_QREQN);
+
+ if (!REG_TEST_FLD_NUM(VPU_40XX_TOP_NOC_QREQN, CPU_CTRL, exp_val, val) ||
+ !REG_TEST_FLD_NUM(VPU_40XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, exp_val, val))
+ return -EIO;
+
+ return 0;
+}
+
+static int top_noc_qreqn_check(struct ivpu_device *vdev, u32 exp_val)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ return top_noc_qrenqn_check_37xx(vdev, exp_val);
+ else
+ return top_noc_qrenqn_check_40xx(vdev, exp_val);
+}
+
+int ivpu_hw_ip_host_ss_configure(struct ivpu_device *vdev)
+{
+ int ret;
+
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) {
+ ret = wait_for_ip_bar(vdev);
+ if (ret) {
+ ivpu_err(vdev, "Timed out waiting for NPU IP bar\n");
+ return ret;
+ }
+ host_ss_rst_clr(vdev);
+ }
+
+ ret = host_ss_noc_qreqn_check(vdev, 0x0);
+ if (ret) {
+ ivpu_err(vdev, "Failed qreqn check: %d\n", ret);
+ return ret;
+ }
+
+ ret = host_ss_noc_qacceptn_check(vdev, 0x0);
+ if (ret) {
+ ivpu_err(vdev, "Failed qacceptn check: %d\n", ret);
+ return ret;
+ }
+
+ ret = host_ss_noc_qdeny_check(vdev, 0x0);
+ if (ret)
+ ivpu_err(vdev, "Failed qdeny check %d\n", ret);
+
+ return ret;
+}
+
+static void idle_gen_drive_37xx(struct ivpu_device *vdev, bool enable)
+{
+ u32 val = REGV_RD32(VPU_37XX_HOST_SS_AON_VPU_IDLE_GEN);
+
+ if (enable)
+ val = REG_SET_FLD(VPU_37XX_HOST_SS_AON_VPU_IDLE_GEN, EN, val);
+ else
+ val = REG_CLR_FLD(VPU_37XX_HOST_SS_AON_VPU_IDLE_GEN, EN, val);
+
+ REGV_WR32(VPU_37XX_HOST_SS_AON_VPU_IDLE_GEN, val);
+}
+
+static void idle_gen_drive_40xx(struct ivpu_device *vdev, bool enable)
+{
+ u32 val = REGV_RD32(VPU_40XX_HOST_SS_AON_IDLE_GEN);
+
+ if (enable)
+ val = REG_SET_FLD(VPU_40XX_HOST_SS_AON_IDLE_GEN, EN, val);
+ else
+ val = REG_CLR_FLD(VPU_40XX_HOST_SS_AON_IDLE_GEN, EN, val);
+
+ REGV_WR32(VPU_40XX_HOST_SS_AON_IDLE_GEN, val);
+}
+
+void ivpu_hw_ip_idle_gen_enable(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ idle_gen_drive_37xx(vdev, true);
+ else
+ idle_gen_drive_40xx(vdev, true);
+}
+
+void ivpu_hw_ip_idle_gen_disable(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ idle_gen_drive_37xx(vdev, false);
+ else
+ idle_gen_drive_40xx(vdev, false);
+}
+
+static void pwr_island_delay_set_50xx(struct ivpu_device *vdev)
+{
+ u32 val, post, status;
+
+ if (vdev->hw->pll.profiling_freq == PLL_PROFILING_FREQ_DEFAULT) {
+ post = PWR_ISLAND_EN_POST_DLY_FREQ_DEFAULT;
+ status = PWR_ISLAND_STATUS_DLY_FREQ_DEFAULT;
+ } else {
+ post = PWR_ISLAND_EN_POST_DLY_FREQ_HIGH;
+ status = PWR_ISLAND_STATUS_DLY_FREQ_HIGH;
+ }
+
+ val = REGV_RD32(VPU_50XX_HOST_SS_AON_PWR_ISLAND_EN_POST_DLY);
+ val = REG_SET_FLD_NUM(VPU_50XX_HOST_SS_AON_PWR_ISLAND_EN_POST_DLY, POST_DLY, post, val);
+ REGV_WR32(VPU_50XX_HOST_SS_AON_PWR_ISLAND_EN_POST_DLY, val);
+
+ val = REGV_RD32(VPU_50XX_HOST_SS_AON_PWR_ISLAND_STATUS_DLY);
+ val = REG_SET_FLD_NUM(VPU_50XX_HOST_SS_AON_PWR_ISLAND_STATUS_DLY, STATUS_DLY, status, val);
+ REGV_WR32(VPU_50XX_HOST_SS_AON_PWR_ISLAND_STATUS_DLY, val);
+}
+
+static void pwr_island_trickle_drive_37xx(struct ivpu_device *vdev, bool enable)
+{
+ u32 val = REGV_RD32(VPU_37XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0);
+
+ if (enable)
+ val = REG_SET_FLD(VPU_37XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, MSS_CPU, val);
+ else
+ val = REG_CLR_FLD(VPU_37XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, MSS_CPU, val);
+
+ REGV_WR32(VPU_37XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, val);
+}
+
+static void pwr_island_trickle_drive_40xx(struct ivpu_device *vdev, bool enable)
+{
+ u32 val = REGV_RD32(VPU_40XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0);
+
+ if (enable)
+ val = REG_SET_FLD(VPU_40XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, CSS_CPU, val);
+ else
+ val = REG_CLR_FLD(VPU_40XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, CSS_CPU, val);
+
+ REGV_WR32(VPU_40XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, val);
+
+ if (enable)
+ ndelay(500);
+}
+
+static void pwr_island_drive_37xx(struct ivpu_device *vdev, bool enable)
+{
+ u32 val = REGV_RD32(VPU_40XX_HOST_SS_AON_PWR_ISLAND_EN0);
+
+ if (enable)
+ val = REG_SET_FLD(VPU_40XX_HOST_SS_AON_PWR_ISLAND_EN0, CSS_CPU, val);
+ else
+ val = REG_CLR_FLD(VPU_40XX_HOST_SS_AON_PWR_ISLAND_EN0, CSS_CPU, val);
+
+ REGV_WR32(VPU_40XX_HOST_SS_AON_PWR_ISLAND_EN0, val);
+
+ if (!enable)
+ ndelay(500);
+}
+
+static void pwr_island_drive_40xx(struct ivpu_device *vdev, bool enable)
+{
+ u32 val = REGV_RD32(VPU_37XX_HOST_SS_AON_PWR_ISLAND_EN0);
+
+ if (enable)
+ val = REG_SET_FLD(VPU_37XX_HOST_SS_AON_PWR_ISLAND_EN0, MSS_CPU, val);
+ else
+ val = REG_CLR_FLD(VPU_37XX_HOST_SS_AON_PWR_ISLAND_EN0, MSS_CPU, val);
+
+ REGV_WR32(VPU_37XX_HOST_SS_AON_PWR_ISLAND_EN0, val);
+}
+
+static void pwr_island_enable(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) {
+ pwr_island_trickle_drive_37xx(vdev, true);
+ pwr_island_drive_37xx(vdev, true);
+ } else {
+ pwr_island_trickle_drive_40xx(vdev, true);
+ pwr_island_drive_40xx(vdev, true);
+ }
+}
+
+static int wait_for_pwr_island_status(struct ivpu_device *vdev, u32 exp_val)
+{
+ if (IVPU_WA(punit_disabled))
+ return 0;
+
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ return REGV_POLL_FLD(VPU_37XX_HOST_SS_AON_PWR_ISLAND_STATUS0, MSS_CPU, exp_val,
+ PWR_ISLAND_STATUS_TIMEOUT_US);
+ else
+ return REGV_POLL_FLD(VPU_40XX_HOST_SS_AON_PWR_ISLAND_STATUS0, CSS_CPU, exp_val,
+ PWR_ISLAND_STATUS_TIMEOUT_US);
+}
+
+static void pwr_island_isolation_drive_37xx(struct ivpu_device *vdev, bool enable)
+{
+ u32 val = REGV_RD32(VPU_37XX_HOST_SS_AON_PWR_ISO_EN0);
+
+ if (enable)
+ val = REG_SET_FLD(VPU_37XX_HOST_SS_AON_PWR_ISO_EN0, MSS_CPU, val);
+ else
+ val = REG_CLR_FLD(VPU_37XX_HOST_SS_AON_PWR_ISO_EN0, MSS_CPU, val);
+
+ REGV_WR32(VPU_37XX_HOST_SS_AON_PWR_ISO_EN0, val);
+}
+
+static void pwr_island_isolation_drive_40xx(struct ivpu_device *vdev, bool enable)
+{
+ u32 val = REGV_RD32(VPU_40XX_HOST_SS_AON_PWR_ISO_EN0);
+
+ if (enable)
+ val = REG_SET_FLD(VPU_40XX_HOST_SS_AON_PWR_ISO_EN0, CSS_CPU, val);
+ else
+ val = REG_CLR_FLD(VPU_40XX_HOST_SS_AON_PWR_ISO_EN0, CSS_CPU, val);
+
+ REGV_WR32(VPU_40XX_HOST_SS_AON_PWR_ISO_EN0, val);
+}
+
+static void pwr_island_isolation_drive(struct ivpu_device *vdev, bool enable)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ pwr_island_isolation_drive_37xx(vdev, enable);
+ else
+ pwr_island_isolation_drive_40xx(vdev, enable);
+}
+
+static void pwr_island_isolation_disable(struct ivpu_device *vdev)
+{
+ pwr_island_isolation_drive(vdev, false);
+}
+
+static void host_ss_clk_drive_37xx(struct ivpu_device *vdev, bool enable)
+{
+ u32 val = REGV_RD32(VPU_37XX_HOST_SS_CPR_CLK_SET);
+
+ if (enable) {
+ val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, TOP_NOC, val);
+ val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, DSS_MAS, val);
+ val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, MSS_MAS, val);
+ } else {
+ val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, TOP_NOC, val);
+ val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, DSS_MAS, val);
+ val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, MSS_MAS, val);
+ }
+
+ REGV_WR32(VPU_37XX_HOST_SS_CPR_CLK_SET, val);
+}
+
+static void host_ss_clk_drive_40xx(struct ivpu_device *vdev, bool enable)
+{
+ u32 val = REGV_RD32(VPU_40XX_HOST_SS_CPR_CLK_EN);
+
+ if (enable) {
+ val = REG_SET_FLD(VPU_40XX_HOST_SS_CPR_CLK_EN, TOP_NOC, val);
+ val = REG_SET_FLD(VPU_40XX_HOST_SS_CPR_CLK_EN, DSS_MAS, val);
+ val = REG_SET_FLD(VPU_40XX_HOST_SS_CPR_CLK_EN, CSS_MAS, val);
+ } else {
+ val = REG_CLR_FLD(VPU_40XX_HOST_SS_CPR_CLK_EN, TOP_NOC, val);
+ val = REG_CLR_FLD(VPU_40XX_HOST_SS_CPR_CLK_EN, DSS_MAS, val);
+ val = REG_CLR_FLD(VPU_40XX_HOST_SS_CPR_CLK_EN, CSS_MAS, val);
+ }
+
+ REGV_WR32(VPU_40XX_HOST_SS_CPR_CLK_EN, val);
+}
+
+static void host_ss_clk_drive(struct ivpu_device *vdev, bool enable)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ host_ss_clk_drive_37xx(vdev, enable);
+ else
+ host_ss_clk_drive_40xx(vdev, enable);
+}
+
+static void host_ss_clk_enable(struct ivpu_device *vdev)
+{
+ host_ss_clk_drive(vdev, true);
+}
+
+static void host_ss_rst_drive_37xx(struct ivpu_device *vdev, bool enable)
+{
+ u32 val = REGV_RD32(VPU_37XX_HOST_SS_CPR_RST_SET);
+
+ if (enable) {
+ val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, TOP_NOC, val);
+ val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, DSS_MAS, val);
+ val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, MSS_MAS, val);
+ } else {
+ val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, TOP_NOC, val);
+ val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, DSS_MAS, val);
+ val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, MSS_MAS, val);
+ }
+
+ REGV_WR32(VPU_37XX_HOST_SS_CPR_RST_SET, val);
+}
+
+static void host_ss_rst_drive_40xx(struct ivpu_device *vdev, bool enable)
+{
+ u32 val = REGV_RD32(VPU_40XX_HOST_SS_CPR_RST_EN);
+
+ if (enable) {
+ val = REG_SET_FLD(VPU_40XX_HOST_SS_CPR_RST_EN, TOP_NOC, val);
+ val = REG_SET_FLD(VPU_40XX_HOST_SS_CPR_RST_EN, DSS_MAS, val);
+ val = REG_SET_FLD(VPU_40XX_HOST_SS_CPR_RST_EN, CSS_MAS, val);
+ } else {
+ val = REG_CLR_FLD(VPU_40XX_HOST_SS_CPR_RST_EN, TOP_NOC, val);
+ val = REG_CLR_FLD(VPU_40XX_HOST_SS_CPR_RST_EN, DSS_MAS, val);
+ val = REG_CLR_FLD(VPU_40XX_HOST_SS_CPR_RST_EN, CSS_MAS, val);
+ }
+
+ REGV_WR32(VPU_40XX_HOST_SS_CPR_RST_EN, val);
+}
+
+static void host_ss_rst_drive(struct ivpu_device *vdev, bool enable)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ host_ss_rst_drive_37xx(vdev, enable);
+ else
+ host_ss_rst_drive_40xx(vdev, enable);
+}
+
+static void host_ss_rst_enable(struct ivpu_device *vdev)
+{
+ host_ss_rst_drive(vdev, true);
+}
+
+static void host_ss_noc_qreqn_top_socmmio_drive_37xx(struct ivpu_device *vdev, bool enable)
+{
+ u32 val = REGV_RD32(VPU_37XX_HOST_SS_NOC_QREQN);
+
+ if (enable)
+ val = REG_SET_FLD(VPU_37XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, val);
+ else
+ val = REG_CLR_FLD(VPU_37XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, val);
+ REGV_WR32(VPU_37XX_HOST_SS_NOC_QREQN, val);
+}
+
+static void host_ss_noc_qreqn_top_socmmio_drive_40xx(struct ivpu_device *vdev, bool enable)
+{
+ u32 val = REGV_RD32(VPU_40XX_HOST_SS_NOC_QREQN);
+
+ if (enable)
+ val = REG_SET_FLD(VPU_40XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, val);
+ else
+ val = REG_CLR_FLD(VPU_40XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, val);
+ REGV_WR32(VPU_40XX_HOST_SS_NOC_QREQN, val);
+}
+
+static void host_ss_noc_qreqn_top_socmmio_drive(struct ivpu_device *vdev, bool enable)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ host_ss_noc_qreqn_top_socmmio_drive_37xx(vdev, enable);
+ else
+ host_ss_noc_qreqn_top_socmmio_drive_40xx(vdev, enable);
+}
+
+static int host_ss_axi_drive(struct ivpu_device *vdev, bool enable)
+{
+ int ret;
+
+ host_ss_noc_qreqn_top_socmmio_drive(vdev, enable);
+
+ ret = host_ss_noc_qacceptn_check(vdev, enable ? 0x1 : 0x0);
+ if (ret) {
+ ivpu_err(vdev, "Failed HOST SS NOC QACCEPTN check: %d\n", ret);
+ return ret;
+ }
+
+ ret = host_ss_noc_qdeny_check(vdev, 0x0);
+ if (ret)
+ ivpu_err(vdev, "Failed HOST SS NOC QDENY check: %d\n", ret);
+
+ return ret;
+}
+
+static void top_noc_qreqn_drive_40xx(struct ivpu_device *vdev, bool enable)
+{
+ u32 val = REGV_RD32(VPU_40XX_TOP_NOC_QREQN);
+
+ if (enable) {
+ val = REG_SET_FLD(VPU_40XX_TOP_NOC_QREQN, CPU_CTRL, val);
+ val = REG_SET_FLD(VPU_40XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, val);
+ } else {
+ val = REG_CLR_FLD(VPU_40XX_TOP_NOC_QREQN, CPU_CTRL, val);
+ val = REG_CLR_FLD(VPU_40XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, val);
+ }
+
+ REGV_WR32(VPU_40XX_TOP_NOC_QREQN, val);
+}
+
+static void top_noc_qreqn_drive_37xx(struct ivpu_device *vdev, bool enable)
+{
+ u32 val = REGV_RD32(VPU_37XX_TOP_NOC_QREQN);
+
+ if (enable) {
+ val = REG_SET_FLD(VPU_37XX_TOP_NOC_QREQN, CPU_CTRL, val);
+ val = REG_SET_FLD(VPU_37XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, val);
+ } else {
+ val = REG_CLR_FLD(VPU_37XX_TOP_NOC_QREQN, CPU_CTRL, val);
+ val = REG_CLR_FLD(VPU_37XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, val);
+ }
+
+ REGV_WR32(VPU_37XX_TOP_NOC_QREQN, val);
+}
+
+static void top_noc_qreqn_drive(struct ivpu_device *vdev, bool enable)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ top_noc_qreqn_drive_37xx(vdev, enable);
+ else
+ top_noc_qreqn_drive_40xx(vdev, enable);
+}
+
+int ivpu_hw_ip_host_ss_axi_enable(struct ivpu_device *vdev)
+{
+ return host_ss_axi_drive(vdev, true);
+}
+
+static int top_noc_qacceptn_check_37xx(struct ivpu_device *vdev, u32 exp_val)
+{
+ u32 val = REGV_RD32(VPU_37XX_TOP_NOC_QACCEPTN);
+
+ if (!REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QACCEPTN, CPU_CTRL, exp_val, val) ||
+ !REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QACCEPTN, HOSTIF_L2CACHE, exp_val, val))
+ return -EIO;
+
+ return 0;
+}
+
+static int top_noc_qacceptn_check_40xx(struct ivpu_device *vdev, u32 exp_val)
+{
+ u32 val = REGV_RD32(VPU_40XX_TOP_NOC_QACCEPTN);
+
+ if (!REG_TEST_FLD_NUM(VPU_40XX_TOP_NOC_QACCEPTN, CPU_CTRL, exp_val, val) ||
+ !REG_TEST_FLD_NUM(VPU_40XX_TOP_NOC_QACCEPTN, HOSTIF_L2CACHE, exp_val, val))
+ return -EIO;
+
+ return 0;
+}
+
+static int top_noc_qacceptn_check(struct ivpu_device *vdev, u32 exp_val)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ return top_noc_qacceptn_check_37xx(vdev, exp_val);
+ else
+ return top_noc_qacceptn_check_40xx(vdev, exp_val);
+}
+
+static int top_noc_qdeny_check_37xx(struct ivpu_device *vdev, u32 exp_val)
+{
+ u32 val = REGV_RD32(VPU_37XX_TOP_NOC_QDENY);
+
+ if (!REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QDENY, CPU_CTRL, exp_val, val) ||
+ !REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QDENY, HOSTIF_L2CACHE, exp_val, val))
+ return -EIO;
+
+ return 0;
+}
+
+static int top_noc_qdeny_check_40xx(struct ivpu_device *vdev, u32 exp_val)
+{
+ u32 val = REGV_RD32(VPU_40XX_TOP_NOC_QDENY);
+
+ if (!REG_TEST_FLD_NUM(VPU_40XX_TOP_NOC_QDENY, CPU_CTRL, exp_val, val) ||
+ !REG_TEST_FLD_NUM(VPU_40XX_TOP_NOC_QDENY, HOSTIF_L2CACHE, exp_val, val))
+ return -EIO;
+
+ return 0;
+}
+
+static int top_noc_qdeny_check(struct ivpu_device *vdev, u32 exp_val)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ return top_noc_qdeny_check_37xx(vdev, exp_val);
+ else
+ return top_noc_qdeny_check_40xx(vdev, exp_val);
+}
+
+static int top_noc_drive(struct ivpu_device *vdev, bool enable)
+{
+ int ret;
+
+ top_noc_qreqn_drive(vdev, enable);
+
+ ret = top_noc_qacceptn_check(vdev, enable ? 0x1 : 0x0);
+ if (ret) {
+ ivpu_err(vdev, "Failed TOP NOC QACCEPTN check: %d\n", ret);
+ return ret;
+ }
+
+ ret = top_noc_qdeny_check(vdev, 0x0);
+ if (ret)
+ ivpu_err(vdev, "Failed TOP NOC QDENY check: %d\n", ret);
+
+ return ret;
+}
+
+int ivpu_hw_ip_top_noc_enable(struct ivpu_device *vdev)
+{
+ return top_noc_drive(vdev, true);
+}
+
+static void dpu_active_drive_37xx(struct ivpu_device *vdev, bool enable)
+{
+ u32 val = REGV_RD32(VPU_37XX_HOST_SS_AON_DPU_ACTIVE);
+
+ if (enable)
+ val = REG_SET_FLD(VPU_37XX_HOST_SS_AON_DPU_ACTIVE, DPU_ACTIVE, val);
+ else
+ val = REG_CLR_FLD(VPU_37XX_HOST_SS_AON_DPU_ACTIVE, DPU_ACTIVE, val);
+
+ REGV_WR32(VPU_37XX_HOST_SS_AON_DPU_ACTIVE, val);
+}
+
+int ivpu_hw_ip_pwr_domain_enable(struct ivpu_device *vdev)
+{
+ int ret;
+
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_50XX)
+ pwr_island_delay_set_50xx(vdev);
+
+ pwr_island_enable(vdev);
+
+ ret = wait_for_pwr_island_status(vdev, 0x1);
+ if (ret) {
+ ivpu_err(vdev, "Timed out waiting for power island status\n");
+ return ret;
+ }
+
+ ret = top_noc_qreqn_check(vdev, 0x0);
+ if (ret) {
+ ivpu_err(vdev, "Failed TOP NOC QREQN check %d\n", ret);
+ return ret;
+ }
+
+ host_ss_clk_enable(vdev);
+ pwr_island_isolation_disable(vdev);
+ host_ss_rst_enable(vdev);
+
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ dpu_active_drive_37xx(vdev, true);
+
+ return ret;
+}
+
+u64 ivpu_hw_ip_read_perf_timer_counter(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ return REGV_RD64(VPU_37XX_CPU_SS_TIM_PERF_FREE_CNT);
+ else
+ return REGV_RD64(VPU_40XX_CPU_SS_TIM_PERF_EXT_FREE_CNT);
+}
+
+static void ivpu_hw_ip_snoop_disable_37xx(struct ivpu_device *vdev)
+{
+ u32 val = REGV_RD32(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES);
+
+ val = REG_SET_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, NOSNOOP_OVERRIDE_EN, val);
+ val = REG_CLR_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, AW_NOSNOOP_OVERRIDE, val);
+
+ if (ivpu_is_force_snoop_enabled(vdev))
+ val = REG_CLR_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, AR_NOSNOOP_OVERRIDE, val);
+ else
+ val = REG_SET_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, AR_NOSNOOP_OVERRIDE, val);
+
+ REGV_WR32(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, val);
+}
+
+static void ivpu_hw_ip_snoop_disable_40xx(struct ivpu_device *vdev)
+{
+ u32 val = REGV_RD32(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES);
+
+ val = REG_SET_FLD(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, SNOOP_OVERRIDE_EN, val);
+ val = REG_SET_FLD(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, AW_SNOOP_OVERRIDE, val);
+
+ if (ivpu_is_force_snoop_enabled(vdev))
+ val = REG_SET_FLD(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, AR_SNOOP_OVERRIDE, val);
+ else
+ val = REG_CLR_FLD(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, AR_SNOOP_OVERRIDE, val);
+
+ REGV_WR32(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, val);
+}
+
+void ivpu_hw_ip_snoop_disable(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ return ivpu_hw_ip_snoop_disable_37xx(vdev);
+ else
+ return ivpu_hw_ip_snoop_disable_40xx(vdev);
+}
+
+static void ivpu_hw_ip_tbu_mmu_enable_37xx(struct ivpu_device *vdev)
+{
+ u32 val = REGV_RD32(VPU_37XX_HOST_IF_TBU_MMUSSIDV);
+
+ val = REG_SET_FLD(VPU_37XX_HOST_IF_TBU_MMUSSIDV, TBU0_AWMMUSSIDV, val);
+ val = REG_SET_FLD(VPU_37XX_HOST_IF_TBU_MMUSSIDV, TBU0_ARMMUSSIDV, val);
+ val = REG_SET_FLD(VPU_37XX_HOST_IF_TBU_MMUSSIDV, TBU2_AWMMUSSIDV, val);
+ val = REG_SET_FLD(VPU_37XX_HOST_IF_TBU_MMUSSIDV, TBU2_ARMMUSSIDV, val);
+
+ REGV_WR32(VPU_37XX_HOST_IF_TBU_MMUSSIDV, val);
+}
+
+static void ivpu_hw_ip_tbu_mmu_enable_40xx(struct ivpu_device *vdev)
+{
+ u32 val = REGV_RD32(VPU_40XX_HOST_IF_TBU_MMUSSIDV);
+
+ val = REG_SET_FLD(VPU_40XX_HOST_IF_TBU_MMUSSIDV, TBU0_AWMMUSSIDV, val);
+ val = REG_SET_FLD(VPU_40XX_HOST_IF_TBU_MMUSSIDV, TBU0_ARMMUSSIDV, val);
+ val = REG_SET_FLD(VPU_40XX_HOST_IF_TBU_MMUSSIDV, TBU1_AWMMUSSIDV, val);
+ val = REG_SET_FLD(VPU_40XX_HOST_IF_TBU_MMUSSIDV, TBU1_ARMMUSSIDV, val);
+ val = REG_SET_FLD(VPU_40XX_HOST_IF_TBU_MMUSSIDV, TBU2_AWMMUSSIDV, val);
+ val = REG_SET_FLD(VPU_40XX_HOST_IF_TBU_MMUSSIDV, TBU2_ARMMUSSIDV, val);
+
+ REGV_WR32(VPU_40XX_HOST_IF_TBU_MMUSSIDV, val);
+}
+
+void ivpu_hw_ip_tbu_mmu_enable(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ return ivpu_hw_ip_tbu_mmu_enable_37xx(vdev);
+ else
+ return ivpu_hw_ip_tbu_mmu_enable_40xx(vdev);
+}
+
+static int soc_cpu_boot_37xx(struct ivpu_device *vdev)
+{
+ u32 val;
+
+ val = REGV_RD32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC);
+ val = REG_SET_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RSTRUN0, val);
+
+ val = REG_CLR_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RSTVEC, val);
+ REGV_WR32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val);
+
+ val = REG_SET_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RESUME0, val);
+ REGV_WR32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val);
+
+ val = REG_CLR_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RESUME0, val);
+ REGV_WR32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val);
+
+ val = vdev->fw->entry_point >> 9;
+ REGV_WR32(VPU_37XX_HOST_SS_LOADING_ADDRESS_LO, val);
+
+ val = REG_SET_FLD(VPU_37XX_HOST_SS_LOADING_ADDRESS_LO, DONE, val);
+ REGV_WR32(VPU_37XX_HOST_SS_LOADING_ADDRESS_LO, val);
+
+ ivpu_dbg(vdev, PM, "Booting firmware, mode: %s\n",
+ vdev->fw->entry_point == vdev->fw->cold_boot_entry_point ? "cold boot" : "resume");
+
+ return 0;
+}
+
+static int cpu_noc_qacceptn_check_40xx(struct ivpu_device *vdev, u32 exp_val)
+{
+ u32 val = REGV_RD32(VPU_40XX_CPU_SS_CPR_NOC_QACCEPTN);
+
+ if (!REG_TEST_FLD_NUM(VPU_40XX_CPU_SS_CPR_NOC_QACCEPTN, TOP_MMIO, exp_val, val))
+ return -EIO;
+
+ return 0;
+}
+
+static int cpu_noc_qdeny_check_40xx(struct ivpu_device *vdev, u32 exp_val)
+{
+ u32 val = REGV_RD32(VPU_40XX_CPU_SS_CPR_NOC_QDENY);
+
+ if (!REG_TEST_FLD_NUM(VPU_40XX_CPU_SS_CPR_NOC_QDENY, TOP_MMIO, exp_val, val))
+ return -EIO;
+
+ return 0;
+}
+
+static void cpu_noc_top_mmio_drive_40xx(struct ivpu_device *vdev, bool enable)
+{
+ u32 val = REGV_RD32(VPU_40XX_CPU_SS_CPR_NOC_QREQN);
+
+ if (enable)
+ val = REG_SET_FLD(VPU_40XX_CPU_SS_CPR_NOC_QREQN, TOP_MMIO, val);
+ else
+ val = REG_CLR_FLD(VPU_40XX_CPU_SS_CPR_NOC_QREQN, TOP_MMIO, val);
+ REGV_WR32(VPU_40XX_CPU_SS_CPR_NOC_QREQN, val);
+}
+
+static int soc_cpu_drive_40xx(struct ivpu_device *vdev, bool enable)
+{
+ int ret;
+
+ cpu_noc_top_mmio_drive_40xx(vdev, enable);
+
+ ret = cpu_noc_qacceptn_check_40xx(vdev, enable ? 0x1 : 0x0);
+ if (ret) {
+ ivpu_err(vdev, "Failed qacceptn check: %d\n", ret);
+ return ret;
+ }
+
+ ret = cpu_noc_qdeny_check_40xx(vdev, 0x0);
+ if (ret)
+ ivpu_err(vdev, "Failed qdeny check: %d\n", ret);
+
+ return ret;
+}
+
+static int soc_cpu_enable(struct ivpu_device *vdev)
+{
+ return soc_cpu_drive_40xx(vdev, true);
+}
+
+static int soc_cpu_boot_40xx(struct ivpu_device *vdev)
+{
+ int ret;
+ u32 val;
+ u64 val64;
+
+ ret = soc_cpu_enable(vdev);
+ if (ret) {
+ ivpu_err(vdev, "Failed to enable SOC CPU: %d\n", ret);
+ return ret;
+ }
+
+ val64 = vdev->fw->entry_point;
+ val64 <<= ffs(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO_IMAGE_LOCATION_MASK) - 1;
+ REGV_WR64(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO, val64);
+
+ val = REGV_RD32(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO);
+ val = REG_SET_FLD(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO, DONE, val);
+ REGV_WR32(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO, val);
+
+ ivpu_dbg(vdev, PM, "Booting firmware, mode: %s\n",
+ ivpu_fw_is_cold_boot(vdev) ? "cold boot" : "resume");
+
+ return 0;
+}
+
+int ivpu_hw_ip_soc_cpu_boot(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ return soc_cpu_boot_37xx(vdev);
+ else
+ return soc_cpu_boot_40xx(vdev);
+}
+
+static void wdt_disable_37xx(struct ivpu_device *vdev)
+{
+ u32 val;
+
+ /* Enable writing and set non-zero WDT value */
+ REGV_WR32(VPU_37XX_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE);
+ REGV_WR32(VPU_37XX_CPU_SS_TIM_WATCHDOG, TIM_WATCHDOG_RESET_VALUE);
+
+ /* Enable writing and disable watchdog timer */
+ REGV_WR32(VPU_37XX_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE);
+ REGV_WR32(VPU_37XX_CPU_SS_TIM_WDOG_EN, 0);
+
+ /* Now clear the timeout interrupt */
+ val = REGV_RD32(VPU_37XX_CPU_SS_TIM_GEN_CONFIG);
+ val = REG_CLR_FLD(VPU_37XX_CPU_SS_TIM_GEN_CONFIG, WDOG_TO_INT_CLR, val);
+ REGV_WR32(VPU_37XX_CPU_SS_TIM_GEN_CONFIG, val);
+}
+
+static void wdt_disable_40xx(struct ivpu_device *vdev)
+{
+ u32 val;
+
+ REGV_WR32(VPU_40XX_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE);
+ REGV_WR32(VPU_40XX_CPU_SS_TIM_WATCHDOG, TIM_WATCHDOG_RESET_VALUE);
+
+ REGV_WR32(VPU_40XX_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE);
+ REGV_WR32(VPU_40XX_CPU_SS_TIM_WDOG_EN, 0);
+
+ val = REGV_RD32(VPU_40XX_CPU_SS_TIM_GEN_CONFIG);
+ val = REG_CLR_FLD(VPU_40XX_CPU_SS_TIM_GEN_CONFIG, WDOG_TO_INT_CLR, val);
+ REGV_WR32(VPU_40XX_CPU_SS_TIM_GEN_CONFIG, val);
+}
+
+void ivpu_hw_ip_wdt_disable(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ return wdt_disable_37xx(vdev);
+ else
+ return wdt_disable_40xx(vdev);
+}
+
+static u32 ipc_rx_count_get_37xx(struct ivpu_device *vdev)
+{
+ u32 count = REGV_RD32_SILENT(VPU_37XX_HOST_SS_TIM_IPC_FIFO_STAT);
+
+ return REG_GET_FLD(VPU_37XX_HOST_SS_TIM_IPC_FIFO_STAT, FILL_LEVEL, count);
+}
+
+static u32 ipc_rx_count_get_40xx(struct ivpu_device *vdev)
+{
+ u32 count = REGV_RD32_SILENT(VPU_40XX_HOST_SS_TIM_IPC_FIFO_STAT);
+
+ return REG_GET_FLD(VPU_40XX_HOST_SS_TIM_IPC_FIFO_STAT, FILL_LEVEL, count);
+}
+
+u32 ivpu_hw_ip_ipc_rx_count_get(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ return ipc_rx_count_get_37xx(vdev);
+ else
+ return ipc_rx_count_get_40xx(vdev);
+}
+
+void ivpu_hw_ip_irq_enable(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) {
+ REGV_WR32(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, ITF_FIREWALL_VIOLATION_MASK_37XX);
+ REGV_WR64(VPU_37XX_HOST_SS_ICB_ENABLE_0, ICB_0_1_IRQ_MASK_37XX);
+ } else {
+ REGV_WR32(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, ITF_FIREWALL_VIOLATION_MASK_40XX);
+ REGV_WR64(VPU_40XX_HOST_SS_ICB_ENABLE_0, ICB_0_1_IRQ_MASK_40XX);
+ }
+}
+
+void ivpu_hw_ip_irq_disable(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) {
+ REGV_WR64(VPU_37XX_HOST_SS_ICB_ENABLE_0, 0x0ull);
+ REGV_WR32(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, 0x0);
+ } else {
+ REGV_WR64(VPU_40XX_HOST_SS_ICB_ENABLE_0, 0x0ull);
+ REGV_WR32(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, 0x0ul);
+ }
+}
+
+static void diagnose_failure_37xx(struct ivpu_device *vdev)
+{
+ u32 reg = REGV_RD32(VPU_37XX_HOST_SS_ICB_STATUS_0) & ICB_0_IRQ_MASK_37XX;
+
+ if (ipc_rx_count_get_37xx(vdev))
+ ivpu_err(vdev, "IPC FIFO queue not empty, missed IPC IRQ");
+
+ if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT, reg))
+ ivpu_err(vdev, "WDT MSS timeout detected\n");
+
+ if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT, reg))
+ ivpu_err(vdev, "WDT NCE timeout detected\n");
+
+ if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT, reg))
+ ivpu_err(vdev, "NOC Firewall irq detected\n");
+}
+
+static void diagnose_failure_40xx(struct ivpu_device *vdev)
+{
+ u32 reg = REGV_RD32(VPU_40XX_HOST_SS_ICB_STATUS_0) & ICB_0_IRQ_MASK_40XX;
+
+ if (ipc_rx_count_get_40xx(vdev))
+ ivpu_err(vdev, "IPC FIFO queue not empty, missed IPC IRQ");
+
+ if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT, reg))
+ ivpu_err(vdev, "WDT MSS timeout detected\n");
+
+ if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT, reg))
+ ivpu_err(vdev, "WDT NCE timeout detected\n");
+
+ if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT, reg))
+ ivpu_err(vdev, "NOC Firewall irq detected\n");
+}
+
+void ivpu_hw_ip_diagnose_failure(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ diagnose_failure_37xx(vdev);
+ else
+ diagnose_failure_40xx(vdev);
+}
+
+void ivpu_hw_ip_irq_clear(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ REGV_WR64(VPU_37XX_HOST_SS_ICB_CLEAR_0, ICB_0_1_IRQ_MASK_37XX);
+ else
+ REGV_WR64(VPU_40XX_HOST_SS_ICB_CLEAR_0, ICB_0_1_IRQ_MASK_40XX);
+}
+
+static void irq_wdt_nce_handler(struct ivpu_device *vdev)
+{
+ ivpu_pm_trigger_recovery(vdev, "WDT NCE IRQ");
+}
+
+static void irq_wdt_mss_handler(struct ivpu_device *vdev)
+{
+ ivpu_hw_ip_wdt_disable(vdev);
+ ivpu_pm_trigger_recovery(vdev, "WDT MSS IRQ");
+}
+
+static void irq_noc_firewall_handler(struct ivpu_device *vdev)
+{
+ ivpu_pm_trigger_recovery(vdev, "NOC Firewall IRQ");
+}
+
+/* Handler for IRQs from NPU core */
+bool ivpu_hw_ip_irq_handler_37xx(struct ivpu_device *vdev, int irq)
+{
+ u32 status = REGV_RD32(VPU_37XX_HOST_SS_ICB_STATUS_0) & ICB_0_IRQ_MASK_37XX;
+
+ if (!status)
+ return false;
+
+ REGV_WR32(VPU_37XX_HOST_SS_ICB_CLEAR_0, status);
+
+ if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_0_INT, status))
+ ivpu_mmu_irq_evtq_handler(vdev);
+
+ if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, HOST_IPC_FIFO_INT, status))
+ ivpu_ipc_irq_handler(vdev);
+
+ if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_1_INT, status))
+ ivpu_dbg(vdev, IRQ, "MMU sync complete\n");
+
+ if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_2_INT, status))
+ ivpu_mmu_irq_gerr_handler(vdev);
+
+ if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT, status))
+ irq_wdt_mss_handler(vdev);
+
+ if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT, status))
+ irq_wdt_nce_handler(vdev);
+
+ if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT, status))
+ irq_noc_firewall_handler(vdev);
+
+ return true;
+}
+
+/* Handler for IRQs from NPU core */
+bool ivpu_hw_ip_irq_handler_40xx(struct ivpu_device *vdev, int irq)
+{
+ u32 status = REGV_RD32(VPU_40XX_HOST_SS_ICB_STATUS_0) & ICB_0_IRQ_MASK_40XX;
+
+ if (!status)
+ return false;
+
+ REGV_WR32(VPU_40XX_HOST_SS_ICB_CLEAR_0, status);
+
+ if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_0_INT, status))
+ ivpu_mmu_irq_evtq_handler(vdev);
+
+ if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, HOST_IPC_FIFO_INT, status))
+ ivpu_ipc_irq_handler(vdev);
+
+ if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_1_INT, status))
+ ivpu_dbg(vdev, IRQ, "MMU sync complete\n");
+
+ if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_2_INT, status))
+ ivpu_mmu_irq_gerr_handler(vdev);
+
+ if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT, status))
+ irq_wdt_mss_handler(vdev);
+
+ if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT, status))
+ irq_wdt_nce_handler(vdev);
+
+ if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT, status))
+ irq_noc_firewall_handler(vdev);
+
+ return true;
+}
+
+static void db_set_37xx(struct ivpu_device *vdev, u32 db_id)
+{
+ u32 reg_stride = VPU_37XX_CPU_SS_DOORBELL_1 - VPU_37XX_CPU_SS_DOORBELL_0;
+ u32 val = REG_FLD(VPU_37XX_CPU_SS_DOORBELL_0, SET);
+
+ REGV_WR32I(VPU_37XX_CPU_SS_DOORBELL_0, reg_stride, db_id, val);
+}
+
+static void db_set_40xx(struct ivpu_device *vdev, u32 db_id)
+{
+ u32 reg_stride = VPU_40XX_CPU_SS_DOORBELL_1 - VPU_40XX_CPU_SS_DOORBELL_0;
+ u32 val = REG_FLD(VPU_40XX_CPU_SS_DOORBELL_0, SET);
+
+ REGV_WR32I(VPU_40XX_CPU_SS_DOORBELL_0, reg_stride, db_id, val);
+}
+
+void ivpu_hw_ip_db_set(struct ivpu_device *vdev, u32 db_id)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ db_set_37xx(vdev, db_id);
+ else
+ db_set_40xx(vdev, db_id);
+}
+
+u32 ivpu_hw_ip_ipc_rx_addr_get(struct ivpu_device *vdev)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ return REGV_RD32(VPU_37XX_HOST_SS_TIM_IPC_FIFO_ATM);
+ else
+ return REGV_RD32(VPU_40XX_HOST_SS_TIM_IPC_FIFO_ATM);
+}
+
+void ivpu_hw_ip_ipc_tx_set(struct ivpu_device *vdev, u32 vpu_addr)
+{
+ if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
+ REGV_WR32(VPU_37XX_CPU_SS_TIM_IPC_FIFO, vpu_addr);
+ else
+ REGV_WR32(VPU_40XX_CPU_SS_TIM_IPC_FIFO, vpu_addr);
+}
diff --git a/drivers/accel/ivpu/ivpu_hw_ip.h b/drivers/accel/ivpu/ivpu_hw_ip.h
new file mode 100644
index 000000000000..5b1b391aa577
--- /dev/null
+++ b/drivers/accel/ivpu/ivpu_hw_ip.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2020-2024 Intel Corporation
+ */
+
+#ifndef __IVPU_HW_IP_H__
+#define __IVPU_HW_IP_H__
+
+#include "ivpu_drv.h"
+
+int ivpu_hw_ip_host_ss_configure(struct ivpu_device *vdev);
+void ivpu_hw_ip_idle_gen_enable(struct ivpu_device *vdev);
+void ivpu_hw_ip_idle_gen_disable(struct ivpu_device *vdev);
+int ivpu_hw_ip_pwr_domain_enable(struct ivpu_device *vdev);
+int ivpu_hw_ip_host_ss_axi_enable(struct ivpu_device *vdev);
+int ivpu_hw_ip_top_noc_enable(struct ivpu_device *vdev);
+u64 ivpu_hw_ip_read_perf_timer_counter(struct ivpu_device *vdev);
+void ivpu_hw_ip_snoop_disable(struct ivpu_device *vdev);
+void ivpu_hw_ip_tbu_mmu_enable(struct ivpu_device *vdev);
+int ivpu_hw_ip_soc_cpu_boot(struct ivpu_device *vdev);
+void ivpu_hw_ip_wdt_disable(struct ivpu_device *vdev);
+void ivpu_hw_ip_diagnose_failure(struct ivpu_device *vdev);
+u32 ivpu_hw_ip_ipc_rx_count_get(struct ivpu_device *vdev);
+void ivpu_hw_ip_irq_clear(struct ivpu_device *vdev);
+bool ivpu_hw_ip_irq_handler_37xx(struct ivpu_device *vdev, int irq);
+bool ivpu_hw_ip_irq_handler_40xx(struct ivpu_device *vdev, int irq);
+void ivpu_hw_ip_db_set(struct ivpu_device *vdev, u32 db_id);
+u32 ivpu_hw_ip_ipc_rx_addr_get(struct ivpu_device *vdev);
+void ivpu_hw_ip_ipc_tx_set(struct ivpu_device *vdev, u32 vpu_addr);
+void ivpu_hw_ip_irq_enable(struct ivpu_device *vdev);
+void ivpu_hw_ip_irq_disable(struct ivpu_device *vdev);
+void ivpu_hw_ip_diagnose_failure(struct ivpu_device *vdev);
+void ivpu_hw_ip_fabric_req_override_enable_50xx(struct ivpu_device *vdev);
+void ivpu_hw_ip_fabric_req_override_disable_50xx(struct ivpu_device *vdev);
+
+#endif /* __IVPU_HW_IP_H__ */
diff --git a/drivers/accel/ivpu/ivpu_ipc.c b/drivers/accel/ivpu/ivpu_ipc.c
index 56ff067f63e2..74ab964d229b 100644
--- a/drivers/accel/ivpu/ivpu_ipc.c
+++ b/drivers/accel/ivpu/ivpu_ipc.c
@@ -129,7 +129,7 @@ static void ivpu_ipc_tx_release(struct ivpu_device *vdev, u32 vpu_addr)
static void ivpu_ipc_tx(struct ivpu_device *vdev, u32 vpu_addr)
{
- ivpu_hw_reg_ipc_tx_set(vdev, vpu_addr);
+ ivpu_hw_ipc_tx_set(vdev, vpu_addr);
}
static void
@@ -378,7 +378,7 @@ ivpu_ipc_match_consumer(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons
return false;
}
-void ivpu_ipc_irq_handler(struct ivpu_device *vdev, bool *wake_thread)
+void ivpu_ipc_irq_handler(struct ivpu_device *vdev)
{
struct ivpu_ipc_info *ipc = vdev->ipc;
struct ivpu_ipc_consumer *cons;
@@ -392,8 +392,8 @@ void ivpu_ipc_irq_handler(struct ivpu_device *vdev, bool *wake_thread)
* Driver needs to purge all messages from IPC FIFO to clear IPC interrupt.
* Without purge IPC FIFO to 0 next IPC interrupts won't be generated.
*/
- while (ivpu_hw_reg_ipc_rx_count_get(vdev)) {
- vpu_addr = ivpu_hw_reg_ipc_rx_addr_get(vdev);
+ while (ivpu_hw_ipc_rx_count_get(vdev)) {
+ vpu_addr = ivpu_hw_ipc_rx_addr_get(vdev);
if (vpu_addr == REG_IO_ERROR) {
ivpu_err_ratelimited(vdev, "Failed to read IPC rx addr register\n");
return;
@@ -442,11 +442,12 @@ void ivpu_ipc_irq_handler(struct ivpu_device *vdev, bool *wake_thread)
}
}
- if (wake_thread)
- *wake_thread = !list_empty(&ipc->cb_msg_list);
+ if (!list_empty(&ipc->cb_msg_list))
+ if (!kfifo_put(&vdev->hw->irq.fifo, IVPU_HW_IRQ_SRC_IPC))
+ ivpu_err_ratelimited(vdev, "IRQ FIFO full\n");
}
-irqreturn_t ivpu_ipc_irq_thread_handler(struct ivpu_device *vdev)
+void ivpu_ipc_irq_thread_handler(struct ivpu_device *vdev)
{
struct ivpu_ipc_info *ipc = vdev->ipc;
struct ivpu_ipc_rx_msg *rx_msg, *r;
@@ -462,8 +463,6 @@ irqreturn_t ivpu_ipc_irq_thread_handler(struct ivpu_device *vdev)
rx_msg->callback(vdev, rx_msg->ipc_hdr, rx_msg->jsm_msg);
ivpu_ipc_rx_msg_del(vdev, rx_msg);
}
-
- return IRQ_HANDLED;
}
int ivpu_ipc_init(struct ivpu_device *vdev)
diff --git a/drivers/accel/ivpu/ivpu_ipc.h b/drivers/accel/ivpu/ivpu_ipc.h
index 40ca3cc4e61f..75f532428d68 100644
--- a/drivers/accel/ivpu/ivpu_ipc.h
+++ b/drivers/accel/ivpu/ivpu_ipc.h
@@ -89,8 +89,8 @@ void ivpu_ipc_enable(struct ivpu_device *vdev);
void ivpu_ipc_disable(struct ivpu_device *vdev);
void ivpu_ipc_reset(struct ivpu_device *vdev);
-void ivpu_ipc_irq_handler(struct ivpu_device *vdev, bool *wake_thread);
-irqreturn_t ivpu_ipc_irq_thread_handler(struct ivpu_device *vdev);
+void ivpu_ipc_irq_handler(struct ivpu_device *vdev);
+void ivpu_ipc_irq_thread_handler(struct ivpu_device *vdev);
void ivpu_ipc_consumer_add(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons,
u32 channel, ivpu_ipc_rx_callback_t callback);
diff --git a/drivers/accel/ivpu/ivpu_job.c b/drivers/accel/ivpu/ivpu_job.c
index a49bc9105ed0..e4e24813fe03 100644
--- a/drivers/accel/ivpu/ivpu_job.c
+++ b/drivers/accel/ivpu/ivpu_job.c
@@ -12,11 +12,13 @@
#include <uapi/drm/ivpu_accel.h>
#include "ivpu_drv.h"
+#include "ivpu_fw.h"
#include "ivpu_hw.h"
#include "ivpu_ipc.h"
#include "ivpu_job.h"
#include "ivpu_jsm_msg.h"
#include "ivpu_pm.h"
+#include "vpu_boot_api.h"
#define CMD_BUF_IDX 0
#define JOB_ID_JOB_MASK GENMASK(7, 0)
@@ -25,14 +27,60 @@
static void ivpu_cmdq_ring_db(struct ivpu_device *vdev, struct ivpu_cmdq *cmdq)
{
- ivpu_hw_reg_db_set(vdev, cmdq->db_id);
+ ivpu_hw_db_set(vdev, cmdq->db_id);
}
-static struct ivpu_cmdq *ivpu_cmdq_alloc(struct ivpu_file_priv *file_priv, u16 engine)
+static int ivpu_preemption_buffers_create(struct ivpu_device *vdev,
+ struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq)
+{
+ u64 primary_size = ALIGN(vdev->fw->primary_preempt_buf_size, PAGE_SIZE);
+ u64 secondary_size = ALIGN(vdev->fw->secondary_preempt_buf_size, PAGE_SIZE);
+ struct ivpu_addr_range range;
+
+ if (vdev->hw->sched_mode != VPU_SCHEDULING_MODE_HW)
+ return 0;
+
+ range.start = vdev->hw->ranges.user.end - (primary_size * IVPU_NUM_CMDQS_PER_CTX);
+ range.end = vdev->hw->ranges.user.end;
+ cmdq->primary_preempt_buf = ivpu_bo_create(vdev, &file_priv->ctx, &range, primary_size,
+ DRM_IVPU_BO_WC);
+ if (!cmdq->primary_preempt_buf) {
+ ivpu_err(vdev, "Failed to create primary preemption buffer\n");
+ return -ENOMEM;
+ }
+
+ range.start = vdev->hw->ranges.shave.end - (secondary_size * IVPU_NUM_CMDQS_PER_CTX);
+ range.end = vdev->hw->ranges.shave.end;
+ cmdq->secondary_preempt_buf = ivpu_bo_create(vdev, &file_priv->ctx, &range, secondary_size,
+ DRM_IVPU_BO_WC);
+ if (!cmdq->secondary_preempt_buf) {
+ ivpu_err(vdev, "Failed to create secondary preemption buffer\n");
+ goto err_free_primary;
+ }
+
+ return 0;
+
+err_free_primary:
+ ivpu_bo_free(cmdq->primary_preempt_buf);
+ return -ENOMEM;
+}
+
+static void ivpu_preemption_buffers_free(struct ivpu_device *vdev,
+ struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq)
+{
+ if (vdev->hw->sched_mode != VPU_SCHEDULING_MODE_HW)
+ return;
+
+ drm_WARN_ON(&vdev->drm, !cmdq->primary_preempt_buf);
+ drm_WARN_ON(&vdev->drm, !cmdq->secondary_preempt_buf);
+ ivpu_bo_free(cmdq->primary_preempt_buf);
+ ivpu_bo_free(cmdq->secondary_preempt_buf);
+}
+
+static struct ivpu_cmdq *ivpu_cmdq_alloc(struct ivpu_file_priv *file_priv)
{
struct xa_limit db_xa_limit = {.max = IVPU_MAX_DB, .min = IVPU_MIN_DB};
struct ivpu_device *vdev = file_priv->vdev;
- struct vpu_job_queue_header *jobq_header;
struct ivpu_cmdq *cmdq;
int ret;
@@ -50,18 +98,14 @@ static struct ivpu_cmdq *ivpu_cmdq_alloc(struct ivpu_file_priv *file_priv, u16 e
if (!cmdq->mem)
goto err_erase_xa;
- cmdq->entry_count = (u32)((ivpu_bo_size(cmdq->mem) - sizeof(struct vpu_job_queue_header)) /
- sizeof(struct vpu_job_queue_entry));
-
- cmdq->jobq = (struct vpu_job_queue *)ivpu_bo_vaddr(cmdq->mem);
- jobq_header = &cmdq->jobq->header;
- jobq_header->engine_idx = engine;
- jobq_header->head = 0;
- jobq_header->tail = 0;
- wmb(); /* Flush WC buffer for jobq->header */
+ ret = ivpu_preemption_buffers_create(vdev, file_priv, cmdq);
+ if (ret)
+ goto err_free_cmdq_mem;
return cmdq;
+err_free_cmdq_mem:
+ ivpu_bo_free(cmdq->mem);
err_erase_xa:
xa_erase(&vdev->db_xa, cmdq->db_id);
err_free_cmdq:
@@ -74,92 +118,183 @@ static void ivpu_cmdq_free(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *c
if (!cmdq)
return;
+ ivpu_preemption_buffers_free(file_priv->vdev, file_priv, cmdq);
ivpu_bo_free(cmdq->mem);
xa_erase(&file_priv->vdev->db_xa, cmdq->db_id);
kfree(cmdq);
}
-static struct ivpu_cmdq *ivpu_cmdq_acquire(struct ivpu_file_priv *file_priv, u16 engine)
+static int ivpu_hws_cmdq_init(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq, u16 engine,
+ u8 priority)
+{
+ struct ivpu_device *vdev = file_priv->vdev;
+ int ret;
+
+ ret = ivpu_jsm_hws_create_cmdq(vdev, file_priv->ctx.id, file_priv->ctx.id, cmdq->db_id,
+ task_pid_nr(current), engine,
+ cmdq->mem->vpu_addr, ivpu_bo_size(cmdq->mem));
+ if (ret)
+ return ret;
+
+ ret = ivpu_jsm_hws_set_context_sched_properties(vdev, file_priv->ctx.id, cmdq->db_id,
+ priority);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int ivpu_register_db(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq)
+{
+ struct ivpu_device *vdev = file_priv->vdev;
+ int ret;
+
+ if (vdev->hw->sched_mode == VPU_SCHEDULING_MODE_HW)
+ ret = ivpu_jsm_hws_register_db(vdev, file_priv->ctx.id, cmdq->db_id, cmdq->db_id,
+ cmdq->mem->vpu_addr, ivpu_bo_size(cmdq->mem));
+ else
+ ret = ivpu_jsm_register_db(vdev, file_priv->ctx.id, cmdq->db_id,
+ cmdq->mem->vpu_addr, ivpu_bo_size(cmdq->mem));
+
+ if (!ret)
+ ivpu_dbg(vdev, JOB, "DB %d registered to ctx %d\n", cmdq->db_id, file_priv->ctx.id);
+
+ return ret;
+}
+
+static int
+ivpu_cmdq_init(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq, u16 engine, u8 priority)
+{
+ struct ivpu_device *vdev = file_priv->vdev;
+ struct vpu_job_queue_header *jobq_header;
+ int ret;
+
+ lockdep_assert_held(&file_priv->lock);
+
+ if (cmdq->db_registered)
+ return 0;
+
+ cmdq->entry_count = (u32)((ivpu_bo_size(cmdq->mem) - sizeof(struct vpu_job_queue_header)) /
+ sizeof(struct vpu_job_queue_entry));
+
+ cmdq->jobq = (struct vpu_job_queue *)ivpu_bo_vaddr(cmdq->mem);
+ jobq_header = &cmdq->jobq->header;
+ jobq_header->engine_idx = engine;
+ jobq_header->head = 0;
+ jobq_header->tail = 0;
+ wmb(); /* Flush WC buffer for jobq->header */
+
+ if (vdev->hw->sched_mode == VPU_SCHEDULING_MODE_HW) {
+ ret = ivpu_hws_cmdq_init(file_priv, cmdq, engine, priority);
+ if (ret)
+ return ret;
+ }
+
+ ret = ivpu_register_db(file_priv, cmdq);
+ if (ret)
+ return ret;
+
+ cmdq->db_registered = true;
+
+ return 0;
+}
+
+static int ivpu_cmdq_fini(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq)
{
struct ivpu_device *vdev = file_priv->vdev;
- struct ivpu_cmdq *cmdq = file_priv->cmdq[engine];
+ int ret;
+
+ lockdep_assert_held(&file_priv->lock);
+
+ if (!cmdq->db_registered)
+ return 0;
+
+ cmdq->db_registered = false;
+
+ if (vdev->hw->sched_mode == VPU_SCHEDULING_MODE_HW) {
+ ret = ivpu_jsm_hws_destroy_cmdq(vdev, file_priv->ctx.id, cmdq->db_id);
+ if (!ret)
+ ivpu_dbg(vdev, JOB, "Command queue %d destroyed\n", cmdq->db_id);
+ }
+
+ ret = ivpu_jsm_unregister_db(vdev, cmdq->db_id);
+ if (!ret)
+ ivpu_dbg(vdev, JOB, "DB %d unregistered\n", cmdq->db_id);
+
+ return 0;
+}
+
+static struct ivpu_cmdq *ivpu_cmdq_acquire(struct ivpu_file_priv *file_priv, u16 engine,
+ u8 priority)
+{
+ int cmdq_idx = IVPU_CMDQ_INDEX(engine, priority);
+ struct ivpu_cmdq *cmdq = file_priv->cmdq[cmdq_idx];
int ret;
lockdep_assert_held(&file_priv->lock);
if (!cmdq) {
- cmdq = ivpu_cmdq_alloc(file_priv, engine);
+ cmdq = ivpu_cmdq_alloc(file_priv);
if (!cmdq)
return NULL;
- file_priv->cmdq[engine] = cmdq;
+ file_priv->cmdq[cmdq_idx] = cmdq;
}
- if (cmdq->db_registered)
- return cmdq;
-
- ret = ivpu_jsm_register_db(vdev, file_priv->ctx.id, cmdq->db_id,
- cmdq->mem->vpu_addr, ivpu_bo_size(cmdq->mem));
+ ret = ivpu_cmdq_init(file_priv, cmdq, engine, priority);
if (ret)
return NULL;
- cmdq->db_registered = true;
-
return cmdq;
}
-static void ivpu_cmdq_release_locked(struct ivpu_file_priv *file_priv, u16 engine)
+static void ivpu_cmdq_release_locked(struct ivpu_file_priv *file_priv, u16 engine, u8 priority)
{
- struct ivpu_cmdq *cmdq = file_priv->cmdq[engine];
+ int cmdq_idx = IVPU_CMDQ_INDEX(engine, priority);
+ struct ivpu_cmdq *cmdq = file_priv->cmdq[cmdq_idx];
lockdep_assert_held(&file_priv->lock);
if (cmdq) {
- file_priv->cmdq[engine] = NULL;
- if (cmdq->db_registered)
- ivpu_jsm_unregister_db(file_priv->vdev, cmdq->db_id);
-
+ file_priv->cmdq[cmdq_idx] = NULL;
+ ivpu_cmdq_fini(file_priv, cmdq);
ivpu_cmdq_free(file_priv, cmdq);
}
}
void ivpu_cmdq_release_all_locked(struct ivpu_file_priv *file_priv)
{
- int i;
+ u16 engine;
+ u8 priority;
lockdep_assert_held(&file_priv->lock);
- for (i = 0; i < IVPU_NUM_ENGINES; i++)
- ivpu_cmdq_release_locked(file_priv, i);
+ for (engine = 0; engine < IVPU_NUM_ENGINES; engine++)
+ for (priority = 0; priority < IVPU_NUM_PRIORITIES; priority++)
+ ivpu_cmdq_release_locked(file_priv, engine, priority);
}
/*
- * Mark the doorbell as unregistered and reset job queue pointers.
+ * Mark the doorbell as unregistered
* This function needs to be called when the VPU hardware is restarted
* and FW loses job queue state. The next time job queue is used it
* will be registered again.
*/
-static void ivpu_cmdq_reset_locked(struct ivpu_file_priv *file_priv, u16 engine)
+static void ivpu_cmdq_reset(struct ivpu_file_priv *file_priv)
{
- struct ivpu_cmdq *cmdq = file_priv->cmdq[engine];
-
- lockdep_assert_held(&file_priv->lock);
-
- if (cmdq) {
- cmdq->db_registered = false;
- cmdq->jobq->header.head = 0;
- cmdq->jobq->header.tail = 0;
- wmb(); /* Flush WC buffer for jobq header */
- }
-}
-
-static void ivpu_cmdq_reset_all(struct ivpu_file_priv *file_priv)
-{
- int i;
+ u16 engine;
+ u8 priority;
mutex_lock(&file_priv->lock);
- for (i = 0; i < IVPU_NUM_ENGINES; i++)
- ivpu_cmdq_reset_locked(file_priv, i);
+ for (engine = 0; engine < IVPU_NUM_ENGINES; engine++) {
+ for (priority = 0; priority < IVPU_NUM_PRIORITIES; priority++) {
+ int cmdq_idx = IVPU_CMDQ_INDEX(engine, priority);
+ struct ivpu_cmdq *cmdq = file_priv->cmdq[cmdq_idx];
+
+ if (cmdq)
+ cmdq->db_registered = false;
+ }
+ }
mutex_unlock(&file_priv->lock);
}
@@ -172,10 +307,9 @@ void ivpu_cmdq_reset_all_contexts(struct ivpu_device *vdev)
mutex_lock(&vdev->context_list_lock);
xa_for_each(&vdev->context_xa, ctx_id, file_priv)
- ivpu_cmdq_reset_all(file_priv);
+ ivpu_cmdq_reset(file_priv);
mutex_unlock(&vdev->context_list_lock);
-
}
static int ivpu_cmdq_push_job(struct ivpu_cmdq *cmdq, struct ivpu_job *job)
@@ -199,6 +333,15 @@ static int ivpu_cmdq_push_job(struct ivpu_cmdq *cmdq, struct ivpu_job *job)
entry->flags = 0;
if (unlikely(ivpu_test_mode & IVPU_TEST_MODE_NULL_SUBMISSION))
entry->flags = VPU_JOB_FLAGS_NULL_SUBMISSION_MASK;
+
+ if (vdev->hw->sched_mode == VPU_SCHEDULING_MODE_HW &&
+ (unlikely(!(ivpu_test_mode & IVPU_TEST_MODE_PREEMPTION_DISABLE)))) {
+ entry->primary_preempt_buf_addr = cmdq->primary_preempt_buf->vpu_addr;
+ entry->primary_preempt_buf_size = ivpu_bo_size(cmdq->primary_preempt_buf);
+ entry->secondary_preempt_buf_addr = cmdq->secondary_preempt_buf->vpu_addr;
+ entry->secondary_preempt_buf_size = ivpu_bo_size(cmdq->secondary_preempt_buf);
+ }
+
wmb(); /* Ensure that tail is updated after filling entry */
header->tail = next_entry;
wmb(); /* Flush WC buffer for jobq header */
@@ -295,11 +438,28 @@ err_free_job:
return NULL;
}
+static struct ivpu_job *ivpu_job_remove_from_submitted_jobs(struct ivpu_device *vdev, u32 job_id)
+{
+ struct ivpu_job *job;
+
+ xa_lock(&vdev->submitted_jobs_xa);
+ job = __xa_erase(&vdev->submitted_jobs_xa, job_id);
+
+ if (xa_empty(&vdev->submitted_jobs_xa) && job) {
+ vdev->busy_time = ktime_add(ktime_sub(ktime_get(), vdev->busy_start_ts),
+ vdev->busy_time);
+ }
+
+ xa_unlock(&vdev->submitted_jobs_xa);
+
+ return job;
+}
+
static int ivpu_job_signal_and_destroy(struct ivpu_device *vdev, u32 job_id, u32 job_status)
{
struct ivpu_job *job;
- job = xa_erase(&vdev->submitted_jobs_xa, job_id);
+ job = ivpu_job_remove_from_submitted_jobs(vdev, job_id);
if (!job)
return -ENOENT;
@@ -328,12 +488,13 @@ void ivpu_jobs_abort_all(struct ivpu_device *vdev)
ivpu_job_signal_and_destroy(vdev, id, DRM_IVPU_JOB_STATUS_ABORTED);
}
-static int ivpu_job_submit(struct ivpu_job *job)
+static int ivpu_job_submit(struct ivpu_job *job, u8 priority)
{
struct ivpu_file_priv *file_priv = job->file_priv;
struct ivpu_device *vdev = job->vdev;
struct xa_limit job_id_range;
struct ivpu_cmdq *cmdq;
+ bool is_first_job;
int ret;
ret = ivpu_rpm_get(vdev);
@@ -342,10 +503,10 @@ static int ivpu_job_submit(struct ivpu_job *job)
mutex_lock(&file_priv->lock);
- cmdq = ivpu_cmdq_acquire(job->file_priv, job->engine_idx);
+ cmdq = ivpu_cmdq_acquire(job->file_priv, job->engine_idx, priority);
if (!cmdq) {
- ivpu_warn_ratelimited(vdev, "Failed get job queue, ctx %d engine %d\n",
- file_priv->ctx.id, job->engine_idx);
+ ivpu_warn_ratelimited(vdev, "Failed to get job queue, ctx %d engine %d prio %d\n",
+ file_priv->ctx.id, job->engine_idx, priority);
ret = -EINVAL;
goto err_unlock_file_priv;
}
@@ -354,6 +515,7 @@ static int ivpu_job_submit(struct ivpu_job *job)
job_id_range.max = job_id_range.min | JOB_ID_JOB_MASK;
xa_lock(&vdev->submitted_jobs_xa);
+ is_first_job = xa_empty(&vdev->submitted_jobs_xa);
ret = __xa_alloc(&vdev->submitted_jobs_xa, &job->job_id, job, job_id_range, GFP_KERNEL);
if (ret) {
ivpu_dbg(vdev, JOB, "Too many active jobs in ctx %d\n",
@@ -373,10 +535,12 @@ static int ivpu_job_submit(struct ivpu_job *job)
wmb(); /* Flush WC buffer for jobq header */
} else {
ivpu_cmdq_ring_db(vdev, cmdq);
+ if (is_first_job)
+ vdev->busy_start_ts = ktime_get();
}
- ivpu_dbg(vdev, JOB, "Job submitted: id %3u ctx %2d engine %d addr 0x%llx next %d\n",
- job->job_id, file_priv->ctx.id, job->engine_idx,
+ ivpu_dbg(vdev, JOB, "Job submitted: id %3u ctx %2d engine %d prio %d addr 0x%llx next %d\n",
+ job->job_id, file_priv->ctx.id, job->engine_idx, priority,
job->cmd_buf_vpu_addr, cmdq->jobq->header.tail);
xa_unlock(&vdev->submitted_jobs_xa);
@@ -464,6 +628,14 @@ unlock_reservations:
return ret;
}
+static inline u8 ivpu_job_to_hws_priority(struct ivpu_file_priv *file_priv, u8 priority)
+{
+ if (priority == DRM_IVPU_JOB_PRIORITY_DEFAULT)
+ return DRM_IVPU_JOB_PRIORITY_NORMAL;
+
+ return priority - 1;
+}
+
int ivpu_submit_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
{
struct ivpu_file_priv *file_priv = file->driver_priv;
@@ -472,6 +644,7 @@ int ivpu_submit_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
struct ivpu_job *job;
u32 *buf_handles;
int idx, ret;
+ u8 priority;
if (params->engine > DRM_IVPU_ENGINE_COPY)
return -EINVAL;
@@ -525,8 +698,10 @@ int ivpu_submit_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
goto err_destroy_job;
}
+ priority = ivpu_job_to_hws_priority(file_priv, params->priority);
+
down_read(&vdev->pm->reset_lock);
- ret = ivpu_job_submit(job);
+ ret = ivpu_job_submit(job, priority);
up_read(&vdev->pm->reset_lock);
if (ret)
goto err_signal_fence;
diff --git a/drivers/accel/ivpu/ivpu_job.h b/drivers/accel/ivpu/ivpu_job.h
index ca4984071cc7..e50002b5788c 100644
--- a/drivers/accel/ivpu/ivpu_job.h
+++ b/drivers/accel/ivpu/ivpu_job.h
@@ -24,6 +24,8 @@ struct ivpu_file_priv;
*/
struct ivpu_cmdq {
struct vpu_job_queue *jobq;
+ struct ivpu_bo *primary_preempt_buf;
+ struct ivpu_bo *secondary_preempt_buf;
struct ivpu_bo *mem;
u32 entry_count;
u32 db_id;
diff --git a/drivers/accel/ivpu/ivpu_jsm_msg.c b/drivers/accel/ivpu/ivpu_jsm_msg.c
index 8cea0dd731b9..e8dd73d947e4 100644
--- a/drivers/accel/ivpu/ivpu_jsm_msg.c
+++ b/drivers/accel/ivpu/ivpu_jsm_msg.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (C) 2020-2023 Intel Corporation
+ * Copyright (C) 2020-2024 Intel Corporation
*/
#include "ivpu_drv.h"
@@ -281,3 +281,260 @@ int ivpu_jsm_pwr_d0i3_enter(struct ivpu_device *vdev)
return ivpu_hw_wait_for_idle(vdev);
}
+
+int ivpu_jsm_hws_create_cmdq(struct ivpu_device *vdev, u32 ctx_id, u32 cmdq_group, u32 cmdq_id,
+ u32 pid, u32 engine, u64 cmdq_base, u32 cmdq_size)
+{
+ struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_CREATE_CMD_QUEUE };
+ struct vpu_jsm_msg resp;
+ int ret;
+
+ req.payload.hws_create_cmdq.host_ssid = ctx_id;
+ req.payload.hws_create_cmdq.process_id = pid;
+ req.payload.hws_create_cmdq.engine_idx = engine;
+ req.payload.hws_create_cmdq.cmdq_group = cmdq_group;
+ req.payload.hws_create_cmdq.cmdq_id = cmdq_id;
+ req.payload.hws_create_cmdq.cmdq_base = cmdq_base;
+ req.payload.hws_create_cmdq.cmdq_size = cmdq_size;
+
+ ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_CREATE_CMD_QUEUE_RSP, &resp,
+ VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm);
+ if (ret)
+ ivpu_warn_ratelimited(vdev, "Failed to create command queue: %d\n", ret);
+
+ return ret;
+}
+
+int ivpu_jsm_hws_destroy_cmdq(struct ivpu_device *vdev, u32 ctx_id, u32 cmdq_id)
+{
+ struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_DESTROY_CMD_QUEUE };
+ struct vpu_jsm_msg resp;
+ int ret;
+
+ req.payload.hws_destroy_cmdq.host_ssid = ctx_id;
+ req.payload.hws_destroy_cmdq.cmdq_id = cmdq_id;
+
+ ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_DESTROY_CMD_QUEUE_RSP, &resp,
+ VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm);
+ if (ret)
+ ivpu_warn_ratelimited(vdev, "Failed to destroy command queue: %d\n", ret);
+
+ return ret;
+}
+
+int ivpu_jsm_hws_register_db(struct ivpu_device *vdev, u32 ctx_id, u32 cmdq_id, u32 db_id,
+ u64 cmdq_base, u32 cmdq_size)
+{
+ struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_HWS_REGISTER_DB };
+ struct vpu_jsm_msg resp;
+ int ret = 0;
+
+ req.payload.hws_register_db.db_id = db_id;
+ req.payload.hws_register_db.host_ssid = ctx_id;
+ req.payload.hws_register_db.cmdq_id = cmdq_id;
+ req.payload.hws_register_db.cmdq_base = cmdq_base;
+ req.payload.hws_register_db.cmdq_size = cmdq_size;
+
+ ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_REGISTER_DB_DONE, &resp,
+ VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm);
+ if (ret)
+ ivpu_err_ratelimited(vdev, "Failed to register doorbell %u: %d\n", db_id, ret);
+
+ return ret;
+}
+
+int ivpu_jsm_hws_resume_engine(struct ivpu_device *vdev, u32 engine)
+{
+ struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_HWS_ENGINE_RESUME };
+ struct vpu_jsm_msg resp;
+ int ret;
+
+ if (engine >= VPU_ENGINE_NB)
+ return -EINVAL;
+
+ req.payload.hws_resume_engine.engine_idx = engine;
+
+ ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_HWS_RESUME_ENGINE_DONE, &resp,
+ VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm);
+ if (ret)
+ ivpu_err_ratelimited(vdev, "Failed to resume engine %d: %d\n", engine, ret);
+
+ return ret;
+}
+
+int ivpu_jsm_hws_set_context_sched_properties(struct ivpu_device *vdev, u32 ctx_id, u32 cmdq_id,
+ u32 priority)
+{
+ struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_SET_CONTEXT_SCHED_PROPERTIES };
+ struct vpu_jsm_msg resp;
+ int ret;
+
+ req.payload.hws_set_context_sched_properties.host_ssid = ctx_id;
+ req.payload.hws_set_context_sched_properties.cmdq_id = cmdq_id;
+ req.payload.hws_set_context_sched_properties.priority_band = priority;
+ req.payload.hws_set_context_sched_properties.realtime_priority_level = 0;
+ req.payload.hws_set_context_sched_properties.in_process_priority = 0;
+ req.payload.hws_set_context_sched_properties.context_quantum = 20000;
+ req.payload.hws_set_context_sched_properties.grace_period_same_priority = 10000;
+ req.payload.hws_set_context_sched_properties.grace_period_lower_priority = 0;
+
+ ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_SET_CONTEXT_SCHED_PROPERTIES_RSP, &resp,
+ VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm);
+ if (ret)
+ ivpu_warn_ratelimited(vdev, "Failed to set context sched properties: %d\n", ret);
+
+ return ret;
+}
+
+int ivpu_jsm_hws_set_scheduling_log(struct ivpu_device *vdev, u32 engine_idx, u32 host_ssid,
+ u64 vpu_log_buffer_va)
+{
+ struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_HWS_SET_SCHEDULING_LOG };
+ struct vpu_jsm_msg resp;
+ int ret;
+
+ req.payload.hws_set_scheduling_log.engine_idx = engine_idx;
+ req.payload.hws_set_scheduling_log.host_ssid = host_ssid;
+ req.payload.hws_set_scheduling_log.vpu_log_buffer_va = vpu_log_buffer_va;
+ req.payload.hws_set_scheduling_log.notify_index = 0;
+ req.payload.hws_set_scheduling_log.enable_extra_events =
+ ivpu_test_mode & IVPU_TEST_MODE_HWS_EXTRA_EVENTS;
+
+ ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_HWS_SET_SCHEDULING_LOG_RSP, &resp,
+ VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm);
+ if (ret)
+ ivpu_warn_ratelimited(vdev, "Failed to set scheduling log: %d\n", ret);
+
+ return ret;
+}
+
+int ivpu_jsm_hws_setup_priority_bands(struct ivpu_device *vdev)
+{
+ struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_SET_PRIORITY_BAND_SETUP };
+ struct vpu_jsm_msg resp;
+ int ret;
+
+ /* Idle */
+ req.payload.hws_priority_band_setup.grace_period[0] = 0;
+ req.payload.hws_priority_band_setup.process_grace_period[0] = 50000;
+ req.payload.hws_priority_band_setup.process_quantum[0] = 160000;
+ /* Normal */
+ req.payload.hws_priority_band_setup.grace_period[1] = 50000;
+ req.payload.hws_priority_band_setup.process_grace_period[1] = 50000;
+ req.payload.hws_priority_band_setup.process_quantum[1] = 300000;
+ /* Focus */
+ req.payload.hws_priority_band_setup.grace_period[2] = 50000;
+ req.payload.hws_priority_band_setup.process_grace_period[2] = 50000;
+ req.payload.hws_priority_band_setup.process_quantum[2] = 200000;
+ /* Realtime */
+ req.payload.hws_priority_band_setup.grace_period[3] = 0;
+ req.payload.hws_priority_band_setup.process_grace_period[3] = 50000;
+ req.payload.hws_priority_band_setup.process_quantum[3] = 200000;
+
+ req.payload.hws_priority_band_setup.normal_band_percentage = 10;
+
+ ret = ivpu_ipc_send_receive_active(vdev, &req, VPU_JSM_MSG_SET_PRIORITY_BAND_SETUP_RSP,
+ &resp, VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm);
+ if (ret)
+ ivpu_warn_ratelimited(vdev, "Failed to set priority bands: %d\n", ret);
+
+ return ret;
+}
+
+int ivpu_jsm_metric_streamer_start(struct ivpu_device *vdev, u64 metric_group_mask,
+ u64 sampling_rate, u64 buffer_addr, u64 buffer_size)
+{
+ struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_METRIC_STREAMER_START };
+ struct vpu_jsm_msg resp;
+ int ret;
+
+ req.payload.metric_streamer_start.metric_group_mask = metric_group_mask;
+ req.payload.metric_streamer_start.sampling_rate = sampling_rate;
+ req.payload.metric_streamer_start.buffer_addr = buffer_addr;
+ req.payload.metric_streamer_start.buffer_size = buffer_size;
+
+ ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_METRIC_STREAMER_START_DONE, &resp,
+ VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm);
+ if (ret) {
+ ivpu_warn_ratelimited(vdev, "Failed to start metric streamer: ret %d\n", ret);
+ return ret;
+ }
+
+ return ret;
+}
+
+int ivpu_jsm_metric_streamer_stop(struct ivpu_device *vdev, u64 metric_group_mask)
+{
+ struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_METRIC_STREAMER_STOP };
+ struct vpu_jsm_msg resp;
+ int ret;
+
+ req.payload.metric_streamer_stop.metric_group_mask = metric_group_mask;
+
+ ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_METRIC_STREAMER_STOP_DONE, &resp,
+ VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm);
+ if (ret)
+ ivpu_warn_ratelimited(vdev, "Failed to stop metric streamer: ret %d\n", ret);
+
+ return ret;
+}
+
+int ivpu_jsm_metric_streamer_update(struct ivpu_device *vdev, u64 metric_group_mask,
+ u64 buffer_addr, u64 buffer_size, u64 *bytes_written)
+{
+ struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_METRIC_STREAMER_UPDATE };
+ struct vpu_jsm_msg resp;
+ int ret;
+
+ req.payload.metric_streamer_update.metric_group_mask = metric_group_mask;
+ req.payload.metric_streamer_update.buffer_addr = buffer_addr;
+ req.payload.metric_streamer_update.buffer_size = buffer_size;
+
+ ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_METRIC_STREAMER_UPDATE_DONE, &resp,
+ VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm);
+ if (ret) {
+ ivpu_warn_ratelimited(vdev, "Failed to update metric streamer: ret %d\n", ret);
+ return ret;
+ }
+
+ if (buffer_size && resp.payload.metric_streamer_done.bytes_written > buffer_size) {
+ ivpu_warn_ratelimited(vdev, "MS buffer overflow: bytes_written %#llx > buffer_size %#llx\n",
+ resp.payload.metric_streamer_done.bytes_written, buffer_size);
+ return -EOVERFLOW;
+ }
+
+ *bytes_written = resp.payload.metric_streamer_done.bytes_written;
+
+ return ret;
+}
+
+int ivpu_jsm_metric_streamer_info(struct ivpu_device *vdev, u64 metric_group_mask, u64 buffer_addr,
+ u64 buffer_size, u32 *sample_size, u64 *info_size)
+{
+ struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_METRIC_STREAMER_INFO };
+ struct vpu_jsm_msg resp;
+ int ret;
+
+ req.payload.metric_streamer_start.metric_group_mask = metric_group_mask;
+ req.payload.metric_streamer_start.buffer_addr = buffer_addr;
+ req.payload.metric_streamer_start.buffer_size = buffer_size;
+
+ ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_METRIC_STREAMER_INFO_DONE, &resp,
+ VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm);
+ if (ret) {
+ ivpu_warn_ratelimited(vdev, "Failed to get metric streamer info: ret %d\n", ret);
+ return ret;
+ }
+
+ if (!resp.payload.metric_streamer_done.sample_size) {
+ ivpu_warn_ratelimited(vdev, "Invalid sample size\n");
+ return -EBADMSG;
+ }
+
+ if (sample_size)
+ *sample_size = resp.payload.metric_streamer_done.sample_size;
+ if (info_size)
+ *info_size = resp.payload.metric_streamer_done.bytes_written;
+
+ return ret;
+}
diff --git a/drivers/accel/ivpu/ivpu_jsm_msg.h b/drivers/accel/ivpu/ivpu_jsm_msg.h
index ae75e5dbcc41..060363409fb3 100644
--- a/drivers/accel/ivpu/ivpu_jsm_msg.h
+++ b/drivers/accel/ivpu/ivpu_jsm_msg.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * Copyright (C) 2020-2023 Intel Corporation
+ * Copyright (C) 2020-2024 Intel Corporation
*/
#ifndef __IVPU_JSM_MSG_H__
@@ -23,4 +23,22 @@ int ivpu_jsm_trace_set_config(struct ivpu_device *vdev, u32 trace_level, u32 tra
u64 trace_hw_component_mask);
int ivpu_jsm_context_release(struct ivpu_device *vdev, u32 host_ssid);
int ivpu_jsm_pwr_d0i3_enter(struct ivpu_device *vdev);
+int ivpu_jsm_hws_create_cmdq(struct ivpu_device *vdev, u32 ctx_id, u32 cmdq_group, u32 cmdq_id,
+ u32 pid, u32 engine, u64 cmdq_base, u32 cmdq_size);
+int ivpu_jsm_hws_destroy_cmdq(struct ivpu_device *vdev, u32 ctx_id, u32 cmdq_id);
+int ivpu_jsm_hws_register_db(struct ivpu_device *vdev, u32 ctx_id, u32 cmdq_id, u32 db_id,
+ u64 cmdq_base, u32 cmdq_size);
+int ivpu_jsm_hws_resume_engine(struct ivpu_device *vdev, u32 engine);
+int ivpu_jsm_hws_set_context_sched_properties(struct ivpu_device *vdev, u32 ctx_id, u32 cmdq_id,
+ u32 priority);
+int ivpu_jsm_hws_set_scheduling_log(struct ivpu_device *vdev, u32 engine_idx, u32 host_ssid,
+ u64 vpu_log_buffer_va);
+int ivpu_jsm_hws_setup_priority_bands(struct ivpu_device *vdev);
+int ivpu_jsm_metric_streamer_start(struct ivpu_device *vdev, u64 metric_group_mask,
+ u64 sampling_rate, u64 buffer_addr, u64 buffer_size);
+int ivpu_jsm_metric_streamer_stop(struct ivpu_device *vdev, u64 metric_group_mask);
+int ivpu_jsm_metric_streamer_update(struct ivpu_device *vdev, u64 metric_group_mask,
+ u64 buffer_addr, u64 buffer_size, u64 *bytes_written);
+int ivpu_jsm_metric_streamer_info(struct ivpu_device *vdev, u64 metric_group_mask, u64 buffer_addr,
+ u64 buffer_size, u32 *sample_size, u64 *info_size);
#endif
diff --git a/drivers/accel/ivpu/ivpu_mmu.c b/drivers/accel/ivpu/ivpu_mmu.c
index 2e46b322c450..8682e6145520 100644
--- a/drivers/accel/ivpu/ivpu_mmu.c
+++ b/drivers/accel/ivpu/ivpu_mmu.c
@@ -519,7 +519,8 @@ static int ivpu_mmu_cmdq_sync(struct ivpu_device *vdev)
if (ret)
return ret;
- clflush_cache_range(q->base, IVPU_MMU_CMDQ_SIZE);
+ if (!ivpu_is_force_snoop_enabled(vdev))
+ clflush_cache_range(q->base, IVPU_MMU_CMDQ_SIZE);
REGV_WR32(IVPU_MMU_REG_CMDQ_PROD, q->prod);
ret = ivpu_mmu_cmdq_wait_for_cons(vdev);
@@ -567,7 +568,8 @@ static int ivpu_mmu_reset(struct ivpu_device *vdev)
int ret;
memset(mmu->cmdq.base, 0, IVPU_MMU_CMDQ_SIZE);
- clflush_cache_range(mmu->cmdq.base, IVPU_MMU_CMDQ_SIZE);
+ if (!ivpu_is_force_snoop_enabled(vdev))
+ clflush_cache_range(mmu->cmdq.base, IVPU_MMU_CMDQ_SIZE);
mmu->cmdq.prod = 0;
mmu->cmdq.cons = 0;
@@ -661,7 +663,8 @@ static void ivpu_mmu_strtab_link_cd(struct ivpu_device *vdev, u32 sid)
WRITE_ONCE(entry[1], str[1]);
WRITE_ONCE(entry[0], str[0]);
- clflush_cache_range(entry, IVPU_MMU_STRTAB_ENT_SIZE);
+ if (!ivpu_is_force_snoop_enabled(vdev))
+ clflush_cache_range(entry, IVPU_MMU_STRTAB_ENT_SIZE);
ivpu_dbg(vdev, MMU, "STRTAB write entry (SSID=%u): 0x%llx, 0x%llx\n", sid, str[0], str[1]);
}
@@ -735,7 +738,8 @@ static int ivpu_mmu_cd_add(struct ivpu_device *vdev, u32 ssid, u64 cd_dma)
WRITE_ONCE(entry[3], cd[3]);
WRITE_ONCE(entry[0], cd[0]);
- clflush_cache_range(entry, IVPU_MMU_CDTAB_ENT_SIZE);
+ if (!ivpu_is_force_snoop_enabled(vdev))
+ clflush_cache_range(entry, IVPU_MMU_CDTAB_ENT_SIZE);
ivpu_dbg(vdev, MMU, "CDTAB %s entry (SSID=%u, dma=%pad): 0x%llx, 0x%llx, 0x%llx, 0x%llx\n",
cd_dma ? "write" : "clear", ssid, &cd_dma, cd[0], cd[1], cd[2], cd[3]);
diff --git a/drivers/accel/ivpu/ivpu_ms.c b/drivers/accel/ivpu/ivpu_ms.c
new file mode 100644
index 000000000000..2f9d37f5c208
--- /dev/null
+++ b/drivers/accel/ivpu/ivpu_ms.c
@@ -0,0 +1,309 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Copyright (C) 2020-2024 Intel Corporation
+ */
+
+#include <drm/drm_file.h>
+
+#include "ivpu_drv.h"
+#include "ivpu_gem.h"
+#include "ivpu_jsm_msg.h"
+#include "ivpu_ms.h"
+#include "ivpu_pm.h"
+
+#define MS_INFO_BUFFER_SIZE SZ_16K
+#define MS_NUM_BUFFERS 2
+#define MS_READ_PERIOD_MULTIPLIER 2
+#define MS_MIN_SAMPLE_PERIOD_NS 1000000
+
+static struct ivpu_ms_instance *
+get_instance_by_mask(struct ivpu_file_priv *file_priv, u64 metric_mask)
+{
+ struct ivpu_ms_instance *ms;
+
+ lockdep_assert_held(&file_priv->ms_lock);
+
+ list_for_each_entry(ms, &file_priv->ms_instance_list, ms_instance_node)
+ if (ms->mask == metric_mask)
+ return ms;
+
+ return NULL;
+}
+
+int ivpu_ms_start_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
+{
+ struct ivpu_file_priv *file_priv = file->driver_priv;
+ struct drm_ivpu_metric_streamer_start *args = data;
+ struct ivpu_device *vdev = file_priv->vdev;
+ struct ivpu_ms_instance *ms;
+ u64 single_buff_size;
+ u32 sample_size;
+ int ret;
+
+ if (!args->metric_group_mask || !args->read_period_samples ||
+ args->sampling_period_ns < MS_MIN_SAMPLE_PERIOD_NS)
+ return -EINVAL;
+
+ mutex_lock(&file_priv->ms_lock);
+
+ if (get_instance_by_mask(file_priv, args->metric_group_mask)) {
+ ivpu_err(vdev, "Instance already exists (mask %#llx)\n", args->metric_group_mask);
+ ret = -EALREADY;
+ goto unlock;
+ }
+
+ ms = kzalloc(sizeof(*ms), GFP_KERNEL);
+ if (!ms) {
+ ret = -ENOMEM;
+ goto unlock;
+ }
+
+ ms->mask = args->metric_group_mask;
+
+ ret = ivpu_jsm_metric_streamer_info(vdev, ms->mask, 0, 0, &sample_size, NULL);
+ if (ret)
+ goto err_free_ms;
+
+ single_buff_size = sample_size *
+ ((u64)args->read_period_samples * MS_READ_PERIOD_MULTIPLIER);
+ ms->bo = ivpu_bo_create_global(vdev, PAGE_ALIGN(single_buff_size * MS_NUM_BUFFERS),
+ DRM_IVPU_BO_CACHED | DRM_IVPU_BO_MAPPABLE);
+ if (!ms->bo) {
+ ivpu_err(vdev, "Failed to allocate MS buffer (size %llu)\n", single_buff_size);
+ ret = -ENOMEM;
+ goto err_free_ms;
+ }
+
+ ms->buff_size = ivpu_bo_size(ms->bo) / MS_NUM_BUFFERS;
+ ms->active_buff_vpu_addr = ms->bo->vpu_addr;
+ ms->inactive_buff_vpu_addr = ms->bo->vpu_addr + ms->buff_size;
+ ms->active_buff_ptr = ivpu_bo_vaddr(ms->bo);
+ ms->inactive_buff_ptr = ivpu_bo_vaddr(ms->bo) + ms->buff_size;
+
+ ret = ivpu_jsm_metric_streamer_start(vdev, ms->mask, args->sampling_period_ns,
+ ms->active_buff_vpu_addr, ms->buff_size);
+ if (ret)
+ goto err_free_bo;
+
+ args->sample_size = sample_size;
+ args->max_data_size = ivpu_bo_size(ms->bo);
+ list_add_tail(&ms->ms_instance_node, &file_priv->ms_instance_list);
+ goto unlock;
+
+err_free_bo:
+ ivpu_bo_free(ms->bo);
+err_free_ms:
+ kfree(ms);
+unlock:
+ mutex_unlock(&file_priv->ms_lock);
+ return ret;
+}
+
+static int
+copy_leftover_bytes(struct ivpu_ms_instance *ms,
+ void __user *user_ptr, u64 user_size, u64 *user_bytes_copied)
+{
+ u64 copy_bytes;
+
+ if (ms->leftover_bytes) {
+ copy_bytes = min(user_size - *user_bytes_copied, ms->leftover_bytes);
+ if (copy_to_user(user_ptr + *user_bytes_copied, ms->leftover_addr, copy_bytes))
+ return -EFAULT;
+
+ ms->leftover_bytes -= copy_bytes;
+ ms->leftover_addr += copy_bytes;
+ *user_bytes_copied += copy_bytes;
+ }
+
+ return 0;
+}
+
+static int
+copy_samples_to_user(struct ivpu_device *vdev, struct ivpu_ms_instance *ms,
+ void __user *user_ptr, u64 user_size, u64 *user_bytes_copied)
+{
+ u64 bytes_written;
+ int ret;
+
+ *user_bytes_copied = 0;
+
+ ret = copy_leftover_bytes(ms, user_ptr, user_size, user_bytes_copied);
+ if (ret)
+ return ret;
+
+ if (*user_bytes_copied == user_size)
+ return 0;
+
+ ret = ivpu_jsm_metric_streamer_update(vdev, ms->mask, ms->inactive_buff_vpu_addr,
+ ms->buff_size, &bytes_written);
+ if (ret)
+ return ret;
+
+ swap(ms->active_buff_vpu_addr, ms->inactive_buff_vpu_addr);
+ swap(ms->active_buff_ptr, ms->inactive_buff_ptr);
+
+ ms->leftover_bytes = bytes_written;
+ ms->leftover_addr = ms->inactive_buff_ptr;
+
+ return copy_leftover_bytes(ms, user_ptr, user_size, user_bytes_copied);
+}
+
+int ivpu_ms_get_data_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
+{
+ struct drm_ivpu_metric_streamer_get_data *args = data;
+ struct ivpu_file_priv *file_priv = file->driver_priv;
+ struct ivpu_device *vdev = file_priv->vdev;
+ struct ivpu_ms_instance *ms;
+ u64 bytes_written;
+ int ret;
+
+ if (!args->metric_group_mask)
+ return -EINVAL;
+
+ mutex_lock(&file_priv->ms_lock);
+
+ ms = get_instance_by_mask(file_priv, args->metric_group_mask);
+ if (!ms) {
+ ivpu_err(vdev, "Instance doesn't exist for mask: %#llx\n", args->metric_group_mask);
+ ret = -EINVAL;
+ goto unlock;
+ }
+
+ if (!args->buffer_size) {
+ ret = ivpu_jsm_metric_streamer_update(vdev, ms->mask, 0, 0, &bytes_written);
+ if (ret)
+ goto unlock;
+ args->data_size = bytes_written + ms->leftover_bytes;
+ goto unlock;
+ }
+
+ if (!args->buffer_ptr) {
+ ret = -EINVAL;
+ goto unlock;
+ }
+
+ ret = copy_samples_to_user(vdev, ms, u64_to_user_ptr(args->buffer_ptr),
+ args->buffer_size, &args->data_size);
+unlock:
+ mutex_unlock(&file_priv->ms_lock);
+
+ return ret;
+}
+
+static void free_instance(struct ivpu_file_priv *file_priv, struct ivpu_ms_instance *ms)
+{
+ lockdep_assert_held(&file_priv->ms_lock);
+
+ list_del(&ms->ms_instance_node);
+ ivpu_jsm_metric_streamer_stop(file_priv->vdev, ms->mask);
+ ivpu_bo_free(ms->bo);
+ kfree(ms);
+}
+
+int ivpu_ms_stop_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
+{
+ struct ivpu_file_priv *file_priv = file->driver_priv;
+ struct drm_ivpu_metric_streamer_stop *args = data;
+ struct ivpu_ms_instance *ms;
+
+ if (!args->metric_group_mask)
+ return -EINVAL;
+
+ mutex_lock(&file_priv->ms_lock);
+
+ ms = get_instance_by_mask(file_priv, args->metric_group_mask);
+ if (ms)
+ free_instance(file_priv, ms);
+
+ mutex_unlock(&file_priv->ms_lock);
+
+ return ms ? 0 : -EINVAL;
+}
+
+static inline struct ivpu_bo *get_ms_info_bo(struct ivpu_file_priv *file_priv)
+{
+ lockdep_assert_held(&file_priv->ms_lock);
+
+ if (file_priv->ms_info_bo)
+ return file_priv->ms_info_bo;
+
+ file_priv->ms_info_bo = ivpu_bo_create_global(file_priv->vdev, MS_INFO_BUFFER_SIZE,
+ DRM_IVPU_BO_CACHED | DRM_IVPU_BO_MAPPABLE);
+ return file_priv->ms_info_bo;
+}
+
+int ivpu_ms_get_info_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
+{
+ struct drm_ivpu_metric_streamer_get_data *args = data;
+ struct ivpu_file_priv *file_priv = file->driver_priv;
+ struct ivpu_device *vdev = file_priv->vdev;
+ struct ivpu_bo *bo;
+ u64 info_size;
+ int ret;
+
+ if (!args->metric_group_mask)
+ return -EINVAL;
+
+ if (!args->buffer_size)
+ return ivpu_jsm_metric_streamer_info(vdev, args->metric_group_mask,
+ 0, 0, NULL, &args->data_size);
+ if (!args->buffer_ptr)
+ return -EINVAL;
+
+ mutex_lock(&file_priv->ms_lock);
+
+ bo = get_ms_info_bo(file_priv);
+ if (!bo) {
+ ret = -ENOMEM;
+ goto unlock;
+ }
+
+ ret = ivpu_jsm_metric_streamer_info(vdev, args->metric_group_mask, bo->vpu_addr,
+ ivpu_bo_size(bo), NULL, &info_size);
+ if (ret)
+ goto unlock;
+
+ if (args->buffer_size < info_size) {
+ ret = -ENOSPC;
+ goto unlock;
+ }
+
+ if (copy_to_user(u64_to_user_ptr(args->buffer_ptr), ivpu_bo_vaddr(bo), info_size))
+ ret = -EFAULT;
+
+ args->data_size = info_size;
+unlock:
+ mutex_unlock(&file_priv->ms_lock);
+
+ return ret;
+}
+
+void ivpu_ms_cleanup(struct ivpu_file_priv *file_priv)
+{
+ struct ivpu_ms_instance *ms, *tmp;
+
+ mutex_lock(&file_priv->ms_lock);
+
+ if (file_priv->ms_info_bo) {
+ ivpu_bo_free(file_priv->ms_info_bo);
+ file_priv->ms_info_bo = NULL;
+ }
+
+ list_for_each_entry_safe(ms, tmp, &file_priv->ms_instance_list, ms_instance_node)
+ free_instance(file_priv, ms);
+
+ mutex_unlock(&file_priv->ms_lock);
+}
+
+void ivpu_ms_cleanup_all(struct ivpu_device *vdev)
+{
+ struct ivpu_file_priv *file_priv;
+ unsigned long ctx_id;
+
+ mutex_lock(&vdev->context_list_lock);
+
+ xa_for_each(&vdev->context_xa, ctx_id, file_priv)
+ ivpu_ms_cleanup(file_priv);
+
+ mutex_unlock(&vdev->context_list_lock);
+}
diff --git a/drivers/accel/ivpu/ivpu_ms.h b/drivers/accel/ivpu/ivpu_ms.h
new file mode 100644
index 000000000000..fbd5ebebc3d9
--- /dev/null
+++ b/drivers/accel/ivpu/ivpu_ms.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
+/*
+ * Copyright (C) 2020-2024 Intel Corporation
+ */
+#ifndef __IVPU_MS_H__
+#define __IVPU_MS_H__
+
+#include <linux/list.h>
+
+struct drm_device;
+struct drm_file;
+struct ivpu_bo;
+struct ivpu_device;
+struct ivpu_file_priv;
+
+struct ivpu_ms_instance {
+ struct ivpu_bo *bo;
+ struct list_head ms_instance_node;
+ u64 mask;
+ u64 buff_size;
+ u64 active_buff_vpu_addr;
+ u64 inactive_buff_vpu_addr;
+ void *active_buff_ptr;
+ void *inactive_buff_ptr;
+ u64 leftover_bytes;
+ void *leftover_addr;
+};
+
+int ivpu_ms_start_ioctl(struct drm_device *dev, void *data, struct drm_file *file);
+int ivpu_ms_stop_ioctl(struct drm_device *dev, void *data, struct drm_file *file);
+int ivpu_ms_get_data_ioctl(struct drm_device *dev, void *data, struct drm_file *file);
+int ivpu_ms_get_info_ioctl(struct drm_device *dev, void *data, struct drm_file *file);
+void ivpu_ms_cleanup(struct ivpu_file_priv *file_priv);
+void ivpu_ms_cleanup_all(struct ivpu_device *vdev);
+
+#endif /* __IVPU_MS_H__ */
diff --git a/drivers/accel/ivpu/ivpu_pm.c b/drivers/accel/ivpu/ivpu_pm.c
index 4f5ea466731f..02b4eac13f8b 100644
--- a/drivers/accel/ivpu/ivpu_pm.c
+++ b/drivers/accel/ivpu/ivpu_pm.c
@@ -18,6 +18,7 @@
#include "ivpu_job.h"
#include "ivpu_jsm_msg.h"
#include "ivpu_mmu.h"
+#include "ivpu_ms.h"
#include "ivpu_pm.h"
static bool ivpu_disable_recovery;
@@ -131,6 +132,7 @@ static void ivpu_pm_recovery_work(struct work_struct *work)
ivpu_suspend(vdev);
ivpu_pm_prepare_cold_boot(vdev);
ivpu_jobs_abort_all(vdev);
+ ivpu_ms_cleanup_all(vdev);
ret = ivpu_resume(vdev);
if (ret)
@@ -262,6 +264,7 @@ int ivpu_pm_runtime_suspend_cb(struct device *dev)
if (!hw_is_idle) {
ivpu_err(vdev, "NPU failed to enter idle, force suspended.\n");
+ atomic_inc(&vdev->pm->reset_counter);
ivpu_fw_log_dump(vdev);
ivpu_pm_prepare_cold_boot(vdev);
} else {
@@ -333,6 +336,8 @@ void ivpu_pm_reset_prepare_cb(struct pci_dev *pdev)
ivpu_hw_reset(vdev);
ivpu_pm_prepare_cold_boot(vdev);
ivpu_jobs_abort_all(vdev);
+ ivpu_ms_cleanup_all(vdev);
+
ivpu_dbg(vdev, PM, "Pre-reset done.\n");
}
diff --git a/drivers/accel/ivpu/ivpu_sysfs.c b/drivers/accel/ivpu/ivpu_sysfs.c
new file mode 100644
index 000000000000..913669f1786e
--- /dev/null
+++ b/drivers/accel/ivpu/ivpu_sysfs.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2024 Intel Corporation
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+
+#include "ivpu_hw.h"
+#include "ivpu_sysfs.h"
+
+/*
+ * npu_busy_time_us is the time that the device spent executing jobs.
+ * The time is counted when and only when there are jobs submitted to firmware.
+ *
+ * This time can be used to measure the utilization of NPU, either by calculating
+ * npu_busy_time_us difference between two timepoints (i.e. measuring the time
+ * that the NPU was active during some workload) or monitoring utilization percentage
+ * by reading npu_busy_time_us periodically.
+ *
+ * When reading the value periodically, it shouldn't be read too often as it may have
+ * an impact on job submission performance. Recommended period is 1 second.
+ */
+static ssize_t
+npu_busy_time_us_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct drm_device *drm = dev_get_drvdata(dev);
+ struct ivpu_device *vdev = to_ivpu_device(drm);
+ ktime_t total, now = 0;
+
+ xa_lock(&vdev->submitted_jobs_xa);
+ total = vdev->busy_time;
+ if (!xa_empty(&vdev->submitted_jobs_xa))
+ now = ktime_sub(ktime_get(), vdev->busy_start_ts);
+ xa_unlock(&vdev->submitted_jobs_xa);
+
+ return sysfs_emit(buf, "%lld\n", ktime_to_us(ktime_add(total, now)));
+}
+
+static DEVICE_ATTR_RO(npu_busy_time_us);
+
+static struct attribute *ivpu_dev_attrs[] = {
+ &dev_attr_npu_busy_time_us.attr,
+ NULL,
+};
+
+static struct attribute_group ivpu_dev_attr_group = {
+ .attrs = ivpu_dev_attrs,
+};
+
+void ivpu_sysfs_init(struct ivpu_device *vdev)
+{
+ int ret;
+
+ ret = devm_device_add_group(vdev->drm.dev, &ivpu_dev_attr_group);
+ if (ret)
+ ivpu_warn(vdev, "Failed to add group to device, ret %d", ret);
+}
diff --git a/drivers/accel/ivpu/ivpu_sysfs.h b/drivers/accel/ivpu/ivpu_sysfs.h
new file mode 100644
index 000000000000..9836f09b35a3
--- /dev/null
+++ b/drivers/accel/ivpu/ivpu_sysfs.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2024 Intel Corporation
+ */
+
+#ifndef __IVPU_SYSFS_H__
+#define __IVPU_SYSFS_H__
+
+#include "ivpu_drv.h"
+
+void ivpu_sysfs_init(struct ivpu_device *vdev);
+
+#endif /* __IVPU_SYSFS_H__ */
diff --git a/drivers/accel/ivpu/vpu_jsm_api.h b/drivers/accel/ivpu/vpu_jsm_api.h
index e46f3531211a..33f462b1a25d 100644
--- a/drivers/accel/ivpu/vpu_jsm_api.h
+++ b/drivers/accel/ivpu/vpu_jsm_api.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT */
/*
- * Copyright (c) 2020-2023, Intel Corporation.
+ * Copyright (c) 2020-2024, Intel Corporation.
*/
/**
@@ -22,12 +22,12 @@
/*
* Minor version changes when API backward compatibility is preserved.
*/
-#define VPU_JSM_API_VER_MINOR 15
+#define VPU_JSM_API_VER_MINOR 16
/*
* API header changed (field names, documentation, formatting) but API itself has not been changed
*/
-#define VPU_JSM_API_VER_PATCH 6
+#define VPU_JSM_API_VER_PATCH 0
/*
* Index in the API version table
@@ -868,6 +868,14 @@ struct vpu_ipc_msg_payload_hws_set_scheduling_log {
* is generated when an event log is written to this index.
*/
u64 notify_index;
+ /*
+ * Enable extra events to be output to log for debug of scheduling algorithm.
+ * Interpreted by VPU as a boolean to enable or disable, expected values are
+ * 0 and 1.
+ */
+ u32 enable_extra_events;
+ /* Zero Padding */
+ u32 reserved_0;
};
/*
diff --git a/drivers/dma-buf/dma-fence-array.c b/drivers/dma-buf/dma-fence-array.c
index 9b3ce8948351..c74ac197d5fe 100644
--- a/drivers/dma-buf/dma-fence-array.c
+++ b/drivers/dma-buf/dma-fence-array.c
@@ -70,7 +70,7 @@ static void dma_fence_array_cb_func(struct dma_fence *f,
static bool dma_fence_array_enable_signaling(struct dma_fence *fence)
{
struct dma_fence_array *array = to_dma_fence_array(fence);
- struct dma_fence_array_cb *cb = (void *)(&array[1]);
+ struct dma_fence_array_cb *cb = array->callbacks;
unsigned i;
for (i = 0; i < array->num_fences; ++i) {
@@ -168,22 +168,20 @@ struct dma_fence_array *dma_fence_array_create(int num_fences,
bool signal_on_any)
{
struct dma_fence_array *array;
- size_t size = sizeof(*array);
WARN_ON(!num_fences || !fences);
- /* Allocate the callback structures behind the array. */
- size += num_fences * sizeof(struct dma_fence_array_cb);
- array = kzalloc(size, GFP_KERNEL);
+ array = kzalloc(struct_size(array, callbacks, num_fences), GFP_KERNEL);
if (!array)
return NULL;
+ array->num_fences = num_fences;
+
spin_lock_init(&array->lock);
dma_fence_init(&array->base, &dma_fence_array_ops, &array->lock,
context, seqno);
init_irq_work(&array->work, irq_dma_fence_array_work);
- array->num_fences = num_fences;
atomic_set(&array->num_pending, signal_on_any ? 1 : num_fences);
array->fences = fences;
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index f9ca4f8fa6c5..68cc9258ffc4 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -108,6 +108,7 @@ drm_dma_helper-$(CONFIG_DRM_KMS_HELPER) += drm_fb_dma_helper.o
obj-$(CONFIG_DRM_GEM_DMA_HELPER) += drm_dma_helper.o
drm_shmem_helper-y := drm_gem_shmem_helper.o
+drm_shmem_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fbdev_shmem.o
obj-$(CONFIG_DRM_GEM_SHMEM_HELPER) += drm_shmem_helper.o
drm_suballoc_helper-y := drm_suballoc.o
@@ -117,6 +118,7 @@ drm_vram_helper-y := drm_gem_vram_helper.o
obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o
drm_ttm_helper-y := drm_gem_ttm_helper.o
+drm_ttm_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fbdev_ttm.o
obj-$(CONFIG_DRM_TTM_HELPER) += drm_ttm_helper.o
#
@@ -142,9 +144,7 @@ drm_kms_helper-y := \
drm_self_refresh_helper.o \
drm_simple_kms_helper.o
drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o
-drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += \
- drm_fbdev_generic.o \
- drm_fb_helper.o
+drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
#
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
index 9caba10315a8..cae7479c3ecf 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
@@ -246,22 +246,6 @@ amdgpu_connector_find_encoder(struct drm_connector *connector,
return NULL;
}
-struct edid *amdgpu_connector_edid(struct drm_connector *connector)
-{
- struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
- struct drm_property_blob *edid_blob = connector->edid_blob_ptr;
-
- if (amdgpu_connector->edid) {
- return amdgpu_connector->edid;
- } else if (edid_blob) {
- struct edid *edid = kmemdup(edid_blob->data, edid_blob->length, GFP_KERNEL);
-
- if (edid)
- amdgpu_connector->edid = edid;
- }
- return amdgpu_connector->edid;
-}
-
static struct edid *
amdgpu_connector_get_hardcoded_edid(struct amdgpu_device *adev)
{
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.h
index 61fcef15ad72..eff833b6ed31 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.h
@@ -24,7 +24,6 @@
#ifndef __AMDGPU_CONNECTORS_H__
#define __AMDGPU_CONNECTORS_H__
-struct edid *amdgpu_connector_edid(struct drm_connector *connector);
void amdgpu_connector_hotplug(struct drm_connector *connector);
int amdgpu_connector_get_monitor_bpc(struct drm_connector *connector);
u16 amdgpu_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index ea14f1c8f430..4f76aa606ac9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -24,7 +24,7 @@
#include <drm/amdgpu_drm.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_ttm.h>
#include <drm/drm_gem.h>
#include <drm/drm_managed.h>
#include <drm/drm_pciids.h>
@@ -2318,9 +2318,9 @@ retry_init:
!list_empty(&adev_to_drm(adev)->mode_config.connector_list)) {
/* select 8 bpp console on low vram cards */
if (adev->gmc.real_vram_size <= (32*1024*1024))
- drm_fbdev_generic_setup(adev_to_drm(adev), 8);
+ drm_fbdev_ttm_setup(adev_to_drm(adev), 8);
else
- drm_fbdev_generic_setup(adev_to_drm(adev), 32);
+ drm_fbdev_ttm_setup(adev_to_drm(adev), 32);
}
ret = amdgpu_debugfs_init(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
index e30eecd02ae1..821f9491565b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
@@ -65,9 +65,7 @@ static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct hrtimer *timer)
static int amdgpu_vkms_enable_vblank(struct drm_crtc *crtc)
{
- struct drm_device *dev = crtc->dev;
- unsigned int pipe = drm_crtc_index(crtc);
- struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+ struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
struct amdgpu_vkms_output *out = drm_crtc_to_amdgpu_vkms_output(crtc);
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
@@ -91,10 +89,8 @@ static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc,
ktime_t *vblank_time,
bool in_vblank_irq)
{
- struct drm_device *dev = crtc->dev;
- unsigned int pipe = crtc->index;
struct amdgpu_vkms_output *output = drm_crtc_to_amdgpu_vkms_output(crtc);
- struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+ struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
if (!READ_ONCE(vblank->enabled)) {
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
index b44fce44c066..dddb5fe16f2c 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
@@ -1299,7 +1299,7 @@ static void dce_v10_0_audio_write_speaker_allocation(struct drm_encoder *encoder
return;
}
- sad_count = drm_edid_to_speaker_allocation(amdgpu_connector_edid(connector), &sadb);
+ sad_count = drm_edid_to_speaker_allocation(amdgpu_connector->edid, &sadb);
if (sad_count < 0) {
DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
sad_count = 0;
@@ -1369,7 +1369,7 @@ static void dce_v10_0_audio_write_sad_regs(struct drm_encoder *encoder)
return;
}
- sad_count = drm_edid_to_sad(amdgpu_connector_edid(connector), &sads);
+ sad_count = drm_edid_to_sad(amdgpu_connector->edid, &sads);
if (sad_count < 0)
DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
if (sad_count <= 0)
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
index 80b2e7f79acf..11780e4d7e9f 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
@@ -1331,7 +1331,7 @@ static void dce_v11_0_audio_write_speaker_allocation(struct drm_encoder *encoder
return;
}
- sad_count = drm_edid_to_speaker_allocation(amdgpu_connector_edid(connector), &sadb);
+ sad_count = drm_edid_to_speaker_allocation(amdgpu_connector->edid, &sadb);
if (sad_count < 0) {
DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
sad_count = 0;
@@ -1401,7 +1401,7 @@ static void dce_v11_0_audio_write_sad_regs(struct drm_encoder *encoder)
return;
}
- sad_count = drm_edid_to_sad(amdgpu_connector_edid(connector), &sads);
+ sad_count = drm_edid_to_sad(amdgpu_connector->edid, &sads);
if (sad_count < 0)
DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
if (sad_count <= 0)
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
index db20012600f5..05c0df97f01d 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
@@ -1217,7 +1217,7 @@ static void dce_v6_0_audio_write_speaker_allocation(struct drm_encoder *encoder)
return;
}
- sad_count = drm_edid_to_speaker_allocation(amdgpu_connector_edid(connector), &sadb);
+ sad_count = drm_edid_to_speaker_allocation(amdgpu_connector->edid, &sadb);
if (sad_count < 0) {
DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
sad_count = 0;
@@ -1292,7 +1292,7 @@ static void dce_v6_0_audio_write_sad_regs(struct drm_encoder *encoder)
return;
}
- sad_count = drm_edid_to_sad(amdgpu_connector_edid(connector), &sads);
+ sad_count = drm_edid_to_sad(amdgpu_connector->edid, &sads);
if (sad_count < 0)
DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
if (sad_count <= 0)
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
index 5b56100ec902..dc73e301d937 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
@@ -1272,7 +1272,7 @@ static void dce_v8_0_audio_write_speaker_allocation(struct drm_encoder *encoder)
return;
}
- sad_count = drm_edid_to_speaker_allocation(amdgpu_connector_edid(connector), &sadb);
+ sad_count = drm_edid_to_speaker_allocation(amdgpu_connector->edid, &sadb);
if (sad_count < 0) {
DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
sad_count = 0;
@@ -1340,7 +1340,7 @@ static void dce_v8_0_audio_write_sad_regs(struct drm_encoder *encoder)
return;
}
- sad_count = drm_edid_to_sad(amdgpu_connector_edid(connector), &sads);
+ sad_count = drm_edid_to_sad(amdgpu_connector->edid, &sads);
if (sad_count < 0)
DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
if (sad_count <= 0)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index f1d67c6f4b98..516eb3968e26 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -531,7 +531,7 @@ static void dm_vupdate_high_irq(void *interrupt_params)
if (acrtc) {
vrr_active = amdgpu_dm_crtc_vrr_active_irq(acrtc);
drm_dev = acrtc->base.dev;
- vblank = &drm_dev->vblank[acrtc->base.index];
+ vblank = drm_crtc_vblank_crtc(&acrtc->base);
previous_timestamp = atomic64_read(&irq_params->previous_timestamp);
frame_duration_ns = vblank->time - previous_timestamp;
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
index 2c661f28410e..2ad33559a33a 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
@@ -5,6 +5,7 @@
*
*/
#include <linux/clk.h>
+#include <linux/of.h>
#include <linux/pm_runtime.h>
#include <linux/spinlock.h>
@@ -294,7 +295,6 @@ komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc,
struct komeda_dev *mdev = kcrtc->master->mdev;
struct completion *flip_done;
struct completion temp;
- int timeout;
/* if caller doesn't send a flip_done, use a private flip_done */
if (input_flip_done) {
@@ -308,8 +308,7 @@ komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc,
mdev->funcs->flush(mdev, kcrtc->master->id, 0);
/* wait the flip take affect.*/
- timeout = wait_for_completion_timeout(flip_done, HZ);
- if (timeout == 0) {
+ if (wait_for_completion_timeout(flip_done, HZ) == 0) {
DRM_ERROR("wait pipe%d flip done timeout\n", kcrtc->master->id);
if (!input_flip_done) {
unsigned long flags;
@@ -610,12 +609,34 @@ get_crtc_primary(struct komeda_kms_dev *kms, struct komeda_crtc *crtc)
return NULL;
}
+static int komeda_attach_bridge(struct device *dev,
+ struct komeda_pipeline *pipe,
+ struct drm_encoder *encoder)
+{
+ struct drm_bridge *bridge;
+ int err;
+
+ bridge = devm_drm_of_get_bridge(dev, pipe->of_node,
+ KOMEDA_OF_PORT_OUTPUT, 0);
+ if (IS_ERR(bridge))
+ return dev_err_probe(dev, PTR_ERR(bridge), "remote bridge not found for pipe: %s\n",
+ of_node_full_name(pipe->of_node));
+
+ err = drm_bridge_attach(encoder, bridge, NULL, 0);
+ if (err)
+ dev_err(dev, "bridge_attach() failed for pipe: %s\n",
+ of_node_full_name(pipe->of_node));
+
+ return err;
+}
+
static int komeda_crtc_add(struct komeda_kms_dev *kms,
struct komeda_crtc *kcrtc)
{
struct drm_crtc *crtc = &kcrtc->base;
struct drm_device *base = &kms->base;
- struct drm_bridge *bridge;
+ struct komeda_pipeline *pipe = kcrtc->master;
+ struct drm_encoder *encoder = &kcrtc->encoder;
int err;
err = drm_crtc_init_with_planes(base, crtc,
@@ -626,27 +647,27 @@ static int komeda_crtc_add(struct komeda_kms_dev *kms,
drm_crtc_helper_add(crtc, &komeda_crtc_helper_funcs);
- crtc->port = kcrtc->master->of_output_port;
+ crtc->port = pipe->of_output_port;
/* Construct an encoder for each pipeline and attach it to the remote
* bridge
*/
kcrtc->encoder.possible_crtcs = drm_crtc_mask(crtc);
- err = drm_simple_encoder_init(base, &kcrtc->encoder,
- DRM_MODE_ENCODER_TMDS);
+ err = drm_simple_encoder_init(base, encoder, DRM_MODE_ENCODER_TMDS);
if (err)
return err;
- bridge = devm_drm_of_get_bridge(base->dev, kcrtc->master->of_node,
- KOMEDA_OF_PORT_OUTPUT, 0);
- if (IS_ERR(bridge))
- return PTR_ERR(bridge);
-
- err = drm_bridge_attach(&kcrtc->encoder, bridge, NULL, 0);
+ if (pipe->of_output_links[0]) {
+ err = komeda_attach_bridge(base->dev, pipe, encoder);
+ if (err)
+ return err;
+ }
drm_crtc_enable_color_mgmt(crtc, 0, true, KOMEDA_COLOR_LUT_SIZE);
- return err;
+ komeda_pipeline_dump(pipe);
+
+ return 0;
}
int komeda_kms_add_crtcs(struct komeda_kms_dev *kms, struct komeda_dev *mdev)
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
index cc57ea4e13ae..55c3773befde 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
@@ -9,7 +9,7 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_module.h>
#include <drm/drm_of.h>
#include "komeda_dev.h"
@@ -59,6 +59,10 @@ static int komeda_platform_probe(struct platform_device *pdev)
struct komeda_drv *mdrv;
int err;
+ err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40));
+ if (err)
+ return dev_err_probe(dev, err, "DMA mask error\n");
+
mdrv = devm_kzalloc(dev, sizeof(*mdrv), GFP_KERNEL);
if (!mdrv)
return -ENOMEM;
@@ -80,7 +84,7 @@ static int komeda_platform_probe(struct platform_device *pdev)
}
dev_set_drvdata(dev, mdrv);
- drm_fbdev_generic_setup(&mdrv->kms->base, 32);
+ drm_fbdev_dma_setup(&mdrv->kms->base, 32);
return 0;
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h
index a4048724564d..83e61c4080c2 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h
@@ -191,5 +191,6 @@ void komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc,
struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev);
void komeda_kms_detach(struct komeda_kms_dev *kms);
void komeda_kms_shutdown(struct komeda_kms_dev *kms);
+void komeda_pipeline_dump(struct komeda_pipeline *pipe);
#endif /*_KOMEDA_KMS_H_*/
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c
index 00f5864a0495..81e244f0c0ca 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c
@@ -10,6 +10,7 @@
#include <drm/drm_print.h>
#include "komeda_dev.h"
+#include "komeda_kms.h"
#include "komeda_pipeline.h"
/** komeda_pipeline_add - Add a pipeline to &komeda_dev */
@@ -247,7 +248,7 @@ static void komeda_component_dump(struct komeda_component *c)
c->max_active_outputs, c->supported_outputs);
}
-static void komeda_pipeline_dump(struct komeda_pipeline *pipe)
+void komeda_pipeline_dump(struct komeda_pipeline *pipe)
{
struct komeda_component *c;
int id;
@@ -351,7 +352,6 @@ int komeda_assemble_pipelines(struct komeda_dev *mdev)
pipe = mdev->pipelines[i];
komeda_pipeline_assemble(pipe);
- komeda_pipeline_dump(pipe);
}
return 0;
diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c
index f8c49ba68e78..aae019e79bda 100644
--- a/drivers/gpu/drm/ast/ast_drv.c
+++ b/drivers/gpu/drm/ast/ast_drv.c
@@ -33,7 +33,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_shmem.h>
#include <drm/drm_gem_shmem_helper.h>
#include <drm/drm_module.h>
#include <drm/drm_probe_helper.h>
@@ -360,7 +360,7 @@ static int ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ret)
return ret;
- drm_fbdev_generic_setup(drm, 32);
+ drm_fbdev_shmem_setup(drm, 32);
return 0;
}
diff --git a/drivers/gpu/drm/atmel-hlcdc/Kconfig b/drivers/gpu/drm/atmel-hlcdc/Kconfig
index 3bdbab3a6333..945f3aa7bb24 100644
--- a/drivers/gpu/drm/atmel-hlcdc/Kconfig
+++ b/drivers/gpu/drm/atmel-hlcdc/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config DRM_ATMEL_HLCDC
tristate "DRM Support for ATMEL HLCDC Display Controller"
- depends on DRM && OF && COMMON_CLK && MFD_ATMEL_HLCDC && ARM
+ depends on DRM && OF && COMMON_CLK && ((MFD_ATMEL_HLCDC && ARM) || COMPILE_TEST)
select DRM_GEM_DMA_HELPER
select DRM_KMS_HELPER
select DRM_PANEL
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
index 66ccb61e2a66..3cd130965e9d 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
@@ -877,11 +877,6 @@ static int adv7511_connector_init(struct adv7511 *adv)
struct drm_bridge *bridge = &adv->bridge;
int ret;
- if (!bridge->encoder) {
- DRM_ERROR("Parent encoder object not found");
- return -ENODEV;
- }
-
if (adv->i2c_main->irq)
adv->connector.polled = DRM_CONNECTOR_POLL_HPD;
else
diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c
index c9e35731e6a1..b754947e3e00 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c
@@ -47,7 +47,7 @@ struct anx6345 {
struct drm_dp_aux aux;
struct drm_bridge bridge;
struct i2c_client *client;
- struct edid *edid;
+ const struct drm_edid *drm_edid;
struct drm_connector connector;
struct drm_panel *panel;
struct regulator *dvdd12;
@@ -458,7 +458,7 @@ static int anx6345_get_modes(struct drm_connector *connector)
mutex_lock(&anx6345->lock);
- if (!anx6345->edid) {
+ if (!anx6345->drm_edid) {
if (!anx6345->powered) {
anx6345_poweron(anx6345);
power_off = true;
@@ -470,19 +470,18 @@ static int anx6345_get_modes(struct drm_connector *connector)
goto unlock;
}
- anx6345->edid = drm_get_edid(connector, &anx6345->aux.ddc);
- if (!anx6345->edid)
+ anx6345->drm_edid = drm_edid_read_ddc(connector, &anx6345->aux.ddc);
+ if (!anx6345->drm_edid)
DRM_ERROR("Failed to read EDID from panel\n");
- err = drm_connector_update_edid_property(connector,
- anx6345->edid);
+ err = drm_edid_connector_update(connector, anx6345->drm_edid);
if (err) {
DRM_ERROR("Failed to update EDID property: %d\n", err);
goto unlock;
}
}
- num_modes += drm_add_edid_modes(connector, anx6345->edid);
+ num_modes += drm_edid_connector_add_modes(connector);
/* Driver currently supports only 6bpc */
connector->display_info.bpc = 6;
@@ -528,11 +527,6 @@ static int anx6345_bridge_attach(struct drm_bridge *bridge,
return -EINVAL;
}
- if (!bridge->encoder) {
- DRM_ERROR("Parent encoder object not found");
- return -ENODEV;
- }
-
/* Register aux channel */
anx6345->aux.name = "DP-AUX";
anx6345->aux.dev = &anx6345->client->dev;
@@ -793,7 +787,7 @@ static void anx6345_i2c_remove(struct i2c_client *client)
unregister_i2c_dummy_clients(anx6345);
- kfree(anx6345->edid);
+ drm_edid_free(anx6345->drm_edid);
mutex_destroy(&anx6345->lock);
}
diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c
index 5748a8581af4..f74694bb9c50 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c
@@ -67,7 +67,7 @@ struct anx78xx {
struct drm_dp_aux aux;
struct drm_bridge bridge;
struct i2c_client *client;
- struct edid *edid;
+ const struct drm_edid *drm_edid;
struct drm_connector connector;
struct anx78xx_platform_data pdata;
struct mutex lock;
@@ -830,8 +830,8 @@ static int anx78xx_get_modes(struct drm_connector *connector)
if (WARN_ON(!anx78xx->powered))
return 0;
- if (anx78xx->edid)
- return drm_add_edid_modes(connector, anx78xx->edid);
+ if (anx78xx->drm_edid)
+ return drm_edid_connector_add_modes(connector);
mutex_lock(&anx78xx->lock);
@@ -841,20 +841,21 @@ static int anx78xx_get_modes(struct drm_connector *connector)
goto unlock;
}
- anx78xx->edid = drm_get_edid(connector, &anx78xx->aux.ddc);
- if (!anx78xx->edid) {
+ anx78xx->drm_edid = drm_edid_read_ddc(connector, &anx78xx->aux.ddc);
+
+ err = drm_edid_connector_update(connector, anx78xx->drm_edid);
+
+ if (!anx78xx->drm_edid) {
DRM_ERROR("Failed to read EDID\n");
goto unlock;
}
- err = drm_connector_update_edid_property(connector,
- anx78xx->edid);
if (err) {
DRM_ERROR("Failed to update EDID property: %d\n", err);
goto unlock;
}
- num_modes = drm_add_edid_modes(connector, anx78xx->edid);
+ num_modes = drm_edid_connector_add_modes(connector);
unlock:
mutex_unlock(&anx78xx->lock);
@@ -897,11 +898,6 @@ static int anx78xx_bridge_attach(struct drm_bridge *bridge,
return -EINVAL;
}
- if (!bridge->encoder) {
- DRM_ERROR("Parent encoder object not found");
- return -ENODEV;
- }
-
/* Register aux channel */
anx78xx->aux.name = "DP-AUX";
anx78xx->aux.dev = &anx78xx->client->dev;
@@ -1091,8 +1087,8 @@ static bool anx78xx_handle_common_int_4(struct anx78xx *anx78xx, u8 irq)
event = true;
anx78xx_poweroff(anx78xx);
/* Free cached EDID */
- kfree(anx78xx->edid);
- anx78xx->edid = NULL;
+ drm_edid_free(anx78xx->drm_edid);
+ anx78xx->drm_edid = NULL;
} else if (irq & SP_HPD_PLUG) {
DRM_DEBUG_KMS("IRQ: Hot plug detect - cable plug\n");
event = true;
@@ -1363,7 +1359,7 @@ static void anx78xx_i2c_remove(struct i2c_client *client)
unregister_i2c_dummy_clients(anx78xx);
- kfree(anx78xx->edid);
+ drm_edid_free(anx78xx->drm_edid);
}
static const struct of_device_id anx78xx_match_table[] = {
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index df9370e0ff23..7b841232321f 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -1228,11 +1228,6 @@ static int analogix_dp_bridge_attach(struct drm_bridge *bridge,
return -EINVAL;
}
- if (!bridge->encoder) {
- DRM_ERROR("Parent encoder object not found");
- return -ENODEV;
- }
-
if (!dp->plat_data->skip_connector) {
connector = &dp->connector;
connector->polled = DRM_CONNECTOR_POLL_HPD;
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
index 59e9ad349969..88e4aa5830f3 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -464,9 +464,11 @@ static int anx7625_odfc_config(struct anx7625_data *ctx,
*/
static int anx7625_set_k_value(struct anx7625_data *ctx)
{
- struct edid *edid = (struct edid *)ctx->slimport_edid_p.edid_raw_data;
+ struct drm_edid_product_id id;
- if (edid->mfg_id[0] == IVO_MID0 && edid->mfg_id[1] == IVO_MID1)
+ drm_edid_get_product_id(ctx->cached_drm_edid, &id);
+
+ if (be16_to_cpu(id.manufacturer_name) == IVO_MID)
return anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
MIPI_DIGITAL_ADJ_1, 0x3B);
@@ -1526,7 +1528,8 @@ static int anx7625_wait_hpd_asserted(struct drm_dp_aux *aux,
static void anx7625_remove_edid(struct anx7625_data *ctx)
{
- ctx->slimport_edid_p.edid_block_num = -1;
+ drm_edid_free(ctx->cached_drm_edid);
+ ctx->cached_drm_edid = NULL;
}
static void anx7625_dp_adjust_swing(struct anx7625_data *ctx)
@@ -1787,27 +1790,32 @@ static ssize_t anx7625_aux_transfer(struct drm_dp_aux *aux,
static const struct drm_edid *anx7625_edid_read(struct anx7625_data *ctx)
{
struct device *dev = ctx->dev;
- struct s_edid_data *p_edid = &ctx->slimport_edid_p;
+ u8 *edid_buf;
int edid_num;
- if (ctx->slimport_edid_p.edid_block_num > 0)
+ if (ctx->cached_drm_edid)
goto out;
+ edid_buf = kmalloc(FOUR_BLOCK_SIZE, GFP_KERNEL);
+ if (!edid_buf)
+ return NULL;
+
pm_runtime_get_sync(dev);
_anx7625_hpd_polling(ctx, 5000 * 100);
- edid_num = sp_tx_edid_read(ctx, p_edid->edid_raw_data);
+ edid_num = sp_tx_edid_read(ctx, edid_buf);
pm_runtime_put_sync(dev);
if (edid_num < 1) {
DRM_DEV_ERROR(dev, "Fail to read EDID: %d\n", edid_num);
+ kfree(edid_buf);
return NULL;
}
- p_edid->edid_block_num = edid_num;
+ ctx->cached_drm_edid = drm_edid_alloc(edid_buf, FOUR_BLOCK_SIZE);
+ kfree(edid_buf);
out:
- return drm_edid_alloc(ctx->slimport_edid_p.edid_raw_data,
- FOUR_BLOCK_SIZE);
+ return drm_edid_dup(ctx->cached_drm_edid);
}
static enum drm_connector_status anx7625_sink_detect(struct anx7625_data *ctx)
@@ -2193,11 +2201,6 @@ static int anx7625_bridge_attach(struct drm_bridge *bridge,
if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
return -EINVAL;
- if (!bridge->encoder) {
- DRM_DEV_ERROR(dev, "Parent encoder object not found");
- return -ENODEV;
- }
-
ctx->aux.drm_dev = bridge->dev;
err = drm_dp_aux_register(&ctx->aux);
if (err) {
@@ -2435,11 +2438,6 @@ static void anx7625_bridge_atomic_enable(struct drm_bridge *bridge,
dev_dbg(dev, "drm atomic enable\n");
- if (!bridge->encoder) {
- dev_err(dev, "Parent encoder object not found");
- return;
- }
-
connector = drm_atomic_get_new_connector_for_encoder(state->base.state,
bridge->encoder);
if (!connector)
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
index 39ed35d33836..eb5580f1ab2f 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.h
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
@@ -286,8 +286,7 @@
#define MIPI_LANE_CTRL_10 0x0F
#define MIPI_DIGITAL_ADJ_1 0x1B
-#define IVO_MID0 0x26
-#define IVO_MID1 0xCF
+#define IVO_MID 0x26CF
#define MIPI_PLL_M_NUM_23_16 0x1E
#define MIPI_PLL_M_NUM_15_8 0x1F
@@ -417,11 +416,6 @@ enum audio_wd_len {
#define EDID_TRY_CNT 3
#define SUPPORT_PIXEL_CLOCK 300000
-struct s_edid_data {
- int edid_block_num;
- u8 edid_raw_data[FOUR_BLOCK_SIZE];
-};
-
/***************** Display End *****************/
#define MAX_LANES_SUPPORT 4
@@ -466,7 +460,7 @@ struct anx7625_data {
struct anx7625_i2c_client i2c;
struct i2c_client *last_client;
struct timer_list hdcp_timer;
- struct s_edid_data slimport_edid_p;
+ const struct drm_edid *cached_drm_edid;
struct device *codec_dev;
hdmi_codec_plugged_cb plugged_cb;
struct work_struct work;
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
index 8a91ef0ae065..dee640ab1d3a 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
@@ -1697,11 +1697,6 @@ static int cdns_mhdp_connector_init(struct cdns_mhdp_device *mhdp)
struct drm_bridge *bridge = &mhdp->bridge;
int ret;
- if (!bridge->encoder) {
- dev_err(mhdp->dev, "Parent encoder object not found");
- return -ENODEV;
- }
-
conn->polled = DRM_CONNECTOR_POLL_HPD;
ret = drm_connector_init(bridge->dev, conn, &cdns_mhdp_conn_funcs,
diff --git a/drivers/gpu/drm/bridge/imx/imx-ldb-helper.c b/drivers/gpu/drm/bridge/imx/imx-ldb-helper.c
index 6967325cd8ee..9b5bebbe357d 100644
--- a/drivers/gpu/drm/bridge/imx/imx-ldb-helper.c
+++ b/drivers/gpu/drm/bridge/imx/imx-ldb-helper.c
@@ -116,11 +116,6 @@ int ldb_bridge_attach_helper(struct drm_bridge *bridge,
return -EINVAL;
}
- if (!bridge->encoder) {
- DRM_DEV_ERROR(ldb->dev, "missing encoder\n");
- return -ENODEV;
- }
-
return drm_bridge_attach(bridge->encoder,
ldb_ch->next_bridge, bridge,
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c
index d0868a6ac6c9..e6dbbdc87ce2 100644
--- a/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c
+++ b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c
@@ -119,11 +119,6 @@ static int imx8qxp_pc_bridge_attach(struct drm_bridge *bridge,
return -EINVAL;
}
- if (!bridge->encoder) {
- DRM_DEV_ERROR(pc->dev, "missing encoder\n");
- return -ENODEV;
- }
-
return drm_bridge_attach(bridge->encoder,
ch->next_bridge, bridge,
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c
index ed8b7a4e0e11..1d11cc1df43c 100644
--- a/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c
+++ b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c
@@ -138,11 +138,6 @@ static int imx8qxp_pixel_link_bridge_attach(struct drm_bridge *bridge,
return -EINVAL;
}
- if (!bridge->encoder) {
- DRM_DEV_ERROR(pl->dev, "missing encoder\n");
- return -ENODEV;
- }
-
return drm_bridge_attach(bridge->encoder,
pl->next_bridge, bridge,
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c b/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c
index 4a886cb808ca..fb7cf4369bb8 100644
--- a/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c
+++ b/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c
@@ -58,11 +58,6 @@ static int imx8qxp_pxl2dpi_bridge_attach(struct drm_bridge *bridge,
return -EINVAL;
}
- if (!bridge->encoder) {
- DRM_DEV_ERROR(p2d->dev, "missing encoder\n");
- return -ENODEV;
- }
-
return drm_bridge_attach(bridge->encoder,
p2d->next_bridge, bridge,
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c
index 3f68c82888c2..cd1b5057ddfb 100644
--- a/drivers/gpu/drm/bridge/ite-it6505.c
+++ b/drivers/gpu/drm/bridge/ite-it6505.c
@@ -1307,9 +1307,15 @@ static void it6505_video_reset(struct it6505 *it6505)
it6505_link_reset_step_train(it6505);
it6505_set_bits(it6505, REG_DATA_MUTE_CTRL, EN_VID_MUTE, EN_VID_MUTE);
it6505_set_bits(it6505, REG_INFOFRAME_CTRL, EN_VID_CTRL_PKT, 0x00);
- it6505_set_bits(it6505, REG_RESET_CTRL, VIDEO_RESET, VIDEO_RESET);
+
+ it6505_set_bits(it6505, REG_VID_BUS_CTRL1, TX_FIFO_RESET, TX_FIFO_RESET);
+ it6505_set_bits(it6505, REG_VID_BUS_CTRL1, TX_FIFO_RESET, 0x00);
+
it6505_set_bits(it6505, REG_501_FIFO_CTRL, RST_501_FIFO, RST_501_FIFO);
it6505_set_bits(it6505, REG_501_FIFO_CTRL, RST_501_FIFO, 0x00);
+
+ it6505_set_bits(it6505, REG_RESET_CTRL, VIDEO_RESET, VIDEO_RESET);
+ usleep_range(1000, 2000);
it6505_set_bits(it6505, REG_RESET_CTRL, VIDEO_RESET, 0x00);
}
@@ -2245,12 +2251,11 @@ static void it6505_link_training_work(struct work_struct *work)
if (ret) {
it6505->auto_train_retry = AUTO_TRAIN_RETRY;
it6505_link_train_ok(it6505);
- return;
} else {
it6505->auto_train_retry--;
+ it6505_dump(it6505);
}
- it6505_dump(it6505);
}
static void it6505_plugged_status_to_codec(struct it6505 *it6505)
@@ -2471,31 +2476,53 @@ static void it6505_irq_link_train_fail(struct it6505 *it6505)
schedule_work(&it6505->link_works);
}
-static void it6505_irq_video_fifo_error(struct it6505 *it6505)
+static bool it6505_test_bit(unsigned int bit, const unsigned int *addr)
{
- struct device *dev = it6505->dev;
-
- DRM_DEV_DEBUG_DRIVER(dev, "video fifo overflow interrupt");
- it6505->auto_train_retry = AUTO_TRAIN_RETRY;
- flush_work(&it6505->link_works);
- it6505_stop_hdcp(it6505);
- it6505_video_reset(it6505);
+ return 1 & (addr[bit / BITS_PER_BYTE] >> (bit % BITS_PER_BYTE));
}
-static void it6505_irq_io_latch_fifo_overflow(struct it6505 *it6505)
+static void it6505_irq_video_handler(struct it6505 *it6505, const int *int_status)
{
struct device *dev = it6505->dev;
+ int reg_0d, reg_int03;
- DRM_DEV_DEBUG_DRIVER(dev, "IO latch fifo overflow interrupt");
- it6505->auto_train_retry = AUTO_TRAIN_RETRY;
- flush_work(&it6505->link_works);
- it6505_stop_hdcp(it6505);
- it6505_video_reset(it6505);
-}
+ /*
+ * When video SCDT change with video not stable,
+ * Or video FIFO error, need video reset
+ */
-static bool it6505_test_bit(unsigned int bit, const unsigned int *addr)
-{
- return 1 & (addr[bit / BITS_PER_BYTE] >> (bit % BITS_PER_BYTE));
+ if ((!it6505_get_video_status(it6505) &&
+ (it6505_test_bit(INT_SCDT_CHANGE, (unsigned int *)int_status))) ||
+ (it6505_test_bit(BIT_INT_IO_FIFO_OVERFLOW,
+ (unsigned int *)int_status)) ||
+ (it6505_test_bit(BIT_INT_VID_FIFO_ERROR,
+ (unsigned int *)int_status))) {
+ it6505->auto_train_retry = AUTO_TRAIN_RETRY;
+ flush_work(&it6505->link_works);
+ it6505_stop_hdcp(it6505);
+ it6505_video_reset(it6505);
+
+ usleep_range(10000, 11000);
+
+ /*
+ * Clear FIFO error IRQ to prevent fifo error -> reset loop
+ * HW will trigger SCDT change IRQ again when video stable
+ */
+
+ reg_int03 = it6505_read(it6505, INT_STATUS_03);
+ reg_0d = it6505_read(it6505, REG_SYSTEM_STS);
+
+ reg_int03 &= (BIT(INT_VID_FIFO_ERROR) | BIT(INT_IO_LATCH_FIFO_OVERFLOW));
+ it6505_write(it6505, INT_STATUS_03, reg_int03);
+
+ DRM_DEV_DEBUG_DRIVER(dev, "reg08 = 0x%02x", reg_int03);
+ DRM_DEV_DEBUG_DRIVER(dev, "reg0D = 0x%02x", reg_0d);
+
+ return;
+ }
+
+ if (it6505_test_bit(INT_SCDT_CHANGE, (unsigned int *)int_status))
+ it6505_irq_scdt(it6505);
}
static irqreturn_t it6505_int_threaded_handler(int unused, void *data)
@@ -2508,15 +2535,12 @@ static irqreturn_t it6505_int_threaded_handler(int unused, void *data)
} irq_vec[] = {
{ BIT_INT_HPD, it6505_irq_hpd },
{ BIT_INT_HPD_IRQ, it6505_irq_hpd_irq },
- { BIT_INT_SCDT, it6505_irq_scdt },
{ BIT_INT_HDCP_FAIL, it6505_irq_hdcp_fail },
{ BIT_INT_HDCP_DONE, it6505_irq_hdcp_done },
{ BIT_INT_AUX_CMD_FAIL, it6505_irq_aux_cmd_fail },
{ BIT_INT_HDCP_KSV_CHECK, it6505_irq_hdcp_ksv_check },
{ BIT_INT_AUDIO_FIFO_ERROR, it6505_irq_audio_fifo_error },
{ BIT_INT_LINK_TRAIN_FAIL, it6505_irq_link_train_fail },
- { BIT_INT_VID_FIFO_ERROR, it6505_irq_video_fifo_error },
- { BIT_INT_IO_FIFO_OVERFLOW, it6505_irq_io_latch_fifo_overflow },
};
int int_status[3], i;
@@ -2546,6 +2570,7 @@ static irqreturn_t it6505_int_threaded_handler(int unused, void *data)
if (it6505_test_bit(irq_vec[i].bit, (unsigned int *)int_status))
irq_vec[i].handler(it6505);
}
+ it6505_irq_video_handler(it6505, (unsigned int *)int_status);
}
pm_runtime_put_sync(dev);
@@ -2882,11 +2907,6 @@ static int it6505_bridge_attach(struct drm_bridge *bridge,
return -EINVAL;
}
- if (!bridge->encoder) {
- dev_err(dev, "Parent encoder object not found");
- return -ENODEV;
- }
-
/* Register aux channel */
it6505->aux.drm_dev = bridge->dev;
diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
index ab702471f3ab..f864c033ba81 100644
--- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
+++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
@@ -337,11 +337,6 @@ static int lt9611uxc_connector_init(struct drm_bridge *bridge, struct lt9611uxc
{
int ret;
- if (!bridge->encoder) {
- DRM_ERROR("Parent encoder object not found");
- return -ENODEV;
- }
-
lt9611uxc->connector.polled = DRM_CONNECTOR_POLL_HPD;
drm_connector_helper_add(&lt9611uxc->connector,
diff --git a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
index 4480523244e4..37f1acf5c0f8 100644
--- a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
+++ b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
@@ -165,11 +165,6 @@ static int ge_b850v3_lvds_create_connector(struct drm_bridge *bridge)
struct drm_connector *connector = &ge_b850v3_lvds_ptr->connector;
int ret;
- if (!bridge->encoder) {
- DRM_ERROR("Parent encoder object not found");
- return -ENODEV;
- }
-
connector->polled = DRM_CONNECTOR_POLL_HPD;
drm_connector_helper_add(connector,
diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c
index ed93fd4c3265..e77aab965fcf 100644
--- a/drivers/gpu/drm/bridge/nxp-ptn3460.c
+++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c
@@ -229,11 +229,6 @@ static int ptn3460_bridge_attach(struct drm_bridge *bridge,
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
return 0;
- if (!bridge->encoder) {
- DRM_ERROR("Parent encoder object not found");
- return -ENODEV;
- }
-
ptn_bridge->connector.polled = DRM_CONNECTOR_POLL_HPD;
ret = drm_connector_init(bridge->dev, &ptn_bridge->connector,
&ptn3460_connector_funcs, DRM_MODE_CONNECTOR_LVDS);
diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
index 32506524d9a2..56c40b516a8f 100644
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -67,11 +67,6 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
return 0;
- if (!bridge->encoder) {
- DRM_ERROR("Missing encoder\n");
- return -ENODEV;
- }
-
drm_connector_helper_add(connector,
&panel_bridge_connector_helper_funcs);
diff --git a/drivers/gpu/drm/bridge/simple-bridge.c b/drivers/gpu/drm/bridge/simple-bridge.c
index 5813a2c4fc5e..2ca89f313cd1 100644
--- a/drivers/gpu/drm/bridge/simple-bridge.c
+++ b/drivers/gpu/drm/bridge/simple-bridge.c
@@ -116,11 +116,6 @@ static int simple_bridge_attach(struct drm_bridge *bridge,
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
return 0;
- if (!bridge->encoder) {
- DRM_ERROR("Missing encoder\n");
- return -ENODEV;
- }
-
drm_connector_helper_add(&sbridge->connector,
&simple_bridge_con_helper_funcs);
ret = drm_connector_init_with_ddc(bridge->dev, &sbridge->connector,
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index 824fb3c65742..c4e9d96933dc 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -1071,11 +1071,6 @@ static int dw_mipi_dsi_bridge_attach(struct drm_bridge *bridge,
{
struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
- if (!bridge->encoder) {
- DRM_ERROR("Parent encoder object not found\n");
- return -ENODEV;
- }
-
/* Set the encoder type as caller does not know it */
bridge->encoder->encoder_type = DRM_MODE_ENCODER_DSI;
diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c
index 166f9a3e9622..fe2b93546eae 100644
--- a/drivers/gpu/drm/bridge/tc358767.c
+++ b/drivers/gpu/drm/bridge/tc358767.c
@@ -382,6 +382,9 @@ struct tc_data {
/* HPD pin number (0 or 1) or -ENODEV */
int hpd_pin;
+
+ /* Number of pixels to subtract from a line due to pixel clock delta */
+ u32 line_pixel_subtract;
};
static inline struct tc_data *aux_to_tc(struct drm_dp_aux *a)
@@ -577,6 +580,11 @@ static int tc_pllupdate(struct tc_data *tc, unsigned int pllctrl)
return 0;
}
+static u32 div64_round_up(u64 v, u32 d)
+{
+ return div_u64(v + d - 1, d);
+}
+
static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock)
{
int ret;
@@ -658,8 +666,11 @@ static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock)
return -EINVAL;
}
- dev_dbg(tc->dev, "PLL: got %d, delta %d\n", best_pixelclock,
- best_delta);
+ tc->line_pixel_subtract = tc->mode.htotal -
+ div64_round_up(tc->mode.htotal * (u64)best_pixelclock, pixelclock);
+
+ dev_dbg(tc->dev, "PLL: got %d, delta %d (subtract %d px)\n", best_pixelclock,
+ best_delta, tc->line_pixel_subtract);
dev_dbg(tc->dev, "PLL: %d / %d / %d * %d / %d\n", refclk,
ext_div[best_pre], best_div, best_mul, ext_div[best_post]);
@@ -885,6 +896,12 @@ static int tc_set_common_video_mode(struct tc_data *tc,
upper_margin, lower_margin, vsync_len);
dev_dbg(tc->dev, "total: %dx%d\n", mode->htotal, mode->vtotal);
+ if (right_margin > tc->line_pixel_subtract) {
+ right_margin -= tc->line_pixel_subtract;
+ } else {
+ dev_err(tc->dev, "Bridge pixel clock too slow for mode\n");
+ right_margin = 0;
+ }
/*
* LCD Ctl Frame Size
@@ -894,7 +911,7 @@ static int tc_set_common_video_mode(struct tc_data *tc,
*/
ret = regmap_write(tc->regmap, VPCTRL0,
FIELD_PREP(VSDELAY, right_margin + 10) |
- OPXLFMT_RGB888 | FRMSYNC_DISABLED | MSF_DISABLED);
+ OPXLFMT_RGB888 | FRMSYNC_ENABLED | MSF_DISABLED);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c
index c7bef5c23927..b1b1e4d5a24a 100644
--- a/drivers/gpu/drm/bridge/ti-tfp410.c
+++ b/drivers/gpu/drm/bridge/ti-tfp410.c
@@ -133,11 +133,6 @@ static int tfp410_attach(struct drm_bridge *bridge,
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
return 0;
- if (!bridge->encoder) {
- dev_err(dvi->dev, "Missing encoder\n");
- return -ENODEV;
- }
-
if (dvi->next_bridge->ops & DRM_BRIDGE_OP_DETECT)
dvi->connector.polled = DRM_CONNECTOR_POLL_HPD;
else
diff --git a/drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt b/drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt
index 44a5c62dedad..b14d4e884971 100644
--- a/drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt
@@ -1,17 +1,6 @@
kms_3d,Fail
kms_addfb_basic@addfb25-bad-modifier,Fail
-kms_cursor_legacy@all-pipes-forked-bo,Fail
-kms_cursor_legacy@all-pipes-forked-move,Fail
-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@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_cursor_legacy@torture-bo,Fail
kms_force_connector_basic@force-edid,Fail
kms_hdmi_inject@inject-4k,Fail
kms_selftest@drm_format,Timeout
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 28abe9aa99ca..584d109330ab 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -353,13 +353,8 @@ err_reset_bridge:
bridge->encoder = NULL;
list_del(&bridge->chain_node);
-#ifdef CONFIG_OF
DRM_ERROR("failed to attach bridge %pOF to encoder %s: %d\n",
bridge->of_node, encoder->name, ret);
-#else
- DRM_ERROR("failed to attach bridge to encoder %s: %d\n",
- encoder->name, ret);
-#endif
return ret;
}
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
index 25aaae937ceb..20e9d7b206a2 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -303,6 +303,8 @@ const u8 *drm_edid_find_extension(const struct drm_edid *drm_edid,
int ext_id, int *ext_index);
void drm_edid_cta_sad_get(const struct cea_sad *cta_sad, u8 *sad);
void drm_edid_cta_sad_set(struct cea_sad *cta_sad, const u8 *sad);
+ssize_t drm_edid_connector_property_show(struct drm_connector *connector,
+ char *buf, loff_t off, size_t count);
/* drm_edid_load.c */
#ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE
diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c
index 08fcefd804bc..28a471fe4bc8 100644
--- a/drivers/gpu/drm/drm_debugfs.c
+++ b/drivers/gpu/drm/drm_debugfs.c
@@ -597,10 +597,10 @@ static int bridges_show(struct seq_file *m, void *data)
drm_printf(&p, "\ttype: [%d] %s\n",
bridge->type,
drm_get_connector_type_name(bridge->type));
-#ifdef CONFIG_OF
+
if (bridge->of_node)
drm_printf(&p, "\tOF: %pOFfc\n", bridge->of_node);
-#endif
+
drm_printf(&p, "\tops: [0x%x]", bridge->ops);
if (bridge->ops & DRM_BRIDGE_OP_DETECT)
drm_puts(&p, " detect");
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 535b624d4c9d..93543071a500 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -346,7 +346,7 @@ void drm_minor_release(struct drm_minor *minor)
* if (ret)
* return ret;
*
- * drm_fbdev_generic_setup(drm, 32);
+ * drm_fbdev_{...}_setup(drm, 32);
*
* return 0;
* }
@@ -947,9 +947,9 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
}
drm_panic_register(dev);
- DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
+ DRM_INFO("Initialized %s %d.%d.%d for %s on minor %d\n",
driver->name, driver->major, driver->minor,
- driver->patchlevel, driver->date,
+ driver->patchlevel,
dev->dev ? dev_name(dev->dev) : "virtual device",
dev->primary ? dev->primary->index : dev->accel->index);
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 4f54c91b31b2..f68a41eeb1fa 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2465,34 +2465,6 @@ fail:
}
/**
- * drm_do_get_edid - get EDID data using a custom EDID block read function
- * @connector: connector we're probing
- * @read_block: EDID block read function
- * @context: private data passed to the block read function
- *
- * When the I2C adapter connected to the DDC bus is hidden behind a device that
- * exposes a different interface to read EDID blocks this function can be used
- * to get EDID data using a custom block read function.
- *
- * As in the general case the DDC bus is accessible by the kernel at the I2C
- * level, drivers must make all reasonable efforts to expose it as an I2C
- * adapter and use drm_get_edid() instead of abusing this function.
- *
- * The EDID may be overridden using debugfs override_edid or firmware EDID
- * (drm_edid_load_firmware() and drm.edid_firmware parameter), in this priority
- * order. Having either of them bypasses actual EDID reads.
- *
- * Return: Pointer to valid EDID or NULL if we couldn't find any.
- */
-struct edid *drm_do_get_edid(struct drm_connector *connector,
- read_block_fn read_block,
- void *context)
-{
- return _drm_do_get_edid(connector, read_block, context, NULL);
-}
-EXPORT_SYMBOL_GPL(drm_do_get_edid);
-
-/**
* drm_edid_raw - Get a pointer to the raw EDID data.
* @drm_edid: drm_edid container
*
@@ -6969,6 +6941,39 @@ out:
return ret;
}
+/* For sysfs edid show implementation */
+ssize_t drm_edid_connector_property_show(struct drm_connector *connector,
+ char *buf, loff_t off, size_t count)
+{
+ const void *edid;
+ size_t size;
+ ssize_t ret = 0;
+
+ mutex_lock(&connector->dev->mode_config.mutex);
+
+ if (!connector->edid_blob_ptr)
+ goto unlock;
+
+ edid = connector->edid_blob_ptr->data;
+ size = connector->edid_blob_ptr->length;
+ if (!edid)
+ goto unlock;
+
+ if (off >= size)
+ goto unlock;
+
+ if (off + count > size)
+ count = size - off;
+
+ memcpy(buf, edid + off, count);
+
+ ret = count;
+unlock:
+ mutex_unlock(&connector->dev->mode_config.mutex);
+
+ return ret;
+}
+
/**
* drm_edid_connector_update - Update connector information from EDID
* @connector: Connector
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index d612133e2cf7..e2e19f49342e 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -85,12 +85,8 @@ static DEFINE_MUTEX(kernel_fb_helper_lock);
* The fb helper functions are useful to provide an fbdev on top of a drm kernel
* mode setting driver. They can be used mostly independently from the crtc
* helper functions used by many drivers to implement the kernel mode setting
- * interfaces.
- *
- * Drivers that support a dumb buffer with a virtual address and mmap support,
- * should try out the generic fbdev emulation using drm_fbdev_generic_setup().
- * It will automatically set up deferred I/O if the driver requires a shadow
- * buffer.
+ * interfaces. Drivers that use one of the shared memory managers, TTM, SHMEM,
+ * DMA, should instead use the corresponding fbdev emulation.
*
* Existing fbdev implementations should restore the fbdev console by using
* drm_fb_helper_lastclose() as their &drm_driver.lastclose callback.
@@ -126,9 +122,6 @@ static DEFINE_MUTEX(kernel_fb_helper_lock);
* atomic context. If drm_fb_helper_deferred_io() is used as the deferred_io
* callback it will also schedule dirty_work with the damage collected from the
* mmap page writes.
- *
- * Deferred I/O is not compatible with SHMEM. Such drivers should request an
- * fbdev shadow buffer and call drm_fbdev_generic_setup() instead.
*/
static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc)
diff --git a/drivers/gpu/drm/drm_fbdev_dma.c b/drivers/gpu/drm/drm_fbdev_dma.c
index 6c9427bb4053..97ef6300d47e 100644
--- a/drivers/gpu/drm/drm_fbdev_dma.c
+++ b/drivers/gpu/drm/drm_fbdev_dma.c
@@ -4,6 +4,7 @@
#include <drm/drm_crtc_helper.h>
#include <drm/drm_drv.h>
+#include <drm/drm_fb_dma_helper.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_dma_helper.h>
@@ -35,6 +36,22 @@ static int drm_fbdev_dma_fb_release(struct fb_info *info, int user)
return 0;
}
+FB_GEN_DEFAULT_DEFERRED_DMAMEM_OPS(drm_fbdev_dma,
+ drm_fb_helper_damage_range,
+ drm_fb_helper_damage_area);
+
+static int drm_fbdev_dma_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+ struct drm_framebuffer *fb = fb_helper->fb;
+ struct drm_gem_dma_object *dma = drm_fb_dma_get_gem_obj(fb, 0);
+
+ if (!dma->map_noncoherent)
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+ return fb_deferred_io_mmap(info, vma);
+}
+
static void drm_fbdev_dma_fb_destroy(struct fb_info *info)
{
struct drm_fb_helper *fb_helper = info->par;
@@ -42,6 +59,7 @@ static void drm_fbdev_dma_fb_destroy(struct fb_info *info)
if (!fb_helper->dev)
return;
+ fb_deferred_io_cleanup(info);
drm_fb_helper_fini(fb_helper);
drm_client_buffer_vunmap(fb_helper->buffer);
@@ -51,20 +69,13 @@ static void drm_fbdev_dma_fb_destroy(struct fb_info *info)
kfree(fb_helper);
}
-static int drm_fbdev_dma_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
- struct drm_fb_helper *fb_helper = info->par;
-
- return drm_gem_prime_mmap(fb_helper->buffer->gem, vma);
-}
-
static const struct fb_ops drm_fbdev_dma_fb_ops = {
.owner = THIS_MODULE,
.fb_open = drm_fbdev_dma_fb_open,
.fb_release = drm_fbdev_dma_fb_release,
- __FB_DEFAULT_DMAMEM_OPS_RDWR,
+ __FB_DEFAULT_DEFERRED_OPS_RDWR(drm_fbdev_dma),
DRM_FB_HELPER_DEFAULT_OPS,
- __FB_DEFAULT_DMAMEM_OPS_DRAW,
+ __FB_DEFAULT_DEFERRED_OPS_DRAW(drm_fbdev_dma),
.fb_mmap = drm_fbdev_dma_fb_mmap,
.fb_destroy = drm_fbdev_dma_fb_destroy,
};
@@ -98,10 +109,6 @@ static int drm_fbdev_dma_helper_fb_probe(struct drm_fb_helper *fb_helper,
dma_obj = to_drm_gem_dma_obj(buffer->gem);
fb = buffer->fb;
- if (drm_WARN_ON(dev, fb->funcs->dirty)) {
- ret = -ENODEV; /* damage handling not supported; use generic emulation */
- goto err_drm_client_buffer_delete;
- }
ret = drm_client_buffer_vmap(buffer, &map);
if (ret) {
@@ -112,7 +119,7 @@ static int drm_fbdev_dma_helper_fb_probe(struct drm_fb_helper *fb_helper,
}
fb_helper->buffer = buffer;
- fb_helper->fb = buffer->fb;
+ fb_helper->fb = fb;
info = drm_fb_helper_alloc_info(fb_helper);
if (IS_ERR(info)) {
@@ -133,8 +140,19 @@ static int drm_fbdev_dma_helper_fb_probe(struct drm_fb_helper *fb_helper,
info->fix.smem_start = page_to_phys(virt_to_page(info->screen_buffer));
info->fix.smem_len = info->screen_size;
+ /* deferred I/O */
+ fb_helper->fbdefio.delay = HZ / 20;
+ fb_helper->fbdefio.deferred_io = drm_fb_helper_deferred_io;
+
+ info->fbdefio = &fb_helper->fbdefio;
+ ret = fb_deferred_io_init(info);
+ if (ret)
+ goto err_drm_fb_helper_release_info;
+
return 0;
+err_drm_fb_helper_release_info:
+ drm_fb_helper_release_info(fb_helper);
err_drm_client_buffer_vunmap:
fb_helper->fb = NULL;
fb_helper->buffer = NULL;
@@ -144,8 +162,28 @@ err_drm_client_buffer_delete:
return ret;
}
+static int drm_fbdev_dma_helper_fb_dirty(struct drm_fb_helper *helper,
+ struct drm_clip_rect *clip)
+{
+ struct drm_device *dev = helper->dev;
+ int ret;
+
+ /* Call damage handlers only if necessary */
+ if (!(clip->x1 < clip->x2 && clip->y1 < clip->y2))
+ return 0;
+
+ if (helper->fb->funcs->dirty) {
+ ret = helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, clip, 1);
+ if (drm_WARN_ONCE(dev, ret, "Dirty helper failed: ret=%d\n", ret))
+ return ret;
+ }
+
+ return 0;
+}
+
static const struct drm_fb_helper_funcs drm_fbdev_dma_helper_funcs = {
.fb_probe = drm_fbdev_dma_helper_fb_probe,
+ .fb_dirty = drm_fbdev_dma_helper_fb_dirty,
};
/*
diff --git a/drivers/gpu/drm/drm_fbdev_shmem.c b/drivers/gpu/drm/drm_fbdev_shmem.c
new file mode 100644
index 000000000000..0c785007f11b
--- /dev/null
+++ b/drivers/gpu/drm/drm_fbdev_shmem.c
@@ -0,0 +1,317 @@
+// SPDX-License-Identifier: MIT
+
+#include <linux/fb.h>
+
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_framebuffer.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_gem_shmem_helper.h>
+
+#include <drm/drm_fbdev_shmem.h>
+
+/*
+ * struct fb_ops
+ */
+
+static int drm_fbdev_shmem_fb_open(struct fb_info *info, int user)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+
+ /* No need to take a ref for fbcon because it unbinds on unregister */
+ if (user && !try_module_get(fb_helper->dev->driver->fops->owner))
+ return -ENODEV;
+
+ return 0;
+}
+
+static int drm_fbdev_shmem_fb_release(struct fb_info *info, int user)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+
+ if (user)
+ module_put(fb_helper->dev->driver->fops->owner);
+
+ return 0;
+}
+
+FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(drm_fbdev_shmem,
+ drm_fb_helper_damage_range,
+ drm_fb_helper_damage_area);
+
+static int drm_fbdev_shmem_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+ struct drm_framebuffer *fb = fb_helper->fb;
+ struct drm_gem_object *obj = drm_gem_fb_get_obj(fb, 0);
+ struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
+
+ if (shmem->map_wc)
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+ return fb_deferred_io_mmap(info, vma);
+}
+
+static void drm_fbdev_shmem_fb_destroy(struct fb_info *info)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+
+ if (!fb_helper->dev)
+ return;
+
+ fb_deferred_io_cleanup(info);
+ drm_fb_helper_fini(fb_helper);
+
+ drm_client_buffer_vunmap(fb_helper->buffer);
+ drm_client_framebuffer_delete(fb_helper->buffer);
+ drm_client_release(&fb_helper->client);
+ drm_fb_helper_unprepare(fb_helper);
+ kfree(fb_helper);
+}
+
+static const struct fb_ops drm_fbdev_shmem_fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_open = drm_fbdev_shmem_fb_open,
+ .fb_release = drm_fbdev_shmem_fb_release,
+ __FB_DEFAULT_DEFERRED_OPS_RDWR(drm_fbdev_shmem),
+ DRM_FB_HELPER_DEFAULT_OPS,
+ __FB_DEFAULT_DEFERRED_OPS_DRAW(drm_fbdev_shmem),
+ .fb_mmap = drm_fbdev_shmem_fb_mmap,
+ .fb_destroy = drm_fbdev_shmem_fb_destroy,
+};
+
+static struct page *drm_fbdev_shmem_get_page(struct fb_info *info, unsigned long offset)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+ struct drm_framebuffer *fb = fb_helper->fb;
+ struct drm_gem_object *obj = drm_gem_fb_get_obj(fb, 0);
+ struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
+ unsigned int i = offset >> PAGE_SHIFT;
+ struct page *page;
+
+ if (fb_WARN_ON_ONCE(info, offset > obj->size))
+ return NULL;
+
+ page = shmem->pages[i]; // protected by active vmap
+ if (page)
+ get_page(page);
+ fb_WARN_ON_ONCE(info, !page);
+
+ return page;
+}
+
+/*
+ * struct drm_fb_helper
+ */
+
+static int drm_fbdev_shmem_helper_fb_probe(struct drm_fb_helper *fb_helper,
+ struct drm_fb_helper_surface_size *sizes)
+{
+ struct drm_client_dev *client = &fb_helper->client;
+ struct drm_device *dev = fb_helper->dev;
+ struct drm_client_buffer *buffer;
+ struct drm_gem_shmem_object *shmem;
+ struct drm_framebuffer *fb;
+ struct fb_info *info;
+ u32 format;
+ struct iosys_map map;
+ int ret;
+
+ drm_dbg_kms(dev, "surface width(%d), height(%d) and bpp(%d)\n",
+ sizes->surface_width, sizes->surface_height,
+ sizes->surface_bpp);
+
+ format = drm_driver_legacy_fb_format(dev, sizes->surface_bpp, sizes->surface_depth);
+ buffer = drm_client_framebuffer_create(client, sizes->surface_width,
+ sizes->surface_height, format);
+ if (IS_ERR(buffer))
+ return PTR_ERR(buffer);
+ shmem = to_drm_gem_shmem_obj(buffer->gem);
+
+ fb = buffer->fb;
+
+ ret = drm_client_buffer_vmap(buffer, &map);
+ if (ret) {
+ goto err_drm_client_buffer_delete;
+ } else if (drm_WARN_ON(dev, map.is_iomem)) {
+ ret = -ENODEV; /* I/O memory not supported; use generic emulation */
+ goto err_drm_client_buffer_delete;
+ }
+
+ fb_helper->buffer = buffer;
+ fb_helper->fb = fb;
+
+ info = drm_fb_helper_alloc_info(fb_helper);
+ if (IS_ERR(info)) {
+ ret = PTR_ERR(info);
+ goto err_drm_client_buffer_vunmap;
+ }
+
+ drm_fb_helper_fill_info(info, fb_helper, sizes);
+
+ info->fbops = &drm_fbdev_shmem_fb_ops;
+
+ /* screen */
+ info->flags |= FBINFO_VIRTFB; /* system memory */
+ if (!shmem->map_wc)
+ info->flags |= FBINFO_READS_FAST; /* signal caching */
+ info->screen_size = sizes->surface_height * fb->pitches[0];
+ info->screen_buffer = map.vaddr;
+ info->fix.smem_len = info->screen_size;
+
+ /* deferred I/O */
+ fb_helper->fbdefio.delay = HZ / 20;
+ fb_helper->fbdefio.get_page = drm_fbdev_shmem_get_page;
+ fb_helper->fbdefio.deferred_io = drm_fb_helper_deferred_io;
+
+ info->fbdefio = &fb_helper->fbdefio;
+ ret = fb_deferred_io_init(info);
+ if (ret)
+ goto err_drm_fb_helper_release_info;
+
+ return 0;
+
+err_drm_fb_helper_release_info:
+ drm_fb_helper_release_info(fb_helper);
+err_drm_client_buffer_vunmap:
+ fb_helper->fb = NULL;
+ fb_helper->buffer = NULL;
+ drm_client_buffer_vunmap(buffer);
+err_drm_client_buffer_delete:
+ drm_client_framebuffer_delete(buffer);
+ return ret;
+}
+
+static int drm_fbdev_shmem_helper_fb_dirty(struct drm_fb_helper *helper,
+ struct drm_clip_rect *clip)
+{
+ struct drm_device *dev = helper->dev;
+ int ret;
+
+ /* Call damage handlers only if necessary */
+ if (!(clip->x1 < clip->x2 && clip->y1 < clip->y2))
+ return 0;
+
+ if (helper->fb->funcs->dirty) {
+ ret = helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, clip, 1);
+ if (drm_WARN_ONCE(dev, ret, "Dirty helper failed: ret=%d\n", ret))
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct drm_fb_helper_funcs drm_fbdev_shmem_helper_funcs = {
+ .fb_probe = drm_fbdev_shmem_helper_fb_probe,
+ .fb_dirty = drm_fbdev_shmem_helper_fb_dirty,
+};
+
+/*
+ * struct drm_client_funcs
+ */
+
+static void drm_fbdev_shmem_client_unregister(struct drm_client_dev *client)
+{
+ struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
+
+ if (fb_helper->info) {
+ drm_fb_helper_unregister_info(fb_helper);
+ } else {
+ drm_client_release(&fb_helper->client);
+ drm_fb_helper_unprepare(fb_helper);
+ kfree(fb_helper);
+ }
+}
+
+static int drm_fbdev_shmem_client_restore(struct drm_client_dev *client)
+{
+ drm_fb_helper_lastclose(client->dev);
+
+ return 0;
+}
+
+static int drm_fbdev_shmem_client_hotplug(struct drm_client_dev *client)
+{
+ struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
+ struct drm_device *dev = client->dev;
+ int ret;
+
+ if (dev->fb_helper)
+ return drm_fb_helper_hotplug_event(dev->fb_helper);
+
+ ret = drm_fb_helper_init(dev, fb_helper);
+ if (ret)
+ goto err_drm_err;
+
+ if (!drm_drv_uses_atomic_modeset(dev))
+ drm_helper_disable_unused_functions(dev);
+
+ ret = drm_fb_helper_initial_config(fb_helper);
+ if (ret)
+ goto err_drm_fb_helper_fini;
+
+ return 0;
+
+err_drm_fb_helper_fini:
+ drm_fb_helper_fini(fb_helper);
+err_drm_err:
+ drm_err(dev, "fbdev-shmem: Failed to setup emulation (ret=%d)\n", ret);
+ return ret;
+}
+
+static const struct drm_client_funcs drm_fbdev_shmem_client_funcs = {
+ .owner = THIS_MODULE,
+ .unregister = drm_fbdev_shmem_client_unregister,
+ .restore = drm_fbdev_shmem_client_restore,
+ .hotplug = drm_fbdev_shmem_client_hotplug,
+};
+
+/**
+ * drm_fbdev_shmem_setup() - Setup fbdev emulation for GEM SHMEM helpers
+ * @dev: DRM device
+ * @preferred_bpp: Preferred bits per pixel for the device.
+ * 32 is used if this is zero.
+ *
+ * This function sets up fbdev emulation for GEM DMA drivers that support
+ * dumb buffers with a virtual address and that can be mmap'ed.
+ * drm_fbdev_shmem_setup() shall be called after the DRM driver registered
+ * the new DRM device with drm_dev_register().
+ *
+ * Restore, hotplug events and teardown are all taken care of. Drivers that do
+ * suspend/resume need to call drm_fb_helper_set_suspend_unlocked() themselves.
+ * Simple drivers might use drm_mode_config_helper_suspend().
+ *
+ * This function is safe to call even when there are no connectors present.
+ * Setup will be retried on the next hotplug event.
+ *
+ * The fbdev is destroyed by drm_dev_unregister().
+ */
+void drm_fbdev_shmem_setup(struct drm_device *dev, unsigned int preferred_bpp)
+{
+ struct drm_fb_helper *fb_helper;
+ int ret;
+
+ drm_WARN(dev, !dev->registered, "Device has not been registered.\n");
+ drm_WARN(dev, dev->fb_helper, "fb_helper is already set!\n");
+
+ fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL);
+ if (!fb_helper)
+ return;
+ drm_fb_helper_prepare(dev, fb_helper, preferred_bpp, &drm_fbdev_shmem_helper_funcs);
+
+ ret = drm_client_init(dev, &fb_helper->client, "fbdev", &drm_fbdev_shmem_client_funcs);
+ if (ret) {
+ drm_err(dev, "Failed to register client: %d\n", ret);
+ goto err_drm_client_init;
+ }
+
+ drm_client_register(&fb_helper->client);
+
+ return;
+
+err_drm_client_init:
+ drm_fb_helper_unprepare(fb_helper);
+ kfree(fb_helper);
+}
+EXPORT_SYMBOL(drm_fbdev_shmem_setup);
diff --git a/drivers/gpu/drm/drm_fbdev_generic.c b/drivers/gpu/drm/drm_fbdev_ttm.c
index 97e579c33d84..bb7898cd7dc6 100644
--- a/drivers/gpu/drm/drm_fbdev_generic.c
+++ b/drivers/gpu/drm/drm_fbdev_ttm.c
@@ -10,10 +10,10 @@
#include <drm/drm_gem.h>
#include <drm/drm_print.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_ttm.h>
/* @user: 1=userspace, 0=fbcon */
-static int drm_fbdev_generic_fb_open(struct fb_info *info, int user)
+static int drm_fbdev_ttm_fb_open(struct fb_info *info, int user)
{
struct drm_fb_helper *fb_helper = info->par;
@@ -24,7 +24,7 @@ static int drm_fbdev_generic_fb_open(struct fb_info *info, int user)
return 0;
}
-static int drm_fbdev_generic_fb_release(struct fb_info *info, int user)
+static int drm_fbdev_ttm_fb_release(struct fb_info *info, int user)
{
struct drm_fb_helper *fb_helper = info->par;
@@ -34,11 +34,11 @@ static int drm_fbdev_generic_fb_release(struct fb_info *info, int user)
return 0;
}
-FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(drm_fbdev_generic,
+FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(drm_fbdev_ttm,
drm_fb_helper_damage_range,
drm_fb_helper_damage_area);
-static void drm_fbdev_generic_fb_destroy(struct fb_info *info)
+static void drm_fbdev_ttm_fb_destroy(struct fb_info *info)
{
struct drm_fb_helper *fb_helper = info->par;
void *shadow = info->screen_buffer;
@@ -56,19 +56,19 @@ static void drm_fbdev_generic_fb_destroy(struct fb_info *info)
kfree(fb_helper);
}
-static const struct fb_ops drm_fbdev_generic_fb_ops = {
+static const struct fb_ops drm_fbdev_ttm_fb_ops = {
.owner = THIS_MODULE,
- .fb_open = drm_fbdev_generic_fb_open,
- .fb_release = drm_fbdev_generic_fb_release,
- FB_DEFAULT_DEFERRED_OPS(drm_fbdev_generic),
+ .fb_open = drm_fbdev_ttm_fb_open,
+ .fb_release = drm_fbdev_ttm_fb_release,
+ FB_DEFAULT_DEFERRED_OPS(drm_fbdev_ttm),
DRM_FB_HELPER_DEFAULT_OPS,
- .fb_destroy = drm_fbdev_generic_fb_destroy,
+ .fb_destroy = drm_fbdev_ttm_fb_destroy,
};
/*
* This function uses the client API to create a framebuffer backed by a dumb buffer.
*/
-static int drm_fbdev_generic_helper_fb_probe(struct drm_fb_helper *fb_helper,
+static int drm_fbdev_ttm_helper_fb_probe(struct drm_fb_helper *fb_helper,
struct drm_fb_helper_surface_size *sizes)
{
struct drm_client_dev *client = &fb_helper->client;
@@ -108,7 +108,7 @@ static int drm_fbdev_generic_helper_fb_probe(struct drm_fb_helper *fb_helper,
drm_fb_helper_fill_info(info, fb_helper, sizes);
- info->fbops = &drm_fbdev_generic_fb_ops;
+ info->fbops = &drm_fbdev_ttm_fb_ops;
/* screen */
info->flags |= FBINFO_VIRTFB | FBINFO_READS_FAST;
@@ -137,9 +137,9 @@ err_drm_client_framebuffer_delete:
return ret;
}
-static void drm_fbdev_generic_damage_blit_real(struct drm_fb_helper *fb_helper,
- struct drm_clip_rect *clip,
- struct iosys_map *dst)
+static void drm_fbdev_ttm_damage_blit_real(struct drm_fb_helper *fb_helper,
+ struct drm_clip_rect *clip,
+ struct iosys_map *dst)
{
struct drm_framebuffer *fb = fb_helper->fb;
size_t offset = clip->y1 * fb->pitches[0];
@@ -176,8 +176,8 @@ static void drm_fbdev_generic_damage_blit_real(struct drm_fb_helper *fb_helper,
}
}
-static int drm_fbdev_generic_damage_blit(struct drm_fb_helper *fb_helper,
- struct drm_clip_rect *clip)
+static int drm_fbdev_ttm_damage_blit(struct drm_fb_helper *fb_helper,
+ struct drm_clip_rect *clip)
{
struct drm_client_buffer *buffer = fb_helper->buffer;
struct iosys_map map, dst;
@@ -201,7 +201,7 @@ static int drm_fbdev_generic_damage_blit(struct drm_fb_helper *fb_helper,
goto out;
dst = map;
- drm_fbdev_generic_damage_blit_real(fb_helper, clip, &dst);
+ drm_fbdev_ttm_damage_blit_real(fb_helper, clip, &dst);
drm_client_buffer_vunmap_local(buffer);
@@ -211,8 +211,8 @@ out:
return ret;
}
-static int drm_fbdev_generic_helper_fb_dirty(struct drm_fb_helper *helper,
- struct drm_clip_rect *clip)
+static int drm_fbdev_ttm_helper_fb_dirty(struct drm_fb_helper *helper,
+ struct drm_clip_rect *clip)
{
struct drm_device *dev = helper->dev;
int ret;
@@ -221,7 +221,7 @@ static int drm_fbdev_generic_helper_fb_dirty(struct drm_fb_helper *helper,
if (!(clip->x1 < clip->x2 && clip->y1 < clip->y2))
return 0;
- ret = drm_fbdev_generic_damage_blit(helper, clip);
+ ret = drm_fbdev_ttm_damage_blit(helper, clip);
if (drm_WARN_ONCE(dev, ret, "Damage blitter failed: ret=%d\n", ret))
return ret;
@@ -234,12 +234,12 @@ static int drm_fbdev_generic_helper_fb_dirty(struct drm_fb_helper *helper,
return 0;
}
-static const struct drm_fb_helper_funcs drm_fbdev_generic_helper_funcs = {
- .fb_probe = drm_fbdev_generic_helper_fb_probe,
- .fb_dirty = drm_fbdev_generic_helper_fb_dirty,
+static const struct drm_fb_helper_funcs drm_fbdev_ttm_helper_funcs = {
+ .fb_probe = drm_fbdev_ttm_helper_fb_probe,
+ .fb_dirty = drm_fbdev_ttm_helper_fb_dirty,
};
-static void drm_fbdev_generic_client_unregister(struct drm_client_dev *client)
+static void drm_fbdev_ttm_client_unregister(struct drm_client_dev *client)
{
struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
@@ -252,14 +252,14 @@ static void drm_fbdev_generic_client_unregister(struct drm_client_dev *client)
}
}
-static int drm_fbdev_generic_client_restore(struct drm_client_dev *client)
+static int drm_fbdev_ttm_client_restore(struct drm_client_dev *client)
{
drm_fb_helper_lastclose(client->dev);
return 0;
}
-static int drm_fbdev_generic_client_hotplug(struct drm_client_dev *client)
+static int drm_fbdev_ttm_client_hotplug(struct drm_client_dev *client)
{
struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
struct drm_device *dev = client->dev;
@@ -284,32 +284,32 @@ static int drm_fbdev_generic_client_hotplug(struct drm_client_dev *client)
err_drm_fb_helper_fini:
drm_fb_helper_fini(fb_helper);
err_drm_err:
- drm_err(dev, "fbdev: Failed to setup generic emulation (ret=%d)\n", ret);
+ drm_err(dev, "fbdev: Failed to setup emulation (ret=%d)\n", ret);
return ret;
}
-static const struct drm_client_funcs drm_fbdev_generic_client_funcs = {
+static const struct drm_client_funcs drm_fbdev_ttm_client_funcs = {
.owner = THIS_MODULE,
- .unregister = drm_fbdev_generic_client_unregister,
- .restore = drm_fbdev_generic_client_restore,
- .hotplug = drm_fbdev_generic_client_hotplug,
+ .unregister = drm_fbdev_ttm_client_unregister,
+ .restore = drm_fbdev_ttm_client_restore,
+ .hotplug = drm_fbdev_ttm_client_hotplug,
};
/**
- * drm_fbdev_generic_setup() - Setup generic fbdev emulation
+ * drm_fbdev_ttm_setup() - Setup fbdev emulation for TTM-based drivers
* @dev: DRM device
* @preferred_bpp: Preferred bits per pixel for the device.
*
- * This function sets up generic fbdev emulation for drivers that supports
+ * This function sets up fbdev emulation for TTM-based drivers that support
* dumb buffers with a virtual address and that can be mmap'ed.
- * drm_fbdev_generic_setup() shall be called after the DRM driver registered
+ * drm_fbdev_ttm_setup() shall be called after the DRM driver registered
* the new DRM device with drm_dev_register().
*
* Restore, hotplug events and teardown are all taken care of. Drivers that do
* suspend/resume need to call drm_fb_helper_set_suspend_unlocked() themselves.
* Simple drivers might use drm_mode_config_helper_suspend().
*
- * In order to provide fixed mmap-able memory ranges, generic fbdev emulation
+ * In order to provide fixed mmap-able memory ranges, fbdev emulation
* uses a shadow buffer in system memory. The implementation blits the shadow
* fbdev buffer onto the real buffer in regular intervals.
*
@@ -318,7 +318,7 @@ static const struct drm_client_funcs drm_fbdev_generic_client_funcs = {
*
* The fbdev is destroyed by drm_dev_unregister().
*/
-void drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
+void drm_fbdev_ttm_setup(struct drm_device *dev, unsigned int preferred_bpp)
{
struct drm_fb_helper *fb_helper;
int ret;
@@ -329,9 +329,9 @@ void drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL);
if (!fb_helper)
return;
- drm_fb_helper_prepare(dev, fb_helper, preferred_bpp, &drm_fbdev_generic_helper_funcs);
+ drm_fb_helper_prepare(dev, fb_helper, preferred_bpp, &drm_fbdev_ttm_helper_funcs);
- ret = drm_client_init(dev, &fb_helper->client, "fbdev", &drm_fbdev_generic_client_funcs);
+ ret = drm_client_init(dev, &fb_helper->client, "fbdev", &drm_fbdev_ttm_client_funcs);
if (ret) {
drm_err(dev, "Failed to register client: %d\n", ret);
goto err_drm_client_init;
@@ -346,4 +346,4 @@ err_drm_client_init:
kfree(fb_helper);
return;
}
-EXPORT_SYMBOL(drm_fbdev_generic_setup);
+EXPORT_SYMBOL(drm_fbdev_ttm_setup);
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index e368fc084c77..51f39912866f 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -529,9 +529,10 @@ int drm_version(struct drm_device *dev, void *data,
version->version_patchlevel = dev->driver->patchlevel;
err = drm_copy_field(version->name, &version->name_len,
dev->driver->name);
+
+ /* Driver date is deprecated. Userspace expects a non-empty string. */
if (!err)
- err = drm_copy_field(version->date, &version->date_len,
- dev->driver->date);
+ err = drm_copy_field(version->date, &version->date_len, "0");
if (!err)
err = drm_copy_field(version->desc, &version->desc_len,
dev->driver->desc);
diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index 795001bb7ff1..a471c46f5ca6 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -765,6 +765,62 @@ ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload,
EXPORT_SYMBOL(mipi_dsi_generic_write);
/**
+ * mipi_dsi_generic_write_chatty() - mipi_dsi_generic_write() w/ an error log
+ * @dsi: DSI peripheral device
+ * @payload: buffer containing the payload
+ * @size: size of payload buffer
+ *
+ * Like mipi_dsi_generic_write() but includes a dev_err()
+ * call for you and returns 0 upon success, not the number of bytes sent.
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_generic_write_chatty(struct mipi_dsi_device *dsi,
+ const void *payload, size_t size)
+{
+ struct device *dev = &dsi->dev;
+ ssize_t ret;
+
+ ret = mipi_dsi_generic_write(dsi, payload, size);
+ if (ret < 0) {
+ dev_err(dev, "sending generic data %*ph failed: %zd\n",
+ (int)size, payload, ret);
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(mipi_dsi_generic_write_chatty);
+
+/**
+ * mipi_dsi_generic_write_multi() - mipi_dsi_generic_write_chatty() w/ accum_err
+ * @ctx: Context for multiple DSI transactions
+ * @payload: buffer containing the payload
+ * @size: size of payload buffer
+ *
+ * Like mipi_dsi_generic_write_chatty() but deals with errors in a way that
+ * makes it convenient to make several calls in a row.
+ */
+void mipi_dsi_generic_write_multi(struct mipi_dsi_multi_context *ctx,
+ const void *payload, size_t size)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ ssize_t ret;
+
+ if (ctx->accum_err)
+ return;
+
+ ret = mipi_dsi_generic_write(dsi, payload, size);
+ if (ret < 0) {
+ ctx->accum_err = ret;
+ dev_err(dev, "sending generic data %*ph failed: %d\n",
+ (int)size, payload, ctx->accum_err);
+ }
+}
+EXPORT_SYMBOL(mipi_dsi_generic_write_multi);
+
+/**
* mipi_dsi_generic_read() - receive data using a generic read packet
* @dsi: DSI peripheral device
* @params: buffer containing the request parameters
@@ -853,6 +909,62 @@ ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi,
EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer);
/**
+ * mipi_dsi_dcs_write_buffer_chatty - mipi_dsi_dcs_write_buffer() w/ an error log
+ * @dsi: DSI peripheral device
+ * @data: buffer containing data to be transmitted
+ * @len: size of transmission buffer
+ *
+ * Like mipi_dsi_dcs_write_buffer() but includes a dev_err()
+ * call for you and returns 0 upon success, not the number of bytes sent.
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_dcs_write_buffer_chatty(struct mipi_dsi_device *dsi,
+ const void *data, size_t len)
+{
+ struct device *dev = &dsi->dev;
+ ssize_t ret;
+
+ ret = mipi_dsi_dcs_write_buffer(dsi, data, len);
+ if (ret < 0) {
+ dev_err(dev, "sending dcs data %*ph failed: %zd\n",
+ (int)len, data, ret);
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer_chatty);
+
+/**
+ * mipi_dsi_dcs_write_buffer_multi - mipi_dsi_dcs_write_buffer_chatty() w/ accum_err
+ * @ctx: Context for multiple DSI transactions
+ * @data: buffer containing data to be transmitted
+ * @len: size of transmission buffer
+ *
+ * Like mipi_dsi_dcs_write_buffer_chatty() but deals with errors in a way that
+ * makes it convenient to make several calls in a row.
+ */
+void mipi_dsi_dcs_write_buffer_multi(struct mipi_dsi_multi_context *ctx,
+ const void *data, size_t len)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ ssize_t ret;
+
+ if (ctx->accum_err)
+ return;
+
+ ret = mipi_dsi_dcs_write_buffer(dsi, data, len);
+ if (ret < 0) {
+ ctx->accum_err = ret;
+ dev_err(dev, "sending dcs data %*ph failed: %d\n",
+ (int)len, data, ctx->accum_err);
+ }
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer_multi);
+
+/**
* mipi_dsi_dcs_write() - send DCS write command
* @dsi: DSI peripheral device
* @cmd: DCS command
@@ -1317,6 +1429,216 @@ int mipi_dsi_dcs_get_display_brightness_large(struct mipi_dsi_device *dsi,
}
EXPORT_SYMBOL(mipi_dsi_dcs_get_display_brightness_large);
+/**
+ * mipi_dsi_picture_parameter_set_multi() - transmit the DSC PPS to the peripheral
+ * @ctx: Context for multiple DSI transactions
+ * @pps: VESA DSC 1.1 Picture Parameter Set
+ *
+ * Like mipi_dsi_picture_parameter_set() but deals with errors in a way that
+ * makes it convenient to make several calls in a row.
+ */
+void mipi_dsi_picture_parameter_set_multi(struct mipi_dsi_multi_context *ctx,
+ const struct drm_dsc_picture_parameter_set *pps)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ ssize_t ret;
+
+ if (ctx->accum_err)
+ return;
+
+ ret = mipi_dsi_picture_parameter_set(dsi, pps);
+ if (ret < 0) {
+ ctx->accum_err = ret;
+ dev_err(dev, "sending PPS failed: %d\n",
+ ctx->accum_err);
+ }
+}
+EXPORT_SYMBOL(mipi_dsi_picture_parameter_set_multi);
+
+/**
+ * mipi_dsi_compression_mode_ext_multi() - enable/disable DSC on the peripheral
+ * @ctx: Context for multiple DSI transactions
+ * @enable: Whether to enable or disable the DSC
+ * @algo: Selected compression algorithm
+ * @pps_selector: Select PPS from the table of pre-stored or uploaded PPS entries
+ *
+ * Like mipi_dsi_compression_mode_ext() but deals with errors in a way that
+ * makes it convenient to make several calls in a row.
+ */
+void mipi_dsi_compression_mode_ext_multi(struct mipi_dsi_multi_context *ctx,
+ bool enable,
+ enum mipi_dsi_compression_algo algo,
+ unsigned int pps_selector)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ ssize_t ret;
+
+ if (ctx->accum_err)
+ return;
+
+ ret = mipi_dsi_compression_mode_ext(dsi, enable, algo, pps_selector);
+ if (ret < 0) {
+ ctx->accum_err = ret;
+ dev_err(dev, "sending COMPRESSION_MODE failed: %d\n",
+ ctx->accum_err);
+ }
+}
+EXPORT_SYMBOL(mipi_dsi_compression_mode_ext_multi);
+
+/**
+ * mipi_dsi_dcs_nop_multi() - send DCS NOP packet
+ * @ctx: Context for multiple DSI transactions
+ *
+ * Like mipi_dsi_dcs_nop() but deals with errors in a way that
+ * makes it convenient to make several calls in a row.
+ */
+void mipi_dsi_dcs_nop_multi(struct mipi_dsi_multi_context *ctx)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ ssize_t ret;
+
+ if (ctx->accum_err)
+ return;
+
+ ret = mipi_dsi_dcs_nop(dsi);
+ if (ret < 0) {
+ ctx->accum_err = ret;
+ dev_err(dev, "sending DCS NOP failed: %d\n",
+ ctx->accum_err);
+ }
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_nop_multi);
+
+/**
+ * mipi_dsi_dcs_enter_sleep_mode_multi() - send DCS ENTER_SLEEP_MODE packet
+ * @ctx: Context for multiple DSI transactions
+ *
+ * Like mipi_dsi_dcs_enter_sleep_mode() but deals with errors in a way that
+ * makes it convenient to make several calls in a row.
+ */
+void mipi_dsi_dcs_enter_sleep_mode_multi(struct mipi_dsi_multi_context *ctx)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ ssize_t ret;
+
+ if (ctx->accum_err)
+ return;
+
+ ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+ if (ret < 0) {
+ ctx->accum_err = ret;
+ dev_err(dev, "sending DCS ENTER_SLEEP_MODE failed: %d\n",
+ ctx->accum_err);
+ }
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_enter_sleep_mode_multi);
+
+/**
+ * mipi_dsi_dcs_exit_sleep_mode_multi() - send DCS EXIT_SLEEP_MODE packet
+ * @ctx: Context for multiple DSI transactions
+ *
+ * Like mipi_dsi_dcs_exit_sleep_mode() but deals with errors in a way that
+ * makes it convenient to make several calls in a row.
+ */
+void mipi_dsi_dcs_exit_sleep_mode_multi(struct mipi_dsi_multi_context *ctx)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ ssize_t ret;
+
+ if (ctx->accum_err)
+ return;
+
+ ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+ if (ret < 0) {
+ ctx->accum_err = ret;
+ dev_err(dev, "sending DCS EXIT_SLEEP_MODE failed: %d\n",
+ ctx->accum_err);
+ }
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_exit_sleep_mode_multi);
+
+/**
+ * mipi_dsi_dcs_set_display_off_multi() - send DCS SET_DISPLAY_OFF packet
+ * @ctx: Context for multiple DSI transactions
+ *
+ * Like mipi_dsi_dcs_set_display_off() but deals with errors in a way that
+ * makes it convenient to make several calls in a row.
+ */
+void mipi_dsi_dcs_set_display_off_multi(struct mipi_dsi_multi_context *ctx)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ ssize_t ret;
+
+ if (ctx->accum_err)
+ return;
+
+ ret = mipi_dsi_dcs_set_display_off(dsi);
+ if (ret < 0) {
+ ctx->accum_err = ret;
+ dev_err(dev, "sending DCS SET_DISPLAY_OFF failed: %d\n",
+ ctx->accum_err);
+ }
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_set_display_off_multi);
+
+/**
+ * mipi_dsi_dcs_set_display_on_multi() - send DCS SET_DISPLAY_ON packet
+ * @ctx: Context for multiple DSI transactions
+ *
+ * Like mipi_dsi_dcs_set_display_on() but deals with errors in a way that
+ * makes it convenient to make several calls in a row.
+ */
+void mipi_dsi_dcs_set_display_on_multi(struct mipi_dsi_multi_context *ctx)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ ssize_t ret;
+
+ if (ctx->accum_err)
+ return;
+
+ ret = mipi_dsi_dcs_set_display_on(dsi);
+ if (ret < 0) {
+ ctx->accum_err = ret;
+ dev_err(dev, "sending DCS SET_DISPLAY_ON failed: %d\n",
+ ctx->accum_err);
+ }
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_set_display_on_multi);
+
+/**
+ * mipi_dsi_dcs_set_tear_on_multi() - send DCS SET_TEAR_ON packet
+ * @ctx: Context for multiple DSI transactions
+ * @mode: the Tearing Effect Output Line mode
+ *
+ * Like mipi_dsi_dcs_set_tear_on() but deals with errors in a way that
+ * makes it convenient to make several calls in a row.
+ */
+void mipi_dsi_dcs_set_tear_on_multi(struct mipi_dsi_multi_context *ctx,
+ enum mipi_dsi_dcs_tear_mode mode)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ ssize_t ret;
+
+ if (ctx->accum_err)
+ return;
+
+ ret = mipi_dsi_dcs_set_tear_on(dsi, mode);
+ if (ret < 0) {
+ ctx->accum_err = ret;
+ dev_err(dev, "sending DCS SET_TEAR_ON failed: %d\n",
+ ctx->accum_err);
+ }
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_on_multi);
+
static int mipi_dsi_drv_probe(struct device *dev)
{
struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index 4f75a1cfd820..249c8c2cb319 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -474,6 +474,10 @@ static int __drm_helper_update_and_validate(struct drm_connector *connector,
if (mode->status != MODE_OK)
continue;
+ mode->status = drm_mode_validate_ycbcr420(mode, connector);
+ if (mode->status != MODE_OK)
+ continue;
+
ret = drm_mode_validate_pipeline(mode, connector, ctx,
&mode->status);
if (ret) {
@@ -486,10 +490,6 @@ static int __drm_helper_update_and_validate(struct drm_connector *connector,
else
return -EDEADLK;
}
-
- if (mode->status != MODE_OK)
- continue;
- mode->status = drm_mode_validate_ycbcr420(mode, connector);
}
return 0;
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index bd9b8ab4f82b..fb3bbb6adcd1 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -266,29 +266,9 @@ static ssize_t edid_show(struct file *filp, struct kobject *kobj,
{
struct device *connector_dev = kobj_to_dev(kobj);
struct drm_connector *connector = to_drm_connector(connector_dev);
- unsigned char *edid;
- size_t size;
- ssize_t ret = 0;
+ ssize_t ret;
- mutex_lock(&connector->dev->mode_config.mutex);
- if (!connector->edid_blob_ptr)
- goto unlock;
-
- edid = connector->edid_blob_ptr->data;
- size = connector->edid_blob_ptr->length;
- if (!edid)
- goto unlock;
-
- if (off >= size)
- goto unlock;
-
- if (off + count > size)
- count = size - off;
- memcpy(buf, edid + off, count);
-
- ret = count;
-unlock:
- mutex_unlock(&connector->dev->mode_config.mutex);
+ ret = drm_edid_connector_property_show(connector, buf, off, count);
return ret;
}
diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c
index dd1eb7e9877d..cc2ed9b3fd2d 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_dp.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c
@@ -1547,7 +1547,7 @@ cdv_intel_dp_start_link_train(struct gma_encoder *encoder)
}
if (!clock_recovery) {
- DRM_DEBUG_KMS("failure in DP patter 1 training, train set %x\n", intel_dp->train_set[0]);
+ DRM_DEBUG_KMS("failure in DP pattern 1 training, train set %x\n", intel_dp->train_set[0]);
}
intel_dp->DP = DP;
diff --git a/drivers/gpu/drm/gud/gud_drv.c b/drivers/gpu/drm/gud/gud_drv.c
index 9d7bf8ee45f1..4f5aa2e5cb89 100644
--- a/drivers/gpu/drm/gud/gud_drv.c
+++ b/drivers/gpu/drm/gud/gud_drv.c
@@ -18,7 +18,7 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_debugfs.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_shmem.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
@@ -622,7 +622,7 @@ static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id)
drm_kms_helper_poll_init(drm);
- drm_fbdev_generic_setup(drm, 0);
+ drm_fbdev_shmem_setup(drm, 0);
return 0;
}
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index 57c21ec452b7..9f9b19ea0587 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -17,7 +17,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_ttm.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_gem_vram_helper.h>
#include <drm/drm_managed.h>
@@ -339,7 +339,7 @@ static int hibmc_pci_probe(struct pci_dev *pdev,
goto err_unload;
}
- drm_fbdev_generic_setup(dev, 32);
+ drm_fbdev_ttm_setup(dev, 32);
return 0;
diff --git a/drivers/gpu/drm/hisilicon/kirin/Kconfig b/drivers/gpu/drm/hisilicon/kirin/Kconfig
index c5265675bf0c..0772f79567ef 100644
--- a/drivers/gpu/drm/hisilicon/kirin/Kconfig
+++ b/drivers/gpu/drm/hisilicon/kirin/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config DRM_HISI_KIRIN
tristate "DRM Support for Hisilicon Kirin series SoCs Platform"
- depends on DRM && OF && ARM64
+ depends on DRM && OF && (ARM64 || COMPILE_TEST)
select DRM_KMS_HELPER
select DRM_GEM_DMA_HELPER
select DRM_MIPI_DSI
diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
index 566de4658719..a39cc549c20b 100644
--- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
+++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
@@ -157,8 +157,8 @@ static u32 dsi_calc_phy_rate(u32 req_kHz, struct mipi_phy_params *phy)
q_pll = 0x10 >> (7 - phy->hstx_ckg_sel);
temp = f_kHz * (u64)q_pll * (u64)ref_clk_ps;
- m_n_int = temp / (u64)1000000000;
- m_n = (temp % (u64)1000000000) / (u64)100000000;
+ m_n_int = div64_u64_rem(temp, 1000000000, &temp);
+ m_n = div_u64(temp, 100000000);
if (m_n_int % 2 == 0) {
if (m_n * 6 >= 50) {
@@ -229,9 +229,8 @@ static u32 dsi_calc_phy_rate(u32 req_kHz, struct mipi_phy_params *phy)
phy->pll_fbd_div5f = 1;
}
- f_kHz = (u64)1000000000 * (u64)m_pll /
- ((u64)ref_clk_ps * (u64)n_pll * (u64)q_pll);
-
+ f_kHz = div64_u64((u64)1000000000 * (u64)m_pll,
+ (u64)ref_clk_ps * (u64)n_pll * (u64)q_pll);
if (f_kHz >= req_kHz)
break;
@@ -490,7 +489,7 @@ static void dsi_set_mode_timing(void __iomem *base,
hsa_time = (hsw * lane_byte_clk_kHz) / pixel_clk_kHz;
hbp_time = (hbp * lane_byte_clk_kHz) / pixel_clk_kHz;
tmp = (u64)htot * (u64)lane_byte_clk_kHz;
- hline_time = DIV_ROUND_UP(tmp, pixel_clk_kHz);
+ hline_time = DIV_ROUND_UP_ULL(tmp, pixel_clk_kHz);
/* all specified in byte-lane clocks */
writel(hsa_time, base + VID_HSA_TIME);
diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h b/drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h
index d79fc031e53d..a87d1135856f 100644
--- a/drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h
+++ b/drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h
@@ -7,6 +7,8 @@
#ifndef __DW_DSI_REG_H__
#define __DW_DSI_REG_H__
+#include <linux/io.h>
+
#define MASK(x) (BIT(x) - 1)
/*
diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h b/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h
index be9e789c2d04..36f923cc7594 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h
@@ -10,7 +10,7 @@
/*
* ADE Registers
*/
-#define MASK(x) (BIT(x) - 1)
+#define MASK(x) (BIT_ULL(x) - 1)
#define ADE_CTRL 0x0004
#define FRM_END_START_OFST 0
diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
index 75292a2f4644..12666985686b 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
@@ -19,7 +19,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_module.h>
@@ -237,7 +237,7 @@ static int kirin_drm_bind(struct device *dev)
if (ret)
goto err_kms_cleanup;
- drm_fbdev_generic_setup(drm_dev, 32);
+ drm_fbdev_dma_setup(drm_dev, 32);
return 0;
diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_drv.c b/drivers/gpu/drm/hyperv/hyperv_drm_drv.c
index cff85086f2d6..ff93e08d5036 100644
--- a/drivers/gpu/drm/hyperv/hyperv_drm_drv.c
+++ b/drivers/gpu/drm/hyperv/hyperv_drm_drv.c
@@ -11,7 +11,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_shmem.h>
#include <drm/drm_gem_shmem_helper.h>
#include <drm/drm_simple_kms_helper.h>
@@ -149,7 +149,7 @@ static int hyperv_vmbus_probe(struct hv_device *hdev,
goto err_free_mmio;
}
- drm_fbdev_generic_setup(dev, 0);
+ drm_fbdev_shmem_setup(dev, 0);
return 0;
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index d8d7de18dd65..2160f05bbd16 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -1283,7 +1283,7 @@ static int read_edid_block(void *data, u8 *buf, unsigned int blk, size_t length)
static int tda998x_connector_get_modes(struct drm_connector *connector)
{
struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
- struct edid *edid;
+ const struct drm_edid *drm_edid;
int n;
/*
@@ -1297,25 +1297,26 @@ static int tda998x_connector_get_modes(struct drm_connector *connector)
if (priv->rev == TDA19988)
reg_clear(priv, REG_TX4, TX4_PD_RAM);
- edid = drm_do_get_edid(connector, read_edid_block, priv);
+ drm_edid = drm_edid_read_custom(connector, read_edid_block, priv);
if (priv->rev == TDA19988)
reg_set(priv, REG_TX4, TX4_PD_RAM);
- if (!edid) {
+ drm_edid_connector_update(connector, drm_edid);
+ cec_notifier_set_phys_addr(priv->cec_notify,
+ connector->display_info.source_physical_address);
+
+ if (!drm_edid) {
dev_warn(&priv->hdmi->dev, "failed to read EDID\n");
return 0;
}
- drm_connector_update_edid_property(connector, edid);
- cec_notifier_set_phys_addr_from_edid(priv->cec_notify, edid);
-
mutex_lock(&priv->audio_mutex);
- n = drm_add_edid_modes(connector, edid);
- priv->sink_has_audio = drm_detect_monitor_audio(edid);
+ n = drm_edid_connector_add_modes(connector);
+ priv->sink_has_audio = connector->display_info.has_audio;
mutex_unlock(&priv->audio_mutex);
- kfree(edid);
+ drm_edid_free(drm_edid);
return n;
}
diff --git a/drivers/gpu/drm/imx/lcdc/imx-lcdc.c b/drivers/gpu/drm/imx/lcdc/imx-lcdc.c
index 43ddf3a9810b..36668455aee8 100644
--- a/drivers/gpu/drm/imx/lcdc/imx-lcdc.c
+++ b/drivers/gpu/drm/imx/lcdc/imx-lcdc.c
@@ -5,7 +5,7 @@
#include <drm/drm_bridge_connector.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_fb_dma_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
@@ -501,7 +501,7 @@ static int imx_lcdc_probe(struct platform_device *pdev)
if (ret)
return dev_err_probe(dev, ret, "Cannot register device\n");
- drm_fbdev_generic_setup(drm, 0);
+ drm_fbdev_dma_setup(drm, 0);
return 0;
}
diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
index 0751235007a7..39fa291f43dd 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
@@ -31,7 +31,7 @@
#include <drm/drm_encoder.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_fb_dma_helper.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
@@ -1399,7 +1399,7 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
goto err_clk_notifier_unregister;
}
- drm_fbdev_generic_setup(drm, 32);
+ drm_fbdev_dma_setup(drm, 32);
return 0;
diff --git a/drivers/gpu/drm/loongson/Kconfig b/drivers/gpu/drm/loongson/Kconfig
index 8e59753e532d..9ed463a76ae2 100644
--- a/drivers/gpu/drm/loongson/Kconfig
+++ b/drivers/gpu/drm/loongson/Kconfig
@@ -6,6 +6,7 @@ config DRM_LOONGSON
depends on LOONGARCH || MIPS || COMPILE_TEST
select DRM_KMS_HELPER
select DRM_TTM
+ select DRM_TTM_HELPER
select I2C
select I2C_ALGOBIT
help
diff --git a/drivers/gpu/drm/loongson/lsdc_drv.c b/drivers/gpu/drm/loongson/lsdc_drv.c
index d8ff60b46abe..adc7344d2f80 100644
--- a/drivers/gpu/drm/loongson/lsdc_drv.c
+++ b/drivers/gpu/drm/loongson/lsdc_drv.c
@@ -10,7 +10,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_ttm.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_modeset_helper.h>
@@ -314,7 +314,7 @@ static int lsdc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ret)
return ret;
- drm_fbdev_generic_setup(ddev, 32);
+ drm_fbdev_ttm_setup(ddev, 32);
return 0;
}
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index b5f605751b0a..c0aa3e4e2219 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -15,7 +15,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem.h>
#include <drm/drm_gem_framebuffer_helper.h>
@@ -644,7 +644,7 @@ static int mtk_drm_bind(struct device *dev)
if (ret < 0)
goto err_deinit;
- drm_fbdev_generic_setup(drm, 32);
+ drm_fbdev_dma_setup(drm, 32);
return 0;
diff --git a/drivers/gpu/drm/mgag200/Kconfig b/drivers/gpu/drm/mgag200/Kconfig
index 5e4d48df4854..3096944a8f0a 100644
--- a/drivers/gpu/drm/mgag200/Kconfig
+++ b/drivers/gpu/drm/mgag200/Kconfig
@@ -12,14 +12,12 @@ config DRM_MGAG200
of the modesetting userspace driver, and a version of mga driver
that will fail on KMS enabled devices.
-config DRM_MGAG200_IOBURST_WORKAROUND
- bool "Disable buffer caching"
- depends on DRM_MGAG200 && PREEMPT_RT && X86
+config DRM_MGAG200_DISABLE_WRITECOMBINE
+ bool "Disable Write Combine mapping of VRAM"
+ depends on DRM_MGAG200 && PREEMPT_RT
help
- Enable a workaround to avoid I/O bursts within the mgag200 driver at
- the expense of overall display performance.
- It restores the <v5.10 behavior, by mapping the framebuffer in system
- RAM as Write-Combining, and flushing the cache after each write.
- This is only useful on x86_64 if you want to run processes with
- deterministic latency.
- If unsure, say N.
+ The VRAM of the G200 is mapped with Write-Combine to improve
+ performances. This can interfere with real-time tasks; even if they
+ are running on other CPU cores than the graphics output.
+ Enable this option only if you run realtime tasks on a server with a
+ Matrox G200. \ No newline at end of file
diff --git a/drivers/gpu/drm/mgag200/Makefile b/drivers/gpu/drm/mgag200/Makefile
index 182e224c460d..0b919352046e 100644
--- a/drivers/gpu/drm/mgag200/Makefile
+++ b/drivers/gpu/drm/mgag200/Makefile
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
mgag200-y := \
mgag200_bmc.o \
+ mgag200_ddc.o \
mgag200_drv.o \
mgag200_g200.o \
mgag200_g200eh.o \
@@ -10,7 +11,6 @@ mgag200-y := \
mgag200_g200ew3.o \
mgag200_g200se.o \
mgag200_g200wb.o \
- mgag200_i2c.o \
mgag200_mode.o
obj-$(CONFIG_DRM_MGAG200) += mgag200.o
diff --git a/drivers/gpu/drm/mgag200/mgag200_ddc.c b/drivers/gpu/drm/mgag200/mgag200_ddc.c
new file mode 100644
index 000000000000..6d81ea8931e8
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/mgag200_ddc.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ */
+/*
+ * Authors: Dave Airlie <[email protected]>
+ */
+
+#include <linux/export.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/i2c.h>
+#include <linux/pci.h>
+
+#include <drm/drm_managed.h>
+
+#include "mgag200_ddc.h"
+#include "mgag200_drv.h"
+
+struct mgag200_ddc {
+ struct mga_device *mdev;
+
+ int data;
+ int clock;
+
+ struct i2c_algo_bit_data bit;
+ struct i2c_adapter adapter;
+};
+
+static int mga_i2c_read_gpio(struct mga_device *mdev)
+{
+ WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA);
+ return RREG8(DAC_DATA);
+}
+
+static void mga_i2c_set_gpio(struct mga_device *mdev, int mask, int val)
+{
+ int tmp;
+
+ WREG8(DAC_INDEX, MGA1064_GEN_IO_CTL);
+ tmp = (RREG8(DAC_DATA) & mask) | val;
+ WREG_DAC(MGA1064_GEN_IO_CTL, tmp);
+ WREG_DAC(MGA1064_GEN_IO_DATA, 0);
+}
+
+static inline void mga_i2c_set(struct mga_device *mdev, int mask, int state)
+{
+ if (state)
+ state = 0;
+ else
+ state = mask;
+ mga_i2c_set_gpio(mdev, ~mask, state);
+}
+
+static void mgag200_ddc_algo_bit_data_setsda(void *data, int state)
+{
+ struct mgag200_ddc *ddc = data;
+
+ mga_i2c_set(ddc->mdev, ddc->data, state);
+}
+
+static void mgag200_ddc_algo_bit_data_setscl(void *data, int state)
+{
+ struct mgag200_ddc *ddc = data;
+
+ mga_i2c_set(ddc->mdev, ddc->clock, state);
+}
+
+static int mgag200_ddc_algo_bit_data_getsda(void *data)
+{
+ struct mgag200_ddc *ddc = data;
+
+ return (mga_i2c_read_gpio(ddc->mdev) & ddc->data) ? 1 : 0;
+}
+
+static int mgag200_ddc_algo_bit_data_getscl(void *data)
+{
+ struct mgag200_ddc *ddc = data;
+
+ return (mga_i2c_read_gpio(ddc->mdev) & ddc->clock) ? 1 : 0;
+}
+
+static int mgag200_ddc_algo_bit_data_pre_xfer(struct i2c_adapter *adapter)
+{
+ struct mgag200_ddc *ddc = i2c_get_adapdata(adapter);
+ struct mga_device *mdev = ddc->mdev;
+
+ /*
+ * Protect access to I/O registers from concurrent modesetting
+ * by acquiring the I/O-register lock.
+ */
+ mutex_lock(&mdev->rmmio_lock);
+
+ return 0;
+}
+
+static void mgag200_ddc_algo_bit_data_post_xfer(struct i2c_adapter *adapter)
+{
+ struct mgag200_ddc *ddc = i2c_get_adapdata(adapter);
+ struct mga_device *mdev = ddc->mdev;
+
+ mutex_unlock(&mdev->rmmio_lock);
+}
+
+static void mgag200_ddc_release(struct drm_device *dev, void *res)
+{
+ struct mgag200_ddc *ddc = res;
+
+ i2c_del_adapter(&ddc->adapter);
+}
+
+struct i2c_adapter *mgag200_ddc_create(struct mga_device *mdev)
+{
+ struct drm_device *dev = &mdev->base;
+ const struct mgag200_device_info *info = mdev->info;
+ struct mgag200_ddc *ddc;
+ struct i2c_algo_bit_data *bit;
+ struct i2c_adapter *adapter;
+ int ret;
+
+ ddc = drmm_kzalloc(dev, sizeof(*ddc), GFP_KERNEL);
+ if (!ddc)
+ return ERR_PTR(-ENOMEM);
+
+ WREG_DAC(MGA1064_GEN_IO_CTL2, 1);
+ WREG_DAC(MGA1064_GEN_IO_DATA, 0xff);
+ WREG_DAC(MGA1064_GEN_IO_CTL, 0);
+
+ ddc->mdev = mdev;
+ ddc->data = BIT(info->i2c.data_bit);
+ ddc->clock = BIT(info->i2c.clock_bit);
+
+ bit = &ddc->bit;
+ bit->data = ddc;
+ bit->setsda = mgag200_ddc_algo_bit_data_setsda;
+ bit->setscl = mgag200_ddc_algo_bit_data_setscl;
+ bit->getsda = mgag200_ddc_algo_bit_data_getsda;
+ bit->getscl = mgag200_ddc_algo_bit_data_getscl;
+ bit->pre_xfer = mgag200_ddc_algo_bit_data_pre_xfer;
+ bit->post_xfer = mgag200_ddc_algo_bit_data_post_xfer;
+ bit->udelay = 10;
+ bit->timeout = usecs_to_jiffies(2200);
+
+ adapter = &ddc->adapter;
+ adapter->owner = THIS_MODULE;
+ adapter->algo_data = bit;
+ adapter->dev.parent = dev->dev;
+ snprintf(adapter->name, sizeof(adapter->name), "Matrox DDC bus");
+ i2c_set_adapdata(adapter, ddc);
+
+ ret = i2c_bit_add_bus(adapter);
+ if (ret)
+ return ERR_PTR(ret);
+
+ ret = drmm_add_action_or_reset(dev, mgag200_ddc_release, ddc);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return adapter;
+}
diff --git a/drivers/gpu/drm/mgag200/mgag200_ddc.h b/drivers/gpu/drm/mgag200/mgag200_ddc.h
new file mode 100644
index 000000000000..fa21d197cc78
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/mgag200_ddc.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __MGAG200_DDC_H__
+#define __MGAG200_DDC_H__
+
+struct i2c_adapter;
+struct mga_device;
+
+struct i2c_adapter *mgag200_ddc_create(struct mga_device *mdev);
+
+#endif
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c
index 573dbe256aa8..62080cf0f2da 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.c
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.c
@@ -12,7 +12,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_shmem.h>
#include <drm/drm_file.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_managed.h>
@@ -84,20 +84,6 @@ resource_size_t mgag200_probe_vram(void __iomem *mem, resource_size_t size)
return offset - 65536;
}
-#if defined(CONFIG_DRM_MGAG200_IOBURST_WORKAROUND)
-static struct drm_gem_object *mgag200_create_object(struct drm_device *dev, size_t size)
-{
- struct drm_gem_shmem_object *shmem;
-
- shmem = kzalloc(sizeof(*shmem), GFP_KERNEL);
- if (!shmem)
- return NULL;
-
- shmem->map_wc = true;
- return &shmem->base;
-}
-#endif
-
/*
* DRM driver
*/
@@ -113,9 +99,6 @@ static const struct drm_driver mgag200_driver = {
.major = DRIVER_MAJOR,
.minor = DRIVER_MINOR,
.patchlevel = DRIVER_PATCHLEVEL,
-#if defined(CONFIG_DRM_MGAG200_IOBURST_WORKAROUND)
- .gem_create_object = mgag200_create_object,
-#endif
DRM_GEM_SHMEM_DRIVER_OPS,
};
@@ -163,12 +146,18 @@ int mgag200_device_preinit(struct mga_device *mdev)
}
mdev->vram_res = res;
+#if defined(CONFIG_DRM_MGAG200_DISABLE_WRITECOMBINE)
+ mdev->vram = devm_ioremap(dev->dev, res->start, resource_size(res));
+ if (!mdev->vram)
+ return -ENOMEM;
+#else
mdev->vram = devm_ioremap_wc(dev->dev, res->start, resource_size(res));
if (!mdev->vram)
return -ENOMEM;
/* Don't fail on errors, but performance might be reduced. */
devm_arch_phys_wc_add(dev->dev, res->start, resource_size(res));
+#endif
return 0;
}
@@ -285,7 +274,7 @@ mgag200_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
* FIXME: A 24-bit color depth does not work with 24 bpp on
* G200ER. Force 32 bpp.
*/
- drm_fbdev_generic_setup(dev, 32);
+ drm_fbdev_shmem_setup(dev, 32);
return 0;
}
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
index 58a0e62eaf18..20e3710e056b 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -10,9 +10,6 @@
#ifndef __MGAG200_DRV_H__
#define __MGAG200_DRV_H__
-#include <linux/i2c-algo-bit.h>
-#include <linux/i2c.h>
-
#include <video/vga.h>
#include <drm/drm_connector.h>
@@ -189,13 +186,6 @@ static inline struct mgag200_crtc_state *to_mgag200_crtc_state(struct drm_crtc_s
return container_of(base, struct mgag200_crtc_state, base);
}
-struct mga_i2c_chan {
- struct i2c_adapter adapter;
- struct drm_device *dev;
- struct i2c_algo_bit_data bit;
- int data, clock;
-};
-
enum mga_type {
G200_PCI,
G200_AGP,
@@ -294,7 +284,6 @@ struct mga_device {
struct drm_plane primary_plane;
struct drm_crtc crtc;
struct drm_encoder encoder;
- struct mga_i2c_chan i2c;
struct drm_connector connector;
};
@@ -431,10 +420,8 @@ void mgag200_crtc_atomic_destroy_state(struct drm_crtc *crtc, struct drm_crtc_st
#define MGAG200_DAC_ENCODER_FUNCS \
.destroy = drm_encoder_cleanup
-int mgag200_vga_connector_helper_get_modes(struct drm_connector *connector);
-
#define MGAG200_VGA_CONNECTOR_HELPER_FUNCS \
- .get_modes = mgag200_vga_connector_helper_get_modes
+ .get_modes = drm_connector_helper_get_modes
#define MGAG200_VGA_CONNECTOR_FUNCS \
.reset = drm_atomic_helper_connector_reset, \
@@ -453,7 +440,4 @@ int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vram_avail
void mgag200_bmc_disable_vidrst(struct mga_device *mdev);
void mgag200_bmc_enable_vidrst(struct mga_device *mdev);
- /* mgag200_i2c.c */
-int mgag200_i2c_init(struct mga_device *mdev, struct mga_i2c_chan *i2c);
-
#endif /* __MGAG200_DRV_H__ */
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200.c b/drivers/gpu/drm/mgag200/mgag200_g200.c
index bf5d7fe525a3..39a29d8ffca6 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200.c
@@ -9,6 +9,7 @@
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_probe_helper.h>
+#include "mgag200_ddc.h"
#include "mgag200_drv.h"
static int mgag200_g200_init_pci_options(struct pci_dev *pdev)
@@ -201,8 +202,8 @@ static int mgag200_g200_pipeline_init(struct mga_device *mdev)
struct drm_plane *primary_plane = &mdev->primary_plane;
struct drm_crtc *crtc = &mdev->crtc;
struct drm_encoder *encoder = &mdev->encoder;
- struct mga_i2c_chan *i2c = &mdev->i2c;
struct drm_connector *connector = &mdev->connector;
+ struct i2c_adapter *ddc;
int ret;
ret = drm_universal_plane_init(dev, primary_plane, 0,
@@ -238,16 +239,16 @@ static int mgag200_g200_pipeline_init(struct mga_device *mdev)
return ret;
}
- ret = mgag200_i2c_init(mdev, i2c);
- if (ret) {
+ ddc = mgag200_ddc_create(mdev);
+ if (IS_ERR(ddc)) {
+ ret = PTR_ERR(ddc);
drm_err(dev, "failed to add DDC bus: %d\n", ret);
return ret;
}
ret = drm_connector_init_with_ddc(dev, connector,
&mgag200_g200_vga_connector_funcs,
- DRM_MODE_CONNECTOR_VGA,
- &i2c->adapter);
+ DRM_MODE_CONNECTOR_VGA, ddc);
if (ret) {
drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
return ret;
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh.c b/drivers/gpu/drm/mgag200/mgag200_g200eh.c
index fad62453a91d..619fee7ffdf5 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200eh.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200eh.c
@@ -9,6 +9,7 @@
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_probe_helper.h>
+#include "mgag200_ddc.h"
#include "mgag200_drv.h"
void mgag200_g200eh_init_registers(struct mga_device *mdev)
@@ -200,8 +201,8 @@ static int mgag200_g200eh_pipeline_init(struct mga_device *mdev)
struct drm_plane *primary_plane = &mdev->primary_plane;
struct drm_crtc *crtc = &mdev->crtc;
struct drm_encoder *encoder = &mdev->encoder;
- struct mga_i2c_chan *i2c = &mdev->i2c;
struct drm_connector *connector = &mdev->connector;
+ struct i2c_adapter *ddc;
int ret;
ret = drm_universal_plane_init(dev, primary_plane, 0,
@@ -237,16 +238,16 @@ static int mgag200_g200eh_pipeline_init(struct mga_device *mdev)
return ret;
}
- ret = mgag200_i2c_init(mdev, i2c);
- if (ret) {
+ ddc = mgag200_ddc_create(mdev);
+ if (IS_ERR(ddc)) {
+ ret = PTR_ERR(ddc);
drm_err(dev, "failed to add DDC bus: %d\n", ret);
return ret;
}
ret = drm_connector_init_with_ddc(dev, connector,
&mgag200_g200eh_vga_connector_funcs,
- DRM_MODE_CONNECTOR_VGA,
- &i2c->adapter);
+ DRM_MODE_CONNECTOR_VGA, ddc);
if (ret) {
drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
return ret;
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
index 0f7d8112cd49..a172b8a4500a 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
@@ -8,6 +8,7 @@
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_probe_helper.h>
+#include "mgag200_ddc.h"
#include "mgag200_drv.h"
/*
@@ -104,8 +105,8 @@ static int mgag200_g200eh3_pipeline_init(struct mga_device *mdev)
struct drm_plane *primary_plane = &mdev->primary_plane;
struct drm_crtc *crtc = &mdev->crtc;
struct drm_encoder *encoder = &mdev->encoder;
- struct mga_i2c_chan *i2c = &mdev->i2c;
struct drm_connector *connector = &mdev->connector;
+ struct i2c_adapter *ddc;
int ret;
ret = drm_universal_plane_init(dev, primary_plane, 0,
@@ -141,16 +142,16 @@ static int mgag200_g200eh3_pipeline_init(struct mga_device *mdev)
return ret;
}
- ret = mgag200_i2c_init(mdev, i2c);
- if (ret) {
+ ddc = mgag200_ddc_create(mdev);
+ if (IS_ERR(ddc)) {
+ ret = PTR_ERR(ddc);
drm_err(dev, "failed to add DDC bus: %d\n", ret);
return ret;
}
ret = drm_connector_init_with_ddc(dev, connector,
&mgag200_g200eh3_vga_connector_funcs,
- DRM_MODE_CONNECTOR_VGA,
- &i2c->adapter);
+ DRM_MODE_CONNECTOR_VGA, ddc);
if (ret) {
drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
return ret;
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c b/drivers/gpu/drm/mgag200/mgag200_g200er.c
index 8d4538b71047..a11c91331e43 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200er.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c
@@ -9,6 +9,7 @@
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_probe_helper.h>
+#include "mgag200_ddc.h"
#include "mgag200_drv.h"
static void mgag200_g200er_init_registers(struct mga_device *mdev)
@@ -243,8 +244,8 @@ static int mgag200_g200er_pipeline_init(struct mga_device *mdev)
struct drm_plane *primary_plane = &mdev->primary_plane;
struct drm_crtc *crtc = &mdev->crtc;
struct drm_encoder *encoder = &mdev->encoder;
- struct mga_i2c_chan *i2c = &mdev->i2c;
struct drm_connector *connector = &mdev->connector;
+ struct i2c_adapter *ddc;
int ret;
ret = drm_universal_plane_init(dev, primary_plane, 0,
@@ -280,16 +281,16 @@ static int mgag200_g200er_pipeline_init(struct mga_device *mdev)
return ret;
}
- ret = mgag200_i2c_init(mdev, i2c);
- if (ret) {
+ ddc = mgag200_ddc_create(mdev);
+ if (IS_ERR(ddc)) {
+ ret = PTR_ERR(ddc);
drm_err(dev, "failed to add DDC bus: %d\n", ret);
return ret;
}
ret = drm_connector_init_with_ddc(dev, connector,
&mgag200_g200er_vga_connector_funcs,
- DRM_MODE_CONNECTOR_VGA,
- &i2c->adapter);
+ DRM_MODE_CONNECTOR_VGA, ddc);
if (ret) {
drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
return ret;
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ev.c b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
index 56e6f986bff3..dfb641b83842 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200ev.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
@@ -9,6 +9,7 @@
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_probe_helper.h>
+#include "mgag200_ddc.h"
#include "mgag200_drv.h"
static void mgag200_g200ev_init_registers(struct mga_device *mdev)
@@ -244,8 +245,8 @@ static int mgag200_g200ev_pipeline_init(struct mga_device *mdev)
struct drm_plane *primary_plane = &mdev->primary_plane;
struct drm_crtc *crtc = &mdev->crtc;
struct drm_encoder *encoder = &mdev->encoder;
- struct mga_i2c_chan *i2c = &mdev->i2c;
struct drm_connector *connector = &mdev->connector;
+ struct i2c_adapter *ddc;
int ret;
ret = drm_universal_plane_init(dev, primary_plane, 0,
@@ -281,16 +282,16 @@ static int mgag200_g200ev_pipeline_init(struct mga_device *mdev)
return ret;
}
- ret = mgag200_i2c_init(mdev, i2c);
- if (ret) {
+ ddc = mgag200_ddc_create(mdev);
+ if (IS_ERR(ddc)) {
+ ret = PTR_ERR(ddc);
drm_err(dev, "failed to add DDC bus: %d\n", ret);
return ret;
}
ret = drm_connector_init_with_ddc(dev, connector,
&mgag200_g200ev_vga_connector_funcs,
- DRM_MODE_CONNECTOR_VGA,
- &i2c->adapter);
+ DRM_MODE_CONNECTOR_VGA, ddc);
if (ret) {
drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
return ret;
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
index 170934414d7d..525b7f75e622 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
@@ -8,6 +8,7 @@
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_probe_helper.h>
+#include "mgag200_ddc.h"
#include "mgag200_drv.h"
static void mgag200_g200ew3_init_registers(struct mga_device *mdev)
@@ -113,8 +114,8 @@ static int mgag200_g200ew3_pipeline_init(struct mga_device *mdev)
struct drm_plane *primary_plane = &mdev->primary_plane;
struct drm_crtc *crtc = &mdev->crtc;
struct drm_encoder *encoder = &mdev->encoder;
- struct mga_i2c_chan *i2c = &mdev->i2c;
struct drm_connector *connector = &mdev->connector;
+ struct i2c_adapter *ddc;
int ret;
ret = drm_universal_plane_init(dev, primary_plane, 0,
@@ -150,16 +151,16 @@ static int mgag200_g200ew3_pipeline_init(struct mga_device *mdev)
return ret;
}
- ret = mgag200_i2c_init(mdev, i2c);
- if (ret) {
+ ddc = mgag200_ddc_create(mdev);
+ if (IS_ERR(ddc)) {
+ ret = PTR_ERR(ddc);
drm_err(dev, "failed to add DDC bus: %d\n", ret);
return ret;
}
ret = drm_connector_init_with_ddc(dev, connector,
&mgag200_g200ew3_vga_connector_funcs,
- DRM_MODE_CONNECTOR_VGA,
- &i2c->adapter);
+ DRM_MODE_CONNECTOR_VGA, ddc);
if (ret) {
drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
return ret;
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200se.c b/drivers/gpu/drm/mgag200/mgag200_g200se.c
index ff2b3c6622e7..ef7606b529ea 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200se.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200se.c
@@ -9,6 +9,7 @@
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_probe_helper.h>
+#include "mgag200_ddc.h"
#include "mgag200_drv.h"
static int mgag200_g200se_init_pci_options(struct pci_dev *pdev)
@@ -375,8 +376,8 @@ static int mgag200_g200se_pipeline_init(struct mga_device *mdev)
struct drm_plane *primary_plane = &mdev->primary_plane;
struct drm_crtc *crtc = &mdev->crtc;
struct drm_encoder *encoder = &mdev->encoder;
- struct mga_i2c_chan *i2c = &mdev->i2c;
struct drm_connector *connector = &mdev->connector;
+ struct i2c_adapter *ddc;
int ret;
ret = drm_universal_plane_init(dev, primary_plane, 0,
@@ -412,16 +413,16 @@ static int mgag200_g200se_pipeline_init(struct mga_device *mdev)
return ret;
}
- ret = mgag200_i2c_init(mdev, i2c);
- if (ret) {
+ ddc = mgag200_ddc_create(mdev);
+ if (IS_ERR(ddc)) {
+ ret = PTR_ERR(ddc);
drm_err(dev, "failed to add DDC bus: %d\n", ret);
return ret;
}
ret = drm_connector_init_with_ddc(dev, connector,
&mgag200_g200se_vga_connector_funcs,
- DRM_MODE_CONNECTOR_VGA,
- &i2c->adapter);
+ DRM_MODE_CONNECTOR_VGA, ddc);
if (ret) {
drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
return ret;
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200wb.c b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
index 9baa727ac6f9..e4def62b1e57 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200wb.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
@@ -9,6 +9,7 @@
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_probe_helper.h>
+#include "mgag200_ddc.h"
#include "mgag200_drv.h"
void mgag200_g200wb_init_registers(struct mga_device *mdev)
@@ -247,8 +248,8 @@ static int mgag200_g200wb_pipeline_init(struct mga_device *mdev)
struct drm_plane *primary_plane = &mdev->primary_plane;
struct drm_crtc *crtc = &mdev->crtc;
struct drm_encoder *encoder = &mdev->encoder;
- struct mga_i2c_chan *i2c = &mdev->i2c;
struct drm_connector *connector = &mdev->connector;
+ struct i2c_adapter *ddc;
int ret;
ret = drm_universal_plane_init(dev, primary_plane, 0,
@@ -284,16 +285,16 @@ static int mgag200_g200wb_pipeline_init(struct mga_device *mdev)
return ret;
}
- ret = mgag200_i2c_init(mdev, i2c);
- if (ret) {
+ ddc = mgag200_ddc_create(mdev);
+ if (IS_ERR(ddc)) {
+ ret = PTR_ERR(ddc);
drm_err(dev, "failed to add DDC bus: %d\n", ret);
return ret;
}
ret = drm_connector_init_with_ddc(dev, connector,
&mgag200_g200wb_vga_connector_funcs,
- DRM_MODE_CONNECTOR_VGA,
- &i2c->adapter);
+ DRM_MODE_CONNECTOR_VGA, ddc);
if (ret) {
drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
return ret;
diff --git a/drivers/gpu/drm/mgag200/mgag200_i2c.c b/drivers/gpu/drm/mgag200/mgag200_i2c.c
deleted file mode 100644
index 423eb302be7e..000000000000
--- a/drivers/gpu/drm/mgag200/mgag200_i2c.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright 2012 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- */
-/*
- * Authors: Dave Airlie <[email protected]>
- */
-
-#include <linux/export.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/i2c.h>
-#include <linux/pci.h>
-
-#include "mgag200_drv.h"
-
-static int mga_i2c_read_gpio(struct mga_device *mdev)
-{
- WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA);
- return RREG8(DAC_DATA);
-}
-
-static void mga_i2c_set_gpio(struct mga_device *mdev, int mask, int val)
-{
- int tmp;
-
- WREG8(DAC_INDEX, MGA1064_GEN_IO_CTL);
- tmp = (RREG8(DAC_DATA) & mask) | val;
- WREG_DAC(MGA1064_GEN_IO_CTL, tmp);
- WREG_DAC(MGA1064_GEN_IO_DATA, 0);
-}
-
-static inline void mga_i2c_set(struct mga_device *mdev, int mask, int state)
-{
- if (state)
- state = 0;
- else
- state = mask;
- mga_i2c_set_gpio(mdev, ~mask, state);
-}
-
-static void mga_gpio_setsda(void *data, int state)
-{
- struct mga_i2c_chan *i2c = data;
- struct mga_device *mdev = to_mga_device(i2c->dev);
- mga_i2c_set(mdev, i2c->data, state);
-}
-
-static void mga_gpio_setscl(void *data, int state)
-{
- struct mga_i2c_chan *i2c = data;
- struct mga_device *mdev = to_mga_device(i2c->dev);
- mga_i2c_set(mdev, i2c->clock, state);
-}
-
-static int mga_gpio_getsda(void *data)
-{
- struct mga_i2c_chan *i2c = data;
- struct mga_device *mdev = to_mga_device(i2c->dev);
- return (mga_i2c_read_gpio(mdev) & i2c->data) ? 1 : 0;
-}
-
-static int mga_gpio_getscl(void *data)
-{
- struct mga_i2c_chan *i2c = data;
- struct mga_device *mdev = to_mga_device(i2c->dev);
- return (mga_i2c_read_gpio(mdev) & i2c->clock) ? 1 : 0;
-}
-
-static void mgag200_i2c_release(void *res)
-{
- struct mga_i2c_chan *i2c = res;
-
- i2c_del_adapter(&i2c->adapter);
-}
-
-int mgag200_i2c_init(struct mga_device *mdev, struct mga_i2c_chan *i2c)
-{
- struct drm_device *dev = &mdev->base;
- const struct mgag200_device_info *info = mdev->info;
- int ret;
-
- WREG_DAC(MGA1064_GEN_IO_CTL2, 1);
- WREG_DAC(MGA1064_GEN_IO_DATA, 0xff);
- WREG_DAC(MGA1064_GEN_IO_CTL, 0);
-
- i2c->data = BIT(info->i2c.data_bit);
- i2c->clock = BIT(info->i2c.clock_bit);
- i2c->adapter.owner = THIS_MODULE;
- i2c->adapter.dev.parent = dev->dev;
- i2c->dev = dev;
- i2c_set_adapdata(&i2c->adapter, i2c);
- snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), "mga i2c");
-
- i2c->adapter.algo_data = &i2c->bit;
-
- i2c->bit.udelay = 10;
- i2c->bit.timeout = 2;
- i2c->bit.data = i2c;
- i2c->bit.setsda = mga_gpio_setsda;
- i2c->bit.setscl = mga_gpio_setscl;
- i2c->bit.getsda = mga_gpio_getsda;
- i2c->bit.getscl = mga_gpio_getscl;
-
- ret = i2c_bit_add_bus(&i2c->adapter);
- if (ret)
- return ret;
-
- return devm_add_action_or_reset(dev->dev, mgag200_i2c_release, i2c);
-}
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index fc54851d3384..bb6204002cb3 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -13,7 +13,6 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
-#include <drm/drm_cache.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_edid.h>
#include <drm/drm_format_helper.h>
@@ -24,6 +23,7 @@
#include <drm/drm_panic.h>
#include <drm/drm_print.h>
+#include "mgag200_ddc.h"
#include "mgag200_drv.h"
/*
@@ -438,13 +438,6 @@ static void mgag200_handle_damage(struct mga_device *mdev, const struct iosys_ma
iosys_map_incr(&dst, drm_fb_clip_offset(fb->pitches[0], fb->format, clip));
drm_fb_memcpy(&dst, fb->pitches, vmap, fb, clip);
-
- /* Flushing the cache greatly improves latency on x86_64 */
-#if defined(CONFIG_DRM_MGAG200_IOBURST_WORKAROUND)
- if (!vmap->is_iomem)
- drm_clflush_virt_range(vmap->vaddr + clip->y1 * fb->pitches[0],
- drm_rect_height(clip) * fb->pitches[0]);
-#endif
}
/*
@@ -737,32 +730,6 @@ void mgag200_crtc_atomic_destroy_state(struct drm_crtc *crtc, struct drm_crtc_st
}
/*
- * Connector
- */
-
-int mgag200_vga_connector_helper_get_modes(struct drm_connector *connector)
-{
- struct mga_device *mdev = to_mga_device(connector->dev);
- const struct drm_edid *drm_edid;
- int count;
-
- /*
- * Protect access to I/O registers from concurrent modesetting
- * by acquiring the I/O-register lock.
- */
- mutex_lock(&mdev->rmmio_lock);
-
- drm_edid = drm_edid_read(connector);
- drm_edid_connector_update(connector, drm_edid);
- count = drm_edid_connector_add_modes(connector);
- drm_edid_free(drm_edid);
-
- mutex_unlock(&mdev->rmmio_lock);
-
- return count;
-}
-
-/*
* Mode config
*/
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 88728a0b2c25..ac9657d7e92d 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -751,7 +751,7 @@ nv50_audio_enable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc,
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nvif_outp *outp = &nv_encoder->outp;
- if (!nv50_audio_supported(encoder) || !drm_detect_monitor_audio(nv_connector->edid))
+ if (!nv50_audio_supported(encoder) || !nv_connector->base.display_info.has_audio)
return;
mutex_lock(&drm->audio.lock);
@@ -1765,7 +1765,7 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta
if ((disp->disp->object.oclass == GT214_DISP ||
disp->disp->object.oclass >= GF110_DISP) &&
nv_encoder->dcb->type != DCB_OUTPUT_LVDS &&
- drm_detect_monitor_audio(nv_connector->edid))
+ nv_connector->base.display_info.has_audio)
hda = true;
if (!nvif_outp_acquired(outp))
@@ -1774,7 +1774,7 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta
switch (nv_encoder->dcb->type) {
case DCB_OUTPUT_TMDS:
if (disp->disp->object.oclass != NV50_DISP &&
- drm_detect_hdmi_monitor(nv_connector->edid))
+ nv_connector->base.display_info.is_hdmi)
nv50_hdmi_enable(encoder, nv_crtc, nv_connector, state, mode, hda);
if (nv_encoder->outp.or.link & 1) {
@@ -1787,7 +1787,7 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta
*/
if (mode->clock >= 165000 &&
nv_encoder->dcb->duallink_possible &&
- !drm_detect_hdmi_monitor(nv_connector->edid))
+ !nv_connector->base.display_info.is_hdmi)
proto = NV507D_SOR_SET_CONTROL_PROTOCOL_DUAL_TMDS;
} else {
proto = NV507D_SOR_SET_CONTROL_PROTOCOL_SINGLE_TMDS_B;
diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c
index 83355dbc15ee..d7c74cc43ba5 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/head.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/head.c
@@ -127,14 +127,8 @@ nv50_head_atomic_check_view(struct nv50_head_atom *armh,
struct drm_display_mode *omode = &asyh->state.adjusted_mode;
struct drm_display_mode *umode = &asyh->state.mode;
int mode = asyc->scaler.mode;
- struct edid *edid;
int umode_vdisplay, omode_hdisplay, omode_vdisplay;
- if (connector->edid_blob_ptr)
- edid = (struct edid *)connector->edid_blob_ptr->data;
- else
- edid = NULL;
-
if (!asyc->scaler.full) {
if (mode == DRM_MODE_SCALE_NONE)
omode = umode;
@@ -162,7 +156,7 @@ nv50_head_atomic_check_view(struct nv50_head_atom *armh,
*/
if ((asyc->scaler.underscan.mode == UNDERSCAN_ON ||
(asyc->scaler.underscan.mode == UNDERSCAN_AUTO &&
- drm_detect_hdmi_monitor(edid)))) {
+ connector->display_info.is_hdmi))) {
u32 bX = asyc->scaler.underscan.hborder;
u32 bY = asyc->scaler.underscan.vborder;
u32 r = (asyh->view.oH << 19) / asyh->view.oW;
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
index a11d16a16c3b..9e6f39912368 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
@@ -213,6 +213,12 @@ struct nvkm_gsp {
struct mutex mutex;;
struct idr idr;
} client_id;
+
+ /* A linked list of registry items. The registry RPC will be built from it. */
+ struct list_head registry_list;
+
+ /* The size of the registry RPC */
+ size_t registry_rpc_size;
};
static inline bool
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 856b3ef5edb8..938832a6af15 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -1034,7 +1034,7 @@ get_tmds_link_bandwidth(struct drm_connector *connector)
unsigned duallink_scale =
nouveau_duallink && nv_encoder->dcb->duallink_possible ? 2 : 1;
- if (drm_detect_hdmi_monitor(nv_connector->edid)) {
+ if (nv_connector->base.display_info.is_hdmi) {
info = &nv_connector->base.display_info;
duallink_scale = 1;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index a947e1d5f309..a58c31089613 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -32,7 +32,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_ttm.h>
#include <drm/drm_gem_ttm_helper.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_vblank.h>
@@ -846,9 +846,9 @@ static int nouveau_drm_probe(struct pci_dev *pdev,
goto fail_drm_dev_init;
if (nouveau_drm(drm_dev)->client.device.info.ram_size <= 32 * 1024 * 1024)
- drm_fbdev_generic_setup(drm_dev, 8);
+ drm_fbdev_ttm_setup(drm_dev, 8);
else
- drm_fbdev_generic_setup(drm_dev, 32);
+ drm_fbdev_ttm_setup(drm_dev, 32);
quirk_broken_nv_runpm(pdev);
return 0;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c
index abe41f7a3404..cf58f9da9139 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c
@@ -54,6 +54,8 @@
#include <nvrm/535.113.01/nvidia/kernel/inc/vgpu/rpc_global_enums.h>
#include <linux/acpi.h>
+#include <linux/ctype.h>
+#include <linux/parser.h>
#define GSP_MSG_MIN_SIZE GSP_PAGE_SIZE
#define GSP_MSG_MAX_SIZE GSP_PAGE_MIN_SIZE * 16
@@ -1080,53 +1082,365 @@ r535_gsp_rpc_unloading_guest_driver(struct nvkm_gsp *gsp, bool suspend)
return nvkm_gsp_rpc_wr(gsp, rpc, true);
}
+enum registry_type {
+ REGISTRY_TABLE_ENTRY_TYPE_DWORD = 1, /* 32-bit unsigned integer */
+ REGISTRY_TABLE_ENTRY_TYPE_BINARY = 2, /* Binary blob */
+ REGISTRY_TABLE_ENTRY_TYPE_STRING = 3, /* Null-terminated string */
+};
+
+/* An arbitrary limit to the length of a registry key */
+#define REGISTRY_MAX_KEY_LENGTH 64
+
+/**
+ * registry_list_entry - linked list member for a registry key/value
+ * @head: list_head struct
+ * @type: dword, binary, or string
+ * @klen: the length of name of the key
+ * @vlen: the length of the value
+ * @key: the key name
+ * @dword: the data, if REGISTRY_TABLE_ENTRY_TYPE_DWORD
+ * @binary: the data, if TYPE_BINARY or TYPE_STRING
+ *
+ * Every registry key/value is represented internally by this struct.
+ *
+ * Type DWORD is a simple 32-bit unsigned integer, and its value is stored in
+ * @dword.
+ *
+ * Types BINARY and STRING are variable-length binary blobs. The only real
+ * difference between BINARY and STRING is that STRING is null-terminated and
+ * is expected to contain only printable characters.
+ *
+ * Note: it is technically possible to have multiple keys with the same name
+ * but different types, but this is not useful since GSP-RM expects keys to
+ * have only one specific type.
+ */
+struct registry_list_entry {
+ struct list_head head;
+ enum registry_type type;
+ size_t klen;
+ char key[REGISTRY_MAX_KEY_LENGTH];
+ size_t vlen;
+ u32 dword; /* TYPE_DWORD */
+ u8 binary[] __counted_by(vlen); /* TYPE_BINARY or TYPE_STRING */
+};
+
+/**
+ * add_registry -- adds a registry entry
+ * @gsp: gsp pointer
+ * @key: name of the registry key
+ * @type: type of data
+ * @data: pointer to value
+ * @length: size of data, in bytes
+ *
+ * Adds a registry key/value pair to the registry database.
+ *
+ * This function collects the registry information in a linked list. After
+ * all registry keys have been added, build_registry() is used to create the
+ * RPC data structure.
+ *
+ * registry_rpc_size is a running total of the size of all registry keys.
+ * It's used to avoid an O(n) calculation of the size when the RPC is built.
+ *
+ * Returns 0 on success, or negative error code on error.
+ */
+static int add_registry(struct nvkm_gsp *gsp, const char *key,
+ enum registry_type type, const void *data, size_t length)
+{
+ struct registry_list_entry *reg;
+ const size_t nlen = strnlen(key, REGISTRY_MAX_KEY_LENGTH) + 1;
+ size_t alloc_size; /* extra bytes to alloc for binary or string value */
+
+ if (nlen > REGISTRY_MAX_KEY_LENGTH)
+ return -EINVAL;
+
+ alloc_size = (type == REGISTRY_TABLE_ENTRY_TYPE_DWORD) ? 0 : length;
+
+ reg = kmalloc(sizeof(*reg) + alloc_size, GFP_KERNEL);
+ if (!reg)
+ return -ENOMEM;
+
+ switch (type) {
+ case REGISTRY_TABLE_ENTRY_TYPE_DWORD:
+ reg->dword = *(const u32 *)(data);
+ break;
+ case REGISTRY_TABLE_ENTRY_TYPE_BINARY:
+ case REGISTRY_TABLE_ENTRY_TYPE_STRING:
+ memcpy(reg->binary, data, alloc_size);
+ break;
+ default:
+ nvkm_error(&gsp->subdev, "unrecognized registry type %u for '%s'\n",
+ type, key);
+ kfree(reg);
+ return -EINVAL;
+ }
+
+ memcpy(reg->key, key, nlen);
+ reg->klen = nlen;
+ reg->vlen = length;
+ reg->type = type;
+
+ list_add_tail(&reg->head, &gsp->registry_list);
+ gsp->registry_rpc_size += sizeof(PACKED_REGISTRY_ENTRY) + nlen + alloc_size;
+
+ return 0;
+}
+
+static int add_registry_num(struct nvkm_gsp *gsp, const char *key, u32 value)
+{
+ return add_registry(gsp, key, REGISTRY_TABLE_ENTRY_TYPE_DWORD,
+ &value, sizeof(u32));
+}
+
+static int add_registry_string(struct nvkm_gsp *gsp, const char *key, const char *value)
+{
+ return add_registry(gsp, key, REGISTRY_TABLE_ENTRY_TYPE_STRING,
+ value, strlen(value) + 1);
+}
+
+/**
+ * build_registry -- create the registry RPC data
+ * @gsp: gsp pointer
+ * @registry: pointer to the RPC payload to fill
+ *
+ * After all registry key/value pairs have been added, call this function to
+ * build the RPC.
+ *
+ * The registry RPC looks like this:
+ *
+ * +-----------------+
+ * |NvU32 size; |
+ * |NvU32 numEntries;|
+ * +-----------------+
+ * +----------------------------------------+
+ * |PACKED_REGISTRY_ENTRY |
+ * +----------------------------------------+
+ * |Null-terminated key (string) for entry 0|
+ * +----------------------------------------+
+ * |Binary/string data value for entry 0 | (only if necessary)
+ * +----------------------------------------+
+ *
+ * +----------------------------------------+
+ * |PACKED_REGISTRY_ENTRY |
+ * +----------------------------------------+
+ * |Null-terminated key (string) for entry 1|
+ * +----------------------------------------+
+ * |Binary/string data value for entry 1 | (only if necessary)
+ * +----------------------------------------+
+ * ... (and so on, one copy for each entry)
+ *
+ *
+ * The 'data' field of an entry is either a 32-bit integer (for type DWORD)
+ * or an offset into the PACKED_REGISTRY_TABLE (for types BINARY and STRING).
+ *
+ * All memory allocated by add_registry() is released.
+ */
+static void build_registry(struct nvkm_gsp *gsp, PACKED_REGISTRY_TABLE *registry)
+{
+ struct registry_list_entry *reg, *n;
+ size_t str_offset;
+ unsigned int i = 0;
+
+ registry->numEntries = list_count_nodes(&gsp->registry_list);
+ str_offset = struct_size(registry, entries, registry->numEntries);
+
+ list_for_each_entry_safe(reg, n, &gsp->registry_list, head) {
+ registry->entries[i].type = reg->type;
+ registry->entries[i].length = reg->vlen;
+
+ /* Append the key name to the table */
+ registry->entries[i].nameOffset = str_offset;
+ memcpy((void *)registry + str_offset, reg->key, reg->klen);
+ str_offset += reg->klen;
+
+ switch (reg->type) {
+ case REGISTRY_TABLE_ENTRY_TYPE_DWORD:
+ registry->entries[i].data = reg->dword;
+ break;
+ case REGISTRY_TABLE_ENTRY_TYPE_BINARY:
+ case REGISTRY_TABLE_ENTRY_TYPE_STRING:
+ /* If the type is binary or string, also append the value */
+ memcpy((void *)registry + str_offset, reg->binary, reg->vlen);
+ registry->entries[i].data = str_offset;
+ str_offset += reg->vlen;
+ break;
+ default:
+ break;
+ }
+
+ i++;
+ list_del(&reg->head);
+ kfree(reg);
+ }
+
+ /* Double-check that we calculated the sizes correctly */
+ WARN_ON(gsp->registry_rpc_size != str_offset);
+
+ registry->size = gsp->registry_rpc_size;
+}
+
+/**
+ * clean_registry -- clean up registry memory in case of error
+ * @gsp: gsp pointer
+ *
+ * Call this function to clean up all memory allocated by add_registry()
+ * in case of error and build_registry() is not called.
+ */
+static void clean_registry(struct nvkm_gsp *gsp)
+{
+ struct registry_list_entry *reg, *n;
+
+ list_for_each_entry_safe(reg, n, &gsp->registry_list, head) {
+ list_del(&reg->head);
+ kfree(reg);
+ }
+
+ gsp->registry_rpc_size = sizeof(PACKED_REGISTRY_TABLE);
+}
+
+MODULE_PARM_DESC(NVreg_RegistryDwords,
+ "A semicolon-separated list of key=integer pairs of GSP-RM registry keys");
+static char *NVreg_RegistryDwords;
+module_param(NVreg_RegistryDwords, charp, 0400);
+
/* dword only */
struct nv_gsp_registry_entries {
const char *name;
u32 value;
};
+/**
+ * r535_registry_entries - required registry entries for GSP-RM
+ *
+ * This array lists registry entries that are required for GSP-RM to
+ * function correctly.
+ *
+ * RMSecBusResetEnable - enables PCI secondary bus reset
+ * RMForcePcieConfigSave - forces GSP-RM to preserve PCI configuration
+ * registers on any PCI reset.
+ */
static const struct nv_gsp_registry_entries r535_registry_entries[] = {
{ "RMSecBusResetEnable", 1 },
{ "RMForcePcieConfigSave", 1 },
};
#define NV_GSP_REG_NUM_ENTRIES ARRAY_SIZE(r535_registry_entries)
+/**
+ * strip - strips all characters in 'reject' from 's'
+ * @s: string to strip
+ * @reject: string of characters to remove
+ *
+ * 's' is modified.
+ *
+ * Returns the length of the new string.
+ */
+static size_t strip(char *s, const char *reject)
+{
+ char *p = s, *p2 = s;
+ size_t length = 0;
+ char c;
+
+ do {
+ while ((c = *p2) && strchr(reject, c))
+ p2++;
+
+ *p++ = c = *p2++;
+ length++;
+ } while (c);
+
+ return length;
+}
+
+/**
+ * r535_gsp_rpc_set_registry - build registry RPC and call GSP-RM
+ * @gsp: gsp pointer
+ *
+ * The GSP-RM registry is a set of key/value pairs that configure some aspects
+ * of GSP-RM. The keys are strings, and the values are 32-bit integers.
+ *
+ * The registry is built from a combination of a static hard-coded list (see
+ * above) and entries passed on the driver's command line.
+ */
static int
r535_gsp_rpc_set_registry(struct nvkm_gsp *gsp)
{
PACKED_REGISTRY_TABLE *rpc;
- char *strings;
- int str_offset;
- int i;
- size_t rpc_size = struct_size(rpc, entries, NV_GSP_REG_NUM_ENTRIES);
+ unsigned int i;
+ int ret;
- /* add strings + null terminator */
- for (i = 0; i < NV_GSP_REG_NUM_ENTRIES; i++)
- rpc_size += strlen(r535_registry_entries[i].name) + 1;
+ INIT_LIST_HEAD(&gsp->registry_list);
+ gsp->registry_rpc_size = sizeof(PACKED_REGISTRY_TABLE);
- rpc = nvkm_gsp_rpc_get(gsp, NV_VGPU_MSG_FUNCTION_SET_REGISTRY, rpc_size);
- if (IS_ERR(rpc))
- return PTR_ERR(rpc);
+ for (i = 0; i < NV_GSP_REG_NUM_ENTRIES; i++) {
+ ret = add_registry_num(gsp, r535_registry_entries[i].name,
+ r535_registry_entries[i].value);
+ if (ret)
+ goto fail;
+ }
- rpc->numEntries = NV_GSP_REG_NUM_ENTRIES;
+ /*
+ * The NVreg_RegistryDwords parameter is a string of key=value
+ * pairs separated by semicolons. We need to extract and trim each
+ * substring, and then parse the substring to extract the key and
+ * value.
+ */
+ if (NVreg_RegistryDwords) {
+ char *p = kstrdup(NVreg_RegistryDwords, GFP_KERNEL);
+ char *start, *next = p, *equal;
+
+ if (!p) {
+ ret = -ENOMEM;
+ goto fail;
+ }
- str_offset = offsetof(typeof(*rpc), entries[NV_GSP_REG_NUM_ENTRIES]);
- strings = (char *)rpc + str_offset;
- for (i = 0; i < NV_GSP_REG_NUM_ENTRIES; i++) {
- int name_len = strlen(r535_registry_entries[i].name) + 1;
-
- rpc->entries[i].nameOffset = str_offset;
- rpc->entries[i].type = 1;
- rpc->entries[i].data = r535_registry_entries[i].value;
- rpc->entries[i].length = 4;
- memcpy(strings, r535_registry_entries[i].name, name_len);
- strings += name_len;
- str_offset += name_len;
+ /* Remove any whitespace from the parameter string */
+ strip(p, " \t\n");
+
+ while ((start = strsep(&next, ";"))) {
+ long value;
+
+ equal = strchr(start, '=');
+ if (!equal || equal == start || equal[1] == 0) {
+ nvkm_error(&gsp->subdev,
+ "ignoring invalid registry string '%s'\n",
+ start);
+ continue;
+ }
+
+ /* Truncate the key=value string to just key */
+ *equal = 0;
+
+ ret = kstrtol(equal + 1, 0, &value);
+ if (!ret) {
+ ret = add_registry_num(gsp, start, value);
+ } else {
+ /* Not a number, so treat it as a string */
+ ret = add_registry_string(gsp, start, equal + 1);
+ }
+
+ if (ret) {
+ nvkm_error(&gsp->subdev,
+ "ignoring invalid registry key/value '%s=%s'\n",
+ start, equal + 1);
+ continue;
+ }
+ }
+
+ kfree(p);
+ }
+
+ rpc = nvkm_gsp_rpc_get(gsp, NV_VGPU_MSG_FUNCTION_SET_REGISTRY, gsp->registry_rpc_size);
+ if (IS_ERR(rpc)) {
+ ret = PTR_ERR(rpc);
+ goto fail;
}
- rpc->size = str_offset;
+
+ build_registry(gsp, rpc);
return nvkm_gsp_rpc_wr(gsp, rpc, false);
+
+fail:
+ clean_registry(gsp);
+ return ret;
}
#if defined(CONFIG_ACPI) && defined(CONFIG_X86)
diff --git a/drivers/gpu/drm/omapdrm/Kconfig b/drivers/gpu/drm/omapdrm/Kconfig
index 6c49270cb290..85ed92042b74 100644
--- a/drivers/gpu/drm/omapdrm/Kconfig
+++ b/drivers/gpu/drm/omapdrm/Kconfig
@@ -2,7 +2,7 @@
config DRM_OMAP
tristate "OMAP DRM"
depends on DRM && OF
- depends on ARCH_OMAP2PLUS
+ depends on ARCH_OMAP2PLUS || COMPILE_TEST
select DRM_KMS_HELPER
select FB_DMAMEM_HELPERS_DEFERRED if DRM_FBDEV_EMULATION
select VIDEOMODE_HELPERS
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c
index 9ea0c64c26b5..fdae677558f3 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem.c
@@ -1023,8 +1023,8 @@ struct sg_table *omap_gem_get_sg(struct drm_gem_object *obj,
if (addr) {
for_each_sg(sgt->sgl, sg, count, i) {
- sg_set_page(sg, phys_to_page(addr), len,
- offset_in_page(addr));
+ sg_set_page(sg, pfn_to_page(__phys_to_pfn(addr)),
+ len, offset_in_page(addr));
sg_dma_address(sg) = addr;
sg_dma_len(sg) = len;
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 982324ef5a41..241406798232 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -145,6 +145,15 @@ config DRM_PANEL_LVDS
handling of power supplies or control signals. It implements automatic
backlight handling if the panel is attached to a backlight controller.
+config DRM_PANEL_HIMAX_HX83102
+ tristate "Himax HX83102-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
+ Himax HX83102 controller.
+
config DRM_PANEL_HIMAX_HX83112A
tristate "Himax HX83112A-based DSI panel"
depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index f0203f6e02f4..051b75b3df7b 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_DRM_PANEL_EBBG_FT8719) += panel-ebbg-ft8719.o
obj-$(CONFIG_DRM_PANEL_ELIDA_KD35T133) += panel-elida-kd35t133.o
obj-$(CONFIG_DRM_PANEL_FEIXIN_K101_IM2BA02) += panel-feixin-k101-im2ba02.o
obj-$(CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D) += panel-feiyang-fy07024di26a30d.o
+obj-$(CONFIG_DRM_PANEL_HIMAX_HX83102) += panel-himax-hx83102.o
obj-$(CONFIG_DRM_PANEL_HIMAX_HX83112A) += panel-himax-hx83112a.o
obj-$(CONFIG_DRM_PANEL_HIMAX_HX8394) += panel-himax-hx8394.o
obj-$(CONFIG_DRM_PANEL_ILITEK_IL9322) += panel-ilitek-ili9322.o
diff --git a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
index 0ffe8f8c01de..f7beace455c3 100644
--- a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
+++ b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
@@ -17,6 +17,8 @@
#include <video/mipi_display.h>
+struct boe_panel;
+
struct panel_desc {
const struct drm_display_mode *modes;
unsigned int bpc;
@@ -32,7 +34,7 @@ struct panel_desc {
unsigned long mode_flags;
enum mipi_dsi_pixel_format format;
- const struct panel_init_cmd *init_cmds;
+ int (*init)(struct boe_panel *boe);
unsigned int lanes;
bool discharge_on_disable;
bool lp11_before_reset;
@@ -54,1396 +56,1343 @@ struct boe_panel {
bool prepared;
};
-enum dsi_cmd_type {
- INIT_DCS_CMD,
- DELAY_CMD,
-};
+static int boe_tv110c9m_init(struct boe_panel *boe)
+{
+ struct mipi_dsi_multi_context ctx = { .dsi = boe->dsi };
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0xd9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x78);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x5a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x63);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x91);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x73);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x95, 0xe6);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x96, 0xf0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6d, 0x66);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x75, 0xa2);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x77, 0x3b);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4d, 0x00, 0x6d,
+ 0x00, 0x89, 0x00, 0xa1, 0x00, 0xb6, 0x00, 0xc9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x00, 0xda, 0x01, 0x13, 0x01, 0x3c, 0x01, 0x7e,
+ 0x01, 0xab, 0x01, 0xf7, 0x02, 0x2f, 0x02, 0x31);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x02, 0x67, 0x02, 0xa6, 0x02, 0xd1, 0x03, 0x08,
+ 0x03, 0x2e, 0x03, 0x5b, 0x03, 0x6b, 0x03, 0x7b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x03, 0x8e, 0x03, 0xa2, 0x03, 0xb7, 0x03, 0xe7,
+ 0x03, 0xfd, 0x03, 0xff);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4d, 0x00, 0x6d,
+ 0x00, 0x89, 0x00, 0xa1, 0x00, 0xb6, 0x00, 0xc9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x00, 0xda, 0x01, 0x13, 0x01, 0x3c, 0x01, 0x7e,
+ 0x01, 0xab, 0x01, 0xf7, 0x02, 0x2f, 0x02, 0x31);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x02, 0x67, 0x02, 0xa6, 0x02, 0xd1, 0x03, 0x08,
+ 0x03, 0x2e, 0x03, 0x5b, 0x03, 0x6b, 0x03, 0x7b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x03, 0x8e, 0x03, 0xa2, 0x03, 0xb7, 0x03, 0xe7,
+ 0x03, 0xfd, 0x03, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4d, 0x00, 0x6d,
+ 0x00, 0x89, 0x00, 0xa1, 0x00, 0xb6, 0x00, 0xc9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x00, 0xda, 0x01, 0x13, 0x01, 0x3c, 0x01, 0x7e,
+ 0x01, 0xab, 0x01, 0xf7, 0x02, 0x2f, 0x02, 0x31);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x02, 0x67, 0x02, 0xa6, 0x02, 0xd1, 0x03, 0x08,
+ 0x03, 0x2e, 0x03, 0x5b, 0x03, 0x6b, 0x03, 0x7b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0x03, 0x8e, 0x03, 0xa2, 0x03, 0xb7, 0x03, 0xe7,
+ 0x03, 0xfd, 0x03, 0xff);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x21);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x45, 0x00, 0x65,
+ 0x00, 0x81, 0x00, 0x99, 0x00, 0xae, 0x00, 0xc1);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x00, 0xd2, 0x01, 0x0b, 0x01, 0x34, 0x01, 0x76,
+ 0x01, 0xa3, 0x01, 0xef, 0x02, 0x27, 0x02, 0x29);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x02, 0x5f, 0x02, 0x9e, 0x02, 0xc9, 0x03, 0x00,
+ 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x03, 0x86, 0x03, 0x9a, 0x03, 0xaf, 0x03, 0xdf,
+ 0x03, 0xf5, 0x03, 0xe0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x45, 0x00, 0x65,
+ 0x00, 0x81, 0x00, 0x99, 0x00, 0xae, 0x00, 0xc1);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x00, 0xd2, 0x01, 0x0b, 0x01, 0x34, 0x01, 0x76,
+ 0x01, 0xa3, 0x01, 0xef, 0x02, 0x27, 0x02, 0x29);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x02, 0x5f, 0x02, 0x9e, 0x02, 0xc9, 0x03, 0x00,
+ 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x03, 0x86, 0x03, 0x9a, 0x03, 0xaf, 0x03, 0xdf,
+ 0x03, 0xf5, 0x03, 0xe0);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x45, 0x00, 0x65,
+ 0x00, 0x81, 0x00, 0x99, 0x00, 0xae, 0x00, 0xc1);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x00, 0xd2, 0x01, 0x0b, 0x01, 0x34, 0x01, 0x76,
+ 0x01, 0xa3, 0x01, 0xef, 0x02, 0x27, 0x02, 0x29);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x02, 0x5f, 0x02, 0x9e, 0x02, 0xc9, 0x03, 0x00,
+ 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0x03, 0x86, 0x03, 0x9a, 0x03, 0xaf, 0x03, 0xdf,
+ 0x03, 0xf5, 0x03, 0xe0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x24);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x01, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x1c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x03, 0x1c);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x1d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0x1d);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x04);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x0f);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0a, 0x0e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0b, 0x0e);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0c, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x0d);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x0c);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x10, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x11, 0x08);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x12, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x13, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x15, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x16, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x17, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x18, 0x1c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x19, 0x1c);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1a, 0x1d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1b, 0x1d);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1c, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1d, 0x04);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1e, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1f, 0x0f);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x0e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x21, 0x0e);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x23, 0x0d);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x0c);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x08);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x28, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2d, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2f, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0x32);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x37, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x38, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x5d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x60);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3d, 0x42);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3f, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x43, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x47, 0x66);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4a, 0x5d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4b, 0x60);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4c, 0x91);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4d, 0x21);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4e, 0x43);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x51, 0x12);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x52, 0x34);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x55, 0x82, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x56, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x58, 0x21);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x59, 0x30);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5a, 0x60);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5b, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5e, 0x00, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5f, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x65, 0x82);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7e, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7f, 0x3c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x82, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x97, 0xc0);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x05, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x91, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x92, 0xa9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x93, 0x1a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x94, 0x96);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd7, 0x55);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xda, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdb, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0xa9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdd, 0x22);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdf, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0xa9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe2, 0xa9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe3, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe4, 0xa9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0xa9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5c, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x8d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x8e, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x90);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x25);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x19, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1f, 0x60);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0x60);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x60);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3f, 0xe0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x40, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x44, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x45, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x48, 0x60);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x49, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5b, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5c, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5e, 0xd0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0x60);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x62, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xf1, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x2a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x64, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x67, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6a, 0x16);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x70, 0x30);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa2, 0xf3);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa3, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa4, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa5, 0xff);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x08);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0xa1);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x31);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x28);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x30);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0c, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x11, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x12, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x13, 0x56);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0x57);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x15, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x16, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x17, 0xa0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x18, 0x86);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x19, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1a, 0x7f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1b, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1c, 0xbf);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x23, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x7f);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1e, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1f, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2f, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x31, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x32, 0x7d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0x78);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x9e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x4e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa9, 0x49);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xaa, 0x4b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xab, 0x48);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xac, 0x43);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xad, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xae, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xaf, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x54);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x4e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x4d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x4c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x41);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x47);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x53);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x3e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x51);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x3c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x3b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x45);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x55);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0x3d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x52);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x4a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0x39);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0x3a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x42);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x27);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x56, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x58, 0x80);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x59, 0x75);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5a, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5b, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5c, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5e, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5f, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x60, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0x2e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x62, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x63, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x64, 0x43);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x65, 0x2d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x66, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x67, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x68, 0x44);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x78, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x2a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0x2f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x23, 0x08);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0xf8);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x28, 0x1a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x1a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2d, 0x1a);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x23);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x80);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0xe0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0x60);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x16, 0xc0);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0xf0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x08);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x18, 0x40);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x51, 0x00, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x53, 0x24);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x55, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0x13);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x03, 0x96, 0x1a, 0x04, 0x04);
+
+ mipi_dsi_msleep(&ctx, 100);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x11);
+
+ mipi_dsi_msleep(&ctx, 200);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x29);
+
+ mipi_dsi_msleep(&ctx, 100);
-struct panel_init_cmd {
- enum dsi_cmd_type type;
- size_t len;
- const char *data;
+ return 0;
};
-#define _INIT_DCS_CMD(...) { \
- .type = INIT_DCS_CMD, \
- .len = sizeof((char[]){__VA_ARGS__}), \
- .data = (char[]){__VA_ARGS__} }
-
-#define _INIT_DELAY_CMD(...) { \
- .type = DELAY_CMD,\
- .len = sizeof((char[]){__VA_ARGS__}), \
- .data = (char[]){__VA_ARGS__} }
-
-static const struct panel_init_cmd boe_tv110c9m_init_cmd[] = {
- _INIT_DCS_CMD(0xFF, 0x20),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0x05, 0xD9),
- _INIT_DCS_CMD(0x07, 0x78),
- _INIT_DCS_CMD(0x08, 0x5A),
- _INIT_DCS_CMD(0x0D, 0x63),
- _INIT_DCS_CMD(0x0E, 0x91),
- _INIT_DCS_CMD(0x0F, 0x73),
- _INIT_DCS_CMD(0x95, 0xE6),
- _INIT_DCS_CMD(0x96, 0xF0),
- _INIT_DCS_CMD(0x30, 0x00),
- _INIT_DCS_CMD(0x6D, 0x66),
- _INIT_DCS_CMD(0x75, 0xA2),
- _INIT_DCS_CMD(0x77, 0x3B),
+static int inx_hj110iz_init(struct boe_panel *boe)
+{
+ struct mipi_dsi_multi_context ctx = { .dsi = boe->dsi };
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0xd1);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0xc0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x87);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x4b);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x63);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x91);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x69);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x94, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x95, 0xf5);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x96, 0xf5);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x9d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x9e, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x69, 0x98);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x75, 0xa2);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x77, 0xb3);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x58, 0x43);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x24);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x91, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x92, 0x4c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x94, 0x86);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x60, 0x96);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0xd0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x63, 0x70);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xca);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x01, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x03, 0x29);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x22);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0x22);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x1d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x1c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0a, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0b, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0c, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x0e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x10, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x11, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x12, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x13, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x15, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x16, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x17, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x18, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x19, 0x29);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1a, 0x22);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1b, 0x22);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1c, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1d, 0x1d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1e, 0x1c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1f, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x21, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x23, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x0e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x28, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x03);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2f, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x35);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x37, 0xa7);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x32);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3d, 0x12);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3f, 0x33);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x40, 0x31);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x41, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x42, 0x42);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x47, 0x77);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x48, 0x77);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4a, 0x45);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4b, 0x45);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4c, 0x14);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4d, 0x21);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4e, 0x43);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4f, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x55, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x56, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x58, 0x21);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x59, 0x70);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5a, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5b, 0x32);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5c, 0x88);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5e, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5f, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7a, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7b, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7c, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7e, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7f, 0x3c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x80, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x81, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x82, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x97, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x10);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd7, 0x55);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x55);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd9, 0x23);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xda, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdd, 0x55);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x27);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdf, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe2, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe3, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe4, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe7, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe8, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe9, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xea, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xeb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xee, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xef, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xf0, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x05, 0x00, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x25);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xf1, 0x10);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1e, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1f, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x32);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x32);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3f, 0x80);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x40, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x43, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x44, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x45, 0x46);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x48, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x49, 0x32);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5b, 0x80);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5c, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5d, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5e, 0x32);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5f, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x60, 0x32);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x62, 0x32);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x68, 0x0c);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6c, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6e, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x78, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x79, 0xc5);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7a, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7b, 0xb0);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0xa1);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x31);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0a, 0xf4);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x30);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0c, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x11, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x12, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x13, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0x58);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x15, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x16, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x17, 0xa0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x18, 0x86);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x23, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x19, 0x0e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1a, 0x31);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1b, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1c, 0x29);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x0e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x31);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1e, 0x62);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1f, 0x62);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2f, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x62);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x31, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x32, 0x7f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0x89);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x67);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x62);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x06);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x89);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x4e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa9, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xaa, 0x3e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xab, 0x3d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xac, 0x3c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xad, 0x3b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xae, 0x3a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xaf, 0x39);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x38);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x27);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd0, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd1, 0x54);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x43);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdf, 0x02);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x18);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x56, 0x06);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x58, 0x80);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x59, 0x78);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5a, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5b, 0x18);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5c, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5d, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5e, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5f, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x60, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0x1c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x62, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x63, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x64, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x65, 0x1b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x66, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x67, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x68, 0x44);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x98, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x9b, 0xbe);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xab, 0x14);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x28);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x2a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0x2f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x23, 0x08);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x62);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0xf8);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x28, 0x1a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x1a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2d, 0x1a);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x64, 0x96);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x65, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x66, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x67, 0x96);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x68, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x69, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6a, 0x96);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6b, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6c, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x70, 0x92);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x71, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x72, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x79, 0x96);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7a, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x88, 0x96);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x89, 0x10);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa2, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa3, 0x30);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa4, 0xc0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa5, 0x03);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe8, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x97, 0x3c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x98, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x99, 0x95);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x9a, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x9b, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x9c, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x9d, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x9e, 0x90);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x25);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x13, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0xd7);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdb, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0xd7);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x17, 0xcf);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x19, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1b, 0x5b);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x20);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x24, 0x00, 0x38,
+ 0x00, 0x4c, 0x00, 0x5e, 0x00, 0x6f, 0x00, 0x7e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x00, 0x8c, 0x00, 0xbe, 0x00, 0xe5, 0x01, 0x27,
+ 0x01, 0x58, 0x01, 0xa8, 0x01, 0xe8, 0x01, 0xea);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x02, 0x28, 0x02, 0x71, 0x02, 0x9e, 0x02, 0xda,
+ 0x03, 0x00, 0x03, 0x31, 0x03, 0x40, 0x03, 0x51);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x03, 0x62, 0x03, 0x75, 0x03, 0x89, 0x03, 0x9c,
+ 0x03, 0xaa, 0x03, 0xb2);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x27, 0x00, 0x3d,
+ 0x00, 0x52, 0x00, 0x64, 0x00, 0x75, 0x00, 0x84);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x00, 0x93, 0x00, 0xc5, 0x00, 0xec, 0x01, 0x2c,
+ 0x01, 0x5d, 0x01, 0xac, 0x01, 0xec, 0x01, 0xee);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x02, 0x2b, 0x02, 0x73, 0x02, 0xa0, 0x02, 0xdb,
+ 0x03, 0x01, 0x03, 0x31, 0x03, 0x41, 0x03, 0x51);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x03, 0x63, 0x03, 0x75, 0x03, 0x89, 0x03, 0x9c,
+ 0x03, 0xaa, 0x03, 0xb2);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x2a, 0x00, 0x40,
+ 0x00, 0x56, 0x00, 0x68, 0x00, 0x7a, 0x00, 0x89);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x00, 0x98, 0x00, 0xc9, 0x00, 0xf1, 0x01, 0x30,
+ 0x01, 0x61, 0x01, 0xb0, 0x01, 0xef, 0x01, 0xf1);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x02, 0x2e, 0x02, 0x76, 0x02, 0xa3, 0x02, 0xdd,
+ 0x03, 0x02, 0x03, 0x32, 0x03, 0x42, 0x03, 0x53);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0x03, 0x66, 0x03, 0x75, 0x03, 0x89, 0x03, 0x9c,
+ 0x03, 0xaa, 0x03, 0xb2);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x21);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x24, 0x00, 0x38,
+ 0x00, 0x4c, 0x00, 0x5e, 0x00, 0x6f, 0x00, 0x7e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x00, 0x8c, 0x00, 0xbe, 0x00, 0xe5, 0x01, 0x27,
+ 0x01, 0x58, 0x01, 0xa8, 0x01, 0xe8, 0x01, 0xea);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x02, 0x28, 0x02, 0x71, 0x02, 0x9e, 0x02, 0xda,
+ 0x03, 0x00, 0x03, 0x31, 0x03, 0x40, 0x03, 0x51);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x03, 0x62, 0x03, 0x77, 0x03, 0x90, 0x03, 0xac,
+ 0x03, 0xca, 0x03, 0xda);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x27, 0x00, 0x3d,
+ 0x00, 0x52, 0x00, 0x64, 0x00, 0x75, 0x00, 0x84);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x00, 0x93, 0x00, 0xc5, 0x00, 0xec, 0x01, 0x2c,
+ 0x01, 0x5d, 0x01, 0xac, 0x01, 0xec, 0x01, 0xee);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x02, 0x2b, 0x02, 0x73, 0x02, 0xa0, 0x02, 0xdb,
+ 0x03, 0x01, 0x03, 0x31, 0x03, 0x41, 0x03, 0x51);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x03, 0x63, 0x03, 0x77, 0x03, 0x90, 0x03, 0xac,
+ 0x03, 0xca, 0x03, 0xda);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x2a, 0x00, 0x40,
+ 0x00, 0x56, 0x00, 0x68, 0x00, 0x7a, 0x00, 0x89);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x00, 0x98, 0x00, 0xc9, 0x00, 0xf1, 0x01, 0x30,
+ 0x01, 0x61, 0x01, 0xb0, 0x01, 0xef, 0x01, 0xf1);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x02, 0x2e, 0x02, 0x76, 0x02, 0xa3, 0x02, 0xdd,
+ 0x03, 0x02, 0x03, 0x32, 0x03, 0x42, 0x03, 0x53);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0x03, 0x66, 0x03, 0x77, 0x03, 0x90, 0x03, 0xac,
+ 0x03, 0xca, 0x03, 0xda);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0xf0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x08);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x01);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x20);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x18, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x10);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x10);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x03, 0xae, 0x1a, 0x04, 0x04);
+
+ mipi_dsi_msleep(&ctx, 100);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x11);
+
+ mipi_dsi_msleep(&ctx, 200);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x29);
+
+ mipi_dsi_msleep(&ctx, 100);
- _INIT_DCS_CMD(0xB0, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4D, 0x00, 0x6D, 0x00, 0x89, 0x00, 0xA1, 0x00, 0xB6, 0x00, 0xC9),
- _INIT_DCS_CMD(0xB1, 0x00, 0xDA, 0x01, 0x13, 0x01, 0x3C, 0x01, 0x7E, 0x01, 0xAB, 0x01, 0xF7, 0x02, 0x2F, 0x02, 0x31),
- _INIT_DCS_CMD(0xB2, 0x02, 0x67, 0x02, 0xA6, 0x02, 0xD1, 0x03, 0x08, 0x03, 0x2E, 0x03, 0x5B, 0x03, 0x6B, 0x03, 0x7B),
- _INIT_DCS_CMD(0xB3, 0x03, 0x8E, 0x03, 0xA2, 0x03, 0xB7, 0x03, 0xE7, 0x03, 0xFD, 0x03, 0xFF),
-
- _INIT_DCS_CMD(0xB4, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4D, 0x00, 0x6D, 0x00, 0x89, 0x00, 0xA1, 0x00, 0xB6, 0x00, 0xC9),
- _INIT_DCS_CMD(0xB5, 0x00, 0xDA, 0x01, 0x13, 0x01, 0x3C, 0x01, 0x7E, 0x01, 0xAB, 0x01, 0xF7, 0x02, 0x2F, 0x02, 0x31),
- _INIT_DCS_CMD(0xB6, 0x02, 0x67, 0x02, 0xA6, 0x02, 0xD1, 0x03, 0x08, 0x03, 0x2E, 0x03, 0x5B, 0x03, 0x6B, 0x03, 0x7B),
- _INIT_DCS_CMD(0xB7, 0x03, 0x8E, 0x03, 0xA2, 0x03, 0xB7, 0x03, 0xE7, 0x03, 0xFD, 0x03, 0xFF),
- _INIT_DCS_CMD(0xB8, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4D, 0x00, 0x6D, 0x00, 0x89, 0x00, 0xA1, 0x00, 0xB6, 0x00, 0xC9),
- _INIT_DCS_CMD(0xB9, 0x00, 0xDA, 0x01, 0x13, 0x01, 0x3C, 0x01, 0x7E, 0x01, 0xAB, 0x01, 0xF7, 0x02, 0x2F, 0x02, 0x31),
- _INIT_DCS_CMD(0xBA, 0x02, 0x67, 0x02, 0xA6, 0x02, 0xD1, 0x03, 0x08, 0x03, 0x2E, 0x03, 0x5B, 0x03, 0x6B, 0x03, 0x7B),
- _INIT_DCS_CMD(0xBB, 0x03, 0x8E, 0x03, 0xA2, 0x03, 0xB7, 0x03, 0xE7, 0x03, 0xFD, 0x03, 0xFF),
-
- _INIT_DCS_CMD(0xFF, 0x21),
- _INIT_DCS_CMD(0xFB, 0x01),
-
- _INIT_DCS_CMD(0xB0, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x45, 0x00, 0x65, 0x00, 0x81, 0x00, 0x99, 0x00, 0xAE, 0x00, 0xC1),
- _INIT_DCS_CMD(0xB1, 0x00, 0xD2, 0x01, 0x0B, 0x01, 0x34, 0x01, 0x76, 0x01, 0xA3, 0x01, 0xEF, 0x02, 0x27, 0x02, 0x29),
- _INIT_DCS_CMD(0xB2, 0x02, 0x5F, 0x02, 0x9E, 0x02, 0xC9, 0x03, 0x00, 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73),
-
- _INIT_DCS_CMD(0xB3, 0x03, 0x86, 0x03, 0x9A, 0x03, 0xAF, 0x03, 0xDF, 0x03, 0xF5, 0x03, 0xE0),
- _INIT_DCS_CMD(0xB4, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x45, 0x00, 0x65, 0x00, 0x81, 0x00, 0x99, 0x00, 0xAE, 0x00, 0xC1),
- _INIT_DCS_CMD(0xB5, 0x00, 0xD2, 0x01, 0x0B, 0x01, 0x34, 0x01, 0x76, 0x01, 0xA3, 0x01, 0xEF, 0x02, 0x27, 0x02, 0x29),
- _INIT_DCS_CMD(0xB6, 0x02, 0x5F, 0x02, 0x9E, 0x02, 0xC9, 0x03, 0x00, 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73),
- _INIT_DCS_CMD(0xB7, 0x03, 0x86, 0x03, 0x9A, 0x03, 0xAF, 0x03, 0xDF, 0x03, 0xF5, 0x03, 0xE0),
-
- _INIT_DCS_CMD(0xB8, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x45, 0x00, 0x65, 0x00, 0x81, 0x00, 0x99, 0x00, 0xAE, 0x00, 0xC1),
- _INIT_DCS_CMD(0xB9, 0x00, 0xD2, 0x01, 0x0B, 0x01, 0x34, 0x01, 0x76, 0x01, 0xA3, 0x01, 0xEF, 0x02, 0x27, 0x02, 0x29),
- _INIT_DCS_CMD(0xBA, 0x02, 0x5F, 0x02, 0x9E, 0x02, 0xC9, 0x03, 0x00, 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73),
-
- _INIT_DCS_CMD(0xBB, 0x03, 0x86, 0x03, 0x9A, 0x03, 0xAF, 0x03, 0xDF, 0x03, 0xF5, 0x03, 0xE0),
- _INIT_DCS_CMD(0xFF, 0x24),
- _INIT_DCS_CMD(0xFB, 0x01),
-
- _INIT_DCS_CMD(0x00, 0x00),
- _INIT_DCS_CMD(0x01, 0x00),
-
- _INIT_DCS_CMD(0x02, 0x1C),
- _INIT_DCS_CMD(0x03, 0x1C),
-
- _INIT_DCS_CMD(0x04, 0x1D),
- _INIT_DCS_CMD(0x05, 0x1D),
-
- _INIT_DCS_CMD(0x06, 0x04),
- _INIT_DCS_CMD(0x07, 0x04),
-
- _INIT_DCS_CMD(0x08, 0x0F),
- _INIT_DCS_CMD(0x09, 0x0F),
-
- _INIT_DCS_CMD(0x0A, 0x0E),
- _INIT_DCS_CMD(0x0B, 0x0E),
-
- _INIT_DCS_CMD(0x0C, 0x0D),
- _INIT_DCS_CMD(0x0D, 0x0D),
-
- _INIT_DCS_CMD(0x0E, 0x0C),
- _INIT_DCS_CMD(0x0F, 0x0C),
-
- _INIT_DCS_CMD(0x10, 0x08),
- _INIT_DCS_CMD(0x11, 0x08),
-
- _INIT_DCS_CMD(0x12, 0x00),
- _INIT_DCS_CMD(0x13, 0x00),
- _INIT_DCS_CMD(0x14, 0x00),
- _INIT_DCS_CMD(0x15, 0x00),
-
- _INIT_DCS_CMD(0x16, 0x00),
- _INIT_DCS_CMD(0x17, 0x00),
-
- _INIT_DCS_CMD(0x18, 0x1C),
- _INIT_DCS_CMD(0x19, 0x1C),
-
- _INIT_DCS_CMD(0x1A, 0x1D),
- _INIT_DCS_CMD(0x1B, 0x1D),
-
- _INIT_DCS_CMD(0x1C, 0x04),
- _INIT_DCS_CMD(0x1D, 0x04),
-
- _INIT_DCS_CMD(0x1E, 0x0F),
- _INIT_DCS_CMD(0x1F, 0x0F),
-
- _INIT_DCS_CMD(0x20, 0x0E),
- _INIT_DCS_CMD(0x21, 0x0E),
-
- _INIT_DCS_CMD(0x22, 0x0D),
- _INIT_DCS_CMD(0x23, 0x0D),
-
- _INIT_DCS_CMD(0x24, 0x0C),
- _INIT_DCS_CMD(0x25, 0x0C),
-
- _INIT_DCS_CMD(0x26, 0x08),
- _INIT_DCS_CMD(0x27, 0x08),
-
- _INIT_DCS_CMD(0x28, 0x00),
- _INIT_DCS_CMD(0x29, 0x00),
- _INIT_DCS_CMD(0x2A, 0x00),
- _INIT_DCS_CMD(0x2B, 0x00),
-
- _INIT_DCS_CMD(0x2D, 0x20),
- _INIT_DCS_CMD(0x2F, 0x0A),
- _INIT_DCS_CMD(0x30, 0x44),
- _INIT_DCS_CMD(0x33, 0x0C),
- _INIT_DCS_CMD(0x34, 0x32),
-
- _INIT_DCS_CMD(0x37, 0x44),
- _INIT_DCS_CMD(0x38, 0x40),
- _INIT_DCS_CMD(0x39, 0x00),
- _INIT_DCS_CMD(0x3A, 0x5D),
- _INIT_DCS_CMD(0x3B, 0x60),
- _INIT_DCS_CMD(0x3D, 0x42),
- _INIT_DCS_CMD(0x3F, 0x06),
- _INIT_DCS_CMD(0x43, 0x06),
- _INIT_DCS_CMD(0x47, 0x66),
- _INIT_DCS_CMD(0x4A, 0x5D),
- _INIT_DCS_CMD(0x4B, 0x60),
- _INIT_DCS_CMD(0x4C, 0x91),
- _INIT_DCS_CMD(0x4D, 0x21),
- _INIT_DCS_CMD(0x4E, 0x43),
- _INIT_DCS_CMD(0x51, 0x12),
- _INIT_DCS_CMD(0x52, 0x34),
- _INIT_DCS_CMD(0x55, 0x82, 0x02),
- _INIT_DCS_CMD(0x56, 0x04),
- _INIT_DCS_CMD(0x58, 0x21),
- _INIT_DCS_CMD(0x59, 0x30),
- _INIT_DCS_CMD(0x5A, 0x60),
- _INIT_DCS_CMD(0x5B, 0x50),
- _INIT_DCS_CMD(0x5E, 0x00, 0x06),
- _INIT_DCS_CMD(0x5F, 0x00),
- _INIT_DCS_CMD(0x65, 0x82),
- _INIT_DCS_CMD(0x7E, 0x20),
- _INIT_DCS_CMD(0x7F, 0x3C),
- _INIT_DCS_CMD(0x82, 0x04),
- _INIT_DCS_CMD(0x97, 0xC0),
-
- _INIT_DCS_CMD(0xB6, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x00),
- _INIT_DCS_CMD(0x91, 0x44),
- _INIT_DCS_CMD(0x92, 0xA9),
- _INIT_DCS_CMD(0x93, 0x1A),
- _INIT_DCS_CMD(0x94, 0x96),
- _INIT_DCS_CMD(0xD7, 0x55),
- _INIT_DCS_CMD(0xDA, 0x0A),
- _INIT_DCS_CMD(0xDE, 0x08),
- _INIT_DCS_CMD(0xDB, 0x05),
- _INIT_DCS_CMD(0xDC, 0xA9),
- _INIT_DCS_CMD(0xDD, 0x22),
-
- _INIT_DCS_CMD(0xDF, 0x05),
- _INIT_DCS_CMD(0xE0, 0xA9),
- _INIT_DCS_CMD(0xE1, 0x05),
- _INIT_DCS_CMD(0xE2, 0xA9),
- _INIT_DCS_CMD(0xE3, 0x05),
- _INIT_DCS_CMD(0xE4, 0xA9),
- _INIT_DCS_CMD(0xE5, 0x05),
- _INIT_DCS_CMD(0xE6, 0xA9),
- _INIT_DCS_CMD(0x5C, 0x00),
- _INIT_DCS_CMD(0x5D, 0x00),
- _INIT_DCS_CMD(0x8D, 0x00),
- _INIT_DCS_CMD(0x8E, 0x00),
- _INIT_DCS_CMD(0xB5, 0x90),
- _INIT_DCS_CMD(0xFF, 0x25),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0x05, 0x00),
- _INIT_DCS_CMD(0x19, 0x07),
- _INIT_DCS_CMD(0x1F, 0x60),
- _INIT_DCS_CMD(0x20, 0x50),
- _INIT_DCS_CMD(0x26, 0x60),
- _INIT_DCS_CMD(0x27, 0x50),
- _INIT_DCS_CMD(0x33, 0x60),
- _INIT_DCS_CMD(0x34, 0x50),
- _INIT_DCS_CMD(0x3F, 0xE0),
- _INIT_DCS_CMD(0x40, 0x00),
- _INIT_DCS_CMD(0x44, 0x00),
- _INIT_DCS_CMD(0x45, 0x40),
- _INIT_DCS_CMD(0x48, 0x60),
- _INIT_DCS_CMD(0x49, 0x50),
- _INIT_DCS_CMD(0x5B, 0x00),
- _INIT_DCS_CMD(0x5C, 0x00),
- _INIT_DCS_CMD(0x5D, 0x00),
- _INIT_DCS_CMD(0x5E, 0xD0),
- _INIT_DCS_CMD(0x61, 0x60),
- _INIT_DCS_CMD(0x62, 0x50),
- _INIT_DCS_CMD(0xF1, 0x10),
- _INIT_DCS_CMD(0xFF, 0x2A),
- _INIT_DCS_CMD(0xFB, 0x01),
-
- _INIT_DCS_CMD(0x64, 0x16),
- _INIT_DCS_CMD(0x67, 0x16),
- _INIT_DCS_CMD(0x6A, 0x16),
-
- _INIT_DCS_CMD(0x70, 0x30),
-
- _INIT_DCS_CMD(0xA2, 0xF3),
- _INIT_DCS_CMD(0xA3, 0xFF),
- _INIT_DCS_CMD(0xA4, 0xFF),
- _INIT_DCS_CMD(0xA5, 0xFF),
-
- _INIT_DCS_CMD(0xD6, 0x08),
-
- _INIT_DCS_CMD(0xFF, 0x26),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0x00, 0xA1),
-
- _INIT_DCS_CMD(0x02, 0x31),
- _INIT_DCS_CMD(0x04, 0x28),
- _INIT_DCS_CMD(0x06, 0x30),
- _INIT_DCS_CMD(0x0C, 0x16),
- _INIT_DCS_CMD(0x0D, 0x0D),
- _INIT_DCS_CMD(0x0F, 0x00),
- _INIT_DCS_CMD(0x11, 0x00),
- _INIT_DCS_CMD(0x12, 0x50),
- _INIT_DCS_CMD(0x13, 0x56),
- _INIT_DCS_CMD(0x14, 0x57),
- _INIT_DCS_CMD(0x15, 0x00),
- _INIT_DCS_CMD(0x16, 0x10),
- _INIT_DCS_CMD(0x17, 0xA0),
- _INIT_DCS_CMD(0x18, 0x86),
- _INIT_DCS_CMD(0x19, 0x0D),
- _INIT_DCS_CMD(0x1A, 0x7F),
- _INIT_DCS_CMD(0x1B, 0x0C),
- _INIT_DCS_CMD(0x1C, 0xBF),
- _INIT_DCS_CMD(0x22, 0x00),
- _INIT_DCS_CMD(0x23, 0x00),
- _INIT_DCS_CMD(0x2A, 0x0D),
- _INIT_DCS_CMD(0x2B, 0x7F),
-
- _INIT_DCS_CMD(0x1D, 0x00),
- _INIT_DCS_CMD(0x1E, 0x65),
- _INIT_DCS_CMD(0x1F, 0x65),
- _INIT_DCS_CMD(0x24, 0x00),
- _INIT_DCS_CMD(0x25, 0x65),
- _INIT_DCS_CMD(0x2F, 0x05),
- _INIT_DCS_CMD(0x30, 0x65),
- _INIT_DCS_CMD(0x31, 0x05),
- _INIT_DCS_CMD(0x32, 0x7D),
- _INIT_DCS_CMD(0x39, 0x00),
- _INIT_DCS_CMD(0x3A, 0x65),
- _INIT_DCS_CMD(0x20, 0x01),
- _INIT_DCS_CMD(0x33, 0x11),
- _INIT_DCS_CMD(0x34, 0x78),
- _INIT_DCS_CMD(0x35, 0x16),
- _INIT_DCS_CMD(0xC8, 0x04),
- _INIT_DCS_CMD(0xC9, 0x9E),
- _INIT_DCS_CMD(0xCA, 0x4E),
- _INIT_DCS_CMD(0xCB, 0x00),
-
- _INIT_DCS_CMD(0xA9, 0x49),
- _INIT_DCS_CMD(0xAA, 0x4B),
- _INIT_DCS_CMD(0xAB, 0x48),
- _INIT_DCS_CMD(0xAC, 0x43),
- _INIT_DCS_CMD(0xAD, 0x40),
- _INIT_DCS_CMD(0xAE, 0x50),
- _INIT_DCS_CMD(0xAF, 0x44),
- _INIT_DCS_CMD(0xB0, 0x54),
- _INIT_DCS_CMD(0xB1, 0x4E),
- _INIT_DCS_CMD(0xB2, 0x4D),
- _INIT_DCS_CMD(0xB3, 0x4C),
- _INIT_DCS_CMD(0xB4, 0x41),
- _INIT_DCS_CMD(0xB5, 0x47),
- _INIT_DCS_CMD(0xB6, 0x53),
- _INIT_DCS_CMD(0xB7, 0x3E),
- _INIT_DCS_CMD(0xB8, 0x51),
- _INIT_DCS_CMD(0xB9, 0x3C),
- _INIT_DCS_CMD(0xBA, 0x3B),
- _INIT_DCS_CMD(0xBB, 0x46),
- _INIT_DCS_CMD(0xBC, 0x45),
- _INIT_DCS_CMD(0xBD, 0x55),
- _INIT_DCS_CMD(0xBE, 0x3D),
- _INIT_DCS_CMD(0xBF, 0x3F),
- _INIT_DCS_CMD(0xC0, 0x52),
- _INIT_DCS_CMD(0xC1, 0x4A),
- _INIT_DCS_CMD(0xC2, 0x39),
- _INIT_DCS_CMD(0xC3, 0x4F),
- _INIT_DCS_CMD(0xC4, 0x3A),
- _INIT_DCS_CMD(0xC5, 0x42),
- _INIT_DCS_CMD(0xFF, 0x27),
- _INIT_DCS_CMD(0xFB, 0x01),
-
- _INIT_DCS_CMD(0x56, 0x06),
- _INIT_DCS_CMD(0x58, 0x80),
- _INIT_DCS_CMD(0x59, 0x75),
- _INIT_DCS_CMD(0x5A, 0x00),
- _INIT_DCS_CMD(0x5B, 0x02),
- _INIT_DCS_CMD(0x5C, 0x00),
- _INIT_DCS_CMD(0x5D, 0x00),
- _INIT_DCS_CMD(0x5E, 0x20),
- _INIT_DCS_CMD(0x5F, 0x10),
- _INIT_DCS_CMD(0x60, 0x00),
- _INIT_DCS_CMD(0x61, 0x2E),
- _INIT_DCS_CMD(0x62, 0x00),
- _INIT_DCS_CMD(0x63, 0x01),
- _INIT_DCS_CMD(0x64, 0x43),
- _INIT_DCS_CMD(0x65, 0x2D),
- _INIT_DCS_CMD(0x66, 0x00),
- _INIT_DCS_CMD(0x67, 0x01),
- _INIT_DCS_CMD(0x68, 0x44),
-
- _INIT_DCS_CMD(0x00, 0x00),
- _INIT_DCS_CMD(0x78, 0x00),
- _INIT_DCS_CMD(0xC3, 0x00),
-
- _INIT_DCS_CMD(0xFF, 0x2A),
- _INIT_DCS_CMD(0xFB, 0x01),
-
- _INIT_DCS_CMD(0x22, 0x2F),
- _INIT_DCS_CMD(0x23, 0x08),
-
- _INIT_DCS_CMD(0x24, 0x00),
- _INIT_DCS_CMD(0x25, 0x65),
- _INIT_DCS_CMD(0x26, 0xF8),
- _INIT_DCS_CMD(0x27, 0x00),
- _INIT_DCS_CMD(0x28, 0x1A),
- _INIT_DCS_CMD(0x29, 0x00),
- _INIT_DCS_CMD(0x2A, 0x1A),
- _INIT_DCS_CMD(0x2B, 0x00),
- _INIT_DCS_CMD(0x2D, 0x1A),
-
- _INIT_DCS_CMD(0xFF, 0x23),
- _INIT_DCS_CMD(0xFB, 0x01),
-
- _INIT_DCS_CMD(0x00, 0x80),
- _INIT_DCS_CMD(0x07, 0x00),
-
- _INIT_DCS_CMD(0xFF, 0xE0),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0x14, 0x60),
- _INIT_DCS_CMD(0x16, 0xC0),
-
- _INIT_DCS_CMD(0xFF, 0xF0),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0x3A, 0x08),
-
- _INIT_DCS_CMD(0xFF, 0x10),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0xB9, 0x01),
- _INIT_DCS_CMD(0xFF, 0x20),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0x18, 0x40),
-
- _INIT_DCS_CMD(0xFF, 0x10),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0xB9, 0x02),
- _INIT_DCS_CMD(0x35, 0x00),
- _INIT_DCS_CMD(0x51, 0x00, 0xFF),
- _INIT_DCS_CMD(0x53, 0x24),
- _INIT_DCS_CMD(0x55, 0x00),
- _INIT_DCS_CMD(0xBB, 0x13),
- _INIT_DCS_CMD(0x3B, 0x03, 0x96, 0x1A, 0x04, 0x04),
- _INIT_DELAY_CMD(100),
- _INIT_DCS_CMD(0x11),
- _INIT_DELAY_CMD(200),
- _INIT_DCS_CMD(0x29),
- _INIT_DELAY_CMD(100),
- {},
+ return 0;
};
-static const struct panel_init_cmd inx_hj110iz_init_cmd[] = {
- _INIT_DCS_CMD(0xFF, 0x20),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0x05, 0xD1),
- _INIT_DCS_CMD(0x06, 0xC0),
- _INIT_DCS_CMD(0x07, 0x87),
- _INIT_DCS_CMD(0x08, 0x4B),
-
- _INIT_DCS_CMD(0x0D, 0x63),
- _INIT_DCS_CMD(0x0E, 0x91),
- _INIT_DCS_CMD(0x0F, 0x69),
- _INIT_DCS_CMD(0x94, 0x00),
- _INIT_DCS_CMD(0x95, 0xF5),
- _INIT_DCS_CMD(0x96, 0xF5),
- _INIT_DCS_CMD(0x9D, 0x00),
- _INIT_DCS_CMD(0x9E, 0x00),
- _INIT_DCS_CMD(0x69, 0x98),
- _INIT_DCS_CMD(0x75, 0xA2),
- _INIT_DCS_CMD(0x77, 0xB3),
-
- _INIT_DCS_CMD(0x58, 0x43),
- _INIT_DCS_CMD(0xFF, 0x24),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0x91, 0x44),
- _INIT_DCS_CMD(0x92, 0x4C),
- _INIT_DCS_CMD(0x94, 0x86),
- _INIT_DCS_CMD(0x60, 0x96),
- _INIT_DCS_CMD(0x61, 0xD0),
- _INIT_DCS_CMD(0x63, 0x70),
- _INIT_DCS_CMD(0xC2, 0xCA),
-
- _INIT_DCS_CMD(0x00, 0x03),
- _INIT_DCS_CMD(0x01, 0x03),
- _INIT_DCS_CMD(0x02, 0x03),
- _INIT_DCS_CMD(0x03, 0x29),
- _INIT_DCS_CMD(0x04, 0x22),
- _INIT_DCS_CMD(0x05, 0x22),
- _INIT_DCS_CMD(0x06, 0x0B),
- _INIT_DCS_CMD(0x07, 0x1D),
- _INIT_DCS_CMD(0x08, 0x1C),
- _INIT_DCS_CMD(0x09, 0x05),
- _INIT_DCS_CMD(0x0A, 0x08),
- _INIT_DCS_CMD(0x0B, 0x09),
- _INIT_DCS_CMD(0x0C, 0x0A),
- _INIT_DCS_CMD(0x0D, 0x0C),
- _INIT_DCS_CMD(0x0E, 0x0D),
- _INIT_DCS_CMD(0x0F, 0x0E),
- _INIT_DCS_CMD(0x10, 0x0F),
- _INIT_DCS_CMD(0x11, 0x10),
- _INIT_DCS_CMD(0x12, 0x11),
- _INIT_DCS_CMD(0x13, 0x04),
- _INIT_DCS_CMD(0x14, 0x00),
- _INIT_DCS_CMD(0x15, 0x03),
- _INIT_DCS_CMD(0x16, 0x03),
- _INIT_DCS_CMD(0x17, 0x03),
- _INIT_DCS_CMD(0x18, 0x03),
- _INIT_DCS_CMD(0x19, 0x29),
- _INIT_DCS_CMD(0x1A, 0x22),
- _INIT_DCS_CMD(0x1B, 0x22),
- _INIT_DCS_CMD(0x1C, 0x0B),
- _INIT_DCS_CMD(0x1D, 0x1D),
- _INIT_DCS_CMD(0x1E, 0x1C),
- _INIT_DCS_CMD(0x1F, 0x05),
- _INIT_DCS_CMD(0x20, 0x08),
- _INIT_DCS_CMD(0x21, 0x09),
- _INIT_DCS_CMD(0x22, 0x0A),
- _INIT_DCS_CMD(0x23, 0x0C),
- _INIT_DCS_CMD(0x24, 0x0D),
- _INIT_DCS_CMD(0x25, 0x0E),
- _INIT_DCS_CMD(0x26, 0x0F),
- _INIT_DCS_CMD(0x27, 0x10),
- _INIT_DCS_CMD(0x28, 0x11),
- _INIT_DCS_CMD(0x29, 0x04),
- _INIT_DCS_CMD(0x2A, 0x00),
- _INIT_DCS_CMD(0x2B, 0x03),
-
- _INIT_DCS_CMD(0x2F, 0x0A),
- _INIT_DCS_CMD(0x30, 0x35),
- _INIT_DCS_CMD(0x37, 0xA7),
- _INIT_DCS_CMD(0x39, 0x00),
- _INIT_DCS_CMD(0x3A, 0x46),
- _INIT_DCS_CMD(0x3B, 0x32),
- _INIT_DCS_CMD(0x3D, 0x12),
-
- _INIT_DCS_CMD(0x3F, 0x33),
- _INIT_DCS_CMD(0x40, 0x31),
- _INIT_DCS_CMD(0x41, 0x40),
- _INIT_DCS_CMD(0x42, 0x42),
- _INIT_DCS_CMD(0x47, 0x77),
- _INIT_DCS_CMD(0x48, 0x77),
- _INIT_DCS_CMD(0x4A, 0x45),
- _INIT_DCS_CMD(0x4B, 0x45),
- _INIT_DCS_CMD(0x4C, 0x14),
-
- _INIT_DCS_CMD(0x4D, 0x21),
- _INIT_DCS_CMD(0x4E, 0x43),
- _INIT_DCS_CMD(0x4F, 0x65),
- _INIT_DCS_CMD(0x55, 0x06),
- _INIT_DCS_CMD(0x56, 0x06),
- _INIT_DCS_CMD(0x58, 0x21),
- _INIT_DCS_CMD(0x59, 0x70),
- _INIT_DCS_CMD(0x5A, 0x46),
- _INIT_DCS_CMD(0x5B, 0x32),
- _INIT_DCS_CMD(0x5C, 0x88),
- _INIT_DCS_CMD(0x5E, 0x00, 0x00),
- _INIT_DCS_CMD(0x5F, 0x00),
-
- _INIT_DCS_CMD(0x7A, 0xFF),
- _INIT_DCS_CMD(0x7B, 0xFF),
- _INIT_DCS_CMD(0x7C, 0x00),
- _INIT_DCS_CMD(0x7D, 0x00),
- _INIT_DCS_CMD(0x7E, 0x20),
- _INIT_DCS_CMD(0x7F, 0x3C),
- _INIT_DCS_CMD(0x80, 0x00),
- _INIT_DCS_CMD(0x81, 0x00),
- _INIT_DCS_CMD(0x82, 0x08),
- _INIT_DCS_CMD(0x97, 0x02),
- _INIT_DCS_CMD(0xC5, 0x10),
-
- _INIT_DCS_CMD(0xD7, 0x55),
- _INIT_DCS_CMD(0xD8, 0x55),
- _INIT_DCS_CMD(0xD9, 0x23),
- _INIT_DCS_CMD(0xDA, 0x05),
- _INIT_DCS_CMD(0xDB, 0x01),
- _INIT_DCS_CMD(0xDC, 0x65),
- _INIT_DCS_CMD(0xDD, 0x55),
- _INIT_DCS_CMD(0xDE, 0x27),
- _INIT_DCS_CMD(0xDF, 0x01),
- _INIT_DCS_CMD(0xE0, 0x65),
- _INIT_DCS_CMD(0xE1, 0x01),
- _INIT_DCS_CMD(0xE2, 0x65),
- _INIT_DCS_CMD(0xE3, 0x01),
- _INIT_DCS_CMD(0xE4, 0x65),
- _INIT_DCS_CMD(0xE5, 0x01),
- _INIT_DCS_CMD(0xE6, 0x65),
- _INIT_DCS_CMD(0xE7, 0x00),
- _INIT_DCS_CMD(0xE8, 0x00),
- _INIT_DCS_CMD(0xE9, 0x01),
- _INIT_DCS_CMD(0xEA, 0x65),
- _INIT_DCS_CMD(0xEB, 0x01),
- _INIT_DCS_CMD(0xEE, 0x65),
- _INIT_DCS_CMD(0xEF, 0x01),
- _INIT_DCS_CMD(0xF0, 0x65),
- _INIT_DCS_CMD(0xB6, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x00),
-
- _INIT_DCS_CMD(0xFF, 0x25),
-
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0x05, 0x00),
- _INIT_DCS_CMD(0xF1, 0x10),
-
- _INIT_DCS_CMD(0x1E, 0x00),
- _INIT_DCS_CMD(0x1F, 0x46),
- _INIT_DCS_CMD(0x20, 0x32),
-
- _INIT_DCS_CMD(0x25, 0x00),
- _INIT_DCS_CMD(0x26, 0x46),
- _INIT_DCS_CMD(0x27, 0x32),
-
- _INIT_DCS_CMD(0x3F, 0x80),
- _INIT_DCS_CMD(0x40, 0x00),
- _INIT_DCS_CMD(0x43, 0x00),
-
- _INIT_DCS_CMD(0x44, 0x46),
- _INIT_DCS_CMD(0x45, 0x46),
-
- _INIT_DCS_CMD(0x48, 0x46),
- _INIT_DCS_CMD(0x49, 0x32),
-
- _INIT_DCS_CMD(0x5B, 0x80),
-
- _INIT_DCS_CMD(0x5C, 0x00),
- _INIT_DCS_CMD(0x5D, 0x46),
- _INIT_DCS_CMD(0x5E, 0x32),
-
- _INIT_DCS_CMD(0x5F, 0x46),
- _INIT_DCS_CMD(0x60, 0x32),
-
- _INIT_DCS_CMD(0x61, 0x46),
- _INIT_DCS_CMD(0x62, 0x32),
- _INIT_DCS_CMD(0x68, 0x0C),
-
- _INIT_DCS_CMD(0x6C, 0x0D),
- _INIT_DCS_CMD(0x6E, 0x0D),
- _INIT_DCS_CMD(0x78, 0x00),
- _INIT_DCS_CMD(0x79, 0xC5),
- _INIT_DCS_CMD(0x7A, 0x0C),
- _INIT_DCS_CMD(0x7B, 0xB0),
-
- _INIT_DCS_CMD(0xFF, 0x26),
- _INIT_DCS_CMD(0xFB, 0x01),
-
- _INIT_DCS_CMD(0x00, 0xA1),
- _INIT_DCS_CMD(0x02, 0x31),
- _INIT_DCS_CMD(0x0A, 0xF4),
- _INIT_DCS_CMD(0x04, 0x50),
- _INIT_DCS_CMD(0x06, 0x30),
- _INIT_DCS_CMD(0x0C, 0x16),
- _INIT_DCS_CMD(0x0D, 0x0D),
- _INIT_DCS_CMD(0x0F, 0x00),
- _INIT_DCS_CMD(0x11, 0x00),
- _INIT_DCS_CMD(0x12, 0x50),
- _INIT_DCS_CMD(0x13, 0x40),
- _INIT_DCS_CMD(0x14, 0x58),
- _INIT_DCS_CMD(0x15, 0x00),
- _INIT_DCS_CMD(0x16, 0x10),
- _INIT_DCS_CMD(0x17, 0xA0),
- _INIT_DCS_CMD(0x18, 0x86),
- _INIT_DCS_CMD(0x22, 0x00),
- _INIT_DCS_CMD(0x23, 0x00),
-
- _INIT_DCS_CMD(0x19, 0x0E),
- _INIT_DCS_CMD(0x1A, 0x31),
- _INIT_DCS_CMD(0x1B, 0x0D),
- _INIT_DCS_CMD(0x1C, 0x29),
- _INIT_DCS_CMD(0x2A, 0x0E),
- _INIT_DCS_CMD(0x2B, 0x31),
-
- _INIT_DCS_CMD(0x1D, 0x00),
- _INIT_DCS_CMD(0x1E, 0x62),
- _INIT_DCS_CMD(0x1F, 0x62),
-
- _INIT_DCS_CMD(0x2F, 0x06),
- _INIT_DCS_CMD(0x30, 0x62),
- _INIT_DCS_CMD(0x31, 0x06),
- _INIT_DCS_CMD(0x32, 0x7F),
- _INIT_DCS_CMD(0x33, 0x11),
- _INIT_DCS_CMD(0x34, 0x89),
- _INIT_DCS_CMD(0x35, 0x67),
-
- _INIT_DCS_CMD(0x39, 0x0B),
- _INIT_DCS_CMD(0x3A, 0x62),
- _INIT_DCS_CMD(0x3B, 0x06),
-
- _INIT_DCS_CMD(0xC8, 0x04),
- _INIT_DCS_CMD(0xC9, 0x89),
- _INIT_DCS_CMD(0xCA, 0x4E),
- _INIT_DCS_CMD(0xCB, 0x00),
- _INIT_DCS_CMD(0xA9, 0x3F),
- _INIT_DCS_CMD(0xAA, 0x3E),
- _INIT_DCS_CMD(0xAB, 0x3D),
- _INIT_DCS_CMD(0xAC, 0x3C),
- _INIT_DCS_CMD(0xAD, 0x3B),
- _INIT_DCS_CMD(0xAE, 0x3A),
- _INIT_DCS_CMD(0xAF, 0x39),
- _INIT_DCS_CMD(0xB0, 0x38),
-
- _INIT_DCS_CMD(0xFF, 0x27),
- _INIT_DCS_CMD(0xFB, 0x01),
-
- _INIT_DCS_CMD(0xD0, 0x11),
- _INIT_DCS_CMD(0xD1, 0x54),
- _INIT_DCS_CMD(0xDE, 0x43),
- _INIT_DCS_CMD(0xDF, 0x02),
-
- _INIT_DCS_CMD(0xC0, 0x18),
- _INIT_DCS_CMD(0xC1, 0x00),
- _INIT_DCS_CMD(0xC2, 0x00),
- _INIT_DCS_CMD(0x00, 0x00),
- _INIT_DCS_CMD(0xC3, 0x00),
- _INIT_DCS_CMD(0x56, 0x06),
-
- _INIT_DCS_CMD(0x58, 0x80),
- _INIT_DCS_CMD(0x59, 0x78),
- _INIT_DCS_CMD(0x5A, 0x00),
- _INIT_DCS_CMD(0x5B, 0x18),
- _INIT_DCS_CMD(0x5C, 0x00),
- _INIT_DCS_CMD(0x5D, 0x01),
- _INIT_DCS_CMD(0x5E, 0x20),
- _INIT_DCS_CMD(0x5F, 0x10),
- _INIT_DCS_CMD(0x60, 0x00),
- _INIT_DCS_CMD(0x61, 0x1C),
- _INIT_DCS_CMD(0x62, 0x00),
- _INIT_DCS_CMD(0x63, 0x01),
- _INIT_DCS_CMD(0x64, 0x44),
- _INIT_DCS_CMD(0x65, 0x1B),
- _INIT_DCS_CMD(0x66, 0x00),
- _INIT_DCS_CMD(0x67, 0x01),
- _INIT_DCS_CMD(0x68, 0x44),
-
- _INIT_DCS_CMD(0x98, 0x01),
- _INIT_DCS_CMD(0xB4, 0x03),
- _INIT_DCS_CMD(0x9B, 0xBE),
-
- _INIT_DCS_CMD(0xAB, 0x14),
- _INIT_DCS_CMD(0xBC, 0x08),
- _INIT_DCS_CMD(0xBD, 0x28),
-
- _INIT_DCS_CMD(0xFF, 0x2A),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0x22, 0x2F),
- _INIT_DCS_CMD(0x23, 0x08),
-
- _INIT_DCS_CMD(0x24, 0x00),
- _INIT_DCS_CMD(0x25, 0x62),
- _INIT_DCS_CMD(0x26, 0xF8),
- _INIT_DCS_CMD(0x27, 0x00),
- _INIT_DCS_CMD(0x28, 0x1A),
- _INIT_DCS_CMD(0x29, 0x00),
- _INIT_DCS_CMD(0x2A, 0x1A),
- _INIT_DCS_CMD(0x2B, 0x00),
- _INIT_DCS_CMD(0x2D, 0x1A),
-
- _INIT_DCS_CMD(0x64, 0x96),
- _INIT_DCS_CMD(0x65, 0x10),
- _INIT_DCS_CMD(0x66, 0x00),
- _INIT_DCS_CMD(0x67, 0x96),
- _INIT_DCS_CMD(0x68, 0x10),
- _INIT_DCS_CMD(0x69, 0x00),
- _INIT_DCS_CMD(0x6A, 0x96),
- _INIT_DCS_CMD(0x6B, 0x10),
- _INIT_DCS_CMD(0x6C, 0x00),
- _INIT_DCS_CMD(0x70, 0x92),
- _INIT_DCS_CMD(0x71, 0x10),
- _INIT_DCS_CMD(0x72, 0x00),
- _INIT_DCS_CMD(0x79, 0x96),
- _INIT_DCS_CMD(0x7A, 0x10),
- _INIT_DCS_CMD(0x88, 0x96),
- _INIT_DCS_CMD(0x89, 0x10),
-
- _INIT_DCS_CMD(0xA2, 0x3F),
- _INIT_DCS_CMD(0xA3, 0x30),
- _INIT_DCS_CMD(0xA4, 0xC0),
- _INIT_DCS_CMD(0xA5, 0x03),
-
- _INIT_DCS_CMD(0xE8, 0x00),
-
- _INIT_DCS_CMD(0x97, 0x3C),
- _INIT_DCS_CMD(0x98, 0x02),
- _INIT_DCS_CMD(0x99, 0x95),
- _INIT_DCS_CMD(0x9A, 0x06),
- _INIT_DCS_CMD(0x9B, 0x00),
- _INIT_DCS_CMD(0x9C, 0x0B),
- _INIT_DCS_CMD(0x9D, 0x0A),
- _INIT_DCS_CMD(0x9E, 0x90),
-
- _INIT_DCS_CMD(0xFF, 0x25),
- _INIT_DCS_CMD(0x13, 0x02),
- _INIT_DCS_CMD(0x14, 0xD7),
- _INIT_DCS_CMD(0xDB, 0x02),
- _INIT_DCS_CMD(0xDC, 0xD7),
- _INIT_DCS_CMD(0x17, 0xCF),
- _INIT_DCS_CMD(0x19, 0x0F),
- _INIT_DCS_CMD(0x1B, 0x5B),
-
- _INIT_DCS_CMD(0xFF, 0x20),
-
- _INIT_DCS_CMD(0xB0, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x24, 0x00, 0x38, 0x00, 0x4C, 0x00, 0x5E, 0x00, 0x6F, 0x00, 0x7E),
- _INIT_DCS_CMD(0xB1, 0x00, 0x8C, 0x00, 0xBE, 0x00, 0xE5, 0x01, 0x27, 0x01, 0x58, 0x01, 0xA8, 0x01, 0xE8, 0x01, 0xEA),
- _INIT_DCS_CMD(0xB2, 0x02, 0x28, 0x02, 0x71, 0x02, 0x9E, 0x02, 0xDA, 0x03, 0x00, 0x03, 0x31, 0x03, 0x40, 0x03, 0x51),
- _INIT_DCS_CMD(0xB3, 0x03, 0x62, 0x03, 0x75, 0x03, 0x89, 0x03, 0x9C, 0x03, 0xAA, 0x03, 0xB2),
-
- _INIT_DCS_CMD(0xB4, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x27, 0x00, 0x3D, 0x00, 0x52, 0x00, 0x64, 0x00, 0x75, 0x00, 0x84),
- _INIT_DCS_CMD(0xB5, 0x00, 0x93, 0x00, 0xC5, 0x00, 0xEC, 0x01, 0x2C, 0x01, 0x5D, 0x01, 0xAC, 0x01, 0xEC, 0x01, 0xEE),
- _INIT_DCS_CMD(0xB6, 0x02, 0x2B, 0x02, 0x73, 0x02, 0xA0, 0x02, 0xDB, 0x03, 0x01, 0x03, 0x31, 0x03, 0x41, 0x03, 0x51),
- _INIT_DCS_CMD(0xB7, 0x03, 0x63, 0x03, 0x75, 0x03, 0x89, 0x03, 0x9C, 0x03, 0xAA, 0x03, 0xB2),
-
- _INIT_DCS_CMD(0xB8, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x2A, 0x00, 0x40, 0x00, 0x56, 0x00, 0x68, 0x00, 0x7A, 0x00, 0x89),
- _INIT_DCS_CMD(0xB9, 0x00, 0x98, 0x00, 0xC9, 0x00, 0xF1, 0x01, 0x30, 0x01, 0x61, 0x01, 0xB0, 0x01, 0xEF, 0x01, 0xF1),
- _INIT_DCS_CMD(0xBA, 0x02, 0x2E, 0x02, 0x76, 0x02, 0xA3, 0x02, 0xDD, 0x03, 0x02, 0x03, 0x32, 0x03, 0x42, 0x03, 0x53),
- _INIT_DCS_CMD(0xBB, 0x03, 0x66, 0x03, 0x75, 0x03, 0x89, 0x03, 0x9C, 0x03, 0xAA, 0x03, 0xB2),
-
- _INIT_DCS_CMD(0xFF, 0x21),
- _INIT_DCS_CMD(0xB0, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x24, 0x00, 0x38, 0x00, 0x4C, 0x00, 0x5E, 0x00, 0x6F, 0x00, 0x7E),
- _INIT_DCS_CMD(0xB1, 0x00, 0x8C, 0x00, 0xBE, 0x00, 0xE5, 0x01, 0x27, 0x01, 0x58, 0x01, 0xA8, 0x01, 0xE8, 0x01, 0xEA),
- _INIT_DCS_CMD(0xB2, 0x02, 0x28, 0x02, 0x71, 0x02, 0x9E, 0x02, 0xDA, 0x03, 0x00, 0x03, 0x31, 0x03, 0x40, 0x03, 0x51),
- _INIT_DCS_CMD(0xB3, 0x03, 0x62, 0x03, 0x77, 0x03, 0x90, 0x03, 0xAC, 0x03, 0xCA, 0x03, 0xDA),
-
- _INIT_DCS_CMD(0xB4, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x27, 0x00, 0x3D, 0x00, 0x52, 0x00, 0x64, 0x00, 0x75, 0x00, 0x84),
- _INIT_DCS_CMD(0xB5, 0x00, 0x93, 0x00, 0xC5, 0x00, 0xEC, 0x01, 0x2C, 0x01, 0x5D, 0x01, 0xAC, 0x01, 0xEC, 0x01, 0xEE),
- _INIT_DCS_CMD(0xB6, 0x02, 0x2B, 0x02, 0x73, 0x02, 0xA0, 0x02, 0xDB, 0x03, 0x01, 0x03, 0x31, 0x03, 0x41, 0x03, 0x51),
- _INIT_DCS_CMD(0xB7, 0x03, 0x63, 0x03, 0x77, 0x03, 0x90, 0x03, 0xAC, 0x03, 0xCA, 0x03, 0xDA),
-
- _INIT_DCS_CMD(0xB8, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x2A, 0x00, 0x40, 0x00, 0x56, 0x00, 0x68, 0x00, 0x7A, 0x00, 0x89),
- _INIT_DCS_CMD(0xB9, 0x00, 0x98, 0x00, 0xC9, 0x00, 0xF1, 0x01, 0x30, 0x01, 0x61, 0x01, 0xB0, 0x01, 0xEF, 0x01, 0xF1),
- _INIT_DCS_CMD(0xBA, 0x02, 0x2E, 0x02, 0x76, 0x02, 0xA3, 0x02, 0xDD, 0x03, 0x02, 0x03, 0x32, 0x03, 0x42, 0x03, 0x53),
- _INIT_DCS_CMD(0xBB, 0x03, 0x66, 0x03, 0x77, 0x03, 0x90, 0x03, 0xAC, 0x03, 0xCA, 0x03, 0xDA),
-
- _INIT_DCS_CMD(0xFF, 0xF0),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0x3A, 0x08),
-
- _INIT_DCS_CMD(0xFF, 0x10),
- _INIT_DCS_CMD(0xB9, 0x01),
-
- _INIT_DCS_CMD(0xFF, 0x20),
-
- _INIT_DCS_CMD(0x18, 0x40),
- _INIT_DCS_CMD(0xFF, 0x10),
-
- _INIT_DCS_CMD(0xB9, 0x02),
- _INIT_DCS_CMD(0xFF, 0x10),
-
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0xB0, 0x01),
- _INIT_DCS_CMD(0x35, 0x00),
- _INIT_DCS_CMD(0x3B, 0x03, 0xAE, 0x1A, 0x04, 0x04),
- _INIT_DELAY_CMD(100),
- _INIT_DCS_CMD(0x11),
- _INIT_DELAY_CMD(200),
- _INIT_DCS_CMD(0x29),
- _INIT_DELAY_CMD(100),
- {},
-};
+static int boe_init(struct boe_panel *boe)
+{
+ struct mipi_dsi_multi_context ctx = { .dsi = boe->dsi };
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0xe5);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x52);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x88);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x8b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x1a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdd, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd2, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe7, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd9, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd7, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd4, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd5, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdf, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0x31);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x1c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0x2c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0x33);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x31);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x37);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x37);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x37);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0x39);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0x2e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0x2f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcf, 0x2f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd0, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd2, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd4, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd5, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x31);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd7, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd9, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xda, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdb, 0x37);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0x37);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdd, 0x37);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x39);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdf, 0x2e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x2f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x2f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe2, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe7, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x2a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x2a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x43);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe4, 0xc0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0xa5);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0xa5);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd5, 0x32);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x25);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x39);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x4e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x72);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x97);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0xdc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x22);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0xa4);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x2b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x2f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0xa9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x25);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x61);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x97);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xb2);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0xcd);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0xd9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0xe7);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xf4);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0xfa);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0xfc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0xaf);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x24);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x39);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x72);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x98);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0xdc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x23);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0xa6);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x2c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x30);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0xaa);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x62);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x9b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xb5);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0xcf);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0xdb);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0xe8);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xf5);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0xfa);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0xfc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0xaf);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x24);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x3b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x73);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x99);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0xe0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0xad);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x36);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x3a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0xae);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x2a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x66);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x9e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xb8);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0xd1);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0xdd);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0xe9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xf6);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0xfa);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0xfc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0xaf);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x25);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x39);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x4e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x72);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x97);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0xdc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x22);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0xa4);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x2b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x2f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0xa9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x25);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x61);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x97);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xb2);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0xcd);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0xd9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0xe7);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xf4);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0xfa);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0xfc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0xaf);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x24);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x39);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x72);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x98);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0xdc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x23);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0xa6);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x2c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x30);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0xaa);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x62);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x9b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xb5);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0xcf);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0xdb);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0xe8);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xf5);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0xfa);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0xfc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0xaf);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x24);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x3b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x73);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x99);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0xe0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0xad);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x36);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x3a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0xae);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x2a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x66);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x9e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xb8);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0xd1);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0xdd);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0xe9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xf6);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0xfa);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0xfc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0xaf);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x68);
+
+ mipi_dsi_msleep(&ctx, 150);
-static const struct panel_init_cmd boe_init_cmd[] = {
- _INIT_DCS_CMD(0xB0, 0x05),
- _INIT_DCS_CMD(0xB1, 0xE5),
- _INIT_DCS_CMD(0xB3, 0x52),
- _INIT_DCS_CMD(0xB0, 0x00),
- _INIT_DCS_CMD(0xB3, 0x88),
- _INIT_DCS_CMD(0xB0, 0x04),
- _INIT_DCS_CMD(0xB8, 0x00),
- _INIT_DCS_CMD(0xB0, 0x00),
- _INIT_DCS_CMD(0xB6, 0x03),
- _INIT_DCS_CMD(0xBA, 0x8B),
- _INIT_DCS_CMD(0xBF, 0x1A),
- _INIT_DCS_CMD(0xC0, 0x0F),
- _INIT_DCS_CMD(0xC2, 0x0C),
- _INIT_DCS_CMD(0xC3, 0x02),
- _INIT_DCS_CMD(0xC4, 0x0C),
- _INIT_DCS_CMD(0xC5, 0x02),
- _INIT_DCS_CMD(0xB0, 0x01),
- _INIT_DCS_CMD(0xE0, 0x26),
- _INIT_DCS_CMD(0xE1, 0x26),
- _INIT_DCS_CMD(0xDC, 0x00),
- _INIT_DCS_CMD(0xDD, 0x00),
- _INIT_DCS_CMD(0xCC, 0x26),
- _INIT_DCS_CMD(0xCD, 0x26),
- _INIT_DCS_CMD(0xC8, 0x00),
- _INIT_DCS_CMD(0xC9, 0x00),
- _INIT_DCS_CMD(0xD2, 0x03),
- _INIT_DCS_CMD(0xD3, 0x03),
- _INIT_DCS_CMD(0xE6, 0x04),
- _INIT_DCS_CMD(0xE7, 0x04),
- _INIT_DCS_CMD(0xC4, 0x09),
- _INIT_DCS_CMD(0xC5, 0x09),
- _INIT_DCS_CMD(0xD8, 0x0A),
- _INIT_DCS_CMD(0xD9, 0x0A),
- _INIT_DCS_CMD(0xC2, 0x0B),
- _INIT_DCS_CMD(0xC3, 0x0B),
- _INIT_DCS_CMD(0xD6, 0x0C),
- _INIT_DCS_CMD(0xD7, 0x0C),
- _INIT_DCS_CMD(0xC0, 0x05),
- _INIT_DCS_CMD(0xC1, 0x05),
- _INIT_DCS_CMD(0xD4, 0x06),
- _INIT_DCS_CMD(0xD5, 0x06),
- _INIT_DCS_CMD(0xCA, 0x07),
- _INIT_DCS_CMD(0xCB, 0x07),
- _INIT_DCS_CMD(0xDE, 0x08),
- _INIT_DCS_CMD(0xDF, 0x08),
- _INIT_DCS_CMD(0xB0, 0x02),
- _INIT_DCS_CMD(0xC0, 0x00),
- _INIT_DCS_CMD(0xC1, 0x0D),
- _INIT_DCS_CMD(0xC2, 0x17),
- _INIT_DCS_CMD(0xC3, 0x26),
- _INIT_DCS_CMD(0xC4, 0x31),
- _INIT_DCS_CMD(0xC5, 0x1C),
- _INIT_DCS_CMD(0xC6, 0x2C),
- _INIT_DCS_CMD(0xC7, 0x33),
- _INIT_DCS_CMD(0xC8, 0x31),
- _INIT_DCS_CMD(0xC9, 0x37),
- _INIT_DCS_CMD(0xCA, 0x37),
- _INIT_DCS_CMD(0xCB, 0x37),
- _INIT_DCS_CMD(0xCC, 0x39),
- _INIT_DCS_CMD(0xCD, 0x2E),
- _INIT_DCS_CMD(0xCE, 0x2F),
- _INIT_DCS_CMD(0xCF, 0x2F),
- _INIT_DCS_CMD(0xD0, 0x07),
- _INIT_DCS_CMD(0xD2, 0x00),
- _INIT_DCS_CMD(0xD3, 0x0D),
- _INIT_DCS_CMD(0xD4, 0x17),
- _INIT_DCS_CMD(0xD5, 0x26),
- _INIT_DCS_CMD(0xD6, 0x31),
- _INIT_DCS_CMD(0xD7, 0x3F),
- _INIT_DCS_CMD(0xD8, 0x3F),
- _INIT_DCS_CMD(0xD9, 0x3F),
- _INIT_DCS_CMD(0xDA, 0x3F),
- _INIT_DCS_CMD(0xDB, 0x37),
- _INIT_DCS_CMD(0xDC, 0x37),
- _INIT_DCS_CMD(0xDD, 0x37),
- _INIT_DCS_CMD(0xDE, 0x39),
- _INIT_DCS_CMD(0xDF, 0x2E),
- _INIT_DCS_CMD(0xE0, 0x2F),
- _INIT_DCS_CMD(0xE1, 0x2F),
- _INIT_DCS_CMD(0xE2, 0x07),
- _INIT_DCS_CMD(0xB0, 0x03),
- _INIT_DCS_CMD(0xC8, 0x0B),
- _INIT_DCS_CMD(0xC9, 0x07),
- _INIT_DCS_CMD(0xC3, 0x00),
- _INIT_DCS_CMD(0xE7, 0x00),
- _INIT_DCS_CMD(0xC5, 0x2A),
- _INIT_DCS_CMD(0xDE, 0x2A),
- _INIT_DCS_CMD(0xCA, 0x43),
- _INIT_DCS_CMD(0xC9, 0x07),
- _INIT_DCS_CMD(0xE4, 0xC0),
- _INIT_DCS_CMD(0xE5, 0x0D),
- _INIT_DCS_CMD(0xCB, 0x00),
- _INIT_DCS_CMD(0xB0, 0x06),
- _INIT_DCS_CMD(0xB8, 0xA5),
- _INIT_DCS_CMD(0xC0, 0xA5),
- _INIT_DCS_CMD(0xC7, 0x0F),
- _INIT_DCS_CMD(0xD5, 0x32),
- _INIT_DCS_CMD(0xB8, 0x00),
- _INIT_DCS_CMD(0xC0, 0x00),
- _INIT_DCS_CMD(0xBC, 0x00),
- _INIT_DCS_CMD(0xB0, 0x07),
- _INIT_DCS_CMD(0xB1, 0x00),
- _INIT_DCS_CMD(0xB2, 0x02),
- _INIT_DCS_CMD(0xB3, 0x0F),
- _INIT_DCS_CMD(0xB4, 0x25),
- _INIT_DCS_CMD(0xB5, 0x39),
- _INIT_DCS_CMD(0xB6, 0x4E),
- _INIT_DCS_CMD(0xB7, 0x72),
- _INIT_DCS_CMD(0xB8, 0x97),
- _INIT_DCS_CMD(0xB9, 0xDC),
- _INIT_DCS_CMD(0xBA, 0x22),
- _INIT_DCS_CMD(0xBB, 0xA4),
- _INIT_DCS_CMD(0xBC, 0x2B),
- _INIT_DCS_CMD(0xBD, 0x2F),
- _INIT_DCS_CMD(0xBE, 0xA9),
- _INIT_DCS_CMD(0xBF, 0x25),
- _INIT_DCS_CMD(0xC0, 0x61),
- _INIT_DCS_CMD(0xC1, 0x97),
- _INIT_DCS_CMD(0xC2, 0xB2),
- _INIT_DCS_CMD(0xC3, 0xCD),
- _INIT_DCS_CMD(0xC4, 0xD9),
- _INIT_DCS_CMD(0xC5, 0xE7),
- _INIT_DCS_CMD(0xC6, 0xF4),
- _INIT_DCS_CMD(0xC7, 0xFA),
- _INIT_DCS_CMD(0xC8, 0xFC),
- _INIT_DCS_CMD(0xC9, 0x00),
- _INIT_DCS_CMD(0xCA, 0x00),
- _INIT_DCS_CMD(0xCB, 0x16),
- _INIT_DCS_CMD(0xCC, 0xAF),
- _INIT_DCS_CMD(0xCD, 0xFF),
- _INIT_DCS_CMD(0xCE, 0xFF),
- _INIT_DCS_CMD(0xB0, 0x08),
- _INIT_DCS_CMD(0xB1, 0x04),
- _INIT_DCS_CMD(0xB2, 0x05),
- _INIT_DCS_CMD(0xB3, 0x11),
- _INIT_DCS_CMD(0xB4, 0x24),
- _INIT_DCS_CMD(0xB5, 0x39),
- _INIT_DCS_CMD(0xB6, 0x4F),
- _INIT_DCS_CMD(0xB7, 0x72),
- _INIT_DCS_CMD(0xB8, 0x98),
- _INIT_DCS_CMD(0xB9, 0xDC),
- _INIT_DCS_CMD(0xBA, 0x23),
- _INIT_DCS_CMD(0xBB, 0xA6),
- _INIT_DCS_CMD(0xBC, 0x2C),
- _INIT_DCS_CMD(0xBD, 0x30),
- _INIT_DCS_CMD(0xBE, 0xAA),
- _INIT_DCS_CMD(0xBF, 0x26),
- _INIT_DCS_CMD(0xC0, 0x62),
- _INIT_DCS_CMD(0xC1, 0x9B),
- _INIT_DCS_CMD(0xC2, 0xB5),
- _INIT_DCS_CMD(0xC3, 0xCF),
- _INIT_DCS_CMD(0xC4, 0xDB),
- _INIT_DCS_CMD(0xC5, 0xE8),
- _INIT_DCS_CMD(0xC6, 0xF5),
- _INIT_DCS_CMD(0xC7, 0xFA),
- _INIT_DCS_CMD(0xC8, 0xFC),
- _INIT_DCS_CMD(0xC9, 0x00),
- _INIT_DCS_CMD(0xCA, 0x00),
- _INIT_DCS_CMD(0xCB, 0x16),
- _INIT_DCS_CMD(0xCC, 0xAF),
- _INIT_DCS_CMD(0xCD, 0xFF),
- _INIT_DCS_CMD(0xCE, 0xFF),
- _INIT_DCS_CMD(0xB0, 0x09),
- _INIT_DCS_CMD(0xB1, 0x04),
- _INIT_DCS_CMD(0xB2, 0x02),
- _INIT_DCS_CMD(0xB3, 0x16),
- _INIT_DCS_CMD(0xB4, 0x24),
- _INIT_DCS_CMD(0xB5, 0x3B),
- _INIT_DCS_CMD(0xB6, 0x4F),
- _INIT_DCS_CMD(0xB7, 0x73),
- _INIT_DCS_CMD(0xB8, 0x99),
- _INIT_DCS_CMD(0xB9, 0xE0),
- _INIT_DCS_CMD(0xBA, 0x26),
- _INIT_DCS_CMD(0xBB, 0xAD),
- _INIT_DCS_CMD(0xBC, 0x36),
- _INIT_DCS_CMD(0xBD, 0x3A),
- _INIT_DCS_CMD(0xBE, 0xAE),
- _INIT_DCS_CMD(0xBF, 0x2A),
- _INIT_DCS_CMD(0xC0, 0x66),
- _INIT_DCS_CMD(0xC1, 0x9E),
- _INIT_DCS_CMD(0xC2, 0xB8),
- _INIT_DCS_CMD(0xC3, 0xD1),
- _INIT_DCS_CMD(0xC4, 0xDD),
- _INIT_DCS_CMD(0xC5, 0xE9),
- _INIT_DCS_CMD(0xC6, 0xF6),
- _INIT_DCS_CMD(0xC7, 0xFA),
- _INIT_DCS_CMD(0xC8, 0xFC),
- _INIT_DCS_CMD(0xC9, 0x00),
- _INIT_DCS_CMD(0xCA, 0x00),
- _INIT_DCS_CMD(0xCB, 0x16),
- _INIT_DCS_CMD(0xCC, 0xAF),
- _INIT_DCS_CMD(0xCD, 0xFF),
- _INIT_DCS_CMD(0xCE, 0xFF),
- _INIT_DCS_CMD(0xB0, 0x0A),
- _INIT_DCS_CMD(0xB1, 0x00),
- _INIT_DCS_CMD(0xB2, 0x02),
- _INIT_DCS_CMD(0xB3, 0x0F),
- _INIT_DCS_CMD(0xB4, 0x25),
- _INIT_DCS_CMD(0xB5, 0x39),
- _INIT_DCS_CMD(0xB6, 0x4E),
- _INIT_DCS_CMD(0xB7, 0x72),
- _INIT_DCS_CMD(0xB8, 0x97),
- _INIT_DCS_CMD(0xB9, 0xDC),
- _INIT_DCS_CMD(0xBA, 0x22),
- _INIT_DCS_CMD(0xBB, 0xA4),
- _INIT_DCS_CMD(0xBC, 0x2B),
- _INIT_DCS_CMD(0xBD, 0x2F),
- _INIT_DCS_CMD(0xBE, 0xA9),
- _INIT_DCS_CMD(0xBF, 0x25),
- _INIT_DCS_CMD(0xC0, 0x61),
- _INIT_DCS_CMD(0xC1, 0x97),
- _INIT_DCS_CMD(0xC2, 0xB2),
- _INIT_DCS_CMD(0xC3, 0xCD),
- _INIT_DCS_CMD(0xC4, 0xD9),
- _INIT_DCS_CMD(0xC5, 0xE7),
- _INIT_DCS_CMD(0xC6, 0xF4),
- _INIT_DCS_CMD(0xC7, 0xFA),
- _INIT_DCS_CMD(0xC8, 0xFC),
- _INIT_DCS_CMD(0xC9, 0x00),
- _INIT_DCS_CMD(0xCA, 0x00),
- _INIT_DCS_CMD(0xCB, 0x16),
- _INIT_DCS_CMD(0xCC, 0xAF),
- _INIT_DCS_CMD(0xCD, 0xFF),
- _INIT_DCS_CMD(0xCE, 0xFF),
- _INIT_DCS_CMD(0xB0, 0x0B),
- _INIT_DCS_CMD(0xB1, 0x04),
- _INIT_DCS_CMD(0xB2, 0x05),
- _INIT_DCS_CMD(0xB3, 0x11),
- _INIT_DCS_CMD(0xB4, 0x24),
- _INIT_DCS_CMD(0xB5, 0x39),
- _INIT_DCS_CMD(0xB6, 0x4F),
- _INIT_DCS_CMD(0xB7, 0x72),
- _INIT_DCS_CMD(0xB8, 0x98),
- _INIT_DCS_CMD(0xB9, 0xDC),
- _INIT_DCS_CMD(0xBA, 0x23),
- _INIT_DCS_CMD(0xBB, 0xA6),
- _INIT_DCS_CMD(0xBC, 0x2C),
- _INIT_DCS_CMD(0xBD, 0x30),
- _INIT_DCS_CMD(0xBE, 0xAA),
- _INIT_DCS_CMD(0xBF, 0x26),
- _INIT_DCS_CMD(0xC0, 0x62),
- _INIT_DCS_CMD(0xC1, 0x9B),
- _INIT_DCS_CMD(0xC2, 0xB5),
- _INIT_DCS_CMD(0xC3, 0xCF),
- _INIT_DCS_CMD(0xC4, 0xDB),
- _INIT_DCS_CMD(0xC5, 0xE8),
- _INIT_DCS_CMD(0xC6, 0xF5),
- _INIT_DCS_CMD(0xC7, 0xFA),
- _INIT_DCS_CMD(0xC8, 0xFC),
- _INIT_DCS_CMD(0xC9, 0x00),
- _INIT_DCS_CMD(0xCA, 0x00),
- _INIT_DCS_CMD(0xCB, 0x16),
- _INIT_DCS_CMD(0xCC, 0xAF),
- _INIT_DCS_CMD(0xCD, 0xFF),
- _INIT_DCS_CMD(0xCE, 0xFF),
- _INIT_DCS_CMD(0xB0, 0x0C),
- _INIT_DCS_CMD(0xB1, 0x04),
- _INIT_DCS_CMD(0xB2, 0x02),
- _INIT_DCS_CMD(0xB3, 0x16),
- _INIT_DCS_CMD(0xB4, 0x24),
- _INIT_DCS_CMD(0xB5, 0x3B),
- _INIT_DCS_CMD(0xB6, 0x4F),
- _INIT_DCS_CMD(0xB7, 0x73),
- _INIT_DCS_CMD(0xB8, 0x99),
- _INIT_DCS_CMD(0xB9, 0xE0),
- _INIT_DCS_CMD(0xBA, 0x26),
- _INIT_DCS_CMD(0xBB, 0xAD),
- _INIT_DCS_CMD(0xBC, 0x36),
- _INIT_DCS_CMD(0xBD, 0x3A),
- _INIT_DCS_CMD(0xBE, 0xAE),
- _INIT_DCS_CMD(0xBF, 0x2A),
- _INIT_DCS_CMD(0xC0, 0x66),
- _INIT_DCS_CMD(0xC1, 0x9E),
- _INIT_DCS_CMD(0xC2, 0xB8),
- _INIT_DCS_CMD(0xC3, 0xD1),
- _INIT_DCS_CMD(0xC4, 0xDD),
- _INIT_DCS_CMD(0xC5, 0xE9),
- _INIT_DCS_CMD(0xC6, 0xF6),
- _INIT_DCS_CMD(0xC7, 0xFA),
- _INIT_DCS_CMD(0xC8, 0xFC),
- _INIT_DCS_CMD(0xC9, 0x00),
- _INIT_DCS_CMD(0xCA, 0x00),
- _INIT_DCS_CMD(0xCB, 0x16),
- _INIT_DCS_CMD(0xCC, 0xAF),
- _INIT_DCS_CMD(0xCD, 0xFF),
- _INIT_DCS_CMD(0xCE, 0xFF),
- _INIT_DCS_CMD(0xB0, 0x00),
- _INIT_DCS_CMD(0xB3, 0x08),
- _INIT_DCS_CMD(0xB0, 0x04),
- _INIT_DCS_CMD(0xB8, 0x68),
- _INIT_DELAY_CMD(150),
- {},
+ return 0;
};
-static const struct panel_init_cmd auo_kd101n80_45na_init_cmd[] = {
- _INIT_DELAY_CMD(24),
- _INIT_DCS_CMD(0x11),
- _INIT_DELAY_CMD(120),
- _INIT_DCS_CMD(0x29),
- _INIT_DELAY_CMD(120),
- {},
-};
+static int auo_kd101n80_45na_init(struct boe_panel *boe)
+{
+ struct mipi_dsi_multi_context ctx = { .dsi = boe->dsi };
-static const struct panel_init_cmd auo_b101uan08_3_init_cmd[] = {
- _INIT_DELAY_CMD(24),
- _INIT_DCS_CMD(0xB0, 0x01),
- _INIT_DCS_CMD(0xC0, 0x48),
- _INIT_DCS_CMD(0xC1, 0x48),
- _INIT_DCS_CMD(0xC2, 0x47),
- _INIT_DCS_CMD(0xC3, 0x47),
- _INIT_DCS_CMD(0xC4, 0x46),
- _INIT_DCS_CMD(0xC5, 0x46),
- _INIT_DCS_CMD(0xC6, 0x45),
- _INIT_DCS_CMD(0xC7, 0x45),
- _INIT_DCS_CMD(0xC8, 0x64),
- _INIT_DCS_CMD(0xC9, 0x64),
- _INIT_DCS_CMD(0xCA, 0x4F),
- _INIT_DCS_CMD(0xCB, 0x4F),
- _INIT_DCS_CMD(0xCC, 0x40),
- _INIT_DCS_CMD(0xCD, 0x40),
- _INIT_DCS_CMD(0xCE, 0x66),
- _INIT_DCS_CMD(0xCF, 0x66),
- _INIT_DCS_CMD(0xD0, 0x4F),
- _INIT_DCS_CMD(0xD1, 0x4F),
- _INIT_DCS_CMD(0xD2, 0x41),
- _INIT_DCS_CMD(0xD3, 0x41),
- _INIT_DCS_CMD(0xD4, 0x48),
- _INIT_DCS_CMD(0xD5, 0x48),
- _INIT_DCS_CMD(0xD6, 0x47),
- _INIT_DCS_CMD(0xD7, 0x47),
- _INIT_DCS_CMD(0xD8, 0x46),
- _INIT_DCS_CMD(0xD9, 0x46),
- _INIT_DCS_CMD(0xDA, 0x45),
- _INIT_DCS_CMD(0xDB, 0x45),
- _INIT_DCS_CMD(0xDC, 0x64),
- _INIT_DCS_CMD(0xDD, 0x64),
- _INIT_DCS_CMD(0xDE, 0x4F),
- _INIT_DCS_CMD(0xDF, 0x4F),
- _INIT_DCS_CMD(0xE0, 0x40),
- _INIT_DCS_CMD(0xE1, 0x40),
- _INIT_DCS_CMD(0xE2, 0x66),
- _INIT_DCS_CMD(0xE3, 0x66),
- _INIT_DCS_CMD(0xE4, 0x4F),
- _INIT_DCS_CMD(0xE5, 0x4F),
- _INIT_DCS_CMD(0xE6, 0x41),
- _INIT_DCS_CMD(0xE7, 0x41),
- _INIT_DELAY_CMD(150),
- {},
-};
+ msleep(24);
-static const struct panel_init_cmd starry_qfh032011_53g_init_cmd[] = {
- _INIT_DCS_CMD(0xB0, 0x01),
- _INIT_DCS_CMD(0xC3, 0x4F),
- _INIT_DCS_CMD(0xC4, 0x40),
- _INIT_DCS_CMD(0xC5, 0x40),
- _INIT_DCS_CMD(0xC6, 0x40),
- _INIT_DCS_CMD(0xC7, 0x40),
- _INIT_DCS_CMD(0xC8, 0x4D),
- _INIT_DCS_CMD(0xC9, 0x52),
- _INIT_DCS_CMD(0xCA, 0x51),
- _INIT_DCS_CMD(0xCD, 0x5D),
- _INIT_DCS_CMD(0xCE, 0x5B),
- _INIT_DCS_CMD(0xCF, 0x4B),
- _INIT_DCS_CMD(0xD0, 0x49),
- _INIT_DCS_CMD(0xD1, 0x47),
- _INIT_DCS_CMD(0xD2, 0x45),
- _INIT_DCS_CMD(0xD3, 0x41),
- _INIT_DCS_CMD(0xD7, 0x50),
- _INIT_DCS_CMD(0xD8, 0x40),
- _INIT_DCS_CMD(0xD9, 0x40),
- _INIT_DCS_CMD(0xDA, 0x40),
- _INIT_DCS_CMD(0xDB, 0x40),
- _INIT_DCS_CMD(0xDC, 0x4E),
- _INIT_DCS_CMD(0xDD, 0x52),
- _INIT_DCS_CMD(0xDE, 0x51),
- _INIT_DCS_CMD(0xE1, 0x5E),
- _INIT_DCS_CMD(0xE2, 0x5C),
- _INIT_DCS_CMD(0xE3, 0x4C),
- _INIT_DCS_CMD(0xE4, 0x4A),
- _INIT_DCS_CMD(0xE5, 0x48),
- _INIT_DCS_CMD(0xE6, 0x46),
- _INIT_DCS_CMD(0xE7, 0x42),
- _INIT_DCS_CMD(0xB0, 0x03),
- _INIT_DCS_CMD(0xBE, 0x03),
- _INIT_DCS_CMD(0xCC, 0x44),
- _INIT_DCS_CMD(0xC8, 0x07),
- _INIT_DCS_CMD(0xC9, 0x05),
- _INIT_DCS_CMD(0xCA, 0x42),
- _INIT_DCS_CMD(0xCD, 0x3E),
- _INIT_DCS_CMD(0xCF, 0x60),
- _INIT_DCS_CMD(0xD2, 0x04),
- _INIT_DCS_CMD(0xD3, 0x04),
- _INIT_DCS_CMD(0xD4, 0x01),
- _INIT_DCS_CMD(0xD5, 0x00),
- _INIT_DCS_CMD(0xD6, 0x03),
- _INIT_DCS_CMD(0xD7, 0x04),
- _INIT_DCS_CMD(0xD9, 0x01),
- _INIT_DCS_CMD(0xDB, 0x01),
- _INIT_DCS_CMD(0xE4, 0xF0),
- _INIT_DCS_CMD(0xE5, 0x0A),
- _INIT_DCS_CMD(0xB0, 0x00),
- _INIT_DCS_CMD(0xCC, 0x08),
- _INIT_DCS_CMD(0xC2, 0x08),
- _INIT_DCS_CMD(0xC4, 0x10),
- _INIT_DCS_CMD(0xB0, 0x02),
- _INIT_DCS_CMD(0xC0, 0x00),
- _INIT_DCS_CMD(0xC1, 0x0A),
- _INIT_DCS_CMD(0xC2, 0x20),
- _INIT_DCS_CMD(0xC3, 0x24),
- _INIT_DCS_CMD(0xC4, 0x23),
- _INIT_DCS_CMD(0xC5, 0x29),
- _INIT_DCS_CMD(0xC6, 0x23),
- _INIT_DCS_CMD(0xC7, 0x1C),
- _INIT_DCS_CMD(0xC8, 0x19),
- _INIT_DCS_CMD(0xC9, 0x17),
- _INIT_DCS_CMD(0xCA, 0x17),
- _INIT_DCS_CMD(0xCB, 0x18),
- _INIT_DCS_CMD(0xCC, 0x1A),
- _INIT_DCS_CMD(0xCD, 0x1E),
- _INIT_DCS_CMD(0xCE, 0x20),
- _INIT_DCS_CMD(0xCF, 0x23),
- _INIT_DCS_CMD(0xD0, 0x07),
- _INIT_DCS_CMD(0xD1, 0x00),
- _INIT_DCS_CMD(0xD2, 0x00),
- _INIT_DCS_CMD(0xD3, 0x0A),
- _INIT_DCS_CMD(0xD4, 0x13),
- _INIT_DCS_CMD(0xD5, 0x1C),
- _INIT_DCS_CMD(0xD6, 0x1A),
- _INIT_DCS_CMD(0xD7, 0x13),
- _INIT_DCS_CMD(0xD8, 0x17),
- _INIT_DCS_CMD(0xD9, 0x1C),
- _INIT_DCS_CMD(0xDA, 0x19),
- _INIT_DCS_CMD(0xDB, 0x17),
- _INIT_DCS_CMD(0xDC, 0x17),
- _INIT_DCS_CMD(0xDD, 0x18),
- _INIT_DCS_CMD(0xDE, 0x1A),
- _INIT_DCS_CMD(0xDF, 0x1E),
- _INIT_DCS_CMD(0xE0, 0x20),
- _INIT_DCS_CMD(0xE1, 0x23),
- _INIT_DCS_CMD(0xE2, 0x07),
- _INIT_DCS_CMD(0X11),
- _INIT_DELAY_CMD(120),
- _INIT_DCS_CMD(0X29),
- _INIT_DELAY_CMD(80),
- {},
-};
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x11);
-static const struct panel_init_cmd starry_himax83102_j02_init_cmd[] = {
- _INIT_DCS_CMD(0xB9, 0x83, 0x10, 0x21, 0x55, 0x00),
- _INIT_DCS_CMD(0xB1, 0x2C, 0xB5, 0xB5, 0x31, 0xF1, 0x31, 0xD7, 0x2F, 0x36, 0x36, 0x36, 0x36, 0x1A, 0x8B, 0x11,
- 0x65, 0x00, 0x88, 0xFA, 0xFF, 0xFF, 0x8F, 0xFF, 0x08, 0x74, 0x33),
- _INIT_DCS_CMD(0xB2, 0x00, 0x47, 0xB0, 0x80, 0x00, 0x12, 0x72, 0x3C, 0xA3, 0x03, 0x03, 0x00, 0x00, 0x88, 0xF5),
- _INIT_DCS_CMD(0xB4, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x63, 0x5C, 0x63, 0x5C, 0x01, 0x9E),
- _INIT_DCS_CMD(0xE9, 0xCD),
- _INIT_DCS_CMD(0xBA, 0x84),
- _INIT_DCS_CMD(0xE9, 0x3F),
- _INIT_DCS_CMD(0xBC, 0x1B, 0x04),
- _INIT_DCS_CMD(0xBE, 0x20),
- _INIT_DCS_CMD(0xBF, 0xFC, 0xC4),
- _INIT_DCS_CMD(0xC0, 0x36, 0x36, 0x22, 0x11, 0x22, 0xA0, 0x61, 0x08, 0xF5, 0x03),
- _INIT_DCS_CMD(0xE9, 0xCC),
- _INIT_DCS_CMD(0xC7, 0x80),
- _INIT_DCS_CMD(0xE9, 0x3F),
- _INIT_DCS_CMD(0xE9, 0xC6),
- _INIT_DCS_CMD(0xC8, 0x97),
- _INIT_DCS_CMD(0xE9, 0x3F),
- _INIT_DCS_CMD(0xC9, 0x00, 0x1E, 0x13, 0x88, 0x01),
- _INIT_DCS_CMD(0xCB, 0x08, 0x13, 0x07, 0x00, 0x0F, 0x33),
- _INIT_DCS_CMD(0xCC, 0x02),
- _INIT_DCS_CMD(0xE9, 0xC4),
- _INIT_DCS_CMD(0xD0, 0x03),
- _INIT_DCS_CMD(0xE9, 0x3F),
- _INIT_DCS_CMD(0xD1, 0x37, 0x06, 0x00, 0x02, 0x04, 0x0C, 0xFF),
- _INIT_DCS_CMD(0xD2, 0x1F, 0x11, 0x1F),
- _INIT_DCS_CMD(0xD3, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x37, 0x47, 0x34, 0x3B, 0x12, 0x12, 0x03,
- 0x03, 0x32, 0x10, 0x10, 0x00, 0x10, 0x32, 0x10, 0x08, 0x00, 0x08, 0x32, 0x17, 0x94, 0x07, 0x94, 0x00, 0x00),
- _INIT_DCS_CMD(0xD5, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x40, 0x40, 0x1A, 0x1A,
- 0x1B, 0x1B, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x20, 0x21, 0x28, 0x29, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18),
- _INIT_DCS_CMD(0xD6, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x40, 0x40, 0x19, 0x19, 0x1A, 0x1A,
- 0x1B, 0x1B, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x29, 0x28, 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18),
- _INIT_DCS_CMD(0xD8, 0xAA, 0xBA, 0xEA, 0xAA, 0xAA, 0xA0, 0xAA, 0xBA, 0xEA, 0xAA, 0xAA, 0xA0, 0xAA, 0xBA, 0xEA, 0xAA,
- 0xAA, 0xA0, 0xAA, 0xBA, 0xEA, 0xAA, 0xAA, 0xA0, 0xAA, 0xBA, 0xEA, 0xAA, 0xAA, 0xA0, 0xAA, 0xBA, 0xEA, 0xAA, 0xAA, 0xA0),
- _INIT_DCS_CMD(0xE0, 0x00, 0x09, 0x14, 0x1E, 0x26, 0x48, 0x61, 0x67, 0x6C, 0x67, 0x7D, 0x7F, 0x80, 0x8B, 0x87, 0x8F, 0x98, 0xAB,
- 0xAB, 0x55, 0x5C, 0x68, 0x73, 0x00, 0x09, 0x14, 0x1E, 0x26, 0x48, 0x61, 0x67, 0x6C, 0x67, 0x7D, 0x7F, 0x80, 0x8B, 0x87, 0x8F, 0x98, 0xAB, 0xAB, 0x55, 0x5C, 0x68, 0x73),
- _INIT_DCS_CMD(0xE7, 0x0E, 0x10, 0x10, 0x21, 0x2B, 0x9A, 0x02, 0x54, 0x9A, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x12, 0x05, 0x02, 0x02, 0x10),
- _INIT_DCS_CMD(0xBD, 0x01),
- _INIT_DCS_CMD(0xB1, 0x01, 0xBF, 0x11),
- _INIT_DCS_CMD(0xCB, 0x86),
- _INIT_DCS_CMD(0xD2, 0x3C, 0xFA),
- _INIT_DCS_CMD(0xD3, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0C, 0x01),
- _INIT_DCS_CMD(0xE7, 0x02, 0x00, 0x28, 0x01, 0x7E, 0x0F, 0x7E, 0x10, 0xA0, 0x00, 0x00, 0x20, 0x40, 0x50, 0x40),
- _INIT_DCS_CMD(0xBD, 0x02),
- _INIT_DCS_CMD(0xD8, 0xFF, 0xFF, 0xBF, 0xFE, 0xAA, 0xA0, 0xFF, 0xFF, 0xBF, 0xFE, 0xAA, 0xA0),
- _INIT_DCS_CMD(0xE7, 0xFE, 0x04, 0xFE, 0x04, 0xFE, 0x04, 0x03, 0x03, 0x03, 0x26, 0x00, 0x26, 0x81, 0x02, 0x40, 0x00, 0x20, 0x9E, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00),
- _INIT_DCS_CMD(0xBD, 0x03),
- _INIT_DCS_CMD(0xE9, 0xC6),
- _INIT_DCS_CMD(0xB4, 0x03, 0xFF, 0xF8),
- _INIT_DCS_CMD(0xE9, 0x3F),
- _INIT_DCS_CMD(0xD8, 0x00, 0x2A, 0xAA, 0xA8, 0x00, 0x00, 0x00, 0x2A, 0xAA, 0xA8, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x2A, 0xAA, 0xA8,
- 0x00, 0x00, 0x00, 0x2A, 0xAA, 0xA8, 0x00, 0x00),
- _INIT_DCS_CMD(0xBD, 0x00),
- _INIT_DCS_CMD(0xE9, 0xC4),
- _INIT_DCS_CMD(0xBA, 0x96),
- _INIT_DCS_CMD(0xE9, 0x3F),
- _INIT_DCS_CMD(0xBD, 0x01),
- _INIT_DCS_CMD(0xE9, 0xC5),
- _INIT_DCS_CMD(0xBA, 0x4F),
- _INIT_DCS_CMD(0xE9, 0x3F),
- _INIT_DCS_CMD(0xBD, 0x00),
- _INIT_DCS_CMD(0x11),
- _INIT_DELAY_CMD(120),
- _INIT_DCS_CMD(0x29),
- {},
-};
+ mipi_dsi_msleep(&ctx, 120);
-static inline struct boe_panel *to_boe_panel(struct drm_panel *panel)
-{
- return container_of(panel, struct boe_panel, base);
-}
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x29);
+
+ mipi_dsi_msleep(&ctx, 120);
-static int boe_panel_init_dcs_cmd(struct boe_panel *boe)
-{
- struct mipi_dsi_device *dsi = boe->dsi;
- struct drm_panel *panel = &boe->base;
- int i, err = 0;
-
- if (boe->desc->init_cmds) {
- const struct panel_init_cmd *init_cmds = boe->desc->init_cmds;
-
- for (i = 0; init_cmds[i].len != 0; i++) {
- const struct panel_init_cmd *cmd = &init_cmds[i];
-
- switch (cmd->type) {
- case DELAY_CMD:
- msleep(cmd->data[0]);
- err = 0;
- break;
-
- case INIT_DCS_CMD:
- err = mipi_dsi_dcs_write(dsi, cmd->data[0],
- cmd->len <= 1 ? NULL :
- &cmd->data[1],
- cmd->len - 1);
- break;
-
- default:
- err = -EINVAL;
- }
-
- if (err < 0) {
- dev_err(panel->dev,
- "failed to write command %u\n", i);
- return err;
- }
- }
- }
return 0;
-}
+};
-static int boe_panel_enter_sleep_mode(struct boe_panel *boe)
+static int auo_b101uan08_3_init(struct boe_panel *boe)
{
- struct mipi_dsi_device *dsi = boe->dsi;
- int ret;
-
- dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+ struct mipi_dsi_multi_context ctx = { .dsi = boe->dsi };
+
+ msleep(24);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x48);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x48);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0x47);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x47);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0x45);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0x45);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x64);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x64);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0x66);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcf, 0x66);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd0, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd1, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd2, 0x41);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x41);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd4, 0x48);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd5, 0x48);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x47);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd7, 0x47);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd9, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xda, 0x45);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdb, 0x45);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0x64);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdd, 0x64);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdf, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe2, 0x66);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe3, 0x66);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe4, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0x41);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe7, 0x41);
+
+ mipi_dsi_msleep(&ctx, 150);
- ret = mipi_dsi_dcs_set_display_off(dsi);
- if (ret < 0)
- return ret;
+ return 0;
+};
- ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
- if (ret < 0)
- return ret;
+static int starry_qfh032011_53g_init(struct boe_panel *boe)
+{
+ struct mipi_dsi_multi_context ctx = { .dsi = boe->dsi };
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x4d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x52);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x51);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0x5d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0x5b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcf, 0x4b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd0, 0x49);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd1, 0x47);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd2, 0x45);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x41);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd7, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd9, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xda, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdb, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0x4e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdd, 0x52);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x51);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x5e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe2, 0x5c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe3, 0x4c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe4, 0x4a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x48);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe7, 0x42);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x42);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0x3e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcf, 0x60);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd2, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd4, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd5, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd7, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd9, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe4, 0xf0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x24);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0x23);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x29);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0x23);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0x1c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x19);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x18);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0x1a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0x1e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcf, 0x23);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd0, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd1, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd2, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd4, 0x13);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd5, 0x1c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x1a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd7, 0x13);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd9, 0x1c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xda, 0x19);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdb, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdd, 0x18);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x1a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdf, 0x1e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x23);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe2, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0X11);
+
+ mipi_dsi_msleep(&ctx, 120);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0X29);
+
+ mipi_dsi_msleep(&ctx, 80);
return 0;
+};
+
+static inline struct boe_panel *to_boe_panel(struct drm_panel *panel)
+{
+ return container_of(panel, struct boe_panel, base);
}
static int boe_panel_disable(struct drm_panel *panel)
{
struct boe_panel *boe = to_boe_panel(panel);
- int ret;
+ struct mipi_dsi_multi_context ctx = { .dsi = boe->dsi };
- ret = boe_panel_enter_sleep_mode(boe);
- if (ret < 0) {
- dev_err(panel->dev, "failed to set panel off: %d\n", ret);
- return ret;
- }
+ boe->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
- msleep(150);
+ mipi_dsi_dcs_set_display_off_multi(&ctx);
+ mipi_dsi_dcs_enter_sleep_mode_multi(&ctx);
- return 0;
+ mipi_dsi_msleep(&ctx, 150);
+
+ return ctx.accum_err;
}
static int boe_panel_unprepare(struct drm_panel *panel)
@@ -1507,7 +1456,11 @@ static int boe_panel_prepare(struct drm_panel *panel)
usleep_range(10000, 11000);
if (boe->desc->lp11_before_reset) {
- mipi_dsi_dcs_nop(boe->dsi);
+ ret = mipi_dsi_dcs_nop(boe->dsi);
+ if (ret < 0) {
+ dev_err(&boe->dsi->dev, "Failed to send NOP: %d\n", ret);
+ goto poweroff;
+ }
usleep_range(1000, 2000);
}
gpiod_set_value(boe->enable_gpio, 1);
@@ -1517,24 +1470,22 @@ static int boe_panel_prepare(struct drm_panel *panel)
gpiod_set_value(boe->enable_gpio, 1);
usleep_range(6000, 10000);
- ret = boe_panel_init_dcs_cmd(boe);
- if (ret < 0) {
- dev_err(panel->dev, "failed to init panel: %d\n", ret);
+ ret = boe->desc->init(boe);
+ if (ret < 0)
goto poweroff;
- }
boe->prepared = true;
return 0;
poweroff:
+ gpiod_set_value(boe->enable_gpio, 0);
regulator_disable(boe->avee);
poweroffavdd:
regulator_disable(boe->avdd);
poweroff1v8:
usleep_range(5000, 7000);
regulator_disable(boe->pp1800);
- gpiod_set_value(boe->enable_gpio, 0);
return ret;
}
@@ -1571,7 +1522,7 @@ static const struct panel_desc boe_tv110c9m_desc = {
| MIPI_DSI_MODE_VIDEO_HSE
| MIPI_DSI_CLOCK_NON_CONTINUOUS
| MIPI_DSI_MODE_VIDEO_BURST,
- .init_cmds = boe_tv110c9m_init_cmd,
+ .init = boe_tv110c9m_init,
};
static const struct drm_display_mode inx_hj110iz_default_mode = {
@@ -1600,7 +1551,7 @@ static const struct panel_desc inx_hj110iz_desc = {
| MIPI_DSI_MODE_VIDEO_HSE
| MIPI_DSI_CLOCK_NON_CONTINUOUS
| MIPI_DSI_MODE_VIDEO_BURST,
- .init_cmds = inx_hj110iz_init_cmd,
+ .init = inx_hj110iz_init,
};
static const struct drm_display_mode boe_tv101wum_nl6_default_mode = {
@@ -1626,7 +1577,7 @@ static const struct panel_desc boe_tv101wum_nl6_desc = {
.format = MIPI_DSI_FMT_RGB888,
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
MIPI_DSI_MODE_LPM,
- .init_cmds = boe_init_cmd,
+ .init = boe_init,
.discharge_on_disable = false,
};
@@ -1653,7 +1604,7 @@ static const struct panel_desc auo_kd101n80_45na_desc = {
.format = MIPI_DSI_FMT_RGB888,
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
MIPI_DSI_MODE_LPM,
- .init_cmds = auo_kd101n80_45na_init_cmd,
+ .init = auo_kd101n80_45na_init,
.discharge_on_disable = true,
};
@@ -1681,7 +1632,7 @@ static const struct panel_desc boe_tv101wum_n53_desc = {
.format = MIPI_DSI_FMT_RGB888,
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
MIPI_DSI_MODE_LPM,
- .init_cmds = boe_init_cmd,
+ .init = boe_init,
};
static const struct drm_display_mode auo_b101uan08_3_default_mode = {
@@ -1708,7 +1659,7 @@ static const struct panel_desc auo_b101uan08_3_desc = {
.format = MIPI_DSI_FMT_RGB888,
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
MIPI_DSI_MODE_LPM,
- .init_cmds = auo_b101uan08_3_init_cmd,
+ .init = auo_b101uan08_3_init,
.lp11_before_reset = true,
};
@@ -1736,7 +1687,7 @@ static const struct panel_desc boe_tv105wum_nw0_desc = {
.format = MIPI_DSI_FMT_RGB888,
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
MIPI_DSI_MODE_LPM,
- .init_cmds = boe_init_cmd,
+ .init = boe_init,
.lp11_before_reset = true,
};
@@ -1763,35 +1714,7 @@ static const struct panel_desc starry_qfh032011_53g_desc = {
.format = MIPI_DSI_FMT_RGB888,
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
MIPI_DSI_MODE_LPM,
- .init_cmds = starry_qfh032011_53g_init_cmd,
- .lp11_before_reset = true,
-};
-
-static const struct drm_display_mode starry_himax83102_j02_default_mode = {
- .clock = 162680,
- .hdisplay = 1200,
- .hsync_start = 1200 + 60,
- .hsync_end = 1200 + 60 + 20,
- .htotal = 1200 + 60 + 20 + 40,
- .vdisplay = 1920,
- .vsync_start = 1920 + 116,
- .vsync_end = 1920 + 116 + 8,
- .vtotal = 1920 + 116 + 8 + 12,
- .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
-};
-
-static const struct panel_desc starry_himax83102_j02_desc = {
- .modes = &starry_himax83102_j02_default_mode,
- .bpc = 8,
- .size = {
- .width_mm = 141,
- .height_mm = 226,
- },
- .lanes = 4,
- .format = MIPI_DSI_FMT_RGB888,
- .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
- MIPI_DSI_MODE_LPM,
- .init_cmds = starry_himax83102_j02_init_cmd,
+ .init = starry_qfh032011_53g_init,
.lp11_before_reset = true,
};
@@ -1970,9 +1893,6 @@ static const struct of_device_id boe_of_match[] = {
{ .compatible = "starry,2081101qfh032011-53g",
.data = &starry_qfh032011_53g_desc
},
- { .compatible = "starry,himax83102-j02",
- .data = &starry_himax83102_j02_desc
- },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, boe_of_match);
diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c
index 6db277efcbb7..01e26b5a2388 100644
--- a/drivers/gpu/drm/panel/panel-edp.c
+++ b/drivers/gpu/drm/panel/panel-edp.c
@@ -2067,6 +2067,7 @@ static const struct edp_panel_entry edp_panels[] = {
EDP_PANEL_ENTRY('C', 'M', 'N', 0x1157, &delay_200_500_e80_d50, "N116BGE-EA2"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x115b, &delay_200_500_e80_d50, "N116BCN-EB1"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x115e, &delay_200_500_e80_d50, "N116BCA-EA1"),
+ EDP_PANEL_ENTRY('C', 'M', 'N', 0x1160, &delay_200_500_e80_d50, "N116BCJ-EAK"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x1247, &delay_200_500_e80_d50, "N120ACA-EA1"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x142b, &delay_200_500_e80_d50, "N140HCA-EAC"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x142e, &delay_200_500_e80_d50, "N140BGA-EA4"),
@@ -2094,6 +2095,7 @@ static const struct edp_panel_entry edp_panels[] = {
EDP_PANEL_ENTRY('K', 'D', 'B', 0x0624, &kingdisplay_kd116n21_30nv_a010.delay, "116N21-30NV-A010"),
EDP_PANEL_ENTRY('K', 'D', 'B', 0x1118, &delay_200_500_e50, "KD116N29-30NK-A005"),
EDP_PANEL_ENTRY('K', 'D', 'B', 0x1120, &delay_200_500_e80_d50, "116N29-30NK-C007"),
+ EDP_PANEL_ENTRY('K', 'D', 'B', 0x1212, &delay_200_500_e50, "KD116N0930A16"),
EDP_PANEL_ENTRY('K', 'D', 'C', 0x044f, &delay_200_500_e50, "KD116N9-30NH-F3"),
EDP_PANEL_ENTRY('K', 'D', 'C', 0x05f1, &delay_200_500_e80_d50, "KD116N5-30NV-G7"),
diff --git a/drivers/gpu/drm/panel/panel-himax-hx83102.c b/drivers/gpu/drm/panel/panel-himax-hx83102.c
new file mode 100644
index 000000000000..6009a3fe1b8f
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-himax-hx83102.c
@@ -0,0 +1,706 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for panels based on Himax HX83102 controller, such as:
+ *
+ * - Starry 10.51" WUXGA MIPI-DSI panel
+ *
+ * Based on drivers/gpu/drm/panel/panel-himax-hx8394.c
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drm_connector.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_panel.h>
+
+#include <video/mipi_display.h>
+
+/* Manufacturer specific DSI commands */
+#define HX83102_SETPOWER 0xb1
+#define HX83102_SETDISP 0xb2
+#define HX83102_SETCYC 0xb4
+#define HX83102_SETEXTC 0xb9
+#define HX83102_SETMIPI 0xba
+#define HX83102_SETVDC 0xbc
+#define HX83102_SETBANK 0xbd
+#define HX83102_UNKNOWN_BE 0xbe
+#define HX83102_SETPTBA 0xbf
+#define HX83102_SETSTBA 0xc0
+#define HX83102_SETTCON 0xc7
+#define HX83102_SETRAMDMY 0xc8
+#define HX83102_SETPWM 0xc9
+#define HX83102_SETCLOCK 0xcb
+#define HX83102_SETPANEL 0xcc
+#define HX83102_SETCASCADE 0xd0
+#define HX83102_SETPCTRL 0xd1
+#define HX83102_UNKNOWN_D2 0xd2
+#define HX83102_SETGIP0 0xd3
+#define HX83102_SETGIP1 0xd5
+#define HX83102_SETGIP2 0xd6
+#define HX83102_SETGIP3 0xd8
+#define HX83102_SETGMA 0xe0
+#define HX83102_UNKNOWN_E1 0xe1
+#define HX83102_SETTP1 0xe7
+#define HX83102_SETSPCCMD 0xe9
+
+struct hx83102 {
+ struct drm_panel base;
+ struct mipi_dsi_device *dsi;
+
+ const struct hx83102_panel_desc *desc;
+
+ enum drm_panel_orientation orientation;
+ struct regulator *pp1800;
+ struct regulator *avee;
+ struct regulator *avdd;
+ struct gpio_desc *enable_gpio;
+};
+
+struct hx83102_panel_desc {
+ const struct drm_display_mode *modes;
+
+ /**
+ * @width_mm: width of the panel's active display area
+ * @height_mm: height of the panel's active display area
+ */
+ struct {
+ unsigned int width_mm;
+ unsigned int height_mm;
+ } size;
+
+ int (*init)(struct hx83102 *ctx);
+};
+
+static inline struct hx83102 *panel_to_hx83102(struct drm_panel *panel)
+{
+ return container_of(panel, struct hx83102, base);
+}
+
+static void hx83102_enable_extended_cmds(struct mipi_dsi_multi_context *dsi_ctx, bool enable)
+{
+ if (enable)
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX83102_SETEXTC, 0x83, 0x10, 0x21, 0x55, 0x00);
+ else
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX83102_SETEXTC, 0x00, 0x00, 0x00);
+}
+
+static int starry_himax83102_j02_init(struct hx83102 *ctx)
+{
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi };
+
+ hx83102_enable_extended_cmds(&dsi_ctx, true);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x2c, 0xb5, 0xb5, 0x31, 0xf1,
+ 0x31, 0xd7, 0x2f, 0x36, 0x36, 0x36, 0x36, 0x1a, 0x8b, 0x11,
+ 0x65, 0x00, 0x88, 0xfa, 0xff, 0xff, 0x8f, 0xff, 0x08, 0x74,
+ 0x33);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x00, 0x47, 0xb0, 0x80, 0x00,
+ 0x12, 0x72, 0x3c, 0xa3, 0x03, 0x03, 0x00, 0x00, 0x88, 0xf5);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x76, 0x76, 0x76, 0x76, 0x76,
+ 0x76, 0x63, 0x5c, 0x63, 0x5c, 0x01, 0x9e);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcd);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x84);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETVDC, 0x1b, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_BE, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xfc, 0xc4);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSTBA, 0x36, 0x36, 0x22, 0x11, 0x22,
+ 0xa0, 0x61, 0x08, 0xf5, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcc);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x80);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETRAMDMY, 0x97);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPWM, 0x00, 0x1e, 0x13, 0x88, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x08, 0x13, 0x07, 0x00, 0x0f, 0x33);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPANEL, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCASCADE, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPCTRL, 0x37, 0x06, 0x00, 0x02, 0x04, 0x0c,
+ 0xff);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x1f, 0x11, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x08, 0x37, 0x47, 0x34, 0x3b, 0x12, 0x12, 0x03, 0x03,
+ 0x32, 0x10, 0x10, 0x00, 0x10, 0x32, 0x10, 0x08, 0x00, 0x08, 0x32,
+ 0x17, 0x94, 0x07, 0x94, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP1, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x40, 0x40, 0x1a, 0x1a, 0x1b,
+ 0x1b, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x20, 0x21,
+ 0x28, 0x29, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP2, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x40, 0x40, 0x19, 0x19, 0x1a, 0x1a, 0x1b,
+ 0x1b, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x29, 0x28,
+ 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xaa, 0xba, 0xea, 0xaa, 0xaa, 0xa0,
+ 0xaa, 0xba, 0xea, 0xaa, 0xaa, 0xa0, 0xaa, 0xba, 0xea, 0xaa, 0xaa,
+ 0xa0, 0xaa, 0xba, 0xea, 0xaa, 0xaa, 0xa0, 0xaa, 0xba, 0xea, 0xaa,
+ 0xaa, 0xa0, 0xaa, 0xba, 0xea, 0xaa, 0xaa, 0xa0);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGMA, 0x00, 0x09, 0x14, 0x1e, 0x26, 0x48,
+ 0x61, 0x67, 0x6c, 0x67, 0x7d, 0x7f, 0x80, 0x8b, 0x87, 0x8f, 0x98,
+ 0xab, 0xab, 0x55, 0x5c, 0x68, 0x73, 0x00, 0x09, 0x14, 0x1e, 0x26,
+ 0x48, 0x61, 0x67, 0x6c, 0x67, 0x7d, 0x7f, 0x80, 0x8b, 0x87, 0x8f,
+ 0x98, 0xab, 0xab, 0x55, 0x5c, 0x68, 0x73);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x0e, 0x10, 0x10, 0x21, 0x2b, 0x9a,
+ 0x02, 0x54, 0x9a, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x12, 0x05,
+ 0x02, 0x02, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x01, 0xbf, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x86);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x3c, 0xfa);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x0c, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x02, 0x00, 0x28, 0x01, 0x7e, 0x0f,
+ 0x7e, 0x10, 0xa0, 0x00, 0x00, 0x20, 0x40, 0x50, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xff, 0xff, 0xbf, 0xfe, 0xaa, 0xa0,
+ 0xff, 0xff, 0xbf, 0xfe, 0xaa, 0xa0);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xfe, 0x04, 0xfe, 0x04, 0xfe, 0x04,
+ 0x03, 0x03, 0x03, 0x26, 0x00, 0x26, 0x81, 0x02, 0x40, 0x00, 0x20,
+ 0x9e, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x03, 0xff, 0xf8);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x00, 0x2a, 0xaa, 0xa8, 0x00, 0x00,
+ 0x00, 0x2a, 0xaa, 0xa8, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00,
+ 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x2a, 0xaa, 0xa8,
+ 0x00, 0x00, 0x00, 0x2a, 0xaa, 0xa8, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x96);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
+
+ return dsi_ctx.accum_err;
+};
+
+static int boe_nv110wum_init(struct hx83102 *ctx)
+{
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi };
+
+ msleep(60);
+
+ hx83102_enable_extended_cmds(&dsi_ctx, true);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x2c, 0xaf, 0xaf, 0x2b, 0xeb, 0x42,
+ 0xe1, 0x4d, 0x36, 0x36, 0x36, 0x36, 0x1a, 0x8b, 0x11, 0x65, 0x00,
+ 0x88, 0xfa, 0xff, 0xff, 0x8f, 0xff, 0x08, 0x9a, 0x33);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x00, 0x47, 0xb0, 0x80, 0x00, 0x12,
+ 0x71, 0x3c, 0xa3, 0x11, 0x00, 0x00, 0x00, 0x88, 0xf5, 0x22, 0x8f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x49, 0x49, 0x32, 0x32, 0x14, 0x32,
+ 0x84, 0x6e, 0x84, 0x6e, 0x01, 0x9c);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcd);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x84);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETVDC, 0x1b, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_BE, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xfc, 0x84);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSTBA, 0x36, 0x36, 0x22, 0x00, 0x00, 0xa0,
+ 0x61, 0x08, 0xf5, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcc);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x80);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETRAMDMY, 0x97);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPWM, 0x00, 0x1e, 0x30, 0xd4, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x08, 0x13, 0x07, 0x00, 0x0f, 0x34);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPANEL, 0x02, 0x03, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCASCADE, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPCTRL, 0x37, 0x06, 0x00, 0x02, 0x04, 0x0c, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x1f, 0x11, 0x1f, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x04,
+ 0x08, 0x04, 0x08, 0x37, 0x37, 0x64, 0x4b, 0x11, 0x11, 0x03, 0x03, 0x32,
+ 0x10, 0x0e, 0x00, 0x0e, 0x32, 0x10, 0x0a, 0x00, 0x0a, 0x32, 0x17, 0x98,
+ 0x07, 0x98, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP1, 0x18, 0x18, 0x18, 0x18, 0x1e, 0x1e,
+ 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f, 0x24, 0x24, 0x24, 0x24, 0x07, 0x06,
+ 0x07, 0x06, 0x05, 0x04, 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x01, 0x00,
+ 0x01, 0x00, 0x21, 0x20, 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0,
+ 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGMA, 0x00, 0x05, 0x0d, 0x14, 0x1b, 0x2c,
+ 0x44, 0x49, 0x51, 0x4c, 0x67, 0x6c, 0x71, 0x80, 0x7d, 0x84, 0x8d, 0xa0,
+ 0xa0, 0x4f, 0x58, 0x64, 0x73, 0x00, 0x05, 0x0d, 0x14, 0x1b, 0x2c, 0x44,
+ 0x49, 0x51, 0x4c, 0x67, 0x6c, 0x71, 0x80, 0x7d, 0x84, 0x8d, 0xa0, 0xa0,
+ 0x4f, 0x58, 0x64, 0x73);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x07, 0x10, 0x10, 0x1a, 0x26, 0x9e,
+ 0x00, 0x53, 0x9b, 0x14, 0x14);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_E1, 0x11, 0x00, 0x00, 0x89, 0x30, 0x80,
+ 0x07, 0x80, 0x02, 0x58, 0x00, 0x14, 0x02, 0x58, 0x02, 0x58, 0x02, 0x00,
+ 0x02, 0x2c, 0x00, 0x20, 0x02, 0x02, 0x00, 0x08, 0x00, 0x0c, 0x05, 0x0e,
+ 0x04, 0x94, 0x18, 0x00, 0x10, 0xf0, 0x03, 0x0c, 0x20, 0x00, 0x06, 0x0b,
+ 0x0b, 0x33, 0x0e);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0,
+ 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x01, 0xbf, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x86);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x96);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc9);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x84);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xd1);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_E1, 0xf6, 0x2b, 0x34, 0x2b, 0x74, 0x3b,
+ 0x74, 0x6b, 0x74);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x02, 0x00, 0x2b, 0x01, 0x7e, 0x0f,
+ 0x7e, 0x10, 0xa0, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x02, 0x00, 0xbb, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xff, 0xaf, 0xff, 0xff, 0xfa, 0xa0,
+ 0xff, 0xaf, 0xff, 0xff, 0xfa, 0xa0);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01,
+ 0x00, 0x00, 0x00, 0x23, 0x00, 0x23, 0x81, 0x02, 0x40, 0x00, 0x20, 0x65,
+ 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xaa, 0xaf, 0xaa, 0xaa, 0xa0, 0x00,
+ 0xaa, 0xaf, 0xaa, 0xaa, 0xa0, 0x00, 0xaa, 0xaf, 0xaa, 0xaa, 0xa0, 0x00,
+ 0xaa, 0xaf, 0xaa, 0xaa, 0xa0, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x03, 0xff, 0xf8);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_E1, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x96);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
+ hx83102_enable_extended_cmds(&dsi_ctx, false);
+
+ mipi_dsi_msleep(dsi_ctx, 50);
+
+ return dsi_ctx.accum_err;
+};
+
+static int ivo_t109nw41_init(struct hx83102 *ctx)
+{
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi };
+
+ msleep(60);
+
+ hx83102_enable_extended_cmds(&dsi_ctx, true);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x2c, 0xed, 0xed, 0x0f, 0xcf, 0x42,
+ 0xf5, 0x39, 0x36, 0x36, 0x36, 0x36, 0x32, 0x8b, 0x11, 0x65, 0x00, 0x88,
+ 0xfa, 0xff, 0xff, 0x8f, 0xff, 0x08, 0xd6, 0x33);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x00, 0x47, 0xb0, 0x80, 0x00, 0x12,
+ 0x71, 0x3c, 0xa3, 0x22, 0x20, 0x00, 0x00, 0x88, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x35, 0x35, 0x43, 0x43, 0x35, 0x35,
+ 0x30, 0x7a, 0x30, 0x7a, 0x01, 0x9d);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcd);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x84);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETVDC, 0x1b, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_BE, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xfc, 0xc4);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSTBA, 0x34, 0x34, 0x22, 0x11, 0x22, 0xa0,
+ 0x31, 0x08, 0xf5, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcc);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x80);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xd3);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x22);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETRAMDMY, 0x97);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPWM, 0x00, 0x1e, 0x13, 0x88, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x08, 0x13, 0x07, 0x00, 0x0f, 0x34);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPANEL, 0x02, 0x03, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCASCADE, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPCTRL, 0x07, 0x06, 0x00, 0x02, 0x04, 0x2c,
+ 0xff);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x08, 0x08, 0x08, 0x37, 0x07, 0x64, 0x7c, 0x11, 0x11, 0x03, 0x03, 0x32,
+ 0x10, 0x0e, 0x00, 0x0e, 0x32, 0x17, 0x97, 0x07, 0x97, 0x32, 0x00, 0x02,
+ 0x00, 0x02, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP1, 0x25, 0x24, 0x25, 0x24, 0x18, 0x18,
+ 0x18, 0x18, 0x07, 0x06, 0x07, 0x06, 0x05, 0x04, 0x05, 0x04, 0x03, 0x02,
+ 0x03, 0x02, 0x01, 0x00, 0x01, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f,
+ 0x1f, 0x1f, 0x21, 0x20, 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGMA, 0x04, 0x04, 0x06, 0x0a, 0x0a, 0x05,
+ 0x12, 0x14, 0x17, 0x13, 0x2c, 0x33, 0x39, 0x4b, 0x4c, 0x56, 0x61, 0x78,
+ 0x7a, 0x41, 0x50, 0x68, 0x73, 0x04, 0x04, 0x06, 0x0a, 0x0a, 0x05, 0x12,
+ 0x14, 0x17, 0x13, 0x2c, 0x33, 0x39, 0x4b, 0x4c, 0x56, 0x61, 0x78, 0x7a,
+ 0x41, 0x50, 0x68, 0x73);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x07, 0x10, 0x10, 0x1a, 0x26, 0x9e,
+ 0x00, 0x4f, 0xa0, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x12, 0x0a, 0x02,
+ 0x02, 0x00, 0x33, 0x02, 0x04, 0x18, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x01, 0x7f, 0x11, 0xfd);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x86);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x00, 0x00, 0x04, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x02, 0x00, 0x2b, 0x01, 0x7e, 0x0f,
+ 0x7e, 0x10, 0xa0, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xf2);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x03, 0x07, 0x00, 0x10, 0x79);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0,
+ 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01,
+ 0x00, 0x00, 0x00, 0x23, 0x00, 0x23, 0x81, 0x02, 0x40, 0x00, 0x20, 0x6e,
+ 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0,
+ 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x03, 0xff, 0xf8);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_E1, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x96);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
+ hx83102_enable_extended_cmds(&dsi_ctx, false);
+
+ mipi_dsi_msleep(dsi_ctx, 60);
+
+ return dsi_ctx.accum_err;
+};
+
+static const struct drm_display_mode starry_mode = {
+ .clock = 162680,
+ .hdisplay = 1200,
+ .hsync_start = 1200 + 60,
+ .hsync_end = 1200 + 60 + 20,
+ .htotal = 1200 + 60 + 20 + 40,
+ .vdisplay = 1920,
+ .vsync_start = 1920 + 116,
+ .vsync_end = 1920 + 116 + 8,
+ .vtotal = 1920 + 116 + 8 + 12,
+ .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+};
+
+static const struct hx83102_panel_desc starry_desc = {
+ .modes = &starry_mode,
+ .size = {
+ .width_mm = 141,
+ .height_mm = 226,
+ },
+ .init = starry_himax83102_j02_init,
+};
+
+static const struct drm_display_mode boe_tv110wum_default_mode = {
+ .clock = 167700,
+ .hdisplay = 1200,
+ .hsync_start = 1200 + 75,
+ .hsync_end = 1200 + 75 + 20,
+ .htotal = 1200 + 75 + 20 + 65,
+ .vdisplay = 1920,
+ .vsync_start = 1920 + 115,
+ .vsync_end = 1920 + 115 + 8,
+ .vtotal = 1920 + 115 + 8 + 12,
+ .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+};
+
+static const struct hx83102_panel_desc boe_nv110wum_desc = {
+ .modes = &boe_tv110wum_default_mode,
+ .size = {
+ .width_mm = 147,
+ .height_mm = 235,
+ },
+ .init = boe_nv110wum_init,
+};
+
+static const struct drm_display_mode ivo_t109nw41_default_mode = {
+ .clock = 167700,
+ .hdisplay = 1200,
+ .hsync_start = 1200 + 75,
+ .hsync_end = 1200 + 75 + 20,
+ .htotal = 1200 + 75 + 20 + 65,
+ .vdisplay = 1920,
+ .vsync_start = 1920 + 115,
+ .vsync_end = 1920 + 115 + 8,
+ .vtotal = 1920 + 115 + 8 + 12,
+ .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+};
+
+static const struct hx83102_panel_desc ivo_t109nw41_desc = {
+ .modes = &ivo_t109nw41_default_mode,
+ .size = {
+ .width_mm = 147,
+ .height_mm = 235,
+ },
+ .init = ivo_t109nw41_init,
+};
+
+static int hx83102_enable(struct drm_panel *panel)
+{
+ msleep(130);
+ return 0;
+}
+
+static int hx83102_disable(struct drm_panel *panel)
+{
+ struct hx83102 *ctx = panel_to_hx83102(panel);
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
+
+ dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+ mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
+ mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
+
+ mipi_dsi_msleep(&dsi_ctx, 150);
+
+ return dsi_ctx.accum_err;
+}
+
+static int hx83102_unprepare(struct drm_panel *panel)
+{
+ struct hx83102 *ctx = panel_to_hx83102(panel);
+
+ gpiod_set_value(ctx->enable_gpio, 0);
+ usleep_range(1000, 2000);
+ regulator_disable(ctx->avee);
+ regulator_disable(ctx->avdd);
+ usleep_range(5000, 7000);
+ regulator_disable(ctx->pp1800);
+
+ return 0;
+}
+
+static int hx83102_prepare(struct drm_panel *panel)
+{
+ struct hx83102 *ctx = panel_to_hx83102(panel);
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
+
+ gpiod_set_value(ctx->enable_gpio, 0);
+ usleep_range(1000, 1500);
+
+ dsi_ctx.accum_err = regulator_enable(ctx->pp1800);
+ if (dsi_ctx.accum_err)
+ return dsi_ctx.accum_err;
+
+ usleep_range(3000, 5000);
+
+ dsi_ctx.accum_err = regulator_enable(ctx->avdd);
+ if (dsi_ctx.accum_err)
+ goto poweroff1v8;
+ dsi_ctx.accum_err = regulator_enable(ctx->avee);
+ if (dsi_ctx.accum_err)
+ goto poweroffavdd;
+
+ usleep_range(10000, 11000);
+
+ mipi_dsi_dcs_nop_multi(&dsi_ctx);
+ if (dsi_ctx.accum_err)
+ goto poweroff;
+
+ usleep_range(1000, 2000);
+
+ gpiod_set_value(ctx->enable_gpio, 1);
+ usleep_range(1000, 2000);
+ gpiod_set_value(ctx->enable_gpio, 0);
+ usleep_range(1000, 2000);
+ gpiod_set_value(ctx->enable_gpio, 1);
+ usleep_range(6000, 10000);
+
+ dsi_ctx.accum_err = ctx->desc->init(ctx);
+
+ mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
+ mipi_dsi_msleep(dsi_ctx, 120);
+ mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
+ if (dsi_ctx.accum_err)
+ goto poweroff;
+
+ return 0;
+
+poweroff:
+ gpiod_set_value(ctx->enable_gpio, 0);
+ regulator_disable(ctx->avee);
+poweroffavdd:
+ regulator_disable(ctx->avdd);
+poweroff1v8:
+ usleep_range(5000, 7000);
+ regulator_disable(ctx->pp1800);
+
+ return dsi_ctx.accum_err;
+}
+
+static int hx83102_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct hx83102 *ctx = panel_to_hx83102(panel);
+ const struct drm_display_mode *m = ctx->desc->modes;
+ struct drm_display_mode *mode;
+
+ mode = drm_mode_duplicate(connector->dev, m);
+
+ mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+ drm_mode_set_name(mode);
+ drm_mode_probed_add(connector, mode);
+
+ connector->display_info.width_mm = ctx->desc->size.width_mm;
+ connector->display_info.height_mm = ctx->desc->size.height_mm;
+ connector->display_info.bpc = 8;
+
+ return 1;
+}
+
+static enum drm_panel_orientation hx83102_get_orientation(struct drm_panel *panel)
+{
+ struct hx83102 *ctx = panel_to_hx83102(panel);
+
+ return ctx->orientation;
+}
+
+static const struct drm_panel_funcs hx83102_drm_funcs = {
+ .disable = hx83102_disable,
+ .unprepare = hx83102_unprepare,
+ .prepare = hx83102_prepare,
+ .enable = hx83102_enable,
+ .get_modes = hx83102_get_modes,
+ .get_orientation = hx83102_get_orientation,
+};
+
+static int hx83102_panel_add(struct hx83102 *ctx)
+{
+ struct device *dev = &ctx->dsi->dev;
+ int err;
+
+ ctx->avdd = devm_regulator_get(dev, "avdd");
+ if (IS_ERR(ctx->avdd))
+ return PTR_ERR(ctx->avdd);
+
+ ctx->avee = devm_regulator_get(dev, "avee");
+ if (IS_ERR(ctx->avee))
+ return PTR_ERR(ctx->avee);
+
+ ctx->pp1800 = devm_regulator_get(dev, "pp1800");
+ if (IS_ERR(ctx->pp1800))
+ return PTR_ERR(ctx->pp1800);
+
+ ctx->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
+ if (IS_ERR(ctx->enable_gpio))
+ return dev_err_probe(dev, PTR_ERR(ctx->enable_gpio), "Cannot get enable GPIO\n");
+
+ ctx->base.prepare_prev_first = true;
+
+ drm_panel_init(&ctx->base, dev, &hx83102_drm_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+ err = of_drm_get_panel_orientation(dev->of_node, &ctx->orientation);
+ if (err < 0)
+ return dev_err_probe(dev, err, "failed to get orientation\n");
+
+ err = drm_panel_of_backlight(&ctx->base);
+ if (err)
+ return err;
+
+ ctx->base.funcs = &hx83102_drm_funcs;
+ ctx->base.dev = &ctx->dsi->dev;
+
+ drm_panel_add(&ctx->base);
+
+ return 0;
+}
+
+static int hx83102_probe(struct mipi_dsi_device *dsi)
+{
+ struct hx83102 *ctx;
+ int ret;
+ const struct hx83102_panel_desc *desc;
+
+ ctx = devm_kzalloc(&dsi->dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ desc = of_device_get_match_data(&dsi->dev);
+ dsi->lanes = 4;
+ dsi->format = MIPI_DSI_FMT_RGB888;
+ dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+ MIPI_DSI_MODE_LPM;
+ ctx->desc = desc;
+ ctx->dsi = dsi;
+ ret = hx83102_panel_add(ctx);
+ if (ret < 0)
+ return ret;
+
+ mipi_dsi_set_drvdata(dsi, ctx);
+
+ ret = mipi_dsi_attach(dsi);
+ if (ret)
+ drm_panel_remove(&ctx->base);
+
+ return ret;
+}
+
+static void hx83102_remove(struct mipi_dsi_device *dsi)
+{
+ struct hx83102 *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);
+
+ if (ctx->base.dev)
+ drm_panel_remove(&ctx->base);
+}
+
+static const struct of_device_id hx83102_of_match[] = {
+ { .compatible = "boe,nv110wum-l60",
+ .data = &boe_nv110wum_desc
+ },
+ { .compatible = "ivo,t109nw41",
+ .data = &ivo_t109nw41_desc
+ },
+ { .compatible = "starry,himax83102-j02",
+ .data = &starry_desc
+ },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, hx83102_of_match);
+
+static struct mipi_dsi_driver hx83102_driver = {
+ .probe = hx83102_probe,
+ .remove = hx83102_remove,
+ .driver = {
+ .name = "panel-himax-hx83102",
+ .of_match_table = hx83102_of_match,
+ },
+};
+module_mipi_dsi_driver(hx83102_driver);
+
+MODULE_AUTHOR("Cong Yang <[email protected]>");
+MODULE_DESCRIPTION("DRM driver for Himax HX83102 based MIPI DSI panels");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/panel/panel-himax-hx8394.c b/drivers/gpu/drm/panel/panel-himax-hx8394.c
index ff0dc08b9829..cb9f46e853de 100644
--- a/drivers/gpu/drm/panel/panel-himax-hx8394.c
+++ b/drivers/gpu/drm/panel/panel-himax-hx8394.c
@@ -370,8 +370,7 @@ static int hx8394_enable(struct drm_panel *panel)
sleep_in:
/* This will probably fail, but let's try orderly power off anyway. */
- ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
- if (!ret)
+ if (!mipi_dsi_dcs_enter_sleep_mode(dsi))
msleep(50);
return ret;
diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c
index b933380b7eb7..775d5d5e828c 100644
--- a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c
+++ b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c
@@ -32,7 +32,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
@@ -651,7 +651,7 @@ static int ili9341_dbi_probe(struct spi_device *spi, struct gpio_desc *dc,
spi_set_drvdata(spi, drm);
- drm_fbdev_generic_setup(drm, 0);
+ drm_fbdev_dma_setup(drm, 0);
return 0;
}
@@ -723,7 +723,8 @@ static int ili9341_probe(struct spi_device *spi)
if (!strcmp(id->name, "sf-tc240t-9370-t"))
return ili9341_dpi_probe(spi, dc, reset);
- else if (!strcmp(id->name, "yx240qv29"))
+
+ if (!strcmp(id->name, "yx240qv29"))
return ili9341_dbi_probe(spi, dc, reset);
return -ENODEV;
diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c
index 267a5307041c..266a087fe14c 100644
--- a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c
+++ b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c
@@ -15,6 +15,8 @@
#include <video/mipi_display.h>
+struct ili9882t;
+
/*
* Use this descriptor struct to describe different panels using the
* Ilitek ILI9882T display controller.
@@ -34,7 +36,7 @@ struct panel_desc {
unsigned long mode_flags;
enum mipi_dsi_pixel_format format;
- const struct panel_init_cmd *init_cmds;
+ int (*init)(struct ili9882t *boe);
unsigned int lanes;
};
@@ -52,371 +54,363 @@ struct ili9882t {
struct gpio_desc *enable_gpio;
};
-enum dsi_cmd_type {
- INIT_DCS_CMD,
- DELAY_CMD,
-};
-
-struct panel_init_cmd {
- enum dsi_cmd_type type;
- size_t len;
- const char *data;
-};
-
-#define _INIT_DCS_CMD(...) { \
- .type = INIT_DCS_CMD, \
- .len = sizeof((char[]){__VA_ARGS__}), \
- .data = (char[]){__VA_ARGS__} }
-
-#define _INIT_DELAY_CMD(...) { \
- .type = DELAY_CMD,\
- .len = sizeof((char[]){__VA_ARGS__}), \
- .data = (char[]){__VA_ARGS__} }
-
/* ILI9882-specific commands, add new commands as you decode them */
#define ILI9882T_DCS_SWITCH_PAGE 0xFF
-#define _INIT_SWITCH_PAGE_CMD(page) \
- _INIT_DCS_CMD(ILI9882T_DCS_SWITCH_PAGE, 0x98, 0x82, (page))
-
-static const struct panel_init_cmd starry_ili9882t_init_cmd[] = {
- _INIT_DELAY_CMD(5),
- _INIT_SWITCH_PAGE_CMD(0x01),
- _INIT_DCS_CMD(0x00, 0x42),
- _INIT_DCS_CMD(0x01, 0x11),
- _INIT_DCS_CMD(0x02, 0x00),
- _INIT_DCS_CMD(0x03, 0x00),
-
- _INIT_DCS_CMD(0x04, 0x01),
- _INIT_DCS_CMD(0x05, 0x11),
- _INIT_DCS_CMD(0x06, 0x00),
- _INIT_DCS_CMD(0x07, 0x00),
-
- _INIT_DCS_CMD(0x08, 0x80),
- _INIT_DCS_CMD(0x09, 0x81),
- _INIT_DCS_CMD(0x0A, 0x71),
- _INIT_DCS_CMD(0x0B, 0x00),
-
- _INIT_DCS_CMD(0x0C, 0x00),
- _INIT_DCS_CMD(0x0E, 0x1A),
-
- _INIT_DCS_CMD(0x24, 0x00),
- _INIT_DCS_CMD(0x25, 0x00),
- _INIT_DCS_CMD(0x26, 0x00),
- _INIT_DCS_CMD(0x27, 0x00),
-
- _INIT_DCS_CMD(0x2C, 0xD4),
- _INIT_DCS_CMD(0xB9, 0x40),
-
- _INIT_DCS_CMD(0xB0, 0x11),
-
- _INIT_DCS_CMD(0xE6, 0x32),
- _INIT_DCS_CMD(0xD1, 0x30),
-
- _INIT_DCS_CMD(0xD6, 0x55),
-
- _INIT_DCS_CMD(0xD0, 0x01),
- _INIT_DCS_CMD(0xE3, 0x93),
- _INIT_DCS_CMD(0xE4, 0x00),
- _INIT_DCS_CMD(0xE5, 0x80),
-
- _INIT_DCS_CMD(0x31, 0x07),
- _INIT_DCS_CMD(0x32, 0x07),
- _INIT_DCS_CMD(0x33, 0x07),
- _INIT_DCS_CMD(0x34, 0x07),
- _INIT_DCS_CMD(0x35, 0x07),
- _INIT_DCS_CMD(0x36, 0x01),
- _INIT_DCS_CMD(0x37, 0x00),
- _INIT_DCS_CMD(0x38, 0x28),
- _INIT_DCS_CMD(0x39, 0x29),
- _INIT_DCS_CMD(0x3A, 0x11),
- _INIT_DCS_CMD(0x3B, 0x13),
- _INIT_DCS_CMD(0x3C, 0x15),
- _INIT_DCS_CMD(0x3D, 0x17),
- _INIT_DCS_CMD(0x3E, 0x09),
- _INIT_DCS_CMD(0x3F, 0x0D),
- _INIT_DCS_CMD(0x40, 0x02),
- _INIT_DCS_CMD(0x41, 0x02),
- _INIT_DCS_CMD(0x42, 0x02),
- _INIT_DCS_CMD(0x43, 0x02),
- _INIT_DCS_CMD(0x44, 0x02),
- _INIT_DCS_CMD(0x45, 0x02),
- _INIT_DCS_CMD(0x46, 0x02),
-
- _INIT_DCS_CMD(0x47, 0x07),
- _INIT_DCS_CMD(0x48, 0x07),
- _INIT_DCS_CMD(0x49, 0x07),
- _INIT_DCS_CMD(0x4A, 0x07),
- _INIT_DCS_CMD(0x4B, 0x07),
- _INIT_DCS_CMD(0x4C, 0x01),
- _INIT_DCS_CMD(0x4D, 0x00),
- _INIT_DCS_CMD(0x4E, 0x28),
- _INIT_DCS_CMD(0x4F, 0x29),
- _INIT_DCS_CMD(0x50, 0x10),
- _INIT_DCS_CMD(0x51, 0x12),
- _INIT_DCS_CMD(0x52, 0x14),
- _INIT_DCS_CMD(0x53, 0x16),
- _INIT_DCS_CMD(0x54, 0x08),
- _INIT_DCS_CMD(0x55, 0x0C),
- _INIT_DCS_CMD(0x56, 0x02),
- _INIT_DCS_CMD(0x57, 0x02),
- _INIT_DCS_CMD(0x58, 0x02),
- _INIT_DCS_CMD(0x59, 0x02),
- _INIT_DCS_CMD(0x5A, 0x02),
- _INIT_DCS_CMD(0x5B, 0x02),
- _INIT_DCS_CMD(0x5C, 0x02),
-
- _INIT_DCS_CMD(0x61, 0x07),
- _INIT_DCS_CMD(0x62, 0x07),
- _INIT_DCS_CMD(0x63, 0x07),
- _INIT_DCS_CMD(0x64, 0x07),
- _INIT_DCS_CMD(0x65, 0x07),
- _INIT_DCS_CMD(0x66, 0x01),
- _INIT_DCS_CMD(0x67, 0x00),
- _INIT_DCS_CMD(0x68, 0x28),
- _INIT_DCS_CMD(0x69, 0x29),
- _INIT_DCS_CMD(0x6A, 0x16),
- _INIT_DCS_CMD(0x6B, 0x14),
- _INIT_DCS_CMD(0x6C, 0x12),
- _INIT_DCS_CMD(0x6D, 0x10),
- _INIT_DCS_CMD(0x6E, 0x0C),
- _INIT_DCS_CMD(0x6F, 0x08),
- _INIT_DCS_CMD(0x70, 0x02),
- _INIT_DCS_CMD(0x71, 0x02),
- _INIT_DCS_CMD(0x72, 0x02),
- _INIT_DCS_CMD(0x73, 0x02),
- _INIT_DCS_CMD(0x74, 0x02),
- _INIT_DCS_CMD(0x75, 0x02),
- _INIT_DCS_CMD(0x76, 0x02),
-
- _INIT_DCS_CMD(0x77, 0x07),
- _INIT_DCS_CMD(0x78, 0x07),
- _INIT_DCS_CMD(0x79, 0x07),
- _INIT_DCS_CMD(0x7A, 0x07),
- _INIT_DCS_CMD(0x7B, 0x07),
- _INIT_DCS_CMD(0x7C, 0x01),
- _INIT_DCS_CMD(0x7D, 0x00),
- _INIT_DCS_CMD(0x7E, 0x28),
- _INIT_DCS_CMD(0x7F, 0x29),
- _INIT_DCS_CMD(0x80, 0x17),
- _INIT_DCS_CMD(0x81, 0x15),
- _INIT_DCS_CMD(0x82, 0x13),
- _INIT_DCS_CMD(0x83, 0x11),
- _INIT_DCS_CMD(0x84, 0x0D),
- _INIT_DCS_CMD(0x85, 0x09),
- _INIT_DCS_CMD(0x86, 0x02),
- _INIT_DCS_CMD(0x87, 0x07),
- _INIT_DCS_CMD(0x88, 0x07),
- _INIT_DCS_CMD(0x89, 0x07),
- _INIT_DCS_CMD(0x8A, 0x07),
- _INIT_DCS_CMD(0x8B, 0x07),
- _INIT_DCS_CMD(0x8C, 0x07),
-
- _INIT_SWITCH_PAGE_CMD(0x02),
- _INIT_DCS_CMD(0x29, 0x3A),
- _INIT_DCS_CMD(0x2A, 0x3B),
-
- _INIT_DCS_CMD(0x06, 0x01),
- _INIT_DCS_CMD(0x07, 0x01),
- _INIT_DCS_CMD(0x08, 0x0C),
- _INIT_DCS_CMD(0x09, 0x44),
-
- _INIT_DCS_CMD(0x3C, 0x0A),
- _INIT_DCS_CMD(0x39, 0x11),
- _INIT_DCS_CMD(0x3D, 0x00),
- _INIT_DCS_CMD(0x3A, 0x0C),
- _INIT_DCS_CMD(0x3B, 0x44),
-
- _INIT_DCS_CMD(0x53, 0x1F),
- _INIT_DCS_CMD(0x5E, 0x40),
- _INIT_DCS_CMD(0x84, 0x00),
-
- _INIT_SWITCH_PAGE_CMD(0x03),
- _INIT_DCS_CMD(0x20, 0x01),
- _INIT_DCS_CMD(0x21, 0x3C),
- _INIT_DCS_CMD(0x22, 0xFA),
-
- _INIT_SWITCH_PAGE_CMD(0x0A),
- _INIT_DCS_CMD(0xE0, 0x01),
- _INIT_DCS_CMD(0xE2, 0x01),
- _INIT_DCS_CMD(0xE5, 0x91),
- _INIT_DCS_CMD(0xE6, 0x3C),
- _INIT_DCS_CMD(0xE7, 0x00),
- _INIT_DCS_CMD(0xE8, 0xFA),
-
- _INIT_SWITCH_PAGE_CMD(0x12),
- _INIT_DCS_CMD(0x87, 0x2C),
-
- _INIT_SWITCH_PAGE_CMD(0x05),
- _INIT_DCS_CMD(0x73, 0xE5),
- _INIT_DCS_CMD(0x7F, 0x6B),
- _INIT_DCS_CMD(0x6D, 0xA4),
- _INIT_DCS_CMD(0x79, 0x54),
- _INIT_DCS_CMD(0x69, 0x97),
- _INIT_DCS_CMD(0x6A, 0x97),
- _INIT_DCS_CMD(0xA5, 0x3F),
- _INIT_DCS_CMD(0x61, 0xDA),
- _INIT_DCS_CMD(0xA7, 0xF1),
- _INIT_DCS_CMD(0x5F, 0x01),
- _INIT_DCS_CMD(0x62, 0x3F),
- _INIT_DCS_CMD(0x1D, 0x90),
- _INIT_DCS_CMD(0x86, 0x87),
-
- _INIT_SWITCH_PAGE_CMD(0x06),
- _INIT_DCS_CMD(0xC0, 0x80),
- _INIT_DCS_CMD(0xC1, 0x07),
- _INIT_DCS_CMD(0xCA, 0x58),
- _INIT_DCS_CMD(0xCB, 0x02),
- _INIT_DCS_CMD(0xCE, 0x58),
- _INIT_DCS_CMD(0xCF, 0x02),
- _INIT_DCS_CMD(0x67, 0x60),
- _INIT_DCS_CMD(0x10, 0x00),
- _INIT_DCS_CMD(0x92, 0x22),
- _INIT_DCS_CMD(0xD3, 0x08),
- _INIT_DCS_CMD(0xD6, 0x55),
- _INIT_DCS_CMD(0xDC, 0x38),
-
- _INIT_SWITCH_PAGE_CMD(0x08),
- _INIT_DCS_CMD(0xE0, 0x00, 0x10, 0x2A, 0x4D, 0x61, 0x56, 0x6A, 0x6E, 0x79, 0x76, 0x8F, 0x95, 0x98, 0xAE, 0xAA, 0xB2, 0xBB, 0xCE, 0xC6, 0xBD, 0xD5, 0xE2, 0xE8),
- _INIT_DCS_CMD(0xE1, 0x00, 0x10, 0x2A, 0x4D, 0x61, 0x56, 0x6A, 0x6E, 0x79, 0x76, 0x8F, 0x95, 0x98, 0xAE, 0xAA, 0xB2, 0xBB, 0xCE, 0xC6, 0xBD, 0xD5, 0xE2, 0xE8),
-
- _INIT_SWITCH_PAGE_CMD(0x04),
- _INIT_DCS_CMD(0xBA, 0x81),
-
- _INIT_SWITCH_PAGE_CMD(0x0C),
- _INIT_DCS_CMD(0x00, 0x02),
- _INIT_DCS_CMD(0x01, 0x00),
- _INIT_DCS_CMD(0x02, 0x03),
- _INIT_DCS_CMD(0x03, 0x01),
- _INIT_DCS_CMD(0x04, 0x03),
- _INIT_DCS_CMD(0x05, 0x02),
- _INIT_DCS_CMD(0x06, 0x04),
- _INIT_DCS_CMD(0x07, 0x03),
- _INIT_DCS_CMD(0x08, 0x03),
- _INIT_DCS_CMD(0x09, 0x04),
- _INIT_DCS_CMD(0x0A, 0x04),
- _INIT_DCS_CMD(0x0B, 0x05),
- _INIT_DCS_CMD(0x0C, 0x04),
- _INIT_DCS_CMD(0x0D, 0x06),
- _INIT_DCS_CMD(0x0E, 0x05),
- _INIT_DCS_CMD(0x0F, 0x07),
- _INIT_DCS_CMD(0x10, 0x04),
- _INIT_DCS_CMD(0x11, 0x08),
- _INIT_DCS_CMD(0x12, 0x05),
- _INIT_DCS_CMD(0x13, 0x09),
- _INIT_DCS_CMD(0x14, 0x05),
- _INIT_DCS_CMD(0x15, 0x0A),
- _INIT_DCS_CMD(0x16, 0x06),
- _INIT_DCS_CMD(0x17, 0x0B),
- _INIT_DCS_CMD(0x18, 0x05),
- _INIT_DCS_CMD(0x19, 0x0C),
- _INIT_DCS_CMD(0x1A, 0x06),
- _INIT_DCS_CMD(0x1B, 0x0D),
- _INIT_DCS_CMD(0x1C, 0x06),
- _INIT_DCS_CMD(0x1D, 0x0E),
- _INIT_DCS_CMD(0x1E, 0x07),
- _INIT_DCS_CMD(0x1F, 0x0F),
- _INIT_DCS_CMD(0x20, 0x06),
- _INIT_DCS_CMD(0x21, 0x10),
- _INIT_DCS_CMD(0x22, 0x07),
- _INIT_DCS_CMD(0x23, 0x11),
- _INIT_DCS_CMD(0x24, 0x07),
- _INIT_DCS_CMD(0x25, 0x12),
- _INIT_DCS_CMD(0x26, 0x08),
- _INIT_DCS_CMD(0x27, 0x13),
- _INIT_DCS_CMD(0x28, 0x07),
- _INIT_DCS_CMD(0x29, 0x14),
- _INIT_DCS_CMD(0x2A, 0x08),
- _INIT_DCS_CMD(0x2B, 0x15),
- _INIT_DCS_CMD(0x2C, 0x08),
- _INIT_DCS_CMD(0x2D, 0x16),
- _INIT_DCS_CMD(0x2E, 0x09),
- _INIT_DCS_CMD(0x2F, 0x17),
- _INIT_DCS_CMD(0x30, 0x08),
- _INIT_DCS_CMD(0x31, 0x18),
- _INIT_DCS_CMD(0x32, 0x09),
- _INIT_DCS_CMD(0x33, 0x19),
- _INIT_DCS_CMD(0x34, 0x09),
- _INIT_DCS_CMD(0x35, 0x1A),
- _INIT_DCS_CMD(0x36, 0x0A),
- _INIT_DCS_CMD(0x37, 0x1B),
- _INIT_DCS_CMD(0x38, 0x0A),
- _INIT_DCS_CMD(0x39, 0x1C),
- _INIT_DCS_CMD(0x3A, 0x0A),
- _INIT_DCS_CMD(0x3B, 0x1D),
- _INIT_DCS_CMD(0x3C, 0x0A),
- _INIT_DCS_CMD(0x3D, 0x1E),
- _INIT_DCS_CMD(0x3E, 0x0A),
- _INIT_DCS_CMD(0x3F, 0x1F),
-
- _INIT_SWITCH_PAGE_CMD(0x04),
- _INIT_DCS_CMD(0xBA, 0x01),
-
- _INIT_SWITCH_PAGE_CMD(0x0E),
- _INIT_DCS_CMD(0x02, 0x0C),
- _INIT_DCS_CMD(0x20, 0x10),
- _INIT_DCS_CMD(0x25, 0x16),
- _INIT_DCS_CMD(0x26, 0xE0),
- _INIT_DCS_CMD(0x27, 0x00),
- _INIT_DCS_CMD(0x29, 0x71),
- _INIT_DCS_CMD(0x2A, 0x46),
- _INIT_DCS_CMD(0x2B, 0x1F),
- _INIT_DCS_CMD(0x2D, 0xC7),
- _INIT_DCS_CMD(0x31, 0x02),
- _INIT_DCS_CMD(0x32, 0xDF),
- _INIT_DCS_CMD(0x33, 0x5A),
- _INIT_DCS_CMD(0x34, 0xC0),
- _INIT_DCS_CMD(0x35, 0x5A),
- _INIT_DCS_CMD(0x36, 0xC0),
- _INIT_DCS_CMD(0x38, 0x65),
- _INIT_DCS_CMD(0x80, 0x3E),
- _INIT_DCS_CMD(0x81, 0xA0),
- _INIT_DCS_CMD(0xB0, 0x01),
- _INIT_DCS_CMD(0xB1, 0xCC),
- _INIT_DCS_CMD(0xC0, 0x12),
- _INIT_DCS_CMD(0xC2, 0xCC),
- _INIT_DCS_CMD(0xC3, 0xCC),
- _INIT_DCS_CMD(0xC4, 0xCC),
- _INIT_DCS_CMD(0xC5, 0xCC),
- _INIT_DCS_CMD(0xC6, 0xCC),
- _INIT_DCS_CMD(0xC7, 0xCC),
- _INIT_DCS_CMD(0xC8, 0xCC),
- _INIT_DCS_CMD(0xC9, 0xCC),
- _INIT_DCS_CMD(0x30, 0x00),
- _INIT_DCS_CMD(0x00, 0x81),
- _INIT_DCS_CMD(0x08, 0x02),
- _INIT_DCS_CMD(0x09, 0x00),
- _INIT_DCS_CMD(0x07, 0x21),
- _INIT_DCS_CMD(0x04, 0x10),
-
- _INIT_SWITCH_PAGE_CMD(0x1E),
- _INIT_DCS_CMD(0x60, 0x00),
- _INIT_DCS_CMD(0x64, 0x00),
- _INIT_DCS_CMD(0x6D, 0x00),
-
- _INIT_SWITCH_PAGE_CMD(0x0B),
- _INIT_DCS_CMD(0xA6, 0x44),
- _INIT_DCS_CMD(0xA7, 0xB6),
- _INIT_DCS_CMD(0xA8, 0x03),
- _INIT_DCS_CMD(0xA9, 0x03),
- _INIT_DCS_CMD(0xAA, 0x51),
- _INIT_DCS_CMD(0xAB, 0x51),
- _INIT_DCS_CMD(0xAC, 0x04),
- _INIT_DCS_CMD(0xBD, 0x92),
- _INIT_DCS_CMD(0xBE, 0xA1),
-
- _INIT_SWITCH_PAGE_CMD(0x05),
- _INIT_DCS_CMD(0x86, 0x87),
-
- _INIT_SWITCH_PAGE_CMD(0x06),
- _INIT_DCS_CMD(0x92, 0x22),
-
- _INIT_SWITCH_PAGE_CMD(0x00),
- _INIT_DCS_CMD(MIPI_DCS_EXIT_SLEEP_MODE),
- _INIT_DELAY_CMD(120),
- _INIT_DCS_CMD(MIPI_DCS_SET_DISPLAY_ON),
- _INIT_DELAY_CMD(20),
- {},
+#define ili9882t_switch_page(ctx, page) \
+ mipi_dsi_dcs_write_seq_multi(ctx, ILI9882T_DCS_SWITCH_PAGE, \
+ 0x98, 0x82, (page))
+
+static int starry_ili9882t_init(struct ili9882t *ili)
+{
+ struct mipi_dsi_multi_context ctx = { .dsi = ili->dsi };
+
+ usleep_range(5000, 5100);
+
+ ili9882t_switch_page(&ctx, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x42);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x01, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x03, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x80);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x81);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0a, 0x71);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0b, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0c, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x1a);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2c, 0xd4);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x40);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x11);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0x32);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd1, 0x30);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x55);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd0, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe3, 0x93);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe4, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x80);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x31, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x32, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x36, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x37, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x38, 0x28);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x29);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x13);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3c, 0x15);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3d, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3e, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3f, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x40, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x41, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x42, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x43, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x44, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x45, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x46, 0x02);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x47, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x48, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x49, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4a, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4b, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4c, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4e, 0x28);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4f, 0x29);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x50, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x51, 0x12);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x52, 0x14);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x53, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x54, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x55, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x56, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x57, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x58, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x59, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5a, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5b, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5c, 0x02);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x62, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x63, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x64, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x65, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x66, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x67, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x68, 0x28);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x69, 0x29);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6a, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6b, 0x14);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6c, 0x12);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6d, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6e, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6f, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x70, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x71, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x72, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x73, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x74, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x75, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x76, 0x02);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x77, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x78, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x79, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7a, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7b, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7c, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7e, 0x28);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7f, 0x29);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x80, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x81, 0x15);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x82, 0x13);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x83, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x84, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x85, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x86, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x87, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x88, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x89, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x8a, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x8b, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x8c, 0x07);
+
+ ili9882t_switch_page(&ctx, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x3a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x3b);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x44);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3c, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x44);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x53, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5e, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x84, 0x00);
+
+ ili9882t_switch_page(&ctx, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x21, 0x3c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0xfa);
+
+ ili9882t_switch_page(&ctx, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe2, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x91);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0x3c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe7, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe8, 0xfa);
+
+ ili9882t_switch_page(&ctx, 0x12);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x87, 0x2c);
+
+ ili9882t_switch_page(&ctx, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x73, 0xe5);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7f, 0x6b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6d, 0xa4);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x79, 0x54);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x69, 0x97);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6a, 0x97);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa5, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0xda);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa7, 0xf1);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5f, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x62, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1d, 0x90);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x86, 0x87);
+
+ ili9882t_switch_page(&ctx, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x80);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x58);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0x58);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcf, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x67, 0x60);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x10, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x92, 0x22);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x55);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0x38);
+
+ ili9882t_switch_page(&ctx, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x00, 0x10, 0x2a, 0x4d, 0x61, 0x56, 0x6a, 0x6e,
+ 0x79, 0x76, 0x8f, 0x95, 0x98, 0xae, 0xaa, 0xb2, 0xbb, 0xce,
+ 0xc6, 0xbd, 0xd5, 0xe2, 0xe8);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x00, 0x10, 0x2a, 0x4d, 0x61, 0x56, 0x6a, 0x6e,
+ 0x79, 0x76, 0x8f, 0x95, 0x98, 0xae, 0xaa, 0xb2, 0xbb, 0xce,
+ 0xc6, 0xbd, 0xd5, 0xe2, 0xe8);
+
+ ili9882t_switch_page(&ctx, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x81);
+
+ ili9882t_switch_page(&ctx, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x01, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x03, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0a, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0b, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0c, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x10, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x11, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x12, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x13, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x15, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x16, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x17, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x18, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x19, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1a, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1b, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1c, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1d, 0x0e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1e, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1f, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x21, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x23, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x12);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x13);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x28, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x14);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x15);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2c, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2d, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2e, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2f, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x31, 0x18);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x32, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x19);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x1a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x36, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x37, 0x1b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x38, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x1c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x1d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3c, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3d, 0x1e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3e, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3f, 0x1f);
+
+ ili9882t_switch_page(&ctx, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x01);
+
+ ili9882t_switch_page(&ctx, 0x0e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0xe0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x71);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2d, 0xc7);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x31, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x32, 0xdf);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x5a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0xc0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x5a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x36, 0xc0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x38, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x80, 0x3e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x81, 0xa0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0xcc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x12);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xcc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0xcc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0xcc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0xcc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xcc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0xcc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0xcc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0xcc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x81);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x21);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x10);
+
+ ili9882t_switch_page(&ctx, 0x1e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x60, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x64, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6d, 0x00);
+
+ ili9882t_switch_page(&ctx, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa6, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa7, 0xb6);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa8, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa9, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xaa, 0x51);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xab, 0x51);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xac, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x92);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0xa1);
+
+ ili9882t_switch_page(&ctx, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x86, 0x87);
+
+ ili9882t_switch_page(&ctx, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x92, 0x22);
+
+ ili9882t_switch_page(&ctx, 0x00);
+ mipi_dsi_dcs_exit_sleep_mode_multi(&ctx);
+
+ mipi_dsi_msleep(&ctx, 120);
+
+ mipi_dsi_dcs_set_display_on_multi(&ctx);
+
+ mipi_dsi_msleep(&ctx, 20);
+
+ return ctx.accum_err;
};
static inline struct ili9882t *to_ili9882t(struct drm_panel *panel)
@@ -424,97 +418,21 @@ static inline struct ili9882t *to_ili9882t(struct drm_panel *panel)
return container_of(panel, struct ili9882t, base);
}
-static int ili9882t_init_dcs_cmd(struct ili9882t *ili)
-{
- struct mipi_dsi_device *dsi = ili->dsi;
- struct drm_panel *panel = &ili->base;
- int i, err = 0;
-
- if (ili->desc->init_cmds) {
- const struct panel_init_cmd *init_cmds = ili->desc->init_cmds;
-
- for (i = 0; init_cmds[i].len != 0; i++) {
- const struct panel_init_cmd *cmd = &init_cmds[i];
-
- switch (cmd->type) {
- case DELAY_CMD:
- msleep(cmd->data[0]);
- err = 0;
- break;
-
- case INIT_DCS_CMD:
- err = mipi_dsi_dcs_write(dsi, cmd->data[0],
- cmd->len <= 1 ? NULL :
- &cmd->data[1],
- cmd->len - 1);
- break;
-
- default:
- err = -EINVAL;
- }
-
- if (err < 0) {
- dev_err(panel->dev,
- "failed to write command %u\n", i);
- return err;
- }
- }
- }
- return 0;
-}
-
-static int ili9882t_switch_page(struct mipi_dsi_device *dsi, u8 page)
-{
- int ret;
- const struct panel_init_cmd cmd = _INIT_SWITCH_PAGE_CMD(page);
-
- ret = mipi_dsi_dcs_write(dsi, cmd.data[0],
- cmd.len <= 1 ? NULL :
- &cmd.data[1],
- cmd.len - 1);
- if (ret) {
- dev_err(&dsi->dev,
- "error switching panel controller page (%d)\n", ret);
- return ret;
- }
-
- return 0;
-}
-
-static int ili9882t_enter_sleep_mode(struct ili9882t *ili)
-{
- struct mipi_dsi_device *dsi = ili->dsi;
- int ret;
-
- dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
-
- ret = mipi_dsi_dcs_set_display_off(dsi);
- if (ret < 0)
- return ret;
-
- ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
static int ili9882t_disable(struct drm_panel *panel)
{
struct ili9882t *ili = to_ili9882t(panel);
- struct mipi_dsi_device *dsi = ili->dsi;
- int ret;
+ struct mipi_dsi_multi_context ctx = { .dsi = ili->dsi };
- ili9882t_switch_page(dsi, 0x00);
- ret = ili9882t_enter_sleep_mode(ili);
- if (ret < 0) {
- dev_err(panel->dev, "failed to set panel off: %d\n", ret);
- return ret;
- }
+ ili9882t_switch_page(&ctx, 0x00);
- msleep(150);
+ ili->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
- return 0;
+ mipi_dsi_dcs_set_display_off_multi(&ctx);
+ mipi_dsi_dcs_enter_sleep_mode_multi(&ctx);
+
+ mipi_dsi_msleep(&ctx, 150);
+
+ return ctx.accum_err;
}
static int ili9882t_unprepare(struct drm_panel *panel)
@@ -560,7 +478,11 @@ static int ili9882t_prepare(struct drm_panel *panel)
usleep_range(10000, 11000);
// MIPI needs to keep the LP11 state before the lcm_reset pin is pulled high
- mipi_dsi_dcs_nop(ili->dsi);
+ ret = mipi_dsi_dcs_nop(ili->dsi);
+ if (ret < 0) {
+ dev_err(&ili->dsi->dev, "Failed to send NOP: %d\n", ret);
+ goto poweroff;
+ }
usleep_range(1000, 2000);
gpiod_set_value(ili->enable_gpio, 1);
@@ -570,22 +492,20 @@ static int ili9882t_prepare(struct drm_panel *panel)
gpiod_set_value(ili->enable_gpio, 1);
usleep_range(6000, 10000);
- ret = ili9882t_init_dcs_cmd(ili);
- if (ret < 0) {
- dev_err(panel->dev, "failed to init panel: %d\n", ret);
+ ret = ili->desc->init(ili);
+ if (ret < 0)
goto poweroff;
- }
return 0;
poweroff:
+ gpiod_set_value(ili->enable_gpio, 0);
regulator_disable(ili->avee);
poweroffavdd:
regulator_disable(ili->avdd);
poweroff1v8:
usleep_range(5000, 7000);
regulator_disable(ili->pp1800);
- gpiod_set_value(ili->enable_gpio, 0);
return ret;
}
@@ -620,7 +540,7 @@ static const struct panel_desc starry_ili9882t_desc = {
.format = MIPI_DSI_FMT_RGB888,
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
MIPI_DSI_MODE_LPM,
- .init_cmds = starry_ili9882t_init_cmd,
+ .init = starry_ili9882t_init,
};
static int ili9882t_get_modes(struct drm_panel *panel,
diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
index 485178a99910..0691a27a0daa 100644
--- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c
+++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -17,14 +17,7 @@
#include <drm/drm_modes.h>
#include <drm/drm_panel.h>
-struct panel_init_cmd {
- size_t len;
- const char *data;
-};
-
-#define _INIT_CMD(...) { \
- .len = sizeof((char[]){__VA_ARGS__}), \
- .data = (char[]){__VA_ARGS__} }
+struct innolux_panel;
struct panel_desc {
const struct drm_display_mode *mode;
@@ -36,7 +29,7 @@ struct panel_desc {
unsigned long flags;
enum mipi_dsi_pixel_format format;
- const struct panel_init_cmd *init_cmds;
+ int (*init)(struct innolux_panel *innolux);
unsigned int lanes;
const char * const *supply_names;
unsigned int num_supplies;
@@ -132,32 +125,10 @@ static int innolux_panel_prepare(struct drm_panel *panel)
/* p079zca: t4, p097pfg: t5 */
usleep_range(20000, 21000);
- if (innolux->desc->init_cmds) {
- const struct panel_init_cmd *cmds =
- innolux->desc->init_cmds;
- unsigned int i;
-
- for (i = 0; cmds[i].len != 0; i++) {
- const struct panel_init_cmd *cmd = &cmds[i];
-
- err = mipi_dsi_generic_write(innolux->link, cmd->data,
- cmd->len);
- if (err < 0) {
- dev_err(panel->dev, "failed to write command %u\n", i);
- goto poweroff;
- }
-
- /*
- * Included by random guessing, because without this
- * (or at least, some delay), the panel sometimes
- * didn't appear to pick up the command sequence.
- */
- err = mipi_dsi_dcs_nop(innolux->link);
- if (err < 0) {
- dev_err(panel->dev, "failed to send DCS nop: %d\n", err);
- goto poweroff;
- }
- }
+ if (innolux->desc->init) {
+ err = innolux->desc->init(innolux);
+ if (err < 0)
+ goto poweroff;
}
err = mipi_dsi_dcs_exit_sleep_mode(innolux->link);
@@ -250,119 +221,137 @@ static const struct drm_display_mode innolux_p097pfg_mode = {
.vtotal = 2048 + 100 + 2 + 18,
};
+static void innolux_panel_write_multi(struct mipi_dsi_multi_context *ctx,
+ const void *payload, size_t size)
+{
+ mipi_dsi_generic_write_multi(ctx, payload, size);
+
+ /*
+ * Included by random guessing, because without this
+ * (or at least, some delay), the panel sometimes
+ * didn't appear to pick up the command sequence.
+ */
+ mipi_dsi_dcs_nop_multi(ctx);
+}
+
+#define innolux_panel_init_cmd_multi(ctx, seq...) \
+ do { \
+ static const u8 d[] = { seq }; \
+ innolux_panel_write_multi(ctx, d, ARRAY_SIZE(d)); \
+ } while (0)
+
+#define innolux_panel_switch_page(ctx, page) \
+ innolux_panel_init_cmd_multi(ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, (page))
+
/*
* Display manufacturer failed to provide init sequencing according to
* https://chromium-review.googlesource.com/c/chromiumos/third_party/coreboot/+/892065/
* so the init sequence stems from a register dump of a working panel.
*/
-static const struct panel_init_cmd innolux_p097pfg_init_cmds[] = {
- /* page 0 */
- _INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x00),
- _INIT_CMD(0xB1, 0xE8, 0x11),
- _INIT_CMD(0xB2, 0x25, 0x02),
- _INIT_CMD(0xB5, 0x08, 0x00),
- _INIT_CMD(0xBC, 0x0F, 0x00),
- _INIT_CMD(0xB8, 0x03, 0x06, 0x00, 0x00),
- _INIT_CMD(0xBD, 0x01, 0x90, 0x14, 0x14),
- _INIT_CMD(0x6F, 0x01),
- _INIT_CMD(0xC0, 0x03),
- _INIT_CMD(0x6F, 0x02),
- _INIT_CMD(0xC1, 0x0D),
- _INIT_CMD(0xD9, 0x01, 0x09, 0x70),
- _INIT_CMD(0xC5, 0x12, 0x21, 0x00),
- _INIT_CMD(0xBB, 0x93, 0x93),
-
- /* page 1 */
- _INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x01),
- _INIT_CMD(0xB3, 0x3C, 0x3C),
- _INIT_CMD(0xB4, 0x0F, 0x0F),
- _INIT_CMD(0xB9, 0x45, 0x45),
- _INIT_CMD(0xBA, 0x14, 0x14),
- _INIT_CMD(0xCA, 0x02),
- _INIT_CMD(0xCE, 0x04),
- _INIT_CMD(0xC3, 0x9B, 0x9B),
- _INIT_CMD(0xD8, 0xC0, 0x03),
- _INIT_CMD(0xBC, 0x82, 0x01),
- _INIT_CMD(0xBD, 0x9E, 0x01),
-
- /* page 2 */
- _INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x02),
- _INIT_CMD(0xB0, 0x82),
- _INIT_CMD(0xD1, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x82, 0x00, 0xA5,
- 0x00, 0xC1, 0x00, 0xEA, 0x01, 0x0D, 0x01, 0x40),
- _INIT_CMD(0xD2, 0x01, 0x6A, 0x01, 0xA8, 0x01, 0xDC, 0x02, 0x29,
- 0x02, 0x67, 0x02, 0x68, 0x02, 0xA8, 0x02, 0xF0),
- _INIT_CMD(0xD3, 0x03, 0x19, 0x03, 0x49, 0x03, 0x67, 0x03, 0x8C,
- 0x03, 0xA6, 0x03, 0xC7, 0x03, 0xDE, 0x03, 0xEC),
- _INIT_CMD(0xD4, 0x03, 0xFF, 0x03, 0xFF),
- _INIT_CMD(0xE0, 0x00, 0x00, 0x00, 0x86, 0x00, 0xC5, 0x00, 0xE5,
- 0x00, 0xFF, 0x01, 0x26, 0x01, 0x45, 0x01, 0x75),
- _INIT_CMD(0xE1, 0x01, 0x9C, 0x01, 0xD5, 0x02, 0x05, 0x02, 0x4D,
- 0x02, 0x86, 0x02, 0x87, 0x02, 0xC3, 0x03, 0x03),
- _INIT_CMD(0xE2, 0x03, 0x2A, 0x03, 0x56, 0x03, 0x72, 0x03, 0x94,
- 0x03, 0xAC, 0x03, 0xCB, 0x03, 0xE0, 0x03, 0xED),
- _INIT_CMD(0xE3, 0x03, 0xFF, 0x03, 0xFF),
-
- /* page 3 */
- _INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x03),
- _INIT_CMD(0xB0, 0x00, 0x00, 0x00, 0x00),
- _INIT_CMD(0xB1, 0x00, 0x00, 0x00, 0x00),
- _INIT_CMD(0xB2, 0x00, 0x00, 0x06, 0x04, 0x01, 0x40, 0x85),
- _INIT_CMD(0xB3, 0x10, 0x07, 0xFC, 0x04, 0x01, 0x40, 0x80),
- _INIT_CMD(0xB6, 0xF0, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01,
- 0x40, 0x80),
- _INIT_CMD(0xBA, 0xC5, 0x07, 0x00, 0x04, 0x11, 0x25, 0x8C),
- _INIT_CMD(0xBB, 0xC5, 0x07, 0x00, 0x03, 0x11, 0x25, 0x8C),
- _INIT_CMD(0xC0, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x80, 0x80),
- _INIT_CMD(0xC1, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x80, 0x80),
- _INIT_CMD(0xC4, 0x00, 0x00),
- _INIT_CMD(0xEF, 0x41),
-
- /* page 4 */
- _INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x04),
- _INIT_CMD(0xEC, 0x4C),
-
- /* page 5 */
- _INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x05),
- _INIT_CMD(0xB0, 0x13, 0x03, 0x03, 0x01),
- _INIT_CMD(0xB1, 0x30, 0x00),
- _INIT_CMD(0xB2, 0x02, 0x02, 0x00),
- _INIT_CMD(0xB3, 0x82, 0x23, 0x82, 0x9D),
- _INIT_CMD(0xB4, 0xC5, 0x75, 0x24, 0x57),
- _INIT_CMD(0xB5, 0x00, 0xD4, 0x72, 0x11, 0x11, 0xAB, 0x0A),
- _INIT_CMD(0xB6, 0x00, 0x00, 0xD5, 0x72, 0x24, 0x56),
- _INIT_CMD(0xB7, 0x5C, 0xDC, 0x5C, 0x5C),
- _INIT_CMD(0xB9, 0x0C, 0x00, 0x00, 0x01, 0x00),
- _INIT_CMD(0xC0, 0x75, 0x11, 0x11, 0x54, 0x05),
- _INIT_CMD(0xC6, 0x00, 0x00, 0x00, 0x00),
- _INIT_CMD(0xD0, 0x00, 0x48, 0x08, 0x00, 0x00),
- _INIT_CMD(0xD1, 0x00, 0x48, 0x09, 0x00, 0x00),
-
- /* page 6 */
- _INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x06),
- _INIT_CMD(0xB0, 0x02, 0x32, 0x32, 0x08, 0x2F),
- _INIT_CMD(0xB1, 0x2E, 0x15, 0x14, 0x13, 0x12),
- _INIT_CMD(0xB2, 0x11, 0x10, 0x00, 0x3D, 0x3D),
- _INIT_CMD(0xB3, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D),
- _INIT_CMD(0xB4, 0x3D, 0x32),
- _INIT_CMD(0xB5, 0x03, 0x32, 0x32, 0x09, 0x2F),
- _INIT_CMD(0xB6, 0x2E, 0x1B, 0x1A, 0x19, 0x18),
- _INIT_CMD(0xB7, 0x17, 0x16, 0x01, 0x3D, 0x3D),
- _INIT_CMD(0xB8, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D),
- _INIT_CMD(0xB9, 0x3D, 0x32),
- _INIT_CMD(0xC0, 0x01, 0x32, 0x32, 0x09, 0x2F),
- _INIT_CMD(0xC1, 0x2E, 0x1A, 0x1B, 0x16, 0x17),
- _INIT_CMD(0xC2, 0x18, 0x19, 0x03, 0x3D, 0x3D),
- _INIT_CMD(0xC3, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D),
- _INIT_CMD(0xC4, 0x3D, 0x32),
- _INIT_CMD(0xC5, 0x00, 0x32, 0x32, 0x08, 0x2F),
- _INIT_CMD(0xC6, 0x2E, 0x14, 0x15, 0x10, 0x11),
- _INIT_CMD(0xC7, 0x12, 0x13, 0x02, 0x3D, 0x3D),
- _INIT_CMD(0xC8, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D),
- _INIT_CMD(0xC9, 0x3D, 0x32),
-
- {},
-};
+static int innolux_p097pfg_init(struct innolux_panel *innolux)
+{
+ struct mipi_dsi_multi_context ctx = { .dsi = innolux->link };
+
+ innolux_panel_switch_page(&ctx, 0x00);
+ innolux_panel_init_cmd_multi(&ctx, 0xb1, 0xe8, 0x11);
+ innolux_panel_init_cmd_multi(&ctx, 0xb2, 0x25, 0x02);
+ innolux_panel_init_cmd_multi(&ctx, 0xb5, 0x08, 0x00);
+ innolux_panel_init_cmd_multi(&ctx, 0xbc, 0x0f, 0x00);
+ innolux_panel_init_cmd_multi(&ctx, 0xb8, 0x03, 0x06, 0x00, 0x00);
+ innolux_panel_init_cmd_multi(&ctx, 0xbd, 0x01, 0x90, 0x14, 0x14);
+ innolux_panel_init_cmd_multi(&ctx, 0x6f, 0x01);
+ innolux_panel_init_cmd_multi(&ctx, 0xc0, 0x03);
+ innolux_panel_init_cmd_multi(&ctx, 0x6f, 0x02);
+ innolux_panel_init_cmd_multi(&ctx, 0xc1, 0x0d);
+ innolux_panel_init_cmd_multi(&ctx, 0xd9, 0x01, 0x09, 0x70);
+ innolux_panel_init_cmd_multi(&ctx, 0xc5, 0x12, 0x21, 0x00);
+ innolux_panel_init_cmd_multi(&ctx, 0xbb, 0x93, 0x93);
+
+ innolux_panel_switch_page(&ctx, 0x01);
+ innolux_panel_init_cmd_multi(&ctx, 0xb3, 0x3c, 0x3c);
+ innolux_panel_init_cmd_multi(&ctx, 0xb4, 0x0f, 0x0f);
+ innolux_panel_init_cmd_multi(&ctx, 0xb9, 0x45, 0x45);
+ innolux_panel_init_cmd_multi(&ctx, 0xba, 0x14, 0x14);
+ innolux_panel_init_cmd_multi(&ctx, 0xca, 0x02);
+ innolux_panel_init_cmd_multi(&ctx, 0xce, 0x04);
+ innolux_panel_init_cmd_multi(&ctx, 0xc3, 0x9b, 0x9b);
+ innolux_panel_init_cmd_multi(&ctx, 0xd8, 0xc0, 0x03);
+ innolux_panel_init_cmd_multi(&ctx, 0xbc, 0x82, 0x01);
+ innolux_panel_init_cmd_multi(&ctx, 0xbd, 0x9e, 0x01);
+
+ innolux_panel_switch_page(&ctx, 0x02);
+ innolux_panel_init_cmd_multi(&ctx, 0xb0, 0x82);
+ innolux_panel_init_cmd_multi(&ctx, 0xd1, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x82, 0x00, 0xa5,
+ 0x00, 0xc1, 0x00, 0xea, 0x01, 0x0d, 0x01, 0x40);
+ innolux_panel_init_cmd_multi(&ctx, 0xd2, 0x01, 0x6a, 0x01, 0xa8, 0x01, 0xdc, 0x02, 0x29,
+ 0x02, 0x67, 0x02, 0x68, 0x02, 0xa8, 0x02, 0xf0);
+ innolux_panel_init_cmd_multi(&ctx, 0xd3, 0x03, 0x19, 0x03, 0x49, 0x03, 0x67, 0x03, 0x8c,
+ 0x03, 0xa6, 0x03, 0xc7, 0x03, 0xde, 0x03, 0xec);
+ innolux_panel_init_cmd_multi(&ctx, 0xd4, 0x03, 0xff, 0x03, 0xff);
+ innolux_panel_init_cmd_multi(&ctx, 0xe0, 0x00, 0x00, 0x00, 0x86, 0x00, 0xc5, 0x00, 0xe5,
+ 0x00, 0xff, 0x01, 0x26, 0x01, 0x45, 0x01, 0x75);
+ innolux_panel_init_cmd_multi(&ctx, 0xe1, 0x01, 0x9c, 0x01, 0xd5, 0x02, 0x05, 0x02, 0x4d,
+ 0x02, 0x86, 0x02, 0x87, 0x02, 0xc3, 0x03, 0x03);
+ innolux_panel_init_cmd_multi(&ctx, 0xe2, 0x03, 0x2a, 0x03, 0x56, 0x03, 0x72, 0x03, 0x94,
+ 0x03, 0xac, 0x03, 0xcb, 0x03, 0xe0, 0x03, 0xed);
+ innolux_panel_init_cmd_multi(&ctx, 0xe3, 0x03, 0xff, 0x03, 0xff);
+
+ innolux_panel_switch_page(&ctx, 0x03);
+ innolux_panel_init_cmd_multi(&ctx, 0xb0, 0x00, 0x00, 0x00, 0x00);
+ innolux_panel_init_cmd_multi(&ctx, 0xb1, 0x00, 0x00, 0x00, 0x00);
+ innolux_panel_init_cmd_multi(&ctx, 0xb2, 0x00, 0x00, 0x06, 0x04, 0x01, 0x40, 0x85);
+ innolux_panel_init_cmd_multi(&ctx, 0xb3, 0x10, 0x07, 0xfc, 0x04, 0x01, 0x40, 0x80);
+ innolux_panel_init_cmd_multi(&ctx, 0xb6, 0xf0, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01,
+ 0x40, 0x80);
+ innolux_panel_init_cmd_multi(&ctx, 0xba, 0xc5, 0x07, 0x00, 0x04, 0x11, 0x25, 0x8c);
+ innolux_panel_init_cmd_multi(&ctx, 0xbb, 0xc5, 0x07, 0x00, 0x03, 0x11, 0x25, 0x8c);
+ innolux_panel_init_cmd_multi(&ctx, 0xc0, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x80, 0x80);
+ innolux_panel_init_cmd_multi(&ctx, 0xc1, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x80, 0x80);
+ innolux_panel_init_cmd_multi(&ctx, 0xc4, 0x00, 0x00);
+ innolux_panel_init_cmd_multi(&ctx, 0xef, 0x41);
+
+ innolux_panel_switch_page(&ctx, 0x04);
+ innolux_panel_init_cmd_multi(&ctx, 0xec, 0x4c);
+
+ innolux_panel_switch_page(&ctx, 0x05);
+ innolux_panel_init_cmd_multi(&ctx, 0xb0, 0x13, 0x03, 0x03, 0x01);
+ innolux_panel_init_cmd_multi(&ctx, 0xb1, 0x30, 0x00);
+ innolux_panel_init_cmd_multi(&ctx, 0xb2, 0x02, 0x02, 0x00);
+ innolux_panel_init_cmd_multi(&ctx, 0xb3, 0x82, 0x23, 0x82, 0x9d);
+ innolux_panel_init_cmd_multi(&ctx, 0xb4, 0xc5, 0x75, 0x24, 0x57);
+ innolux_panel_init_cmd_multi(&ctx, 0xb5, 0x00, 0xd4, 0x72, 0x11, 0x11, 0xab, 0x0a);
+ innolux_panel_init_cmd_multi(&ctx, 0xb6, 0x00, 0x00, 0xd5, 0x72, 0x24, 0x56);
+ innolux_panel_init_cmd_multi(&ctx, 0xb7, 0x5c, 0xdc, 0x5c, 0x5c);
+ innolux_panel_init_cmd_multi(&ctx, 0xb9, 0x0c, 0x00, 0x00, 0x01, 0x00);
+ innolux_panel_init_cmd_multi(&ctx, 0xc0, 0x75, 0x11, 0x11, 0x54, 0x05);
+ innolux_panel_init_cmd_multi(&ctx, 0xc6, 0x00, 0x00, 0x00, 0x00);
+ innolux_panel_init_cmd_multi(&ctx, 0xd0, 0x00, 0x48, 0x08, 0x00, 0x00);
+ innolux_panel_init_cmd_multi(&ctx, 0xd1, 0x00, 0x48, 0x09, 0x00, 0x00);
+
+ innolux_panel_switch_page(&ctx, 0x06);
+ innolux_panel_init_cmd_multi(&ctx, 0xb0, 0x02, 0x32, 0x32, 0x08, 0x2f);
+ innolux_panel_init_cmd_multi(&ctx, 0xb1, 0x2e, 0x15, 0x14, 0x13, 0x12);
+ innolux_panel_init_cmd_multi(&ctx, 0xb2, 0x11, 0x10, 0x00, 0x3d, 0x3d);
+ innolux_panel_init_cmd_multi(&ctx, 0xb3, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d);
+ innolux_panel_init_cmd_multi(&ctx, 0xb4, 0x3d, 0x32);
+ innolux_panel_init_cmd_multi(&ctx, 0xb5, 0x03, 0x32, 0x32, 0x09, 0x2f);
+ innolux_panel_init_cmd_multi(&ctx, 0xb6, 0x2e, 0x1b, 0x1a, 0x19, 0x18);
+ innolux_panel_init_cmd_multi(&ctx, 0xb7, 0x17, 0x16, 0x01, 0x3d, 0x3d);
+ innolux_panel_init_cmd_multi(&ctx, 0xb8, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d);
+ innolux_panel_init_cmd_multi(&ctx, 0xb9, 0x3d, 0x32);
+ innolux_panel_init_cmd_multi(&ctx, 0xc0, 0x01, 0x32, 0x32, 0x09, 0x2f);
+ innolux_panel_init_cmd_multi(&ctx, 0xc1, 0x2e, 0x1a, 0x1b, 0x16, 0x17);
+ innolux_panel_init_cmd_multi(&ctx, 0xc2, 0x18, 0x19, 0x03, 0x3d, 0x3d);
+ innolux_panel_init_cmd_multi(&ctx, 0xc3, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d);
+ innolux_panel_init_cmd_multi(&ctx, 0xc4, 0x3d, 0x32);
+ innolux_panel_init_cmd_multi(&ctx, 0xc5, 0x00, 0x32, 0x32, 0x08, 0x2f);
+ innolux_panel_init_cmd_multi(&ctx, 0xc6, 0x2e, 0x14, 0x15, 0x10, 0x11);
+ innolux_panel_init_cmd_multi(&ctx, 0xc7, 0x12, 0x13, 0x02, 0x3d, 0x3d);
+ innolux_panel_init_cmd_multi(&ctx, 0xc8, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d);
+ innolux_panel_init_cmd_multi(&ctx, 0xc9, 0x3d, 0x32);
+
+ return ctx.accum_err;
+}
static const struct panel_desc innolux_p097pfg_panel_desc = {
.mode = &innolux_p097pfg_mode,
@@ -374,7 +363,7 @@ static const struct panel_desc innolux_p097pfg_panel_desc = {
.flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
MIPI_DSI_MODE_LPM,
.format = MIPI_DSI_FMT_RGB888,
- .init_cmds = innolux_p097pfg_init_cmds,
+ .init = innolux_p097pfg_init,
.lanes = 4,
.supply_names = innolux_p097pfg_supply_names,
.num_supplies = ARRAY_SIZE(innolux_p097pfg_supply_names),
diff --git a/drivers/gpu/drm/panel/panel-lg-sw43408.c b/drivers/gpu/drm/panel/panel-lg-sw43408.c
index 115f4702d59f..354b94e36d07 100644
--- a/drivers/gpu/drm/panel/panel-lg-sw43408.c
+++ b/drivers/gpu/drm/panel/panel-lg-sw43408.c
@@ -40,83 +40,83 @@ static inline struct sw43408_panel *to_panel_info(struct drm_panel *panel)
static int sw43408_unprepare(struct drm_panel *panel)
{
- struct sw43408_panel *ctx = to_panel_info(panel);
+ struct sw43408_panel *sw43408 = to_panel_info(panel);
+ struct mipi_dsi_multi_context ctx = { .dsi = sw43408->link };
int ret;
- ret = mipi_dsi_dcs_set_display_off(ctx->link);
- if (ret < 0)
- dev_err(panel->dev, "set_display_off cmd failed ret = %d\n", ret);
+ mipi_dsi_dcs_set_display_off_multi(&ctx);
- ret = mipi_dsi_dcs_enter_sleep_mode(ctx->link);
- if (ret < 0)
- dev_err(panel->dev, "enter_sleep cmd failed ret = %d\n", ret);
+ mipi_dsi_dcs_enter_sleep_mode_multi(&ctx);
- msleep(100);
+ mipi_dsi_msleep(&ctx, 100);
- gpiod_set_value(ctx->reset_gpio, 1);
+ gpiod_set_value(sw43408->reset_gpio, 1);
+
+ ret = regulator_bulk_disable(ARRAY_SIZE(sw43408->supplies), sw43408->supplies);
- return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+ return ret ? : ctx.accum_err;
}
static int sw43408_program(struct drm_panel *panel)
{
- struct sw43408_panel *ctx = to_panel_info(panel);
+ struct sw43408_panel *sw43408 = to_panel_info(panel);
+ struct mipi_dsi_multi_context ctx = { .dsi = sw43408->link };
struct drm_dsc_picture_parameter_set pps;
- mipi_dsi_dcs_write_seq(ctx->link, MIPI_DCS_SET_GAMMA_CURVE, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, MIPI_DCS_SET_GAMMA_CURVE, 0x02);
- mipi_dsi_dcs_set_tear_on(ctx->link, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
+ mipi_dsi_dcs_set_tear_on_multi(&ctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
- mipi_dsi_dcs_write_seq(ctx->link, 0x53, 0x0c, 0x30);
- mipi_dsi_dcs_write_seq(ctx->link, 0x55, 0x00, 0x70, 0xdf, 0x00, 0x70, 0xdf);
- mipi_dsi_dcs_write_seq(ctx->link, 0xf7, 0x01, 0x49, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x53, 0x0c, 0x30);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x55, 0x00, 0x70, 0xdf, 0x00, 0x70, 0xdf);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xf7, 0x01, 0x49, 0x0c);
- mipi_dsi_dcs_exit_sleep_mode(ctx->link);
+ mipi_dsi_dcs_exit_sleep_mode_multi(&ctx);
- msleep(135);
+ mipi_dsi_msleep(&ctx, 135);
/* COMPRESSION_MODE moved after setting the PPS */
- mipi_dsi_dcs_write_seq(ctx->link, 0xb0, 0xac);
- mipi_dsi_dcs_write_seq(ctx->link, 0xe5,
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0xac);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5,
0x00, 0x3a, 0x00, 0x3a, 0x00, 0x0e, 0x10);
- mipi_dsi_dcs_write_seq(ctx->link, 0xb5,
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5,
0x75, 0x60, 0x2d, 0x5d, 0x80, 0x00, 0x0a, 0x0b,
0x00, 0x05, 0x0b, 0x00, 0x80, 0x0d, 0x0e, 0x40,
0x00, 0x0c, 0x00, 0x16, 0x00, 0xb8, 0x00, 0x80,
0x0d, 0x0e, 0x40, 0x00, 0x0c, 0x00, 0x16, 0x00,
0xb8, 0x00, 0x81, 0x00, 0x03, 0x03, 0x03, 0x01,
0x01);
- msleep(85);
- mipi_dsi_dcs_write_seq(ctx->link, 0xcd,
+ mipi_dsi_msleep(&ctx, 85);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd,
0x00, 0x00, 0x00, 0x19, 0x19, 0x19, 0x19, 0x19,
0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
0x16, 0x16);
- mipi_dsi_dcs_write_seq(ctx->link, 0xcb, 0x80, 0x5c, 0x07, 0x03, 0x28);
- mipi_dsi_dcs_write_seq(ctx->link, 0xc0, 0x02, 0x02, 0x0f);
- mipi_dsi_dcs_write_seq(ctx->link, 0x55, 0x04, 0x61, 0xdb, 0x04, 0x70, 0xdb);
- mipi_dsi_dcs_write_seq(ctx->link, 0xb0, 0xca);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x80, 0x5c, 0x07, 0x03, 0x28);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x02, 0x02, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x55, 0x04, 0x61, 0xdb, 0x04, 0x70, 0xdb);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0xca);
+
+ mipi_dsi_dcs_set_display_on_multi(&ctx);
- mipi_dsi_dcs_set_display_on(ctx->link);
+ mipi_dsi_msleep(&ctx, 50);
- msleep(50);
+ sw43408->link->mode_flags &= ~MIPI_DSI_MODE_LPM;
- ctx->link->mode_flags &= ~MIPI_DSI_MODE_LPM;
+ drm_dsc_pps_payload_pack(&pps, sw43408->link->dsc);
- drm_dsc_pps_payload_pack(&pps, ctx->link->dsc);
- mipi_dsi_picture_parameter_set(ctx->link, &pps);
+ mipi_dsi_picture_parameter_set_multi(&ctx, &pps);
- ctx->link->mode_flags |= MIPI_DSI_MODE_LPM;
+ sw43408->link->mode_flags |= MIPI_DSI_MODE_LPM;
/*
* This panel uses PPS selectors with offset:
* PPS 1 if pps_identifier is 0
* PPS 2 if pps_identifier is 1
*/
- mipi_dsi_compression_mode_ext(ctx->link, true,
- MIPI_DSI_COMPRESSION_DSC, 1);
-
- return 0;
+ mipi_dsi_compression_mode_ext_multi(&ctx, true,
+ MIPI_DSI_COMPRESSION_DSC, 1);
+ return ctx.accum_err;
}
static int sw43408_prepare(struct drm_panel *panel)
diff --git a/drivers/gpu/drm/panel/panel-novatek-nt36672e.c b/drivers/gpu/drm/panel/panel-novatek-nt36672e.c
index 20b7bfe4aa12..e81a70147259 100644
--- a/drivers/gpu/drm/panel/panel-novatek-nt36672e.c
+++ b/drivers/gpu/drm/panel/panel-novatek-nt36672e.c
@@ -33,7 +33,7 @@ struct panel_desc {
enum mipi_dsi_pixel_format format;
unsigned int lanes;
const char *panel_name;
- int (*init_sequence)(struct mipi_dsi_device *dsi);
+ void (*init_sequence)(struct mipi_dsi_multi_context *ctx);
};
struct nt36672e_panel {
@@ -49,295 +49,293 @@ static inline struct nt36672e_panel *to_nt36672e_panel(struct drm_panel *panel)
return container_of(panel, struct nt36672e_panel, panel);
}
-static int nt36672e_1080x2408_60hz_init(struct mipi_dsi_device *dsi)
+static void nt36672e_1080x2408_60hz_init(struct mipi_dsi_multi_context *ctx)
{
- mipi_dsi_dcs_write_seq(dsi, 0xff, 0x10);
- mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0xc0, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0xc1, 0x89, 0x28, 0x00, 0x08, 0x00, 0xaa, 0x02,
- 0x0e, 0x00, 0x2b, 0x00, 0x07, 0x0d, 0xb7, 0x0c, 0xb7);
-
- mipi_dsi_dcs_write_seq(dsi, 0xc2, 0x1b, 0xa0);
- mipi_dsi_dcs_write_seq(dsi, 0xff, 0x20);
- mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x01, 0x66);
- mipi_dsi_dcs_write_seq(dsi, 0x06, 0x40);
- mipi_dsi_dcs_write_seq(dsi, 0x07, 0x38);
- mipi_dsi_dcs_write_seq(dsi, 0x2f, 0x83);
- mipi_dsi_dcs_write_seq(dsi, 0x69, 0x91);
- mipi_dsi_dcs_write_seq(dsi, 0x95, 0xd1);
- mipi_dsi_dcs_write_seq(dsi, 0x96, 0xd1);
- mipi_dsi_dcs_write_seq(dsi, 0xf2, 0x64);
- mipi_dsi_dcs_write_seq(dsi, 0xf3, 0x54);
- mipi_dsi_dcs_write_seq(dsi, 0xf4, 0x64);
- mipi_dsi_dcs_write_seq(dsi, 0xf5, 0x54);
- mipi_dsi_dcs_write_seq(dsi, 0xf6, 0x64);
- mipi_dsi_dcs_write_seq(dsi, 0xf7, 0x54);
- mipi_dsi_dcs_write_seq(dsi, 0xf8, 0x64);
- mipi_dsi_dcs_write_seq(dsi, 0xf9, 0x54);
- mipi_dsi_dcs_write_seq(dsi, 0xff, 0x24);
- mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x01, 0x0f);
- mipi_dsi_dcs_write_seq(dsi, 0x03, 0x0c);
- mipi_dsi_dcs_write_seq(dsi, 0x05, 0x1d);
- mipi_dsi_dcs_write_seq(dsi, 0x08, 0x2f);
- mipi_dsi_dcs_write_seq(dsi, 0x09, 0x2e);
- mipi_dsi_dcs_write_seq(dsi, 0x0a, 0x2d);
- mipi_dsi_dcs_write_seq(dsi, 0x0b, 0x2c);
- mipi_dsi_dcs_write_seq(dsi, 0x11, 0x17);
- mipi_dsi_dcs_write_seq(dsi, 0x12, 0x13);
- mipi_dsi_dcs_write_seq(dsi, 0x13, 0x15);
- mipi_dsi_dcs_write_seq(dsi, 0x15, 0x14);
- mipi_dsi_dcs_write_seq(dsi, 0x16, 0x16);
- mipi_dsi_dcs_write_seq(dsi, 0x17, 0x18);
- mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x1d, 0x1d);
- mipi_dsi_dcs_write_seq(dsi, 0x20, 0x2f);
- mipi_dsi_dcs_write_seq(dsi, 0x21, 0x2e);
- mipi_dsi_dcs_write_seq(dsi, 0x22, 0x2d);
- mipi_dsi_dcs_write_seq(dsi, 0x23, 0x2c);
- mipi_dsi_dcs_write_seq(dsi, 0x29, 0x17);
- mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x13);
- mipi_dsi_dcs_write_seq(dsi, 0x2b, 0x15);
- mipi_dsi_dcs_write_seq(dsi, 0x2f, 0x14);
- mipi_dsi_dcs_write_seq(dsi, 0x30, 0x16);
- mipi_dsi_dcs_write_seq(dsi, 0x31, 0x18);
- mipi_dsi_dcs_write_seq(dsi, 0x32, 0x04);
- mipi_dsi_dcs_write_seq(dsi, 0x34, 0x10);
- mipi_dsi_dcs_write_seq(dsi, 0x35, 0x1f);
- mipi_dsi_dcs_write_seq(dsi, 0x36, 0x1f);
- mipi_dsi_dcs_write_seq(dsi, 0x4d, 0x14);
- mipi_dsi_dcs_write_seq(dsi, 0x4e, 0x36);
- mipi_dsi_dcs_write_seq(dsi, 0x4f, 0x36);
- mipi_dsi_dcs_write_seq(dsi, 0x53, 0x36);
- mipi_dsi_dcs_write_seq(dsi, 0x71, 0x30);
- mipi_dsi_dcs_write_seq(dsi, 0x79, 0x11);
- mipi_dsi_dcs_write_seq(dsi, 0x7a, 0x82);
- mipi_dsi_dcs_write_seq(dsi, 0x7b, 0x8f);
- mipi_dsi_dcs_write_seq(dsi, 0x7d, 0x04);
- mipi_dsi_dcs_write_seq(dsi, 0x80, 0x04);
- mipi_dsi_dcs_write_seq(dsi, 0x81, 0x04);
- mipi_dsi_dcs_write_seq(dsi, 0x82, 0x13);
- mipi_dsi_dcs_write_seq(dsi, 0x84, 0x31);
- mipi_dsi_dcs_write_seq(dsi, 0x85, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x86, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x87, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x90, 0x13);
- mipi_dsi_dcs_write_seq(dsi, 0x92, 0x31);
- mipi_dsi_dcs_write_seq(dsi, 0x93, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x94, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x95, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x9c, 0xf4);
- mipi_dsi_dcs_write_seq(dsi, 0x9d, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0xa0, 0x0f);
- mipi_dsi_dcs_write_seq(dsi, 0xa2, 0x0f);
- mipi_dsi_dcs_write_seq(dsi, 0xa3, 0x02);
- mipi_dsi_dcs_write_seq(dsi, 0xa4, 0x04);
- mipi_dsi_dcs_write_seq(dsi, 0xa5, 0x04);
- mipi_dsi_dcs_write_seq(dsi, 0xc6, 0xc0);
- mipi_dsi_dcs_write_seq(dsi, 0xc9, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0xd9, 0x80);
- mipi_dsi_dcs_write_seq(dsi, 0xe9, 0x02);
- mipi_dsi_dcs_write_seq(dsi, 0xff, 0x25);
- mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x18, 0x22);
- mipi_dsi_dcs_write_seq(dsi, 0x19, 0xe4);
- mipi_dsi_dcs_write_seq(dsi, 0x21, 0x40);
- mipi_dsi_dcs_write_seq(dsi, 0x66, 0xd8);
- mipi_dsi_dcs_write_seq(dsi, 0x68, 0x50);
- mipi_dsi_dcs_write_seq(dsi, 0x69, 0x10);
- mipi_dsi_dcs_write_seq(dsi, 0x6b, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x6d, 0x0d);
- mipi_dsi_dcs_write_seq(dsi, 0x6e, 0x48);
- mipi_dsi_dcs_write_seq(dsi, 0x72, 0x41);
- mipi_dsi_dcs_write_seq(dsi, 0x73, 0x4a);
- mipi_dsi_dcs_write_seq(dsi, 0x74, 0xd0);
- mipi_dsi_dcs_write_seq(dsi, 0x77, 0x62);
- mipi_dsi_dcs_write_seq(dsi, 0x79, 0x7e);
- mipi_dsi_dcs_write_seq(dsi, 0x7d, 0x03);
- mipi_dsi_dcs_write_seq(dsi, 0x7e, 0x15);
- mipi_dsi_dcs_write_seq(dsi, 0x7f, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x84, 0x4d);
- mipi_dsi_dcs_write_seq(dsi, 0xcf, 0x80);
- mipi_dsi_dcs_write_seq(dsi, 0xd6, 0x80);
- mipi_dsi_dcs_write_seq(dsi, 0xd7, 0x80);
- mipi_dsi_dcs_write_seq(dsi, 0xef, 0x20);
- mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x84);
- mipi_dsi_dcs_write_seq(dsi, 0xff, 0x26);
- mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x81, 0x0f);
- mipi_dsi_dcs_write_seq(dsi, 0x83, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x84, 0x03);
- mipi_dsi_dcs_write_seq(dsi, 0x85, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x86, 0x03);
- mipi_dsi_dcs_write_seq(dsi, 0x87, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x88, 0x05);
- mipi_dsi_dcs_write_seq(dsi, 0x8a, 0x1a);
- mipi_dsi_dcs_write_seq(dsi, 0x8b, 0x11);
- mipi_dsi_dcs_write_seq(dsi, 0x8c, 0x24);
- mipi_dsi_dcs_write_seq(dsi, 0x8e, 0x42);
- mipi_dsi_dcs_write_seq(dsi, 0x8f, 0x11);
- mipi_dsi_dcs_write_seq(dsi, 0x90, 0x11);
- mipi_dsi_dcs_write_seq(dsi, 0x91, 0x11);
- mipi_dsi_dcs_write_seq(dsi, 0x9a, 0x80);
- mipi_dsi_dcs_write_seq(dsi, 0x9b, 0x04);
- mipi_dsi_dcs_write_seq(dsi, 0x9c, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x9d, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x9e, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0xff, 0x27);
- mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x01, 0x68);
- mipi_dsi_dcs_write_seq(dsi, 0x20, 0x81);
- mipi_dsi_dcs_write_seq(dsi, 0x21, 0x6a);
- mipi_dsi_dcs_write_seq(dsi, 0x25, 0x81);
- mipi_dsi_dcs_write_seq(dsi, 0x26, 0x94);
- mipi_dsi_dcs_write_seq(dsi, 0x6e, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x6f, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x70, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x71, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x72, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x75, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x76, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x77, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x7d, 0x09);
- mipi_dsi_dcs_write_seq(dsi, 0x7e, 0x67);
- mipi_dsi_dcs_write_seq(dsi, 0x80, 0x23);
- mipi_dsi_dcs_write_seq(dsi, 0x82, 0x09);
- mipi_dsi_dcs_write_seq(dsi, 0x83, 0x67);
- mipi_dsi_dcs_write_seq(dsi, 0x88, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x89, 0x10);
- mipi_dsi_dcs_write_seq(dsi, 0xa5, 0x10);
- mipi_dsi_dcs_write_seq(dsi, 0xa6, 0x23);
- mipi_dsi_dcs_write_seq(dsi, 0xa7, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x40);
- mipi_dsi_dcs_write_seq(dsi, 0xe5, 0x02);
- mipi_dsi_dcs_write_seq(dsi, 0xe6, 0xd3);
- mipi_dsi_dcs_write_seq(dsi, 0xeb, 0x03);
- mipi_dsi_dcs_write_seq(dsi, 0xec, 0x28);
- mipi_dsi_dcs_write_seq(dsi, 0xff, 0x2a);
- mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x00, 0x91);
- mipi_dsi_dcs_write_seq(dsi, 0x03, 0x20);
- mipi_dsi_dcs_write_seq(dsi, 0x07, 0x50);
- mipi_dsi_dcs_write_seq(dsi, 0x0a, 0x70);
- mipi_dsi_dcs_write_seq(dsi, 0x0c, 0x04);
- mipi_dsi_dcs_write_seq(dsi, 0x0d, 0x40);
- mipi_dsi_dcs_write_seq(dsi, 0x0f, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x11, 0xe0);
- mipi_dsi_dcs_write_seq(dsi, 0x15, 0x0f);
- mipi_dsi_dcs_write_seq(dsi, 0x16, 0xa4);
- mipi_dsi_dcs_write_seq(dsi, 0x19, 0x0f);
- mipi_dsi_dcs_write_seq(dsi, 0x1a, 0x78);
- mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x23);
- mipi_dsi_dcs_write_seq(dsi, 0x1d, 0x36);
- mipi_dsi_dcs_write_seq(dsi, 0x1e, 0x3e);
- mipi_dsi_dcs_write_seq(dsi, 0x1f, 0x3e);
- mipi_dsi_dcs_write_seq(dsi, 0x20, 0x3e);
- mipi_dsi_dcs_write_seq(dsi, 0x28, 0xfd);
- mipi_dsi_dcs_write_seq(dsi, 0x29, 0x12);
- mipi_dsi_dcs_write_seq(dsi, 0x2a, 0xe1);
- mipi_dsi_dcs_write_seq(dsi, 0x2d, 0x0a);
- mipi_dsi_dcs_write_seq(dsi, 0x30, 0x49);
- mipi_dsi_dcs_write_seq(dsi, 0x33, 0x96);
- mipi_dsi_dcs_write_seq(dsi, 0x34, 0xff);
- mipi_dsi_dcs_write_seq(dsi, 0x35, 0x40);
- mipi_dsi_dcs_write_seq(dsi, 0x36, 0xde);
- mipi_dsi_dcs_write_seq(dsi, 0x37, 0xf9);
- mipi_dsi_dcs_write_seq(dsi, 0x38, 0x45);
- mipi_dsi_dcs_write_seq(dsi, 0x39, 0xd9);
- mipi_dsi_dcs_write_seq(dsi, 0x3a, 0x49);
- mipi_dsi_dcs_write_seq(dsi, 0x4a, 0xf0);
- mipi_dsi_dcs_write_seq(dsi, 0x7a, 0x09);
- mipi_dsi_dcs_write_seq(dsi, 0x7b, 0x40);
- mipi_dsi_dcs_write_seq(dsi, 0x7f, 0xf0);
- mipi_dsi_dcs_write_seq(dsi, 0x83, 0x0f);
- mipi_dsi_dcs_write_seq(dsi, 0x84, 0xa4);
- mipi_dsi_dcs_write_seq(dsi, 0x87, 0x0f);
- mipi_dsi_dcs_write_seq(dsi, 0x88, 0x78);
- mipi_dsi_dcs_write_seq(dsi, 0x89, 0x23);
- mipi_dsi_dcs_write_seq(dsi, 0x8b, 0x36);
- mipi_dsi_dcs_write_seq(dsi, 0x8c, 0x7d);
- mipi_dsi_dcs_write_seq(dsi, 0x8d, 0x7d);
- mipi_dsi_dcs_write_seq(dsi, 0x8e, 0x7d);
- mipi_dsi_dcs_write_seq(dsi, 0xff, 0x20);
- mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00, 0x00, 0x00, 0x17, 0x00, 0x49, 0x00,
- 0x6a, 0x00, 0x89, 0x00, 0x9f, 0x00, 0xb6, 0x00, 0xc8);
- mipi_dsi_dcs_write_seq(dsi, 0xb1, 0x00, 0xd9, 0x01, 0x10, 0x01, 0x3a, 0x01,
- 0x7a, 0x01, 0xa9, 0x01, 0xf2, 0x02, 0x2d, 0x02, 0x2e);
- mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x02, 0x64, 0x02, 0xa3, 0x02, 0xca, 0x03,
- 0x00, 0x03, 0x1e, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
- mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
- 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
- 0x71, 0x00, 0x90, 0x00, 0xa7, 0x00, 0xbf, 0x00, 0xd1);
- mipi_dsi_dcs_write_seq(dsi, 0xb5, 0x00, 0xe2, 0x01, 0x1a, 0x01, 0x43, 0x01,
- 0x83, 0x01, 0xb2, 0x01, 0xfa, 0x02, 0x34, 0x02, 0x36);
- mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x02, 0x6b, 0x02, 0xa8, 0x02, 0xd0, 0x03,
- 0x03, 0x03, 0x21, 0x03, 0x4d, 0x03, 0x5b, 0x03, 0x6b);
- mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x03, 0x7e, 0x03, 0x94, 0x03, 0xac, 0x03,
- 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
- 0x72, 0x00, 0x92, 0x00, 0xa8, 0x00, 0xbf, 0x00, 0xd1);
- mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x00, 0xe2, 0x01, 0x18, 0x01, 0x42, 0x01,
- 0x81, 0x01, 0xaf, 0x01, 0xf5, 0x02, 0x2f, 0x02, 0x31);
- mipi_dsi_dcs_write_seq(dsi, 0xba, 0x02, 0x68, 0x02, 0xa6, 0x02, 0xcd, 0x03,
- 0x01, 0x03, 0x1f, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
- mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
- 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0xff, 0x21);
- mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00, 0x00, 0x00, 0x17, 0x00, 0x49, 0x00,
- 0x6a, 0x00, 0x89, 0x00, 0x9f, 0x00, 0xb6, 0x00, 0xc8);
- mipi_dsi_dcs_write_seq(dsi, 0xb1, 0x00, 0xd9, 0x01, 0x10, 0x01, 0x3a, 0x01,
- 0x7a, 0x01, 0xa9, 0x01, 0xf2, 0x02, 0x2d, 0x02, 0x2e);
- mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x02, 0x64, 0x02, 0xa3, 0x02, 0xca, 0x03,
- 0x00, 0x03, 0x1e, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
- mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
- 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
- 0x71, 0x00, 0x90, 0x00, 0xa7, 0x00, 0xbf, 0x00, 0xd1);
- mipi_dsi_dcs_write_seq(dsi, 0xb5, 0x00, 0xe2, 0x01, 0x1a, 0x01, 0x43, 0x01,
- 0x83, 0x01, 0xb2, 0x01, 0xfa, 0x02, 0x34, 0x02, 0x36);
- mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x02, 0x6b, 0x02, 0xa8, 0x02, 0xd0, 0x03,
- 0x03, 0x03, 0x21, 0x03, 0x4d, 0x03, 0x5b, 0x03, 0x6b);
- mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x03, 0x7e, 0x03, 0x94, 0x03, 0xac, 0x03,
- 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
- 0x72, 0x00, 0x92, 0x00, 0xa8, 0x00, 0xbf, 0x00, 0xd1);
- mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x00, 0xe2, 0x01, 0x18, 0x01, 0x42, 0x01,
- 0x81, 0x01, 0xaf, 0x01, 0xf5, 0x02, 0x2f, 0x02, 0x31);
- mipi_dsi_dcs_write_seq(dsi, 0xba, 0x02, 0x68, 0x02, 0xa6, 0x02, 0xcd, 0x03,
- 0x01, 0x03, 0x1f, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
- mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
- 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0xff, 0x2c);
- mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x61, 0x1f);
- mipi_dsi_dcs_write_seq(dsi, 0x62, 0x1f);
- mipi_dsi_dcs_write_seq(dsi, 0x7e, 0x03);
- mipi_dsi_dcs_write_seq(dsi, 0x6a, 0x14);
- mipi_dsi_dcs_write_seq(dsi, 0x6b, 0x36);
- mipi_dsi_dcs_write_seq(dsi, 0x6c, 0x36);
- mipi_dsi_dcs_write_seq(dsi, 0x6d, 0x36);
- mipi_dsi_dcs_write_seq(dsi, 0x53, 0x04);
- mipi_dsi_dcs_write_seq(dsi, 0x54, 0x04);
- mipi_dsi_dcs_write_seq(dsi, 0x55, 0x04);
- mipi_dsi_dcs_write_seq(dsi, 0x56, 0x0f);
- mipi_dsi_dcs_write_seq(dsi, 0x58, 0x0f);
- mipi_dsi_dcs_write_seq(dsi, 0x59, 0x0f);
- mipi_dsi_dcs_write_seq(dsi, 0xff, 0xf0);
- mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x5a, 0x00);
-
- mipi_dsi_dcs_write_seq(dsi, 0xff, 0x10);
- mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x51, 0xff);
- mipi_dsi_dcs_write_seq(dsi, 0x53, 0x24);
- mipi_dsi_dcs_write_seq(dsi, 0x55, 0x01);
-
- return 0;
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x10);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb0, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xc0, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xc1, 0x89, 0x28, 0x00, 0x08, 0x00, 0xaa, 0x02,
+ 0x0e, 0x00, 0x2b, 0x00, 0x07, 0x0d, 0xb7, 0x0c, 0xb7);
+
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xc2, 0x1b, 0xa0);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x20);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x01, 0x66);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x06, 0x40);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x07, 0x38);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x2f, 0x83);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x69, 0x91);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x95, 0xd1);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x96, 0xd1);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xf2, 0x64);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xf3, 0x54);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xf4, 0x64);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xf5, 0x54);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xf6, 0x64);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xf7, 0x54);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xf8, 0x64);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xf9, 0x54);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x24);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x01, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x03, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x05, 0x1d);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x08, 0x2f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x09, 0x2e);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x0a, 0x2d);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x0b, 0x2c);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x11, 0x17);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x12, 0x13);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x13, 0x15);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x15, 0x14);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x16, 0x16);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x17, 0x18);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x1b, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x1d, 0x1d);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x20, 0x2f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x21, 0x2e);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x22, 0x2d);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x23, 0x2c);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x29, 0x17);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x2a, 0x13);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x2b, 0x15);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x2f, 0x14);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x30, 0x16);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x31, 0x18);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x32, 0x04);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x34, 0x10);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x35, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x36, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x4d, 0x14);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x4e, 0x36);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x4f, 0x36);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x53, 0x36);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x71, 0x30);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x79, 0x11);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x7a, 0x82);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x7b, 0x8f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x7d, 0x04);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x80, 0x04);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x81, 0x04);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x82, 0x13);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x84, 0x31);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x85, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x86, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x87, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x90, 0x13);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x92, 0x31);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x93, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x94, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x95, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x9c, 0xf4);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x9d, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xa0, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xa2, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xa3, 0x02);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xa4, 0x04);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xa5, 0x04);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xc6, 0xc0);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xc9, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xd9, 0x80);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xe9, 0x02);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x25);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x18, 0x22);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x19, 0xe4);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x21, 0x40);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x66, 0xd8);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x68, 0x50);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x69, 0x10);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x6b, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x6d, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x6e, 0x48);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x72, 0x41);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x73, 0x4a);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x74, 0xd0);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x77, 0x62);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x79, 0x7e);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x7d, 0x03);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x7e, 0x15);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x7f, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x84, 0x4d);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xcf, 0x80);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xd6, 0x80);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xd7, 0x80);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xef, 0x20);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xf0, 0x84);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x26);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x81, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x83, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x84, 0x03);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x85, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x86, 0x03);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x87, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x88, 0x05);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x8a, 0x1a);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x8b, 0x11);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x8c, 0x24);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x8e, 0x42);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x8f, 0x11);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x90, 0x11);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x91, 0x11);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x9a, 0x80);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x9b, 0x04);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x9c, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x9d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x9e, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x27);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x01, 0x68);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x20, 0x81);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x21, 0x6a);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x25, 0x81);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x26, 0x94);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x6e, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x6f, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x70, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x71, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x72, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x75, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x76, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x77, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x7d, 0x09);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x7e, 0x67);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x80, 0x23);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x82, 0x09);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x83, 0x67);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x88, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x89, 0x10);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xa5, 0x10);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xa6, 0x23);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xa7, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb6, 0x40);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xe5, 0x02);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xe6, 0xd3);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xeb, 0x03);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xec, 0x28);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x2a);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x00, 0x91);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x03, 0x20);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x07, 0x50);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x0a, 0x70);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x0c, 0x04);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x0d, 0x40);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x0f, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x11, 0xe0);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x15, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x16, 0xa4);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x19, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x1a, 0x78);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x1b, 0x23);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x1d, 0x36);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x1e, 0x3e);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x1f, 0x3e);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x20, 0x3e);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x28, 0xfd);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x29, 0x12);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x2a, 0xe1);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x2d, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x30, 0x49);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x33, 0x96);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x34, 0xff);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x35, 0x40);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x36, 0xde);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x37, 0xf9);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x38, 0x45);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x39, 0xd9);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x3a, 0x49);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x4a, 0xf0);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x7a, 0x09);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x7b, 0x40);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x7f, 0xf0);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x83, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x84, 0xa4);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x87, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x88, 0x78);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x89, 0x23);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x8b, 0x36);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x8c, 0x7d);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x8d, 0x7d);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x8e, 0x7d);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x20);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb0, 0x00, 0x00, 0x00, 0x17, 0x00, 0x49, 0x00,
+ 0x6a, 0x00, 0x89, 0x00, 0x9f, 0x00, 0xb6, 0x00, 0xc8);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb1, 0x00, 0xd9, 0x01, 0x10, 0x01, 0x3a, 0x01,
+ 0x7a, 0x01, 0xa9, 0x01, 0xf2, 0x02, 0x2d, 0x02, 0x2e);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb2, 0x02, 0x64, 0x02, 0xa3, 0x02, 0xca, 0x03,
+ 0x00, 0x03, 0x1e, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb3, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
+ 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
+ 0x71, 0x00, 0x90, 0x00, 0xa7, 0x00, 0xbf, 0x00, 0xd1);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb5, 0x00, 0xe2, 0x01, 0x1a, 0x01, 0x43, 0x01,
+ 0x83, 0x01, 0xb2, 0x01, 0xfa, 0x02, 0x34, 0x02, 0x36);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb6, 0x02, 0x6b, 0x02, 0xa8, 0x02, 0xd0, 0x03,
+ 0x03, 0x03, 0x21, 0x03, 0x4d, 0x03, 0x5b, 0x03, 0x6b);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb7, 0x03, 0x7e, 0x03, 0x94, 0x03, 0xac, 0x03,
+ 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
+ 0x72, 0x00, 0x92, 0x00, 0xa8, 0x00, 0xbf, 0x00, 0xd1);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb9, 0x00, 0xe2, 0x01, 0x18, 0x01, 0x42, 0x01,
+ 0x81, 0x01, 0xaf, 0x01, 0xf5, 0x02, 0x2f, 0x02, 0x31);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xba, 0x02, 0x68, 0x02, 0xa6, 0x02, 0xcd, 0x03,
+ 0x01, 0x03, 0x1f, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xbb, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
+ 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x21);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb0, 0x00, 0x00, 0x00, 0x17, 0x00, 0x49, 0x00,
+ 0x6a, 0x00, 0x89, 0x00, 0x9f, 0x00, 0xb6, 0x00, 0xc8);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb1, 0x00, 0xd9, 0x01, 0x10, 0x01, 0x3a, 0x01,
+ 0x7a, 0x01, 0xa9, 0x01, 0xf2, 0x02, 0x2d, 0x02, 0x2e);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb2, 0x02, 0x64, 0x02, 0xa3, 0x02, 0xca, 0x03,
+ 0x00, 0x03, 0x1e, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb3, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
+ 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
+ 0x71, 0x00, 0x90, 0x00, 0xa7, 0x00, 0xbf, 0x00, 0xd1);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb5, 0x00, 0xe2, 0x01, 0x1a, 0x01, 0x43, 0x01,
+ 0x83, 0x01, 0xb2, 0x01, 0xfa, 0x02, 0x34, 0x02, 0x36);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb6, 0x02, 0x6b, 0x02, 0xa8, 0x02, 0xd0, 0x03,
+ 0x03, 0x03, 0x21, 0x03, 0x4d, 0x03, 0x5b, 0x03, 0x6b);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb7, 0x03, 0x7e, 0x03, 0x94, 0x03, 0xac, 0x03,
+ 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
+ 0x72, 0x00, 0x92, 0x00, 0xa8, 0x00, 0xbf, 0x00, 0xd1);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb9, 0x00, 0xe2, 0x01, 0x18, 0x01, 0x42, 0x01,
+ 0x81, 0x01, 0xaf, 0x01, 0xf5, 0x02, 0x2f, 0x02, 0x31);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xba, 0x02, 0x68, 0x02, 0xa6, 0x02, 0xcd, 0x03,
+ 0x01, 0x03, 0x1f, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xbb, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
+ 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x2c);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x61, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x62, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x7e, 0x03);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x6a, 0x14);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x6b, 0x36);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x6c, 0x36);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x6d, 0x36);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x53, 0x04);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x54, 0x04);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x55, 0x04);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x56, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x58, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x59, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0xf0);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x5a, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x10);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x51, 0xff);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x53, 0x24);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x55, 0x01);
}
static int nt36672e_power_on(struct nt36672e_panel *ctx)
@@ -379,68 +377,46 @@ static int nt36672e_power_off(struct nt36672e_panel *ctx)
return ret;
}
-static int nt36672e_on(struct nt36672e_panel *ctx)
+static int nt36672e_on(struct nt36672e_panel *nt36672e)
{
- struct mipi_dsi_device *dsi = ctx->dsi;
- const struct panel_desc *desc = ctx->desc;
- int ret = 0;
+ struct mipi_dsi_multi_context ctx = { .dsi = nt36672e->dsi };
+ const struct panel_desc *desc = nt36672e->desc;
- dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+ nt36672e->dsi->mode_flags |= MIPI_DSI_MODE_LPM;
- if (desc->init_sequence) {
- ret = desc->init_sequence(dsi);
- if (ret < 0) {
- dev_err(&dsi->dev, "panel init sequence failed: %d\n", ret);
- return ret;
- }
- }
+ if (desc->init_sequence)
+ desc->init_sequence(&ctx);
- ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
- if (ret < 0) {
- dev_err(&dsi->dev, "Failed to exit sleep mode: %d\n", ret);
- return ret;
- }
- msleep(120);
+ mipi_dsi_dcs_exit_sleep_mode_multi(&ctx);
+ mipi_dsi_msleep(&ctx, 120);
- ret = mipi_dsi_dcs_set_display_on(dsi);
- if (ret < 0) {
- dev_err(&dsi->dev, "Failed to set display on: %d\n", ret);
- return ret;
- }
- msleep(100);
+ mipi_dsi_dcs_set_display_on_multi(&ctx);
- return 0;
+ mipi_dsi_msleep(&ctx, 100);
+
+ return ctx.accum_err;
}
-static int nt36672e_off(struct nt36672e_panel *ctx)
+static int nt36672e_off(struct nt36672e_panel *panel)
{
- struct mipi_dsi_device *dsi = ctx->dsi;
- int ret = 0;
+ struct mipi_dsi_multi_context ctx = { .dsi = panel->dsi };
- dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+ panel->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
- ret = mipi_dsi_dcs_set_display_off(dsi);
- if (ret < 0) {
- dev_err(&dsi->dev, "Failed to set display off: %d\n", ret);
- return ret;
- }
- msleep(20);
+ mipi_dsi_dcs_set_display_off_multi(&ctx);
+ mipi_dsi_msleep(&ctx, 20);
- ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
- if (ret < 0) {
- dev_err(&dsi->dev, "Failed to enter sleep mode: %d\n", ret);
- return ret;
- }
- msleep(60);
+ mipi_dsi_dcs_enter_sleep_mode_multi(&ctx);
+ mipi_dsi_msleep(&ctx, 60);
- return 0;
+ return ctx.accum_err;
}
static int nt36672e_panel_prepare(struct drm_panel *panel)
{
struct nt36672e_panel *ctx = to_nt36672e_panel(panel);
struct mipi_dsi_device *dsi = ctx->dsi;
- int ret = 0;
+ int ret;
ret = nt36672e_power_on(ctx);
if (ret < 0)
@@ -448,7 +424,6 @@ static int nt36672e_panel_prepare(struct drm_panel *panel)
ret = nt36672e_on(ctx);
if (ret < 0) {
- dev_err(&dsi->dev, "Failed to initialize panel: %d\n", ret);
if (nt36672e_power_off(ctx))
dev_err(&dsi->dev, "power off failed\n");
return ret;
@@ -461,11 +436,9 @@ static int nt36672e_panel_unprepare(struct drm_panel *panel)
{
struct nt36672e_panel *ctx = to_nt36672e_panel(panel);
struct mipi_dsi_device *dsi = ctx->dsi;
- int ret = 0;
+ int ret;
- ret = nt36672e_off(ctx);
- if (ret < 0)
- dev_err(&dsi->dev, "Failed to un-initialize panel: %d\n", ret);
+ nt36672e_off(ctx);
ret = nt36672e_power_off(ctx);
if (ret < 0)
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index dcb6d0b6ced0..1b0a6b4e034c 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -2870,6 +2870,35 @@ static const struct panel_desc lg_lb070wv8 = {
.connector_type = DRM_MODE_CONNECTOR_LVDS,
};
+static const struct drm_display_mode lincolntech_lcd185_101ct_mode = {
+ .clock = 155127,
+ .hdisplay = 1920,
+ .hsync_start = 1920 + 128,
+ .hsync_end = 1920 + 128 + 20,
+ .htotal = 1920 + 128 + 20 + 12,
+ .vdisplay = 1200,
+ .vsync_start = 1200 + 19,
+ .vsync_end = 1200 + 19 + 4,
+ .vtotal = 1200 + 19 + 4 + 20,
+};
+
+static const struct panel_desc lincolntech_lcd185_101ct = {
+ .modes = &lincolntech_lcd185_101ct_mode,
+ .bpc = 8,
+ .num_modes = 1,
+ .size = {
+ .width = 217,
+ .height = 136,
+ },
+ .delay = {
+ .prepare = 50,
+ .disable = 50,
+ },
+ .bus_flags = DRM_BUS_FLAG_DE_HIGH,
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+ .connector_type = DRM_MODE_CONNECTOR_LVDS,
+};
+
static const struct display_timing logictechno_lt161010_2nh_timing = {
.pixelclock = { 26400000, 33300000, 46800000 },
.hactive = { 800, 800, 800 },
@@ -3026,6 +3055,64 @@ static const struct panel_desc logicpd_type_28 = {
.connector_type = DRM_MODE_CONNECTOR_DPI,
};
+static const struct drm_display_mode microtips_mf_101hiebcaf0_c_mode = {
+ .clock = 150275,
+ .hdisplay = 1920,
+ .hsync_start = 1920 + 32,
+ .hsync_end = 1920 + 32 + 52,
+ .htotal = 1920 + 32 + 52 + 24,
+ .vdisplay = 1200,
+ .vsync_start = 1200 + 24,
+ .vsync_end = 1200 + 24 + 8,
+ .vtotal = 1200 + 24 + 8 + 3,
+};
+
+static const struct panel_desc microtips_mf_101hiebcaf0_c = {
+ .modes = &microtips_mf_101hiebcaf0_c_mode,
+ .bpc = 8,
+ .num_modes = 1,
+ .size = {
+ .width = 217,
+ .height = 136,
+ },
+ .delay = {
+ .prepare = 50,
+ .disable = 50,
+ },
+ .bus_flags = DRM_BUS_FLAG_DE_HIGH,
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+ .connector_type = DRM_MODE_CONNECTOR_LVDS,
+};
+
+static const struct drm_display_mode microtips_mf_103hieb0ga0_mode = {
+ .clock = 93301,
+ .hdisplay = 1920,
+ .hsync_start = 1920 + 72,
+ .hsync_end = 1920 + 72 + 72,
+ .htotal = 1920 + 72 + 72 + 72,
+ .vdisplay = 720,
+ .vsync_start = 720 + 3,
+ .vsync_end = 720 + 3 + 3,
+ .vtotal = 720 + 3 + 3 + 2,
+};
+
+static const struct panel_desc microtips_mf_103hieb0ga0 = {
+ .modes = &microtips_mf_103hieb0ga0_mode,
+ .bpc = 8,
+ .num_modes = 1,
+ .size = {
+ .width = 244,
+ .height = 92,
+ },
+ .delay = {
+ .prepare = 50,
+ .disable = 50,
+ },
+ .bus_flags = DRM_BUS_FLAG_DE_HIGH,
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+ .connector_type = DRM_MODE_CONNECTOR_LVDS,
+};
+
static const struct drm_display_mode mitsubishi_aa070mc01_mode = {
.clock = 30400,
.hdisplay = 800,
@@ -4645,6 +4732,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "lg,lb070wv8",
.data = &lg_lb070wv8,
}, {
+ .compatible = "lincolntech,lcd185-101ct",
+ .data = &lincolntech_lcd185_101ct,
+ }, {
.compatible = "logicpd,type28",
.data = &logicpd_type_28,
}, {
@@ -4663,6 +4753,12 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "logictechno,lttd800480070-l6wh-rt",
.data = &logictechno_lttd800480070_l6wh_rt,
}, {
+ .compatible = "microtips,mf-101hiebcaf0",
+ .data = &microtips_mf_101hiebcaf0_c,
+ }, {
+ .compatible = "microtips,mf-103hieb0ga0",
+ .data = &microtips_mf_103hieb0ga0,
+ }, {
.compatible = "mitsubishi,aa070mc01-ca1",
.data = &mitsubishi_aa070mc01,
}, {
diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c
index beee5563031a..5eb3f5719fdf 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.c
+++ b/drivers/gpu/drm/qxl/qxl_drv.c
@@ -37,7 +37,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_ttm.h>
#include <drm/drm_file.h>
#include <drm/drm_gem_ttm_helper.h>
#include <drm/drm_module.h>
@@ -118,7 +118,7 @@ qxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ret)
goto modeset_cleanup;
- drm_fbdev_generic_setup(&qdev->ddev, 32);
+ drm_fbdev_ttm_setup(&qdev->ddev, 32);
return 0;
modeset_cleanup:
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c
index 2bff0d9e20f5..0aa395fac36f 100644
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -701,7 +701,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
if (radeon_connector->use_digital &&
(radeon_connector->audio == RADEON_AUDIO_ENABLE))
return ATOM_ENCODER_MODE_HDMI;
- else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
+ else if (connector->display_info.is_hdmi &&
(radeon_connector->audio == RADEON_AUDIO_AUTO))
return ATOM_ENCODER_MODE_HDMI;
else if (radeon_connector->use_digital)
@@ -720,7 +720,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
if (radeon_audio != 0) {
if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
return ATOM_ENCODER_MODE_HDMI;
- else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
+ else if (connector->display_info.is_hdmi &&
(radeon_connector->audio == RADEON_AUDIO_AUTO))
return ATOM_ENCODER_MODE_HDMI;
else
@@ -737,14 +737,14 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
(dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
if (radeon_audio != 0 &&
- drm_detect_monitor_audio(radeon_connector_edid(connector)) &&
+ connector->display_info.has_audio &&
ASIC_IS_DCE4(rdev) && !ASIC_IS_DCE5(rdev))
return ATOM_ENCODER_MODE_DP_AUDIO;
return ATOM_ENCODER_MODE_DP;
} else if (radeon_audio != 0) {
if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
return ATOM_ENCODER_MODE_HDMI;
- else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
+ else if (connector->display_info.is_hdmi &&
(radeon_connector->audio == RADEON_AUDIO_AUTO))
return ATOM_ENCODER_MODE_HDMI;
else
@@ -755,7 +755,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
break;
case DRM_MODE_CONNECTOR_eDP:
if (radeon_audio != 0 &&
- drm_detect_monitor_audio(radeon_connector_edid(connector)) &&
+ connector->display_info.has_audio &&
ASIC_IS_DCE4(rdev) && !ASIC_IS_DCE5(rdev))
return ATOM_ENCODER_MODE_DP_AUDIO;
return ATOM_ENCODER_MODE_DP;
diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c
index 681119c91d94..09dda114e218 100644
--- a/drivers/gpu/drm/radeon/evergreen_hdmi.c
+++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c
@@ -412,7 +412,7 @@ void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable)
if (enable) {
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
- if (connector && drm_detect_monitor_audio(radeon_connector_edid(connector))) {
+ if (connector && connector->display_info.has_audio) {
WREG32(HDMI_INFOFRAME_CONTROL0 + dig->afmt->offset,
HDMI_AVI_INFO_SEND | /* enable AVI info frames */
HDMI_AVI_INFO_CONT | /* required for audio info values to be updated */
@@ -450,8 +450,7 @@ void evergreen_dp_enable(struct drm_encoder *encoder, bool enable)
if (!dig || !dig->afmt)
return;
- if (enable && connector &&
- drm_detect_monitor_audio(radeon_connector_edid(connector))) {
+ if (enable && connector && connector->display_info.has_audio) {
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
struct radeon_connector_atom_dig *dig_connector;
diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c
index 74753bb26d33..0bcd767b9f47 100644
--- a/drivers/gpu/drm/radeon/radeon_audio.c
+++ b/drivers/gpu/drm/radeon/radeon_audio.c
@@ -303,6 +303,7 @@ void radeon_audio_endpoint_wreg(struct radeon_device *rdev, u32 offset,
static void radeon_audio_write_sad_regs(struct drm_encoder *encoder)
{
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+ struct radeon_connector *radeon_connector = to_radeon_connector(connector);
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct cea_sad *sads;
int sad_count;
@@ -310,7 +311,7 @@ static void radeon_audio_write_sad_regs(struct drm_encoder *encoder)
if (!connector)
return;
- sad_count = drm_edid_to_sad(radeon_connector_edid(connector), &sads);
+ sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
if (sad_count < 0)
DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
if (sad_count <= 0)
@@ -326,6 +327,7 @@ static void radeon_audio_write_sad_regs(struct drm_encoder *encoder)
static void radeon_audio_write_speaker_allocation(struct drm_encoder *encoder)
{
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+ struct radeon_connector *radeon_connector = to_radeon_connector(connector);
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
u8 *sadb = NULL;
int sad_count;
@@ -333,8 +335,7 @@ static void radeon_audio_write_speaker_allocation(struct drm_encoder *encoder)
if (!connector)
return;
- sad_count = drm_edid_to_speaker_allocation(radeon_connector_edid(connector),
- &sadb);
+ sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
if (sad_count < 0) {
DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n",
sad_count);
@@ -409,7 +410,7 @@ void radeon_audio_detect(struct drm_connector *connector,
radeon_encoder->audio = rdev->audio.hdmi_funcs;
}
- if (drm_detect_monitor_audio(radeon_connector_edid(connector))) {
+ if (connector->display_info.has_audio) {
if (!dig->pin)
dig->pin = radeon_audio_get_pin(encoder);
radeon_audio_enable(rdev, dig->pin, 0xf);
@@ -646,7 +647,7 @@ static void radeon_audio_hdmi_mode_set(struct drm_encoder *encoder,
if (!connector)
return;
- if (drm_detect_monitor_audio(radeon_connector_edid(connector))) {
+ if (connector->display_info.has_audio) {
radeon_audio_set_mute(encoder, true);
radeon_audio_write_speaker_allocation(encoder);
@@ -686,7 +687,7 @@ static void radeon_audio_dp_mode_set(struct drm_encoder *encoder,
if (!connector)
return;
- if (drm_detect_monitor_audio(radeon_connector_edid(connector))) {
+ if (connector->display_info.has_audio) {
radeon_audio_write_speaker_allocation(encoder);
radeon_audio_write_sad_regs(encoder);
radeon_audio_write_latency_fields(encoder, mode);
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index b84b58926106..80879e946342 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -109,7 +109,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector)
case DRM_MODE_CONNECTOR_DVII:
case DRM_MODE_CONNECTOR_HDMIB:
if (radeon_connector->use_digital) {
- if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
+ if (connector->display_info.is_hdmi) {
if (connector->display_info.bpc)
bpc = connector->display_info.bpc;
}
@@ -117,7 +117,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector)
break;
case DRM_MODE_CONNECTOR_DVID:
case DRM_MODE_CONNECTOR_HDMIA:
- if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
+ if (connector->display_info.is_hdmi) {
if (connector->display_info.bpc)
bpc = connector->display_info.bpc;
}
@@ -126,7 +126,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector)
dig_connector = radeon_connector->con_priv;
if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
(dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) ||
- drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
+ connector->display_info.is_hdmi) {
if (connector->display_info.bpc)
bpc = connector->display_info.bpc;
}
@@ -150,7 +150,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector)
break;
}
- if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
+ if (connector->display_info.is_hdmi) {
/* hdmi deep color only implemented on DCE4+ */
if ((bpc > 8) && !ASIC_IS_DCE4(rdev)) {
DRM_DEBUG("%s: HDMI deep color %d bpc unsupported. Using 8 bpc.\n",
@@ -255,21 +255,6 @@ static struct drm_encoder *radeon_find_encoder(struct drm_connector *connector,
return NULL;
}
-struct edid *radeon_connector_edid(struct drm_connector *connector)
-{
- struct radeon_connector *radeon_connector = to_radeon_connector(connector);
- struct drm_property_blob *edid_blob = connector->edid_blob_ptr;
-
- if (radeon_connector->edid) {
- return radeon_connector->edid;
- } else if (edid_blob) {
- struct edid *edid = kmemdup(edid_blob->data, edid_blob->length, GFP_KERNEL);
- if (edid)
- radeon_connector->edid = edid;
- }
- return radeon_connector->edid;
-}
-
static void radeon_connector_get_edid(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
@@ -1478,7 +1463,7 @@ static enum drm_mode_status radeon_dvi_mode_valid(struct drm_connector *connecto
(radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) ||
(radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_B))
return MODE_OK;
- else if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
+ else if (ASIC_IS_DCE6(rdev) && connector->display_info.is_hdmi) {
/* HDMI 1.3+ supports max clock of 340 Mhz */
if (mode->clock > 340000)
return MODE_CLOCK_HIGH;
@@ -1774,7 +1759,7 @@ static enum drm_mode_status radeon_dp_mode_valid(struct drm_connector *connector
(radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
return radeon_dp_mode_valid_helper(connector, mode);
} else {
- if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
+ if (ASIC_IS_DCE6(rdev) && connector->display_info.is_hdmi) {
/* HDMI 1.3+ supports max clock of 340 Mhz */
if (mode->clock > 340000)
return MODE_CLOCK_HIGH;
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 5f1d24d3120c..843383f7237f 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -1722,7 +1722,7 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
(!(mode->flags & DRM_MODE_FLAG_INTERLACE)) &&
((radeon_encoder->underscan_type == UNDERSCAN_ON) ||
((radeon_encoder->underscan_type == UNDERSCAN_AUTO) &&
- drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
+ connector->display_info.is_hdmi &&
is_hdtv_mode(mode)))) {
if (radeon_encoder->underscan_hborder != 0)
radeon_crtc->h_border = radeon_encoder->underscan_hborder;
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c
index 3de3dce9e89d..0f723292409e 100644
--- a/drivers/gpu/drm/radeon/radeon_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_encoders.c
@@ -386,7 +386,7 @@ bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder,
case DRM_MODE_CONNECTOR_HDMIB:
if (radeon_connector->use_digital) {
/* HDMI 1.3 supports up to 340 Mhz over single link */
- if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
+ if (ASIC_IS_DCE6(rdev) && connector->display_info.is_hdmi) {
if (pixel_clock > 340000)
return true;
else
@@ -408,7 +408,7 @@ bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder,
return false;
else {
/* HDMI 1.3 supports up to 340 Mhz over single link */
- if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
+ if (ASIC_IS_DCE6(rdev) && connector->display_info.is_hdmi) {
if (pixel_clock > 340000)
return true;
else
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 546381a5c918..e0a5af180801 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -701,8 +701,6 @@ extern u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connecto
extern bool radeon_connector_is_dp12_capable(struct drm_connector *connector);
extern int radeon_get_monitor_bpc(struct drm_connector *connector);
-extern struct edid *radeon_connector_edid(struct drm_connector *connector);
-
extern void radeon_connector_hotplug(struct drm_connector *connector);
extern int radeon_dp_mode_valid_helper(struct drm_connector *connector,
struct drm_display_mode *mode);
diff --git a/drivers/gpu/drm/renesas/rcar-du/Kconfig b/drivers/gpu/drm/renesas/rcar-du/Kconfig
index 53c356aed5d5..c17e7c50492c 100644
--- a/drivers/gpu/drm/renesas/rcar-du/Kconfig
+++ b/drivers/gpu/drm/renesas/rcar-du/Kconfig
@@ -2,7 +2,7 @@
config DRM_RCAR_DU
tristate "DRM Support for R-Car Display Unit"
depends on DRM && OF
- depends on ARM || ARM64
+ depends on ARM || ARM64 || COMPILE_TEST
depends on ARCH_RENESAS || COMPILE_TEST
select DRM_KMS_HELPER
select DRM_GEM_DMA_HELPER
diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c
index dee530e4c8b2..fb719d9aff10 100644
--- a/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c
@@ -20,7 +20,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_managed.h>
#include <drm/drm_probe_helper.h>
@@ -716,7 +716,7 @@ static int rcar_du_probe(struct platform_device *pdev)
drm_info(&rcdu->ddev, "Device %s probed\n", dev_name(&pdev->dev));
- drm_fbdev_generic_setup(&rcdu->ddev, 32);
+ drm_fbdev_dma_setup(&rcdu->ddev, 32);
return 0;
diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.c b/drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.c
index 470d34da1d6c..e5eca8691a33 100644
--- a/drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.c
+++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.c
@@ -14,7 +14,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_probe_helper.h>
@@ -149,7 +149,7 @@ static int rzg2l_du_probe(struct platform_device *pdev)
drm_info(&rcdu->ddev, "Device %s probed\n", dev_name(&pdev->dev));
- drm_fbdev_generic_setup(&rcdu->ddev, 32);
+ drm_fbdev_dma_setup(&rcdu->ddev, 32);
return 0;
diff --git a/drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c
index e83c3e52251d..890cc2f6408d 100644
--- a/drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c
+++ b/drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c
@@ -19,7 +19,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_modeset_helper.h>
#include <drm/drm_module.h>
@@ -250,7 +250,7 @@ static int shmob_drm_probe(struct platform_device *pdev)
if (ret < 0)
goto err_modeset_cleanup;
- drm_fbdev_generic_setup(ddev, 16);
+ drm_fbdev_dma_setup(ddev, 16);
return 0;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index ab55d7132550..44d769d9234d 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -18,7 +18,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_of.h>
#include <drm/drm_probe_helper.h>
@@ -191,7 +191,7 @@ static int rockchip_drm_bind(struct device *dev)
if (ret)
goto err_kms_helper_poll_fini;
- drm_fbdev_generic_setup(drm_dev, 0);
+ drm_fbdev_dma_setup(drm_dev, 0);
return 0;
err_kms_helper_poll_fini:
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
index 62ebbdb16253..9873172e3fd3 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
@@ -2344,7 +2344,7 @@ static void vop2_setup_layer_mixer(struct vop2_video_port *vp)
port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT2_MUX,
(vp2->nlayers + vp1->nlayers + vp0->nlayers - 1));
else
- port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX, 8);
+ port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT2_MUX, 8);
layer_sel = vop2_readl(vop2, RK3568_OVL_LAYER_SEL);
diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c
index ebd943b9e357..6f51bcf774e2 100644
--- a/drivers/gpu/drm/solomon/ssd130x.c
+++ b/drivers/gpu/drm/solomon/ssd130x.c
@@ -23,7 +23,7 @@
#include <drm/drm_crtc_helper.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_edid.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_shmem.h>
#include <drm/drm_format_helper.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
@@ -2029,7 +2029,7 @@ struct ssd130x_device *ssd130x_probe(struct device *dev, struct regmap *regmap)
if (ret)
return ERR_PTR(dev_err_probe(dev, ret, "DRM device register failed\n"));
- drm_fbdev_generic_setup(drm, 32);
+ drm_fbdev_shmem_setup(drm, 32);
return ssd130x;
}
diff --git a/drivers/gpu/drm/stm/Kconfig b/drivers/gpu/drm/stm/Kconfig
index fa49cde43bb2..4c906d602825 100644
--- a/drivers/gpu/drm/stm/Kconfig
+++ b/drivers/gpu/drm/stm/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config DRM_STM
tristate "DRM Support for STMicroelectronics SoC Series"
- depends on DRM && ARCH_STM32
+ depends on DRM && (ARCH_STM32 || COMPILE_TEST)
select DRM_KMS_HELPER
select DRM_GEM_DMA_HELPER
select DRM_PANEL_BRIDGE
diff --git a/drivers/gpu/drm/tiny/bochs.c b/drivers/gpu/drm/tiny/bochs.c
index c23c9f0cf49c..5ea89f21a5bd 100644
--- a/drivers/gpu/drm/tiny/bochs.c
+++ b/drivers/gpu/drm/tiny/bochs.c
@@ -7,7 +7,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_edid.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_ttm.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_framebuffer_helper.h>
@@ -85,7 +85,7 @@ struct bochs_device {
u16 yres_virtual;
u32 stride;
u32 bpp;
- struct edid *edid;
+ const struct drm_edid *drm_edid;
/* drm */
struct drm_device *dev;
@@ -199,10 +199,10 @@ static int bochs_hw_load_edid(struct bochs_device *bochs)
if (drm_edid_header_is_valid(header) != 8)
return -1;
- kfree(bochs->edid);
- bochs->edid = drm_do_get_edid(&bochs->connector,
- bochs_get_edid_block, bochs);
- if (bochs->edid == NULL)
+ drm_edid_free(bochs->drm_edid);
+ bochs->drm_edid = drm_edid_read_custom(&bochs->connector,
+ bochs_get_edid_block, bochs);
+ if (!bochs->drm_edid)
return -1;
return 0;
@@ -303,7 +303,7 @@ static void bochs_hw_fini(struct drm_device *dev)
if (bochs->fb_map)
iounmap(bochs->fb_map);
pci_release_regions(to_pci_dev(dev->dev));
- kfree(bochs->edid);
+ drm_edid_free(bochs->drm_edid);
}
static void bochs_hw_blank(struct bochs_device *bochs, bool blank)
@@ -471,12 +471,9 @@ static const struct drm_simple_display_pipe_funcs bochs_pipe_funcs = {
static int bochs_connector_get_modes(struct drm_connector *connector)
{
- struct bochs_device *bochs =
- container_of(connector, struct bochs_device, connector);
- int count = 0;
+ int count;
- if (bochs->edid)
- count = drm_add_edid_modes(connector, bochs->edid);
+ count = drm_edid_connector_add_modes(connector);
if (!count) {
count = drm_add_modes_noedid(connector, 8192, 8192);
@@ -507,10 +504,10 @@ static void bochs_connector_init(struct drm_device *dev)
drm_connector_helper_add(connector, &bochs_connector_connector_helper_funcs);
bochs_hw_load_edid(bochs);
- if (bochs->edid) {
+ if (bochs->drm_edid) {
DRM_INFO("Found EDID data blob.\n");
drm_connector_attach_edid_property(connector);
- drm_connector_update_edid_property(connector, bochs->edid);
+ drm_edid_connector_update(&bochs->connector, bochs->drm_edid);
}
}
@@ -670,7 +667,7 @@ static int bochs_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent
if (ret)
goto err_hw_fini;
- drm_fbdev_generic_setup(dev, 32);
+ drm_fbdev_ttm_setup(dev, 32);
return ret;
err_hw_fini:
diff --git a/drivers/gpu/drm/tiny/cirrus.c b/drivers/gpu/drm/tiny/cirrus.c
index 4e3a152f897a..3ac4f310aa2a 100644
--- a/drivers/gpu/drm/tiny/cirrus.c
+++ b/drivers/gpu/drm/tiny/cirrus.c
@@ -31,7 +31,7 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_edid.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_shmem.h>
#include <drm/drm_file.h>
#include <drm/drm_format_helper.h>
#include <drm/drm_fourcc.h>
@@ -716,7 +716,7 @@ static int cirrus_pci_probe(struct pci_dev *pdev,
if (ret)
return ret;
- drm_fbdev_generic_setup(dev, 16);
+ drm_fbdev_shmem_setup(dev, 16);
return 0;
}
diff --git a/drivers/gpu/drm/tiny/gm12u320.c b/drivers/gpu/drm/tiny/gm12u320.c
index 0187539ff5ea..8b4efd39d7c4 100644
--- a/drivers/gpu/drm/tiny/gm12u320.c
+++ b/drivers/gpu/drm/tiny/gm12u320.c
@@ -13,7 +13,7 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_edid.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_shmem.h>
#include <drm/drm_file.h>
#include <drm/drm_format_helper.h>
#include <drm/drm_fourcc.h>
@@ -699,7 +699,7 @@ static int gm12u320_usb_probe(struct usb_interface *interface,
if (ret)
goto err_put_device;
- drm_fbdev_generic_setup(dev, 0);
+ drm_fbdev_shmem_setup(dev, 0);
return 0;
diff --git a/drivers/gpu/drm/tiny/hx8357d.c b/drivers/gpu/drm/tiny/hx8357d.c
index cdc4486e059b..2e631282edeb 100644
--- a/drivers/gpu/drm/tiny/hx8357d.c
+++ b/drivers/gpu/drm/tiny/hx8357d.c
@@ -18,7 +18,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_managed.h>
@@ -256,7 +256,7 @@ static int hx8357d_probe(struct spi_device *spi)
spi_set_drvdata(spi, drm);
- drm_fbdev_generic_setup(drm, 0);
+ drm_fbdev_dma_setup(drm, 0);
return 0;
}
diff --git a/drivers/gpu/drm/tiny/ili9163.c b/drivers/gpu/drm/tiny/ili9163.c
index bc4384d410fc..86f9d8834901 100644
--- a/drivers/gpu/drm/tiny/ili9163.c
+++ b/drivers/gpu/drm/tiny/ili9163.c
@@ -9,7 +9,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_mipi_dbi.h>
@@ -185,7 +185,7 @@ static int ili9163_probe(struct spi_device *spi)
if (ret)
return ret;
- drm_fbdev_generic_setup(drm, 0);
+ drm_fbdev_dma_setup(drm, 0);
return 0;
}
diff --git a/drivers/gpu/drm/tiny/ili9225.c b/drivers/gpu/drm/tiny/ili9225.c
index dd8b0a181be9..b6b7a49147bf 100644
--- a/drivers/gpu/drm/tiny/ili9225.c
+++ b/drivers/gpu/drm/tiny/ili9225.c
@@ -20,7 +20,7 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_fb_dma_helper.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
@@ -426,7 +426,7 @@ static int ili9225_probe(struct spi_device *spi)
spi_set_drvdata(spi, drm);
- drm_fbdev_generic_setup(drm, 0);
+ drm_fbdev_dma_setup(drm, 0);
return 0;
}
@@ -447,7 +447,6 @@ static void ili9225_shutdown(struct spi_device *spi)
static struct spi_driver ili9225_spi_driver = {
.driver = {
.name = "ili9225",
- .owner = THIS_MODULE,
.of_match_table = ili9225_of_match,
},
.id_table = ili9225_id,
diff --git a/drivers/gpu/drm/tiny/ili9341.c b/drivers/gpu/drm/tiny/ili9341.c
index 47b61c3bf145..8bcada30af71 100644
--- a/drivers/gpu/drm/tiny/ili9341.c
+++ b/drivers/gpu/drm/tiny/ili9341.c
@@ -17,7 +17,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_managed.h>
@@ -218,7 +218,7 @@ static int ili9341_probe(struct spi_device *spi)
spi_set_drvdata(spi, drm);
- drm_fbdev_generic_setup(drm, 0);
+ drm_fbdev_dma_setup(drm, 0);
return 0;
}
diff --git a/drivers/gpu/drm/tiny/ili9486.c b/drivers/gpu/drm/tiny/ili9486.c
index 938bceed5999..70d366260041 100644
--- a/drivers/gpu/drm/tiny/ili9486.c
+++ b/drivers/gpu/drm/tiny/ili9486.c
@@ -16,7 +16,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_managed.h>
@@ -247,7 +247,7 @@ static int ili9486_probe(struct spi_device *spi)
spi_set_drvdata(spi, drm);
- drm_fbdev_generic_setup(drm, 0);
+ drm_fbdev_dma_setup(drm, 0);
return 0;
}
diff --git a/drivers/gpu/drm/tiny/mi0283qt.c b/drivers/gpu/drm/tiny/mi0283qt.c
index 01ff43c8ac3f..cdc5423990ca 100644
--- a/drivers/gpu/drm/tiny/mi0283qt.c
+++ b/drivers/gpu/drm/tiny/mi0283qt.c
@@ -15,7 +15,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_managed.h>
@@ -226,7 +226,7 @@ static int mi0283qt_probe(struct spi_device *spi)
spi_set_drvdata(spi, drm);
- drm_fbdev_generic_setup(drm, 0);
+ drm_fbdev_dma_setup(drm, 0);
return 0;
}
@@ -263,7 +263,6 @@ static const struct dev_pm_ops mi0283qt_pm_ops = {
static struct spi_driver mi0283qt_spi_driver = {
.driver = {
.name = "mi0283qt",
- .owner = THIS_MODULE,
.of_match_table = mi0283qt_of_match,
.pm = &mi0283qt_pm_ops,
},
diff --git a/drivers/gpu/drm/tiny/ofdrm.c b/drivers/gpu/drm/tiny/ofdrm.c
index ab89b7fc7bf6..35996f7eedac 100644
--- a/drivers/gpu/drm/tiny/ofdrm.c
+++ b/drivers/gpu/drm/tiny/ofdrm.c
@@ -11,7 +11,7 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_device.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_shmem.h>
#include <drm/drm_format_helper.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
@@ -1377,7 +1377,7 @@ static int ofdrm_probe(struct platform_device *pdev)
if (color_mode == 16)
color_mode = odev->format->depth; // can be 15 or 16
- drm_fbdev_generic_setup(dev, color_mode);
+ drm_fbdev_shmem_setup(dev, color_mode);
return 0;
}
diff --git a/drivers/gpu/drm/tiny/panel-mipi-dbi.c b/drivers/gpu/drm/tiny/panel-mipi-dbi.c
index f80a141fcf36..b353a731f253 100644
--- a/drivers/gpu/drm/tiny/panel-mipi-dbi.c
+++ b/drivers/gpu/drm/tiny/panel-mipi-dbi.c
@@ -16,7 +16,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_managed.h>
@@ -335,7 +335,7 @@ static int panel_mipi_dbi_spi_probe(struct spi_device *spi)
spi_set_drvdata(spi, drm);
- drm_fbdev_generic_setup(drm, 0);
+ drm_fbdev_dma_setup(drm, 0);
return 0;
}
@@ -384,7 +384,6 @@ MODULE_DEVICE_TABLE(spi, panel_mipi_dbi_spi_id);
static struct spi_driver panel_mipi_dbi_spi_driver = {
.driver = {
.name = "panel-mipi-dbi-spi",
- .owner = THIS_MODULE,
.of_match_table = panel_mipi_dbi_spi_of_match,
.pm = &panel_mipi_dbi_pm_ops,
},
diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c
index 8fd6758f5725..1f78aa3d26bb 100644
--- a/drivers/gpu/drm/tiny/repaper.c
+++ b/drivers/gpu/drm/tiny/repaper.c
@@ -26,7 +26,7 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_fb_dma_helper.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_format_helper.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
@@ -1118,7 +1118,7 @@ static int repaper_probe(struct spi_device *spi)
DRM_DEBUG_DRIVER("SPI speed: %uMHz\n", spi->max_speed_hz / 1000000);
- drm_fbdev_generic_setup(drm, 0);
+ drm_fbdev_dma_setup(drm, 0);
return 0;
}
diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c
index 1d8fa07572c5..d19e10289428 100644
--- a/drivers/gpu/drm/tiny/simpledrm.c
+++ b/drivers/gpu/drm/tiny/simpledrm.c
@@ -17,7 +17,7 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_device.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_shmem.h>
#include <drm/drm_format_helper.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
@@ -1042,7 +1042,7 @@ static int simpledrm_probe(struct platform_device *pdev)
if (color_mode == 16)
color_mode = sdev->format->depth; // can be 15 or 16
- drm_fbdev_generic_setup(dev, color_mode);
+ drm_fbdev_shmem_setup(dev, color_mode);
return 0;
}
diff --git a/drivers/gpu/drm/tiny/st7586.c b/drivers/gpu/drm/tiny/st7586.c
index 7336fa1ddaed..b9c6ed352182 100644
--- a/drivers/gpu/drm/tiny/st7586.c
+++ b/drivers/gpu/drm/tiny/st7586.c
@@ -16,7 +16,7 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_fb_dma_helper.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_format_helper.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
@@ -371,7 +371,7 @@ static int st7586_probe(struct spi_device *spi)
spi_set_drvdata(spi, drm);
- drm_fbdev_generic_setup(drm, 0);
+ drm_fbdev_dma_setup(drm, 0);
return 0;
}
@@ -392,7 +392,6 @@ static void st7586_shutdown(struct spi_device *spi)
static struct spi_driver st7586_spi_driver = {
.driver = {
.name = "st7586",
- .owner = THIS_MODULE,
.of_match_table = st7586_of_match,
},
.id_table = st7586_id,
diff --git a/drivers/gpu/drm/tiny/st7735r.c b/drivers/gpu/drm/tiny/st7735r.c
index 477eb36fbb70..1676da00883d 100644
--- a/drivers/gpu/drm/tiny/st7735r.c
+++ b/drivers/gpu/drm/tiny/st7735r.c
@@ -18,7 +18,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_managed.h>
@@ -241,7 +241,7 @@ static int st7735r_probe(struct spi_device *spi)
spi_set_drvdata(spi, drm);
- drm_fbdev_generic_setup(drm, 0);
+ drm_fbdev_dma_setup(drm, 0);
return 0;
}
diff --git a/drivers/gpu/drm/udl/Makefile b/drivers/gpu/drm/udl/Makefile
index 3f6db179455d..43d69a16af18 100644
--- a/drivers/gpu/drm/udl/Makefile
+++ b/drivers/gpu/drm/udl/Makefile
@@ -1,4 +1,10 @@
# SPDX-License-Identifier: GPL-2.0-only
-udl-y := udl_drv.o udl_modeset.o udl_main.o udl_transfer.o
+
+udl-y := \
+ udl_drv.o \
+ udl_edid.o \
+ udl_main.o \
+ udl_modeset.o \
+ udl_transfer.o
obj-$(CONFIG_DRM_UDL) := udl.o
diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c
index 1506094a8009..9612e9af27a4 100644
--- a/drivers/gpu/drm/udl/udl_drv.c
+++ b/drivers/gpu/drm/udl/udl_drv.c
@@ -6,7 +6,7 @@
#include <linux/module.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_shmem.h>
#include <drm/drm_file.h>
#include <drm/drm_gem_shmem_helper.h>
#include <drm/drm_managed.h>
@@ -117,7 +117,7 @@ static int udl_usb_probe(struct usb_interface *interface,
DRM_INFO("Initialized udl on minor %d\n", udl->drm.primary->index);
- drm_fbdev_generic_setup(&udl->drm, 0);
+ drm_fbdev_shmem_setup(&udl->drm, 0);
return 0;
}
diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h
index 282ebd6c02fd..1eb716d9dad5 100644
--- a/drivers/gpu/drm/udl/udl_drv.h
+++ b/drivers/gpu/drm/udl/udl_drv.h
@@ -49,17 +49,6 @@ struct urb_list {
size_t size;
};
-struct udl_connector {
- struct drm_connector connector;
- /* last udl_detect edid */
- struct edid *edid;
-};
-
-static inline struct udl_connector *to_udl_connector(struct drm_connector *connector)
-{
- return container_of(connector, struct udl_connector, connector);
-}
-
struct udl_device {
struct drm_device drm;
struct device *dev;
@@ -68,6 +57,7 @@ struct udl_device {
struct drm_plane primary_plane;
struct drm_crtc crtc;
struct drm_encoder encoder;
+ struct drm_connector connector;
struct mutex gem_lock;
diff --git a/drivers/gpu/drm/udl/udl_edid.c b/drivers/gpu/drm/udl/udl_edid.c
new file mode 100644
index 000000000000..d67e6bf1f2ae
--- /dev/null
+++ b/drivers/gpu/drm/udl/udl_edid.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/string.h>
+
+#include <drm/drm_drv.h>
+#include <drm/drm_edid.h>
+
+#include "udl_drv.h"
+#include "udl_edid.h"
+
+static int udl_read_edid_block(void *data, u8 *buf, unsigned int block, size_t len)
+{
+ struct udl_device *udl = data;
+ struct drm_device *dev = &udl->drm;
+ struct usb_device *udev = udl_to_usb_device(udl);
+ u8 *read_buff;
+ int idx, ret;
+ size_t i;
+
+ read_buff = kmalloc(2, GFP_KERNEL);
+ if (!read_buff)
+ return -ENOMEM;
+
+ if (!drm_dev_enter(dev, &idx)) {
+ ret = -ENODEV;
+ goto err_kfree;
+ }
+
+ for (i = 0; i < len; i++) {
+ int bval = (i + block * EDID_LENGTH) << 8;
+
+ ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+ 0x02, (0x80 | (0x02 << 5)), bval,
+ 0xA1, read_buff, 2, USB_CTRL_GET_TIMEOUT);
+ if (ret < 0) {
+ drm_err(dev, "Read EDID byte %zu failed err %x\n", i, ret);
+ goto err_drm_dev_exit;
+ } else if (ret < 1) {
+ ret = -EIO;
+ drm_err(dev, "Read EDID byte %zu failed\n", i);
+ goto err_drm_dev_exit;
+ }
+
+ buf[i] = read_buff[1];
+ }
+
+ drm_dev_exit(idx);
+ kfree(read_buff);
+
+ return 0;
+
+err_drm_dev_exit:
+ drm_dev_exit(idx);
+err_kfree:
+ kfree(read_buff);
+ return ret;
+}
+
+bool udl_probe_edid(struct udl_device *udl)
+{
+ u8 hdr[8];
+ int ret;
+
+ ret = udl_read_edid_block(udl, hdr, 0, sizeof(hdr));
+ if (ret)
+ return false;
+
+ /*
+ * The adapter sends all-zeros if no monitor has been
+ * connected. We consider anything else a connection.
+ */
+ return !!memchr_inv(hdr, 0, sizeof(hdr));
+}
+
+const struct drm_edid *udl_edid_read(struct drm_connector *connector)
+{
+ struct udl_device *udl = to_udl(connector->dev);
+
+ return drm_edid_read_custom(connector, udl_read_edid_block, udl);
+}
diff --git a/drivers/gpu/drm/udl/udl_edid.h b/drivers/gpu/drm/udl/udl_edid.h
new file mode 100644
index 000000000000..fe15ff3752b7
--- /dev/null
+++ b/drivers/gpu/drm/udl/udl_edid.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef UDL_EDID_H
+#define UDL_EDID_H
+
+#include <linux/types.h>
+
+struct drm_connector;
+struct drm_edid;
+struct udl_device;
+
+bool udl_probe_edid(struct udl_device *udl);
+const struct drm_edid *udl_edid_read(struct drm_connector *connector);
+
+#endif
diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c
index 7702359c90c2..bbb04f98886a 100644
--- a/drivers/gpu/drm/udl/udl_modeset.c
+++ b/drivers/gpu/drm/udl/udl_modeset.c
@@ -25,6 +25,7 @@
#include <drm/drm_vblank.h>
#include "udl_drv.h"
+#include "udl_edid.h"
#include "udl_proto.h"
/*
@@ -415,129 +416,42 @@ static const struct drm_encoder_funcs udl_encoder_funcs = {
static int udl_connector_helper_get_modes(struct drm_connector *connector)
{
- struct udl_connector *udl_connector = to_udl_connector(connector);
+ const struct drm_edid *drm_edid;
+ int count;
- drm_connector_update_edid_property(connector, udl_connector->edid);
- if (udl_connector->edid)
- return drm_add_edid_modes(connector, udl_connector->edid);
+ drm_edid = udl_edid_read(connector);
+ drm_edid_connector_update(connector, drm_edid);
+ count = drm_edid_connector_add_modes(connector);
+ drm_edid_free(drm_edid);
- return 0;
-}
-
-static const struct drm_connector_helper_funcs udl_connector_helper_funcs = {
- .get_modes = udl_connector_helper_get_modes,
-};
-
-static int udl_get_edid_block(void *data, u8 *buf, unsigned int block, size_t len)
-{
- struct udl_device *udl = data;
- struct drm_device *dev = &udl->drm;
- struct usb_device *udev = udl_to_usb_device(udl);
- u8 *read_buff;
- int ret;
- size_t i;
-
- read_buff = kmalloc(2, GFP_KERNEL);
- if (!read_buff)
- return -ENOMEM;
-
- for (i = 0; i < len; i++) {
- int bval = (i + block * EDID_LENGTH) << 8;
-
- ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
- 0x02, (0x80 | (0x02 << 5)), bval,
- 0xA1, read_buff, 2, USB_CTRL_GET_TIMEOUT);
- if (ret < 0) {
- drm_err(dev, "Read EDID byte %zu failed err %x\n", i, ret);
- goto err_kfree;
- } else if (ret < 1) {
- ret = -EIO;
- drm_err(dev, "Read EDID byte %zu failed\n", i);
- goto err_kfree;
- }
-
- buf[i] = read_buff[1];
- }
-
- kfree(read_buff);
-
- return 0;
-
-err_kfree:
- kfree(read_buff);
- return ret;
+ return count;
}
-static enum drm_connector_status udl_connector_detect(struct drm_connector *connector, bool force)
+static int udl_connector_helper_detect_ctx(struct drm_connector *connector,
+ struct drm_modeset_acquire_ctx *ctx,
+ bool force)
{
- struct drm_device *dev = connector->dev;
- struct udl_device *udl = to_udl(dev);
- struct udl_connector *udl_connector = to_udl_connector(connector);
- enum drm_connector_status status = connector_status_disconnected;
- int idx;
+ struct udl_device *udl = to_udl(connector->dev);
- /* cleanup previous EDID */
- kfree(udl_connector->edid);
- udl_connector->edid = NULL;
+ if (udl_probe_edid(udl))
+ return connector_status_connected;
- if (!drm_dev_enter(dev, &idx))
- return connector_status_disconnected;
-
- udl_connector->edid = drm_do_get_edid(connector, udl_get_edid_block, udl);
- if (udl_connector->edid)
- status = connector_status_connected;
-
- drm_dev_exit(idx);
-
- return status;
+ return connector_status_disconnected;
}
-static void udl_connector_destroy(struct drm_connector *connector)
-{
- struct udl_connector *udl_connector = to_udl_connector(connector);
-
- drm_connector_cleanup(connector);
- kfree(udl_connector->edid);
- kfree(udl_connector);
-}
+static const struct drm_connector_helper_funcs udl_connector_helper_funcs = {
+ .get_modes = udl_connector_helper_get_modes,
+ .detect_ctx = udl_connector_helper_detect_ctx,
+};
static const struct drm_connector_funcs udl_connector_funcs = {
.reset = drm_atomic_helper_connector_reset,
- .detect = udl_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = udl_connector_destroy,
+ .destroy = drm_connector_cleanup,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
-struct drm_connector *udl_connector_init(struct drm_device *dev)
-{
- struct udl_connector *udl_connector;
- struct drm_connector *connector;
- int ret;
-
- udl_connector = kzalloc(sizeof(*udl_connector), GFP_KERNEL);
- if (!udl_connector)
- return ERR_PTR(-ENOMEM);
-
- connector = &udl_connector->connector;
- ret = drm_connector_init(dev, connector, &udl_connector_funcs, DRM_MODE_CONNECTOR_VGA);
- if (ret)
- goto err_kfree;
-
- drm_connector_helper_add(connector, &udl_connector_helper_funcs);
-
- connector->polled = DRM_CONNECTOR_POLL_HPD |
- DRM_CONNECTOR_POLL_CONNECT |
- DRM_CONNECTOR_POLL_DISCONNECT;
-
- return connector;
-
-err_kfree:
- kfree(udl_connector);
- return ERR_PTR(ret);
-}
-
/*
* Modesetting
*/
@@ -607,9 +521,15 @@ int udl_modeset_init(struct drm_device *dev)
return ret;
encoder->possible_crtcs = drm_crtc_mask(crtc);
- connector = udl_connector_init(dev);
- if (IS_ERR(connector))
- return PTR_ERR(connector);
+ connector = &udl->connector;
+ ret = drm_connector_init(dev, connector, &udl_connector_funcs, DRM_MODE_CONNECTOR_VGA);
+ if (ret)
+ return ret;
+ drm_connector_helper_add(connector, &udl_connector_helper_funcs);
+
+ connector->polled = DRM_CONNECTOR_POLL_CONNECT |
+ DRM_CONNECTOR_POLL_DISCONNECT;
+
ret = drm_connector_attach_encoder(connector, encoder);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c
index 28b7ddce7747..f7477488b1cc 100644
--- a/drivers/gpu/drm/v3d/v3d_drv.c
+++ b/drivers/gpu/drm/v3d/v3d_drv.c
@@ -94,6 +94,9 @@ static int v3d_get_param_ioctl(struct drm_device *dev, void *data,
case DRM_V3D_PARAM_SUPPORTS_CPU_QUEUE:
args->value = 1;
return 0;
+ case DRM_V3D_PARAM_MAX_PERF_COUNTERS:
+ args->value = v3d->max_counters;
+ return 0;
default:
DRM_DEBUG("Unknown parameter %d\n", args->param);
return -EINVAL;
@@ -208,6 +211,7 @@ static const struct drm_ioctl_desc v3d_drm_ioctls[] = {
DRM_IOCTL_DEF_DRV(V3D_PERFMON_DESTROY, v3d_perfmon_destroy_ioctl, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(V3D_PERFMON_GET_VALUES, v3d_perfmon_get_values_ioctl, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(V3D_SUBMIT_CPU, v3d_submit_cpu_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(V3D_PERFMON_GET_COUNTER, v3d_perfmon_get_counter_ioctl, DRM_RENDER_ALLOW),
};
static const struct drm_driver v3d_drm_driver = {
@@ -294,6 +298,13 @@ static int v3d_platform_drm_probe(struct platform_device *pdev)
v3d->cores = V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_NCORES);
WARN_ON(v3d->cores > 1); /* multicore not yet implemented */
+ if (v3d->ver >= 71)
+ v3d->max_counters = ARRAY_SIZE(v3d_v71_performance_counters);
+ else if (v3d->ver >= 42)
+ v3d->max_counters = ARRAY_SIZE(v3d_v42_performance_counters);
+ else
+ v3d->max_counters = 0;
+
v3d->reset = devm_reset_control_get_exclusive(dev, NULL);
if (IS_ERR(v3d->reset)) {
ret = PTR_ERR(v3d->reset);
diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h
index a2c516fe6d79..556cbb400ba0 100644
--- a/drivers/gpu/drm/v3d/v3d_drv.h
+++ b/drivers/gpu/drm/v3d/v3d_drv.h
@@ -11,6 +11,8 @@
#include <drm/drm_gem_shmem_helper.h>
#include <drm/gpu_scheduler.h>
+#include "v3d_performance_counters.h"
+
#include "uapi/drm/v3d_drm.h"
struct clk;
@@ -102,6 +104,11 @@ struct v3d_dev {
int ver;
bool single_irq_line;
+ /* Different revisions of V3D have different total number of performance
+ * counters
+ */
+ unsigned int max_counters;
+
void __iomem *hub_regs;
void __iomem *core_regs[3];
void __iomem *bridge_regs;
@@ -344,8 +351,11 @@ struct v3d_timestamp_query {
struct drm_syncobj *syncobj;
};
+/* Maximum number of performance counters supported by any version of V3D */
+#define V3D_MAX_COUNTERS ARRAY_SIZE(v3d_v71_performance_counters)
+
/* Number of perfmons required to handle all supported performance counters */
-#define V3D_MAX_PERFMONS DIV_ROUND_UP(V3D_PERFCNT_NUM, \
+#define V3D_MAX_PERFMONS DIV_ROUND_UP(V3D_MAX_COUNTERS, \
DRM_V3D_MAX_PERF_COUNTERS)
struct v3d_performance_query {
@@ -575,6 +585,8 @@ int v3d_perfmon_destroy_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
int v3d_perfmon_get_values_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
+int v3d_perfmon_get_counter_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
/* v3d_sysfs.c */
int v3d_sysfs_init(struct device *dev);
diff --git a/drivers/gpu/drm/v3d/v3d_perfmon.c b/drivers/gpu/drm/v3d/v3d_perfmon.c
index e1be7368b87d..73e2bb8bdb7f 100644
--- a/drivers/gpu/drm/v3d/v3d_perfmon.c
+++ b/drivers/gpu/drm/v3d/v3d_perfmon.c
@@ -123,6 +123,7 @@ int v3d_perfmon_create_ioctl(struct drm_device *dev, void *data,
{
struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
struct drm_v3d_perfmon_create *req = data;
+ struct v3d_dev *v3d = v3d_priv->v3d;
struct v3d_perfmon *perfmon;
unsigned int i;
int ret;
@@ -134,7 +135,7 @@ int v3d_perfmon_create_ioctl(struct drm_device *dev, void *data,
/* Make sure all counters are valid. */
for (i = 0; i < req->ncounters; i++) {
- if (req->counters[i] >= V3D_PERFCNT_NUM)
+ if (req->counters[i] >= v3d->max_counters)
return -EINVAL;
}
@@ -216,3 +217,36 @@ int v3d_perfmon_get_values_ioctl(struct drm_device *dev, void *data,
return ret;
}
+
+int v3d_perfmon_get_counter_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_v3d_perfmon_get_counter *req = data;
+ struct v3d_dev *v3d = to_v3d_dev(dev);
+ const struct v3d_perf_counter_desc *counter;
+
+ for (int i = 0; i < ARRAY_SIZE(req->reserved); i++) {
+ if (req->reserved[i] != 0)
+ return -EINVAL;
+ }
+
+ /* Make sure that the counter ID is valid */
+ if (req->counter >= v3d->max_counters)
+ return -EINVAL;
+
+ if (v3d->ver >= 71) {
+ WARN_ON(v3d->max_counters != ARRAY_SIZE(v3d_v71_performance_counters));
+ counter = &v3d_v71_performance_counters[req->counter];
+ } else if (v3d->ver >= 42) {
+ WARN_ON(v3d->max_counters != ARRAY_SIZE(v3d_v42_performance_counters));
+ counter = &v3d_v42_performance_counters[req->counter];
+ } else {
+ return -EOPNOTSUPP;
+ }
+
+ strscpy(req->name, counter->name, sizeof(req->name));
+ strscpy(req->category, counter->category, sizeof(req->category));
+ strscpy(req->description, counter->description, sizeof(req->description));
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/v3d/v3d_performance_counters.h b/drivers/gpu/drm/v3d/v3d_performance_counters.h
new file mode 100644
index 000000000000..72822205ebdc
--- /dev/null
+++ b/drivers/gpu/drm/v3d/v3d_performance_counters.h
@@ -0,0 +1,208 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2024 Raspberry Pi
+ */
+#ifndef V3D_PERFORMANCE_COUNTERS_H
+#define V3D_PERFORMANCE_COUNTERS_H
+
+/* Holds a description of a given performance counter. The index of performance
+ * counter is given by the array on v3d_performance_counter.h
+ */
+struct v3d_perf_counter_desc {
+ /* Category of the counter */
+ char category[32];
+
+ /* Name of the counter */
+ char name[64];
+
+ /* Description of the counter */
+ char description[256];
+};
+
+static const struct v3d_perf_counter_desc v3d_v71_performance_counters[] = {
+ {"CORE", "cycle-count", "[CORE] Cycle counter"},
+ {"CORE", "core-active", "[CORE] Bin/Render/Compute active cycles"},
+ {"CLE", "CLE-bin-thread-active-cycles", "[CLE] Bin thread active cycles"},
+ {"CLE", "CLE-render-thread-active-cycles", "[CLE] Render thread active cycles"},
+ {"CORE", "compute-active-cycles", "[CORE] Compute active cycles"},
+ {"FEP", "FEP-valid-primitives-no-rendered-pixels", "[FEP] Valid primitives that result in no rendered pixels, for all rendered tiles"},
+ {"FEP", "FEP-valid-primitives-rendered-pixels", "[FEP] Valid primitives for all rendered tiles (primitives may be counted in more than one tile)"},
+ {"FEP", "FEP-clipped-quads", "[FEP] Early-Z/Near/Far clipped quads"},
+ {"FEP", "FEP-valid-quads", "[FEP] Valid quads"},
+ {"TLB", "TLB-quads-not-passing-stencil-test", "[TLB] Quads with no pixels passing the stencil test"},
+ {"TLB", "TLB-quads-not-passing-z-and-stencil-test", "[TLB] Quads with no pixels passing the Z and stencil tests"},
+ {"TLB", "TLB-quads-passing-z-and-stencil-test", "[TLB] Quads with any pixels passing the Z and stencil tests"},
+ {"TLB", "TLB-quads-written-to-color-buffer", "[TLB] Quads with valid pixels written to colour buffer"},
+ {"TLB", "TLB-partial-quads-written-to-color-buffer", "[TLB] Partial quads written to the colour buffer"},
+ {"PTB", "PTB-primitives-need-clipping", "[PTB] Primitives that need clipping"},
+ {"PTB", "PTB-primitives-discarded-outside-viewport", "[PTB] Primitives discarded by being outside the viewport"},
+ {"PTB", "PTB-primitives-binned", "[PTB] Total primitives binned"},
+ {"PTB", "PTB-primitives-discarded-reversed", "[PTB] Primitives that are discarded because they are reversed"},
+ {"QPU", "QPU-total-instr-cache-hit", "[QPU] Total instruction cache hits for all slices"},
+ {"QPU", "QPU-total-instr-cache-miss", "[QPU] Total instruction cache misses for all slices"},
+ {"QPU", "QPU-total-uniform-cache-hit", "[QPU] Total uniforms cache hits for all slices"},
+ {"QPU", "QPU-total-uniform-cache-miss", "[QPU] Total uniforms cache misses for all slices"},
+ {"TMU", "TMU-active-cycles", "[TMU] Active cycles"},
+ {"TMU", "TMU-stalled-cycles", "[TMU] Stalled cycles"},
+ {"TMU", "TMU-total-text-quads-access", "[TMU] Total texture cache accesses"},
+ {"TMU", "TMU-cache-x4-active-cycles", "[TMU] Cache active cycles for x4 access"},
+ {"TMU", "TMU-cache-x4-stalled-cycles", "[TMU] Cache stalled cycles for x4 access"},
+ {"TMU", "TMU-total-text-quads-x4-access", "[TMU] Total texture cache x4 access"},
+ {"L2T", "L2T-total-cache-hit", "[L2T] Total Level 2 cache hits"},
+ {"L2T", "L2T-total-cache-miss", "[L2T] Total Level 2 cache misses"},
+ {"L2T", "L2T-local", "[L2T] Local mode access"},
+ {"L2T", "L2T-writeback", "[L2T] Writeback"},
+ {"L2T", "L2T-zero", "[L2T] Zero"},
+ {"L2T", "L2T-merge", "[L2T] Merge"},
+ {"L2T", "L2T-fill", "[L2T] Fill"},
+ {"L2T", "L2T-stalls-no-wid", "[L2T] Stalls because no WID available"},
+ {"L2T", "L2T-stalls-no-rid", "[L2T] Stalls because no RID available"},
+ {"L2T", "L2T-stalls-queue-full", "[L2T] Stalls because internal queue full"},
+ {"L2T", "L2T-stalls-wrightback", "[L2T] Stalls because writeback in flight"},
+ {"L2T", "L2T-stalls-mem", "[L2T] Stalls because AXI blocks read"},
+ {"L2T", "L2T-stalls-fill", "[L2T] Stalls because fill pending for victim cache-line"},
+ {"L2T", "L2T-hitq", "[L2T] Sent request via hit queue"},
+ {"L2T", "L2T-hitq-full", "[L2T] Sent request via main queue because hit queue is full"},
+ {"L2T", "L2T-stalls-read-data", "[L2T] Stalls because waiting for data from SDRAM"},
+ {"L2T", "L2T-TMU-read-hits", "[L2T] TMU read hits"},
+ {"L2T", "L2T-TMU-read-miss", "[L2T] TMU read misses"},
+ {"L2T", "L2T-VCD-read-hits", "[L2T] VCD read hits"},
+ {"L2T", "L2T-VCD-read-miss", "[L2T] VCD read misses"},
+ {"L2T", "L2T-SLC-read-hits", "[L2T] SLC read hits (all slices)"},
+ {"L2T", "L2T-SLC-read-miss", "[L2T] SLC read misses (all slices)"},
+ {"AXI", "AXI-writes-seen-watch-0", "[AXI] Writes seen by watch 0"},
+ {"AXI", "AXI-reads-seen-watch-0", "[AXI] Reads seen by watch 0"},
+ {"AXI", "AXI-writes-stalled-seen-watch-0", "[AXI] Write stalls seen by watch 0"},
+ {"AXI", "AXI-reads-stalled-seen-watch-0", "[AXI] Read stalls seen by watch 0"},
+ {"AXI", "AXI-write-bytes-seen-watch-0", "[AXI] Total bytes written seen by watch 0"},
+ {"AXI", "AXI-read-bytes-seen-watch-0", "[AXI] Total bytes read seen by watch 0"},
+ {"AXI", "AXI-writes-seen-watch-1", "[AXI] Writes seen by watch 1"},
+ {"AXI", "AXI-reads-seen-watch-1", "[AXI] Reads seen by watch 1"},
+ {"AXI", "AXI-writes-stalled-seen-watch-1", "[AXI] Write stalls seen by watch 1"},
+ {"AXI", "AXI-reads-stalled-seen-watch-1", "[AXI] Read stalls seen by watch 1"},
+ {"AXI", "AXI-write-bytes-seen-watch-1", "[AXI] Total bytes written seen by watch 1"},
+ {"AXI", "AXI-read-bytes-seen-watch-1", "[AXI] Total bytes read seen by watch 1"},
+ {"CORE", "core-memory-writes", "[CORE] Total memory writes"},
+ {"L2T", "L2T-memory-writes", "[L2T] Total memory writes"},
+ {"PTB", "PTB-memory-writes", "[PTB] Total memory writes"},
+ {"TLB", "TLB-memory-writes", "[TLB] Total memory writes"},
+ {"CORE", "core-memory-reads", "[CORE] Total memory reads"},
+ {"L2T", "L2T-memory-reads", "[L2T] Total memory reads"},
+ {"PTB", "PTB-memory-reads", "[PTB] Total memory reads"},
+ {"PSE", "PSE-memory-reads", "[PSE] Total memory reads"},
+ {"TLB", "TLB-memory-reads", "[TLB] Total memory reads"},
+ {"PTB", "PTB-memory-words-writes", "[PTB] Total memory words written"},
+ {"TLB", "TLB-memory-words-writes", "[TLB] Total memory words written"},
+ {"PSE", "PSE-memory-words-reads", "[PSE] Total memory words read"},
+ {"TLB", "TLB-memory-words-reads", "[TLB] Total memory words read"},
+ {"AXI", "AXI-read-trans", "[AXI] Read transaction count"},
+ {"AXI", "AXI-write-trans", "[AXI] Write transaction count"},
+ {"AXI", "AXI-read-wait-cycles", "[AXI] Read total wait cycles"},
+ {"AXI", "AXI-write-wait-cycles", "[AXI] Write total wait cycles"},
+ {"AXI", "AXI-max-outstanding-reads", "[AXI] Maximum outstanding read transactions"},
+ {"AXI", "AXI-max-outstanding-writes", "[AXI] Maximum outstanding write transactions"},
+ {"QPU", "QPU-wait-bubble", "[QPU] Pipeline bubble in qcycles due all threads waiting"},
+ {"QPU", "QPU-ic-miss-bubble", "[QPU] Pipeline bubble in qcycles due instruction-cache miss"},
+ {"QPU", "QPU-active", "[QPU] Executed shader instruction"},
+ {"QPU", "QPU-total-active-clk-cycles-fragment-shading", "[QPU] Total active clock cycles for all QPUs doing fragment shading (counts only when QPU is not stalled)"},
+ {"QPU", "QPU-stalls", "[QPU] Stalled qcycles executing shader instruction"},
+ {"QPU", "QPU-total-clk-cycles-waiting-fragment-shading", "[QPU] Total stalled clock cycles for all QPUs doing fragment shading"},
+ {"QPU", "QPU-stalls-TMU", "[QPU] Stalled qcycles waiting for TMU"},
+ {"QPU", "QPU-stalls-TLB", "[QPU] Stalled qcycles waiting for TLB"},
+ {"QPU", "QPU-stalls-VPM", "[QPU] Stalled qcycles waiting for VPM"},
+ {"QPU", "QPU-stalls-uniforms", "[QPU] Stalled qcycles waiting for uniforms"},
+ {"QPU", "QPU-stalls-SFU", "[QPU] Stalled qcycles waiting for SFU"},
+ {"QPU", "QPU-stalls-other", "[QPU] Stalled qcycles waiting for any other reason (vary/W/Z)"},
+};
+
+static const struct v3d_perf_counter_desc v3d_v42_performance_counters[] = {
+ {"FEP", "FEP-valid-primitives-no-rendered-pixels", "[FEP] Valid primitives that result in no rendered pixels, for all rendered tiles"},
+ {"FEP", "FEP-valid-primitives-rendered-pixels", "[FEP] Valid primitives for all rendered tiles (primitives may be counted in more than one tile)"},
+ {"FEP", "FEP-clipped-quads", "[FEP] Early-Z/Near/Far clipped quads"},
+ {"FEP", "FEP-valid-quads", "[FEP] Valid quads"},
+ {"TLB", "TLB-quads-not-passing-stencil-test", "[TLB] Quads with no pixels passing the stencil test"},
+ {"TLB", "TLB-quads-not-passing-z-and-stencil-test", "[TLB] Quads with no pixels passing the Z and stencil tests"},
+ {"TLB", "TLB-quads-passing-z-and-stencil-test", "[TLB] Quads with any pixels passing the Z and stencil tests"},
+ {"TLB", "TLB-quads-with-zero-coverage", "[TLB] Quads with all pixels having zero coverage"},
+ {"TLB", "TLB-quads-with-non-zero-coverage", "[TLB] Quads with any pixels having non-zero coverage"},
+ {"TLB", "TLB-quads-written-to-color-buffer", "[TLB] Quads with valid pixels written to colour buffer"},
+ {"PTB", "PTB-primitives-discarded-outside-viewport", "[PTB] Primitives discarded by being outside the viewport"},
+ {"PTB", "PTB-primitives-need-clipping", "[PTB] Primitives that need clipping"},
+ {"PTB", "PTB-primitives-discarded-reversed", "[PTB] Primitives that are discarded because they are reversed"},
+ {"QPU", "QPU-total-idle-clk-cycles", "[QPU] Total idle clock cycles for all QPUs"},
+ {"QPU", "QPU-total-active-clk-cycles-vertex-coord-shading", "[QPU] Total active clock cycles for all QPUs doing vertex/coordinate/user shading (counts only when QPU is not stalled)"},
+ {"QPU", "QPU-total-active-clk-cycles-fragment-shading", "[QPU] Total active clock cycles for all QPUs doing fragment shading (counts only when QPU is not stalled)"},
+ {"QPU", "QPU-total-clk-cycles-executing-valid-instr", "[QPU] Total clock cycles for all QPUs executing valid instructions"},
+ {"QPU", "QPU-total-clk-cycles-waiting-TMU", "[QPU] Total clock cycles for all QPUs stalled waiting for TMUs only (counter won't increment if QPU also stalling for another reason)"},
+ {"QPU", "QPU-total-clk-cycles-waiting-scoreboard", "[QPU] Total clock cycles for all QPUs stalled waiting for Scoreboard only (counter won't increment if QPU also stalling for another reason)"},
+ {"QPU", "QPU-total-clk-cycles-waiting-varyings", "[QPU] Total clock cycles for all QPUs stalled waiting for Varyings only (counter won't increment if QPU also stalling for another reason)"},
+ {"QPU", "QPU-total-instr-cache-hit", "[QPU] Total instruction cache hits for all slices"},
+ {"QPU", "QPU-total-instr-cache-miss", "[QPU] Total instruction cache misses for all slices"},
+ {"QPU", "QPU-total-uniform-cache-hit", "[QPU] Total uniforms cache hits for all slices"},
+ {"QPU", "QPU-total-uniform-cache-miss", "[QPU] Total uniforms cache misses for all slices"},
+ {"TMU", "TMU-total-text-quads-access", "[TMU] Total texture cache accesses"},
+ {"TMU", "TMU-total-text-cache-miss", "[TMU] Total texture cache misses (number of fetches from memory/L2cache)"},
+ {"VPM", "VPM-total-clk-cycles-VDW-stalled", "[VPM] Total clock cycles VDW is stalled waiting for VPM access"},
+ {"VPM", "VPM-total-clk-cycles-VCD-stalled", "[VPM] Total clock cycles VCD is stalled waiting for VPM access"},
+ {"CLE", "CLE-bin-thread-active-cycles", "[CLE] Bin thread active cycles"},
+ {"CLE", "CLE-render-thread-active-cycles", "[CLE] Render thread active cycles"},
+ {"L2T", "L2T-total-cache-hit", "[L2T] Total Level 2 cache hits"},
+ {"L2T", "L2T-total-cache-miss", "[L2T] Total Level 2 cache misses"},
+ {"CORE", "cycle-count", "[CORE] Cycle counter"},
+ {"QPU", "QPU-total-clk-cycles-waiting-vertex-coord-shading", "[QPU] Total stalled clock cycles for all QPUs doing vertex/coordinate/user shading"},
+ {"QPU", "QPU-total-clk-cycles-waiting-fragment-shading", "[QPU] Total stalled clock cycles for all QPUs doing fragment shading"},
+ {"PTB", "PTB-primitives-binned", "[PTB] Total primitives binned"},
+ {"AXI", "AXI-writes-seen-watch-0", "[AXI] Writes seen by watch 0"},
+ {"AXI", "AXI-reads-seen-watch-0", "[AXI] Reads seen by watch 0"},
+ {"AXI", "AXI-writes-stalled-seen-watch-0", "[AXI] Write stalls seen by watch 0"},
+ {"AXI", "AXI-reads-stalled-seen-watch-0", "[AXI] Read stalls seen by watch 0"},
+ {"AXI", "AXI-write-bytes-seen-watch-0", "[AXI] Total bytes written seen by watch 0"},
+ {"AXI", "AXI-read-bytes-seen-watch-0", "[AXI] Total bytes read seen by watch 0"},
+ {"AXI", "AXI-writes-seen-watch-1", "[AXI] Writes seen by watch 1"},
+ {"AXI", "AXI-reads-seen-watch-1", "[AXI] Reads seen by watch 1"},
+ {"AXI", "AXI-writes-stalled-seen-watch-1", "[AXI] Write stalls seen by watch 1"},
+ {"AXI", "AXI-reads-stalled-seen-watch-1", "[AXI] Read stalls seen by watch 1"},
+ {"AXI", "AXI-write-bytes-seen-watch-1", "[AXI] Total bytes written seen by watch 1"},
+ {"AXI", "AXI-read-bytes-seen-watch-1", "[AXI] Total bytes read seen by watch 1"},
+ {"TLB", "TLB-partial-quads-written-to-color-buffer", "[TLB] Partial quads written to the colour buffer"},
+ {"TMU", "TMU-total-config-access", "[TMU] Total config accesses"},
+ {"L2T", "L2T-no-id-stalled", "[L2T] No ID stall"},
+ {"L2T", "L2T-command-queue-stalled", "[L2T] Command queue full stall"},
+ {"L2T", "L2T-TMU-writes", "[L2T] TMU write accesses"},
+ {"TMU", "TMU-active-cycles", "[TMU] Active cycles"},
+ {"TMU", "TMU-stalled-cycles", "[TMU] Stalled cycles"},
+ {"CLE", "CLE-thread-active-cycles", "[CLE] Bin or render thread active cycles"},
+ {"L2T", "L2T-TMU-reads", "[L2T] TMU read accesses"},
+ {"L2T", "L2T-CLE-reads", "[L2T] CLE read accesses"},
+ {"L2T", "L2T-VCD-reads", "[L2T] VCD read accesses"},
+ {"L2T", "L2T-TMU-config-reads", "[L2T] TMU CFG read accesses"},
+ {"L2T", "L2T-SLC0-reads", "[L2T] SLC0 read accesses"},
+ {"L2T", "L2T-SLC1-reads", "[L2T] SLC1 read accesses"},
+ {"L2T", "L2T-SLC2-reads", "[L2T] SLC2 read accesses"},
+ {"L2T", "L2T-TMU-write-miss", "[L2T] TMU write misses"},
+ {"L2T", "L2T-TMU-read-miss", "[L2T] TMU read misses"},
+ {"L2T", "L2T-CLE-read-miss", "[L2T] CLE read misses"},
+ {"L2T", "L2T-VCD-read-miss", "[L2T] VCD read misses"},
+ {"L2T", "L2T-TMU-config-read-miss", "[L2T] TMU CFG read misses"},
+ {"L2T", "L2T-SLC0-read-miss", "[L2T] SLC0 read misses"},
+ {"L2T", "L2T-SLC1-read-miss", "[L2T] SLC1 read misses"},
+ {"L2T", "L2T-SLC2-read-miss", "[L2T] SLC2 read misses"},
+ {"CORE", "core-memory-writes", "[CORE] Total memory writes"},
+ {"L2T", "L2T-memory-writes", "[L2T] Total memory writes"},
+ {"PTB", "PTB-memory-writes", "[PTB] Total memory writes"},
+ {"TLB", "TLB-memory-writes", "[TLB] Total memory writes"},
+ {"CORE", "core-memory-reads", "[CORE] Total memory reads"},
+ {"L2T", "L2T-memory-reads", "[L2T] Total memory reads"},
+ {"PTB", "PTB-memory-reads", "[PTB] Total memory reads"},
+ {"PSE", "PSE-memory-reads", "[PSE] Total memory reads"},
+ {"TLB", "TLB-memory-reads", "[TLB] Total memory reads"},
+ {"GMP", "GMP-memory-reads", "[GMP] Total memory reads"},
+ {"PTB", "PTB-memory-words-writes", "[PTB] Total memory words written"},
+ {"TLB", "TLB-memory-words-writes", "[TLB] Total memory words written"},
+ {"PSE", "PSE-memory-words-reads", "[PSE] Total memory words read"},
+ {"TLB", "TLB-memory-words-reads", "[TLB] Total memory words read"},
+ {"TMU", "TMU-MRU-hits", "[TMU] Total MRU hits"},
+ {"CORE", "compute-active-cycles", "[CORE] Compute active cycles"},
+};
+
+#endif
diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c
index 7cd8c335cd9b..03df37a3acf5 100644
--- a/drivers/gpu/drm/v3d/v3d_sched.c
+++ b/drivers/gpu/drm/v3d/v3d_sched.c
@@ -490,7 +490,7 @@ v3d_write_performance_query_result(struct v3d_cpu_job *job, void *data, u32 quer
struct v3d_file_priv *v3d_priv = job->base.file->driver_priv;
struct v3d_dev *v3d = job->base.v3d;
struct v3d_perfmon *perfmon;
- u64 counter_values[V3D_PERFCNT_NUM];
+ u64 counter_values[V3D_MAX_COUNTERS];
for (int i = 0; i < performance_query->nperfmons; i++) {
perfmon = v3d_perfmon_find(v3d_priv,
diff --git a/drivers/gpu/drm/vboxvideo/vbox_drv.c b/drivers/gpu/drm/vboxvideo/vbox_drv.c
index cd9e66a06596..ef36834c8673 100644
--- a/drivers/gpu/drm/vboxvideo/vbox_drv.c
+++ b/drivers/gpu/drm/vboxvideo/vbox_drv.c
@@ -14,7 +14,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_ttm.h>
#include <drm/drm_file.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_managed.h>
@@ -80,7 +80,7 @@ static int vbox_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ret)
goto err_irq_fini;
- drm_fbdev_generic_setup(&vbox->ddev, 32);
+ drm_fbdev_ttm_setup(&vbox->ddev, 32);
return 0;
diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c
index ad924a8502e9..64baf2f22d9f 100644
--- a/drivers/gpu/drm/virtio/virtgpu_display.c
+++ b/drivers/gpu/drm/virtio/virtgpu_display.c
@@ -164,11 +164,9 @@ static int virtio_gpu_conn_get_modes(struct drm_connector *connector)
struct drm_display_mode *mode = NULL;
int count, width, height;
- if (output->edid) {
- count = drm_add_edid_modes(connector, output->edid);
- if (count)
- return count;
- }
+ count = drm_edid_connector_add_modes(connector);
+ if (count)
+ return count;
width = le32_to_cpu(output->info.r.width);
height = le32_to_cpu(output->info.r.height);
@@ -369,5 +367,5 @@ void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev)
return;
for (i = 0 ; i < vgdev->num_scanouts; ++i)
- kfree(vgdev->outputs[i].edid);
+ drm_edid_free(vgdev->outputs[i].drm_edid);
}
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c
index 188e126383c2..e5a2665e50ea 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.c
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.c
@@ -35,7 +35,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_shmem.h>
#include <drm/drm_file.h>
#include "virtgpu_drv.h"
@@ -103,7 +103,7 @@ static int virtio_gpu_probe(struct virtio_device *vdev)
if (ret)
goto err_deinit;
- drm_fbdev_generic_setup(vdev->priv, 32);
+ drm_fbdev_shmem_setup(vdev->priv, 32);
return 0;
err_deinit:
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
index bb7d86a0c6a1..64c236169db8 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.h
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
@@ -179,7 +179,7 @@ struct virtio_gpu_output {
struct drm_encoder enc;
struct virtio_gpu_display_one info;
struct virtio_gpu_update_cursor cursor;
- struct edid *edid;
+ const struct drm_edid *drm_edid;
int cur_x;
int cur_y;
bool needs_modeset;
diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
index b1a00c0c25a7..0d3d0d09f39b 100644
--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -741,21 +741,21 @@ static void virtio_gpu_cmd_get_edid_cb(struct virtio_gpu_device *vgdev,
(struct virtio_gpu_resp_edid *)vbuf->resp_buf;
uint32_t scanout = le32_to_cpu(cmd->scanout);
struct virtio_gpu_output *output;
- struct edid *new_edid, *old_edid;
+ const struct drm_edid *new_edid, *old_edid;
if (scanout >= vgdev->num_scanouts)
return;
output = vgdev->outputs + scanout;
- new_edid = drm_do_get_edid(&output->conn, virtio_get_edid_block, resp);
- drm_connector_update_edid_property(&output->conn, new_edid);
+ new_edid = drm_edid_read_custom(&output->conn, virtio_get_edid_block, resp);
+ drm_edid_connector_update(&output->conn, new_edid);
spin_lock(&vgdev->display_info_lock);
- old_edid = output->edid;
- output->edid = new_edid;
+ old_edid = output->drm_edid;
+ output->drm_edid = new_edid;
spin_unlock(&vgdev->display_info_lock);
- kfree(old_edid);
+ drm_edid_free(old_edid);
wake_up(&vgdev->resp_wq);
}
diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c
index dd0af086e7fa..8dc9dc13896e 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.c
+++ b/drivers/gpu/drm/vkms/vkms_drv.c
@@ -17,7 +17,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_shmem.h>
#include <drm/drm_file.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_ioctl.h>
@@ -223,7 +223,7 @@ static int vkms_create(struct vkms_config *config)
if (ret)
goto out_devres;
- drm_fbdev_generic_setup(&vkms_device->drm, 0);
+ drm_fbdev_shmem_setup(&vkms_device->drm, 0);
return 0;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 8f1730aeacc9..504aea22f7f2 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -37,7 +37,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_ttm.h>
#include <drm/drm_gem_ttm_helper.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_module.h>
@@ -1686,7 +1686,7 @@ static int vmw_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
vmw_fifo_resource_inc(vmw);
vmw_svga_enable(vmw);
- drm_fbdev_generic_setup(&vmw->drm, 0);
+ drm_fbdev_ttm_setup(&vmw->drm, 0);
vmw_debugfs_gem_init(vmw);
vmw_debugfs_resource_managers_init(vmw);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c
index 7e93a45948f7..3bfcf671fcd5 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c
@@ -31,7 +31,6 @@
#include "vmwgfx_bo.h"
#include "vmwgfx_drv.h"
#include "vmwgfx_kms.h"
-#include "vmwgfx_vkms.h"
#include "vmw_surface_cache.h"
diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c b/drivers/gpu/drm/xlnx/zynqmp_disp.c
index c9fb432d4cbd..9368acf56eaf 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_disp.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c
@@ -141,24 +141,18 @@ struct zynqmp_disp_layer {
* struct zynqmp_disp - Display controller
* @dev: Device structure
* @dpsub: Display subsystem
- * @blend.base: Register I/O base address for the blender
- * @avbuf.base: Register I/O base address for the audio/video buffer manager
- * @audio.base: Registers I/O base address for the audio mixer
+ * @blend: Register I/O base address for the blender
+ * @avbuf: Register I/O base address for the audio/video buffer manager
+ * @audio: Registers I/O base address for the audio mixer
* @layers: Layers (planes)
*/
struct zynqmp_disp {
struct device *dev;
struct zynqmp_dpsub *dpsub;
- struct {
- void __iomem *base;
- } blend;
- struct {
- void __iomem *base;
- } avbuf;
- struct {
- void __iomem *base;
- } audio;
+ void __iomem *blend;
+ void __iomem *avbuf;
+ void __iomem *audio;
struct zynqmp_disp_layer layers[ZYNQMP_DPSUB_NUM_LAYERS];
};
@@ -410,12 +404,12 @@ static const struct zynqmp_disp_format avbuf_live_fmts[] = {
static u32 zynqmp_disp_avbuf_read(struct zynqmp_disp *disp, int reg)
{
- return readl(disp->avbuf.base + reg);
+ return readl(disp->avbuf + reg);
}
static void zynqmp_disp_avbuf_write(struct zynqmp_disp *disp, int reg, u32 val)
{
- writel(val, disp->avbuf.base + reg);
+ writel(val, disp->avbuf + reg);
}
static bool zynqmp_disp_layer_is_video(const struct zynqmp_disp_layer *layer)
@@ -651,7 +645,7 @@ static void zynqmp_disp_avbuf_disable(struct zynqmp_disp *disp)
static void zynqmp_disp_blend_write(struct zynqmp_disp *disp, int reg, u32 val)
{
- writel(val, disp->blend.base + reg);
+ writel(val, disp->blend + reg);
}
/*
@@ -877,7 +871,7 @@ static void zynqmp_disp_blend_layer_disable(struct zynqmp_disp *disp,
static void zynqmp_disp_audio_write(struct zynqmp_disp *disp, int reg, u32 val)
{
- writel(val, disp->audio.base + reg);
+ writel(val, disp->audio + reg);
}
/**
@@ -1412,21 +1406,21 @@ int zynqmp_disp_probe(struct zynqmp_dpsub *dpsub)
disp->dev = &pdev->dev;
disp->dpsub = dpsub;
- disp->blend.base = devm_platform_ioremap_resource_byname(pdev, "blend");
- if (IS_ERR(disp->blend.base)) {
- ret = PTR_ERR(disp->blend.base);
+ disp->blend = devm_platform_ioremap_resource_byname(pdev, "blend");
+ if (IS_ERR(disp->blend)) {
+ ret = PTR_ERR(disp->blend);
goto error;
}
- disp->avbuf.base = devm_platform_ioremap_resource_byname(pdev, "av_buf");
- if (IS_ERR(disp->avbuf.base)) {
- ret = PTR_ERR(disp->avbuf.base);
+ disp->avbuf = devm_platform_ioremap_resource_byname(pdev, "av_buf");
+ if (IS_ERR(disp->avbuf)) {
+ ret = PTR_ERR(disp->avbuf);
goto error;
}
- disp->audio.base = devm_platform_ioremap_resource_byname(pdev, "aud");
- if (IS_ERR(disp->audio.base)) {
- ret = PTR_ERR(disp->audio.base);
+ disp->audio = devm_platform_ioremap_resource_byname(pdev, "aud");
+ if (IS_ERR(disp->audio)) {
+ ret = PTR_ERR(disp->audio);
goto error;
}
diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c b/drivers/gpu/drm/xlnx/zynqmp_dp.c
index 8c2d24809014..9df068a413f3 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_dp.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c
@@ -606,28 +606,21 @@ static void zynqmp_dp_adjust_train(struct zynqmp_dp *dp,
u8 link_status[DP_LINK_STATUS_SIZE])
{
u8 *train_set = dp->train_set;
- u8 voltage = 0, preemphasis = 0;
u8 i;
for (i = 0; i < dp->mode.lane_cnt; i++) {
- u8 v = drm_dp_get_adjust_request_voltage(link_status, i);
- u8 p = drm_dp_get_adjust_request_pre_emphasis(link_status, i);
+ u8 voltage = drm_dp_get_adjust_request_voltage(link_status, i);
+ u8 preemphasis =
+ drm_dp_get_adjust_request_pre_emphasis(link_status, i);
- if (v > voltage)
- voltage = v;
+ if (voltage >= DP_TRAIN_VOLTAGE_SWING_LEVEL_3)
+ voltage |= DP_TRAIN_MAX_SWING_REACHED;
- if (p > preemphasis)
- preemphasis = p;
- }
-
- if (voltage >= DP_TRAIN_VOLTAGE_SWING_LEVEL_3)
- voltage |= DP_TRAIN_MAX_SWING_REACHED;
+ if (preemphasis >= DP_TRAIN_PRE_EMPH_LEVEL_2)
+ preemphasis |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
- if (preemphasis >= DP_TRAIN_PRE_EMPH_LEVEL_2)
- preemphasis |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
-
- for (i = 0; i < dp->mode.lane_cnt; i++)
train_set[i] = voltage | preemphasis;
+ }
}
/**
@@ -1007,7 +1000,7 @@ zynqmp_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
msg->buffer, msg->size,
&msg->reply);
if (!ret) {
- dev_dbg(dp->dev, "aux %d retries\n", i);
+ dev_vdbg(dp->dev, "aux %d retries\n", i);
return msg->size;
}
diff --git a/drivers/gpu/drm/xlnx/zynqmp_dpsub.h b/drivers/gpu/drm/xlnx/zynqmp_dpsub.h
index 09ea01878f2a..b18554467e9c 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_dpsub.h
+++ b/drivers/gpu/drm/xlnx/zynqmp_dpsub.h
@@ -53,6 +53,7 @@ enum zynqmp_dpsub_format {
* @drm: The DRM/KMS device data
* @bridge: The DP encoder bridge
* @disp: The display controller
+ * @layers: Video and graphics layers
* @dp: The DisplayPort controller
* @dma_align: DMA alignment constraint (must be a power of 2)
*/
diff --git a/drivers/gpu/drm/xlnx/zynqmp_kms.h b/drivers/gpu/drm/xlnx/zynqmp_kms.h
index 01be96b00e3f..cb13c6b8008e 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_kms.h
+++ b/drivers/gpu/drm/xlnx/zynqmp_kms.h
@@ -22,9 +22,9 @@
struct zynqmp_dpsub;
/**
- * struct zynqmp_dpsub - ZynqMP DisplayPort Subsystem DRM/KMS data
+ * struct zynqmp_dpsub_drm - ZynqMP DisplayPort Subsystem DRM/KMS data
* @dpsub: Backpointer to the DisplayPort subsystem
- * @drm: The DRM/KMS device
+ * @dev: The DRM/KMS device
* @planes: The DRM planes
* @crtc: The DRM CRTC
* @encoder: The dummy DRM encoder
diff --git a/drivers/video/fbdev/core/fb_defio.c b/drivers/video/fbdev/core/fb_defio.c
index 806ecd32219b..5ee7e78c2cea 100644
--- a/drivers/video/fbdev/core/fb_defio.c
+++ b/drivers/video/fbdev/core/fb_defio.c
@@ -23,33 +23,71 @@
#include <linux/rmap.h>
#include <linux/pagemap.h>
-static struct page *fb_deferred_io_page(struct fb_info *info, unsigned long offs)
+static struct page *fb_deferred_io_get_page(struct fb_info *info, unsigned long offs)
{
- void *screen_base = (void __force *) info->screen_base;
- struct page *page;
+ struct fb_deferred_io *fbdefio = info->fbdefio;
+ const void *screen_buffer = info->screen_buffer;
+ struct page *page = NULL;
- if (is_vmalloc_addr(screen_base + offs))
- page = vmalloc_to_page(screen_base + offs);
- else
+ if (fbdefio->get_page)
+ return fbdefio->get_page(info, offs);
+
+ if (is_vmalloc_addr(screen_buffer + offs))
+ page = vmalloc_to_page(screen_buffer + offs);
+ else if (info->fix.smem_start)
page = pfn_to_page((info->fix.smem_start + offs) >> PAGE_SHIFT);
+ if (page)
+ get_page(page);
+
return page;
}
+static struct fb_deferred_io_pageref *fb_deferred_io_pageref_lookup(struct fb_info *info,
+ unsigned long offset,
+ struct page *page)
+{
+ unsigned long pgoff = offset >> PAGE_SHIFT;
+ struct fb_deferred_io_pageref *pageref;
+
+ if (fb_WARN_ON_ONCE(info, pgoff >= info->npagerefs))
+ return NULL; /* incorrect allocation size */
+
+ /* 1:1 mapping between pageref and page offset */
+ pageref = &info->pagerefs[pgoff];
+
+ if (pageref->page)
+ goto out;
+
+ pageref->page = page;
+ pageref->offset = pgoff << PAGE_SHIFT;
+ INIT_LIST_HEAD(&pageref->list);
+
+out:
+ if (fb_WARN_ON_ONCE(info, pageref->page != page))
+ return NULL; /* inconsistent state */
+ return pageref;
+}
+
+static void fb_deferred_io_pageref_clear(struct fb_deferred_io_pageref *pageref)
+{
+ struct page *page = pageref->page;
+
+ if (page)
+ page->mapping = NULL;
+}
+
static struct fb_deferred_io_pageref *fb_deferred_io_pageref_get(struct fb_info *info,
unsigned long offset,
struct page *page)
{
struct fb_deferred_io *fbdefio = info->fbdefio;
struct list_head *pos = &fbdefio->pagereflist;
- unsigned long pgoff = offset >> PAGE_SHIFT;
struct fb_deferred_io_pageref *pageref, *cur;
- if (WARN_ON_ONCE(pgoff >= info->npagerefs))
- return NULL; /* incorrect allocation size */
-
- /* 1:1 mapping between pageref and page offset */
- pageref = &info->pagerefs[pgoff];
+ pageref = fb_deferred_io_pageref_lookup(info, offset, page);
+ if (!pageref)
+ return NULL;
/*
* This check is to catch the case where a new process could start
@@ -60,9 +98,6 @@ static struct fb_deferred_io_pageref *fb_deferred_io_pageref_get(struct fb_info
if (!list_empty(&pageref->list))
goto pageref_already_added;
- pageref->page = page;
- pageref->offset = pgoff << PAGE_SHIFT;
-
if (unlikely(fbdefio->sort_pagereflist)) {
/*
* We loop through the list of pagerefs before adding in
@@ -101,12 +136,10 @@ static vm_fault_t fb_deferred_io_fault(struct vm_fault *vmf)
if (offset >= info->fix.smem_len)
return VM_FAULT_SIGBUS;
- page = fb_deferred_io_page(info, offset);
+ page = fb_deferred_io_get_page(info, offset);
if (!page)
return VM_FAULT_SIGBUS;
- get_page(page);
-
if (vmf->vma->vm_file)
page->mapping = vmf->vma->vm_file->f_mapping;
else
@@ -264,7 +297,7 @@ int fb_deferred_io_init(struct fb_info *info)
{
struct fb_deferred_io *fbdefio = info->fbdefio;
struct fb_deferred_io_pageref *pagerefs;
- unsigned long npagerefs, i;
+ unsigned long npagerefs;
int ret;
BUG_ON(!fbdefio);
@@ -286,8 +319,6 @@ int fb_deferred_io_init(struct fb_info *info)
ret = -ENOMEM;
goto err;
}
- for (i = 0; i < npagerefs; ++i)
- INIT_LIST_HEAD(&pagerefs[i].list);
info->npagerefs = npagerefs;
info->pagerefs = pagerefs;
@@ -312,16 +343,13 @@ EXPORT_SYMBOL_GPL(fb_deferred_io_open);
static void fb_deferred_io_lastclose(struct fb_info *info)
{
- struct page *page;
- int i;
+ unsigned long i;
flush_delayed_work(&info->deferred_work);
/* clear out the mapping that we setup */
- for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) {
- page = fb_deferred_io_page(info, i);
- page->mapping = NULL;
- }
+ for (i = 0; i < info->npagerefs; ++i)
+ fb_deferred_io_pageref_clear(&info->pagerefs[i]);
}
void fb_deferred_io_release(struct fb_info *info)
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index fe88d7fc6b8f..58ee9adf9091 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1636,8 +1636,12 @@ struct drm_connector {
/**
* @edid_blob_ptr: DRM property containing EDID if present. Protected by
- * &drm_mode_config.mutex. This should be updated only by calling
+ * &drm_mode_config.mutex.
+ *
+ * This must be updated only by calling drm_edid_connector_update() or
* drm_connector_update_edid_property().
+ *
+ * This must not be used by drivers directly.
*/
struct drm_property_blob *edid_blob_ptr;
diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h
index 8878260d7529..cd37936c3926 100644
--- a/include/drm/drm_drv.h
+++ b/include/drm/drm_drv.h
@@ -411,7 +411,7 @@ struct drm_driver {
char *name;
/** @desc: driver description */
char *desc;
- /** @date: driver date */
+ /** @date: driver date, unused, to be removed */
char *date;
/**
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index b085525e53e2..6bdfa254a1c1 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -423,10 +423,6 @@ static inline void drm_edid_decode_panel_id(u32 panel_id, char vend[4], u16 *pro
}
bool drm_probe_ddc(struct i2c_adapter *adapter);
-struct edid *drm_do_get_edid(struct drm_connector *connector,
- int (*get_edid_block)(void *data, u8 *buf, unsigned int block,
- size_t len),
- void *data);
struct edid *drm_get_edid(struct drm_connector *connector,
struct i2c_adapter *adapter);
struct edid *drm_get_edid_switcheroo(struct drm_connector *connector,
diff --git a/include/drm/drm_fbdev_generic.h b/include/drm/drm_fbdev_generic.h
deleted file mode 100644
index 75799342098d..000000000000
--- a/include/drm/drm_fbdev_generic.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-
-#ifndef DRM_FBDEV_GENERIC_H
-#define DRM_FBDEV_GENERIC_H
-
-struct drm_device;
-
-#ifdef CONFIG_DRM_FBDEV_EMULATION
-void drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp);
-#else
-static inline void drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
-{ }
-#endif
-
-#endif
diff --git a/include/drm/drm_fbdev_shmem.h b/include/drm/drm_fbdev_shmem.h
new file mode 100644
index 000000000000..fb43cadd1950
--- /dev/null
+++ b/include/drm/drm_fbdev_shmem.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: MIT */
+
+#ifndef DRM_FBDEV_SHMEM_H
+#define DRM_FBDEV_SHMEM_H
+
+struct drm_device;
+
+#ifdef CONFIG_DRM_FBDEV_EMULATION
+void drm_fbdev_shmem_setup(struct drm_device *dev, unsigned int preferred_bpp);
+#else
+static inline void drm_fbdev_shmem_setup(struct drm_device *dev, unsigned int preferred_bpp)
+{ }
+#endif
+
+#endif
diff --git a/include/drm/drm_fbdev_ttm.h b/include/drm/drm_fbdev_ttm.h
new file mode 100644
index 000000000000..9e6c3bdf3537
--- /dev/null
+++ b/include/drm/drm_fbdev_ttm.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: MIT */
+
+#ifndef DRM_FBDEV_TTM_H
+#define DRM_FBDEV_TTM_H
+
+struct drm_device;
+
+#ifdef CONFIG_DRM_FBDEV_EMULATION
+void drm_fbdev_ttm_setup(struct drm_device *dev, unsigned int preferred_bpp);
+#else
+static inline void drm_fbdev_ttm_setup(struct drm_device *dev, unsigned int preferred_bpp)
+{ }
+#endif
+
+#endif
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index 82b1cc434ea3..bd5a0b6d0711 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -197,6 +197,27 @@ struct mipi_dsi_device {
struct drm_dsc_config *dsc;
};
+/**
+ * struct mipi_dsi_multi_context - Context to call multiple MIPI DSI funcs in a row
+ */
+struct mipi_dsi_multi_context {
+ /**
+ * @dsi: Pointer to the MIPI DSI device
+ */
+ struct mipi_dsi_device *dsi;
+
+ /**
+ * @accum_err: Storage for the accumulated error over the multiple calls
+ *
+ * Init to 0. If a function encounters an error then the error code
+ * will be stored here. If you call a function and this points to a
+ * non-zero value then the function will be a noop. This allows calling
+ * a function many times in a row and just checking the error at the
+ * end to see if any of them failed.
+ */
+ int accum_err;
+};
+
#define MIPI_DSI_MODULE_PREFIX "mipi-dsi:"
#define to_mipi_dsi_device(__dev) container_of_const(__dev, struct mipi_dsi_device, dev)
@@ -254,11 +275,28 @@ int mipi_dsi_compression_mode_ext(struct mipi_dsi_device *dsi, bool enable,
int mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi,
const struct drm_dsc_picture_parameter_set *pps);
+void mipi_dsi_compression_mode_ext_multi(struct mipi_dsi_multi_context *ctx,
+ bool enable,
+ enum mipi_dsi_compression_algo algo,
+ unsigned int pps_selector);
+void mipi_dsi_picture_parameter_set_multi(struct mipi_dsi_multi_context *ctx,
+ const struct drm_dsc_picture_parameter_set *pps);
+
ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload,
size_t size);
+int mipi_dsi_generic_write_chatty(struct mipi_dsi_device *dsi,
+ const void *payload, size_t size);
+void mipi_dsi_generic_write_multi(struct mipi_dsi_multi_context *ctx,
+ const void *payload, size_t size);
ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
size_t num_params, void *data, size_t size);
+#define mipi_dsi_msleep(ctx, delay) \
+ do { \
+ if (!ctx.accum_err) \
+ msleep(delay); \
+ } while (0)
+
/**
* enum mipi_dsi_dcs_tear_mode - Tearing Effect Output Line mode
* @MIPI_DSI_DCS_TEAR_MODE_VBLANK: the TE output line consists of V-Blanking
@@ -279,6 +317,10 @@ enum mipi_dsi_dcs_tear_mode {
ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi,
const void *data, size_t len);
+int mipi_dsi_dcs_write_buffer_chatty(struct mipi_dsi_device *dsi,
+ const void *data, size_t len);
+void mipi_dsi_dcs_write_buffer_multi(struct mipi_dsi_multi_context *ctx,
+ const void *data, size_t len);
ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 cmd,
const void *data, size_t len);
ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 cmd, void *data,
@@ -309,42 +351,86 @@ int mipi_dsi_dcs_set_display_brightness_large(struct mipi_dsi_device *dsi,
int mipi_dsi_dcs_get_display_brightness_large(struct mipi_dsi_device *dsi,
u16 *brightness);
+void mipi_dsi_dcs_nop_multi(struct mipi_dsi_multi_context *ctx);
+void mipi_dsi_dcs_enter_sleep_mode_multi(struct mipi_dsi_multi_context *ctx);
+void mipi_dsi_dcs_exit_sleep_mode_multi(struct mipi_dsi_multi_context *ctx);
+void mipi_dsi_dcs_set_display_off_multi(struct mipi_dsi_multi_context *ctx);
+void mipi_dsi_dcs_set_display_on_multi(struct mipi_dsi_multi_context *ctx);
+void mipi_dsi_dcs_set_tear_on_multi(struct mipi_dsi_multi_context *ctx,
+ enum mipi_dsi_dcs_tear_mode mode);
+
/**
* mipi_dsi_generic_write_seq - transmit data using a generic write packet
+ *
+ * This macro will print errors for you and will RETURN FROM THE CALLING
+ * FUNCTION (yes this is non-intuitive) upon error.
+ *
+ * Because of the non-intuitive return behavior, THIS MACRO IS DEPRECATED.
+ * Please replace calls of it with mipi_dsi_generic_write_seq_multi().
+ *
* @dsi: DSI peripheral device
* @seq: buffer containing the payload
*/
#define mipi_dsi_generic_write_seq(dsi, seq...) \
do { \
static const u8 d[] = { seq }; \
- struct device *dev = &dsi->dev; \
int ret; \
- ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d)); \
- if (ret < 0) { \
- dev_err_ratelimited(dev, "transmit data failed: %d\n", \
- ret); \
+ ret = mipi_dsi_generic_write_chatty(dsi, d, ARRAY_SIZE(d)); \
+ if (ret < 0) \
return ret; \
- } \
+ } while (0)
+
+/**
+ * mipi_dsi_generic_write_seq_multi - transmit data using a generic write packet
+ *
+ * This macro will print errors for you and error handling is optimized for
+ * callers that call this multiple times in a row.
+ *
+ * @ctx: Context for multiple DSI transactions
+ * @seq: buffer containing the payload
+ */
+#define mipi_dsi_generic_write_seq_multi(ctx, seq...) \
+ do { \
+ static const u8 d[] = { seq }; \
+ mipi_dsi_generic_write_multi(ctx, d, ARRAY_SIZE(d)); \
} while (0)
/**
* mipi_dsi_dcs_write_seq - transmit a DCS command with payload
+ *
+ * This macro will print errors for you and will RETURN FROM THE CALLING
+ * FUNCTION (yes this is non-intuitive) upon error.
+ *
+ * Because of the non-intuitive return behavior, THIS MACRO IS DEPRECATED.
+ * Please replace calls of it with mipi_dsi_dcs_write_seq_multi().
+ *
* @dsi: DSI peripheral device
* @cmd: Command
* @seq: buffer containing data to be transmitted
*/
-#define mipi_dsi_dcs_write_seq(dsi, cmd, seq...) \
- do { \
- static const u8 d[] = { cmd, seq }; \
- struct device *dev = &dsi->dev; \
- int ret; \
- ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
- if (ret < 0) { \
- dev_err_ratelimited( \
- dev, "sending command %#02x failed: %d\n", \
- cmd, ret); \
- return ret; \
- } \
+#define mipi_dsi_dcs_write_seq(dsi, cmd, seq...) \
+ do { \
+ static const u8 d[] = { cmd, seq }; \
+ int ret; \
+ ret = mipi_dsi_dcs_write_buffer_chatty(dsi, d, ARRAY_SIZE(d)); \
+ if (ret < 0) \
+ return ret; \
+ } while (0)
+
+/**
+ * mipi_dsi_dcs_write_seq_multi - transmit a DCS command with payload
+ *
+ * This macro will print errors for you and error handling is optimized for
+ * callers that call this multiple times in a row.
+ *
+ * @ctx: Context for multiple DSI transactions
+ * @cmd: Command
+ * @seq: buffer containing data to be transmitted
+ */
+#define mipi_dsi_dcs_write_seq_multi(ctx, cmd, seq...) \
+ do { \
+ static const u8 d[] = { cmd, seq }; \
+ mipi_dsi_dcs_write_buffer_multi(ctx, d, ARRAY_SIZE(d)); \
} while (0)
/**
diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
index 8de3c9a5f61b..ab0f167474b1 100644
--- a/include/drm/drm_mode_config.h
+++ b/include/drm/drm_mode_config.h
@@ -106,8 +106,8 @@ struct drm_mode_config_funcs {
* Drivers implementing fbdev emulation use drm_kms_helper_hotplug_event()
* to call this hook to inform the fbdev helper of output changes.
*
- * This hook is deprecated, drivers should instead use
- * drm_fbdev_generic_setup() which takes care of any necessary
+ * This hook is deprecated, drivers should instead implement fbdev
+ * support with struct drm_client, which takes care of any necessary
* hotplug event forwarding already without further involvement by
* the driver.
*/
diff --git a/include/linux/dma-fence-array.h b/include/linux/dma-fence-array.h
index ec7f25def392..29c5650c1038 100644
--- a/include/linux/dma-fence-array.h
+++ b/include/linux/dma-fence-array.h
@@ -33,6 +33,7 @@ struct dma_fence_array_cb {
* @num_pending: fences in the array still pending
* @fences: array of the fences
* @work: internal irq_work function
+ * @callbacks: array of callback helpers
*/
struct dma_fence_array {
struct dma_fence base;
@@ -43,6 +44,8 @@ struct dma_fence_array {
struct dma_fence **fences;
struct irq_work work;
+
+ struct dma_fence_array_cb callbacks[] __counted_by(num_fences);
};
/**
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 0f0834939b6a..db7d97b10964 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -225,6 +225,7 @@ struct fb_deferred_io {
struct mutex lock; /* mutex that protects the pageref list */
struct list_head pagereflist; /* list of pagerefs for touched pages */
/* callback */
+ struct page *(*get_page)(struct fb_info *info, unsigned long offset);
void (*deferred_io)(struct fb_info *info, struct list_head *pagelist);
};
#endif
diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h
index 96e32dafd4f0..d5ebafacdd70 100644
--- a/include/uapi/drm/amdgpu_drm.h
+++ b/include/uapi/drm/amdgpu_drm.h
@@ -1269,6 +1269,15 @@ struct drm_amdgpu_info_gpuvm_fault {
#define AMDGPU_FAMILY_GC_10_3_7 151 /* GC 10.3.7 */
#define AMDGPU_FAMILY_GC_11_5_0 150 /* GC 11.5.0 */
+/* FIXME wrong namespace! */
+struct drm_color_ctm_3x4 {
+ /*
+ * Conversion matrix with 3x4 dimensions in S31.32 sign-magnitude
+ * (not two's complement!) format.
+ */
+ __u64 matrix[12];
+};
+
#if defined(__cplusplus)
}
#endif
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index 1ca5c7e418fd..d390011b89b4 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -846,14 +846,6 @@ struct drm_color_ctm {
__u64 matrix[9];
};
-struct drm_color_ctm_3x4 {
- /*
- * Conversion matrix with 3x4 dimensions in S31.32 sign-magnitude
- * (not two's complement!) format.
- */
- __u64 matrix[12];
-};
-
struct drm_color_lut {
/*
* Values are mapped linearly to 0.0 - 1.0 range, with 0x0 == 0.0 and
diff --git a/include/uapi/drm/ivpu_accel.h b/include/uapi/drm/ivpu_accel.h
index 19a13468eca5..084fb529e1e9 100644
--- a/include/uapi/drm/ivpu_accel.h
+++ b/include/uapi/drm/ivpu_accel.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
/*
- * Copyright (C) 2020-2023 Intel Corporation
+ * Copyright (C) 2020-2024 Intel Corporation
*/
#ifndef __UAPI_IVPU_DRM_H__
@@ -21,6 +21,10 @@ extern "C" {
#define DRM_IVPU_BO_INFO 0x03
#define DRM_IVPU_SUBMIT 0x05
#define DRM_IVPU_BO_WAIT 0x06
+#define DRM_IVPU_METRIC_STREAMER_START 0x07
+#define DRM_IVPU_METRIC_STREAMER_STOP 0x08
+#define DRM_IVPU_METRIC_STREAMER_GET_DATA 0x09
+#define DRM_IVPU_METRIC_STREAMER_GET_INFO 0x0a
#define DRM_IOCTL_IVPU_GET_PARAM \
DRM_IOWR(DRM_COMMAND_BASE + DRM_IVPU_GET_PARAM, struct drm_ivpu_param)
@@ -40,6 +44,22 @@ extern "C" {
#define DRM_IOCTL_IVPU_BO_WAIT \
DRM_IOWR(DRM_COMMAND_BASE + DRM_IVPU_BO_WAIT, struct drm_ivpu_bo_wait)
+#define DRM_IOCTL_IVPU_METRIC_STREAMER_START \
+ DRM_IOWR(DRM_COMMAND_BASE + DRM_IVPU_METRIC_STREAMER_START, \
+ struct drm_ivpu_metric_streamer_start)
+
+#define DRM_IOCTL_IVPU_METRIC_STREAMER_STOP \
+ DRM_IOW(DRM_COMMAND_BASE + DRM_IVPU_METRIC_STREAMER_STOP, \
+ struct drm_ivpu_metric_streamer_stop)
+
+#define DRM_IOCTL_IVPU_METRIC_STREAMER_GET_DATA \
+ DRM_IOWR(DRM_COMMAND_BASE + DRM_IVPU_METRIC_STREAMER_GET_DATA, \
+ struct drm_ivpu_metric_streamer_get_data)
+
+#define DRM_IOCTL_IVPU_METRIC_STREAMER_GET_INFO \
+ DRM_IOWR(DRM_COMMAND_BASE + DRM_IVPU_METRIC_STREAMER_GET_INFO, \
+ struct drm_ivpu_metric_streamer_get_data)
+
/**
* DOC: contexts
*
@@ -336,6 +356,53 @@ struct drm_ivpu_bo_wait {
__u32 pad;
};
+/**
+ * struct drm_ivpu_metric_streamer_start - Start collecting metric data
+ */
+struct drm_ivpu_metric_streamer_start {
+ /** @metric_group_mask: Indicates metric streamer instance */
+ __u64 metric_group_mask;
+ /** @sampling_period_ns: Sampling period in nanoseconds */
+ __u64 sampling_period_ns;
+ /**
+ * @read_period_samples:
+ *
+ * Number of samples after which user space will try to read the data.
+ * Reading the data after significantly longer period may cause data loss.
+ */
+ __u32 read_period_samples;
+ /** @sample_size: Returned size of a single sample in bytes */
+ __u32 sample_size;
+ /** @max_data_size: Returned max @data_size from %DRM_IOCTL_IVPU_METRIC_STREAMER_GET_DATA */
+ __u32 max_data_size;
+};
+
+/**
+ * struct drm_ivpu_metric_streamer_get_data - Copy collected metric data
+ */
+struct drm_ivpu_metric_streamer_get_data {
+ /** @metric_group_mask: Indicates metric streamer instance */
+ __u64 metric_group_mask;
+ /** @buffer_ptr: A pointer to a destination for the copied data */
+ __u64 buffer_ptr;
+ /** @buffer_size: Size of the destination buffer */
+ __u64 buffer_size;
+ /**
+ * @data_size: Returned size of copied metric data
+ *
+ * If the @buffer_size is zero, returns the amount of data ready to be copied.
+ */
+ __u64 data_size;
+};
+
+/**
+ * struct drm_ivpu_metric_streamer_stop - Stop collecting metric data
+ */
+struct drm_ivpu_metric_streamer_stop {
+ /** @metric_group_mask: Indicates metric streamer instance */
+ __u64 metric_group_mask;
+};
+
#if defined(__cplusplus)
}
#endif
diff --git a/include/uapi/drm/v3d_drm.h b/include/uapi/drm/v3d_drm.h
index dce1835eced4..87fc5bb0a61e 100644
--- a/include/uapi/drm/v3d_drm.h
+++ b/include/uapi/drm/v3d_drm.h
@@ -42,6 +42,7 @@ extern "C" {
#define DRM_V3D_PERFMON_DESTROY 0x09
#define DRM_V3D_PERFMON_GET_VALUES 0x0a
#define DRM_V3D_SUBMIT_CPU 0x0b
+#define DRM_V3D_PERFMON_GET_COUNTER 0x0c
#define DRM_IOCTL_V3D_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CL, struct drm_v3d_submit_cl)
#define DRM_IOCTL_V3D_WAIT_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_WAIT_BO, struct drm_v3d_wait_bo)
@@ -58,6 +59,8 @@ extern "C" {
#define DRM_IOCTL_V3D_PERFMON_GET_VALUES DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_PERFMON_GET_VALUES, \
struct drm_v3d_perfmon_get_values)
#define DRM_IOCTL_V3D_SUBMIT_CPU DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CPU, struct drm_v3d_submit_cpu)
+#define DRM_IOCTL_V3D_PERFMON_GET_COUNTER DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_PERFMON_GET_COUNTER, \
+ struct drm_v3d_perfmon_get_counter)
#define DRM_V3D_SUBMIT_CL_FLUSH_CACHE 0x01
#define DRM_V3D_SUBMIT_EXTENSION 0x02
@@ -286,6 +289,7 @@ enum drm_v3d_param {
DRM_V3D_PARAM_SUPPORTS_PERFMON,
DRM_V3D_PARAM_SUPPORTS_MULTISYNC_EXT,
DRM_V3D_PARAM_SUPPORTS_CPU_QUEUE,
+ DRM_V3D_PARAM_MAX_PERF_COUNTERS,
};
struct drm_v3d_get_param {
@@ -599,6 +603,16 @@ struct drm_v3d_submit_cpu {
__u64 extensions;
};
+/* The performance counters index represented by this enum are deprecated and
+ * must no longer be used. These counters are only valid for V3D 4.2.
+ *
+ * In order to check for performance counter information,
+ * use DRM_IOCTL_V3D_PERFMON_GET_COUNTER.
+ *
+ * Don't use V3D_PERFCNT_NUM to retrieve the maximum number of performance
+ * counters. You should use DRM_IOCTL_V3D_GET_PARAM with the following
+ * parameter: DRM_V3D_PARAM_MAX_PERF_COUNTERS.
+ */
enum {
V3D_PERFCNT_FEP_VALID_PRIMTS_NO_PIXELS,
V3D_PERFCNT_FEP_VALID_PRIMS,
@@ -717,6 +731,40 @@ struct drm_v3d_perfmon_get_values {
__u64 values_ptr;
};
+#define DRM_V3D_PERFCNT_MAX_NAME 64
+#define DRM_V3D_PERFCNT_MAX_CATEGORY 32
+#define DRM_V3D_PERFCNT_MAX_DESCRIPTION 256
+
+/**
+ * struct drm_v3d_perfmon_get_counter - ioctl to get the description of a
+ * performance counter
+ *
+ * As userspace needs to retrieve information about the performance counters
+ * available, this IOCTL allows users to get information about a performance
+ * counter (name, category and description).
+ */
+struct drm_v3d_perfmon_get_counter {
+ /*
+ * Counter ID
+ *
+ * Must be smaller than the maximum number of performance counters, which
+ * can be retrieve through DRM_V3D_PARAM_MAX_PERF_COUNTERS.
+ */
+ __u8 counter;
+
+ /* Name of the counter */
+ __u8 name[DRM_V3D_PERFCNT_MAX_NAME];
+
+ /* Category of the counter */
+ __u8 category[DRM_V3D_PERFCNT_MAX_CATEGORY];
+
+ /* Description of the counter */
+ __u8 description[DRM_V3D_PERFCNT_MAX_DESCRIPTION];
+
+ /* mbz */
+ __u8 reserved[7];
+};
+
#if defined(__cplusplus)
}
#endif
diff --git a/lib/fonts/Kconfig b/lib/fonts/Kconfig
index 7e945fdcbf11..befcb463f738 100644
--- a/lib/fonts/Kconfig
+++ b/lib/fonts/Kconfig
@@ -10,7 +10,7 @@ if FONT_SUPPORT
config FONTS
bool "Select compiled-in fonts"
- depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
+ depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE || DRM_PANIC
help
Say Y here if you would like to use fonts other than the default
your frame buffer console usually use.
@@ -23,7 +23,7 @@ config FONTS
config FONT_8x8
bool "VGA 8x8 font" if FONTS
- depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
+ depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE || DRM_PANIC
default y if !SPARC && !FONTS
help
This is the "high resolution" font for the VGA frame buffer (the one
@@ -46,7 +46,7 @@ config FONT_8x16
config FONT_6x11
bool "Mac console 6x11 font (not supported by all drivers)" if FONTS
- depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
+ depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE || DRM_PANIC
default y if !SPARC && !FONTS && MAC
help
Small console font with Macintosh-style high-half glyphs. Some Mac
@@ -54,7 +54,7 @@ config FONT_6x11
config FONT_7x14
bool "console 7x14 font (not supported by all drivers)" if FONTS
- depends on FRAMEBUFFER_CONSOLE
+ depends on FRAMEBUFFER_CONSOLE || DRM_PANIC
help
Console font with characters just a bit smaller than the default.
If the standard 8x16 font is a little too big for you, say Y.
@@ -62,7 +62,7 @@ config FONT_7x14
config FONT_PEARL_8x8
bool "Pearl (old m68k) console 8x8 font" if FONTS
- depends on FRAMEBUFFER_CONSOLE
+ depends on FRAMEBUFFER_CONSOLE || DRM_PANIC
default y if !SPARC && !FONTS && AMIGA
help
Small console font with PC-style control-character and high-half
@@ -70,7 +70,7 @@ config FONT_PEARL_8x8
config FONT_ACORN_8x8
bool "Acorn console 8x8 font" if FONTS
- depends on FRAMEBUFFER_CONSOLE
+ depends on FRAMEBUFFER_CONSOLE || DRM_PANIC
default y if !SPARC && !FONTS && ARM && ARCH_ACORN
help
Small console font with PC-style control characters and high-half
@@ -90,7 +90,7 @@ config FONT_6x10
config FONT_10x18
bool "console 10x18 font (not supported by all drivers)" if FONTS
- depends on FRAMEBUFFER_CONSOLE
+ depends on FRAMEBUFFER_CONSOLE || DRM_PANIC
help
This is a high resolution console font for machines with very
big letters. It fits between the sun 12x22 and the normal 8x16 font.
@@ -105,7 +105,7 @@ config FONT_SUN8x16
config FONT_SUN12x22
bool "Sparc console 12x22 font (not supported by all drivers)"
- depends on FRAMEBUFFER_CONSOLE && (!SPARC && FONTS || SPARC)
+ depends on (FRAMEBUFFER_CONSOLE && (!SPARC && FONTS || SPARC)) || DRM_PANIC
help
This is the high resolution console font for Sun machines with very
big letters (like the letters used in the SPARC PROM). If the
@@ -113,7 +113,7 @@ config FONT_SUN12x22
config FONT_TER16x32
bool "Terminus 16x32 font (not supported by all drivers)"
- depends on FRAMEBUFFER_CONSOLE && (!SPARC && FONTS || SPARC)
+ depends on (FRAMEBUFFER_CONSOLE && (!SPARC && FONTS || SPARC)) || DRM_PANIC
help
Terminus Font is a clean, fixed width bitmap font, designed
for long (8 and more hours per day) work with computers.
@@ -122,7 +122,7 @@ config FONT_TER16x32
config FONT_6x8
bool "OLED 6x8 font" if FONTS
- depends on FRAMEBUFFER_CONSOLE
+ depends on FRAMEBUFFER_CONSOLE || DRM_PANIC
help
This font is useful for small displays (OLED).