aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/display/bridge/ti,ths813x.txt (renamed from Documentation/devicetree/bindings/display/bridge/ti,ths8135.txt)13
-rw-r--r--Documentation/devicetree/bindings/display/panel/arm,versatile-tft-panel.txt31
-rw-r--r--Documentation/devicetree/bindings/display/st,stm32-ltdc.txt2
-rw-r--r--MAINTAINERS9
-rw-r--r--drivers/dma-buf/reservation.c31
-rw-r--r--drivers/dma-buf/sw_sync.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c2
-rw-r--r--drivers/gpu/drm/arc/arcpgu_hdmi.c3
-rw-r--r--drivers/gpu/drm/arc/arcpgu_sim.c16
-rw-r--r--drivers/gpu/drm/arm/hdlcd_crtc.c5
-rw-r--r--drivers/gpu/drm/arm/malidp_planes.c6
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c24
-rw-r--r--drivers/gpu/drm/bridge/analogix-anx78xx.c3
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix_dp_core.c6
-rw-r--r--drivers/gpu/drm/bridge/dumb-vga-dac.c59
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c200
-rw-r--r--drivers/gpu/drm/drm_atomic.c6
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c15
-rw-r--r--drivers/gpu/drm/drm_connector.c9
-rw-r--r--drivers/gpu/drm/drm_crtc.c6
-rw-r--r--drivers/gpu/drm/drm_debugfs_crc.c19
-rw-r--r--drivers/gpu/drm/drm_dp_helper.c4
-rw-r--r--drivers/gpu/drm/drm_dp_mst_topology.c3
-rw-r--r--drivers/gpu/drm/drm_edid.c4
-rw-r--r--drivers/gpu/drm/drm_encoder.c4
-rw-r--r--drivers/gpu/drm/drm_fourcc.c50
-rw-r--r--drivers/gpu/drm/drm_ioctl.c6
-rw-r--r--drivers/gpu/drm/drm_memory.c13
-rw-r--r--drivers/gpu/drm/drm_mipi_dsi.c9
-rw-r--r--drivers/gpu/drm/drm_modes.c62
-rw-r--r--drivers/gpu/drm/drm_plane.c4
-rw-r--r--drivers/gpu/drm/drm_prime.c141
-rw-r--r--drivers/gpu/drm/drm_probe_helper.c2
-rw-r--r--drivers/gpu/drm/drm_simple_kms_helper.c5
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c14
-rw-r--r--drivers/gpu/drm/i2c/sil164_drv.c3
-rw-r--r--drivers/gpu/drm/i2c/tda998x_drv.c3
-rw-r--r--drivers/gpu/drm/i915/intel_atomic_plane.c8
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c3
-rw-r--r--drivers/gpu/drm/i915/intel_display.c56
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h1
-rw-r--r--drivers/gpu/drm/i915/intel_dsi.c5
-rw-r--r--drivers/gpu/drm/i915/intel_dvo.c3
-rw-r--r--drivers/gpu/drm/i915/intel_fbc.c3
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c3
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c3
-rw-r--r--drivers/gpu/drm/i915/intel_sprite.c8
-rw-r--r--drivers/gpu/drm/imx/ipuv3-plane.c10
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_plane.c5
-rw-r--r--drivers/gpu/drm/meson/meson_plane.c5
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_mode.c4
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c20
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c20
-rw-r--r--drivers/gpu/drm/panel/Kconfig10
-rw-r--r--drivers/gpu/drm/panel/Makefile1
-rw-r--r--drivers/gpu/drm/panel/panel-arm-versatile.c377
-rw-r--r--drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c16
-rw-r--r--drivers/gpu/drm/pl111/Kconfig1
-rw-r--r--drivers/gpu/drm/pl111/pl111_display.c64
-rw-r--r--drivers/gpu/drm/pl111/pl111_drm.h8
-rw-r--r--drivers/gpu/drm/pl111/pl111_drv.c138
-rw-r--r--drivers/gpu/drm/pl111/pl111_versatile.c86
-rw-r--r--drivers/gpu/drm/radeon/radeon.h1
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_ttm.c6
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_plane.c9
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.c22
-rw-r--r--drivers/gpu/drm/stm/drv.c20
-rw-r--r--drivers/gpu/drm/stm/dw_mipi_dsi-stm.c53
-rw-r--r--drivers/gpu/drm/stm/ltdc.c118
-rw-r--r--drivers/gpu/drm/stm/ltdc.h1
-rw-r--r--drivers/gpu/drm/sun4i/Makefile3
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_backend.c248
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_backend.h18
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_crtc.c21
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_drv.c27
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_drv.h1
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_framebuffer.c24
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_frontend.c389
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_frontend.h99
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_layer.c117
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_layer.h11
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_tcon.c4
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_ui_layer.c9
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_vi_layer.c9
-rw-r--r--drivers/gpu/drm/sun4i/sunxi_engine.h90
-rw-r--r--drivers/gpu/drm/tegra/plane.c9
-rw-r--r--drivers/gpu/drm/tinydrm/core/tinydrm-pipe.c34
-rw-r--r--drivers/gpu/drm/tinydrm/ili9225.c6
-rw-r--r--drivers/gpu/drm/tinydrm/mi0283qt.c106
-rw-r--r--drivers/gpu/drm/tinydrm/mipi-dbi.c101
-rw-r--r--drivers/gpu/drm/tinydrm/st7586.c15
-rw-r--r--drivers/gpu/drm/tinydrm/st7735r.c11
-rw-r--r--drivers/gpu/drm/vc4/Makefile1
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.c26
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.h68
-rw-r--r--drivers/gpu/drm/vc4/vc4_gem.c48
-rw-r--r--drivers/gpu/drm/vc4/vc4_irq.c40
-rw-r--r--drivers/gpu/drm/vc4/vc4_perfmon.c188
-rw-r--r--drivers/gpu/drm/vc4/vc4_plane.c23
-rw-r--r--drivers/gpu/drm/vc4/vc4_regs.h35
-rw-r--r--drivers/gpu/drm/vc4/vc4_v3d.c64
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_ioctl.c2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c7
-rw-r--r--drivers/gpu/drm/zte/zx_plane.c18
-rw-r--r--include/drm/bridge/dw_mipi_dsi.h17
-rw-r--r--include/drm/drm_atomic.h9
-rw-r--r--include/drm/drm_bridge.h35
-rw-r--r--include/drm/drm_cache.h2
-rw-r--r--include/drm/drm_dp_helper.h18
-rw-r--r--include/drm/drm_fourcc.h2
-rw-r--r--include/drm/drm_mode_config.h12
-rw-r--r--include/drm/drm_modes.h24
-rw-r--r--include/drm/drm_prime.h22
-rw-r--r--include/drm/tinydrm/ili9341.h54
-rw-r--r--include/drm/tinydrm/mipi-dbi.h5
-rw-r--r--include/uapi/drm/drm_mode.h30
-rw-r--r--include/uapi/drm/vc4_drm.h76
123 files changed, 3251 insertions, 827 deletions
diff --git a/Documentation/devicetree/bindings/display/bridge/ti,ths8135.txt b/Documentation/devicetree/bindings/display/bridge/ti,ths813x.txt
index 6ec1a880ac18..df3d7c1ac09e 100644
--- a/Documentation/devicetree/bindings/display/bridge/ti,ths8135.txt
+++ b/Documentation/devicetree/bindings/display/bridge/ti,ths813x.txt
@@ -1,11 +1,16 @@
1THS8135 Video DAC 1THS8134 and THS8135 Video DAC
2----------------- 2-----------------------------
3 3
4This is the binding for Texas Instruments THS8135 Video DAC bridge. 4This is the binding for Texas Instruments THS8134, THS8134A, THS8134B and
5THS8135 Video DAC bridges.
5 6
6Required properties: 7Required properties:
7 8
8- compatible: Must be "ti,ths8135" 9- compatible: Must be one of
10 "ti,ths8134"
11 "ti,ths8134a," "ti,ths8134"
12 "ti,ths8134b", "ti,ths8134"
13 "ti,ths8135"
9 14
10Required nodes: 15Required nodes:
11 16
diff --git a/Documentation/devicetree/bindings/display/panel/arm,versatile-tft-panel.txt b/Documentation/devicetree/bindings/display/panel/arm,versatile-tft-panel.txt
new file mode 100644
index 000000000000..248141c3c7e3
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/arm,versatile-tft-panel.txt
@@ -0,0 +1,31 @@
1ARM Versatile TFT Panels
2
3These panels are connected to the daughterboards found on the
4ARM Versatile reference designs.
5
6This device node must appear as a child to a "syscon"-compatible
7node.
8
9Required properties:
10- compatible: should be "arm,versatile-tft-panel"
11
12Required subnodes:
13- port: see display/panel/panel-common.txt, graph.txt
14
15
16Example:
17
18sysreg@0 {
19 compatible = "arm,versatile-sysreg", "syscon", "simple-mfd";
20 reg = <0x00000 0x1000>;
21
22 panel: display@0 {
23 compatible = "arm,versatile-tft-panel";
24
25 port {
26 panel_in: endpoint {
27 remote-endpoint = <&foo>;
28 };
29 };
30 };
31};
diff --git a/Documentation/devicetree/bindings/display/st,stm32-ltdc.txt b/Documentation/devicetree/bindings/display/st,stm32-ltdc.txt
index 029252253ad4..3eb1b48b47dd 100644
--- a/Documentation/devicetree/bindings/display/st,stm32-ltdc.txt
+++ b/Documentation/devicetree/bindings/display/st,stm32-ltdc.txt
@@ -98,7 +98,7 @@ Example 2: DSI panel
98 compatible = "st,stm32-dsi"; 98 compatible = "st,stm32-dsi";
99 reg = <0x40016c00 0x800>; 99 reg = <0x40016c00 0x800>;
100 clocks = <&rcc 1 CLK_F469_DSI>, <&clk_hse>; 100 clocks = <&rcc 1 CLK_F469_DSI>, <&clk_hse>;
101 clock-names = "ref", "pclk"; 101 clock-names = "pclk", "ref";
102 resets = <&rcc STM32F4_APB2_RESET(DSI)>; 102 resets = <&rcc STM32F4_APB2_RESET(DSI)>;
103 reset-names = "apb"; 103 reset-names = "apb";
104 104
diff --git a/MAINTAINERS b/MAINTAINERS
index 3bdc260e36b7..2afba909724c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4456,6 +4456,13 @@ T: git git://anongit.freedesktop.org/drm/drm-misc
4456S: Supported 4456S: Supported
4457F: drivers/gpu/drm/pl111/ 4457F: drivers/gpu/drm/pl111/
4458 4458
4459DRM DRIVER FOR ARM VERSATILE TFT PANELS
4460M: Linus Walleij <linus.walleij@linaro.org>
4461T: git git://anongit.freedesktop.org/drm/drm-misc
4462S: Maintained
4463F: drivers/gpu/drm/panel/panel-arm-versatile.c
4464F: Documentation/devicetree/bindings/display/panel/arm,versatile-tft-panel.txt
4465
4459DRM DRIVER FOR AST SERVER GRAPHICS CHIPS 4466DRM DRIVER FOR AST SERVER GRAPHICS CHIPS
4460M: Dave Airlie <airlied@redhat.com> 4467M: Dave Airlie <airlied@redhat.com>
4461S: Odd Fixes 4468S: Odd Fixes
@@ -4610,8 +4617,8 @@ F: include/uapi/drm/
4610F: include/linux/vga* 4617F: include/linux/vga*
4611 4618
4612DRM DRIVERS AND MISC GPU PATCHES 4619DRM DRIVERS AND MISC GPU PATCHES
4613M: Daniel Vetter <daniel.vetter@intel.com>
4614M: Gustavo Padovan <gustavo@padovan.org> 4620M: Gustavo Padovan <gustavo@padovan.org>
4621M: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
4615M: Sean Paul <seanpaul@chromium.org> 4622M: Sean Paul <seanpaul@chromium.org>
4616W: https://01.org/linuxgraphics/gfx-docs/maintainer-tools/drm-misc.html 4623W: https://01.org/linuxgraphics/gfx-docs/maintainer-tools/drm-misc.html
4617S: Maintained 4624S: Maintained
diff --git a/drivers/dma-buf/reservation.c b/drivers/dma-buf/reservation.c
index 04ebe2204c12..314eb1071cce 100644
--- a/drivers/dma-buf/reservation.c
+++ b/drivers/dma-buf/reservation.c
@@ -374,8 +374,9 @@ EXPORT_SYMBOL(reservation_object_copy_fences);
374 * @pshared: the array of shared fence ptrs returned (array is krealloc'd to 374 * @pshared: the array of shared fence ptrs returned (array is krealloc'd to
375 * the required size, and must be freed by caller) 375 * the required size, and must be freed by caller)
376 * 376 *
377 * RETURNS 377 * Retrieve all fences from the reservation object. If the pointer for the
378 * Zero or -errno 378 * exclusive fence is not specified the fence is put into the array of the
379 * shared fences as well. Returns either zero or -ENOMEM.
379 */ 380 */
380int reservation_object_get_fences_rcu(struct reservation_object *obj, 381int reservation_object_get_fences_rcu(struct reservation_object *obj,
381 struct dma_fence **pfence_excl, 382 struct dma_fence **pfence_excl,
@@ -389,8 +390,8 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
389 390
390 do { 391 do {
391 struct reservation_object_list *fobj; 392 struct reservation_object_list *fobj;
392 unsigned seq; 393 unsigned int i, seq;
393 unsigned int i; 394 size_t sz = 0;
394 395
395 shared_count = i = 0; 396 shared_count = i = 0;
396 397
@@ -402,9 +403,14 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
402 goto unlock; 403 goto unlock;
403 404
404 fobj = rcu_dereference(obj->fence); 405 fobj = rcu_dereference(obj->fence);
405 if (fobj) { 406 if (fobj)
407 sz += sizeof(*shared) * fobj->shared_max;
408
409 if (!pfence_excl && fence_excl)
410 sz += sizeof(*shared);
411
412 if (sz) {
406 struct dma_fence **nshared; 413 struct dma_fence **nshared;
407 size_t sz = sizeof(*shared) * fobj->shared_max;
408 414
409 nshared = krealloc(shared, sz, 415 nshared = krealloc(shared, sz,
410 GFP_NOWAIT | __GFP_NOWARN); 416 GFP_NOWAIT | __GFP_NOWARN);
@@ -420,13 +426,19 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
420 break; 426 break;
421 } 427 }
422 shared = nshared; 428 shared = nshared;
423 shared_count = fobj->shared_count; 429 shared_count = fobj ? fobj->shared_count : 0;
424
425 for (i = 0; i < shared_count; ++i) { 430 for (i = 0; i < shared_count; ++i) {
426 shared[i] = rcu_dereference(fobj->shared[i]); 431 shared[i] = rcu_dereference(fobj->shared[i]);
427 if (!dma_fence_get_rcu(shared[i])) 432 if (!dma_fence_get_rcu(shared[i]))
428 break; 433 break;
429 } 434 }
435
436 if (!pfence_excl && fence_excl) {
437 shared[i] = fence_excl;
438 fence_excl = NULL;
439 ++i;
440 ++shared_count;
441 }
430 } 442 }
431 443
432 if (i != shared_count || read_seqcount_retry(&obj->seq, seq)) { 444 if (i != shared_count || read_seqcount_retry(&obj->seq, seq)) {
@@ -448,7 +460,8 @@ unlock:
448 460
449 *pshared_count = shared_count; 461 *pshared_count = shared_count;
450 *pshared = shared; 462 *pshared = shared;
451 *pfence_excl = fence_excl; 463 if (pfence_excl)
464 *pfence_excl = fence_excl;
452 465
453 return ret; 466 return ret;
454} 467}
diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c
index 24f83f9eeaed..7779bdbd18d1 100644
--- a/drivers/dma-buf/sw_sync.c
+++ b/drivers/dma-buf/sw_sync.c
@@ -43,14 +43,14 @@
43 * timelines. 43 * timelines.
44 * 44 *
45 * Fences can be created with SW_SYNC_IOC_CREATE_FENCE ioctl with struct 45 * Fences can be created with SW_SYNC_IOC_CREATE_FENCE ioctl with struct
46 * sw_sync_ioctl_create_fence as parameter. 46 * sw_sync_create_fence_data as parameter.
47 * 47 *
48 * To increment the timeline counter, SW_SYNC_IOC_INC ioctl should be used 48 * To increment the timeline counter, SW_SYNC_IOC_INC ioctl should be used
49 * with the increment as u32. This will update the last signaled value 49 * with the increment as u32. This will update the last signaled value
50 * from the timeline and signal any fence that has a seqno smaller or equal 50 * from the timeline and signal any fence that has a seqno smaller or equal
51 * to it. 51 * to it.
52 * 52 *
53 * struct sw_sync_ioctl_create_fence 53 * struct sw_sync_create_fence_data
54 * @value: the seqno to initialise the fence with 54 * @value: the seqno to initialise the fence with
55 * @name: the name of the new sync point 55 * @name: the name of the new sync point
56 * @fence: return the fd of the new sync_file with the created fence 56 * @fence: return the fd of the new sync_file with the created fence
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index d5a2eefd6c3e..31126df06c8c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -1504,6 +1504,7 @@ struct amdgpu_device {
1504 const struct amdgpu_asic_funcs *asic_funcs; 1504 const struct amdgpu_asic_funcs *asic_funcs;
1505 bool shutdown; 1505 bool shutdown;
1506 bool need_dma32; 1506 bool need_dma32;
1507 bool need_swiotlb;
1507 bool accel_working; 1508 bool accel_working;
1508 struct work_struct reset_work; 1509 struct work_struct reset_work;
1509 struct notifier_block acpi_nb; 1510 struct notifier_block acpi_nb;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index e4bb435e614b..d897c4c61a01 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -1018,7 +1018,7 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm,
1018 } 1018 }
1019 1019
1020#ifdef CONFIG_SWIOTLB 1020#ifdef CONFIG_SWIOTLB
1021 if (swiotlb_nr_tbl()) { 1021 if (adev->need_swiotlb && swiotlb_nr_tbl()) {
1022 return ttm_dma_populate(&gtt->ttm, adev->dev, ctx); 1022 return ttm_dma_populate(&gtt->ttm, adev->dev, ctx);
1023 } 1023 }
1024#endif 1024#endif
@@ -1045,7 +1045,7 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm)
1045 adev = amdgpu_ttm_adev(ttm->bdev); 1045 adev = amdgpu_ttm_adev(ttm->bdev);
1046 1046
1047#ifdef CONFIG_SWIOTLB 1047#ifdef CONFIG_SWIOTLB
1048 if (swiotlb_nr_tbl()) { 1048 if (adev->need_swiotlb && swiotlb_nr_tbl()) {
1049 ttm_dma_unpopulate(&gtt->ttm, adev->dev); 1049 ttm_dma_unpopulate(&gtt->ttm, adev->dev);
1050 return; 1050 return;
1051 } 1051 }
@@ -2010,7 +2010,7 @@ static int amdgpu_ttm_debugfs_init(struct amdgpu_device *adev)
2010 count = ARRAY_SIZE(amdgpu_ttm_debugfs_list); 2010 count = ARRAY_SIZE(amdgpu_ttm_debugfs_list);
2011 2011
2012#ifdef CONFIG_SWIOTLB 2012#ifdef CONFIG_SWIOTLB
2013 if (!swiotlb_nr_tbl()) 2013 if (!(adev->need_swiotlb && swiotlb_nr_tbl()))
2014 --count; 2014 --count;
2015#endif 2015#endif
2016 2016
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
index 8e28270d1ea9..5f5eb15ccf4a 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
@@ -22,6 +22,7 @@
22 */ 22 */
23#include <linux/firmware.h> 23#include <linux/firmware.h>
24#include <drm/drmP.h> 24#include <drm/drmP.h>
25#include <drm/drm_cache.h>
25#include "amdgpu.h" 26#include "amdgpu.h"
26#include "gmc_v6_0.h" 27#include "gmc_v6_0.h"
27#include "amdgpu_ucode.h" 28#include "amdgpu_ucode.h"
@@ -851,6 +852,7 @@ static int gmc_v6_0_sw_init(void *handle)
851 pci_set_consistent_dma_mask(adev->pdev, DMA_BIT_MASK(32)); 852 pci_set_consistent_dma_mask(adev->pdev, DMA_BIT_MASK(32));
852 dev_warn(adev->dev, "amdgpu: No coherent DMA available.\n"); 853 dev_warn(adev->dev, "amdgpu: No coherent DMA available.\n");
853 } 854 }
855 adev->need_swiotlb = drm_get_max_iomem() > ((u64)1 << dma_bits);
854 856
855 r = gmc_v6_0_init_microcode(adev); 857 r = gmc_v6_0_init_microcode(adev);
856 if (r) { 858 if (r) {
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
index 86e9d682c59e..12e49bd8fd2d 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
@@ -22,6 +22,7 @@
22 */ 22 */
23#include <linux/firmware.h> 23#include <linux/firmware.h>
24#include <drm/drmP.h> 24#include <drm/drmP.h>
25#include <drm/drm_cache.h>
25#include "amdgpu.h" 26#include "amdgpu.h"
26#include "cikd.h" 27#include "cikd.h"
27#include "cik.h" 28#include "cik.h"
@@ -999,6 +1000,7 @@ static int gmc_v7_0_sw_init(void *handle)
999 pci_set_consistent_dma_mask(adev->pdev, DMA_BIT_MASK(32)); 1000 pci_set_consistent_dma_mask(adev->pdev, DMA_BIT_MASK(32));
1000 pr_warn("amdgpu: No coherent DMA available\n"); 1001 pr_warn("amdgpu: No coherent DMA available\n");
1001 } 1002 }
1003 adev->need_swiotlb = drm_get_max_iomem() > ((u64)1 << dma_bits);
1002 1004
1003 r = gmc_v7_0_init_microcode(adev); 1005 r = gmc_v7_0_init_microcode(adev);
1004 if (r) { 1006 if (r) {
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
index 9a813d834f1a..9a170e37fbe7 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
@@ -22,6 +22,7 @@
22 */ 22 */
23#include <linux/firmware.h> 23#include <linux/firmware.h>
24#include <drm/drmP.h> 24#include <drm/drmP.h>
25#include <drm/drm_cache.h>
25#include "amdgpu.h" 26#include "amdgpu.h"
26#include "gmc_v8_0.h" 27#include "gmc_v8_0.h"
27#include "amdgpu_ucode.h" 28#include "amdgpu_ucode.h"
@@ -1085,6 +1086,7 @@ static int gmc_v8_0_sw_init(void *handle)
1085 */ 1086 */
1086 adev->need_dma32 = false; 1087 adev->need_dma32 = false;
1087 dma_bits = adev->need_dma32 ? 32 : 40; 1088 dma_bits = adev->need_dma32 ? 32 : 40;
1089 adev->need_swiotlb = drm_get_max_iomem() > ((u64)1 << dma_bits);
1088 r = pci_set_dma_mask(adev->pdev, DMA_BIT_MASK(dma_bits)); 1090 r = pci_set_dma_mask(adev->pdev, DMA_BIT_MASK(dma_bits));
1089 if (r) { 1091 if (r) {
1090 adev->need_dma32 = true; 1092 adev->need_dma32 = true;
@@ -1096,6 +1098,7 @@ static int gmc_v8_0_sw_init(void *handle)
1096 pci_set_consistent_dma_mask(adev->pdev, DMA_BIT_MASK(32)); 1098 pci_set_consistent_dma_mask(adev->pdev, DMA_BIT_MASK(32));
1097 pr_warn("amdgpu: No coherent DMA available\n"); 1099 pr_warn("amdgpu: No coherent DMA available\n");
1098 } 1100 }
1101 adev->need_swiotlb = drm_get_max_iomem() > ((u64)1 << dma_bits);
1099 1102
1100 r = gmc_v8_0_init_microcode(adev); 1103 r = gmc_v8_0_init_microcode(adev);
1101 if (r) { 1104 if (r) {
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
index 2719937e09d6..100ec69f020a 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
@@ -21,6 +21,7 @@
21 * 21 *
22 */ 22 */
23#include <linux/firmware.h> 23#include <linux/firmware.h>
24#include <drm/drm_cache.h>
24#include "amdgpu.h" 25#include "amdgpu.h"
25#include "gmc_v9_0.h" 26#include "gmc_v9_0.h"
26#include "amdgpu_atomfirmware.h" 27#include "amdgpu_atomfirmware.h"
@@ -852,6 +853,7 @@ static int gmc_v9_0_sw_init(void *handle)
852 pci_set_consistent_dma_mask(adev->pdev, DMA_BIT_MASK(32)); 853 pci_set_consistent_dma_mask(adev->pdev, DMA_BIT_MASK(32));
853 printk(KERN_WARNING "amdgpu: No coherent DMA available.\n"); 854 printk(KERN_WARNING "amdgpu: No coherent DMA available.\n");
854 } 855 }
856 adev->need_swiotlb = drm_get_max_iomem() > ((u64)1 << dma_bits);
855 857
856 r = gmc_v9_0_mc_init(adev); 858 r = gmc_v9_0_mc_init(adev);
857 if (r) 859 if (r)
diff --git a/drivers/gpu/drm/arc/arcpgu_hdmi.c b/drivers/gpu/drm/arc/arcpgu_hdmi.c
index 0ce7f398bcff..977dfa55162f 100644
--- a/drivers/gpu/drm/arc/arcpgu_hdmi.c
+++ b/drivers/gpu/drm/arc/arcpgu_hdmi.c
@@ -15,7 +15,8 @@
15 */ 15 */
16 16
17#include <drm/drm_crtc.h> 17#include <drm/drm_crtc.h>
18#include <drm/drm_encoder_slave.h> 18#include <drm/drm_encoder.h>
19#include <drm/drm_device.h>
19 20
20#include "arcpgu.h" 21#include "arcpgu.h"
21 22
diff --git a/drivers/gpu/drm/arc/arcpgu_sim.c b/drivers/gpu/drm/arc/arcpgu_sim.c
index bca3a678c955..b8f6f9a5dfbe 100644
--- a/drivers/gpu/drm/arc/arcpgu_sim.c
+++ b/drivers/gpu/drm/arc/arcpgu_sim.c
@@ -15,7 +15,6 @@
15 */ 15 */
16 16
17#include <drm/drm_crtc_helper.h> 17#include <drm/drm_crtc_helper.h>
18#include <drm/drm_encoder_slave.h>
19#include <drm/drm_atomic_helper.h> 18#include <drm/drm_atomic_helper.h>
20 19
21#include "arcpgu.h" 20#include "arcpgu.h"
@@ -29,7 +28,6 @@
29 28
30struct arcpgu_drm_connector { 29struct arcpgu_drm_connector {
31 struct drm_connector connector; 30 struct drm_connector connector;
32 struct drm_encoder_slave *encoder_slave;
33}; 31};
34 32
35static int arcpgu_drm_connector_get_modes(struct drm_connector *connector) 33static int arcpgu_drm_connector_get_modes(struct drm_connector *connector)
@@ -68,7 +66,7 @@ static struct drm_encoder_funcs arcpgu_drm_encoder_funcs = {
68int arcpgu_drm_sim_init(struct drm_device *drm, struct device_node *np) 66int arcpgu_drm_sim_init(struct drm_device *drm, struct device_node *np)
69{ 67{
70 struct arcpgu_drm_connector *arcpgu_connector; 68 struct arcpgu_drm_connector *arcpgu_connector;
71 struct drm_encoder_slave *encoder; 69 struct drm_encoder *encoder;
72 struct drm_connector *connector; 70 struct drm_connector *connector;
73 int ret; 71 int ret;
74 72
@@ -76,10 +74,10 @@ int arcpgu_drm_sim_init(struct drm_device *drm, struct device_node *np)
76 if (encoder == NULL) 74 if (encoder == NULL)
77 return -ENOMEM; 75 return -ENOMEM;
78 76
79 encoder->base.possible_crtcs = 1; 77 encoder->possible_crtcs = 1;
80 encoder->base.possible_clones = 0; 78 encoder->possible_clones = 0;
81 79
82 ret = drm_encoder_init(drm, &encoder->base, &arcpgu_drm_encoder_funcs, 80 ret = drm_encoder_init(drm, encoder, &arcpgu_drm_encoder_funcs,
83 DRM_MODE_ENCODER_VIRTUAL, NULL); 81 DRM_MODE_ENCODER_VIRTUAL, NULL);
84 if (ret) 82 if (ret)
85 return ret; 83 return ret;
@@ -101,21 +99,19 @@ int arcpgu_drm_sim_init(struct drm_device *drm, struct device_node *np)
101 goto error_encoder_cleanup; 99 goto error_encoder_cleanup;
102 } 100 }
103 101
104 ret = drm_mode_connector_attach_encoder(connector, &encoder->base); 102 ret = drm_mode_connector_attach_encoder(connector, encoder);
105 if (ret < 0) { 103 if (ret < 0) {
106 dev_err(drm->dev, "could not attach connector to encoder\n"); 104 dev_err(drm->dev, "could not attach connector to encoder\n");
107 drm_connector_unregister(connector); 105 drm_connector_unregister(connector);
108 goto error_connector_cleanup; 106 goto error_connector_cleanup;
109 } 107 }
110 108
111 arcpgu_connector->encoder_slave = encoder;
112
113 return 0; 109 return 0;
114 110
115error_connector_cleanup: 111error_connector_cleanup:
116 drm_connector_cleanup(connector); 112 drm_connector_cleanup(connector);
117 113
118error_encoder_cleanup: 114error_encoder_cleanup:
119 drm_encoder_cleanup(&encoder->base); 115 drm_encoder_cleanup(encoder);
120 return ret; 116 return ret;
121} 117}
diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
index 630721f429f7..877647ef35a9 100644
--- a/drivers/gpu/drm/arm/hdlcd_crtc.c
+++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
@@ -249,8 +249,9 @@ static int hdlcd_plane_atomic_check(struct drm_plane *plane,
249 return -EINVAL; 249 return -EINVAL;
250 } 250 }
251 251
252 clip.x2 = crtc_state->adjusted_mode.hdisplay; 252 if (crtc_state->enable)
253 clip.y2 = crtc_state->adjusted_mode.vdisplay; 253 drm_mode_get_hv_timing(&crtc_state->mode,
254 &clip.x2, &clip.y2);
254 255
255 return drm_atomic_helper_check_plane_state(state, crtc_state, &clip, 256 return drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
256 DRM_PLANE_HELPER_NO_SCALING, 257 DRM_PLANE_HELPER_NO_SCALING,
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
index 33c5ef96ced0..2885d69af456 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -148,8 +148,10 @@ static int malidp_se_check_scaling(struct malidp_plane *mp,
148 if (!crtc_state) 148 if (!crtc_state)
149 return -EINVAL; 149 return -EINVAL;
150 150
151 clip.x2 = crtc_state->adjusted_mode.hdisplay; 151 if (crtc_state->enable)
152 clip.y2 = crtc_state->adjusted_mode.vdisplay; 152 drm_mode_get_hv_timing(&crtc_state->mode,
153 &clip.x2, &clip.y2);
154
153 ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip, 155 ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
154 0, INT_MAX, true, true); 156 0, INT_MAX, true, true);
155 if (ret) 157 if (ret)
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
index 703c2d13603f..e18800ed7cd1 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
@@ -194,20 +194,6 @@ static int atmel_hlcdc_format_to_plane_mode(u32 format, u32 *mode)
194 return 0; 194 return 0;
195} 195}
196 196
197static bool atmel_hlcdc_format_embeds_alpha(u32 format)
198{
199 int i;
200
201 for (i = 0; i < sizeof(format); i++) {
202 char tmp = (format >> (8 * i)) & 0xff;
203
204 if (tmp == 'A')
205 return true;
206 }
207
208 return false;
209}
210
211static u32 heo_downscaling_xcoef[] = { 197static u32 heo_downscaling_xcoef[] = {
212 0x11343311, 198 0x11343311,
213 0x000000f7, 199 0x000000f7,
@@ -377,13 +363,13 @@ atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane,
377{ 363{
378 unsigned int cfg = ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16 | state->ahb_id; 364 unsigned int cfg = ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16 | state->ahb_id;
379 const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; 365 const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
380 u32 format = state->base.fb->format->format; 366 const struct drm_format_info *format = state->base.fb->format;
381 367
382 /* 368 /*
383 * Rotation optimization is not working on RGB888 (rotation is still 369 * Rotation optimization is not working on RGB888 (rotation is still
384 * working but without any optimization). 370 * working but without any optimization).
385 */ 371 */
386 if (format == DRM_FORMAT_RGB888) 372 if (format->format == DRM_FORMAT_RGB888)
387 cfg |= ATMEL_HLCDC_LAYER_DMA_ROTDIS; 373 cfg |= ATMEL_HLCDC_LAYER_DMA_ROTDIS;
388 374
389 atmel_hlcdc_layer_write_cfg(&plane->layer, ATMEL_HLCDC_LAYER_DMA_CFG, 375 atmel_hlcdc_layer_write_cfg(&plane->layer, ATMEL_HLCDC_LAYER_DMA_CFG,
@@ -395,7 +381,7 @@ atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane,
395 cfg |= ATMEL_HLCDC_LAYER_OVR | ATMEL_HLCDC_LAYER_ITER2BL | 381 cfg |= ATMEL_HLCDC_LAYER_OVR | ATMEL_HLCDC_LAYER_ITER2BL |
396 ATMEL_HLCDC_LAYER_ITER; 382 ATMEL_HLCDC_LAYER_ITER;
397 383
398 if (atmel_hlcdc_format_embeds_alpha(format)) 384 if (format->has_alpha)
399 cfg |= ATMEL_HLCDC_LAYER_LAEN; 385 cfg |= ATMEL_HLCDC_LAYER_LAEN;
400 else 386 else
401 cfg |= ATMEL_HLCDC_LAYER_GAEN | 387 cfg |= ATMEL_HLCDC_LAYER_GAEN |
@@ -566,7 +552,7 @@ atmel_hlcdc_plane_prepare_disc_area(struct drm_crtc_state *c_state)
566 ovl_state = drm_plane_state_to_atmel_hlcdc_plane_state(ovl_s); 552 ovl_state = drm_plane_state_to_atmel_hlcdc_plane_state(ovl_s);
567 553
568 if (!ovl_s->fb || 554 if (!ovl_s->fb ||
569 atmel_hlcdc_format_embeds_alpha(ovl_s->fb->format->format) || 555 ovl_s->fb->format->has_alpha ||
570 ovl_state->alpha != 255) 556 ovl_state->alpha != 255)
571 continue; 557 continue;
572 558
@@ -769,7 +755,7 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p,
769 755
770 if ((state->crtc_h != state->src_h || state->crtc_w != state->src_w) && 756 if ((state->crtc_h != state->src_h || state->crtc_w != state->src_w) &&
771 (!desc->layout.memsize || 757 (!desc->layout.memsize ||
772 atmel_hlcdc_format_embeds_alpha(state->base.fb->format->format))) 758 state->base.fb->format->has_alpha))
773 return -EINVAL; 759 return -EINVAL;
774 760
775 if (state->crtc_x < 0 || state->crtc_y < 0) 761 if (state->crtc_x < 0 || state->crtc_y < 0)
diff --git a/drivers/gpu/drm/bridge/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix-anx78xx.c
index ed12a7ddd64a..b49043866be6 100644
--- a/drivers/gpu/drm/bridge/analogix-anx78xx.c
+++ b/drivers/gpu/drm/bridge/analogix-anx78xx.c
@@ -1301,8 +1301,7 @@ static void unregister_i2c_dummy_clients(struct anx78xx *anx78xx)
1301 unsigned int i; 1301 unsigned int i;
1302 1302
1303 for (i = 0; i < ARRAY_SIZE(anx78xx->i2c_dummy); i++) 1303 for (i = 0; i < ARRAY_SIZE(anx78xx->i2c_dummy); i++)
1304 if (anx78xx->i2c_dummy[i]) 1304 i2c_unregister_device(anx78xx->i2c_dummy[i]);
1305 i2c_unregister_device(anx78xx->i2c_dummy[i]);
1306} 1305}
1307 1306
1308static const struct regmap_config anx78xx_regmap_config = { 1307static const struct regmap_config anx78xx_regmap_config = {
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index a8905049b9da..b2756bc4225a 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -727,7 +727,6 @@ static int analogix_dp_set_link_train(struct analogix_dp_device *dp,
727 727
728static int analogix_dp_config_video(struct analogix_dp_device *dp) 728static int analogix_dp_config_video(struct analogix_dp_device *dp)
729{ 729{
730 int retval = 0;
731 int timeout_loop = 0; 730 int timeout_loop = 0;
732 int done_count = 0; 731 int done_count = 0;
733 732
@@ -783,10 +782,7 @@ static int analogix_dp_config_video(struct analogix_dp_device *dp)
783 usleep_range(1000, 1001); 782 usleep_range(1000, 1001);
784 } 783 }
785 784
786 if (retval != 0) 785 return 0;
787 dev_err(dp->dev, "Video stream is not detected!\n");
788
789 return retval;
790} 786}
791 787
792static void analogix_dp_enable_scramble(struct analogix_dp_device *dp, 788static void analogix_dp_enable_scramble(struct analogix_dp_device *dp,
diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c
index de5e7dee7ad6..498d5948d1a8 100644
--- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
+++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
@@ -11,6 +11,7 @@
11 */ 11 */
12 12
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/of_device.h>
14#include <linux/of_graph.h> 15#include <linux/of_graph.h>
15#include <linux/regulator/consumer.h> 16#include <linux/regulator/consumer.h>
16 17
@@ -204,6 +205,7 @@ static int dumb_vga_probe(struct platform_device *pdev)
204 205
205 vga->bridge.funcs = &dumb_vga_bridge_funcs; 206 vga->bridge.funcs = &dumb_vga_bridge_funcs;
206 vga->bridge.of_node = pdev->dev.of_node; 207 vga->bridge.of_node = pdev->dev.of_node;
208 vga->bridge.timings = of_device_get_match_data(&pdev->dev);
207 209
208 drm_bridge_add(&vga->bridge); 210 drm_bridge_add(&vga->bridge);
209 211
@@ -222,10 +224,61 @@ static int dumb_vga_remove(struct platform_device *pdev)
222 return 0; 224 return 0;
223} 225}
224 226
227/*
228 * We assume the ADV7123 DAC is the "default" for historical reasons
229 * Information taken from the ADV7123 datasheet, revision D.
230 * NOTE: the ADV7123EP seems to have other timings and need a new timings
231 * set if used.
232 */
233static const struct drm_bridge_timings default_dac_timings = {
234 /* Timing specifications, datasheet page 7 */
235 .sampling_edge = DRM_BUS_FLAG_PIXDATA_POSEDGE,
236 .setup_time_ps = 500,
237 .hold_time_ps = 1500,
238};
239
240/*
241 * Information taken from the THS8134, THS8134A, THS8134B datasheet named
242 * "SLVS205D", dated May 1990, revised March 2000.
243 */
244static const struct drm_bridge_timings ti_ths8134_dac_timings = {
245 /* From timing diagram, datasheet page 9 */
246 .sampling_edge = DRM_BUS_FLAG_PIXDATA_POSEDGE,
247 /* From datasheet, page 12 */
248 .setup_time_ps = 3000,
249 /* I guess this means latched input */
250 .hold_time_ps = 0,
251};
252
253/*
254 * Information taken from the THS8135 datasheet named "SLAS343B", dated
255 * May 2001, revised April 2013.
256 */
257static const struct drm_bridge_timings ti_ths8135_dac_timings = {
258 /* From timing diagram, datasheet page 14 */
259 .sampling_edge = DRM_BUS_FLAG_PIXDATA_POSEDGE,
260 /* From datasheet, page 16 */
261 .setup_time_ps = 2000,
262 .hold_time_ps = 500,
263};
264
225static const struct of_device_id dumb_vga_match[] = { 265static const struct of_device_id dumb_vga_match[] = {
226 { .compatible = "dumb-vga-dac" }, 266 {
227 { .compatible = "adi,adv7123" }, 267 .compatible = "dumb-vga-dac",
228 { .compatible = "ti,ths8135" }, 268 .data = NULL,
269 },
270 {
271 .compatible = "adi,adv7123",
272 .data = &default_dac_timings,
273 },
274 {
275 .compatible = "ti,ths8135",
276 .data = &ti_ths8135_dac_timings,
277 },
278 {
279 .compatible = "ti,ths8134",
280 .data = &ti_ths8134_dac_timings,
281 },
229 {}, 282 {},
230}; 283};
231MODULE_DEVICE_TABLE(of, dumb_vga_match); 284MODULE_DEVICE_TABLE(of, dumb_vga_match);
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index d9cca4fd66ec..7bac101c285c 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -29,7 +29,10 @@
29#include <drm/bridge/dw_mipi_dsi.h> 29#include <drm/bridge/dw_mipi_dsi.h>
30#include <video/mipi_display.h> 30#include <video/mipi_display.h>
31 31
32#define HWVER_131 0x31333100 /* IP version 1.31 */
33
32#define DSI_VERSION 0x00 34#define DSI_VERSION 0x00
35#define VERSION GENMASK(31, 8)
33 36
34#define DSI_PWR_UP 0x04 37#define DSI_PWR_UP 0x04
35#define RESET 0 38#define RESET 0
@@ -136,10 +139,6 @@
136 GEN_SW_0P_TX_LP) 139 GEN_SW_0P_TX_LP)
137 140
138#define DSI_GEN_HDR 0x6c 141#define DSI_GEN_HDR 0x6c
139/* TODO These 2 defines will be reworked thanks to mipi_dsi_create_packet() */
140#define GEN_HDATA(data) (((data) & 0xffff) << 8)
141#define GEN_HTYPE(type) (((type) & 0xff) << 0)
142
143#define DSI_GEN_PLD_DATA 0x70 142#define DSI_GEN_PLD_DATA 0x70
144 143
145#define DSI_CMD_PKT_STATUS 0x74 144#define DSI_CMD_PKT_STATUS 0x74
@@ -169,11 +168,12 @@
169#define PHY_CLKHS2LP_TIME(lbcc) (((lbcc) & 0x3ff) << 16) 168#define PHY_CLKHS2LP_TIME(lbcc) (((lbcc) & 0x3ff) << 16)
170#define PHY_CLKLP2HS_TIME(lbcc) ((lbcc) & 0x3ff) 169#define PHY_CLKLP2HS_TIME(lbcc) ((lbcc) & 0x3ff)
171 170
172/* TODO Next register is slightly different between 1.30 & 1.31 IP version */
173#define DSI_PHY_TMR_CFG 0x9c 171#define DSI_PHY_TMR_CFG 0x9c
174#define PHY_HS2LP_TIME(lbcc) (((lbcc) & 0xff) << 24) 172#define PHY_HS2LP_TIME(lbcc) (((lbcc) & 0xff) << 24)
175#define PHY_LP2HS_TIME(lbcc) (((lbcc) & 0xff) << 16) 173#define PHY_LP2HS_TIME(lbcc) (((lbcc) & 0xff) << 16)
176#define MAX_RD_TIME(lbcc) ((lbcc) & 0x7fff) 174#define MAX_RD_TIME(lbcc) ((lbcc) & 0x7fff)
175#define PHY_HS2LP_TIME_V131(lbcc) (((lbcc) & 0x3ff) << 16)
176#define PHY_LP2HS_TIME_V131(lbcc) ((lbcc) & 0x3ff)
177 177
178#define DSI_PHY_RSTZ 0xa0 178#define DSI_PHY_RSTZ 0xa0
179#define PHY_DISFORCEPLL 0 179#define PHY_DISFORCEPLL 0
@@ -212,7 +212,9 @@
212#define DSI_INT_ST1 0xc0 212#define DSI_INT_ST1 0xc0
213#define DSI_INT_MSK0 0xc4 213#define DSI_INT_MSK0 0xc4
214#define DSI_INT_MSK1 0xc8 214#define DSI_INT_MSK1 0xc8
215
215#define DSI_PHY_TMR_RD_CFG 0xf4 216#define DSI_PHY_TMR_RD_CFG 0xf4
217#define MAX_RD_TIME_V131(lbcc) ((lbcc) & 0x7fff)
216 218
217#define PHY_STATUS_TIMEOUT_US 10000 219#define PHY_STATUS_TIMEOUT_US 10000
218#define CMD_PKT_STATUS_TIMEOUT_US 20000 220#define CMD_PKT_STATUS_TIMEOUT_US 20000
@@ -359,52 +361,23 @@ static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val)
359 return 0; 361 return 0;
360} 362}
361 363
362static int dw_mipi_dsi_dcs_short_write(struct dw_mipi_dsi *dsi, 364static int dw_mipi_dsi_write(struct dw_mipi_dsi *dsi,
363 const struct mipi_dsi_msg *msg) 365 const struct mipi_dsi_packet *packet)
364{ 366{
365 const u8 *tx_buf = msg->tx_buf; 367 const u8 *tx_buf = packet->payload;
366 u16 data = 0; 368 int len = packet->payload_length, pld_data_bytes = sizeof(u32), ret;
369 __le32 word;
367 u32 val; 370 u32 val;
368 371
369 if (msg->tx_len > 0) 372 while (len) {
370 data |= tx_buf[0];
371 if (msg->tx_len > 1)
372 data |= tx_buf[1] << 8;
373
374 if (msg->tx_len > 2) {
375 dev_err(dsi->dev, "too long tx buf length %zu for short write\n",
376 msg->tx_len);
377 return -EINVAL;
378 }
379
380 val = GEN_HDATA(data) | GEN_HTYPE(msg->type);
381 return dw_mipi_dsi_gen_pkt_hdr_write(dsi, val);
382}
383
384static int dw_mipi_dsi_dcs_long_write(struct dw_mipi_dsi *dsi,
385 const struct mipi_dsi_msg *msg)
386{
387 const u8 *tx_buf = msg->tx_buf;
388 int len = msg->tx_len, pld_data_bytes = sizeof(u32), ret;
389 u32 hdr_val = GEN_HDATA(msg->tx_len) | GEN_HTYPE(msg->type);
390 u32 remainder;
391 u32 val;
392
393 if (msg->tx_len < 3) {
394 dev_err(dsi->dev, "wrong tx buf length %zu for long write\n",
395 msg->tx_len);
396 return -EINVAL;
397 }
398
399 while (DIV_ROUND_UP(len, pld_data_bytes)) {
400 if (len < pld_data_bytes) { 373 if (len < pld_data_bytes) {
401 remainder = 0; 374 word = 0;
402 memcpy(&remainder, tx_buf, len); 375 memcpy(&word, tx_buf, len);
403 dsi_write(dsi, DSI_GEN_PLD_DATA, remainder); 376 dsi_write(dsi, DSI_GEN_PLD_DATA, le32_to_cpu(word));
404 len = 0; 377 len = 0;
405 } else { 378 } else {
406 memcpy(&remainder, tx_buf, pld_data_bytes); 379 memcpy(&word, tx_buf, pld_data_bytes);
407 dsi_write(dsi, DSI_GEN_PLD_DATA, remainder); 380 dsi_write(dsi, DSI_GEN_PLD_DATA, le32_to_cpu(word));
408 tx_buf += pld_data_bytes; 381 tx_buf += pld_data_bytes;
409 len -= pld_data_bytes; 382 len -= pld_data_bytes;
410 } 383 }
@@ -419,40 +392,74 @@ static int dw_mipi_dsi_dcs_long_write(struct dw_mipi_dsi *dsi,
419 } 392 }
420 } 393 }
421 394
422 return dw_mipi_dsi_gen_pkt_hdr_write(dsi, hdr_val); 395 word = 0;
396 memcpy(&word, packet->header, sizeof(packet->header));
397 return dw_mipi_dsi_gen_pkt_hdr_write(dsi, le32_to_cpu(word));
398}
399
400static int dw_mipi_dsi_read(struct dw_mipi_dsi *dsi,
401 const struct mipi_dsi_msg *msg)
402{
403 int i, j, ret, len = msg->rx_len;
404 u8 *buf = msg->rx_buf;
405 u32 val;
406
407 /* Wait end of the read operation */
408 ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS,
409 val, !(val & GEN_RD_CMD_BUSY),
410 1000, CMD_PKT_STATUS_TIMEOUT_US);
411 if (ret) {
412 dev_err(dsi->dev, "Timeout during read operation\n");
413 return ret;
414 }
415
416 for (i = 0; i < len; i += 4) {
417 /* Read fifo must not be empty before all bytes are read */
418 ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS,
419 val, !(val & GEN_PLD_R_EMPTY),
420 1000, CMD_PKT_STATUS_TIMEOUT_US);
421 if (ret) {
422 dev_err(dsi->dev, "Read payload FIFO is empty\n");
423 return ret;
424 }
425
426 val = dsi_read(dsi, DSI_GEN_PLD_DATA);
427 for (j = 0; j < 4 && j + i < len; j++)
428 buf[i + j] = val >> (8 * j);
429 }
430
431 return ret;
423} 432}
424 433
425static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host, 434static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host,
426 const struct mipi_dsi_msg *msg) 435 const struct mipi_dsi_msg *msg)
427{ 436{
428 struct dw_mipi_dsi *dsi = host_to_dsi(host); 437 struct dw_mipi_dsi *dsi = host_to_dsi(host);
429 int ret; 438 struct mipi_dsi_packet packet;
439 int ret, nb_bytes;
440
441 ret = mipi_dsi_create_packet(&packet, msg);
442 if (ret) {
443 dev_err(dsi->dev, "failed to create packet: %d\n", ret);
444 return ret;
445 }
430 446
431 /*
432 * TODO dw drv improvements
433 * use mipi_dsi_create_packet() instead of all following
434 * functions and code (no switch cases, no
435 * dw_mipi_dsi_dcs_short_write(), only the loop in long_write...)
436 * and use packet.header...
437 */
438 dw_mipi_message_config(dsi, msg); 447 dw_mipi_message_config(dsi, msg);
439 448
440 switch (msg->type) { 449 ret = dw_mipi_dsi_write(dsi, &packet);
441 case MIPI_DSI_DCS_SHORT_WRITE: 450 if (ret)
442 case MIPI_DSI_DCS_SHORT_WRITE_PARAM: 451 return ret;
443 case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE: 452
444 ret = dw_mipi_dsi_dcs_short_write(dsi, msg); 453 if (msg->rx_buf && msg->rx_len) {
445 break; 454 ret = dw_mipi_dsi_read(dsi, msg);
446 case MIPI_DSI_DCS_LONG_WRITE: 455 if (ret)
447 ret = dw_mipi_dsi_dcs_long_write(dsi, msg); 456 return ret;
448 break; 457 nb_bytes = msg->rx_len;
449 default: 458 } else {
450 dev_err(dsi->dev, "unsupported message type 0x%02x\n", 459 nb_bytes = packet.size;
451 msg->type);
452 ret = -EINVAL;
453 } 460 }
454 461
455 return ret; 462 return nb_bytes;
456} 463}
457 464
458static const struct mipi_dsi_host_ops dw_mipi_dsi_host_ops = { 465static const struct mipi_dsi_host_ops dw_mipi_dsi_host_ops = {
@@ -658,6 +665,8 @@ static void dw_mipi_dsi_vertical_timing_config(struct dw_mipi_dsi *dsi,
658 665
659static void dw_mipi_dsi_dphy_timing_config(struct dw_mipi_dsi *dsi) 666static void dw_mipi_dsi_dphy_timing_config(struct dw_mipi_dsi *dsi)
660{ 667{
668 u32 hw_version;
669
661 /* 670 /*
662 * TODO dw drv improvements 671 * TODO dw drv improvements
663 * data & clock lane timers should be computed according to panel 672 * data & clock lane timers should be computed according to panel
@@ -665,8 +674,17 @@ static void dw_mipi_dsi_dphy_timing_config(struct dw_mipi_dsi *dsi)
665 * note: DSI_PHY_TMR_CFG.MAX_RD_TIME should be in line with 674 * note: DSI_PHY_TMR_CFG.MAX_RD_TIME should be in line with
666 * DSI_CMD_MODE_CFG.MAX_RD_PKT_SIZE_LP (see CMD_MODE_ALL_LP) 675 * DSI_CMD_MODE_CFG.MAX_RD_PKT_SIZE_LP (see CMD_MODE_ALL_LP)
667 */ 676 */
668 dsi_write(dsi, DSI_PHY_TMR_CFG, PHY_HS2LP_TIME(0x40) 677
669 | PHY_LP2HS_TIME(0x40) | MAX_RD_TIME(10000)); 678 hw_version = dsi_read(dsi, DSI_VERSION) & VERSION;
679
680 if (hw_version >= HWVER_131) {
681 dsi_write(dsi, DSI_PHY_TMR_CFG, PHY_HS2LP_TIME_V131(0x40) |
682 PHY_LP2HS_TIME_V131(0x40));
683 dsi_write(dsi, DSI_PHY_TMR_RD_CFG, MAX_RD_TIME_V131(10000));
684 } else {
685 dsi_write(dsi, DSI_PHY_TMR_CFG, PHY_HS2LP_TIME(0x40) |
686 PHY_LP2HS_TIME(0x40) | MAX_RD_TIME(10000));
687 }
670 688
671 dsi_write(dsi, DSI_PHY_TMR_LPCLK_CFG, PHY_CLKHS2LP_TIME(0x40) 689 dsi_write(dsi, DSI_PHY_TMR_LPCLK_CFG, PHY_CLKHS2LP_TIME(0x40)
672 | PHY_CLKLP2HS_TIME(0x40)); 690 | PHY_CLKLP2HS_TIME(0x40));
@@ -746,9 +764,9 @@ static void dw_mipi_dsi_bridge_post_disable(struct drm_bridge *bridge)
746 pm_runtime_put(dsi->dev); 764 pm_runtime_put(dsi->dev);
747} 765}
748 766
749void dw_mipi_dsi_bridge_mode_set(struct drm_bridge *bridge, 767static void dw_mipi_dsi_bridge_mode_set(struct drm_bridge *bridge,
750 struct drm_display_mode *mode, 768 struct drm_display_mode *mode,
751 struct drm_display_mode *adjusted_mode) 769 struct drm_display_mode *adjusted_mode)
752{ 770{
753 struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge); 771 struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
754 const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops; 772 const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops;
@@ -922,8 +940,6 @@ __dw_mipi_dsi_probe(struct platform_device *pdev,
922 dsi->bridge.of_node = pdev->dev.of_node; 940 dsi->bridge.of_node = pdev->dev.of_node;
923#endif 941#endif
924 942
925 dev_set_drvdata(dev, dsi);
926
927 return dsi; 943 return dsi;
928} 944}
929 945
@@ -935,23 +951,16 @@ static void __dw_mipi_dsi_remove(struct dw_mipi_dsi *dsi)
935/* 951/*
936 * Probe/remove API, used from platforms based on the DRM bridge API. 952 * Probe/remove API, used from platforms based on the DRM bridge API.
937 */ 953 */
938int dw_mipi_dsi_probe(struct platform_device *pdev, 954struct dw_mipi_dsi *
939 const struct dw_mipi_dsi_plat_data *plat_data) 955dw_mipi_dsi_probe(struct platform_device *pdev,
956 const struct dw_mipi_dsi_plat_data *plat_data)
940{ 957{
941 struct dw_mipi_dsi *dsi; 958 return __dw_mipi_dsi_probe(pdev, plat_data);
942
943 dsi = __dw_mipi_dsi_probe(pdev, plat_data);
944 if (IS_ERR(dsi))
945 return PTR_ERR(dsi);
946
947 return 0;
948} 959}
949EXPORT_SYMBOL_GPL(dw_mipi_dsi_probe); 960EXPORT_SYMBOL_GPL(dw_mipi_dsi_probe);
950 961
951void dw_mipi_dsi_remove(struct platform_device *pdev) 962void dw_mipi_dsi_remove(struct dw_mipi_dsi *dsi)
952{ 963{
953 struct dw_mipi_dsi *dsi = platform_get_drvdata(pdev);
954
955 mipi_dsi_host_unregister(&dsi->dsi_host); 964 mipi_dsi_host_unregister(&dsi->dsi_host);
956 965
957 __dw_mipi_dsi_remove(dsi); 966 __dw_mipi_dsi_remove(dsi);
@@ -961,31 +970,30 @@ EXPORT_SYMBOL_GPL(dw_mipi_dsi_remove);
961/* 970/*
962 * Bind/unbind API, used from platforms based on the component framework. 971 * Bind/unbind API, used from platforms based on the component framework.
963 */ 972 */
964int dw_mipi_dsi_bind(struct platform_device *pdev, struct drm_encoder *encoder, 973struct dw_mipi_dsi *
965 const struct dw_mipi_dsi_plat_data *plat_data) 974dw_mipi_dsi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
975 const struct dw_mipi_dsi_plat_data *plat_data)
966{ 976{
967 struct dw_mipi_dsi *dsi; 977 struct dw_mipi_dsi *dsi;
968 int ret; 978 int ret;
969 979
970 dsi = __dw_mipi_dsi_probe(pdev, plat_data); 980 dsi = __dw_mipi_dsi_probe(pdev, plat_data);
971 if (IS_ERR(dsi)) 981 if (IS_ERR(dsi))
972 return PTR_ERR(dsi); 982 return dsi;
973 983
974 ret = drm_bridge_attach(encoder, &dsi->bridge, NULL); 984 ret = drm_bridge_attach(encoder, &dsi->bridge, NULL);
975 if (ret) { 985 if (ret) {
976 dw_mipi_dsi_remove(pdev); 986 dw_mipi_dsi_remove(dsi);
977 DRM_ERROR("Failed to initialize bridge with drm\n"); 987 DRM_ERROR("Failed to initialize bridge with drm\n");
978 return ret; 988 return ERR_PTR(ret);
979 } 989 }
980 990
981 return 0; 991 return dsi;
982} 992}
983EXPORT_SYMBOL_GPL(dw_mipi_dsi_bind); 993EXPORT_SYMBOL_GPL(dw_mipi_dsi_bind);
984 994
985void dw_mipi_dsi_unbind(struct device *dev) 995void dw_mipi_dsi_unbind(struct dw_mipi_dsi *dsi)
986{ 996{
987 struct dw_mipi_dsi *dsi = dev_get_drvdata(dev);
988
989 __dw_mipi_dsi_remove(dsi); 997 __dw_mipi_dsi_remove(dsi);
990} 998}
991EXPORT_SYMBOL_GPL(dw_mipi_dsi_unbind); 999EXPORT_SYMBOL_GPL(dw_mipi_dsi_unbind);
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index b76d49218cf1..7d9ad20040a1 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -390,7 +390,7 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
390 390
391 if (blob) { 391 if (blob) {
392 if (blob->length != sizeof(struct drm_mode_modeinfo) || 392 if (blob->length != sizeof(struct drm_mode_modeinfo) ||
393 drm_mode_convert_umode(&state->mode, 393 drm_mode_convert_umode(state->crtc->dev, &state->mode,
394 (const struct drm_mode_modeinfo *) 394 (const struct drm_mode_modeinfo *)
395 blob->data)) 395 blob->data))
396 return -EINVAL; 396 return -EINVAL;
@@ -863,10 +863,10 @@ static int drm_atomic_plane_check(struct drm_plane *plane,
863 int ret; 863 int ret;
864 864
865 /* either *both* CRTC and FB must be set, or neither */ 865 /* either *both* CRTC and FB must be set, or neither */
866 if (WARN_ON(state->crtc && !state->fb)) { 866 if (state->crtc && !state->fb) {
867 DRM_DEBUG_ATOMIC("CRTC set but no FB\n"); 867 DRM_DEBUG_ATOMIC("CRTC set but no FB\n");
868 return -EINVAL; 868 return -EINVAL;
869 } else if (WARN_ON(state->fb && !state->crtc)) { 869 } else if (state->fb && !state->crtc) {
870 DRM_DEBUG_ATOMIC("FB set but no CRTC\n"); 870 DRM_DEBUG_ATOMIC("FB set but no CRTC\n");
871 return -EINVAL; 871 return -EINVAL;
872 } 872 }
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index ab4032167094..ae3cbfe9e01c 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1878,6 +1878,8 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
1878 new_crtc_state->event->base.completion = &commit->flip_done; 1878 new_crtc_state->event->base.completion = &commit->flip_done;
1879 new_crtc_state->event->base.completion_release = release_crtc_commit; 1879 new_crtc_state->event->base.completion_release = release_crtc_commit;
1880 drm_crtc_commit_get(commit); 1880 drm_crtc_commit_get(commit);
1881
1882 commit->abort_completion = true;
1881 } 1883 }
1882 1884
1883 for_each_oldnew_connector_in_state(state, conn, old_conn_state, new_conn_state, i) { 1885 for_each_oldnew_connector_in_state(state, conn, old_conn_state, new_conn_state, i) {
@@ -3421,8 +3423,21 @@ EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state);
3421void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state) 3423void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state)
3422{ 3424{
3423 if (state->commit) { 3425 if (state->commit) {
3426 /*
3427 * In the event that a non-blocking commit returns
3428 * -ERESTARTSYS before the commit_tail work is queued, we will
3429 * have an extra reference to the commit object. Release it, if
3430 * the event has not been consumed by the worker.
3431 *
3432 * state->event may be freed, so we can't directly look at
3433 * state->event->base.completion.
3434 */
3435 if (state->event && state->commit->abort_completion)
3436 drm_crtc_commit_put(state->commit);
3437
3424 kfree(state->commit->event); 3438 kfree(state->commit->event);
3425 state->commit->event = NULL; 3439 state->commit->event = NULL;
3440
3426 drm_crtc_commit_put(state->commit); 3441 drm_crtc_commit_put(state->commit);
3427 } 3442 }
3428 3443
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index e6a21e69059c..d6a7eba087a0 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -205,9 +205,14 @@ int drm_connector_init(struct drm_device *dev,
205 connector->dev = dev; 205 connector->dev = dev;
206 connector->funcs = funcs; 206 connector->funcs = funcs;
207 207
208 ret = ida_simple_get(&config->connector_ida, 0, 0, GFP_KERNEL); 208 /* connector index is used with 32bit bitmasks */
209 if (ret < 0) 209 ret = ida_simple_get(&config->connector_ida, 0, 32, GFP_KERNEL);
210 if (ret < 0) {
211 DRM_DEBUG_KMS("Failed to allocate %s connector index: %d\n",
212 drm_connector_enum_list[connector_type].name,
213 ret);
210 goto out_put; 214 goto out_put;
215 }
211 connector->index = ret; 216 connector->index = ret;
212 ret = 0; 217 ret = 0;
213 218
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index f0556e654116..353e24fcde9e 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -282,6 +282,10 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
282 WARN_ON(primary && primary->type != DRM_PLANE_TYPE_PRIMARY); 282 WARN_ON(primary && primary->type != DRM_PLANE_TYPE_PRIMARY);
283 WARN_ON(cursor && cursor->type != DRM_PLANE_TYPE_CURSOR); 283 WARN_ON(cursor && cursor->type != DRM_PLANE_TYPE_CURSOR);
284 284
285 /* crtc index is used with 32bit bitmasks */
286 if (WARN_ON(config->num_crtc >= 32))
287 return -EINVAL;
288
285 crtc->dev = dev; 289 crtc->dev = dev;
286 crtc->funcs = funcs; 290 crtc->funcs = funcs;
287 291
@@ -610,7 +614,7 @@ retry:
610 goto out; 614 goto out;
611 } 615 }
612 616
613 ret = drm_mode_convert_umode(mode, &crtc_req->mode); 617 ret = drm_mode_convert_umode(dev, mode, &crtc_req->mode);
614 if (ret) { 618 if (ret) {
615 DRM_DEBUG_KMS("Invalid mode\n"); 619 DRM_DEBUG_KMS("Invalid mode\n");
616 goto out; 620 goto out;
diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c
index 9dd879589a2c..9f8312137cad 100644
--- a/drivers/gpu/drm/drm_debugfs_crc.c
+++ b/drivers/gpu/drm/drm_debugfs_crc.c
@@ -307,10 +307,29 @@ static ssize_t crtc_crc_read(struct file *filep, char __user *user_buf,
307 return LINE_LEN(crc->values_cnt); 307 return LINE_LEN(crc->values_cnt);
308} 308}
309 309
310static unsigned int crtc_crc_poll(struct file *file, poll_table *wait)
311{
312 struct drm_crtc *crtc = file->f_inode->i_private;
313 struct drm_crtc_crc *crc = &crtc->crc;
314 unsigned ret;
315
316 poll_wait(file, &crc->wq, wait);
317
318 spin_lock_irq(&crc->lock);
319 if (crc->source && crtc_crc_data_count(crc))
320 ret = POLLIN | POLLRDNORM;
321 else
322 ret = 0;
323 spin_unlock_irq(&crc->lock);
324
325 return ret;
326}
327
310static const struct file_operations drm_crtc_crc_data_fops = { 328static const struct file_operations drm_crtc_crc_data_fops = {
311 .owner = THIS_MODULE, 329 .owner = THIS_MODULE,
312 .open = crtc_crc_open, 330 .open = crtc_crc_open,
313 .read = crtc_crc_read, 331 .read = crtc_crc_read,
332 .poll = crtc_crc_poll,
314 .release = crtc_crc_release, 333 .release = crtc_crc_release,
315}; 334};
316 335
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index adf79be42c1e..ffe14ec3e7f2 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -146,6 +146,8 @@ u8 drm_dp_link_rate_to_bw_code(int link_rate)
146 return DP_LINK_BW_2_7; 146 return DP_LINK_BW_2_7;
147 case 540000: 147 case 540000:
148 return DP_LINK_BW_5_4; 148 return DP_LINK_BW_5_4;
149 case 810000:
150 return DP_LINK_BW_8_1;
149 } 151 }
150} 152}
151EXPORT_SYMBOL(drm_dp_link_rate_to_bw_code); 153EXPORT_SYMBOL(drm_dp_link_rate_to_bw_code);
@@ -161,6 +163,8 @@ int drm_dp_bw_code_to_link_rate(u8 link_bw)
161 return 270000; 163 return 270000;
162 case DP_LINK_BW_5_4: 164 case DP_LINK_BW_5_4:
163 return 540000; 165 return 540000;
166 case DP_LINK_BW_8_1:
167 return 810000;
164 } 168 }
165} 169}
166EXPORT_SYMBOL(drm_dp_bw_code_to_link_rate); 170EXPORT_SYMBOL(drm_dp_bw_code_to_link_rate);
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index 70dcfa58d3c2..36df7df5fe1a 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -2087,6 +2087,9 @@ static bool drm_dp_get_vc_payload_bw(int dp_link_bw,
2087 case DP_LINK_BW_5_4: 2087 case DP_LINK_BW_5_4:
2088 *out = 10 * dp_link_count; 2088 *out = 10 * dp_link_count;
2089 break; 2089 break;
2090 case DP_LINK_BW_8_1:
2091 *out = 15 * dp_link_count;
2092 break;
2090 } 2093 }
2091 return true; 2094 return true;
2092} 2095}
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index ddd537914575..b1cb2627548f 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2767,7 +2767,7 @@ do_detailed_mode(struct detailed_timing *timing, void *c)
2767 2767
2768 drm_mode_probed_add(closure->connector, newmode); 2768 drm_mode_probed_add(closure->connector, newmode);
2769 closure->modes++; 2769 closure->modes++;
2770 closure->preferred = 0; 2770 closure->preferred = false;
2771 } 2771 }
2772} 2772}
2773 2773
@@ -2784,7 +2784,7 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid,
2784 struct detailed_mode_closure closure = { 2784 struct detailed_mode_closure closure = {
2785 .connector = connector, 2785 .connector = connector,
2786 .edid = edid, 2786 .edid = edid,
2787 .preferred = 1, 2787 .preferred = true,
2788 .quirks = quirks, 2788 .quirks = quirks,
2789 }; 2789 };
2790 2790
diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
index 59e0ebe733f8..273e1c59c54a 100644
--- a/drivers/gpu/drm/drm_encoder.c
+++ b/drivers/gpu/drm/drm_encoder.c
@@ -110,6 +110,10 @@ int drm_encoder_init(struct drm_device *dev,
110{ 110{
111 int ret; 111 int ret;
112 112
113 /* encoder index is used with 32bit bitmasks */
114 if (WARN_ON(dev->mode_config.num_encoder >= 32))
115 return -EINVAL;
116
113 ret = drm_mode_object_add(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER); 117 ret = drm_mode_object_add(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER);
114 if (ret) 118 if (ret)
115 return ret; 119 return ret;
diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c
index 9c0152df45ad..5ca6395cd4d3 100644
--- a/drivers/gpu/drm/drm_fourcc.c
+++ b/drivers/gpu/drm/drm_fourcc.c
@@ -112,18 +112,18 @@ const struct drm_format_info *__drm_format_info(u32 format)
112 { .format = DRM_FORMAT_XBGR4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 112 { .format = DRM_FORMAT_XBGR4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
113 { .format = DRM_FORMAT_RGBX4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 113 { .format = DRM_FORMAT_RGBX4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
114 { .format = DRM_FORMAT_BGRX4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 114 { .format = DRM_FORMAT_BGRX4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
115 { .format = DRM_FORMAT_ARGB4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 115 { .format = DRM_FORMAT_ARGB4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
116 { .format = DRM_FORMAT_ABGR4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 116 { .format = DRM_FORMAT_ABGR4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
117 { .format = DRM_FORMAT_RGBA4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 117 { .format = DRM_FORMAT_RGBA4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
118 { .format = DRM_FORMAT_BGRA4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 118 { .format = DRM_FORMAT_BGRA4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
119 { .format = DRM_FORMAT_XRGB1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 119 { .format = DRM_FORMAT_XRGB1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
120 { .format = DRM_FORMAT_XBGR1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 120 { .format = DRM_FORMAT_XBGR1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
121 { .format = DRM_FORMAT_RGBX5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 121 { .format = DRM_FORMAT_RGBX5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
122 { .format = DRM_FORMAT_BGRX5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 122 { .format = DRM_FORMAT_BGRX5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
123 { .format = DRM_FORMAT_ARGB1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 123 { .format = DRM_FORMAT_ARGB1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
124 { .format = DRM_FORMAT_ABGR1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 124 { .format = DRM_FORMAT_ABGR1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
125 { .format = DRM_FORMAT_RGBA5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 125 { .format = DRM_FORMAT_RGBA5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
126 { .format = DRM_FORMAT_BGRA5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 126 { .format = DRM_FORMAT_BGRA5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
127 { .format = DRM_FORMAT_RGB565, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 127 { .format = DRM_FORMAT_RGB565, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
128 { .format = DRM_FORMAT_BGR565, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 128 { .format = DRM_FORMAT_BGR565, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
129 { .format = DRM_FORMAT_RGB888, .depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 }, 129 { .format = DRM_FORMAT_RGB888, .depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 },
@@ -132,26 +132,26 @@ const struct drm_format_info *__drm_format_info(u32 format)
132 { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, 132 { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
133 { .format = DRM_FORMAT_RGBX8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, 133 { .format = DRM_FORMAT_RGBX8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
134 { .format = DRM_FORMAT_BGRX8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, 134 { .format = DRM_FORMAT_BGRX8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
135 { .format = DRM_FORMAT_RGB565_A8, .depth = 24, .num_planes = 2, .cpp = { 2, 1, 0 }, .hsub = 1, .vsub = 1 }, 135 { .format = DRM_FORMAT_RGB565_A8, .depth = 24, .num_planes = 2, .cpp = { 2, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
136 { .format = DRM_FORMAT_BGR565_A8, .depth = 24, .num_planes = 2, .cpp = { 2, 1, 0 }, .hsub = 1, .vsub = 1 }, 136 { .format = DRM_FORMAT_BGR565_A8, .depth = 24, .num_planes = 2, .cpp = { 2, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
137 { .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, 137 { .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
138 { .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, 138 { .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
139 { .format = DRM_FORMAT_RGBX1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, 139 { .format = DRM_FORMAT_RGBX1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
140 { .format = DRM_FORMAT_BGRX1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, 140 { .format = DRM_FORMAT_BGRX1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
141 { .format = DRM_FORMAT_ARGB2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, 141 { .format = DRM_FORMAT_ARGB2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
142 { .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, 142 { .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
143 { .format = DRM_FORMAT_RGBA1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, 143 { .format = DRM_FORMAT_RGBA1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
144 { .format = DRM_FORMAT_BGRA1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, 144 { .format = DRM_FORMAT_BGRA1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
145 { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, 145 { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
146 { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, 146 { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
147 { .format = DRM_FORMAT_RGBA8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, 147 { .format = DRM_FORMAT_RGBA8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
148 { .format = DRM_FORMAT_BGRA8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, 148 { .format = DRM_FORMAT_BGRA8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
149 { .format = DRM_FORMAT_RGB888_A8, .depth = 32, .num_planes = 2, .cpp = { 3, 1, 0 }, .hsub = 1, .vsub = 1 }, 149 { .format = DRM_FORMAT_RGB888_A8, .depth = 32, .num_planes = 2, .cpp = { 3, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
150 { .format = DRM_FORMAT_BGR888_A8, .depth = 32, .num_planes = 2, .cpp = { 3, 1, 0 }, .hsub = 1, .vsub = 1 }, 150 { .format = DRM_FORMAT_BGR888_A8, .depth = 32, .num_planes = 2, .cpp = { 3, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
151 { .format = DRM_FORMAT_XRGB8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1 }, 151 { .format = DRM_FORMAT_XRGB8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
152 { .format = DRM_FORMAT_XBGR8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1 }, 152 { .format = DRM_FORMAT_XBGR8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
153 { .format = DRM_FORMAT_RGBX8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1 }, 153 { .format = DRM_FORMAT_RGBX8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
154 { .format = DRM_FORMAT_BGRX8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1 }, 154 { .format = DRM_FORMAT_BGRX8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
155 { .format = DRM_FORMAT_YUV410, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4 }, 155 { .format = DRM_FORMAT_YUV410, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4 },
156 { .format = DRM_FORMAT_YVU410, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4 }, 156 { .format = DRM_FORMAT_YVU410, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4 },
157 { .format = DRM_FORMAT_YUV411, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1 }, 157 { .format = DRM_FORMAT_YUV411, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1 },
@@ -172,7 +172,7 @@ const struct drm_format_info *__drm_format_info(u32 format)
172 { .format = DRM_FORMAT_YVYU, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 }, 172 { .format = DRM_FORMAT_YVYU, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 },
173 { .format = DRM_FORMAT_UYVY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 }, 173 { .format = DRM_FORMAT_UYVY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 },
174 { .format = DRM_FORMAT_VYUY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 }, 174 { .format = DRM_FORMAT_VYUY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 },
175 { .format = DRM_FORMAT_AYUV, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, 175 { .format = DRM_FORMAT_AYUV, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
176 }; 176 };
177 177
178 unsigned int i; 178 unsigned int i;
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 4aafe4802099..af782911c505 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -509,7 +509,7 @@ int drm_ioctl_permit(u32 flags, struct drm_file *file_priv)
509 return -EACCES; 509 return -EACCES;
510 510
511 /* MASTER is only for master or control clients */ 511 /* MASTER is only for master or control clients */
512 if (unlikely((flags & DRM_MASTER) && 512 if (unlikely((flags & DRM_MASTER) &&
513 !drm_is_current_master(file_priv) && 513 !drm_is_current_master(file_priv) &&
514 !drm_is_control_client(file_priv))) 514 !drm_is_control_client(file_priv)))
515 return -EACCES; 515 return -EACCES;
@@ -704,7 +704,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
704 * 704 *
705 * ##define DRM_IOCTL_MY_DRIVER_OPERATION \ 705 * ##define DRM_IOCTL_MY_DRIVER_OPERATION \
706 * DRM_IOW(DRM_COMMAND_BASE, struct my_driver_operation) 706 * DRM_IOW(DRM_COMMAND_BASE, struct my_driver_operation)
707 * 707 *
708 * DRM driver private IOCTL must be in the range from DRM_COMMAND_BASE to 708 * DRM driver private IOCTL must be in the range from DRM_COMMAND_BASE to
709 * DRM_COMMAND_END. Finally you need an array of &struct drm_ioctl_desc to wire 709 * DRM_COMMAND_END. Finally you need an array of &struct drm_ioctl_desc to wire
710 * up the handlers and set the access rights:: 710 * up the handlers and set the access rights::
@@ -848,7 +848,7 @@ long drm_ioctl(struct file *filp,
848 if (kdata != stack_kdata) 848 if (kdata != stack_kdata)
849 kfree(kdata); 849 kfree(kdata);
850 if (retcode) 850 if (retcode)
851 DRM_DEBUG("ret = %d\n", retcode); 851 DRM_DEBUG("pid=%d, ret = %d\n", task_pid_nr(current), retcode);
852 return retcode; 852 return retcode;
853} 853}
854EXPORT_SYMBOL(drm_ioctl); 854EXPORT_SYMBOL(drm_ioctl);
diff --git a/drivers/gpu/drm/drm_memory.c b/drivers/gpu/drm/drm_memory.c
index fc0ebd273ef8..7ca500b8c399 100644
--- a/drivers/gpu/drm/drm_memory.c
+++ b/drivers/gpu/drm/drm_memory.c
@@ -149,3 +149,16 @@ void drm_legacy_ioremapfree(struct drm_local_map *map, struct drm_device *dev)
149 iounmap(map->handle); 149 iounmap(map->handle);
150} 150}
151EXPORT_SYMBOL(drm_legacy_ioremapfree); 151EXPORT_SYMBOL(drm_legacy_ioremapfree);
152
153u64 drm_get_max_iomem(void)
154{
155 struct resource *tmp;
156 u64 max_iomem = 0;
157
158 for (tmp = iomem_resource.child; tmp; tmp = tmp->sibling) {
159 max_iomem = max(max_iomem, tmp->end);
160 }
161
162 return max_iomem;
163}
164EXPORT_SYMBOL(drm_get_max_iomem);
diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index 4b47226b90d4..bc73b7f5b9fc 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -498,8 +498,9 @@ int mipi_dsi_shutdown_peripheral(struct mipi_dsi_device *dsi)
498 .tx_buf = (u8 [2]) { 0, 0 }, 498 .tx_buf = (u8 [2]) { 0, 0 },
499 .tx_len = 2, 499 .tx_len = 2,
500 }; 500 };
501 int ret = mipi_dsi_device_transfer(dsi, &msg);
501 502
502 return mipi_dsi_device_transfer(dsi, &msg); 503 return (ret < 0) ? ret : 0;
503} 504}
504EXPORT_SYMBOL(mipi_dsi_shutdown_peripheral); 505EXPORT_SYMBOL(mipi_dsi_shutdown_peripheral);
505 506
@@ -517,8 +518,9 @@ int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi)
517 .tx_buf = (u8 [2]) { 0, 0 }, 518 .tx_buf = (u8 [2]) { 0, 0 },
518 .tx_len = 2, 519 .tx_len = 2,
519 }; 520 };
521 int ret = mipi_dsi_device_transfer(dsi, &msg);
520 522
521 return mipi_dsi_device_transfer(dsi, &msg); 523 return (ret < 0) ? ret : 0;
522} 524}
523EXPORT_SYMBOL(mipi_dsi_turn_on_peripheral); 525EXPORT_SYMBOL(mipi_dsi_turn_on_peripheral);
524 526
@@ -541,8 +543,9 @@ int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
541 .tx_len = sizeof(tx), 543 .tx_len = sizeof(tx),
542 .tx_buf = tx, 544 .tx_buf = tx,
543 }; 545 };
546 int ret = mipi_dsi_device_transfer(dsi, &msg);
544 547
545 return mipi_dsi_device_transfer(dsi, &msg); 548 return (ret < 0) ? ret : 0;
546} 549}
547EXPORT_SYMBOL(mipi_dsi_set_maximum_return_packet_size); 550EXPORT_SYMBOL(mipi_dsi_set_maximum_return_packet_size);
548 551
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 4a3f68a33844..c397b523c945 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -833,7 +833,7 @@ EXPORT_SYMBOL(drm_mode_get_hv_timing);
833 */ 833 */
834void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags) 834void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags)
835{ 835{
836 if ((p == NULL) || ((p->type & DRM_MODE_TYPE_CRTC_C) == DRM_MODE_TYPE_BUILTIN)) 836 if (!p)
837 return; 837 return;
838 838
839 p->crtc_clock = p->clock; 839 p->crtc_clock = p->clock;
@@ -1023,19 +1023,18 @@ bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1,
1023} 1023}
1024EXPORT_SYMBOL(drm_mode_equal_no_clocks_no_stereo); 1024EXPORT_SYMBOL(drm_mode_equal_no_clocks_no_stereo);
1025 1025
1026/** 1026static enum drm_mode_status
1027 * drm_mode_validate_basic - make sure the mode is somewhat sane
1028 * @mode: mode to check
1029 *
1030 * Check that the mode timings are at least somewhat reasonable.
1031 * Any hardware specific limits are left up for each driver to check.
1032 *
1033 * Returns:
1034 * The mode status
1035 */
1036enum drm_mode_status
1037drm_mode_validate_basic(const struct drm_display_mode *mode) 1027drm_mode_validate_basic(const struct drm_display_mode *mode)
1038{ 1028{
1029 if (mode->type & ~DRM_MODE_TYPE_ALL)
1030 return MODE_BAD;
1031
1032 if (mode->flags & ~DRM_MODE_FLAG_ALL)
1033 return MODE_BAD;
1034
1035 if ((mode->flags & DRM_MODE_FLAG_3D_MASK) > DRM_MODE_FLAG_3D_MAX)
1036 return MODE_BAD;
1037
1039 if (mode->clock == 0) 1038 if (mode->clock == 0)
1040 return MODE_CLOCK_LOW; 1039 return MODE_CLOCK_LOW;
1041 1040
@@ -1053,7 +1052,35 @@ drm_mode_validate_basic(const struct drm_display_mode *mode)
1053 1052
1054 return MODE_OK; 1053 return MODE_OK;
1055} 1054}
1056EXPORT_SYMBOL(drm_mode_validate_basic); 1055
1056/**
1057 * drm_mode_validate_driver - make sure the mode is somewhat sane
1058 * @dev: drm device
1059 * @mode: mode to check
1060 *
1061 * First do basic validation on the mode, and then allow the driver
1062 * to check for device/driver specific limitations via the optional
1063 * &drm_mode_config_helper_funcs.mode_valid hook.
1064 *
1065 * Returns:
1066 * The mode status
1067 */
1068enum drm_mode_status
1069drm_mode_validate_driver(struct drm_device *dev,
1070 const struct drm_display_mode *mode)
1071{
1072 enum drm_mode_status status;
1073
1074 status = drm_mode_validate_basic(mode);
1075 if (status != MODE_OK)
1076 return status;
1077
1078 if (dev->mode_config.funcs->mode_valid)
1079 return dev->mode_config.funcs->mode_valid(dev, mode);
1080 else
1081 return MODE_OK;
1082}
1083EXPORT_SYMBOL(drm_mode_validate_driver);
1057 1084
1058/** 1085/**
1059 * drm_mode_validate_size - make sure modes adhere to size constraints 1086 * drm_mode_validate_size - make sure modes adhere to size constraints
@@ -1555,6 +1582,7 @@ void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out,
1555 1582
1556/** 1583/**
1557 * drm_crtc_convert_umode - convert a modeinfo into a drm_display_mode 1584 * drm_crtc_convert_umode - convert a modeinfo into a drm_display_mode
1585 * @dev: drm device
1558 * @out: drm_display_mode to return to the user 1586 * @out: drm_display_mode to return to the user
1559 * @in: drm_mode_modeinfo to use 1587 * @in: drm_mode_modeinfo to use
1560 * 1588 *
@@ -1564,7 +1592,8 @@ void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out,
1564 * Returns: 1592 * Returns:
1565 * Zero on success, negative errno on failure. 1593 * Zero on success, negative errno on failure.
1566 */ 1594 */
1567int drm_mode_convert_umode(struct drm_display_mode *out, 1595int drm_mode_convert_umode(struct drm_device *dev,
1596 struct drm_display_mode *out,
1568 const struct drm_mode_modeinfo *in) 1597 const struct drm_mode_modeinfo *in)
1569{ 1598{
1570 int ret = -EINVAL; 1599 int ret = -EINVAL;
@@ -1574,9 +1603,6 @@ int drm_mode_convert_umode(struct drm_display_mode *out,
1574 goto out; 1603 goto out;
1575 } 1604 }
1576 1605
1577 if ((in->flags & DRM_MODE_FLAG_3D_MASK) > DRM_MODE_FLAG_3D_MAX)
1578 goto out;
1579
1580 out->clock = in->clock; 1606 out->clock = in->clock;
1581 out->hdisplay = in->hdisplay; 1607 out->hdisplay = in->hdisplay;
1582 out->hsync_start = in->hsync_start; 1608 out->hsync_start = in->hsync_start;
@@ -1594,7 +1620,7 @@ int drm_mode_convert_umode(struct drm_display_mode *out,
1594 strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); 1620 strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
1595 out->name[DRM_DISPLAY_MODE_LEN-1] = 0; 1621 out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
1596 1622
1597 out->status = drm_mode_validate_basic(out); 1623 out->status = drm_mode_validate_driver(dev, out);
1598 if (out->status != MODE_OK) 1624 if (out->status != MODE_OK)
1599 goto out; 1625 goto out;
1600 1626
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index 2c90519576a3..22b54663b6e7 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -173,6 +173,10 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
173 unsigned int format_modifier_count = 0; 173 unsigned int format_modifier_count = 0;
174 int ret; 174 int ret;
175 175
176 /* plane index is used with 32bit bitmasks */
177 if (WARN_ON(config->num_total_plane >= 32))
178 return -EINVAL;
179
176 ret = drm_mode_object_add(dev, &plane->base, DRM_MODE_OBJECT_PLANE); 180 ret = drm_mode_object_add(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
177 if (ret) 181 if (ret)
178 return ret; 182 return ret;
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index 9a17725b0f7a..e82a976f0fba 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -73,6 +73,9 @@
73 * Drivers should detect this situation and return back the gem object 73 * Drivers should detect this situation and return back the gem object
74 * from the dma-buf private. Prime will do this automatically for drivers that 74 * from the dma-buf private. Prime will do this automatically for drivers that
75 * use the drm_gem_prime_{import,export} helpers. 75 * use the drm_gem_prime_{import,export} helpers.
76 *
77 * GEM struct &dma_buf_ops symbols are now exported. They can be resued by
78 * drivers which implement GEM interface.
76 */ 79 */
77 80
78struct drm_prime_member { 81struct drm_prime_member {
@@ -180,9 +183,20 @@ static int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpri
180 return -ENOENT; 183 return -ENOENT;
181} 184}
182 185
183static int drm_gem_map_attach(struct dma_buf *dma_buf, 186/**
184 struct device *target_dev, 187 * drm_gem_map_attach - dma_buf attach implementation for GEM
185 struct dma_buf_attachment *attach) 188 * @dma_buf: buffer to attach device to
189 * @target_dev: not used
190 * @attach: buffer attachment data
191 *
192 * Allocates &drm_prime_attachment and calls &drm_driver.gem_prime_pin for
193 * device specific attachment. This can be used as the &dma_buf_ops.attach
194 * callback.
195 *
196 * Returns 0 on success, negative error code on failure.
197 */
198int drm_gem_map_attach(struct dma_buf *dma_buf, struct device *target_dev,
199 struct dma_buf_attachment *attach)
186{ 200{
187 struct drm_prime_attachment *prime_attach; 201 struct drm_prime_attachment *prime_attach;
188 struct drm_gem_object *obj = dma_buf->priv; 202 struct drm_gem_object *obj = dma_buf->priv;
@@ -200,9 +214,18 @@ static int drm_gem_map_attach(struct dma_buf *dma_buf,
200 214
201 return dev->driver->gem_prime_pin(obj); 215 return dev->driver->gem_prime_pin(obj);
202} 216}
217EXPORT_SYMBOL(drm_gem_map_attach);
203 218
204static void drm_gem_map_detach(struct dma_buf *dma_buf, 219/**
205 struct dma_buf_attachment *attach) 220 * drm_gem_map_detach - dma_buf detach implementation for GEM
221 * @dma_buf: buffer to detach from
222 * @attach: attachment to be detached
223 *
224 * Cleans up &dma_buf_attachment. This can be used as the &dma_buf_ops.detach
225 * callback.
226 */
227void drm_gem_map_detach(struct dma_buf *dma_buf,
228 struct dma_buf_attachment *attach)
206{ 229{
207 struct drm_prime_attachment *prime_attach = attach->priv; 230 struct drm_prime_attachment *prime_attach = attach->priv;
208 struct drm_gem_object *obj = dma_buf->priv; 231 struct drm_gem_object *obj = dma_buf->priv;
@@ -228,6 +251,7 @@ static void drm_gem_map_detach(struct dma_buf *dma_buf,
228 kfree(prime_attach); 251 kfree(prime_attach);
229 attach->priv = NULL; 252 attach->priv = NULL;
230} 253}
254EXPORT_SYMBOL(drm_gem_map_detach);
231 255
232void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv, 256void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv,
233 struct dma_buf *dma_buf) 257 struct dma_buf *dma_buf)
@@ -254,8 +278,20 @@ void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpr
254 } 278 }
255} 279}
256 280
257static struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach, 281/**
258 enum dma_data_direction dir) 282 * drm_gem_map_dma_buf - map_dma_buf implementation for GEM
283 * @attach: attachment whose scatterlist is to be returned
284 * @dir: direction of DMA transfer
285 *
286 * Calls &drm_driver.gem_prime_get_sg_table and then maps the scatterlist. This
287 * can be used as the &dma_buf_ops.map_dma_buf callback.
288 *
289 * Returns sg_table containing the scatterlist to be returned; returns ERR_PTR
290 * on error. May return -EINTR if it is interrupted by a signal.
291 */
292
293struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach,
294 enum dma_data_direction dir)
259{ 295{
260 struct drm_prime_attachment *prime_attach = attach->priv; 296 struct drm_prime_attachment *prime_attach = attach->priv;
261 struct drm_gem_object *obj = attach->dmabuf->priv; 297 struct drm_gem_object *obj = attach->dmabuf->priv;
@@ -291,13 +327,21 @@ static struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach,
291 327
292 return sgt; 328 return sgt;
293} 329}
330EXPORT_SYMBOL(drm_gem_map_dma_buf);
294 331
295static void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach, 332/**
296 struct sg_table *sgt, 333 * drm_gem_unmap_dma_buf - unmap_dma_buf implementation for GEM
297 enum dma_data_direction dir) 334 *
335 * Not implemented. The unmap is done at drm_gem_map_detach(). This can be
336 * used as the &dma_buf_ops.unmap_dma_buf callback.
337 */
338void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
339 struct sg_table *sgt,
340 enum dma_data_direction dir)
298{ 341{
299 /* nothing to be done here */ 342 /* nothing to be done here */
300} 343}
344EXPORT_SYMBOL(drm_gem_unmap_dma_buf);
301 345
302/** 346/**
303 * drm_gem_dmabuf_export - dma_buf export implementation for GEM 347 * drm_gem_dmabuf_export - dma_buf export implementation for GEM
@@ -348,47 +392,99 @@ void drm_gem_dmabuf_release(struct dma_buf *dma_buf)
348} 392}
349EXPORT_SYMBOL(drm_gem_dmabuf_release); 393EXPORT_SYMBOL(drm_gem_dmabuf_release);
350 394
351static void *drm_gem_dmabuf_vmap(struct dma_buf *dma_buf) 395/**
396 * drm_gem_dmabuf_vmap - dma_buf vmap implementation for GEM
397 * @dma_buf: buffer to be mapped
398 *
399 * Sets up a kernel virtual mapping. This can be used as the &dma_buf_ops.vmap
400 * callback.
401 *
402 * Returns the kernel virtual address.
403 */
404void *drm_gem_dmabuf_vmap(struct dma_buf *dma_buf)
352{ 405{
353 struct drm_gem_object *obj = dma_buf->priv; 406 struct drm_gem_object *obj = dma_buf->priv;
354 struct drm_device *dev = obj->dev; 407 struct drm_device *dev = obj->dev;
355 408
356 return dev->driver->gem_prime_vmap(obj); 409 return dev->driver->gem_prime_vmap(obj);
357} 410}
411EXPORT_SYMBOL(drm_gem_dmabuf_vmap);
358 412
359static void drm_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr) 413/**
414 * drm_gem_dmabuf_vunmap - dma_buf vunmap implementation for GEM
415 * @dma_buf: buffer to be unmapped
416 * @vaddr: the virtual address of the buffer
417 *
418 * Releases a kernel virtual mapping. This can be used as the
419 * &dma_buf_ops.vunmap callback.
420 */
421void drm_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr)
360{ 422{
361 struct drm_gem_object *obj = dma_buf->priv; 423 struct drm_gem_object *obj = dma_buf->priv;
362 struct drm_device *dev = obj->dev; 424 struct drm_device *dev = obj->dev;
363 425
364 dev->driver->gem_prime_vunmap(obj, vaddr); 426 dev->driver->gem_prime_vunmap(obj, vaddr);
365} 427}
428EXPORT_SYMBOL(drm_gem_dmabuf_vunmap);
366 429
367static void *drm_gem_dmabuf_kmap_atomic(struct dma_buf *dma_buf, 430/**
368 unsigned long page_num) 431 * drm_gem_dmabuf_kmap_atomic - map_atomic implementation for GEM
432 *
433 * Not implemented. This can be used as the &dma_buf_ops.map_atomic callback.
434 */
435void *drm_gem_dmabuf_kmap_atomic(struct dma_buf *dma_buf,
436 unsigned long page_num)
369{ 437{
370 return NULL; 438 return NULL;
371} 439}
440EXPORT_SYMBOL(drm_gem_dmabuf_kmap_atomic);
372 441
373static void drm_gem_dmabuf_kunmap_atomic(struct dma_buf *dma_buf, 442/**
374 unsigned long page_num, void *addr) 443 * drm_gem_dmabuf_kunmap_atomic - unmap_atomic implementation for GEM
444 *
445 * Not implemented. This can be used as the &dma_buf_ops.unmap_atomic callback.
446 */
447void drm_gem_dmabuf_kunmap_atomic(struct dma_buf *dma_buf,
448 unsigned long page_num, void *addr)
375{ 449{
376 450
377} 451}
378static void *drm_gem_dmabuf_kmap(struct dma_buf *dma_buf, 452EXPORT_SYMBOL(drm_gem_dmabuf_kunmap_atomic);
379 unsigned long page_num) 453
454/**
455 * drm_gem_dmabuf_kmap - map implementation for GEM
456 *
457 * Not implemented. This can be used as the &dma_buf_ops.map callback.
458 */
459void *drm_gem_dmabuf_kmap(struct dma_buf *dma_buf, unsigned long page_num)
380{ 460{
381 return NULL; 461 return NULL;
382} 462}
463EXPORT_SYMBOL(drm_gem_dmabuf_kmap);
383 464
384static void drm_gem_dmabuf_kunmap(struct dma_buf *dma_buf, 465/**
385 unsigned long page_num, void *addr) 466 * drm_gem_dmabuf_kunmap - unmap implementation for GEM
467 *
468 * Not implemented. This can be used as the &dma_buf_ops.unmap callback.
469 */
470void drm_gem_dmabuf_kunmap(struct dma_buf *dma_buf, unsigned long page_num,
471 void *addr)
386{ 472{
387 473
388} 474}
475EXPORT_SYMBOL(drm_gem_dmabuf_kunmap);
389 476
390static int drm_gem_dmabuf_mmap(struct dma_buf *dma_buf, 477/**
391 struct vm_area_struct *vma) 478 * drm_gem_dmabuf_mmap - dma_buf mmap implementation for GEM
479 * @dma_buf: buffer to be mapped
480 * @vma: virtual address range
481 *
482 * Provides memory mapping for the buffer. This can be used as the
483 * &dma_buf_ops.mmap callback.
484 *
485 * Returns 0 on success or a negative error code on failure.
486 */
487int drm_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma)
392{ 488{
393 struct drm_gem_object *obj = dma_buf->priv; 489 struct drm_gem_object *obj = dma_buf->priv;
394 struct drm_device *dev = obj->dev; 490 struct drm_device *dev = obj->dev;
@@ -398,6 +494,7 @@ static int drm_gem_dmabuf_mmap(struct dma_buf *dma_buf,
398 494
399 return dev->driver->gem_prime_mmap(obj, vma); 495 return dev->driver->gem_prime_mmap(obj, vma);
400} 496}
497EXPORT_SYMBOL(drm_gem_dmabuf_mmap);
401 498
402static const struct dma_buf_ops drm_gem_prime_dmabuf_ops = { 499static const struct dma_buf_ops drm_gem_prime_dmabuf_ops = {
403 .attach = drm_gem_map_attach, 500 .attach = drm_gem_map_attach,
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index 555fbe54d6e2..2d1643bdae78 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -499,7 +499,7 @@ retry:
499 499
500 list_for_each_entry(mode, &connector->modes, head) { 500 list_for_each_entry(mode, &connector->modes, head) {
501 if (mode->status == MODE_OK) 501 if (mode->status == MODE_OK)
502 mode->status = drm_mode_validate_basic(mode); 502 mode->status = drm_mode_validate_driver(dev, mode);
503 503
504 if (mode->status == MODE_OK) 504 if (mode->status == MODE_OK)
505 mode->status = drm_mode_validate_size(mode, maxX, maxY); 505 mode->status = drm_mode_validate_size(mode, maxX, maxY);
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
index 9f3b1c94802b..9d3f6b70812c 100644
--- a/drivers/gpu/drm/drm_simple_kms_helper.c
+++ b/drivers/gpu/drm/drm_simple_kms_helper.c
@@ -100,8 +100,9 @@ static int drm_simple_kms_plane_atomic_check(struct drm_plane *plane,
100 if (!crtc_state->enable) 100 if (!crtc_state->enable)
101 return 0; /* nothing to check when disabling or disabled */ 101 return 0; /* nothing to check when disabling or disabled */
102 102
103 clip.x2 = crtc_state->adjusted_mode.hdisplay; 103 if (crtc_state->enable)
104 clip.y2 = crtc_state->adjusted_mode.vdisplay; 104 drm_mode_get_hv_timing(&crtc_state->mode,
105 &clip.x2, &clip.y2);
105 106
106 ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state, 107 ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state,
107 &clip, 108 &clip,
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index dc5d79465f9b..257299ec95c4 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -179,18 +179,6 @@ static const u8 filter_cr_horiz_tap4[] = {
179 70, 59, 48, 37, 27, 19, 11, 5, 179 70, 59, 48, 37, 27, 19, 11, 5,
180}; 180};
181 181
182static inline bool is_alpha_format(unsigned int pixel_format)
183{
184 switch (pixel_format) {
185 case DRM_FORMAT_ARGB8888:
186 case DRM_FORMAT_ARGB1555:
187 case DRM_FORMAT_ARGB4444:
188 return true;
189 default:
190 return false;
191 }
192}
193
194static inline u32 vp_reg_read(struct mixer_context *ctx, u32 reg_id) 182static inline u32 vp_reg_read(struct mixer_context *ctx, u32 reg_id)
195{ 183{
196 return readl(ctx->vp_regs + reg_id); 184 return readl(ctx->vp_regs + reg_id);
@@ -625,7 +613,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
625 mixer_reg_write(ctx, MXR_GRAPHIC_BASE(win), dma_addr); 613 mixer_reg_write(ctx, MXR_GRAPHIC_BASE(win), dma_addr);
626 614
627 mixer_cfg_layer(ctx, win, priority, true); 615 mixer_cfg_layer(ctx, win, priority, true);
628 mixer_cfg_gfx_blend(ctx, win, is_alpha_format(fb->format->format)); 616 mixer_cfg_gfx_blend(ctx, win, fb->format->has_alpha);
629 617
630 /* layer update mandatory for mixer 16.0.33.0 */ 618 /* layer update mandatory for mixer 16.0.33.0 */
631 if (ctx->mxr_ver == MXR_VER_16_0_33_0 || 619 if (ctx->mxr_ver == MXR_VER_16_0_33_0 ||
diff --git a/drivers/gpu/drm/i2c/sil164_drv.c b/drivers/gpu/drm/i2c/sil164_drv.c
index ecaa58757529..c52d7a3af786 100644
--- a/drivers/gpu/drm/i2c/sil164_drv.c
+++ b/drivers/gpu/drm/i2c/sil164_drv.c
@@ -326,8 +326,7 @@ sil164_encoder_destroy(struct drm_encoder *encoder)
326{ 326{
327 struct sil164_priv *priv = to_sil164_priv(encoder); 327 struct sil164_priv *priv = to_sil164_priv(encoder);
328 328
329 if (priv->duallink_slave) 329 i2c_unregister_device(priv->duallink_slave);
330 i2c_unregister_device(priv->duallink_slave);
331 330
332 kfree(priv); 331 kfree(priv);
333 drm_i2c_encoder_destroy(encoder); 332 drm_i2c_encoder_destroy(encoder);
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index cd3f0873bbdd..9e67a7b4e3a4 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -1600,8 +1600,7 @@ fail:
1600 /* if encoder_init fails, the encoder slave is never registered, 1600 /* if encoder_init fails, the encoder slave is never registered,
1601 * so cleanup here: 1601 * so cleanup here:
1602 */ 1602 */
1603 if (priv->cec) 1603 i2c_unregister_device(priv->cec);
1604 i2c_unregister_device(priv->cec);
1605 return -ENXIO; 1604 return -ENXIO;
1606} 1605}
1607 1606
diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c
index 57ee8b786cd8..0ee32275994a 100644
--- a/drivers/gpu/drm/i915/intel_atomic_plane.c
+++ b/drivers/gpu/drm/i915/intel_atomic_plane.c
@@ -128,14 +128,6 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_
128 if (!intel_state->base.crtc && !old_plane_state->base.crtc) 128 if (!intel_state->base.crtc && !old_plane_state->base.crtc)
129 return 0; 129 return 0;
130 130
131 /* Clip all planes to CRTC size, or 0x0 if CRTC is disabled */
132 intel_state->clip.x1 = 0;
133 intel_state->clip.y1 = 0;
134 intel_state->clip.x2 =
135 crtc_state->base.enable ? crtc_state->pipe_src_w : 0;
136 intel_state->clip.y2 =
137 crtc_state->base.enable ? crtc_state->pipe_src_h : 0;
138
139 if (state->fb && drm_rotation_90_or_270(state->rotation)) { 131 if (state->fb && drm_rotation_90_or_270(state->rotation)) {
140 struct drm_format_name_buf format_name; 132 struct drm_format_name_buf format_name;
141 133
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 9f31aea51dff..1cd4a7c22bd5 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -304,9 +304,6 @@ intel_crt_mode_valid(struct drm_connector *connector,
304 int max_dotclk = dev_priv->max_dotclk_freq; 304 int max_dotclk = dev_priv->max_dotclk_freq;
305 int max_clock; 305 int max_clock;
306 306
307 if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
308 return MODE_NO_DBLESCAN;
309
310 if (mode->clock < 25000) 307 if (mode->clock < 25000)
311 return MODE_CLOCK_LOW; 308 return MODE_CLOCK_LOW;
312 309
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index e9bba2ab4904..15523f0e3b44 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6404,9 +6404,18 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
6404 * - LVDS dual channel mode 6404 * - LVDS dual channel mode
6405 * - Double wide pipe 6405 * - Double wide pipe
6406 */ 6406 */
6407 if ((intel_crtc_has_type(pipe_config, INTEL_OUTPUT_LVDS) && 6407 if (pipe_config->pipe_src_w & 1) {
6408 intel_is_dual_link_lvds(dev)) || pipe_config->double_wide) 6408 if (pipe_config->double_wide) {
6409 pipe_config->pipe_src_w &= ~1; 6409 DRM_DEBUG_KMS("Odd pipe source width not supported with double wide pipe\n");
6410 return -EINVAL;
6411 }
6412
6413 if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_LVDS) &&
6414 intel_is_dual_link_lvds(dev)) {
6415 DRM_DEBUG_KMS("Odd pipe source width not supported with dual link LVDS\n");
6416 return -EINVAL;
6417 }
6418 }
6410 6419
6411 /* Cantiga+ cannot handle modes with a hsync front porch of 0. 6420 /* Cantiga+ cannot handle modes with a hsync front porch of 0.
6412 * WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw. 6421 * WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw.
@@ -9343,13 +9352,18 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state,
9343 struct intel_plane_state *plane_state) 9352 struct intel_plane_state *plane_state)
9344{ 9353{
9345 const struct drm_framebuffer *fb = plane_state->base.fb; 9354 const struct drm_framebuffer *fb = plane_state->base.fb;
9355 struct drm_rect clip = {};
9346 int src_x, src_y; 9356 int src_x, src_y;
9347 u32 offset; 9357 u32 offset;
9348 int ret; 9358 int ret;
9349 9359
9360 if (crtc_state->base.enable)
9361 drm_mode_get_hv_timing(&crtc_state->base.mode,
9362 &clip.x2, &clip.y2);
9363
9350 ret = drm_atomic_helper_check_plane_state(&plane_state->base, 9364 ret = drm_atomic_helper_check_plane_state(&plane_state->base,
9351 &crtc_state->base, 9365 &crtc_state->base,
9352 &plane_state->clip, 9366 &clip,
9353 DRM_PLANE_HELPER_NO_SCALING, 9367 DRM_PLANE_HELPER_NO_SCALING,
9354 DRM_PLANE_HELPER_NO_SCALING, 9368 DRM_PLANE_HELPER_NO_SCALING,
9355 true, true); 9369 true, true);
@@ -12784,6 +12798,7 @@ intel_check_primary_plane(struct intel_plane *plane,
12784 int min_scale = DRM_PLANE_HELPER_NO_SCALING; 12798 int min_scale = DRM_PLANE_HELPER_NO_SCALING;
12785 int max_scale = DRM_PLANE_HELPER_NO_SCALING; 12799 int max_scale = DRM_PLANE_HELPER_NO_SCALING;
12786 bool can_position = false; 12800 bool can_position = false;
12801 struct drm_rect clip = {};
12787 int ret; 12802 int ret;
12788 12803
12789 if (INTEL_GEN(dev_priv) >= 9) { 12804 if (INTEL_GEN(dev_priv) >= 9) {
@@ -12795,9 +12810,13 @@ intel_check_primary_plane(struct intel_plane *plane,
12795 can_position = true; 12810 can_position = true;
12796 } 12811 }
12797 12812
12813 if (crtc_state->base.enable)
12814 drm_mode_get_hv_timing(&crtc_state->base.mode,
12815 &clip.x2, &clip.y2);
12816
12798 ret = drm_atomic_helper_check_plane_state(&state->base, 12817 ret = drm_atomic_helper_check_plane_state(&state->base,
12799 &crtc_state->base, 12818 &crtc_state->base,
12800 &state->clip, 12819 &clip,
12801 min_scale, max_scale, 12820 min_scale, max_scale,
12802 can_position, true); 12821 can_position, true);
12803 if (ret) 12822 if (ret)
@@ -14097,10 +14116,37 @@ static void intel_atomic_state_free(struct drm_atomic_state *state)
14097 kfree(state); 14116 kfree(state);
14098} 14117}
14099 14118
14119static enum drm_mode_status
14120intel_mode_valid(struct drm_device *dev,
14121 const struct drm_display_mode *mode)
14122{
14123 if (mode->vscan > 1)
14124 return MODE_NO_VSCAN;
14125
14126 if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
14127 return MODE_NO_DBLESCAN;
14128
14129 if (mode->flags & DRM_MODE_FLAG_HSKEW)
14130 return MODE_H_ILLEGAL;
14131
14132 if (mode->flags & (DRM_MODE_FLAG_CSYNC |
14133 DRM_MODE_FLAG_NCSYNC |
14134 DRM_MODE_FLAG_PCSYNC))
14135 return MODE_HSYNC;
14136
14137 if (mode->flags & (DRM_MODE_FLAG_BCAST |
14138 DRM_MODE_FLAG_PIXMUX |
14139 DRM_MODE_FLAG_CLKDIV2))
14140 return MODE_BAD;
14141
14142 return MODE_OK;
14143}
14144
14100static const struct drm_mode_config_funcs intel_mode_funcs = { 14145static const struct drm_mode_config_funcs intel_mode_funcs = {
14101 .fb_create = intel_user_framebuffer_create, 14146 .fb_create = intel_user_framebuffer_create,
14102 .get_format_info = intel_get_format_info, 14147 .get_format_info = intel_get_format_info,
14103 .output_poll_changed = intel_fbdev_output_poll_changed, 14148 .output_poll_changed = intel_fbdev_output_poll_changed,
14149 .mode_valid = intel_mode_valid,
14104 .atomic_check = intel_atomic_check, 14150 .atomic_check = intel_atomic_check,
14105 .atomic_commit = intel_atomic_commit, 14151 .atomic_commit = intel_atomic_commit,
14106 .atomic_state_alloc = intel_atomic_state_alloc, 14152 .atomic_state_alloc = intel_atomic_state_alloc,
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 71355fdec94a..cdcbeb595bb1 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -406,7 +406,6 @@ struct intel_atomic_state {
406 406
407struct intel_plane_state { 407struct intel_plane_state {
408 struct drm_plane_state base; 408 struct drm_plane_state base;
409 struct drm_rect clip;
410 struct i915_vma *vma; 409 struct i915_vma *vma;
411 410
412 struct { 411 struct {
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
index f67d321376e4..51a1d6868b1e 100644
--- a/drivers/gpu/drm/i915/intel_dsi.c
+++ b/drivers/gpu/drm/i915/intel_dsi.c
@@ -1266,11 +1266,6 @@ intel_dsi_mode_valid(struct drm_connector *connector,
1266 1266
1267 DRM_DEBUG_KMS("\n"); 1267 DRM_DEBUG_KMS("\n");
1268 1268
1269 if (mode->flags & DRM_MODE_FLAG_DBLSCAN) {
1270 DRM_DEBUG_KMS("MODE_NO_DBLESCAN\n");
1271 return MODE_NO_DBLESCAN;
1272 }
1273
1274 if (fixed_mode) { 1269 if (fixed_mode) {
1275 if (mode->hdisplay > fixed_mode->hdisplay) 1270 if (mode->hdisplay > fixed_mode->hdisplay)
1276 return MODE_PANEL; 1271 return MODE_PANEL;
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index 754baa00bea9..59c066ca14e5 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -219,9 +219,6 @@ intel_dvo_mode_valid(struct drm_connector *connector,
219 int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; 219 int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
220 int target_clock = mode->clock; 220 int target_clock = mode->clock;
221 221
222 if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
223 return MODE_NO_DBLESCAN;
224
225 /* XXX: Validate clock range */ 222 /* XXX: Validate clock range */
226 223
227 if (fixed_mode) { 224 if (fixed_mode) {
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 80682a418a70..d7d1ac79c38a 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -799,8 +799,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
799 return false; 799 return false;
800 } 800 }
801 801
802 if ((cache->crtc.mode_flags & DRM_MODE_FLAG_INTERLACE) || 802 if (cache->crtc.mode_flags & DRM_MODE_FLAG_INTERLACE) {
803 (cache->crtc.mode_flags & DRM_MODE_FLAG_DBLSCAN)) {
804 fbc->no_fbc_reason = "incompatible mode"; 803 fbc->no_fbc_reason = "incompatible mode";
805 return false; 804 return false;
806 } 805 }
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 2df18a85c3b4..23150f598dfa 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1314,9 +1314,6 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
1314 bool force_dvi = 1314 bool force_dvi =
1315 READ_ONCE(to_intel_digital_connector_state(connector->state)->force_audio) == HDMI_AUDIO_OFF_DVI; 1315 READ_ONCE(to_intel_digital_connector_state(connector->state)->force_audio) == HDMI_AUDIO_OFF_DVI;
1316 1316
1317 if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
1318 return MODE_NO_DBLESCAN;
1319
1320 clock = mode->clock; 1317 clock = mode->clock;
1321 1318
1322 if ((mode->flags & DRM_MODE_FLAG_3D_MASK) == DRM_MODE_FLAG_3D_FRAME_PACKING) 1319 if ((mode->flags & DRM_MODE_FLAG_3D_MASK) == DRM_MODE_FLAG_3D_FRAME_PACKING)
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 2b8764897d68..0bf97ed5ffac 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1607,9 +1607,6 @@ intel_sdvo_mode_valid(struct drm_connector *connector,
1607 struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); 1607 struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
1608 int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; 1608 int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
1609 1609
1610 if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
1611 return MODE_NO_DBLESCAN;
1612
1613 if (intel_sdvo->pixel_clock_min > mode->clock) 1610 if (intel_sdvo->pixel_clock_min > mode->clock)
1614 return MODE_CLOCK_LOW; 1611 return MODE_CLOCK_LOW;
1615 1612
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 32f10621fac8..3be22c0fcfb5 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -864,7 +864,7 @@ intel_check_sprite_plane(struct intel_plane *plane,
864 uint32_t src_x, src_y, src_w, src_h; 864 uint32_t src_x, src_y, src_w, src_h;
865 struct drm_rect *src = &state->base.src; 865 struct drm_rect *src = &state->base.src;
866 struct drm_rect *dst = &state->base.dst; 866 struct drm_rect *dst = &state->base.dst;
867 const struct drm_rect *clip = &state->clip; 867 struct drm_rect clip = {};
868 int max_stride = INTEL_GEN(dev_priv) >= 9 ? 32768 : 16384; 868 int max_stride = INTEL_GEN(dev_priv) >= 9 ? 32768 : 16384;
869 int hscale, vscale; 869 int hscale, vscale;
870 int max_scale, min_scale; 870 int max_scale, min_scale;
@@ -923,7 +923,11 @@ intel_check_sprite_plane(struct intel_plane *plane,
923 vscale = drm_rect_calc_vscale_relaxed(src, dst, min_scale, max_scale); 923 vscale = drm_rect_calc_vscale_relaxed(src, dst, min_scale, max_scale);
924 BUG_ON(vscale < 0); 924 BUG_ON(vscale < 0);
925 925
926 state->base.visible = drm_rect_clip_scaled(src, dst, clip, hscale, vscale); 926 if (crtc_state->base.enable)
927 drm_mode_get_hv_timing(&crtc_state->base.mode,
928 &clip.x2, &clip.y2);
929
930 state->base.visible = drm_rect_clip_scaled(src, dst, &clip, hscale, vscale);
927 931
928 crtc_x = dst->x1; 932 crtc_x = dst->x1;
929 crtc_y = dst->y1; 933 crtc_y = dst->y1;
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c
index 57ed56d8623f..150628293c51 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3-plane.c
@@ -351,7 +351,7 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,
351 struct drm_framebuffer *old_fb = old_state->fb; 351 struct drm_framebuffer *old_fb = old_state->fb;
352 unsigned long eba, ubo, vbo, old_ubo, old_vbo, alpha_eba; 352 unsigned long eba, ubo, vbo, old_ubo, old_vbo, alpha_eba;
353 bool can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY); 353 bool can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY);
354 struct drm_rect clip; 354 struct drm_rect clip = {};
355 int hsub, vsub; 355 int hsub, vsub;
356 int ret; 356 int ret;
357 357
@@ -367,10 +367,10 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,
367 if (WARN_ON(!crtc_state)) 367 if (WARN_ON(!crtc_state))
368 return -EINVAL; 368 return -EINVAL;
369 369
370 clip.x1 = 0; 370 if (crtc_state->enable)
371 clip.y1 = 0; 371 drm_mode_get_hv_timing(&crtc_state->mode,
372 clip.x2 = crtc_state->adjusted_mode.hdisplay; 372 &clip.x2, &clip.y2);
373 clip.y2 = crtc_state->adjusted_mode.vdisplay; 373
374 ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip, 374 ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
375 DRM_PLANE_HELPER_NO_SCALING, 375 DRM_PLANE_HELPER_NO_SCALING,
376 DRM_PLANE_HELPER_NO_SCALING, 376 DRM_PLANE_HELPER_NO_SCALING,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.c b/drivers/gpu/drm/mediatek/mtk_drm_plane.c
index 5ef898b93d8d..b5c6eec9a584 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_plane.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_plane.c
@@ -108,8 +108,9 @@ static int mtk_plane_atomic_check(struct drm_plane *plane,
108 if (IS_ERR(crtc_state)) 108 if (IS_ERR(crtc_state))
109 return PTR_ERR(crtc_state); 109 return PTR_ERR(crtc_state);
110 110
111 clip.x2 = crtc_state->mode.hdisplay; 111 if (crtc_state->enable)
112 clip.y2 = crtc_state->mode.vdisplay; 112 drm_mode_get_hv_timing(&crtc_state->mode,
113 &clip.x2, &clip.y2);
113 114
114 return drm_atomic_helper_check_plane_state(state, crtc_state, &clip, 115 return drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
115 DRM_PLANE_HELPER_NO_SCALING, 116 DRM_PLANE_HELPER_NO_SCALING,
diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c
index d0a6ac8390f3..3801bee1f9e6 100644
--- a/drivers/gpu/drm/meson/meson_plane.c
+++ b/drivers/gpu/drm/meson/meson_plane.c
@@ -58,8 +58,9 @@ static int meson_plane_atomic_check(struct drm_plane *plane,
58 if (IS_ERR(crtc_state)) 58 if (IS_ERR(crtc_state))
59 return PTR_ERR(crtc_state); 59 return PTR_ERR(crtc_state);
60 60
61 clip.x2 = crtc_state->mode.hdisplay; 61 if (crtc_state->enable)
62 clip.y2 = crtc_state->mode.vdisplay; 62 drm_mode_get_hv_timing(&crtc_state->mode,
63 &clip.x2, &clip.y2);
63 64
64 return drm_atomic_helper_check_plane_state(state, crtc_state, &clip, 65 return drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
65 DRM_PLANE_HELPER_NO_SCALING, 66 DRM_PLANE_HELPER_NO_SCALING,
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 68e5d9c94475..fb50a9ddaae8 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -1620,8 +1620,8 @@ static int mga_vga_mode_valid(struct drm_connector *connector,
1620 return MODE_VIRTUAL_X; 1620 return MODE_VIRTUAL_X;
1621 if (mode->vdisplay > 1024) 1621 if (mode->vdisplay > 1024)
1622 return MODE_VIRTUAL_Y; 1622 return MODE_VIRTUAL_Y;
1623 if (mga_vga_calculate_mode_bandwidth(mode, 1623 if (mga_vga_calculate_mode_bandwidth(mode, bpp) >
1624 bpp > (31877 * 1024))) 1624 (31877 * 1024))
1625 return MODE_BANDWIDTH; 1625 return MODE_BANDWIDTH;
1626 } else if (mdev->type == G200_EV && 1626 } else if (mdev->type == G200_EV &&
1627 (mga_vga_calculate_mode_bandwidth(mode, bpp) 1627 (mga_vga_calculate_mode_bandwidth(mode, bpp)
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index 29678876fc09..98d4d7331767 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -286,7 +286,7 @@ static int mdp5_plane_atomic_check_with_state(struct drm_crtc_state *crtc_state,
286 uint32_t max_width, max_height; 286 uint32_t max_width, max_height;
287 bool out_of_bounds = false; 287 bool out_of_bounds = false;
288 uint32_t caps = 0; 288 uint32_t caps = 0;
289 struct drm_rect clip; 289 struct drm_rect clip = {};
290 int min_scale, max_scale; 290 int min_scale, max_scale;
291 int ret; 291 int ret;
292 292
@@ -320,13 +320,13 @@ static int mdp5_plane_atomic_check_with_state(struct drm_crtc_state *crtc_state,
320 return -ERANGE; 320 return -ERANGE;
321 } 321 }
322 322
323 clip.x1 = 0;
324 clip.y1 = 0;
325 clip.x2 = crtc_state->adjusted_mode.hdisplay;
326 clip.y2 = crtc_state->adjusted_mode.vdisplay;
327 min_scale = FRAC_16_16(1, 8); 323 min_scale = FRAC_16_16(1, 8);
328 max_scale = FRAC_16_16(8, 1); 324 max_scale = FRAC_16_16(8, 1);
329 325
326 if (crtc_state->enable)
327 drm_mode_get_hv_timing(&crtc_state->mode,
328 &clip.x2, &clip.y2);
329
330 ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip, 330 ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
331 min_scale, max_scale, 331 min_scale, max_scale,
332 true, true); 332 true, true);
@@ -471,7 +471,7 @@ static int mdp5_plane_atomic_async_check(struct drm_plane *plane,
471{ 471{
472 struct mdp5_plane_state *mdp5_state = to_mdp5_plane_state(state); 472 struct mdp5_plane_state *mdp5_state = to_mdp5_plane_state(state);
473 struct drm_crtc_state *crtc_state; 473 struct drm_crtc_state *crtc_state;
474 struct drm_rect clip; 474 struct drm_rect clip = {};
475 int min_scale, max_scale; 475 int min_scale, max_scale;
476 int ret; 476 int ret;
477 477
@@ -499,13 +499,13 @@ static int mdp5_plane_atomic_async_check(struct drm_plane *plane,
499 plane->state->fb != state->fb) 499 plane->state->fb != state->fb)
500 return -EINVAL; 500 return -EINVAL;
501 501
502 clip.x1 = 0;
503 clip.y1 = 0;
504 clip.x2 = crtc_state->adjusted_mode.hdisplay;
505 clip.y2 = crtc_state->adjusted_mode.vdisplay;
506 min_scale = FRAC_16_16(1, 8); 502 min_scale = FRAC_16_16(1, 8);
507 max_scale = FRAC_16_16(8, 1); 503 max_scale = FRAC_16_16(8, 1);
508 504
505 if (crtc_state->enable)
506 drm_mode_get_hv_timing(&crtc_state->mode,
507 &clip.x2, &clip.y2);
508
509 ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip, 509 ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
510 min_scale, max_scale, 510 min_scale, max_scale,
511 true, true); 511 true, true);
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index dd8d4352ed99..1f55b3d80a56 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -232,8 +232,6 @@ struct nv50_wndw_atom {
232 struct drm_plane_state state; 232 struct drm_plane_state state;
233 u8 interval; 233 u8 interval;
234 234
235 struct drm_rect clip;
236
237 struct { 235 struct {
238 u32 handle; 236 u32 handle;
239 u16 offset:12; 237 u16 offset:12;
@@ -848,10 +846,6 @@ nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw,
848 int ret; 846 int ret;
849 847
850 NV_ATOMIC(drm, "%s acquire\n", wndw->plane.name); 848 NV_ATOMIC(drm, "%s acquire\n", wndw->plane.name);
851 asyw->clip.x1 = 0;
852 asyw->clip.y1 = 0;
853 asyw->clip.x2 = asyh->state.mode.hdisplay;
854 asyw->clip.y2 = asyh->state.mode.vdisplay;
855 849
856 asyw->image.w = fb->base.width; 850 asyw->image.w = fb->base.width;
857 asyw->image.h = fb->base.height; 851 asyw->image.h = fb->base.height;
@@ -1149,10 +1143,15 @@ static int
1149nv50_curs_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, 1143nv50_curs_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
1150 struct nv50_head_atom *asyh) 1144 struct nv50_head_atom *asyh)
1151{ 1145{
1146 struct drm_rect clip = {};
1152 int ret; 1147 int ret;
1153 1148
1149 if (asyh->state.enable)
1150 drm_mode_get_hv_timing(&asyh->state.mode,
1151 &clip.x2, &clip.y2);
1152
1154 ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state, 1153 ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state,
1155 &asyw->clip, 1154 &clip,
1156 DRM_PLANE_HELPER_NO_SCALING, 1155 DRM_PLANE_HELPER_NO_SCALING,
1157 DRM_PLANE_HELPER_NO_SCALING, 1156 DRM_PLANE_HELPER_NO_SCALING,
1158 true, true); 1157 true, true);
@@ -1436,13 +1435,18 @@ nv50_base_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
1436 struct nv50_head_atom *asyh) 1435 struct nv50_head_atom *asyh)
1437{ 1436{
1438 const struct drm_framebuffer *fb = asyw->state.fb; 1437 const struct drm_framebuffer *fb = asyw->state.fb;
1438 struct drm_rect clip = {};
1439 int ret; 1439 int ret;
1440 1440
1441 if (!fb->format->depth) 1441 if (!fb->format->depth)
1442 return -EINVAL; 1442 return -EINVAL;
1443 1443
1444 if (asyh->state.enable)
1445 drm_mode_get_hv_timing(&asyh->state.mode,
1446 &clip.x2, &clip.y2);
1447
1444 ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state, 1448 ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state,
1445 &asyw->clip, 1449 &clip,
1446 DRM_PLANE_HELPER_NO_SCALING, 1450 DRM_PLANE_HELPER_NO_SCALING,
1447 DRM_PLANE_HELPER_NO_SCALING, 1451 DRM_PLANE_HELPER_NO_SCALING,
1448 false, true); 1452 false, true);
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 6ba4031f3919..988048ebcc22 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -7,6 +7,16 @@ config DRM_PANEL
7menu "Display Panels" 7menu "Display Panels"
8 depends on DRM && DRM_PANEL 8 depends on DRM && DRM_PANEL
9 9
10config DRM_PANEL_ARM_VERSATILE
11 tristate "ARM Versatile panel driver"
12 depends on OF
13 depends on MFD_SYSCON
14 select VIDEOMODE_HELPERS
15 help
16 This driver supports the ARM Versatile panels connected to ARM
17 reference designs. The panel is detected using special registers
18 in the Versatile family syscon registers.
19
10config DRM_PANEL_LVDS 20config DRM_PANEL_LVDS
11 tristate "Generic LVDS panel driver" 21 tristate "Generic LVDS panel driver"
12 depends on OF 22 depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index 6d251ebc568c..3d2a88d0e965 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -1,4 +1,5 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
2obj-$(CONFIG_DRM_PANEL_ARM_VERSATILE) += panel-arm-versatile.o
2obj-$(CONFIG_DRM_PANEL_LVDS) += panel-lvds.o 3obj-$(CONFIG_DRM_PANEL_LVDS) += panel-lvds.o
3obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o 4obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
4obj-$(CONFIG_DRM_PANEL_ILITEK_IL9322) += panel-ilitek-ili9322.o 5obj-$(CONFIG_DRM_PANEL_ILITEK_IL9322) += panel-ilitek-ili9322.o
diff --git a/drivers/gpu/drm/panel/panel-arm-versatile.c b/drivers/gpu/drm/panel/panel-arm-versatile.c
new file mode 100644
index 000000000000..3930b4925b15
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-arm-versatile.c
@@ -0,0 +1,377 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Panel driver for the ARM Versatile family reference designs from
4 * ARM Limited.
5 *
6 * Author:
7 * Linus Walleij <linus.wallei@linaro.org>
8 *
9 * On the Versatile AB, these panels come mounted on daughterboards
10 * named "IB1" or "IB2" (Interface Board 1 & 2 respectively.) They
11 * are documented in ARM DUI 0225D Appendix C and D. These daughter
12 * boards support TFT display panels.
13 *
14 * - The IB1 is a passive board where the display connector defines a
15 * few wires for encoding the display type for autodetection,
16 * suitable display settings can then be looked up from this setting.
17 * The magic bits can be read out from the system controller.
18 *
19 * - The IB2 is a more complex board intended for GSM phone development
20 * with some logic and a control register, which needs to be accessed
21 * and the board display needs to be turned on explicitly.
22 *
23 * On the Versatile PB, a special CLCD adaptor board is available
24 * supporting the same displays as the Versatile AB, plus one more
25 * Epson QCIF display.
26 *
27 */
28#include <drm/drmP.h>
29#include <drm/drm_panel.h>
30
31#include <linux/bitops.h>
32#include <linux/init.h>
33#include <linux/kernel.h>
34#include <linux/mfd/syscon.h>
35#include <linux/module.h>
36#include <linux/platform_device.h>
37#include <linux/regmap.h>
38
39#include <video/of_videomode.h>
40#include <video/videomode.h>
41
42/*
43 * This configuration register in the Versatile and RealView
44 * family is uniformly present but appears more and more
45 * unutilized starting with the RealView series.
46 */
47#define SYS_CLCD 0x50
48
49/* The Versatile can detect the connected panel type */
50#define SYS_CLCD_CLCDID_MASK (BIT(8)|BIT(9)|BIT(10)|BIT(11)|BIT(12))
51#define SYS_CLCD_ID_SANYO_3_8 (0x00 << 8)
52#define SYS_CLCD_ID_SHARP_8_4 (0x01 << 8)
53#define SYS_CLCD_ID_EPSON_2_2 (0x02 << 8)
54#define SYS_CLCD_ID_SANYO_2_5 (0x07 << 8)
55#define SYS_CLCD_ID_VGA (0x1f << 8)
56
57/* IB2 control register for the Versatile daughterboard */
58#define IB2_CTRL 0x00
59#define IB2_CTRL_LCD_SD BIT(1) /* 1 = shut down LCD */
60#define IB2_CTRL_LCD_BL_ON BIT(0)
61#define IB2_CTRL_LCD_MASK (BIT(0)|BIT(1))
62
63/**
64 * struct versatile_panel_type - lookup struct for the supported panels
65 */
66struct versatile_panel_type {
67 /**
68 * @name: the name of this panel
69 */
70 const char *name;
71 /**
72 * @magic: the magic value from the detection register
73 */
74 u32 magic;
75 /**
76 * @mode: the DRM display mode for this panel
77 */
78 struct drm_display_mode mode;
79 /**
80 * @bus_flags: the DRM bus flags for this panel e.g. inverted clock
81 */
82 u32 bus_flags;
83 /**
84 * @width_mm: the panel width in mm
85 */
86 u32 width_mm;
87 /**
88 * @height_mm: the panel height in mm
89 */
90 u32 height_mm;
91 /**
92 * @ib2: the panel may be connected on an IB2 daughterboard
93 */
94 bool ib2;
95};
96
97/**
98 * struct versatile_panel - state container for the Versatile panels
99 */
100struct versatile_panel {
101 /**
102 * @dev: the container device
103 */
104 struct device *dev;
105 /**
106 * @panel: the DRM panel instance for this device
107 */
108 struct drm_panel panel;
109 /**
110 * @panel_type: the Versatile panel type as detected
111 */
112 const struct versatile_panel_type *panel_type;
113 /**
114 * @map: map to the parent syscon where the main register reside
115 */
116 struct regmap *map;
117 /**
118 * @ib2_map: map to the IB2 syscon, if applicable
119 */
120 struct regmap *ib2_map;
121};
122
123static const struct versatile_panel_type versatile_panels[] = {
124 /*
125 * Sanyo TM38QV67A02A - 3.8 inch QVGA (320x240) Color TFT
126 * found on the Versatile AB IB1 connector or the Versatile
127 * PB adaptor board connector.
128 */
129 {
130 .name = "Sanyo TM38QV67A02A",
131 .magic = SYS_CLCD_ID_SANYO_3_8,
132 .width_mm = 79,
133 .height_mm = 54,
134 .mode = {
135 .clock = 10000000,
136 .hdisplay = 320,
137 .hsync_start = 320 + 6,
138 .hsync_end = 320 + 6 + 6,
139 .htotal = 320 + 6 + 6 + 6,
140 .vdisplay = 240,
141 .vsync_start = 240 + 5,
142 .vsync_end = 240 + 5 + 6,
143 .vtotal = 240 + 5 + 6 + 5,
144 .vrefresh = 116,
145 .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC,
146 },
147 },
148 /*
149 * Sharp LQ084V1DG21 640x480 VGA Color TFT module
150 * found on the Versatile AB IB1 connector or the Versatile
151 * PB adaptor board connector.
152 */
153 {
154 .name = "Sharp LQ084V1DG21",
155 .magic = SYS_CLCD_ID_SHARP_8_4,
156 .width_mm = 171,
157 .height_mm = 130,
158 .mode = {
159 .clock = 25000000,
160 .hdisplay = 640,
161 .hsync_start = 640 + 24,
162 .hsync_end = 640 + 24 + 96,
163 .htotal = 640 + 24 + 96 + 24,
164 .vdisplay = 480,
165 .vsync_start = 480 + 11,
166 .vsync_end = 480 + 11 + 2,
167 .vtotal = 480 + 11 + 2 + 32,
168 .vrefresh = 60,
169 .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC,
170 },
171 },
172 /*
173 * Epson L2F50113T00 - 2.2 inch QCIF 176x220 Color TFT
174 * found on the Versatile PB adaptor board connector.
175 */
176 {
177 .name = "Epson L2F50113T00",
178 .magic = SYS_CLCD_ID_EPSON_2_2,
179 .width_mm = 34,
180 .height_mm = 45,
181 .mode = {
182 .clock = 625000000,
183 .hdisplay = 176,
184 .hsync_start = 176 + 2,
185 .hsync_end = 176 + 2 + 3,
186 .htotal = 176 + 2 + 3 + 3,
187 .vdisplay = 220,
188 .vsync_start = 220 + 0,
189 .vsync_end = 220 + 0 + 2,
190 .vtotal = 220 + 0 + 2 + 1,
191 .vrefresh = 390,
192 .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC,
193 },
194 .bus_flags = DRM_BUS_FLAG_PIXDATA_NEGEDGE,
195 },
196 /*
197 * Sanyo ALR252RGT 240x320 portrait display found on the
198 * Versatile AB IB2 daughterboard for GSM prototyping.
199 */
200 {
201 .name = "Sanyo ALR252RGT",
202 .magic = SYS_CLCD_ID_SANYO_2_5,
203 .width_mm = 37,
204 .height_mm = 50,
205 .mode = {
206 .clock = 5400000,
207 .hdisplay = 240,
208 .hsync_start = 240 + 10,
209 .hsync_end = 240 + 10 + 10,
210 .htotal = 240 + 10 + 10 + 20,
211 .vdisplay = 320,
212 .vsync_start = 320 + 2,
213 .vsync_end = 320 + 2 + 2,
214 .vtotal = 320 + 2 + 2 + 2,
215 .vrefresh = 116,
216 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
217 },
218 .bus_flags = DRM_BUS_FLAG_PIXDATA_NEGEDGE,
219 .ib2 = true,
220 },
221};
222
223static inline struct versatile_panel *
224to_versatile_panel(struct drm_panel *panel)
225{
226 return container_of(panel, struct versatile_panel, panel);
227}
228
229static int versatile_panel_disable(struct drm_panel *panel)
230{
231 struct versatile_panel *vpanel = to_versatile_panel(panel);
232
233 /* If we're on an IB2 daughterboard, turn off display */
234 if (vpanel->ib2_map) {
235 dev_dbg(vpanel->dev, "disable IB2 display\n");
236 regmap_update_bits(vpanel->ib2_map,
237 IB2_CTRL,
238 IB2_CTRL_LCD_MASK,
239 IB2_CTRL_LCD_SD);
240 }
241
242 return 0;
243}
244
245static int versatile_panel_enable(struct drm_panel *panel)
246{
247 struct versatile_panel *vpanel = to_versatile_panel(panel);
248
249 /* If we're on an IB2 daughterboard, turn on display */
250 if (vpanel->ib2_map) {
251 dev_dbg(vpanel->dev, "enable IB2 display\n");
252 regmap_update_bits(vpanel->ib2_map,
253 IB2_CTRL,
254 IB2_CTRL_LCD_MASK,
255 IB2_CTRL_LCD_BL_ON);
256 }
257
258 return 0;
259}
260
261static int versatile_panel_get_modes(struct drm_panel *panel)
262{
263 struct drm_connector *connector = panel->connector;
264 struct versatile_panel *vpanel = to_versatile_panel(panel);
265 struct drm_display_mode *mode;
266
267 strncpy(connector->display_info.name, vpanel->panel_type->name,
268 DRM_DISPLAY_INFO_LEN);
269 connector->display_info.width_mm = vpanel->panel_type->width_mm;
270 connector->display_info.height_mm = vpanel->panel_type->height_mm;
271 connector->display_info.bus_flags = vpanel->panel_type->bus_flags;
272
273 mode = drm_mode_duplicate(panel->drm, &vpanel->panel_type->mode);
274 drm_mode_set_name(mode);
275 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
276
277 mode->width_mm = vpanel->panel_type->width_mm;
278 mode->height_mm = vpanel->panel_type->height_mm;
279 drm_mode_probed_add(connector, mode);
280
281 return 1;
282}
283
284static const struct drm_panel_funcs versatile_panel_drm_funcs = {
285 .disable = versatile_panel_disable,
286 .enable = versatile_panel_enable,
287 .get_modes = versatile_panel_get_modes,
288};
289
290static int versatile_panel_probe(struct platform_device *pdev)
291{
292 struct device *dev = &pdev->dev;
293 struct versatile_panel *vpanel;
294 struct device *parent;
295 struct regmap *map;
296 int ret;
297 u32 val;
298 int i;
299
300 parent = dev->parent;
301 if (!parent) {
302 dev_err(dev, "no parent for versatile panel\n");
303 return -ENODEV;
304 }
305 map = syscon_node_to_regmap(parent->of_node);
306 if (IS_ERR(map)) {
307 dev_err(dev, "no regmap for versatile panel parent\n");
308 return PTR_ERR(map);
309 }
310
311 vpanel = devm_kzalloc(dev, sizeof(*vpanel), GFP_KERNEL);
312 if (!vpanel)
313 return -ENOMEM;
314
315 ret = regmap_read(map, SYS_CLCD, &val);
316 if (ret) {
317 dev_err(dev, "cannot access syscon regs\n");
318 return ret;
319 }
320
321 val &= SYS_CLCD_CLCDID_MASK;
322
323 for (i = 0; i < ARRAY_SIZE(versatile_panels); i++) {
324 const struct versatile_panel_type *pt;
325
326 pt = &versatile_panels[i];
327 if (pt->magic == val) {
328 vpanel->panel_type = pt;
329 break;
330 }
331 }
332
333 /* No panel detected or VGA, let's leave this show */
334 if (i == ARRAY_SIZE(versatile_panels)) {
335 dev_info(dev, "no panel detected\n");
336 return -ENODEV;
337 }
338
339 dev_info(dev, "detected: %s\n", vpanel->panel_type->name);
340 vpanel->dev = dev;
341 vpanel->map = map;
342
343 /* Check if the panel is mounted on an IB2 daughterboard */
344 if (vpanel->panel_type->ib2) {
345 vpanel->ib2_map = syscon_regmap_lookup_by_compatible(
346 "arm,versatile-ib2-syscon");
347 if (IS_ERR(vpanel->ib2_map))
348 vpanel->ib2_map = NULL;
349 else
350 dev_info(dev, "panel mounted on IB2 daughterboard\n");
351 }
352
353 drm_panel_init(&vpanel->panel);
354 vpanel->panel.dev = dev;
355 vpanel->panel.funcs = &versatile_panel_drm_funcs;
356
357 return drm_panel_add(&vpanel->panel);
358}
359
360static const struct of_device_id versatile_panel_match[] = {
361 { .compatible = "arm,versatile-tft-panel", },
362 {},
363};
364MODULE_DEVICE_TABLE(of, versatile_panel_match);
365
366static struct platform_driver versatile_panel_driver = {
367 .probe = versatile_panel_probe,
368 .driver = {
369 .name = "versatile-tft-panel",
370 .of_match_table = versatile_panel_match,
371 },
372};
373module_platform_driver(versatile_panel_driver);
374
375MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
376MODULE_DESCRIPTION("ARM Versatile panel driver");
377MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
index 7f915f706fa6..74a806121f80 100644
--- a/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
+++ b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
@@ -59,34 +59,28 @@ static inline struct wuxga_nt_panel *to_wuxga_nt_panel(struct drm_panel *panel)
59 59
60static int wuxga_nt_panel_on(struct wuxga_nt_panel *wuxga_nt) 60static int wuxga_nt_panel_on(struct wuxga_nt_panel *wuxga_nt)
61{ 61{
62 struct mipi_dsi_device *dsi = wuxga_nt->dsi; 62 return mipi_dsi_turn_on_peripheral(wuxga_nt->dsi);
63 int ret;
64
65 ret = mipi_dsi_turn_on_peripheral(dsi);
66 if (ret < 0)
67 return ret;
68
69 return 0;
70} 63}
71 64
72static int wuxga_nt_panel_disable(struct drm_panel *panel) 65static int wuxga_nt_panel_disable(struct drm_panel *panel)
73{ 66{
74 struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel); 67 struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel);
68 int mipi_ret, bl_ret = 0;
75 69
76 if (!wuxga_nt->enabled) 70 if (!wuxga_nt->enabled)
77 return 0; 71 return 0;
78 72
79 mipi_dsi_shutdown_peripheral(wuxga_nt->dsi); 73 mipi_ret = mipi_dsi_shutdown_peripheral(wuxga_nt->dsi);
80 74
81 if (wuxga_nt->backlight) { 75 if (wuxga_nt->backlight) {
82 wuxga_nt->backlight->props.power = FB_BLANK_POWERDOWN; 76 wuxga_nt->backlight->props.power = FB_BLANK_POWERDOWN;
83 wuxga_nt->backlight->props.state |= BL_CORE_FBBLANK; 77 wuxga_nt->backlight->props.state |= BL_CORE_FBBLANK;
84 backlight_update_status(wuxga_nt->backlight); 78 bl_ret = backlight_update_status(wuxga_nt->backlight);
85 } 79 }
86 80
87 wuxga_nt->enabled = false; 81 wuxga_nt->enabled = false;
88 82
89 return 0; 83 return mipi_ret ? mipi_ret : bl_ret;
90} 84}
91 85
92static int wuxga_nt_panel_unprepare(struct drm_panel *panel) 86static int wuxga_nt_panel_unprepare(struct drm_panel *panel)
diff --git a/drivers/gpu/drm/pl111/Kconfig b/drivers/gpu/drm/pl111/Kconfig
index e5e2abd66491..82cb3e60ddc8 100644
--- a/drivers/gpu/drm/pl111/Kconfig
+++ b/drivers/gpu/drm/pl111/Kconfig
@@ -8,6 +8,7 @@ config DRM_PL111
8 select DRM_GEM_CMA_HELPER 8 select DRM_GEM_CMA_HELPER
9 select DRM_BRIDGE 9 select DRM_BRIDGE
10 select DRM_PANEL_BRIDGE 10 select DRM_PANEL_BRIDGE
11 select DRM_DUMB_VGA_DAC
11 select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE 12 select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
12 help 13 help
13 Choose this option for DRM support for the PL111 CLCD controller. 14 Choose this option for DRM support for the PL111 CLCD controller.
diff --git a/drivers/gpu/drm/pl111/pl111_display.c b/drivers/gpu/drm/pl111/pl111_display.c
index 06c4bf756b69..d75923896609 100644
--- a/drivers/gpu/drm/pl111/pl111_display.c
+++ b/drivers/gpu/drm/pl111/pl111_display.c
@@ -94,6 +94,7 @@ static void pl111_display_enable(struct drm_simple_display_pipe *pipe,
94 const struct drm_display_mode *mode = &cstate->mode; 94 const struct drm_display_mode *mode = &cstate->mode;
95 struct drm_framebuffer *fb = plane->state->fb; 95 struct drm_framebuffer *fb = plane->state->fb;
96 struct drm_connector *connector = priv->connector; 96 struct drm_connector *connector = priv->connector;
97 struct drm_bridge *bridge = priv->bridge;
97 u32 cntl; 98 u32 cntl;
98 u32 ppl, hsw, hfp, hbp; 99 u32 ppl, hsw, hfp, hbp;
99 u32 lpp, vsw, vfp, vbp; 100 u32 lpp, vsw, vfp, vbp;
@@ -137,17 +138,46 @@ static void pl111_display_enable(struct drm_simple_display_pipe *pipe,
137 tim2 = readl(priv->regs + CLCD_TIM2); 138 tim2 = readl(priv->regs + CLCD_TIM2);
138 tim2 &= (TIM2_BCD | TIM2_PCD_LO_MASK | TIM2_PCD_HI_MASK); 139 tim2 &= (TIM2_BCD | TIM2_PCD_LO_MASK | TIM2_PCD_HI_MASK);
139 140
141 if (priv->variant->broken_clockdivider)
142 tim2 |= TIM2_BCD;
143
140 if (mode->flags & DRM_MODE_FLAG_NHSYNC) 144 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
141 tim2 |= TIM2_IHS; 145 tim2 |= TIM2_IHS;
142 146
143 if (mode->flags & DRM_MODE_FLAG_NVSYNC) 147 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
144 tim2 |= TIM2_IVS; 148 tim2 |= TIM2_IVS;
145 149
146 if (connector->display_info.bus_flags & DRM_BUS_FLAG_DE_LOW) 150 if (connector) {
147 tim2 |= TIM2_IOE; 151 if (connector->display_info.bus_flags & DRM_BUS_FLAG_DE_LOW)
152 tim2 |= TIM2_IOE;
148 153
149 if (connector->display_info.bus_flags & DRM_BUS_FLAG_PIXDATA_NEGEDGE) 154 if (connector->display_info.bus_flags &
150 tim2 |= TIM2_IPC; 155 DRM_BUS_FLAG_PIXDATA_NEGEDGE)
156 tim2 |= TIM2_IPC;
157 }
158
159 if (bridge) {
160 const struct drm_bridge_timings *btimings = bridge->timings;
161
162 /*
163 * Here is when things get really fun. Sometimes the bridge
164 * timings are such that the signal out from PL11x is not
165 * stable before the receiving bridge (such as a dumb VGA DAC
166 * or similar) samples it. If that happens, we compensate by
167 * the only method we have: output the data on the opposite
168 * edge of the clock so it is for sure stable when it gets
169 * sampled.
170 *
171 * The PL111 manual does not contain proper timining diagrams
172 * or data for these details, but we know from experiments
173 * that the setup time is more than 3000 picoseconds (3 ns).
174 * If we have a bridge that requires the signal to be stable
175 * earlier than 3000 ps before the clock pulse, we have to
176 * output the data on the opposite edge to avoid flicker.
177 */
178 if (btimings && btimings->setup_time_ps >= 3000)
179 tim2 ^= TIM2_IPC;
180 }
151 181
152 tim2 |= cpl << 16; 182 tim2 |= cpl << 16;
153 writel(tim2, priv->regs + CLCD_TIM2); 183 writel(tim2, priv->regs + CLCD_TIM2);
@@ -172,10 +202,17 @@ static void pl111_display_enable(struct drm_simple_display_pipe *pipe,
172 cntl |= CNTL_LCDBPP24 | CNTL_BGR; 202 cntl |= CNTL_LCDBPP24 | CNTL_BGR;
173 break; 203 break;
174 case DRM_FORMAT_BGR565: 204 case DRM_FORMAT_BGR565:
175 cntl |= CNTL_LCDBPP16_565; 205 if (priv->variant->is_pl110)
206 cntl |= CNTL_LCDBPP16;
207 else
208 cntl |= CNTL_LCDBPP16_565;
176 break; 209 break;
177 case DRM_FORMAT_RGB565: 210 case DRM_FORMAT_RGB565:
178 cntl |= CNTL_LCDBPP16_565 | CNTL_BGR; 211 if (priv->variant->is_pl110)
212 cntl |= CNTL_LCDBPP16;
213 else
214 cntl |= CNTL_LCDBPP16_565;
215 cntl |= CNTL_BGR;
179 break; 216 break;
180 case DRM_FORMAT_ABGR1555: 217 case DRM_FORMAT_ABGR1555:
181 case DRM_FORMAT_XBGR1555: 218 case DRM_FORMAT_XBGR1555:
@@ -199,6 +236,10 @@ static void pl111_display_enable(struct drm_simple_display_pipe *pipe,
199 break; 236 break;
200 } 237 }
201 238
239 /* The PL110 in Integrator/Versatile does the BGR routing externally */
240 if (priv->variant->external_bgr)
241 cntl &= ~CNTL_BGR;
242
202 /* Power sequence: first enable and chill */ 243 /* Power sequence: first enable and chill */
203 writel(cntl, priv->regs + priv->ctrl); 244 writel(cntl, priv->regs + priv->ctrl);
204 245
@@ -215,7 +256,8 @@ static void pl111_display_enable(struct drm_simple_display_pipe *pipe,
215 cntl |= CNTL_LCDPWR; 256 cntl |= CNTL_LCDPWR;
216 writel(cntl, priv->regs + priv->ctrl); 257 writel(cntl, priv->regs + priv->ctrl);
217 258
218 drm_crtc_vblank_on(crtc); 259 if (!priv->variant->broken_vblank)
260 drm_crtc_vblank_on(crtc);
219} 261}
220 262
221void pl111_display_disable(struct drm_simple_display_pipe *pipe) 263void pl111_display_disable(struct drm_simple_display_pipe *pipe)
@@ -225,7 +267,8 @@ void pl111_display_disable(struct drm_simple_display_pipe *pipe)
225 struct pl111_drm_dev_private *priv = drm->dev_private; 267 struct pl111_drm_dev_private *priv = drm->dev_private;
226 u32 cntl; 268 u32 cntl;
227 269
228 drm_crtc_vblank_off(crtc); 270 if (!priv->variant->broken_vblank)
271 drm_crtc_vblank_off(crtc);
229 272
230 /* Power Down */ 273 /* Power Down */
231 cntl = readl(priv->regs + priv->ctrl); 274 cntl = readl(priv->regs + priv->ctrl);
@@ -417,6 +460,11 @@ pl111_init_clock_divider(struct drm_device *drm)
417 dev_err(drm->dev, "CLCD: unable to get clcdclk.\n"); 460 dev_err(drm->dev, "CLCD: unable to get clcdclk.\n");
418 return PTR_ERR(parent); 461 return PTR_ERR(parent);
419 } 462 }
463 /* If the clock divider is broken, use the parent directly */
464 if (priv->variant->broken_clockdivider) {
465 priv->clk = parent;
466 return 0;
467 }
420 parent_name = __clk_get_name(parent); 468 parent_name = __clk_get_name(parent);
421 469
422 spin_lock_init(&priv->tim2_lock); 470 spin_lock_init(&priv->tim2_lock);
diff --git a/drivers/gpu/drm/pl111/pl111_drm.h b/drivers/gpu/drm/pl111/pl111_drm.h
index 07fa2cdb364a..6d0e450e51b1 100644
--- a/drivers/gpu/drm/pl111/pl111_drm.h
+++ b/drivers/gpu/drm/pl111/pl111_drm.h
@@ -36,12 +36,20 @@ struct drm_minor;
36 * struct pl111_variant_data - encodes IP differences 36 * struct pl111_variant_data - encodes IP differences
37 * @name: the name of this variant 37 * @name: the name of this variant
38 * @is_pl110: this is the early PL110 variant 38 * @is_pl110: this is the early PL110 variant
39 * @external_bgr: this is the Versatile Pl110 variant with external
40 * BGR/RGB routing
41 * @broken_clockdivider: the clock divider is broken and we need to
42 * use the supplied clock directly
43 * @broken_vblank: the vblank IRQ is broken on this variant
39 * @formats: array of supported pixel formats on this variant 44 * @formats: array of supported pixel formats on this variant
40 * @nformats: the length of the array of supported pixel formats 45 * @nformats: the length of the array of supported pixel formats
41 */ 46 */
42struct pl111_variant_data { 47struct pl111_variant_data {
43 const char *name; 48 const char *name;
44 bool is_pl110; 49 bool is_pl110;
50 bool external_bgr;
51 bool broken_clockdivider;
52 bool broken_vblank;
45 const u32 *formats; 53 const u32 *formats;
46 unsigned int nformats; 54 unsigned int nformats;
47}; 55};
diff --git a/drivers/gpu/drm/pl111/pl111_drv.c b/drivers/gpu/drm/pl111/pl111_drv.c
index acb738c69873..1231905150d0 100644
--- a/drivers/gpu/drm/pl111/pl111_drv.c
+++ b/drivers/gpu/drm/pl111/pl111_drv.c
@@ -58,6 +58,8 @@
58#include <linux/dma-buf.h> 58#include <linux/dma-buf.h>
59#include <linux/module.h> 59#include <linux/module.h>
60#include <linux/slab.h> 60#include <linux/slab.h>
61#include <linux/of.h>
62#include <linux/of_graph.h>
61 63
62#include <drm/drmP.h> 64#include <drm/drmP.h>
63#include <drm/drm_atomic_helper.h> 65#include <drm/drm_atomic_helper.h>
@@ -85,9 +87,13 @@ static int pl111_modeset_init(struct drm_device *dev)
85{ 87{
86 struct drm_mode_config *mode_config; 88 struct drm_mode_config *mode_config;
87 struct pl111_drm_dev_private *priv = dev->dev_private; 89 struct pl111_drm_dev_private *priv = dev->dev_private;
88 struct drm_panel *panel; 90 struct device_node *np = dev->dev->of_node;
89 struct drm_bridge *bridge; 91 struct device_node *remote;
92 struct drm_panel *panel = NULL;
93 struct drm_bridge *bridge = NULL;
94 bool defer = false;
90 int ret = 0; 95 int ret = 0;
96 int i;
91 97
92 drm_mode_config_init(dev); 98 drm_mode_config_init(dev);
93 mode_config = &dev->mode_config; 99 mode_config = &dev->mode_config;
@@ -97,10 +103,54 @@ static int pl111_modeset_init(struct drm_device *dev)
97 mode_config->min_height = 1; 103 mode_config->min_height = 1;
98 mode_config->max_height = 768; 104 mode_config->max_height = 768;
99 105
100 ret = drm_of_find_panel_or_bridge(dev->dev->of_node, 106 i = 0;
101 0, 0, &panel, &bridge); 107 for_each_endpoint_of_node(np, remote) {
102 if (ret && ret != -ENODEV) 108 struct drm_panel *tmp_panel;
103 return ret; 109 struct drm_bridge *tmp_bridge;
110
111 dev_dbg(dev->dev, "checking endpoint %d\n", i);
112
113 ret = drm_of_find_panel_or_bridge(dev->dev->of_node,
114 0, i,
115 &tmp_panel,
116 &tmp_bridge);
117 if (ret) {
118 if (ret == -EPROBE_DEFER) {
119 /*
120 * Something deferred, but that is often just
121 * another way of saying -ENODEV, but let's
122 * cast a vote for later deferral.
123 */
124 defer = true;
125 } else if (ret != -ENODEV) {
126 /* Continue, maybe something else is working */
127 dev_err(dev->dev,
128 "endpoint %d returns %d\n", i, ret);
129 }
130 }
131
132 if (tmp_panel) {
133 dev_info(dev->dev,
134 "found panel on endpoint %d\n", i);
135 panel = tmp_panel;
136 }
137 if (tmp_bridge) {
138 dev_info(dev->dev,
139 "found bridge on endpoint %d\n", i);
140 bridge = tmp_bridge;
141 }
142
143 i++;
144 }
145
146 /*
147 * If we can't find neither panel nor bridge on any of the
148 * endpoints, and any of them retured -EPROBE_DEFER, then
149 * let's defer this driver too.
150 */
151 if ((!panel && !bridge) && defer)
152 return -EPROBE_DEFER;
153
104 if (panel) { 154 if (panel) {
105 bridge = drm_panel_bridge_add(panel, 155 bridge = drm_panel_bridge_add(panel,
106 DRM_MODE_CONNECTOR_Unknown); 156 DRM_MODE_CONNECTOR_Unknown);
@@ -108,11 +158,17 @@ static int pl111_modeset_init(struct drm_device *dev)
108 ret = PTR_ERR(bridge); 158 ret = PTR_ERR(bridge);
109 goto out_config; 159 goto out_config;
110 } 160 }
111 /* 161 } else if (bridge) {
112 * TODO: when we are using a different bridge than a panel 162 dev_info(dev->dev, "Using non-panel bridge\n");
113 * (such as a dumb VGA connector) we need to devise a different 163 } else {
114 * method to get the connector out of the bridge. 164 dev_err(dev->dev, "No bridge, exiting\n");
115 */ 165 return -ENODEV;
166 }
167
168 priv->bridge = bridge;
169 if (panel) {
170 priv->panel = panel;
171 priv->connector = panel->connector;
116 } 172 }
117 173
118 ret = pl111_display_init(dev); 174 ret = pl111_display_init(dev);
@@ -126,14 +182,12 @@ static int pl111_modeset_init(struct drm_device *dev)
126 if (ret) 182 if (ret)
127 return ret; 183 return ret;
128 184
129 priv->bridge = bridge; 185 if (!priv->variant->broken_vblank) {
130 priv->panel = panel; 186 ret = drm_vblank_init(dev, 1);
131 priv->connector = panel->connector; 187 if (ret != 0) {
132 188 dev_err(dev->dev, "Failed to init vblank\n");
133 ret = drm_vblank_init(dev, 1); 189 goto out_bridge;
134 if (ret != 0) { 190 }
135 dev_err(dev->dev, "Failed to init vblank\n");
136 goto out_bridge;
137 } 191 }
138 192
139 drm_mode_config_reset(dev); 193 drm_mode_config_reset(dev);
@@ -170,10 +224,6 @@ static struct drm_driver pl111_drm_driver = {
170 .dumb_create = drm_gem_cma_dumb_create, 224 .dumb_create = drm_gem_cma_dumb_create,
171 .gem_free_object_unlocked = drm_gem_cma_free_object, 225 .gem_free_object_unlocked = drm_gem_cma_free_object,
172 .gem_vm_ops = &drm_gem_cma_vm_ops, 226 .gem_vm_ops = &drm_gem_cma_vm_ops,
173
174 .enable_vblank = pl111_enable_vblank,
175 .disable_vblank = pl111_disable_vblank,
176
177 .prime_handle_to_fd = drm_gem_prime_handle_to_fd, 227 .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
178 .prime_fd_to_handle = drm_gem_prime_fd_to_handle, 228 .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
179 .gem_prime_import = drm_gem_prime_import, 229 .gem_prime_import = drm_gem_prime_import,
@@ -191,7 +241,7 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
191{ 241{
192 struct device *dev = &amba_dev->dev; 242 struct device *dev = &amba_dev->dev;
193 struct pl111_drm_dev_private *priv; 243 struct pl111_drm_dev_private *priv;
194 struct pl111_variant_data *variant = id->data; 244 const struct pl111_variant_data *variant = id->data;
195 struct drm_device *drm; 245 struct drm_device *drm;
196 int ret; 246 int ret;
197 247
@@ -199,6 +249,11 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
199 if (!priv) 249 if (!priv)
200 return -ENOMEM; 250 return -ENOMEM;
201 251
252 if (!variant->broken_vblank) {
253 pl111_drm_driver.enable_vblank = pl111_enable_vblank;
254 pl111_drm_driver.disable_vblank = pl111_disable_vblank;
255 }
256
202 drm = drm_dev_alloc(&pl111_drm_driver, dev); 257 drm = drm_dev_alloc(&pl111_drm_driver, dev);
203 if (IS_ERR(drm)) 258 if (IS_ERR(drm))
204 return PTR_ERR(drm); 259 return PTR_ERR(drm);
@@ -207,27 +262,10 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
207 drm->dev_private = priv; 262 drm->dev_private = priv;
208 priv->variant = variant; 263 priv->variant = variant;
209 264
210 /* 265 /* The two variants swap this register */
211 * The PL110 and PL111 variants have two registers
212 * swapped: interrupt enable and control. For this reason
213 * we use offsets that we can change per variant.
214 */
215 if (variant->is_pl110) { 266 if (variant->is_pl110) {
216 /* 267 priv->ienb = CLCD_PL110_IENB;
217 * The ARM Versatile boards are even more special: 268 priv->ctrl = CLCD_PL110_CNTL;
218 * their PrimeCell ID say they are PL110 but the
219 * control and interrupt enable registers are anyway
220 * swapped to the PL111 order so they are not following
221 * the PL110 datasheet.
222 */
223 if (of_machine_is_compatible("arm,versatile-ab") ||
224 of_machine_is_compatible("arm,versatile-pb")) {
225 priv->ienb = CLCD_PL111_IENB;
226 priv->ctrl = CLCD_PL111_CNTL;
227 } else {
228 priv->ienb = CLCD_PL110_IENB;
229 priv->ctrl = CLCD_PL110_CNTL;
230 }
231 } else { 269 } else {
232 priv->ienb = CLCD_PL111_IENB; 270 priv->ienb = CLCD_PL111_IENB;
233 priv->ctrl = CLCD_PL111_CNTL; 271 priv->ctrl = CLCD_PL111_CNTL;
@@ -239,6 +277,11 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
239 return PTR_ERR(priv->regs); 277 return PTR_ERR(priv->regs);
240 } 278 }
241 279
280 /* This may override some variant settings */
281 ret = pl111_versatile_init(dev, priv);
282 if (ret)
283 goto dev_unref;
284
242 /* turn off interrupts before requesting the irq */ 285 /* turn off interrupts before requesting the irq */
243 writel(0, priv->regs + priv->ienb); 286 writel(0, priv->regs + priv->ienb);
244 287
@@ -249,10 +292,6 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
249 return ret; 292 return ret;
250 } 293 }
251 294
252 ret = pl111_versatile_init(dev, priv);
253 if (ret)
254 goto dev_unref;
255
256 ret = pl111_modeset_init(drm); 295 ret = pl111_modeset_init(drm);
257 if (ret != 0) 296 if (ret != 0)
258 goto dev_unref; 297 goto dev_unref;
@@ -284,8 +323,7 @@ static int pl111_amba_remove(struct amba_device *amba_dev)
284} 323}
285 324
286/* 325/*
287 * This variant exist in early versions like the ARM Integrator 326 * This early variant lacks the 565 and 444 pixel formats.
288 * and this version lacks the 565 and 444 pixel formats.
289 */ 327 */
290static const u32 pl110_pixel_formats[] = { 328static const u32 pl110_pixel_formats[] = {
291 DRM_FORMAT_ABGR8888, 329 DRM_FORMAT_ABGR8888,
diff --git a/drivers/gpu/drm/pl111/pl111_versatile.c b/drivers/gpu/drm/pl111/pl111_versatile.c
index 97d4af6925a3..05a4b89e0934 100644
--- a/drivers/gpu/drm/pl111/pl111_versatile.c
+++ b/drivers/gpu/drm/pl111/pl111_versatile.c
@@ -1,3 +1,4 @@
1#include <linux/amba/clcd-regs.h>
1#include <linux/device.h> 2#include <linux/device.h>
2#include <linux/of.h> 3#include <linux/of.h>
3#include <linux/regmap.h> 4#include <linux/regmap.h>
@@ -64,10 +65,8 @@ static const struct of_device_id versatile_clcd_of_match[] = {
64#define INTEGRATOR_CLCD_LCDBIASEN BIT(8) 65#define INTEGRATOR_CLCD_LCDBIASEN BIT(8)
65#define INTEGRATOR_CLCD_LCDBIASUP BIT(9) 66#define INTEGRATOR_CLCD_LCDBIASUP BIT(9)
66#define INTEGRATOR_CLCD_LCDBIASDN BIT(10) 67#define INTEGRATOR_CLCD_LCDBIASDN BIT(10)
67/* Bits 11,12,13 controls the LCD type */ 68/* Bits 11,12,13 controls the LCD or VGA bridge type */
68#define INTEGRATOR_CLCD_LCDMUX_MASK (BIT(11)|BIT(12)|BIT(13))
69#define INTEGRATOR_CLCD_LCDMUX_LCD24 BIT(11) 69#define INTEGRATOR_CLCD_LCDMUX_LCD24 BIT(11)
70#define INTEGRATOR_CLCD_LCDMUX_VGA565 BIT(12)
71#define INTEGRATOR_CLCD_LCDMUX_SHARP (BIT(11)|BIT(12)) 70#define INTEGRATOR_CLCD_LCDMUX_SHARP (BIT(11)|BIT(12))
72#define INTEGRATOR_CLCD_LCDMUX_VGA555 BIT(13) 71#define INTEGRATOR_CLCD_LCDMUX_VGA555 BIT(13)
73#define INTEGRATOR_CLCD_LCDMUX_VGA24 (BIT(11)|BIT(12)|BIT(13)) 72#define INTEGRATOR_CLCD_LCDMUX_VGA24 (BIT(11)|BIT(12)|BIT(13))
@@ -82,16 +81,7 @@ static const struct of_device_id versatile_clcd_of_match[] = {
82/* 0 = 24bit VGA, 1 = 18bit VGA */ 81/* 0 = 24bit VGA, 1 = 18bit VGA */
83#define INTEGRATOR_CLCD_LCD_N24BITEN BIT(19) 82#define INTEGRATOR_CLCD_LCD_N24BITEN BIT(19)
84 83
85#define INTEGRATOR_CLCD_MASK (INTEGRATOR_CLCD_LCDBIASEN | \ 84#define INTEGRATOR_CLCD_MASK GENMASK(19, 8)
86 INTEGRATOR_CLCD_LCDBIASUP | \
87 INTEGRATOR_CLCD_LCDBIASDN | \
88 INTEGRATOR_CLCD_LCDMUX_MASK | \
89 INTEGRATOR_CLCD_LCD0_EN | \
90 INTEGRATOR_CLCD_LCD1_EN | \
91 INTEGRATOR_CLCD_LCD_STATIC1 | \
92 INTEGRATOR_CLCD_LCD_STATIC2 | \
93 INTEGRATOR_CLCD_LCD_STATIC | \
94 INTEGRATOR_CLCD_LCD_N24BITEN)
95 85
96static void pl111_integrator_enable(struct drm_device *drm, u32 format) 86static void pl111_integrator_enable(struct drm_device *drm, u32 format)
97{ 87{
@@ -106,11 +96,8 @@ static void pl111_integrator_enable(struct drm_device *drm, u32 format)
106 switch (format) { 96 switch (format) {
107 case DRM_FORMAT_XBGR8888: 97 case DRM_FORMAT_XBGR8888:
108 case DRM_FORMAT_XRGB8888: 98 case DRM_FORMAT_XRGB8888:
109 break; 99 /* 24bit formats */
110 case DRM_FORMAT_BGR565: 100 val |= INTEGRATOR_CLCD_LCDMUX_VGA24;
111 case DRM_FORMAT_RGB565:
112 /* truecolor RGB565 */
113 val |= INTEGRATOR_CLCD_LCDMUX_VGA565;
114 break; 101 break;
115 case DRM_FORMAT_XBGR1555: 102 case DRM_FORMAT_XBGR1555:
116 case DRM_FORMAT_XRGB1555: 103 case DRM_FORMAT_XRGB1555:
@@ -217,6 +204,57 @@ static void pl111_realview_clcd_enable(struct drm_device *drm, u32 format)
217 SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH); 204 SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH);
218} 205}
219 206
207/* PL110 pixel formats for Integrator, vanilla PL110 */
208static const u32 pl110_integrator_pixel_formats[] = {
209 DRM_FORMAT_ABGR8888,
210 DRM_FORMAT_XBGR8888,
211 DRM_FORMAT_ARGB8888,
212 DRM_FORMAT_XRGB8888,
213 DRM_FORMAT_ABGR1555,
214 DRM_FORMAT_XBGR1555,
215 DRM_FORMAT_ARGB1555,
216 DRM_FORMAT_XRGB1555,
217};
218
219/* Extended PL110 pixel formats for Integrator and Versatile */
220static const u32 pl110_versatile_pixel_formats[] = {
221 DRM_FORMAT_ABGR8888,
222 DRM_FORMAT_XBGR8888,
223 DRM_FORMAT_ARGB8888,
224 DRM_FORMAT_XRGB8888,
225 DRM_FORMAT_BGR565, /* Uses external PLD */
226 DRM_FORMAT_RGB565, /* Uses external PLD */
227 DRM_FORMAT_ABGR1555,
228 DRM_FORMAT_XBGR1555,
229 DRM_FORMAT_ARGB1555,
230 DRM_FORMAT_XRGB1555,
231};
232
233/*
234 * The Integrator variant is a PL110 with a bunch of broken, or not
235 * yet implemented features
236 */
237static const struct pl111_variant_data pl110_integrator = {
238 .name = "PL110 Integrator",
239 .is_pl110 = true,
240 .broken_clockdivider = true,
241 .broken_vblank = true,
242 .formats = pl110_integrator_pixel_formats,
243 .nformats = ARRAY_SIZE(pl110_integrator_pixel_formats),
244};
245
246/*
247 * This is the in-between PL110 variant found in the ARM Versatile,
248 * supporting RGB565/BGR565
249 */
250static const struct pl111_variant_data pl110_versatile = {
251 .name = "PL110 Versatile",
252 .is_pl110 = true,
253 .external_bgr = true,
254 .formats = pl110_versatile_pixel_formats,
255 .nformats = ARRAY_SIZE(pl110_versatile_pixel_formats),
256};
257
220int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv) 258int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv)
221{ 259{
222 const struct of_device_id *clcd_id; 260 const struct of_device_id *clcd_id;
@@ -241,14 +279,24 @@ int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv)
241 switch (versatile_clcd_type) { 279 switch (versatile_clcd_type) {
242 case INTEGRATOR_CLCD_CM: 280 case INTEGRATOR_CLCD_CM:
243 versatile_syscon_map = map; 281 versatile_syscon_map = map;
282 priv->variant = &pl110_integrator;
244 priv->variant_display_enable = pl111_integrator_enable; 283 priv->variant_display_enable = pl111_integrator_enable;
245 dev_info(dev, "set up callbacks for Integrator PL110\n"); 284 dev_info(dev, "set up callbacks for Integrator PL110\n");
246 break; 285 break;
247 case VERSATILE_CLCD: 286 case VERSATILE_CLCD:
248 versatile_syscon_map = map; 287 versatile_syscon_map = map;
288 /* This can do RGB565 with external PLD */
289 priv->variant = &pl110_versatile;
249 priv->variant_display_enable = pl111_versatile_enable; 290 priv->variant_display_enable = pl111_versatile_enable;
250 priv->variant_display_disable = pl111_versatile_disable; 291 priv->variant_display_disable = pl111_versatile_disable;
251 dev_info(dev, "set up callbacks for Versatile PL110+\n"); 292 /*
293 * The Versatile has a variant halfway between PL110
294 * and PL111 where these two registers have already been
295 * swapped.
296 */
297 priv->ienb = CLCD_PL111_IENB;
298 priv->ctrl = CLCD_PL111_CNTL;
299 dev_info(dev, "set up callbacks for Versatile PL110\n");
252 break; 300 break;
253 case REALVIEW_CLCD_EB: 301 case REALVIEW_CLCD_EB:
254 case REALVIEW_CLCD_PB1176: 302 case REALVIEW_CLCD_PB1176:
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index d34887873dea..4a2eb409aacc 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -2387,6 +2387,7 @@ struct radeon_device {
2387 struct radeon_dummy_page dummy_page; 2387 struct radeon_dummy_page dummy_page;
2388 bool shutdown; 2388 bool shutdown;
2389 bool need_dma32; 2389 bool need_dma32;
2390 bool need_swiotlb;
2390 bool accel_working; 2391 bool accel_working;
2391 bool fastfb_working; /* IGP feature*/ 2392 bool fastfb_working; /* IGP feature*/
2392 bool needs_reset, in_reset; 2393 bool needs_reset, in_reset;
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 8d3e3d2e0090..7f40c6f7c4dd 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -29,6 +29,7 @@
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include <drm/drmP.h> 30#include <drm/drmP.h>
31#include <drm/drm_crtc_helper.h> 31#include <drm/drm_crtc_helper.h>
32#include <drm/drm_cache.h>
32#include <drm/radeon_drm.h> 33#include <drm/radeon_drm.h>
33#include <linux/pm_runtime.h> 34#include <linux/pm_runtime.h>
34#include <linux/vgaarb.h> 35#include <linux/vgaarb.h>
@@ -1378,6 +1379,7 @@ int radeon_device_init(struct radeon_device *rdev,
1378 pci_set_consistent_dma_mask(rdev->pdev, DMA_BIT_MASK(32)); 1379 pci_set_consistent_dma_mask(rdev->pdev, DMA_BIT_MASK(32));
1379 pr_warn("radeon: No coherent DMA available\n"); 1380 pr_warn("radeon: No coherent DMA available\n");
1380 } 1381 }
1382 rdev->need_swiotlb = drm_get_max_iomem() > ((u64)1 << dma_bits);
1381 1383
1382 /* Registers mapping */ 1384 /* Registers mapping */
1383 /* TODO: block userspace mapping of io register */ 1385 /* TODO: block userspace mapping of io register */
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
index a0a839bc39bf..c1e3862a48a4 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -756,7 +756,7 @@ static int radeon_ttm_tt_populate(struct ttm_tt *ttm,
756#endif 756#endif
757 757
758#ifdef CONFIG_SWIOTLB 758#ifdef CONFIG_SWIOTLB
759 if (swiotlb_nr_tbl()) { 759 if (rdev->need_swiotlb && swiotlb_nr_tbl()) {
760 return ttm_dma_populate(&gtt->ttm, rdev->dev, ctx); 760 return ttm_dma_populate(&gtt->ttm, rdev->dev, ctx);
761 } 761 }
762#endif 762#endif
@@ -788,7 +788,7 @@ static void radeon_ttm_tt_unpopulate(struct ttm_tt *ttm)
788#endif 788#endif
789 789
790#ifdef CONFIG_SWIOTLB 790#ifdef CONFIG_SWIOTLB
791 if (swiotlb_nr_tbl()) { 791 if (rdev->need_swiotlb && swiotlb_nr_tbl()) {
792 ttm_dma_unpopulate(&gtt->ttm, rdev->dev); 792 ttm_dma_unpopulate(&gtt->ttm, rdev->dev);
793 return; 793 return;
794 } 794 }
@@ -1155,7 +1155,7 @@ static int radeon_ttm_debugfs_init(struct radeon_device *rdev)
1155 count = ARRAY_SIZE(radeon_ttm_debugfs_list); 1155 count = ARRAY_SIZE(radeon_ttm_debugfs_list);
1156 1156
1157#ifdef CONFIG_SWIOTLB 1157#ifdef CONFIG_SWIOTLB
1158 if (!swiotlb_nr_tbl()) 1158 if (!(rdev->need_swiotlb && swiotlb_nr_tbl()))
1159 --count; 1159 --count;
1160#endif 1160#endif
1161 1161
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index 4a3d16cf3ed6..5687a94d4cb1 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -572,7 +572,7 @@ int __rcar_du_plane_atomic_check(struct drm_plane *plane,
572{ 572{
573 struct drm_device *dev = plane->dev; 573 struct drm_device *dev = plane->dev;
574 struct drm_crtc_state *crtc_state; 574 struct drm_crtc_state *crtc_state;
575 struct drm_rect clip; 575 struct drm_rect clip = {};
576 int ret; 576 int ret;
577 577
578 if (!state->crtc) { 578 if (!state->crtc) {
@@ -589,10 +589,9 @@ int __rcar_du_plane_atomic_check(struct drm_plane *plane,
589 if (IS_ERR(crtc_state)) 589 if (IS_ERR(crtc_state))
590 return PTR_ERR(crtc_state); 590 return PTR_ERR(crtc_state);
591 591
592 clip.x1 = 0; 592 if (crtc_state->enable)
593 clip.y1 = 0; 593 drm_mode_get_hv_timing(&crtc_state->mode,
594 clip.x2 = crtc_state->mode.hdisplay; 594 &clip.x2, &clip.y2);
595 clip.y2 = crtc_state->mode.vdisplay;
596 595
597 ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip, 596 ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
598 DRM_PLANE_HELPER_NO_SCALING, 597 DRM_PLANE_HELPER_NO_SCALING,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index ba7505292b78..7715853ef90a 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -253,17 +253,6 @@ static bool is_yuv_support(uint32_t format)
253 } 253 }
254} 254}
255 255
256static bool is_alpha_support(uint32_t format)
257{
258 switch (format) {
259 case DRM_FORMAT_ARGB8888:
260 case DRM_FORMAT_ABGR8888:
261 return true;
262 default:
263 return false;
264 }
265}
266
267static uint16_t scl_vop_cal_scale(enum scale_mode mode, uint32_t src, 256static uint16_t scl_vop_cal_scale(enum scale_mode mode, uint32_t src,
268 uint32_t dst, bool is_horizontal, 257 uint32_t dst, bool is_horizontal,
269 int vsu_mode, int *vskiplines) 258 int vsu_mode, int *vskiplines)
@@ -641,7 +630,7 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
641 struct vop_win *vop_win = to_vop_win(plane); 630 struct vop_win *vop_win = to_vop_win(plane);
642 const struct vop_win_data *win = vop_win->data; 631 const struct vop_win_data *win = vop_win->data;
643 int ret; 632 int ret;
644 struct drm_rect clip; 633 struct drm_rect clip = {};
645 int min_scale = win->phy->scl ? FRAC_16_16(1, 8) : 634 int min_scale = win->phy->scl ? FRAC_16_16(1, 8) :
646 DRM_PLANE_HELPER_NO_SCALING; 635 DRM_PLANE_HELPER_NO_SCALING;
647 int max_scale = win->phy->scl ? FRAC_16_16(8, 1) : 636 int max_scale = win->phy->scl ? FRAC_16_16(8, 1) :
@@ -654,10 +643,9 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
654 if (WARN_ON(!crtc_state)) 643 if (WARN_ON(!crtc_state))
655 return -EINVAL; 644 return -EINVAL;
656 645
657 clip.x1 = 0; 646 if (crtc_state->enable)
658 clip.y1 = 0; 647 drm_mode_get_hv_timing(&crtc_state->mode,
659 clip.x2 = crtc_state->adjusted_mode.hdisplay; 648 &clip.x2, &clip.y2);
660 clip.y2 = crtc_state->adjusted_mode.vdisplay;
661 649
662 ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip, 650 ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
663 min_scale, max_scale, 651 min_scale, max_scale,
@@ -790,7 +778,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
790 rb_swap = has_rb_swapped(fb->format->format); 778 rb_swap = has_rb_swapped(fb->format->format);
791 VOP_WIN_SET(vop, win, rb_swap, rb_swap); 779 VOP_WIN_SET(vop, win, rb_swap, rb_swap);
792 780
793 if (is_alpha_support(fb->format->format)) { 781 if (fb->format->has_alpha) {
794 VOP_WIN_SET(vop, win, dst_alpha_ctl, 782 VOP_WIN_SET(vop, win, dst_alpha_ctl,
795 DST_FACTOR_M0(ALPHA_SRC_INVERSE)); 783 DST_FACTOR_M0(ALPHA_SRC_INVERSE));
796 val = SRC_ALPHA_EN(1) | SRC_COLOR_M0(ALPHA_SRC_PRE_MUL) | 784 val = SRC_ALPHA_EN(1) | SRC_COLOR_M0(ALPHA_SRC_PRE_MUL) |
diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c
index 8fe954c27fba..8bc7e8418b8d 100644
--- a/drivers/gpu/drm/stm/drv.c
+++ b/drivers/gpu/drm/stm/drv.c
@@ -31,6 +31,24 @@ static const struct drm_mode_config_funcs drv_mode_config_funcs = {
31 .atomic_commit = drm_atomic_helper_commit, 31 .atomic_commit = drm_atomic_helper_commit,
32}; 32};
33 33
34static int stm_gem_cma_dumb_create(struct drm_file *file,
35 struct drm_device *dev,
36 struct drm_mode_create_dumb *args)
37{
38#ifdef CONFIG_MMU
39 unsigned int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
40
41 /*
42 * in order to optimize data transfer, pitch is aligned on
43 * 128 bytes, height is aligned on 4 bytes
44 */
45 args->pitch = roundup(min_pitch, 128);
46 args->height = roundup(args->height, 4);
47#endif
48
49 return drm_gem_cma_dumb_create_internal(file, dev, args);
50}
51
34DEFINE_DRM_GEM_CMA_FOPS(drv_driver_fops); 52DEFINE_DRM_GEM_CMA_FOPS(drv_driver_fops);
35 53
36static struct drm_driver drv_driver = { 54static struct drm_driver drv_driver = {
@@ -44,7 +62,7 @@ static struct drm_driver drv_driver = {
44 .minor = 0, 62 .minor = 0,
45 .patchlevel = 0, 63 .patchlevel = 0,
46 .fops = &drv_driver_fops, 64 .fops = &drv_driver_fops,
47 .dumb_create = drm_gem_cma_dumb_create, 65 .dumb_create = stm_gem_cma_dumb_create,
48 .prime_handle_to_fd = drm_gem_prime_handle_to_fd, 66 .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
49 .prime_fd_to_handle = drm_gem_prime_fd_to_handle, 67 .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
50 .gem_free_object_unlocked = drm_gem_cma_free_object, 68 .gem_free_object_unlocked = drm_gem_cma_free_object,
diff --git a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
index fd02506274da..a514b593f37c 100644
--- a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
+++ b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
@@ -14,7 +14,14 @@
14#include <drm/bridge/dw_mipi_dsi.h> 14#include <drm/bridge/dw_mipi_dsi.h>
15#include <video/mipi_display.h> 15#include <video/mipi_display.h>
16 16
17/* DSI wrapper register & bit definitions */ 17#define HWVER_130 0x31333000 /* IP version 1.30 */
18#define HWVER_131 0x31333100 /* IP version 1.31 */
19
20/* DSI digital registers & bit definitions */
21#define DSI_VERSION 0x00
22#define VERSION GENMASK(31, 8)
23
24/* DSI wrapper registers & bit definitions */
18/* Note: registers are named as in the Reference Manual */ 25/* Note: registers are named as in the Reference Manual */
19#define DSI_WCFGR 0x0400 /* Wrapper ConFiGuration Reg */ 26#define DSI_WCFGR 0x0400 /* Wrapper ConFiGuration Reg */
20#define WCFGR_DSIM BIT(0) /* DSI Mode */ 27#define WCFGR_DSIM BIT(0) /* DSI Mode */
@@ -65,6 +72,10 @@ enum dsi_color {
65struct dw_mipi_dsi_stm { 72struct dw_mipi_dsi_stm {
66 void __iomem *base; 73 void __iomem *base;
67 struct clk *pllref_clk; 74 struct clk *pllref_clk;
75 struct dw_mipi_dsi *dsi;
76 u32 hw_version;
77 int lane_min_kbps;
78 int lane_max_kbps;
68}; 79};
69 80
70static inline void dsi_write(struct dw_mipi_dsi_stm *dsi, u32 reg, u32 val) 81static inline void dsi_write(struct dw_mipi_dsi_stm *dsi, u32 reg, u32 val)
@@ -121,7 +132,8 @@ static int dsi_pll_get_clkout_khz(int clkin_khz, int idf, int ndiv, int odf)
121 return DIV_ROUND_CLOSEST(clkin_khz * ndiv, divisor); 132 return DIV_ROUND_CLOSEST(clkin_khz * ndiv, divisor);
122} 133}
123 134
124static int dsi_pll_get_params(int clkin_khz, int clkout_khz, 135static int dsi_pll_get_params(struct dw_mipi_dsi_stm *dsi,
136 int clkin_khz, int clkout_khz,
125 int *idf, int *ndiv, int *odf) 137 int *idf, int *ndiv, int *odf)
126{ 138{
127 int i, o, n, n_min, n_max; 139 int i, o, n, n_min, n_max;
@@ -131,8 +143,8 @@ static int dsi_pll_get_params(int clkin_khz, int clkout_khz,
131 if (clkin_khz <= 0 || clkout_khz <= 0) 143 if (clkin_khz <= 0 || clkout_khz <= 0)
132 return -EINVAL; 144 return -EINVAL;
133 145
134 fvco_min = LANE_MIN_KBPS * 2 * ODF_MAX; 146 fvco_min = dsi->lane_min_kbps * 2 * ODF_MAX;
135 fvco_max = LANE_MAX_KBPS * 2 * ODF_MIN; 147 fvco_max = dsi->lane_max_kbps * 2 * ODF_MIN;
136 148
137 best_delta = 1000000; /* big started value (1000000khz) */ 149 best_delta = 1000000; /* big started value (1000000khz) */
138 150
@@ -212,6 +224,15 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, struct drm_display_mode *mode,
212 int ret, bpp; 224 int ret, bpp;
213 u32 val; 225 u32 val;
214 226
227 /* Update lane capabilities according to hw version */
228 dsi->hw_version = dsi_read(dsi, DSI_VERSION) & VERSION;
229 dsi->lane_min_kbps = LANE_MIN_KBPS;
230 dsi->lane_max_kbps = LANE_MAX_KBPS;
231 if (dsi->hw_version == HWVER_131) {
232 dsi->lane_min_kbps *= 2;
233 dsi->lane_max_kbps *= 2;
234 }
235
215 pll_in_khz = (unsigned int)(clk_get_rate(dsi->pllref_clk) / 1000); 236 pll_in_khz = (unsigned int)(clk_get_rate(dsi->pllref_clk) / 1000);
216 237
217 /* Compute requested pll out */ 238 /* Compute requested pll out */
@@ -219,12 +240,12 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, struct drm_display_mode *mode,
219 pll_out_khz = mode->clock * bpp / lanes; 240 pll_out_khz = mode->clock * bpp / lanes;
220 /* Add 20% to pll out to be higher than pixel bw (burst mode only) */ 241 /* Add 20% to pll out to be higher than pixel bw (burst mode only) */
221 pll_out_khz = (pll_out_khz * 12) / 10; 242 pll_out_khz = (pll_out_khz * 12) / 10;
222 if (pll_out_khz > LANE_MAX_KBPS) { 243 if (pll_out_khz > dsi->lane_max_kbps) {
223 pll_out_khz = LANE_MAX_KBPS; 244 pll_out_khz = dsi->lane_max_kbps;
224 DRM_WARN("Warning max phy mbps is used\n"); 245 DRM_WARN("Warning max phy mbps is used\n");
225 } 246 }
226 if (pll_out_khz < LANE_MIN_KBPS) { 247 if (pll_out_khz < dsi->lane_min_kbps) {
227 pll_out_khz = LANE_MIN_KBPS; 248 pll_out_khz = dsi->lane_min_kbps;
228 DRM_WARN("Warning min phy mbps is used\n"); 249 DRM_WARN("Warning min phy mbps is used\n");
229 } 250 }
230 251
@@ -232,7 +253,8 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, struct drm_display_mode *mode,
232 idf = 0; 253 idf = 0;
233 ndiv = 0; 254 ndiv = 0;
234 odf = 0; 255 odf = 0;
235 ret = dsi_pll_get_params(pll_in_khz, pll_out_khz, &idf, &ndiv, &odf); 256 ret = dsi_pll_get_params(dsi, pll_in_khz, pll_out_khz,
257 &idf, &ndiv, &odf);
236 if (ret) 258 if (ret)
237 DRM_WARN("Warning dsi_pll_get_params(): bad params\n"); 259 DRM_WARN("Warning dsi_pll_get_params(): bad params\n");
238 260
@@ -312,21 +334,24 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev)
312 dw_mipi_dsi_stm_plat_data.base = dsi->base; 334 dw_mipi_dsi_stm_plat_data.base = dsi->base;
313 dw_mipi_dsi_stm_plat_data.priv_data = dsi; 335 dw_mipi_dsi_stm_plat_data.priv_data = dsi;
314 336
315 ret = dw_mipi_dsi_probe(pdev, &dw_mipi_dsi_stm_plat_data); 337 platform_set_drvdata(pdev, dsi);
316 if (ret) { 338
339 dsi->dsi = dw_mipi_dsi_probe(pdev, &dw_mipi_dsi_stm_plat_data);
340 if (IS_ERR(dsi->dsi)) {
317 DRM_ERROR("Failed to initialize mipi dsi host\n"); 341 DRM_ERROR("Failed to initialize mipi dsi host\n");
318 clk_disable_unprepare(dsi->pllref_clk); 342 clk_disable_unprepare(dsi->pllref_clk);
343 return PTR_ERR(dsi->dsi);
319 } 344 }
320 345
321 return ret; 346 return 0;
322} 347}
323 348
324static int dw_mipi_dsi_stm_remove(struct platform_device *pdev) 349static int dw_mipi_dsi_stm_remove(struct platform_device *pdev)
325{ 350{
326 struct dw_mipi_dsi_stm *dsi = dw_mipi_dsi_stm_plat_data.priv_data; 351 struct dw_mipi_dsi_stm *dsi = platform_get_drvdata(pdev);
327 352
328 clk_disable_unprepare(dsi->pllref_clk); 353 clk_disable_unprepare(dsi->pllref_clk);
329 dw_mipi_dsi_remove(pdev); 354 dw_mipi_dsi_remove(dsi->dsi);
330 355
331 return 0; 356 return 0;
332} 357}
diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c
index 6dc5d4ec4e17..1a3277e483d5 100644
--- a/drivers/gpu/drm/stm/ltdc.c
+++ b/drivers/gpu/drm/stm/ltdc.c
@@ -175,6 +175,8 @@
175 175
176#define LXCFBLNR_CFBLN GENMASK(10, 0) /* Color Frame Buffer Line Number */ 176#define LXCFBLNR_CFBLN GENMASK(10, 0) /* Color Frame Buffer Line Number */
177 177
178#define CLUT_SIZE 256
179
178#define CONSTA_MAX 0xFF /* CONSTant Alpha MAX= 1.0 */ 180#define CONSTA_MAX 0xFF /* CONSTant Alpha MAX= 1.0 */
179#define BF1_PAXCA 0x600 /* Pixel Alpha x Constant Alpha */ 181#define BF1_PAXCA 0x600 /* Pixel Alpha x Constant Alpha */
180#define BF1_CA 0x400 /* Constant Alpha */ 182#define BF1_CA 0x400 /* Constant Alpha */
@@ -326,6 +328,26 @@ static inline u32 to_drm_pixelformat(enum ltdc_pix_fmt pf)
326 } 328 }
327} 329}
328 330
331static inline u32 get_pixelformat_without_alpha(u32 drm)
332{
333 switch (drm) {
334 case DRM_FORMAT_ARGB4444:
335 return DRM_FORMAT_XRGB4444;
336 case DRM_FORMAT_RGBA4444:
337 return DRM_FORMAT_RGBX4444;
338 case DRM_FORMAT_ARGB1555:
339 return DRM_FORMAT_XRGB1555;
340 case DRM_FORMAT_RGBA5551:
341 return DRM_FORMAT_RGBX5551;
342 case DRM_FORMAT_ARGB8888:
343 return DRM_FORMAT_XRGB8888;
344 case DRM_FORMAT_RGBA8888:
345 return DRM_FORMAT_RGBX8888;
346 default:
347 return 0;
348 }
349}
350
329static irqreturn_t ltdc_irq_thread(int irq, void *arg) 351static irqreturn_t ltdc_irq_thread(int irq, void *arg)
330{ 352{
331 struct drm_device *ddev = arg; 353 struct drm_device *ddev = arg;
@@ -363,6 +385,28 @@ static irqreturn_t ltdc_irq(int irq, void *arg)
363 * DRM_CRTC 385 * DRM_CRTC
364 */ 386 */
365 387
388static void ltdc_crtc_update_clut(struct drm_crtc *crtc)
389{
390 struct ltdc_device *ldev = crtc_to_ltdc(crtc);
391 struct drm_color_lut *lut;
392 u32 val;
393 int i;
394
395 if (!crtc || !crtc->state)
396 return;
397
398 if (!crtc->state->color_mgmt_changed || !crtc->state->gamma_lut)
399 return;
400
401 lut = (struct drm_color_lut *)crtc->state->gamma_lut->data;
402
403 for (i = 0; i < CLUT_SIZE; i++, lut++) {
404 val = ((lut->red << 8) & 0xff0000) | (lut->green & 0xff00) |
405 (lut->blue >> 8) | (i << 24);
406 reg_write(ldev->regs, LTDC_L1CLUTWR, val);
407 }
408}
409
366static void ltdc_crtc_atomic_enable(struct drm_crtc *crtc, 410static void ltdc_crtc_atomic_enable(struct drm_crtc *crtc,
367 struct drm_crtc_state *old_state) 411 struct drm_crtc_state *old_state)
368{ 412{
@@ -404,12 +448,35 @@ static void ltdc_crtc_atomic_disable(struct drm_crtc *crtc,
404 reg_set(ldev->regs, LTDC_SRCR, SRCR_IMR); 448 reg_set(ldev->regs, LTDC_SRCR, SRCR_IMR);
405} 449}
406 450
451static bool ltdc_crtc_mode_fixup(struct drm_crtc *crtc,
452 const struct drm_display_mode *mode,
453 struct drm_display_mode *adjusted_mode)
454{
455 struct ltdc_device *ldev = crtc_to_ltdc(crtc);
456 int rate = mode->clock * 1000;
457
458 /*
459 * TODO clk_round_rate() does not work yet. When ready, it can
460 * be used instead of clk_set_rate() then clk_get_rate().
461 */
462
463 clk_disable(ldev->pixel_clk);
464 if (clk_set_rate(ldev->pixel_clk, rate) < 0) {
465 DRM_ERROR("Cannot set rate (%dHz) for pixel clk\n", rate);
466 return false;
467 }
468 clk_enable(ldev->pixel_clk);
469
470 adjusted_mode->clock = clk_get_rate(ldev->pixel_clk) / 1000;
471
472 return true;
473}
474
407static void ltdc_crtc_mode_set_nofb(struct drm_crtc *crtc) 475static void ltdc_crtc_mode_set_nofb(struct drm_crtc *crtc)
408{ 476{
409 struct ltdc_device *ldev = crtc_to_ltdc(crtc); 477 struct ltdc_device *ldev = crtc_to_ltdc(crtc);
410 struct drm_display_mode *mode = &crtc->state->adjusted_mode; 478 struct drm_display_mode *mode = &crtc->state->adjusted_mode;
411 struct videomode vm; 479 struct videomode vm;
412 int rate = mode->clock * 1000;
413 u32 hsync, vsync, accum_hbp, accum_vbp, accum_act_w, accum_act_h; 480 u32 hsync, vsync, accum_hbp, accum_vbp, accum_act_w, accum_act_h;
414 u32 total_width, total_height; 481 u32 total_width, total_height;
415 u32 val; 482 u32 val;
@@ -432,15 +499,6 @@ static void ltdc_crtc_mode_set_nofb(struct drm_crtc *crtc)
432 total_width = accum_act_w + vm.hfront_porch; 499 total_width = accum_act_w + vm.hfront_porch;
433 total_height = accum_act_h + vm.vfront_porch; 500 total_height = accum_act_h + vm.vfront_porch;
434 501
435 clk_disable(ldev->pixel_clk);
436
437 if (clk_set_rate(ldev->pixel_clk, rate) < 0) {
438 DRM_ERROR("Cannot set rate (%dHz) for pixel clk\n", rate);
439 return;
440 }
441
442 clk_enable(ldev->pixel_clk);
443
444 /* Configures the HS, VS, DE and PC polarities. Default Active Low */ 502 /* Configures the HS, VS, DE and PC polarities. Default Active Low */
445 val = 0; 503 val = 0;
446 504
@@ -486,6 +544,8 @@ static void ltdc_crtc_atomic_flush(struct drm_crtc *crtc,
486 544
487 DRM_DEBUG_ATOMIC("\n"); 545 DRM_DEBUG_ATOMIC("\n");
488 546
547 ltdc_crtc_update_clut(crtc);
548
489 /* Commit shadow registers = update planes at next vblank */ 549 /* Commit shadow registers = update planes at next vblank */
490 reg_set(ldev->regs, LTDC_SRCR, SRCR_VBR); 550 reg_set(ldev->regs, LTDC_SRCR, SRCR_VBR);
491 551
@@ -502,6 +562,7 @@ static void ltdc_crtc_atomic_flush(struct drm_crtc *crtc,
502} 562}
503 563
504static const struct drm_crtc_helper_funcs ltdc_crtc_helper_funcs = { 564static const struct drm_crtc_helper_funcs ltdc_crtc_helper_funcs = {
565 .mode_fixup = ltdc_crtc_mode_fixup,
505 .mode_set_nofb = ltdc_crtc_mode_set_nofb, 566 .mode_set_nofb = ltdc_crtc_mode_set_nofb,
506 .atomic_flush = ltdc_crtc_atomic_flush, 567 .atomic_flush = ltdc_crtc_atomic_flush,
507 .atomic_enable = ltdc_crtc_atomic_enable, 568 .atomic_enable = ltdc_crtc_atomic_enable,
@@ -533,6 +594,7 @@ static const struct drm_crtc_funcs ltdc_crtc_funcs = {
533 .reset = drm_atomic_helper_crtc_reset, 594 .reset = drm_atomic_helper_crtc_reset,
534 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, 595 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
535 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, 596 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
597 .gamma_set = drm_atomic_helper_legacy_gamma_set,
536}; 598};
537 599
538/* 600/*
@@ -638,6 +700,14 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane,
638 700
639 /* Specifies the blending factors */ 701 /* Specifies the blending factors */
640 val = BF1_PAXCA | BF2_1PAXCA; 702 val = BF1_PAXCA | BF2_1PAXCA;
703 if (!fb->format->has_alpha)
704 val = BF1_CA | BF2_1CA;
705
706 /* Manage hw-specific capabilities */
707 if (ldev->caps.non_alpha_only_l1 &&
708 plane->type != DRM_PLANE_TYPE_PRIMARY)
709 val = BF1_PAXCA | BF2_1PAXCA;
710
641 reg_update_bits(ldev->regs, LTDC_L1BFCR + lofs, 711 reg_update_bits(ldev->regs, LTDC_L1BFCR + lofs,
642 LXBFCR_BF2 | LXBFCR_BF1, val); 712 LXBFCR_BF2 | LXBFCR_BF1, val);
643 713
@@ -705,8 +775,8 @@ static struct drm_plane *ltdc_plane_create(struct drm_device *ddev,
705 struct device *dev = ddev->dev; 775 struct device *dev = ddev->dev;
706 struct drm_plane *plane; 776 struct drm_plane *plane;
707 unsigned int i, nb_fmt = 0; 777 unsigned int i, nb_fmt = 0;
708 u32 formats[NB_PF]; 778 u32 formats[NB_PF * 2];
709 u32 drm_fmt; 779 u32 drm_fmt, drm_fmt_no_alpha;
710 int ret; 780 int ret;
711 781
712 /* Get supported pixel formats */ 782 /* Get supported pixel formats */
@@ -715,6 +785,18 @@ static struct drm_plane *ltdc_plane_create(struct drm_device *ddev,
715 if (!drm_fmt) 785 if (!drm_fmt)
716 continue; 786 continue;
717 formats[nb_fmt++] = drm_fmt; 787 formats[nb_fmt++] = drm_fmt;
788
789 /* Add the no-alpha related format if any & supported */
790 drm_fmt_no_alpha = get_pixelformat_without_alpha(drm_fmt);
791 if (!drm_fmt_no_alpha)
792 continue;
793
794 /* Manage hw-specific capabilities */
795 if (ldev->caps.non_alpha_only_l1 &&
796 type != DRM_PLANE_TYPE_PRIMARY)
797 continue;
798
799 formats[nb_fmt++] = drm_fmt_no_alpha;
718 } 800 }
719 801
720 plane = devm_kzalloc(dev, sizeof(*plane), GFP_KERNEL); 802 plane = devm_kzalloc(dev, sizeof(*plane), GFP_KERNEL);
@@ -765,6 +847,9 @@ static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc)
765 847
766 drm_crtc_helper_add(crtc, &ltdc_crtc_helper_funcs); 848 drm_crtc_helper_add(crtc, &ltdc_crtc_helper_funcs);
767 849
850 drm_mode_crtc_set_gamma_size(crtc, CLUT_SIZE);
851 drm_crtc_enable_color_mgmt(crtc, 0, false, CLUT_SIZE);
852
768 DRM_DEBUG_DRIVER("CRTC:%d created\n", crtc->base.id); 853 DRM_DEBUG_DRIVER("CRTC:%d created\n", crtc->base.id);
769 854
770 /* Add planes. Note : the first layer is used by primary plane */ 855 /* Add planes. Note : the first layer is used by primary plane */
@@ -839,10 +924,19 @@ static int ltdc_get_caps(struct drm_device *ddev)
839 case HWVER_10300: 924 case HWVER_10300:
840 ldev->caps.reg_ofs = REG_OFS_NONE; 925 ldev->caps.reg_ofs = REG_OFS_NONE;
841 ldev->caps.pix_fmt_hw = ltdc_pix_fmt_a0; 926 ldev->caps.pix_fmt_hw = ltdc_pix_fmt_a0;
927 /*
928 * Hw older versions support non-alpha color formats derived
929 * from native alpha color formats only on the primary layer.
930 * For instance, RG16 native format without alpha works fine
931 * on 2nd layer but XR24 (derived color format from AR24)
932 * does not work on 2nd layer.
933 */
934 ldev->caps.non_alpha_only_l1 = true;
842 break; 935 break;
843 case HWVER_20101: 936 case HWVER_20101:
844 ldev->caps.reg_ofs = REG_OFS_4; 937 ldev->caps.reg_ofs = REG_OFS_4;
845 ldev->caps.pix_fmt_hw = ltdc_pix_fmt_a1; 938 ldev->caps.pix_fmt_hw = ltdc_pix_fmt_a1;
939 ldev->caps.non_alpha_only_l1 = false;
846 break; 940 break;
847 default: 941 default:
848 return -ENODEV; 942 return -ENODEV;
diff --git a/drivers/gpu/drm/stm/ltdc.h b/drivers/gpu/drm/stm/ltdc.h
index edd1c0a446d1..edb268129c54 100644
--- a/drivers/gpu/drm/stm/ltdc.h
+++ b/drivers/gpu/drm/stm/ltdc.h
@@ -17,6 +17,7 @@ struct ltdc_caps {
17 u32 reg_ofs; /* register offset for applicable regs */ 17 u32 reg_ofs; /* register offset for applicable regs */
18 u32 bus_width; /* bus width (32 or 64 bits) */ 18 u32 bus_width; /* bus width (32 or 64 bits) */
19 const u32 *pix_fmt_hw; /* supported pixel formats */ 19 const u32 *pix_fmt_hw; /* supported pixel formats */
20 bool non_alpha_only_l1; /* non-native no-alpha formats on layer 1 */
20}; 21};
21 22
22struct ltdc_device { 23struct ltdc_device {
diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index 2b37a6abbb1d..582607c0c488 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -1,5 +1,6 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
2sun4i-backend-y += sun4i_backend.o sun4i_layer.o 2sun4i-backend-y += sun4i_backend.o sun4i_layer.o
3sun4i-frontend-y += sun4i_frontend.o
3 4
4sun4i-drm-y += sun4i_drv.o 5sun4i-drm-y += sun4i_drv.o
5sun4i-drm-y += sun4i_framebuffer.o 6sun4i-drm-y += sun4i_framebuffer.o
@@ -24,6 +25,6 @@ obj-$(CONFIG_DRM_SUN4I) += sun4i-tcon.o
24obj-$(CONFIG_DRM_SUN4I) += sun4i_tv.o 25obj-$(CONFIG_DRM_SUN4I) += sun4i_tv.o
25obj-$(CONFIG_DRM_SUN4I) += sun6i_drc.o 26obj-$(CONFIG_DRM_SUN4I) += sun6i_drc.o
26 27
27obj-$(CONFIG_DRM_SUN4I_BACKEND) += sun4i-backend.o 28obj-$(CONFIG_DRM_SUN4I_BACKEND) += sun4i-backend.o sun4i-frontend.o
28obj-$(CONFIG_DRM_SUN4I_HDMI) += sun4i-drm-hdmi.o 29obj-$(CONFIG_DRM_SUN4I_HDMI) += sun4i-drm-hdmi.o
29obj-$(CONFIG_DRM_SUN8I_MIXER) += sun8i-mixer.o 30obj-$(CONFIG_DRM_SUN8I_MIXER) += sun8i-mixer.o
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index 847eecbe4d14..245b189fc4d8 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -11,6 +11,7 @@
11 */ 11 */
12 12
13#include <drm/drmP.h> 13#include <drm/drmP.h>
14#include <drm/drm_atomic.h>
14#include <drm/drm_atomic_helper.h> 15#include <drm/drm_atomic_helper.h>
15#include <drm/drm_crtc.h> 16#include <drm/drm_crtc.h>
16#include <drm/drm_crtc_helper.h> 17#include <drm/drm_crtc_helper.h>
@@ -26,6 +27,7 @@
26 27
27#include "sun4i_backend.h" 28#include "sun4i_backend.h"
28#include "sun4i_drv.h" 29#include "sun4i_drv.h"
30#include "sun4i_frontend.h"
29#include "sun4i_layer.h" 31#include "sun4i_layer.h"
30#include "sunxi_engine.h" 32#include "sunxi_engine.h"
31 33
@@ -93,7 +95,7 @@ void sun4i_backend_layer_enable(struct sun4i_backend *backend,
93static int sun4i_backend_drm_format_to_layer(struct drm_plane *plane, 95static int sun4i_backend_drm_format_to_layer(struct drm_plane *plane,
94 u32 format, u32 *mode) 96 u32 format, u32 *mode)
95{ 97{
96 if ((plane->type == DRM_PLANE_TYPE_PRIMARY) && 98 if (plane && (plane->type == DRM_PLANE_TYPE_PRIMARY) &&
97 (format == DRM_FORMAT_ARGB8888)) 99 (format == DRM_FORMAT_ARGB8888))
98 format = DRM_FORMAT_XRGB8888; 100 format = DRM_FORMAT_XRGB8888;
99 101
@@ -141,7 +143,6 @@ int sun4i_backend_update_layer_coord(struct sun4i_backend *backend,
141 int layer, struct drm_plane *plane) 143 int layer, struct drm_plane *plane)
142{ 144{
143 struct drm_plane_state *state = plane->state; 145 struct drm_plane_state *state = plane->state;
144 struct drm_framebuffer *fb = state->fb;
145 146
146 DRM_DEBUG_DRIVER("Updating layer %d\n", layer); 147 DRM_DEBUG_DRIVER("Updating layer %d\n", layer);
147 148
@@ -153,12 +154,6 @@ int sun4i_backend_update_layer_coord(struct sun4i_backend *backend,
153 state->crtc_h)); 154 state->crtc_h));
154 } 155 }
155 156
156 /* Set the line width */
157 DRM_DEBUG_DRIVER("Layer line width: %d bits\n", fb->pitches[0] * 8);
158 regmap_write(backend->engine.regs,
159 SUN4I_BACKEND_LAYLINEWIDTH_REG(layer),
160 fb->pitches[0] * 8);
161
162 /* Set height and width */ 157 /* Set height and width */
163 DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n", 158 DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n",
164 state->crtc_w, state->crtc_h); 159 state->crtc_w, state->crtc_h);
@@ -210,6 +205,30 @@ int sun4i_backend_update_layer_formats(struct sun4i_backend *backend,
210 return 0; 205 return 0;
211} 206}
212 207
208int sun4i_backend_update_layer_frontend(struct sun4i_backend *backend,
209 int layer, uint32_t fmt)
210{
211 u32 val;
212 int ret;
213
214 ret = sun4i_backend_drm_format_to_layer(NULL, fmt, &val);
215 if (ret) {
216 DRM_DEBUG_DRIVER("Invalid format\n");
217 return ret;
218 }
219
220 regmap_update_bits(backend->engine.regs,
221 SUN4I_BACKEND_ATTCTL_REG0(layer),
222 SUN4I_BACKEND_ATTCTL_REG0_LAY_VDOEN,
223 SUN4I_BACKEND_ATTCTL_REG0_LAY_VDOEN);
224
225 regmap_update_bits(backend->engine.regs,
226 SUN4I_BACKEND_ATTCTL_REG1(layer),
227 SUN4I_BACKEND_ATTCTL_REG1_LAY_FBFMT, val);
228
229 return 0;
230}
231
213int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend, 232int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend,
214 int layer, struct drm_plane *plane) 233 int layer, struct drm_plane *plane)
215{ 234{
@@ -218,6 +237,12 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend,
218 u32 lo_paddr, hi_paddr; 237 u32 lo_paddr, hi_paddr;
219 dma_addr_t paddr; 238 dma_addr_t paddr;
220 239
240 /* Set the line width */
241 DRM_DEBUG_DRIVER("Layer line width: %d bits\n", fb->pitches[0] * 8);
242 regmap_write(backend->engine.regs,
243 SUN4I_BACKEND_LAYLINEWIDTH_REG(layer),
244 fb->pitches[0] * 8);
245
221 /* Get the start of the displayed memory */ 246 /* Get the start of the displayed memory */
222 paddr = drm_fb_cma_get_gem_addr(fb, state, 0); 247 paddr = drm_fb_cma_get_gem_addr(fb, state, 0);
223 DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr); 248 DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
@@ -246,6 +271,176 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend,
246 return 0; 271 return 0;
247} 272}
248 273
274int sun4i_backend_update_layer_zpos(struct sun4i_backend *backend, int layer,
275 struct drm_plane *plane)
276{
277 struct drm_plane_state *state = plane->state;
278 unsigned int priority = state->normalized_zpos;
279
280 DRM_DEBUG_DRIVER("Setting layer %d's priority to %d\n", layer, priority);
281
282 regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_ATTCTL_REG0(layer),
283 SUN4I_BACKEND_ATTCTL_REG0_LAY_PRISEL_MASK,
284 SUN4I_BACKEND_ATTCTL_REG0_LAY_PRISEL(priority));
285
286 return 0;
287}
288
289static bool sun4i_backend_plane_uses_scaler(struct drm_plane_state *state)
290{
291 u16 src_h = state->src_h >> 16;
292 u16 src_w = state->src_w >> 16;
293
294 DRM_DEBUG_DRIVER("Input size %dx%d, output size %dx%d\n",
295 src_w, src_h, state->crtc_w, state->crtc_h);
296
297 if ((state->crtc_h != src_h) || (state->crtc_w != src_w))
298 return true;
299
300 return false;
301}
302
303static bool sun4i_backend_plane_uses_frontend(struct drm_plane_state *state)
304{
305 struct sun4i_layer *layer = plane_to_sun4i_layer(state->plane);
306 struct sun4i_backend *backend = layer->backend;
307
308 if (IS_ERR(backend->frontend))
309 return false;
310
311 return sun4i_backend_plane_uses_scaler(state);
312}
313
314static void sun4i_backend_atomic_begin(struct sunxi_engine *engine,
315 struct drm_crtc_state *old_state)
316{
317 u32 val;
318
319 WARN_ON(regmap_read_poll_timeout(engine->regs,
320 SUN4I_BACKEND_REGBUFFCTL_REG,
321 val, !(val & SUN4I_BACKEND_REGBUFFCTL_LOADCTL),
322 100, 50000));
323}
324
325static int sun4i_backend_atomic_check(struct sunxi_engine *engine,
326 struct drm_crtc_state *crtc_state)
327{
328 struct drm_atomic_state *state = crtc_state->state;
329 struct drm_device *drm = state->dev;
330 struct drm_plane *plane;
331 unsigned int num_planes = 0;
332 unsigned int num_alpha_planes = 0;
333 unsigned int num_frontend_planes = 0;
334
335 DRM_DEBUG_DRIVER("Starting checking our planes\n");
336
337 if (!crtc_state->planes_changed)
338 return 0;
339
340 drm_for_each_plane_mask(plane, drm, crtc_state->plane_mask) {
341 struct drm_plane_state *plane_state =
342 drm_atomic_get_plane_state(state, plane);
343 struct sun4i_layer_state *layer_state =
344 state_to_sun4i_layer_state(plane_state);
345 struct drm_framebuffer *fb = plane_state->fb;
346 struct drm_format_name_buf format_name;
347
348 if (sun4i_backend_plane_uses_frontend(plane_state)) {
349 DRM_DEBUG_DRIVER("Using the frontend for plane %d\n",
350 plane->index);
351
352 layer_state->uses_frontend = true;
353 num_frontend_planes++;
354 } else {
355 layer_state->uses_frontend = false;
356 }
357
358 DRM_DEBUG_DRIVER("Plane FB format is %s\n",
359 drm_get_format_name(fb->format->format,
360 &format_name));
361 if (fb->format->has_alpha)
362 num_alpha_planes++;
363
364 num_planes++;
365 }
366
367 /*
368 * The hardware is a bit unusual here.
369 *
370 * Even though it supports 4 layers, it does the composition
371 * in two separate steps.
372 *
373 * The first one is assigning a layer to one of its two
374 * pipes. If more that 1 layer is assigned to the same pipe,
375 * and if pixels overlaps, the pipe will take the pixel from
376 * the layer with the highest priority.
377 *
378 * The second step is the actual alpha blending, that takes
379 * the two pipes as input, and uses the eventual alpha
380 * component to do the transparency between the two.
381 *
382 * This two steps scenario makes us unable to guarantee a
383 * robust alpha blending between the 4 layers in all
384 * situations, since this means that we need to have one layer
385 * with alpha at the lowest position of our two pipes.
386 *
387 * However, we cannot even do that, since the hardware has a
388 * bug where the lowest plane of the lowest pipe (pipe 0,
389 * priority 0), if it has any alpha, will discard the pixel
390 * entirely and just display the pixels in the background
391 * color (black by default).
392 *
393 * This means that we effectively have only three valid
394 * configurations with alpha, all of them with the alpha being
395 * on pipe1 with the lowest position, which can be 1, 2 or 3
396 * depending on the number of planes and their zpos.
397 */
398 if (num_alpha_planes > SUN4I_BACKEND_NUM_ALPHA_LAYERS) {
399 DRM_DEBUG_DRIVER("Too many planes with alpha, rejecting...\n");
400 return -EINVAL;
401 }
402
403 if (num_frontend_planes > SUN4I_BACKEND_NUM_FRONTEND_LAYERS) {
404 DRM_DEBUG_DRIVER("Too many planes going through the frontend, rejecting\n");
405 return -EINVAL;
406 }
407
408 DRM_DEBUG_DRIVER("State valid with %u planes, %u alpha, %u video\n",
409 num_planes, num_alpha_planes, num_frontend_planes);
410
411 return 0;
412}
413
414static void sun4i_backend_vblank_quirk(struct sunxi_engine *engine)
415{
416 struct sun4i_backend *backend = engine_to_sun4i_backend(engine);
417 struct sun4i_frontend *frontend = backend->frontend;
418
419 if (!frontend)
420 return;
421
422 /*
423 * In a teardown scenario with the frontend involved, we have
424 * to keep the frontend enabled until the next vblank, and
425 * only then disable it.
426 *
427 * This is due to the fact that the backend will not take into
428 * account the new configuration (with the plane that used to
429 * be fed by the frontend now disabled) until we write to the
430 * commit bit and the hardware fetches the new configuration
431 * during the next vblank.
432 *
433 * So we keep the frontend around in order to prevent any
434 * visual artifacts.
435 */
436 spin_lock(&backend->frontend_lock);
437 if (backend->frontend_teardown) {
438 sun4i_frontend_exit(frontend);
439 backend->frontend_teardown = false;
440 }
441 spin_unlock(&backend->frontend_lock);
442};
443
249static int sun4i_backend_init_sat(struct device *dev) { 444static int sun4i_backend_init_sat(struct device *dev) {
250 struct sun4i_backend *backend = dev_get_drvdata(dev); 445 struct sun4i_backend *backend = dev_get_drvdata(dev);
251 int ret; 446 int ret;
@@ -330,11 +525,43 @@ static int sun4i_backend_of_get_id(struct device_node *node)
330 return ret; 525 return ret;
331} 526}
332 527
528/* TODO: This needs to take multiple pipelines into account */
529static struct sun4i_frontend *sun4i_backend_find_frontend(struct sun4i_drv *drv,
530 struct device_node *node)
531{
532 struct device_node *port, *ep, *remote;
533 struct sun4i_frontend *frontend;
534
535 port = of_graph_get_port_by_id(node, 0);
536 if (!port)
537 return ERR_PTR(-EINVAL);
538
539 for_each_available_child_of_node(port, ep) {
540 remote = of_graph_get_remote_port_parent(ep);
541 if (!remote)
542 continue;
543
544 /* does this node match any registered engines? */
545 list_for_each_entry(frontend, &drv->frontend_list, list) {
546 if (remote == frontend->node) {
547 of_node_put(remote);
548 of_node_put(port);
549 return frontend;
550 }
551 }
552 }
553
554 return ERR_PTR(-EINVAL);
555}
556
333static const struct sunxi_engine_ops sun4i_backend_engine_ops = { 557static const struct sunxi_engine_ops sun4i_backend_engine_ops = {
558 .atomic_begin = sun4i_backend_atomic_begin,
559 .atomic_check = sun4i_backend_atomic_check,
334 .commit = sun4i_backend_commit, 560 .commit = sun4i_backend_commit,
335 .layers_init = sun4i_layers_init, 561 .layers_init = sun4i_layers_init,
336 .apply_color_correction = sun4i_backend_apply_color_correction, 562 .apply_color_correction = sun4i_backend_apply_color_correction,
337 .disable_color_correction = sun4i_backend_disable_color_correction, 563 .disable_color_correction = sun4i_backend_disable_color_correction,
564 .vblank_quirk = sun4i_backend_vblank_quirk,
338}; 565};
339 566
340static struct regmap_config sun4i_backend_regmap_config = { 567static struct regmap_config sun4i_backend_regmap_config = {
@@ -360,6 +587,7 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
360 if (!backend) 587 if (!backend)
361 return -ENOMEM; 588 return -ENOMEM;
362 dev_set_drvdata(dev, backend); 589 dev_set_drvdata(dev, backend);
590 spin_lock_init(&backend->frontend_lock);
363 591
364 backend->engine.node = dev->of_node; 592 backend->engine.node = dev->of_node;
365 backend->engine.ops = &sun4i_backend_engine_ops; 593 backend->engine.ops = &sun4i_backend_engine_ops;
@@ -367,6 +595,10 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
367 if (backend->engine.id < 0) 595 if (backend->engine.id < 0)
368 return backend->engine.id; 596 return backend->engine.id;
369 597
598 backend->frontend = sun4i_backend_find_frontend(drv, dev->of_node);
599 if (IS_ERR(backend->frontend))
600 dev_warn(dev, "Couldn't find matching frontend, frontend features disabled\n");
601
370 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 602 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
371 regs = devm_ioremap_resource(dev, res); 603 regs = devm_ioremap_resource(dev, res);
372 if (IS_ERR(regs)) 604 if (IS_ERR(regs))
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h
index ac3cc029f5cd..52e77591186a 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.h
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.h
@@ -72,6 +72,7 @@
72#define SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(x) ((x) << 15) 72#define SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(x) ((x) << 15)
73#define SUN4I_BACKEND_ATTCTL_REG0_LAY_PRISEL_MASK GENMASK(11, 10) 73#define SUN4I_BACKEND_ATTCTL_REG0_LAY_PRISEL_MASK GENMASK(11, 10)
74#define SUN4I_BACKEND_ATTCTL_REG0_LAY_PRISEL(x) ((x) << 10) 74#define SUN4I_BACKEND_ATTCTL_REG0_LAY_PRISEL(x) ((x) << 10)
75#define SUN4I_BACKEND_ATTCTL_REG0_LAY_VDOEN BIT(1)
75 76
76#define SUN4I_BACKEND_ATTCTL_REG1(l) (0x8a0 + (0x4 * (l))) 77#define SUN4I_BACKEND_ATTCTL_REG1(l) (0x8a0 + (0x4 * (l)))
77#define SUN4I_BACKEND_ATTCTL_REG1_LAY_HSCAFCT GENMASK(15, 14) 78#define SUN4I_BACKEND_ATTCTL_REG1_LAY_HSCAFCT GENMASK(15, 14)
@@ -111,7 +112,9 @@
111#define SUN4I_BACKEND_SPRALPHACTL_REG 0x90c 112#define SUN4I_BACKEND_SPRALPHACTL_REG 0x90c
112#define SUN4I_BACKEND_IYUVCTL_REG 0x920 113#define SUN4I_BACKEND_IYUVCTL_REG 0x920
113#define SUN4I_BACKEND_IYUVADD_REG(c) (0x930 + (0x4 * (c))) 114#define SUN4I_BACKEND_IYUVADD_REG(c) (0x930 + (0x4 * (c)))
114#define SUN4I_BACKEND_IYUVLINEWITDTH_REG(c) (0x940 + (0x4 * (c))) 115
116#define SUN4I_BACKEND_IYUVLINEWIDTH_REG(c) (0x940 + (0x4 * (c)))
117
115#define SUN4I_BACKEND_YGCOEF_REG(c) (0x950 + (0x4 * (c))) 118#define SUN4I_BACKEND_YGCOEF_REG(c) (0x950 + (0x4 * (c)))
116#define SUN4I_BACKEND_YGCONS_REG 0x95c 119#define SUN4I_BACKEND_YGCONS_REG 0x95c
117#define SUN4I_BACKEND_URCOEF_REG(c) (0x960 + (0x4 * (c))) 120#define SUN4I_BACKEND_URCOEF_REG(c) (0x960 + (0x4 * (c)))
@@ -143,8 +146,13 @@
143#define SUN4I_BACKEND_HWCCOLORTAB_OFF 0x4c00 146#define SUN4I_BACKEND_HWCCOLORTAB_OFF 0x4c00
144#define SUN4I_BACKEND_PIPE_OFF(p) (0x5000 + (0x400 * (p))) 147#define SUN4I_BACKEND_PIPE_OFF(p) (0x5000 + (0x400 * (p)))
145 148
149#define SUN4I_BACKEND_NUM_LAYERS 4
150#define SUN4I_BACKEND_NUM_ALPHA_LAYERS 1
151#define SUN4I_BACKEND_NUM_FRONTEND_LAYERS 1
152
146struct sun4i_backend { 153struct sun4i_backend {
147 struct sunxi_engine engine; 154 struct sunxi_engine engine;
155 struct sun4i_frontend *frontend;
148 156
149 struct reset_control *reset; 157 struct reset_control *reset;
150 158
@@ -154,6 +162,10 @@ struct sun4i_backend {
154 162
155 struct clk *sat_clk; 163 struct clk *sat_clk;
156 struct reset_control *sat_reset; 164 struct reset_control *sat_reset;
165
166 /* Protects against races in the frontend teardown */
167 spinlock_t frontend_lock;
168 bool frontend_teardown;
157}; 169};
158 170
159static inline struct sun4i_backend * 171static inline struct sun4i_backend *
@@ -170,5 +182,9 @@ int sun4i_backend_update_layer_formats(struct sun4i_backend *backend,
170 int layer, struct drm_plane *plane); 182 int layer, struct drm_plane *plane);
171int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend, 183int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend,
172 int layer, struct drm_plane *plane); 184 int layer, struct drm_plane *plane);
185int sun4i_backend_update_layer_frontend(struct sun4i_backend *backend,
186 int layer, uint32_t in_fmt);
187int sun4i_backend_update_layer_zpos(struct sun4i_backend *backend,
188 int layer, struct drm_plane *plane);
173 189
174#endif /* _SUN4I_BACKEND_H_ */ 190#endif /* _SUN4I_BACKEND_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index 5decae0069d0..3b2d11b675e8 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -25,6 +25,7 @@
25 25
26#include <video/videomode.h> 26#include <video/videomode.h>
27 27
28#include "sun4i_backend.h"
28#include "sun4i_crtc.h" 29#include "sun4i_crtc.h"
29#include "sun4i_drv.h" 30#include "sun4i_drv.h"
30#include "sunxi_engine.h" 31#include "sunxi_engine.h"
@@ -46,11 +47,25 @@ static struct drm_encoder *sun4i_crtc_get_encoder(struct drm_crtc *crtc)
46 return NULL; 47 return NULL;
47} 48}
48 49
50static int sun4i_crtc_atomic_check(struct drm_crtc *crtc,
51 struct drm_crtc_state *state)
52{
53 struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
54 struct sunxi_engine *engine = scrtc->engine;
55 int ret = 0;
56
57 if (engine && engine->ops && engine->ops->atomic_check)
58 ret = engine->ops->atomic_check(engine, state);
59
60 return ret;
61}
62
49static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc, 63static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
50 struct drm_crtc_state *old_state) 64 struct drm_crtc_state *old_state)
51{ 65{
52 struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc); 66 struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
53 struct drm_device *dev = crtc->dev; 67 struct drm_device *dev = crtc->dev;
68 struct sunxi_engine *engine = scrtc->engine;
54 unsigned long flags; 69 unsigned long flags;
55 70
56 if (crtc->state->event) { 71 if (crtc->state->event) {
@@ -60,7 +75,10 @@ static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
60 scrtc->event = crtc->state->event; 75 scrtc->event = crtc->state->event;
61 spin_unlock_irqrestore(&dev->event_lock, flags); 76 spin_unlock_irqrestore(&dev->event_lock, flags);
62 crtc->state->event = NULL; 77 crtc->state->event = NULL;
63 } 78 }
79
80 if (engine->ops->atomic_begin)
81 engine->ops->atomic_begin(engine, old_state);
64} 82}
65 83
66static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc, 84static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc,
@@ -125,6 +143,7 @@ static void sun4i_crtc_mode_set_nofb(struct drm_crtc *crtc)
125} 143}
126 144
127static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = { 145static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = {
146 .atomic_check = sun4i_crtc_atomic_check,
128 .atomic_begin = sun4i_crtc_atomic_begin, 147 .atomic_begin = sun4i_crtc_atomic_begin,
129 .atomic_flush = sun4i_crtc_atomic_flush, 148 .atomic_flush = sun4i_crtc_atomic_flush,
130 .atomic_enable = sun4i_crtc_atomic_enable, 149 .atomic_enable = sun4i_crtc_atomic_enable,
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 4570da0227b4..3957c2ff6870 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -23,6 +23,7 @@
23#include <drm/drm_of.h> 23#include <drm/drm_of.h>
24 24
25#include "sun4i_drv.h" 25#include "sun4i_drv.h"
26#include "sun4i_frontend.h"
26#include "sun4i_framebuffer.h" 27#include "sun4i_framebuffer.h"
27#include "sun4i_tcon.h" 28#include "sun4i_tcon.h"
28 29
@@ -91,6 +92,7 @@ static int sun4i_drv_bind(struct device *dev)
91 goto free_drm; 92 goto free_drm;
92 } 93 }
93 drm->dev_private = drv; 94 drm->dev_private = drv;
95 INIT_LIST_HEAD(&drv->frontend_list);
94 INIT_LIST_HEAD(&drv->engine_list); 96 INIT_LIST_HEAD(&drv->engine_list);
95 INIT_LIST_HEAD(&drv->tcon_list); 97 INIT_LIST_HEAD(&drv->tcon_list);
96 98
@@ -177,6 +179,14 @@ static bool sun4i_drv_node_is_frontend(struct device_node *node)
177 of_device_is_compatible(node, "allwinner,sun8i-a33-display-frontend"); 179 of_device_is_compatible(node, "allwinner,sun8i-a33-display-frontend");
178} 180}
179 181
182static bool sun4i_drv_node_is_supported_frontend(struct device_node *node)
183{
184 if (IS_ENABLED(CONFIG_DRM_SUN4I_BACKEND))
185 return !!of_match_node(sun4i_frontend_of_table, node);
186
187 return false;
188}
189
180static bool sun4i_drv_node_is_tcon(struct device_node *node) 190static bool sun4i_drv_node_is_tcon(struct device_node *node)
181{ 191{
182 return !!of_match_node(sun4i_tcon_of_table, node); 192 return !!of_match_node(sun4i_tcon_of_table, node);
@@ -225,9 +235,11 @@ static int sun4i_drv_add_endpoints(struct device *dev,
225 int count = 0; 235 int count = 0;
226 236
227 /* 237 /*
228 * We don't support the frontend for now, so we will never 238 * The frontend has been disabled in some of our old device
229 * have a device bound. Just skip over it, but we still want 239 * trees. If we find a node that is the frontend and is
230 * the rest our pipeline to be added. 240 * disabled, we should just follow through and parse its
241 * child, but without adding it to the component list.
242 * Otherwise, we obviously want to add it to the list.
231 */ 243 */
232 if (!sun4i_drv_node_is_frontend(node) && 244 if (!sun4i_drv_node_is_frontend(node) &&
233 !of_device_is_available(node)) 245 !of_device_is_available(node))
@@ -240,7 +252,14 @@ static int sun4i_drv_add_endpoints(struct device *dev,
240 if (sun4i_drv_node_is_connector(node)) 252 if (sun4i_drv_node_is_connector(node))
241 return 0; 253 return 0;
242 254
243 if (!sun4i_drv_node_is_frontend(node)) { 255 /*
256 * If the device is either just a regular device, or an
257 * enabled frontend supported by the driver, we add it to our
258 * component list.
259 */
260 if (!sun4i_drv_node_is_frontend(node) ||
261 (sun4i_drv_node_is_supported_frontend(node) &&
262 of_device_is_available(node))) {
244 /* Add current component */ 263 /* Add current component */
245 DRM_DEBUG_DRIVER("Adding component %pOF\n", node); 264 DRM_DEBUG_DRIVER("Adding component %pOF\n", node);
246 drm_of_component_match_add(dev, match, compare_of, node); 265 drm_of_component_match_add(dev, match, compare_of, node);
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.h b/drivers/gpu/drm/sun4i/sun4i_drv.h
index 2825f140da54..5750b8ce8b31 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.h
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.h
@@ -19,6 +19,7 @@
19 19
20struct sun4i_drv { 20struct sun4i_drv {
21 struct list_head engine_list; 21 struct list_head engine_list;
22 struct list_head frontend_list;
22 struct list_head tcon_list; 23 struct list_head tcon_list;
23}; 24};
24 25
diff --git a/drivers/gpu/drm/sun4i/sun4i_framebuffer.c b/drivers/gpu/drm/sun4i/sun4i_framebuffer.c
index 38a36c0dfa2f..5f29850ef8ac 100644
--- a/drivers/gpu/drm/sun4i/sun4i_framebuffer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_framebuffer.c
@@ -10,6 +10,7 @@
10 * the License, or (at your option) any later version. 10 * the License, or (at your option) any later version.
11 */ 11 */
12 12
13#include <drm/drm_atomic.h>
13#include <drm/drm_atomic_helper.h> 14#include <drm/drm_atomic_helper.h>
14#include <drm/drm_fb_helper.h> 15#include <drm/drm_fb_helper.h>
15#include <drm/drm_fb_cma_helper.h> 16#include <drm/drm_fb_cma_helper.h>
@@ -19,13 +20,33 @@
19#include "sun4i_drv.h" 20#include "sun4i_drv.h"
20#include "sun4i_framebuffer.h" 21#include "sun4i_framebuffer.h"
21 22
23static int sun4i_de_atomic_check(struct drm_device *dev,
24 struct drm_atomic_state *state)
25{
26 int ret;
27
28 ret = drm_atomic_helper_check_modeset(dev, state);
29 if (ret)
30 return ret;
31
32 ret = drm_atomic_normalize_zpos(dev, state);
33 if (ret)
34 return ret;
35
36 return drm_atomic_helper_check_planes(dev, state);
37}
38
22static const struct drm_mode_config_funcs sun4i_de_mode_config_funcs = { 39static const struct drm_mode_config_funcs sun4i_de_mode_config_funcs = {
23 .output_poll_changed = drm_fb_helper_output_poll_changed, 40 .output_poll_changed = drm_fb_helper_output_poll_changed,
24 .atomic_check = drm_atomic_helper_check, 41 .atomic_check = sun4i_de_atomic_check,
25 .atomic_commit = drm_atomic_helper_commit, 42 .atomic_commit = drm_atomic_helper_commit,
26 .fb_create = drm_gem_fb_create, 43 .fb_create = drm_gem_fb_create,
27}; 44};
28 45
46static struct drm_mode_config_helper_funcs sun4i_de_mode_config_helpers = {
47 .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
48};
49
29int sun4i_framebuffer_init(struct drm_device *drm) 50int sun4i_framebuffer_init(struct drm_device *drm)
30{ 51{
31 drm_mode_config_reset(drm); 52 drm_mode_config_reset(drm);
@@ -34,6 +55,7 @@ int sun4i_framebuffer_init(struct drm_device *drm)
34 drm->mode_config.max_height = 8192; 55 drm->mode_config.max_height = 8192;
35 56
36 drm->mode_config.funcs = &sun4i_de_mode_config_funcs; 57 drm->mode_config.funcs = &sun4i_de_mode_config_funcs;
58 drm->mode_config.helper_private = &sun4i_de_mode_config_helpers;
37 59
38 return drm_fb_cma_fbdev_init(drm, 32, 0); 60 return drm_fb_cma_fbdev_init(drm, 32, 0);
39} 61}
diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c
new file mode 100644
index 000000000000..ddf6cfa6dd23
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c
@@ -0,0 +1,389 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2017 Free Electrons
4 * Maxime Ripard <maxime.ripard@free-electrons.com>
5 */
6#include <drm/drmP.h>
7#include <drm/drm_gem_cma_helper.h>
8#include <drm/drm_fb_cma_helper.h>
9
10#include <linux/clk.h>
11#include <linux/component.h>
12#include <linux/module.h>
13#include <linux/platform_device.h>
14#include <linux/pm_runtime.h>
15#include <linux/regmap.h>
16#include <linux/reset.h>
17
18#include "sun4i_drv.h"
19#include "sun4i_frontend.h"
20
21static const u32 sun4i_frontend_vert_coef[32] = {
22 0x00004000, 0x000140ff, 0x00033ffe, 0x00043ffd,
23 0x00063efc, 0xff083dfc, 0x000a3bfb, 0xff0d39fb,
24 0xff0f37fb, 0xff1136fa, 0xfe1433fb, 0xfe1631fb,
25 0xfd192ffb, 0xfd1c2cfb, 0xfd1f29fb, 0xfc2127fc,
26 0xfc2424fc, 0xfc2721fc, 0xfb291ffd, 0xfb2c1cfd,
27 0xfb2f19fd, 0xfb3116fe, 0xfb3314fe, 0xfa3611ff,
28 0xfb370fff, 0xfb390dff, 0xfb3b0a00, 0xfc3d08ff,
29 0xfc3e0600, 0xfd3f0400, 0xfe3f0300, 0xff400100,
30};
31
32static const u32 sun4i_frontend_horz_coef[64] = {
33 0x40000000, 0x00000000, 0x40fe0000, 0x0000ff03,
34 0x3ffd0000, 0x0000ff05, 0x3ffc0000, 0x0000ff06,
35 0x3efb0000, 0x0000ff08, 0x3dfb0000, 0x0000ff09,
36 0x3bfa0000, 0x0000fe0d, 0x39fa0000, 0x0000fe0f,
37 0x38fa0000, 0x0000fe10, 0x36fa0000, 0x0000fe12,
38 0x33fa0000, 0x0000fd16, 0x31fa0000, 0x0000fd18,
39 0x2ffa0000, 0x0000fd1a, 0x2cfa0000, 0x0000fc1e,
40 0x29fa0000, 0x0000fc21, 0x27fb0000, 0x0000fb23,
41 0x24fb0000, 0x0000fb26, 0x21fb0000, 0x0000fb29,
42 0x1ffc0000, 0x0000fa2b, 0x1cfc0000, 0x0000fa2e,
43 0x19fd0000, 0x0000fa30, 0x16fd0000, 0x0000fa33,
44 0x14fd0000, 0x0000fa35, 0x11fe0000, 0x0000fa37,
45 0x0ffe0000, 0x0000fa39, 0x0dfe0000, 0x0000fa3b,
46 0x0afe0000, 0x0000fa3e, 0x08ff0000, 0x0000fb3e,
47 0x06ff0000, 0x0000fb40, 0x05ff0000, 0x0000fc40,
48 0x03ff0000, 0x0000fd41, 0x01ff0000, 0x0000fe42,
49};
50
51static void sun4i_frontend_scaler_init(struct sun4i_frontend *frontend)
52{
53 int i;
54
55 for (i = 0; i < 32; i++) {
56 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZCOEF0_REG(i),
57 sun4i_frontend_horz_coef[2 * i]);
58 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZCOEF0_REG(i),
59 sun4i_frontend_horz_coef[2 * i]);
60 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZCOEF1_REG(i),
61 sun4i_frontend_horz_coef[2 * i + 1]);
62 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZCOEF1_REG(i),
63 sun4i_frontend_horz_coef[2 * i + 1]);
64 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTCOEF_REG(i),
65 sun4i_frontend_vert_coef[i]);
66 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTCOEF_REG(i),
67 sun4i_frontend_vert_coef[i]);
68 }
69
70 regmap_update_bits(frontend->regs, SUN4I_FRONTEND_FRM_CTRL_REG,
71 SUN4I_FRONTEND_FRM_CTRL_COEF_ACCESS_CTRL,
72 SUN4I_FRONTEND_FRM_CTRL_COEF_ACCESS_CTRL);
73}
74
75int sun4i_frontend_init(struct sun4i_frontend *frontend)
76{
77 return pm_runtime_get_sync(frontend->dev);
78}
79EXPORT_SYMBOL(sun4i_frontend_init);
80
81void sun4i_frontend_exit(struct sun4i_frontend *frontend)
82{
83 pm_runtime_put(frontend->dev);
84}
85EXPORT_SYMBOL(sun4i_frontend_exit);
86
87void sun4i_frontend_update_buffer(struct sun4i_frontend *frontend,
88 struct drm_plane *plane)
89{
90 struct drm_plane_state *state = plane->state;
91 struct drm_framebuffer *fb = state->fb;
92 dma_addr_t paddr;
93
94 /* Set the line width */
95 DRM_DEBUG_DRIVER("Frontend stride: %d bytes\n", fb->pitches[0]);
96 regmap_write(frontend->regs, SUN4I_FRONTEND_LINESTRD0_REG,
97 fb->pitches[0]);
98
99 /* Set the physical address of the buffer in memory */
100 paddr = drm_fb_cma_get_gem_addr(fb, state, 0);
101 paddr -= PHYS_OFFSET;
102 DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
103 regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR0_REG, paddr);
104}
105EXPORT_SYMBOL(sun4i_frontend_update_buffer);
106
107static int sun4i_frontend_drm_format_to_input_fmt(uint32_t fmt, u32 *val)
108{
109 switch (fmt) {
110 case DRM_FORMAT_ARGB8888:
111 *val = 5;
112 return 0;
113
114 default:
115 return -EINVAL;
116 }
117}
118
119static int sun4i_frontend_drm_format_to_output_fmt(uint32_t fmt, u32 *val)
120{
121 switch (fmt) {
122 case DRM_FORMAT_XRGB8888:
123 case DRM_FORMAT_ARGB8888:
124 *val = 2;
125 return 0;
126
127 default:
128 return -EINVAL;
129 }
130}
131
132int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
133 struct drm_plane *plane, uint32_t out_fmt)
134{
135 struct drm_plane_state *state = plane->state;
136 struct drm_framebuffer *fb = state->fb;
137 u32 out_fmt_val;
138 u32 in_fmt_val;
139 int ret;
140
141 ret = sun4i_frontend_drm_format_to_input_fmt(fb->format->format,
142 &in_fmt_val);
143 if (ret) {
144 DRM_DEBUG_DRIVER("Invalid input format\n");
145 return ret;
146 }
147
148 ret = sun4i_frontend_drm_format_to_output_fmt(out_fmt, &out_fmt_val);
149 if (ret) {
150 DRM_DEBUG_DRIVER("Invalid output format\n");
151 return ret;
152 }
153
154 /*
155 * I have no idea what this does exactly, but it seems to be
156 * related to the scaler FIR filter phase parameters.
157 */
158 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZPHASE_REG, 0x400);
159 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZPHASE_REG, 0x400);
160 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE0_REG, 0x400);
161 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE0_REG, 0x400);
162 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE1_REG, 0x400);
163 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE1_REG, 0x400);
164
165 regmap_write(frontend->regs, SUN4I_FRONTEND_INPUT_FMT_REG,
166 SUN4I_FRONTEND_INPUT_FMT_DATA_MOD(1) |
167 SUN4I_FRONTEND_INPUT_FMT_DATA_FMT(in_fmt_val) |
168 SUN4I_FRONTEND_INPUT_FMT_PS(1));
169
170 /*
171 * TODO: It look like the A31 and A80 at least will need the
172 * bit 7 (ALPHA_EN) enabled when using a format with alpha (so
173 * ARGB8888).
174 */
175 regmap_write(frontend->regs, SUN4I_FRONTEND_OUTPUT_FMT_REG,
176 SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT(out_fmt_val));
177
178 return 0;
179}
180EXPORT_SYMBOL(sun4i_frontend_update_formats);
181
182void sun4i_frontend_update_coord(struct sun4i_frontend *frontend,
183 struct drm_plane *plane)
184{
185 struct drm_plane_state *state = plane->state;
186
187 /* Set height and width */
188 DRM_DEBUG_DRIVER("Frontend size W: %u H: %u\n",
189 state->crtc_w, state->crtc_h);
190 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_INSIZE_REG,
191 SUN4I_FRONTEND_INSIZE(state->src_h >> 16,
192 state->src_w >> 16));
193 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_INSIZE_REG,
194 SUN4I_FRONTEND_INSIZE(state->src_h >> 16,
195 state->src_w >> 16));
196
197 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_OUTSIZE_REG,
198 SUN4I_FRONTEND_OUTSIZE(state->crtc_h, state->crtc_w));
199 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_OUTSIZE_REG,
200 SUN4I_FRONTEND_OUTSIZE(state->crtc_h, state->crtc_w));
201
202 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZFACT_REG,
203 state->src_w / state->crtc_w);
204 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZFACT_REG,
205 state->src_w / state->crtc_w);
206
207 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTFACT_REG,
208 state->src_h / state->crtc_h);
209 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTFACT_REG,
210 state->src_h / state->crtc_h);
211
212 regmap_write_bits(frontend->regs, SUN4I_FRONTEND_FRM_CTRL_REG,
213 SUN4I_FRONTEND_FRM_CTRL_REG_RDY,
214 SUN4I_FRONTEND_FRM_CTRL_REG_RDY);
215}
216EXPORT_SYMBOL(sun4i_frontend_update_coord);
217
218int sun4i_frontend_enable(struct sun4i_frontend *frontend)
219{
220 regmap_write_bits(frontend->regs, SUN4I_FRONTEND_FRM_CTRL_REG,
221 SUN4I_FRONTEND_FRM_CTRL_FRM_START,
222 SUN4I_FRONTEND_FRM_CTRL_FRM_START);
223
224 return 0;
225}
226EXPORT_SYMBOL(sun4i_frontend_enable);
227
228static struct regmap_config sun4i_frontend_regmap_config = {
229 .reg_bits = 32,
230 .val_bits = 32,
231 .reg_stride = 4,
232 .max_register = 0x0a14,
233};
234
235static int sun4i_frontend_bind(struct device *dev, struct device *master,
236 void *data)
237{
238 struct platform_device *pdev = to_platform_device(dev);
239 struct sun4i_frontend *frontend;
240 struct drm_device *drm = data;
241 struct sun4i_drv *drv = drm->dev_private;
242 struct resource *res;
243 void __iomem *regs;
244
245 frontend = devm_kzalloc(dev, sizeof(*frontend), GFP_KERNEL);
246 if (!frontend)
247 return -ENOMEM;
248
249 dev_set_drvdata(dev, frontend);
250 frontend->dev = dev;
251 frontend->node = dev->of_node;
252
253 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
254 regs = devm_ioremap_resource(dev, res);
255 if (IS_ERR(regs))
256 return PTR_ERR(regs);
257
258 frontend->regs = devm_regmap_init_mmio(dev, regs,
259 &sun4i_frontend_regmap_config);
260 if (IS_ERR(frontend->regs)) {
261 dev_err(dev, "Couldn't create the frontend regmap\n");
262 return PTR_ERR(frontend->regs);
263 }
264
265 frontend->reset = devm_reset_control_get(dev, NULL);
266 if (IS_ERR(frontend->reset)) {
267 dev_err(dev, "Couldn't get our reset line\n");
268 return PTR_ERR(frontend->reset);
269 }
270
271 frontend->bus_clk = devm_clk_get(dev, "ahb");
272 if (IS_ERR(frontend->bus_clk)) {
273 dev_err(dev, "Couldn't get our bus clock\n");
274 return PTR_ERR(frontend->bus_clk);
275 }
276
277 frontend->mod_clk = devm_clk_get(dev, "mod");
278 if (IS_ERR(frontend->mod_clk)) {
279 dev_err(dev, "Couldn't get our mod clock\n");
280 return PTR_ERR(frontend->mod_clk);
281 }
282
283 frontend->ram_clk = devm_clk_get(dev, "ram");
284 if (IS_ERR(frontend->ram_clk)) {
285 dev_err(dev, "Couldn't get our ram clock\n");
286 return PTR_ERR(frontend->ram_clk);
287 }
288
289 list_add_tail(&frontend->list, &drv->frontend_list);
290 pm_runtime_enable(dev);
291
292 return 0;
293}
294
295static void sun4i_frontend_unbind(struct device *dev, struct device *master,
296 void *data)
297{
298 struct sun4i_frontend *frontend = dev_get_drvdata(dev);
299
300 list_del(&frontend->list);
301 pm_runtime_force_suspend(dev);
302}
303
304static const struct component_ops sun4i_frontend_ops = {
305 .bind = sun4i_frontend_bind,
306 .unbind = sun4i_frontend_unbind,
307};
308
309static int sun4i_frontend_probe(struct platform_device *pdev)
310{
311 return component_add(&pdev->dev, &sun4i_frontend_ops);
312}
313
314static int sun4i_frontend_remove(struct platform_device *pdev)
315{
316 component_del(&pdev->dev, &sun4i_frontend_ops);
317
318 return 0;
319}
320
321static int sun4i_frontend_runtime_resume(struct device *dev)
322{
323 struct sun4i_frontend *frontend = dev_get_drvdata(dev);
324 int ret;
325
326 clk_set_rate(frontend->mod_clk, 300000000);
327
328 clk_prepare_enable(frontend->bus_clk);
329 clk_prepare_enable(frontend->mod_clk);
330 clk_prepare_enable(frontend->ram_clk);
331
332 ret = reset_control_reset(frontend->reset);
333 if (ret) {
334 dev_err(dev, "Couldn't reset our device\n");
335 return ret;
336 }
337
338 regmap_update_bits(frontend->regs, SUN4I_FRONTEND_EN_REG,
339 SUN4I_FRONTEND_EN_EN,
340 SUN4I_FRONTEND_EN_EN);
341
342 regmap_update_bits(frontend->regs, SUN4I_FRONTEND_BYPASS_REG,
343 SUN4I_FRONTEND_BYPASS_CSC_EN,
344 SUN4I_FRONTEND_BYPASS_CSC_EN);
345
346 sun4i_frontend_scaler_init(frontend);
347
348 return 0;
349}
350
351static int sun4i_frontend_runtime_suspend(struct device *dev)
352{
353 struct sun4i_frontend *frontend = dev_get_drvdata(dev);
354
355 clk_disable_unprepare(frontend->ram_clk);
356 clk_disable_unprepare(frontend->mod_clk);
357 clk_disable_unprepare(frontend->bus_clk);
358
359 reset_control_assert(frontend->reset);
360
361 return 0;
362}
363
364static const struct dev_pm_ops sun4i_frontend_pm_ops = {
365 .runtime_resume = sun4i_frontend_runtime_resume,
366 .runtime_suspend = sun4i_frontend_runtime_suspend,
367};
368
369const struct of_device_id sun4i_frontend_of_table[] = {
370 { .compatible = "allwinner,sun8i-a33-display-frontend" },
371 { }
372};
373EXPORT_SYMBOL(sun4i_frontend_of_table);
374MODULE_DEVICE_TABLE(of, sun4i_frontend_of_table);
375
376static struct platform_driver sun4i_frontend_driver = {
377 .probe = sun4i_frontend_probe,
378 .remove = sun4i_frontend_remove,
379 .driver = {
380 .name = "sun4i-frontend",
381 .of_match_table = sun4i_frontend_of_table,
382 .pm = &sun4i_frontend_pm_ops,
383 },
384};
385module_platform_driver(sun4i_frontend_driver);
386
387MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
388MODULE_DESCRIPTION("Allwinner A10 Display Engine Frontend Driver");
389MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.h b/drivers/gpu/drm/sun4i/sun4i_frontend.h
new file mode 100644
index 000000000000..02661ce81f3e
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun4i_frontend.h
@@ -0,0 +1,99 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2017 Free Electrons
4 * Maxime Ripard <maxime.ripard@free-electrons.com>
5 */
6
7#ifndef _SUN4I_FRONTEND_H_
8#define _SUN4I_FRONTEND_H_
9
10#include <linux/list.h>
11
12#define SUN4I_FRONTEND_EN_REG 0x000
13#define SUN4I_FRONTEND_EN_EN BIT(0)
14
15#define SUN4I_FRONTEND_FRM_CTRL_REG 0x004
16#define SUN4I_FRONTEND_FRM_CTRL_COEF_ACCESS_CTRL BIT(23)
17#define SUN4I_FRONTEND_FRM_CTRL_FRM_START BIT(16)
18#define SUN4I_FRONTEND_FRM_CTRL_COEF_RDY BIT(1)
19#define SUN4I_FRONTEND_FRM_CTRL_REG_RDY BIT(0)
20
21#define SUN4I_FRONTEND_BYPASS_REG 0x008
22#define SUN4I_FRONTEND_BYPASS_CSC_EN BIT(1)
23
24#define SUN4I_FRONTEND_BUF_ADDR0_REG 0x020
25
26#define SUN4I_FRONTEND_LINESTRD0_REG 0x040
27
28#define SUN4I_FRONTEND_INPUT_FMT_REG 0x04c
29#define SUN4I_FRONTEND_INPUT_FMT_DATA_MOD(mod) ((mod) << 8)
30#define SUN4I_FRONTEND_INPUT_FMT_DATA_FMT(fmt) ((fmt) << 4)
31#define SUN4I_FRONTEND_INPUT_FMT_PS(ps) (ps)
32
33#define SUN4I_FRONTEND_OUTPUT_FMT_REG 0x05c
34#define SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT(fmt) (fmt)
35
36#define SUN4I_FRONTEND_CH0_INSIZE_REG 0x100
37#define SUN4I_FRONTEND_INSIZE(h, w) ((((h) - 1) << 16) | (((w) - 1)))
38
39#define SUN4I_FRONTEND_CH0_OUTSIZE_REG 0x104
40#define SUN4I_FRONTEND_OUTSIZE(h, w) ((((h) - 1) << 16) | (((w) - 1)))
41
42#define SUN4I_FRONTEND_CH0_HORZFACT_REG 0x108
43#define SUN4I_FRONTEND_HORZFACT(i, f) (((i) << 16) | (f))
44
45#define SUN4I_FRONTEND_CH0_VERTFACT_REG 0x10c
46#define SUN4I_FRONTEND_VERTFACT(i, f) (((i) << 16) | (f))
47
48#define SUN4I_FRONTEND_CH0_HORZPHASE_REG 0x110
49#define SUN4I_FRONTEND_CH0_VERTPHASE0_REG 0x114
50#define SUN4I_FRONTEND_CH0_VERTPHASE1_REG 0x118
51
52#define SUN4I_FRONTEND_CH1_INSIZE_REG 0x200
53#define SUN4I_FRONTEND_CH1_OUTSIZE_REG 0x204
54#define SUN4I_FRONTEND_CH1_HORZFACT_REG 0x208
55#define SUN4I_FRONTEND_CH1_VERTFACT_REG 0x20c
56
57#define SUN4I_FRONTEND_CH1_HORZPHASE_REG 0x210
58#define SUN4I_FRONTEND_CH1_VERTPHASE0_REG 0x214
59#define SUN4I_FRONTEND_CH1_VERTPHASE1_REG 0x218
60
61#define SUN4I_FRONTEND_CH0_HORZCOEF0_REG(i) (0x400 + i * 4)
62#define SUN4I_FRONTEND_CH0_HORZCOEF1_REG(i) (0x480 + i * 4)
63#define SUN4I_FRONTEND_CH0_VERTCOEF_REG(i) (0x500 + i * 4)
64#define SUN4I_FRONTEND_CH1_HORZCOEF0_REG(i) (0x600 + i * 4)
65#define SUN4I_FRONTEND_CH1_HORZCOEF1_REG(i) (0x680 + i * 4)
66#define SUN4I_FRONTEND_CH1_VERTCOEF_REG(i) (0x700 + i * 4)
67
68struct clk;
69struct device_node;
70struct drm_plane;
71struct regmap;
72struct reset_control;
73
74struct sun4i_frontend {
75 struct list_head list;
76 struct device *dev;
77 struct device_node *node;
78
79 struct clk *bus_clk;
80 struct clk *mod_clk;
81 struct clk *ram_clk;
82 struct regmap *regs;
83 struct reset_control *reset;
84};
85
86extern const struct of_device_id sun4i_frontend_of_table[];
87
88int sun4i_frontend_init(struct sun4i_frontend *frontend);
89void sun4i_frontend_exit(struct sun4i_frontend *frontend);
90int sun4i_frontend_enable(struct sun4i_frontend *frontend);
91
92void sun4i_frontend_update_buffer(struct sun4i_frontend *frontend,
93 struct drm_plane *plane);
94void sun4i_frontend_update_coord(struct sun4i_frontend *frontend,
95 struct drm_plane *plane);
96int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
97 struct drm_plane *plane, uint32_t out_fmt);
98
99#endif /* _SUN4I_FRONTEND_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
index 7bddf12548d3..19be798e4fac 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -15,34 +15,107 @@
15#include <drm/drmP.h> 15#include <drm/drmP.h>
16 16
17#include "sun4i_backend.h" 17#include "sun4i_backend.h"
18#include "sun4i_frontend.h"
18#include "sun4i_layer.h" 19#include "sun4i_layer.h"
19#include "sunxi_engine.h" 20#include "sunxi_engine.h"
20 21
21struct sun4i_plane_desc { 22struct sun4i_plane_desc {
22 enum drm_plane_type type; 23 enum drm_plane_type type;
23 u8 pipe; 24 u8 pipe;
24 const uint32_t *formats; 25 const uint32_t *formats;
25 uint32_t nformats; 26 uint32_t nformats;
26}; 27};
27 28
29static void sun4i_backend_layer_reset(struct drm_plane *plane)
30{
31 struct sun4i_layer *layer = plane_to_sun4i_layer(plane);
32 struct sun4i_layer_state *state;
33
34 if (plane->state) {
35 state = state_to_sun4i_layer_state(plane->state);
36
37 __drm_atomic_helper_plane_destroy_state(&state->state);
38
39 kfree(state);
40 plane->state = NULL;
41 }
42
43 state = kzalloc(sizeof(*state), GFP_KERNEL);
44 if (state) {
45 plane->state = &state->state;
46 plane->state->plane = plane;
47 plane->state->zpos = layer->id;
48 }
49}
50
51static struct drm_plane_state *
52sun4i_backend_layer_duplicate_state(struct drm_plane *plane)
53{
54 struct sun4i_layer_state *orig = state_to_sun4i_layer_state(plane->state);
55 struct sun4i_layer_state *copy;
56
57 copy = kzalloc(sizeof(*copy), GFP_KERNEL);
58 if (!copy)
59 return NULL;
60
61 __drm_atomic_helper_plane_duplicate_state(plane, &copy->state);
62 copy->uses_frontend = orig->uses_frontend;
63
64 return &copy->state;
65}
66
67static void sun4i_backend_layer_destroy_state(struct drm_plane *plane,
68 struct drm_plane_state *state)
69{
70 struct sun4i_layer_state *s_state = state_to_sun4i_layer_state(state);
71
72 __drm_atomic_helper_plane_destroy_state(state);
73
74 kfree(s_state);
75}
76
28static void sun4i_backend_layer_atomic_disable(struct drm_plane *plane, 77static void sun4i_backend_layer_atomic_disable(struct drm_plane *plane,
29 struct drm_plane_state *old_state) 78 struct drm_plane_state *old_state)
30{ 79{
80 struct sun4i_layer_state *layer_state = state_to_sun4i_layer_state(old_state);
31 struct sun4i_layer *layer = plane_to_sun4i_layer(plane); 81 struct sun4i_layer *layer = plane_to_sun4i_layer(plane);
32 struct sun4i_backend *backend = layer->backend; 82 struct sun4i_backend *backend = layer->backend;
33 83
34 sun4i_backend_layer_enable(backend, layer->id, false); 84 sun4i_backend_layer_enable(backend, layer->id, false);
85
86 if (layer_state->uses_frontend) {
87 unsigned long flags;
88
89 spin_lock_irqsave(&backend->frontend_lock, flags);
90 backend->frontend_teardown = true;
91 spin_unlock_irqrestore(&backend->frontend_lock, flags);
92 }
35} 93}
36 94
37static void sun4i_backend_layer_atomic_update(struct drm_plane *plane, 95static void sun4i_backend_layer_atomic_update(struct drm_plane *plane,
38 struct drm_plane_state *old_state) 96 struct drm_plane_state *old_state)
39{ 97{
98 struct sun4i_layer_state *layer_state = state_to_sun4i_layer_state(plane->state);
40 struct sun4i_layer *layer = plane_to_sun4i_layer(plane); 99 struct sun4i_layer *layer = plane_to_sun4i_layer(plane);
41 struct sun4i_backend *backend = layer->backend; 100 struct sun4i_backend *backend = layer->backend;
101 struct sun4i_frontend *frontend = backend->frontend;
102
103 if (layer_state->uses_frontend) {
104 sun4i_frontend_init(frontend);
105 sun4i_frontend_update_coord(frontend, plane);
106 sun4i_frontend_update_buffer(frontend, plane);
107 sun4i_frontend_update_formats(frontend, plane,
108 DRM_FORMAT_ARGB8888);
109 sun4i_backend_update_layer_frontend(backend, layer->id,
110 DRM_FORMAT_ARGB8888);
111 sun4i_frontend_enable(frontend);
112 } else {
113 sun4i_backend_update_layer_formats(backend, layer->id, plane);
114 sun4i_backend_update_layer_buffer(backend, layer->id, plane);
115 }
42 116
43 sun4i_backend_update_layer_coord(backend, layer->id, plane); 117 sun4i_backend_update_layer_coord(backend, layer->id, plane);
44 sun4i_backend_update_layer_formats(backend, layer->id, plane); 118 sun4i_backend_update_layer_zpos(backend, layer->id, plane);
45 sun4i_backend_update_layer_buffer(backend, layer->id, plane);
46 sun4i_backend_layer_enable(backend, layer->id, true); 119 sun4i_backend_layer_enable(backend, layer->id, true);
47} 120}
48 121
@@ -52,11 +125,11 @@ static const struct drm_plane_helper_funcs sun4i_backend_layer_helper_funcs = {
52}; 125};
53 126
54static const struct drm_plane_funcs sun4i_backend_layer_funcs = { 127static const struct drm_plane_funcs sun4i_backend_layer_funcs = {
55 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, 128 .atomic_destroy_state = sun4i_backend_layer_destroy_state,
56 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, 129 .atomic_duplicate_state = sun4i_backend_layer_duplicate_state,
57 .destroy = drm_plane_cleanup, 130 .destroy = drm_plane_cleanup,
58 .disable_plane = drm_atomic_helper_disable_plane, 131 .disable_plane = drm_atomic_helper_disable_plane,
59 .reset = drm_atomic_helper_plane_reset, 132 .reset = sun4i_backend_layer_reset,
60 .update_plane = drm_atomic_helper_update_plane, 133 .update_plane = drm_atomic_helper_update_plane,
61}; 134};
62 135
@@ -128,32 +201,12 @@ struct drm_plane **sun4i_layers_init(struct drm_device *drm,
128 struct sun4i_backend *backend = engine_to_sun4i_backend(engine); 201 struct sun4i_backend *backend = engine_to_sun4i_backend(engine);
129 int i; 202 int i;
130 203
131 planes = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes) + 1, 204 /* We need to have a sentinel at the need, hence the overallocation */
205 planes = devm_kcalloc(drm->dev, SUN4I_BACKEND_NUM_LAYERS + 1,
132 sizeof(*planes), GFP_KERNEL); 206 sizeof(*planes), GFP_KERNEL);
133 if (!planes) 207 if (!planes)
134 return ERR_PTR(-ENOMEM); 208 return ERR_PTR(-ENOMEM);
135 209
136 /*
137 * The hardware is a bit unusual here.
138 *
139 * Even though it supports 4 layers, it does the composition
140 * in two separate steps.
141 *
142 * The first one is assigning a layer to one of its two
143 * pipes. If more that 1 layer is assigned to the same pipe,
144 * and if pixels overlaps, the pipe will take the pixel from
145 * the layer with the highest priority.
146 *
147 * The second step is the actual alpha blending, that takes
148 * the two pipes as input, and uses the eventual alpha
149 * component to do the transparency between the two.
150 *
151 * This two steps scenario makes us unable to guarantee a
152 * robust alpha blending between the 4 layers in all
153 * situations. So we just expose two layers, one per pipe. On
154 * SoCs that support it, sprites could fill the need for more
155 * layers.
156 */
157 for (i = 0; i < ARRAY_SIZE(sun4i_backend_planes); i++) { 210 for (i = 0; i < ARRAY_SIZE(sun4i_backend_planes); i++) {
158 const struct sun4i_plane_desc *plane = &sun4i_backend_planes[i]; 211 const struct sun4i_plane_desc *plane = &sun4i_backend_planes[i];
159 struct sun4i_layer *layer; 212 struct sun4i_layer *layer;
@@ -165,6 +218,8 @@ struct drm_plane **sun4i_layers_init(struct drm_device *drm,
165 return ERR_CAST(layer); 218 return ERR_CAST(layer);
166 }; 219 };
167 220
221 drm_plane_create_zpos_immutable_property(&layer->plane, i);
222
168 DRM_DEBUG_DRIVER("Assigning %s plane to pipe %d\n", 223 DRM_DEBUG_DRIVER("Assigning %s plane to pipe %d\n",
169 i ? "overlay" : "primary", plane->pipe); 224 i ? "overlay" : "primary", plane->pipe);
170 regmap_update_bits(engine->regs, SUN4I_BACKEND_ATTCTL_REG0(i), 225 regmap_update_bits(engine->regs, SUN4I_BACKEND_ATTCTL_REG0(i),
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h b/drivers/gpu/drm/sun4i/sun4i_layer.h
index 4e84f438b346..75b4868ba87c 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.h
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.h
@@ -22,12 +22,23 @@ struct sun4i_layer {
22 int id; 22 int id;
23}; 23};
24 24
25struct sun4i_layer_state {
26 struct drm_plane_state state;
27 bool uses_frontend;
28};
29
25static inline struct sun4i_layer * 30static inline struct sun4i_layer *
26plane_to_sun4i_layer(struct drm_plane *plane) 31plane_to_sun4i_layer(struct drm_plane *plane)
27{ 32{
28 return container_of(plane, struct sun4i_layer, plane); 33 return container_of(plane, struct sun4i_layer, plane);
29} 34}
30 35
36static inline struct sun4i_layer_state *
37state_to_sun4i_layer_state(struct drm_plane_state *state)
38{
39 return container_of(state, struct sun4i_layer_state, state);
40}
41
31struct drm_plane **sun4i_layers_init(struct drm_device *drm, 42struct drm_plane **sun4i_layers_init(struct drm_device *drm,
32 struct sunxi_engine *engine); 43 struct sunxi_engine *engine);
33 44
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 3c15cf24b503..4b7340ee6290 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -540,6 +540,7 @@ static irqreturn_t sun4i_tcon_handler(int irq, void *private)
540 struct sun4i_tcon *tcon = private; 540 struct sun4i_tcon *tcon = private;
541 struct drm_device *drm = tcon->drm; 541 struct drm_device *drm = tcon->drm;
542 struct sun4i_crtc *scrtc = tcon->crtc; 542 struct sun4i_crtc *scrtc = tcon->crtc;
543 struct sunxi_engine *engine = scrtc->engine;
543 unsigned int status; 544 unsigned int status;
544 545
545 regmap_read(tcon->regs, SUN4I_TCON_GINT0_REG, &status); 546 regmap_read(tcon->regs, SUN4I_TCON_GINT0_REG, &status);
@@ -557,6 +558,9 @@ static irqreturn_t sun4i_tcon_handler(int irq, void *private)
557 SUN4I_TCON_GINT0_VBLANK_INT(1), 558 SUN4I_TCON_GINT0_VBLANK_INT(1),
558 0); 559 0);
559 560
561 if (engine->ops->vblank_quirk)
562 engine->ops->vblank_quirk(engine);
563
560 return IRQ_HANDLED; 564 return IRQ_HANDLED;
561} 565}
562 566
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
index 28d7c48d50fe..2f0ccd50b54d 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
@@ -211,7 +211,7 @@ static int sun8i_ui_layer_atomic_check(struct drm_plane *plane,
211 struct drm_crtc *crtc = state->crtc; 211 struct drm_crtc *crtc = state->crtc;
212 struct drm_crtc_state *crtc_state; 212 struct drm_crtc_state *crtc_state;
213 int min_scale, max_scale; 213 int min_scale, max_scale;
214 struct drm_rect clip; 214 struct drm_rect clip = {};
215 215
216 if (!crtc) 216 if (!crtc)
217 return 0; 217 return 0;
@@ -220,10 +220,9 @@ static int sun8i_ui_layer_atomic_check(struct drm_plane *plane,
220 if (WARN_ON(!crtc_state)) 220 if (WARN_ON(!crtc_state))
221 return -EINVAL; 221 return -EINVAL;
222 222
223 clip.x1 = 0; 223 if (crtc_state->enable)
224 clip.y1 = 0; 224 drm_mode_get_hv_timing(&crtc_state->mode,
225 clip.x2 = crtc_state->adjusted_mode.hdisplay; 225 &clip.x2, &clip.y2);
226 clip.y2 = crtc_state->adjusted_mode.vdisplay;
227 226
228 min_scale = DRM_PLANE_HELPER_NO_SCALING; 227 min_scale = DRM_PLANE_HELPER_NO_SCALING;
229 max_scale = DRM_PLANE_HELPER_NO_SCALING; 228 max_scale = DRM_PLANE_HELPER_NO_SCALING;
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index 40c3b303068a..eb3bf2d7291a 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -239,7 +239,7 @@ static int sun8i_vi_layer_atomic_check(struct drm_plane *plane,
239 struct drm_crtc *crtc = state->crtc; 239 struct drm_crtc *crtc = state->crtc;
240 struct drm_crtc_state *crtc_state; 240 struct drm_crtc_state *crtc_state;
241 int min_scale, max_scale; 241 int min_scale, max_scale;
242 struct drm_rect clip; 242 struct drm_rect clip = {};
243 243
244 if (!crtc) 244 if (!crtc)
245 return 0; 245 return 0;
@@ -248,10 +248,9 @@ static int sun8i_vi_layer_atomic_check(struct drm_plane *plane,
248 if (WARN_ON(!crtc_state)) 248 if (WARN_ON(!crtc_state))
249 return -EINVAL; 249 return -EINVAL;
250 250
251 clip.x1 = 0; 251 if (crtc_state->enable)
252 clip.y1 = 0; 252 drm_mode_get_hv_timing(&crtc_state->mode,
253 clip.x2 = crtc_state->adjusted_mode.hdisplay; 253 &clip.x2, &clip.y2);
254 clip.y2 = crtc_state->adjusted_mode.vdisplay;
255 254
256 min_scale = DRM_PLANE_HELPER_NO_SCALING; 255 min_scale = DRM_PLANE_HELPER_NO_SCALING;
257 max_scale = DRM_PLANE_HELPER_NO_SCALING; 256 max_scale = DRM_PLANE_HELPER_NO_SCALING;
diff --git a/drivers/gpu/drm/sun4i/sunxi_engine.h b/drivers/gpu/drm/sun4i/sunxi_engine.h
index 4cb70ae65c79..d317ea04b8aa 100644
--- a/drivers/gpu/drm/sun4i/sunxi_engine.h
+++ b/drivers/gpu/drm/sun4i/sunxi_engine.h
@@ -12,16 +12,106 @@
12 12
13struct drm_plane; 13struct drm_plane;
14struct drm_device; 14struct drm_device;
15struct drm_crtc_state;
15 16
16struct sunxi_engine; 17struct sunxi_engine;
17 18
19/**
20 * struct sunxi_engine_ops - helper operations for sunXi engines
21 *
22 * These hooks are used by the common part of the DRM driver to
23 * implement the proper behaviour.
24 */
18struct sunxi_engine_ops { 25struct sunxi_engine_ops {
26 /**
27 * @atomic_begin:
28 *
29 * This callback allows to prepare our engine for an atomic
30 * update. This is mirroring the
31 * &drm_crtc_helper_funcs.atomic_begin callback, so any
32 * documentation there applies.
33 *
34 * This function is optional.
35 */
36 void (*atomic_begin)(struct sunxi_engine *engine,
37 struct drm_crtc_state *old_state);
38
39 /**
40 * @atomic_check:
41 *
42 * This callback allows to validate plane-update related CRTC
43 * constraints specific to engines. This is mirroring the
44 * &drm_crtc_helper_funcs.atomic_check callback, so any
45 * documentation there applies.
46 *
47 * This function is optional.
48 *
49 * RETURNS:
50 *
51 * 0 on success or a negative error code.
52 */
53 int (*atomic_check)(struct sunxi_engine *engine,
54 struct drm_crtc_state *state);
55
56 /**
57 * @commit:
58 *
59 * This callback will trigger the hardware switch to commit
60 * the new configuration that has been setup during the next
61 * vblank period.
62 *
63 * This function is optional.
64 */
19 void (*commit)(struct sunxi_engine *engine); 65 void (*commit)(struct sunxi_engine *engine);
66
67 /**
68 * @layers_init:
69 *
70 * This callback is used to allocate, initialize and register
71 * the layers supported by that engine.
72 *
73 * This function is mandatory.
74 *
75 * RETURNS:
76 *
77 * The array of struct drm_plane backing the layers, or an
78 * error pointer on failure.
79 */
20 struct drm_plane **(*layers_init)(struct drm_device *drm, 80 struct drm_plane **(*layers_init)(struct drm_device *drm,
21 struct sunxi_engine *engine); 81 struct sunxi_engine *engine);
22 82
83 /**
84 * @apply_color_correction:
85 *
86 * This callback will enable the color correction in the
87 * engine. This is useful only for the composite output.
88 *
89 * This function is optional.
90 */
23 void (*apply_color_correction)(struct sunxi_engine *engine); 91 void (*apply_color_correction)(struct sunxi_engine *engine);
92
93 /**
94 * @disable_color_correction:
95 *
96 * This callback will stop the color correction in the
97 * engine. This is useful only for the composite output.
98 *
99 * This function is optional.
100 */
24 void (*disable_color_correction)(struct sunxi_engine *engine); 101 void (*disable_color_correction)(struct sunxi_engine *engine);
102
103 /**
104 * @vblank_quirk:
105 *
106 * This callback is used to implement engine-specific
107 * behaviour part of the VBLANK event. It is run with all the
108 * constraints of an interrupt (can't sleep, all local
109 * interrupts disabled) and therefore should be as fast as
110 * possible.
111 *
112 * This function is optional.
113 */
114 void (*vblank_quirk)(struct sunxi_engine *engine);
25}; 115};
26 116
27/** 117/**
diff --git a/drivers/gpu/drm/tegra/plane.c b/drivers/gpu/drm/tegra/plane.c
index 36a06a993698..7267a01e6f08 100644
--- a/drivers/gpu/drm/tegra/plane.c
+++ b/drivers/gpu/drm/tegra/plane.c
@@ -82,7 +82,7 @@ int tegra_plane_state_add(struct tegra_plane *plane,
82{ 82{
83 struct drm_crtc_state *crtc_state; 83 struct drm_crtc_state *crtc_state;
84 struct tegra_dc_state *tegra; 84 struct tegra_dc_state *tegra;
85 struct drm_rect clip; 85 struct drm_rect clip = {};
86 int err; 86 int err;
87 87
88 /* Propagate errors from allocation or locking failures. */ 88 /* Propagate errors from allocation or locking failures. */
@@ -90,10 +90,9 @@ int tegra_plane_state_add(struct tegra_plane *plane,
90 if (IS_ERR(crtc_state)) 90 if (IS_ERR(crtc_state))
91 return PTR_ERR(crtc_state); 91 return PTR_ERR(crtc_state);
92 92
93 clip.x1 = 0; 93 if (crtc_state->enable)
94 clip.y1 = 0; 94 drm_mode_get_hv_timing(&crtc_state->mode,
95 clip.x2 = crtc_state->mode.hdisplay; 95 &clip.x2, &clip.y2);
96 clip.y2 = crtc_state->mode.vdisplay;
97 96
98 /* Check plane state for visibility and calculate clipping bounds */ 97 /* Check plane state for visibility and calculate clipping bounds */
99 err = drm_atomic_helper_check_plane_state(state, crtc_state, &clip, 98 err = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-pipe.c b/drivers/gpu/drm/tinydrm/core/tinydrm-pipe.c
index f41fc506ff87..11ae950b0fc9 100644
--- a/drivers/gpu/drm/tinydrm/core/tinydrm-pipe.c
+++ b/drivers/gpu/drm/tinydrm/core/tinydrm-pipe.c
@@ -15,7 +15,7 @@
15 15
16struct tinydrm_connector { 16struct tinydrm_connector {
17 struct drm_connector base; 17 struct drm_connector base;
18 const struct drm_display_mode *mode; 18 struct drm_display_mode mode;
19}; 19};
20 20
21static inline struct tinydrm_connector * 21static inline struct tinydrm_connector *
@@ -29,7 +29,7 @@ static int tinydrm_connector_get_modes(struct drm_connector *connector)
29 struct tinydrm_connector *tconn = to_tinydrm_connector(connector); 29 struct tinydrm_connector *tconn = to_tinydrm_connector(connector);
30 struct drm_display_mode *mode; 30 struct drm_display_mode *mode;
31 31
32 mode = drm_mode_duplicate(connector->dev, tconn->mode); 32 mode = drm_mode_duplicate(connector->dev, &tconn->mode);
33 if (!mode) { 33 if (!mode) {
34 DRM_ERROR("Failed to duplicate mode\n"); 34 DRM_ERROR("Failed to duplicate mode\n");
35 return 0; 35 return 0;
@@ -92,7 +92,7 @@ tinydrm_connector_create(struct drm_device *drm,
92 if (!tconn) 92 if (!tconn)
93 return ERR_PTR(-ENOMEM); 93 return ERR_PTR(-ENOMEM);
94 94
95 tconn->mode = mode; 95 drm_mode_copy(&tconn->mode, mode);
96 connector = &tconn->base; 96 connector = &tconn->base;
97 97
98 drm_connector_helper_add(connector, &tinydrm_connector_hfuncs); 98 drm_connector_helper_add(connector, &tinydrm_connector_hfuncs);
@@ -199,35 +199,27 @@ tinydrm_display_pipe_init(struct tinydrm_device *tdev,
199 unsigned int rotation) 199 unsigned int rotation)
200{ 200{
201 struct drm_device *drm = tdev->drm; 201 struct drm_device *drm = tdev->drm;
202 struct drm_display_mode *mode_copy; 202 struct drm_display_mode mode_copy;
203 struct drm_connector *connector; 203 struct drm_connector *connector;
204 int ret; 204 int ret;
205 205
206 mode_copy = devm_kmalloc(drm->dev, sizeof(*mode_copy), GFP_KERNEL); 206 drm_mode_copy(&mode_copy, mode);
207 if (!mode_copy) 207 ret = tinydrm_rotate_mode(&mode_copy, rotation);
208 return -ENOMEM;
209
210 *mode_copy = *mode;
211 ret = tinydrm_rotate_mode(mode_copy, rotation);
212 if (ret) { 208 if (ret) {
213 DRM_ERROR("Illegal rotation value %u\n", rotation); 209 DRM_ERROR("Illegal rotation value %u\n", rotation);
214 return -EINVAL; 210 return -EINVAL;
215 } 211 }
216 212
217 drm->mode_config.min_width = mode_copy->hdisplay; 213 drm->mode_config.min_width = mode_copy.hdisplay;
218 drm->mode_config.max_width = mode_copy->hdisplay; 214 drm->mode_config.max_width = mode_copy.hdisplay;
219 drm->mode_config.min_height = mode_copy->vdisplay; 215 drm->mode_config.min_height = mode_copy.vdisplay;
220 drm->mode_config.max_height = mode_copy->vdisplay; 216 drm->mode_config.max_height = mode_copy.vdisplay;
221 217
222 connector = tinydrm_connector_create(drm, mode_copy, connector_type); 218 connector = tinydrm_connector_create(drm, &mode_copy, connector_type);
223 if (IS_ERR(connector)) 219 if (IS_ERR(connector))
224 return PTR_ERR(connector); 220 return PTR_ERR(connector);
225 221
226 ret = drm_simple_display_pipe_init(drm, &tdev->pipe, funcs, formats, 222 return drm_simple_display_pipe_init(drm, &tdev->pipe, funcs, formats,
227 format_count, NULL, connector); 223 format_count, NULL, connector);
228 if (ret)
229 return ret;
230
231 return 0;
232} 224}
233EXPORT_SYMBOL(tinydrm_display_pipe_init); 225EXPORT_SYMBOL(tinydrm_display_pipe_init);
diff --git a/drivers/gpu/drm/tinydrm/ili9225.c b/drivers/gpu/drm/tinydrm/ili9225.c
index c0cf49849302..a0759502b81a 100644
--- a/drivers/gpu/drm/tinydrm/ili9225.c
+++ b/drivers/gpu/drm/tinydrm/ili9225.c
@@ -180,7 +180,6 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe,
180{ 180{
181 struct tinydrm_device *tdev = pipe_to_tinydrm(pipe); 181 struct tinydrm_device *tdev = pipe_to_tinydrm(pipe);
182 struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); 182 struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev);
183 struct drm_framebuffer *fb = pipe->plane.fb;
184 struct device *dev = tdev->drm->dev; 183 struct device *dev = tdev->drm->dev;
185 int ret; 184 int ret;
186 u8 am_id; 185 u8 am_id;
@@ -269,10 +268,7 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe,
269 268
270 ili9225_command(mipi, ILI9225_DISPLAY_CONTROL_1, 0x1017); 269 ili9225_command(mipi, ILI9225_DISPLAY_CONTROL_1, 0x1017);
271 270
272 mipi->enabled = true; 271 mipi_dbi_enable_flush(mipi);
273
274 if (fb)
275 fb->funcs->dirty(fb, NULL, 0, 0, NULL, 0);
276} 272}
277 273
278static void ili9225_pipe_disable(struct drm_simple_display_pipe *pipe) 274static void ili9225_pipe_disable(struct drm_simple_display_pipe *pipe)
diff --git a/drivers/gpu/drm/tinydrm/mi0283qt.c b/drivers/gpu/drm/tinydrm/mi0283qt.c
index 674d407640be..79cb5af5abac 100644
--- a/drivers/gpu/drm/tinydrm/mi0283qt.c
+++ b/drivers/gpu/drm/tinydrm/mi0283qt.c
@@ -9,47 +9,59 @@
9 * (at your option) any later version. 9 * (at your option) any later version.
10 */ 10 */
11 11
12#include <drm/drm_fb_helper.h>
13#include <drm/drm_modeset_helper.h>
14#include <drm/tinydrm/ili9341.h>
15#include <drm/tinydrm/mipi-dbi.h>
16#include <drm/tinydrm/tinydrm-helpers.h>
17#include <linux/delay.h> 12#include <linux/delay.h>
18#include <linux/gpio/consumer.h> 13#include <linux/gpio/consumer.h>
19#include <linux/module.h> 14#include <linux/module.h>
20#include <linux/property.h> 15#include <linux/property.h>
21#include <linux/regulator/consumer.h> 16#include <linux/regulator/consumer.h>
22#include <linux/spi/spi.h> 17#include <linux/spi/spi.h>
18
19#include <drm/drm_fb_helper.h>
20#include <drm/drm_modeset_helper.h>
21#include <drm/tinydrm/mipi-dbi.h>
22#include <drm/tinydrm/tinydrm-helpers.h>
23#include <video/mipi_display.h> 23#include <video/mipi_display.h>
24 24
25static int mi0283qt_init(struct mipi_dbi *mipi) 25#define ILI9341_FRMCTR1 0xb1
26#define ILI9341_DISCTRL 0xb6
27#define ILI9341_ETMOD 0xb7
28
29#define ILI9341_PWCTRL1 0xc0
30#define ILI9341_PWCTRL2 0xc1
31#define ILI9341_VMCTRL1 0xc5
32#define ILI9341_VMCTRL2 0xc7
33#define ILI9341_PWCTRLA 0xcb
34#define ILI9341_PWCTRLB 0xcf
35
36#define ILI9341_PGAMCTRL 0xe0
37#define ILI9341_NGAMCTRL 0xe1
38#define ILI9341_DTCTRLA 0xe8
39#define ILI9341_DTCTRLB 0xea
40#define ILI9341_PWRSEQ 0xed
41
42#define ILI9341_EN3GAM 0xf2
43#define ILI9341_PUMPCTRL 0xf7
44
45#define ILI9341_MADCTL_BGR BIT(3)
46#define ILI9341_MADCTL_MV BIT(5)
47#define ILI9341_MADCTL_MX BIT(6)
48#define ILI9341_MADCTL_MY BIT(7)
49
50static void mi0283qt_enable(struct drm_simple_display_pipe *pipe,
51 struct drm_crtc_state *crtc_state)
26{ 52{
27 struct tinydrm_device *tdev = &mipi->tinydrm; 53 struct tinydrm_device *tdev = pipe_to_tinydrm(pipe);
28 struct device *dev = tdev->drm->dev; 54 struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev);
29 u8 addr_mode; 55 u8 addr_mode;
30 int ret; 56 int ret;
31 57
32 DRM_DEBUG_KMS("\n"); 58 DRM_DEBUG_KMS("\n");
33 59
34 ret = regulator_enable(mipi->regulator); 60 ret = mipi_dbi_poweron_conditional_reset(mipi);
35 if (ret) { 61 if (ret < 0)
36 DRM_DEV_ERROR(dev, "Failed to enable regulator %d\n", ret); 62 return;
37 return ret; 63 if (ret == 1)
38 } 64 goto out_enable;
39
40 /* Avoid flicker by skipping setup if the bootloader has done it */
41 if (mipi_dbi_display_is_on(mipi))
42 return 0;
43
44 mipi_dbi_hw_reset(mipi);
45 ret = mipi_dbi_command(mipi, MIPI_DCS_SOFT_RESET);
46 if (ret) {
47 DRM_DEV_ERROR(dev, "Error sending command %d\n", ret);
48 regulator_disable(mipi->regulator);
49 return ret;
50 }
51
52 msleep(20);
53 65
54 mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_OFF); 66 mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_OFF);
55 67
@@ -68,7 +80,7 @@ static int mi0283qt_init(struct mipi_dbi *mipi)
68 mipi_dbi_command(mipi, ILI9341_VMCTRL2, 0xbe); 80 mipi_dbi_command(mipi, ILI9341_VMCTRL2, 0xbe);
69 81
70 /* Memory Access Control */ 82 /* Memory Access Control */
71 mipi_dbi_command(mipi, MIPI_DCS_SET_PIXEL_FORMAT, 0x55); 83 mipi_dbi_command(mipi, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT);
72 84
73 switch (mipi->rotation) { 85 switch (mipi->rotation) {
74 default: 86 default:
@@ -112,19 +124,12 @@ static int mi0283qt_init(struct mipi_dbi *mipi)
112 mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_ON); 124 mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_ON);
113 msleep(100); 125 msleep(100);
114 126
115 return 0; 127out_enable:
116} 128 mipi_dbi_enable_flush(mipi);
117
118static void mi0283qt_fini(void *data)
119{
120 struct mipi_dbi *mipi = data;
121
122 DRM_DEBUG_KMS("\n");
123 regulator_disable(mipi->regulator);
124} 129}
125 130
126static const struct drm_simple_display_pipe_funcs mi0283qt_pipe_funcs = { 131static const struct drm_simple_display_pipe_funcs mi0283qt_pipe_funcs = {
127 .enable = mipi_dbi_pipe_enable, 132 .enable = mi0283qt_enable,
128 .disable = mipi_dbi_pipe_disable, 133 .disable = mipi_dbi_pipe_disable,
129 .update = tinydrm_display_pipe_update, 134 .update = tinydrm_display_pipe_update,
130 .prepare_fb = tinydrm_display_pipe_prepare_fb, 135 .prepare_fb = tinydrm_display_pipe_prepare_fb,
@@ -205,17 +210,6 @@ static int mi0283qt_probe(struct spi_device *spi)
205 if (ret) 210 if (ret)
206 return ret; 211 return ret;
207 212
208 ret = mi0283qt_init(mipi);
209 if (ret)
210 return ret;
211
212 /* use devres to fini after drm unregister (drv->remove is before) */
213 ret = devm_add_action(dev, mi0283qt_fini, mipi);
214 if (ret) {
215 mi0283qt_fini(mipi);
216 return ret;
217 }
218
219 spi_set_drvdata(spi, mipi); 213 spi_set_drvdata(spi, mipi);
220 214
221 return devm_tinydrm_register(&mipi->tinydrm); 215 return devm_tinydrm_register(&mipi->tinydrm);
@@ -231,25 +225,13 @@ static void mi0283qt_shutdown(struct spi_device *spi)
231static int __maybe_unused mi0283qt_pm_suspend(struct device *dev) 225static int __maybe_unused mi0283qt_pm_suspend(struct device *dev)
232{ 226{
233 struct mipi_dbi *mipi = dev_get_drvdata(dev); 227 struct mipi_dbi *mipi = dev_get_drvdata(dev);
234 int ret;
235 228
236 ret = drm_mode_config_helper_suspend(mipi->tinydrm.drm); 229 return drm_mode_config_helper_suspend(mipi->tinydrm.drm);
237 if (ret)
238 return ret;
239
240 mi0283qt_fini(mipi);
241
242 return 0;
243} 230}
244 231
245static int __maybe_unused mi0283qt_pm_resume(struct device *dev) 232static int __maybe_unused mi0283qt_pm_resume(struct device *dev)
246{ 233{
247 struct mipi_dbi *mipi = dev_get_drvdata(dev); 234 struct mipi_dbi *mipi = dev_get_drvdata(dev);
248 int ret;
249
250 ret = mi0283qt_init(mipi);
251 if (ret)
252 return ret;
253 235
254 drm_mode_config_helper_resume(mipi->tinydrm.drm); 236 drm_mode_config_helper_resume(mipi->tinydrm.drm);
255 237
diff --git a/drivers/gpu/drm/tinydrm/mipi-dbi.c b/drivers/gpu/drm/tinydrm/mipi-dbi.c
index aa6b6ce56891..75dd65c57e74 100644
--- a/drivers/gpu/drm/tinydrm/mipi-dbi.c
+++ b/drivers/gpu/drm/tinydrm/mipi-dbi.c
@@ -271,21 +271,16 @@ static const struct drm_framebuffer_funcs mipi_dbi_fb_funcs = {
271}; 271};
272 272
273/** 273/**
274 * mipi_dbi_pipe_enable - MIPI DBI pipe enable helper 274 * mipi_dbi_enable_flush - MIPI DBI enable helper
275 * @pipe: Display pipe 275 * @mipi: MIPI DBI structure
276 * @crtc_state: CRTC state
277 * 276 *
278 * This function enables backlight. Drivers can use this as their 277 * This function sets &mipi_dbi->enabled, flushes the whole framebuffer and
278 * enables the backlight. Drivers can use this in their
279 * &drm_simple_display_pipe_funcs->enable callback. 279 * &drm_simple_display_pipe_funcs->enable callback.
280 */ 280 */
281void mipi_dbi_pipe_enable(struct drm_simple_display_pipe *pipe, 281void mipi_dbi_enable_flush(struct mipi_dbi *mipi)
282 struct drm_crtc_state *crtc_state)
283{ 282{
284 struct tinydrm_device *tdev = pipe_to_tinydrm(pipe); 283 struct drm_framebuffer *fb = mipi->tinydrm.pipe.plane.fb;
285 struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev);
286 struct drm_framebuffer *fb = pipe->plane.fb;
287
288 DRM_DEBUG_KMS("\n");
289 284
290 mipi->enabled = true; 285 mipi->enabled = true;
291 if (fb) 286 if (fb)
@@ -293,7 +288,7 @@ void mipi_dbi_pipe_enable(struct drm_simple_display_pipe *pipe,
293 288
294 tinydrm_enable_backlight(mipi->backlight); 289 tinydrm_enable_backlight(mipi->backlight);
295} 290}
296EXPORT_SYMBOL(mipi_dbi_pipe_enable); 291EXPORT_SYMBOL(mipi_dbi_enable_flush);
297 292
298static void mipi_dbi_blank(struct mipi_dbi *mipi) 293static void mipi_dbi_blank(struct mipi_dbi *mipi)
299{ 294{
@@ -316,8 +311,8 @@ static void mipi_dbi_blank(struct mipi_dbi *mipi)
316 * mipi_dbi_pipe_disable - MIPI DBI pipe disable helper 311 * mipi_dbi_pipe_disable - MIPI DBI pipe disable helper
317 * @pipe: Display pipe 312 * @pipe: Display pipe
318 * 313 *
319 * This function disables backlight if present or if not the 314 * This function disables backlight if present, if not the display memory is
320 * display memory is blanked. Drivers can use this as their 315 * blanked. The regulator is disabled if in use. Drivers can use this as their
321 * &drm_simple_display_pipe_funcs->disable callback. 316 * &drm_simple_display_pipe_funcs->disable callback.
322 */ 317 */
323void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe) 318void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe)
@@ -333,6 +328,9 @@ void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe)
333 tinydrm_disable_backlight(mipi->backlight); 328 tinydrm_disable_backlight(mipi->backlight);
334 else 329 else
335 mipi_dbi_blank(mipi); 330 mipi_dbi_blank(mipi);
331
332 if (mipi->regulator)
333 regulator_disable(mipi->regulator);
336} 334}
337EXPORT_SYMBOL(mipi_dbi_pipe_disable); 335EXPORT_SYMBOL(mipi_dbi_pipe_disable);
338 336
@@ -416,7 +414,7 @@ void mipi_dbi_hw_reset(struct mipi_dbi *mipi)
416 return; 414 return;
417 415
418 gpiod_set_value_cansleep(mipi->reset, 0); 416 gpiod_set_value_cansleep(mipi->reset, 0);
419 msleep(20); 417 usleep_range(20, 1000);
420 gpiod_set_value_cansleep(mipi->reset, 1); 418 gpiod_set_value_cansleep(mipi->reset, 1);
421 msleep(120); 419 msleep(120);
422} 420}
@@ -443,6 +441,7 @@ bool mipi_dbi_display_is_on(struct mipi_dbi *mipi)
443 441
444 val &= ~DCS_POWER_MODE_RESERVED_MASK; 442 val &= ~DCS_POWER_MODE_RESERVED_MASK;
445 443
444 /* The poweron/reset value is 08h DCS_POWER_MODE_DISPLAY_NORMAL_MODE */
446 if (val != (DCS_POWER_MODE_DISPLAY | 445 if (val != (DCS_POWER_MODE_DISPLAY |
447 DCS_POWER_MODE_DISPLAY_NORMAL_MODE | DCS_POWER_MODE_SLEEP_MODE)) 446 DCS_POWER_MODE_DISPLAY_NORMAL_MODE | DCS_POWER_MODE_SLEEP_MODE))
448 return false; 447 return false;
@@ -453,6 +452,78 @@ bool mipi_dbi_display_is_on(struct mipi_dbi *mipi)
453} 452}
454EXPORT_SYMBOL(mipi_dbi_display_is_on); 453EXPORT_SYMBOL(mipi_dbi_display_is_on);
455 454
455static int mipi_dbi_poweron_reset_conditional(struct mipi_dbi *mipi, bool cond)
456{
457 struct device *dev = mipi->tinydrm.drm->dev;
458 int ret;
459
460 if (mipi->regulator) {
461 ret = regulator_enable(mipi->regulator);
462 if (ret) {
463 DRM_DEV_ERROR(dev, "Failed to enable regulator (%d)\n", ret);
464 return ret;
465 }
466 }
467
468 if (cond && mipi_dbi_display_is_on(mipi))
469 return 1;
470
471 mipi_dbi_hw_reset(mipi);
472 ret = mipi_dbi_command(mipi, MIPI_DCS_SOFT_RESET);
473 if (ret) {
474 DRM_DEV_ERROR(dev, "Failed to send reset command (%d)\n", ret);
475 if (mipi->regulator)
476 regulator_disable(mipi->regulator);
477 return ret;
478 }
479
480 /*
481 * If we did a hw reset, we know the controller is in Sleep mode and
482 * per MIPI DSC spec should wait 5ms after soft reset. If we didn't,
483 * we assume worst case and wait 120ms.
484 */
485 if (mipi->reset)
486 usleep_range(5000, 20000);
487 else
488 msleep(120);
489
490 return 0;
491}
492
493/**
494 * mipi_dbi_poweron_reset - MIPI DBI poweron and reset
495 * @mipi: MIPI DBI structure
496 *
497 * This function enables the regulator if used and does a hardware and software
498 * reset.
499 *
500 * Returns:
501 * Zero on success, or a negative error code.
502 */
503int mipi_dbi_poweron_reset(struct mipi_dbi *mipi)
504{
505 return mipi_dbi_poweron_reset_conditional(mipi, false);
506}
507EXPORT_SYMBOL(mipi_dbi_poweron_reset);
508
509/**
510 * mipi_dbi_poweron_conditional_reset - MIPI DBI poweron and conditional reset
511 * @mipi: MIPI DBI structure
512 *
513 * This function enables the regulator if used and if the display is off, it
514 * does a hardware and software reset. If mipi_dbi_display_is_on() determines
515 * that the display is on, no reset is performed.
516 *
517 * Returns:
518 * Zero if the controller was reset, 1 if the display was already on, or a
519 * negative error code.
520 */
521int mipi_dbi_poweron_conditional_reset(struct mipi_dbi *mipi)
522{
523 return mipi_dbi_poweron_reset_conditional(mipi, true);
524}
525EXPORT_SYMBOL(mipi_dbi_poweron_conditional_reset);
526
456#if IS_ENABLED(CONFIG_SPI) 527#if IS_ENABLED(CONFIG_SPI)
457 528
458/** 529/**
diff --git a/drivers/gpu/drm/tinydrm/st7586.c b/drivers/gpu/drm/tinydrm/st7586.c
index 5aebfceb740e..a6396ef9cc4a 100644
--- a/drivers/gpu/drm/tinydrm/st7586.c
+++ b/drivers/gpu/drm/tinydrm/st7586.c
@@ -179,20 +179,16 @@ static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe,
179{ 179{
180 struct tinydrm_device *tdev = pipe_to_tinydrm(pipe); 180 struct tinydrm_device *tdev = pipe_to_tinydrm(pipe);
181 struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); 181 struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev);
182 struct drm_framebuffer *fb = pipe->plane.fb;
183 struct device *dev = tdev->drm->dev;
184 int ret; 182 int ret;
185 u8 addr_mode; 183 u8 addr_mode;
186 184
187 DRM_DEBUG_KMS("\n"); 185 DRM_DEBUG_KMS("\n");
188 186
189 mipi_dbi_hw_reset(mipi); 187 ret = mipi_dbi_poweron_reset(mipi);
190 ret = mipi_dbi_command(mipi, ST7586_AUTO_READ_CTRL, 0x9f); 188 if (ret)
191 if (ret) {
192 DRM_DEV_ERROR(dev, "Error sending command %d\n", ret);
193 return; 189 return;
194 }
195 190
191 mipi_dbi_command(mipi, ST7586_AUTO_READ_CTRL, 0x9f);
196 mipi_dbi_command(mipi, ST7586_OTP_RW_CTRL, 0x00); 192 mipi_dbi_command(mipi, ST7586_OTP_RW_CTRL, 0x00);
197 193
198 msleep(10); 194 msleep(10);
@@ -241,10 +237,7 @@ static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe,
241 237
242 mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_ON); 238 mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_ON);
243 239
244 mipi->enabled = true; 240 mipi_dbi_enable_flush(mipi);
245
246 if (fb)
247 fb->funcs->dirty(fb, NULL, 0, 0, NULL, 0);
248} 241}
249 242
250static void st7586_pipe_disable(struct drm_simple_display_pipe *pipe) 243static void st7586_pipe_disable(struct drm_simple_display_pipe *pipe)
diff --git a/drivers/gpu/drm/tinydrm/st7735r.c b/drivers/gpu/drm/tinydrm/st7735r.c
index 98ff447f40b4..08b4fb18edb6 100644
--- a/drivers/gpu/drm/tinydrm/st7735r.c
+++ b/drivers/gpu/drm/tinydrm/st7735r.c
@@ -40,19 +40,14 @@ static void jd_t18003_t01_pipe_enable(struct drm_simple_display_pipe *pipe,
40{ 40{
41 struct tinydrm_device *tdev = pipe_to_tinydrm(pipe); 41 struct tinydrm_device *tdev = pipe_to_tinydrm(pipe);
42 struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); 42 struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev);
43 struct device *dev = tdev->drm->dev;
44 int ret; 43 int ret;
45 u8 addr_mode; 44 u8 addr_mode;
46 45
47 DRM_DEBUG_KMS("\n"); 46 DRM_DEBUG_KMS("\n");
48 47
49 mipi_dbi_hw_reset(mipi); 48 ret = mipi_dbi_poweron_reset(mipi);
50 49 if (ret)
51 ret = mipi_dbi_command(mipi, MIPI_DCS_SOFT_RESET);
52 if (ret) {
53 DRM_DEV_ERROR(dev, "Error sending command %d\n", ret);
54 return; 50 return;
55 }
56 51
57 msleep(150); 52 msleep(150);
58 53
@@ -102,7 +97,7 @@ static void jd_t18003_t01_pipe_enable(struct drm_simple_display_pipe *pipe,
102 97
103 msleep(20); 98 msleep(20);
104 99
105 mipi_dbi_pipe_enable(pipe, crtc_state); 100 mipi_dbi_enable_flush(mipi);
106} 101}
107 102
108static const struct drm_simple_display_pipe_funcs jd_t18003_t01_pipe_funcs = { 103static const struct drm_simple_display_pipe_funcs jd_t18003_t01_pipe_funcs = {
diff --git a/drivers/gpu/drm/vc4/Makefile b/drivers/gpu/drm/vc4/Makefile
index f5500df51686..4a3a868235f8 100644
--- a/drivers/gpu/drm/vc4/Makefile
+++ b/drivers/gpu/drm/vc4/Makefile
@@ -15,6 +15,7 @@ vc4-y := \
15 vc4_vec.o \ 15 vc4_vec.o \
16 vc4_hvs.o \ 16 vc4_hvs.o \
17 vc4_irq.o \ 17 vc4_irq.o \
18 vc4_perfmon.o \
18 vc4_plane.o \ 19 vc4_plane.o \
19 vc4_render_cl.o \ 20 vc4_render_cl.o \
20 vc4_trace_points.o \ 21 vc4_trace_points.o \
diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
index ceb385fd69c5..94b99c90425a 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -101,6 +101,7 @@ static int vc4_get_param_ioctl(struct drm_device *dev, void *data,
101 case DRM_VC4_PARAM_SUPPORTS_THREADED_FS: 101 case DRM_VC4_PARAM_SUPPORTS_THREADED_FS:
102 case DRM_VC4_PARAM_SUPPORTS_FIXED_RCL_ORDER: 102 case DRM_VC4_PARAM_SUPPORTS_FIXED_RCL_ORDER:
103 case DRM_VC4_PARAM_SUPPORTS_MADVISE: 103 case DRM_VC4_PARAM_SUPPORTS_MADVISE:
104 case DRM_VC4_PARAM_SUPPORTS_PERFMON:
104 args->value = true; 105 args->value = true;
105 break; 106 break;
106 default: 107 default:
@@ -111,6 +112,26 @@ static int vc4_get_param_ioctl(struct drm_device *dev, void *data,
111 return 0; 112 return 0;
112} 113}
113 114
115static int vc4_open(struct drm_device *dev, struct drm_file *file)
116{
117 struct vc4_file *vc4file;
118
119 vc4file = kzalloc(sizeof(*vc4file), GFP_KERNEL);
120 if (!vc4file)
121 return -ENOMEM;
122
123 vc4_perfmon_open_file(vc4file);
124 file->driver_priv = vc4file;
125 return 0;
126}
127
128static void vc4_close(struct drm_device *dev, struct drm_file *file)
129{
130 struct vc4_file *vc4file = file->driver_priv;
131
132 vc4_perfmon_close_file(vc4file);
133}
134
114static const struct vm_operations_struct vc4_vm_ops = { 135static const struct vm_operations_struct vc4_vm_ops = {
115 .fault = vc4_fault, 136 .fault = vc4_fault,
116 .open = drm_gem_vm_open, 137 .open = drm_gem_vm_open,
@@ -143,6 +164,9 @@ static const struct drm_ioctl_desc vc4_drm_ioctls[] = {
143 DRM_IOCTL_DEF_DRV(VC4_GET_TILING, vc4_get_tiling_ioctl, DRM_RENDER_ALLOW), 164 DRM_IOCTL_DEF_DRV(VC4_GET_TILING, vc4_get_tiling_ioctl, DRM_RENDER_ALLOW),
144 DRM_IOCTL_DEF_DRV(VC4_LABEL_BO, vc4_label_bo_ioctl, DRM_RENDER_ALLOW), 165 DRM_IOCTL_DEF_DRV(VC4_LABEL_BO, vc4_label_bo_ioctl, DRM_RENDER_ALLOW),
145 DRM_IOCTL_DEF_DRV(VC4_GEM_MADVISE, vc4_gem_madvise_ioctl, DRM_RENDER_ALLOW), 166 DRM_IOCTL_DEF_DRV(VC4_GEM_MADVISE, vc4_gem_madvise_ioctl, DRM_RENDER_ALLOW),
167 DRM_IOCTL_DEF_DRV(VC4_PERFMON_CREATE, vc4_perfmon_create_ioctl, DRM_RENDER_ALLOW),
168 DRM_IOCTL_DEF_DRV(VC4_PERFMON_DESTROY, vc4_perfmon_destroy_ioctl, DRM_RENDER_ALLOW),
169 DRM_IOCTL_DEF_DRV(VC4_PERFMON_GET_VALUES, vc4_perfmon_get_values_ioctl, DRM_RENDER_ALLOW),
146}; 170};
147 171
148static struct drm_driver vc4_drm_driver = { 172static struct drm_driver vc4_drm_driver = {
@@ -153,6 +177,8 @@ static struct drm_driver vc4_drm_driver = {
153 DRIVER_RENDER | 177 DRIVER_RENDER |
154 DRIVER_PRIME), 178 DRIVER_PRIME),
155 .lastclose = drm_fb_helper_lastclose, 179 .lastclose = drm_fb_helper_lastclose,
180 .open = vc4_open,
181 .postclose = vc4_close,
156 .irq_handler = vc4_irq, 182 .irq_handler = vc4_irq,
157 .irq_preinstall = vc4_irq_preinstall, 183 .irq_preinstall = vc4_irq_preinstall,
158 .irq_postinstall = vc4_irq_postinstall, 184 .irq_postinstall = vc4_irq_postinstall,
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 3af22936d9b3..fefa1664a9f5 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -11,6 +11,8 @@
11#include <drm/drm_encoder.h> 11#include <drm/drm_encoder.h>
12#include <drm/drm_gem_cma_helper.h> 12#include <drm/drm_gem_cma_helper.h>
13 13
14#include "uapi/drm/vc4_drm.h"
15
14/* Don't forget to update vc4_bo.c: bo_type_names[] when adding to 16/* Don't forget to update vc4_bo.c: bo_type_names[] when adding to
15 * this. 17 * this.
16 */ 18 */
@@ -29,6 +31,36 @@ enum vc4_kernel_bo_type {
29 VC4_BO_TYPE_COUNT 31 VC4_BO_TYPE_COUNT
30}; 32};
31 33
34/* Performance monitor object. The perform lifetime is controlled by userspace
35 * using perfmon related ioctls. A perfmon can be attached to a submit_cl
36 * request, and when this is the case, HW perf counters will be activated just
37 * before the submit_cl is submitted to the GPU and disabled when the job is
38 * done. This way, only events related to a specific job will be counted.
39 */
40struct vc4_perfmon {
41 /* Tracks the number of users of the perfmon, when this counter reaches
42 * zero the perfmon is destroyed.
43 */
44 refcount_t refcnt;
45
46 /* Number of counters activated in this perfmon instance
47 * (should be less than DRM_VC4_MAX_PERF_COUNTERS).
48 */
49 u8 ncounters;
50
51 /* Events counted by the HW perf counters. */
52 u8 events[DRM_VC4_MAX_PERF_COUNTERS];
53
54 /* Storage for counter values. Counters are incremented by the HW
55 * perf counter values every time the perfmon is attached to a GPU job.
56 * This way, perfmon users don't have to retrieve the results after
57 * each job if they want to track events covering several submissions.
58 * Note that counter values can't be reset, but you can fake a reset by
59 * destroying the perfmon and creating a new one.
60 */
61 u64 counters[0];
62};
63
32struct vc4_dev { 64struct vc4_dev {
33 struct drm_device *dev; 65 struct drm_device *dev;
34 66
@@ -121,6 +153,11 @@ struct vc4_dev {
121 wait_queue_head_t job_wait_queue; 153 wait_queue_head_t job_wait_queue;
122 struct work_struct job_done_work; 154 struct work_struct job_done_work;
123 155
156 /* Used to track the active perfmon if any. Access to this field is
157 * protected by job_lock.
158 */
159 struct vc4_perfmon *active_perfmon;
160
124 /* List of struct vc4_seqno_cb for callbacks to be made from a 161 /* List of struct vc4_seqno_cb for callbacks to be made from a
125 * workqueue when the given seqno is passed. 162 * workqueue when the given seqno is passed.
126 */ 163 */
@@ -406,6 +443,21 @@ struct vc4_exec_info {
406 void *uniforms_v; 443 void *uniforms_v;
407 uint32_t uniforms_p; 444 uint32_t uniforms_p;
408 uint32_t uniforms_size; 445 uint32_t uniforms_size;
446
447 /* Pointer to a performance monitor object if the user requested it,
448 * NULL otherwise.
449 */
450 struct vc4_perfmon *perfmon;
451};
452
453/* Per-open file private data. Any driver-specific resource that has to be
454 * released when the DRM file is closed should be placed here.
455 */
456struct vc4_file {
457 struct {
458 struct idr idr;
459 struct mutex lock;
460 } perfmon;
409}; 461};
410 462
411static inline struct vc4_exec_info * 463static inline struct vc4_exec_info *
@@ -646,3 +698,19 @@ bool vc4_check_tex_size(struct vc4_exec_info *exec,
646/* vc4_validate_shader.c */ 698/* vc4_validate_shader.c */
647struct vc4_validated_shader_info * 699struct vc4_validated_shader_info *
648vc4_validate_shader(struct drm_gem_cma_object *shader_obj); 700vc4_validate_shader(struct drm_gem_cma_object *shader_obj);
701
702/* vc4_perfmon.c */
703void vc4_perfmon_get(struct vc4_perfmon *perfmon);
704void vc4_perfmon_put(struct vc4_perfmon *perfmon);
705void vc4_perfmon_start(struct vc4_dev *vc4, struct vc4_perfmon *perfmon);
706void vc4_perfmon_stop(struct vc4_dev *vc4, struct vc4_perfmon *perfmon,
707 bool capture);
708struct vc4_perfmon *vc4_perfmon_find(struct vc4_file *vc4file, int id);
709void vc4_perfmon_open_file(struct vc4_file *vc4file);
710void vc4_perfmon_close_file(struct vc4_file *vc4file);
711int vc4_perfmon_create_ioctl(struct drm_device *dev, void *data,
712 struct drm_file *file_priv);
713int vc4_perfmon_destroy_ioctl(struct drm_device *dev, void *data,
714 struct drm_file *file_priv);
715int vc4_perfmon_get_values_ioctl(struct drm_device *dev, void *data,
716 struct drm_file *file_priv);
diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c
index c94cce96544c..2107b0daf8ef 100644
--- a/drivers/gpu/drm/vc4/vc4_gem.c
+++ b/drivers/gpu/drm/vc4/vc4_gem.c
@@ -467,14 +467,30 @@ again:
467 467
468 vc4_flush_caches(dev); 468 vc4_flush_caches(dev);
469 469
470 /* Only start the perfmon if it was not already started by a previous
471 * job.
472 */
473 if (exec->perfmon && vc4->active_perfmon != exec->perfmon)
474 vc4_perfmon_start(vc4, exec->perfmon);
475
470 /* Either put the job in the binner if it uses the binner, or 476 /* Either put the job in the binner if it uses the binner, or
471 * immediately move it to the to-be-rendered queue. 477 * immediately move it to the to-be-rendered queue.
472 */ 478 */
473 if (exec->ct0ca != exec->ct0ea) { 479 if (exec->ct0ca != exec->ct0ea) {
474 submit_cl(dev, 0, exec->ct0ca, exec->ct0ea); 480 submit_cl(dev, 0, exec->ct0ca, exec->ct0ea);
475 } else { 481 } else {
482 struct vc4_exec_info *next;
483
476 vc4_move_job_to_render(dev, exec); 484 vc4_move_job_to_render(dev, exec);
477 goto again; 485 next = vc4_first_bin_job(vc4);
486
487 /* We can't start the next bin job if the previous job had a
488 * different perfmon instance attached to it. The same goes
489 * if one of them had a perfmon attached to it and the other
490 * one doesn't.
491 */
492 if (next && next->perfmon == exec->perfmon)
493 goto again;
478 } 494 }
479} 495}
480 496
@@ -642,6 +658,7 @@ vc4_queue_submit(struct drm_device *dev, struct vc4_exec_info *exec,
642 struct ww_acquire_ctx *acquire_ctx) 658 struct ww_acquire_ctx *acquire_ctx)
643{ 659{
644 struct vc4_dev *vc4 = to_vc4_dev(dev); 660 struct vc4_dev *vc4 = to_vc4_dev(dev);
661 struct vc4_exec_info *renderjob;
645 uint64_t seqno; 662 uint64_t seqno;
646 unsigned long irqflags; 663 unsigned long irqflags;
647 struct vc4_fence *fence; 664 struct vc4_fence *fence;
@@ -667,11 +684,14 @@ vc4_queue_submit(struct drm_device *dev, struct vc4_exec_info *exec,
667 684
668 list_add_tail(&exec->head, &vc4->bin_job_list); 685 list_add_tail(&exec->head, &vc4->bin_job_list);
669 686
670 /* If no job was executing, kick ours off. Otherwise, it'll 687 /* If no bin job was executing and if the render job (if any) has the
671 * get started when the previous job's flush done interrupt 688 * same perfmon as our job attached to it (or if both jobs don't have
672 * occurs. 689 * perfmon activated), then kick ours off. Otherwise, it'll get
690 * started when the previous job's flush/render done interrupt occurs.
673 */ 691 */
674 if (vc4_first_bin_job(vc4) == exec) { 692 renderjob = vc4_first_render_job(vc4);
693 if (vc4_first_bin_job(vc4) == exec &&
694 (!renderjob || renderjob->perfmon == exec->perfmon)) {
675 vc4_submit_next_bin_job(dev); 695 vc4_submit_next_bin_job(dev);
676 vc4_queue_hangcheck(dev); 696 vc4_queue_hangcheck(dev);
677 } 697 }
@@ -936,6 +956,9 @@ vc4_complete_exec(struct drm_device *dev, struct vc4_exec_info *exec)
936 vc4->bin_alloc_used &= ~exec->bin_slots; 956 vc4->bin_alloc_used &= ~exec->bin_slots;
937 spin_unlock_irqrestore(&vc4->job_lock, irqflags); 957 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
938 958
959 /* Release the reference we had on the perf monitor. */
960 vc4_perfmon_put(exec->perfmon);
961
939 mutex_lock(&vc4->power_lock); 962 mutex_lock(&vc4->power_lock);
940 if (--vc4->power_refcount == 0) { 963 if (--vc4->power_refcount == 0) {
941 pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev); 964 pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev);
@@ -1088,6 +1111,7 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data,
1088 struct drm_file *file_priv) 1111 struct drm_file *file_priv)
1089{ 1112{
1090 struct vc4_dev *vc4 = to_vc4_dev(dev); 1113 struct vc4_dev *vc4 = to_vc4_dev(dev);
1114 struct vc4_file *vc4file = file_priv->driver_priv;
1091 struct drm_vc4_submit_cl *args = data; 1115 struct drm_vc4_submit_cl *args = data;
1092 struct vc4_exec_info *exec; 1116 struct vc4_exec_info *exec;
1093 struct ww_acquire_ctx acquire_ctx; 1117 struct ww_acquire_ctx acquire_ctx;
@@ -1101,6 +1125,11 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data,
1101 return -EINVAL; 1125 return -EINVAL;
1102 } 1126 }
1103 1127
1128 if (args->pad2 != 0) {
1129 DRM_DEBUG("->pad2 must be set to zero\n");
1130 return -EINVAL;
1131 }
1132
1104 exec = kcalloc(1, sizeof(*exec), GFP_KERNEL); 1133 exec = kcalloc(1, sizeof(*exec), GFP_KERNEL);
1105 if (!exec) { 1134 if (!exec) {
1106 DRM_ERROR("malloc failure on exec struct\n"); 1135 DRM_ERROR("malloc failure on exec struct\n");
@@ -1126,6 +1155,15 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data,
1126 if (ret) 1155 if (ret)
1127 goto fail; 1156 goto fail;
1128 1157
1158 if (args->perfmonid) {
1159 exec->perfmon = vc4_perfmon_find(vc4file,
1160 args->perfmonid);
1161 if (!exec->perfmon) {
1162 ret = -ENOENT;
1163 goto fail;
1164 }
1165 }
1166
1129 if (exec->args->bin_cl_size != 0) { 1167 if (exec->args->bin_cl_size != 0) {
1130 ret = vc4_get_bcl(dev, exec); 1168 ret = vc4_get_bcl(dev, exec);
1131 if (ret) 1169 if (ret)
diff --git a/drivers/gpu/drm/vc4/vc4_irq.c b/drivers/gpu/drm/vc4/vc4_irq.c
index 3dd62d75f531..4cd2ccfe15f4 100644
--- a/drivers/gpu/drm/vc4/vc4_irq.c
+++ b/drivers/gpu/drm/vc4/vc4_irq.c
@@ -104,13 +104,20 @@ static void
104vc4_irq_finish_bin_job(struct drm_device *dev) 104vc4_irq_finish_bin_job(struct drm_device *dev)
105{ 105{
106 struct vc4_dev *vc4 = to_vc4_dev(dev); 106 struct vc4_dev *vc4 = to_vc4_dev(dev);
107 struct vc4_exec_info *exec = vc4_first_bin_job(vc4); 107 struct vc4_exec_info *next, *exec = vc4_first_bin_job(vc4);
108 108
109 if (!exec) 109 if (!exec)
110 return; 110 return;
111 111
112 vc4_move_job_to_render(dev, exec); 112 vc4_move_job_to_render(dev, exec);
113 vc4_submit_next_bin_job(dev); 113 next = vc4_first_bin_job(vc4);
114
115 /* Only submit the next job in the bin list if it matches the perfmon
116 * attached to the one that just finished (or if both jobs don't have
117 * perfmon attached to them).
118 */
119 if (next && next->perfmon == exec->perfmon)
120 vc4_submit_next_bin_job(dev);
114} 121}
115 122
116static void 123static void
@@ -122,6 +129,10 @@ vc4_cancel_bin_job(struct drm_device *dev)
122 if (!exec) 129 if (!exec)
123 return; 130 return;
124 131
132 /* Stop the perfmon so that the next bin job can be started. */
133 if (exec->perfmon)
134 vc4_perfmon_stop(vc4, exec->perfmon, false);
135
125 list_move_tail(&exec->head, &vc4->bin_job_list); 136 list_move_tail(&exec->head, &vc4->bin_job_list);
126 vc4_submit_next_bin_job(dev); 137 vc4_submit_next_bin_job(dev);
127} 138}
@@ -131,18 +142,41 @@ vc4_irq_finish_render_job(struct drm_device *dev)
131{ 142{
132 struct vc4_dev *vc4 = to_vc4_dev(dev); 143 struct vc4_dev *vc4 = to_vc4_dev(dev);
133 struct vc4_exec_info *exec = vc4_first_render_job(vc4); 144 struct vc4_exec_info *exec = vc4_first_render_job(vc4);
145 struct vc4_exec_info *nextbin, *nextrender;
134 146
135 if (!exec) 147 if (!exec)
136 return; 148 return;
137 149
138 vc4->finished_seqno++; 150 vc4->finished_seqno++;
139 list_move_tail(&exec->head, &vc4->job_done_list); 151 list_move_tail(&exec->head, &vc4->job_done_list);
152
153 nextbin = vc4_first_bin_job(vc4);
154 nextrender = vc4_first_render_job(vc4);
155
156 /* Only stop the perfmon if following jobs in the queue don't expect it
157 * to be enabled.
158 */
159 if (exec->perfmon && !nextrender &&
160 (!nextbin || nextbin->perfmon != exec->perfmon))
161 vc4_perfmon_stop(vc4, exec->perfmon, true);
162
163 /* If there's a render job waiting, start it. If this is not the case
164 * we may have to unblock the binner if it's been stalled because of
165 * perfmon (this can be checked by comparing the perfmon attached to
166 * the finished renderjob to the one attached to the next bin job: if
167 * they don't match, this means the binner is stalled and should be
168 * restarted).
169 */
170 if (nextrender)
171 vc4_submit_next_render_job(dev);
172 else if (nextbin && nextbin->perfmon != exec->perfmon)
173 vc4_submit_next_bin_job(dev);
174
140 if (exec->fence) { 175 if (exec->fence) {
141 dma_fence_signal_locked(exec->fence); 176 dma_fence_signal_locked(exec->fence);
142 dma_fence_put(exec->fence); 177 dma_fence_put(exec->fence);
143 exec->fence = NULL; 178 exec->fence = NULL;
144 } 179 }
145 vc4_submit_next_render_job(dev);
146 180
147 wake_up_all(&vc4->job_wait_queue); 181 wake_up_all(&vc4->job_wait_queue);
148 schedule_work(&vc4->job_done_work); 182 schedule_work(&vc4->job_done_work);
diff --git a/drivers/gpu/drm/vc4/vc4_perfmon.c b/drivers/gpu/drm/vc4/vc4_perfmon.c
new file mode 100644
index 000000000000..437e7a27f21d
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_perfmon.c
@@ -0,0 +1,188 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2018 Broadcom
4 */
5
6/**
7 * DOC: VC4 V3D performance monitor module
8 *
9 * The V3D block provides 16 hardware counters which can count various events.
10 */
11
12#include "vc4_drv.h"
13#include "vc4_regs.h"
14
15#define VC4_PERFMONID_MIN 1
16#define VC4_PERFMONID_MAX U32_MAX
17
18void vc4_perfmon_get(struct vc4_perfmon *perfmon)
19{
20 if (perfmon)
21 refcount_inc(&perfmon->refcnt);
22}
23
24void vc4_perfmon_put(struct vc4_perfmon *perfmon)
25{
26 if (perfmon && refcount_dec_and_test(&perfmon->refcnt))
27 kfree(perfmon);
28}
29
30void vc4_perfmon_start(struct vc4_dev *vc4, struct vc4_perfmon *perfmon)
31{
32 unsigned int i;
33 u32 mask;
34
35 if (WARN_ON_ONCE(!perfmon || vc4->active_perfmon))
36 return;
37
38 for (i = 0; i < perfmon->ncounters; i++)
39 V3D_WRITE(V3D_PCTRS(i), perfmon->events[i]);
40
41 mask = GENMASK(perfmon->ncounters - 1, 0);
42 V3D_WRITE(V3D_PCTRC, mask);
43 V3D_WRITE(V3D_PCTRE, V3D_PCTRE_EN | mask);
44 vc4->active_perfmon = perfmon;
45}
46
47void vc4_perfmon_stop(struct vc4_dev *vc4, struct vc4_perfmon *perfmon,
48 bool capture)
49{
50 unsigned int i;
51
52 if (WARN_ON_ONCE(!vc4->active_perfmon ||
53 perfmon != vc4->active_perfmon))
54 return;
55
56 if (capture) {
57 for (i = 0; i < perfmon->ncounters; i++)
58 perfmon->counters[i] += V3D_READ(V3D_PCTR(i));
59 }
60
61 V3D_WRITE(V3D_PCTRE, 0);
62 vc4->active_perfmon = NULL;
63}
64
65struct vc4_perfmon *vc4_perfmon_find(struct vc4_file *vc4file, int id)
66{
67 struct vc4_perfmon *perfmon;
68
69 mutex_lock(&vc4file->perfmon.lock);
70 perfmon = idr_find(&vc4file->perfmon.idr, id);
71 vc4_perfmon_get(perfmon);
72 mutex_unlock(&vc4file->perfmon.lock);
73
74 return perfmon;
75}
76
77void vc4_perfmon_open_file(struct vc4_file *vc4file)
78{
79 mutex_init(&vc4file->perfmon.lock);
80 idr_init(&vc4file->perfmon.idr);
81}
82
83static int vc4_perfmon_idr_del(int id, void *elem, void *data)
84{
85 struct vc4_perfmon *perfmon = elem;
86
87 vc4_perfmon_put(perfmon);
88
89 return 0;
90}
91
92void vc4_perfmon_close_file(struct vc4_file *vc4file)
93{
94 mutex_lock(&vc4file->perfmon.lock);
95 idr_for_each(&vc4file->perfmon.idr, vc4_perfmon_idr_del, NULL);
96 idr_destroy(&vc4file->perfmon.idr);
97 mutex_unlock(&vc4file->perfmon.lock);
98}
99
100int vc4_perfmon_create_ioctl(struct drm_device *dev, void *data,
101 struct drm_file *file_priv)
102{
103 struct vc4_file *vc4file = file_priv->driver_priv;
104 struct drm_vc4_perfmon_create *req = data;
105 struct vc4_perfmon *perfmon;
106 unsigned int i;
107 int ret;
108
109 /* Number of monitored counters cannot exceed HW limits. */
110 if (req->ncounters > DRM_VC4_MAX_PERF_COUNTERS ||
111 !req->ncounters)
112 return -EINVAL;
113
114 /* Make sure all events are valid. */
115 for (i = 0; i < req->ncounters; i++) {
116 if (req->events[i] >= VC4_PERFCNT_NUM_EVENTS)
117 return -EINVAL;
118 }
119
120 perfmon = kzalloc(sizeof(*perfmon) + (req->ncounters * sizeof(u64)),
121 GFP_KERNEL);
122 if (!perfmon)
123 return -ENOMEM;
124
125 for (i = 0; i < req->ncounters; i++)
126 perfmon->events[i] = req->events[i];
127
128 perfmon->ncounters = req->ncounters;
129
130 refcount_set(&perfmon->refcnt, 1);
131
132 mutex_lock(&vc4file->perfmon.lock);
133 ret = idr_alloc(&vc4file->perfmon.idr, perfmon, VC4_PERFMONID_MIN,
134 VC4_PERFMONID_MAX, GFP_KERNEL);
135 mutex_unlock(&vc4file->perfmon.lock);
136
137 if (ret < 0) {
138 kfree(perfmon);
139 return ret;
140 }
141
142 req->id = ret;
143 return 0;
144}
145
146int vc4_perfmon_destroy_ioctl(struct drm_device *dev, void *data,
147 struct drm_file *file_priv)
148{
149 struct vc4_file *vc4file = file_priv->driver_priv;
150 struct drm_vc4_perfmon_destroy *req = data;
151 struct vc4_perfmon *perfmon;
152
153 mutex_lock(&vc4file->perfmon.lock);
154 perfmon = idr_remove(&vc4file->perfmon.idr, req->id);
155 mutex_unlock(&vc4file->perfmon.lock);
156
157 if (!perfmon)
158 return -EINVAL;
159
160 vc4_perfmon_put(perfmon);
161 return 0;
162}
163
164int vc4_perfmon_get_values_ioctl(struct drm_device *dev, void *data,
165 struct drm_file *file_priv)
166{
167 struct vc4_file *vc4file = file_priv->driver_priv;
168 struct drm_vc4_perfmon_get_values *req = data;
169 struct vc4_perfmon *perfmon;
170 int ret;
171
172 mutex_lock(&vc4file->perfmon.lock);
173 perfmon = idr_find(&vc4file->perfmon.idr, req->id);
174 vc4_perfmon_get(perfmon);
175 mutex_unlock(&vc4file->perfmon.lock);
176
177 if (!perfmon)
178 return -EINVAL;
179
180 if (copy_to_user(u64_to_user_ptr(req->values_ptr), perfmon->counters,
181 perfmon->ncounters * sizeof(u64)))
182 ret = -EFAULT;
183 else
184 ret = 0;
185
186 vc4_perfmon_put(perfmon);
187 return ret;
188}
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index 515f97997624..61ad955645a5 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -85,47 +85,46 @@ static const struct hvs_format {
85 u32 drm; /* DRM_FORMAT_* */ 85 u32 drm; /* DRM_FORMAT_* */
86 u32 hvs; /* HVS_FORMAT_* */ 86 u32 hvs; /* HVS_FORMAT_* */
87 u32 pixel_order; 87 u32 pixel_order;
88 bool has_alpha;
89} hvs_formats[] = { 88} hvs_formats[] = {
90 { 89 {
91 .drm = DRM_FORMAT_XRGB8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888, 90 .drm = DRM_FORMAT_XRGB8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888,
92 .pixel_order = HVS_PIXEL_ORDER_ABGR, .has_alpha = false, 91 .pixel_order = HVS_PIXEL_ORDER_ABGR,
93 }, 92 },
94 { 93 {
95 .drm = DRM_FORMAT_ARGB8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888, 94 .drm = DRM_FORMAT_ARGB8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888,
96 .pixel_order = HVS_PIXEL_ORDER_ABGR, .has_alpha = true, 95 .pixel_order = HVS_PIXEL_ORDER_ABGR,
97 }, 96 },
98 { 97 {
99 .drm = DRM_FORMAT_ABGR8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888, 98 .drm = DRM_FORMAT_ABGR8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888,
100 .pixel_order = HVS_PIXEL_ORDER_ARGB, .has_alpha = true, 99 .pixel_order = HVS_PIXEL_ORDER_ARGB,
101 }, 100 },
102 { 101 {
103 .drm = DRM_FORMAT_XBGR8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888, 102 .drm = DRM_FORMAT_XBGR8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888,
104 .pixel_order = HVS_PIXEL_ORDER_ARGB, .has_alpha = false, 103 .pixel_order = HVS_PIXEL_ORDER_ARGB,
105 }, 104 },
106 { 105 {
107 .drm = DRM_FORMAT_RGB565, .hvs = HVS_PIXEL_FORMAT_RGB565, 106 .drm = DRM_FORMAT_RGB565, .hvs = HVS_PIXEL_FORMAT_RGB565,
108 .pixel_order = HVS_PIXEL_ORDER_XRGB, .has_alpha = false, 107 .pixel_order = HVS_PIXEL_ORDER_XRGB,
109 }, 108 },
110 { 109 {
111 .drm = DRM_FORMAT_BGR565, .hvs = HVS_PIXEL_FORMAT_RGB565, 110 .drm = DRM_FORMAT_BGR565, .hvs = HVS_PIXEL_FORMAT_RGB565,
112 .pixel_order = HVS_PIXEL_ORDER_XBGR, .has_alpha = false, 111 .pixel_order = HVS_PIXEL_ORDER_XBGR,
113 }, 112 },
114 { 113 {
115 .drm = DRM_FORMAT_ARGB1555, .hvs = HVS_PIXEL_FORMAT_RGBA5551, 114 .drm = DRM_FORMAT_ARGB1555, .hvs = HVS_PIXEL_FORMAT_RGBA5551,
116 .pixel_order = HVS_PIXEL_ORDER_ABGR, .has_alpha = true, 115 .pixel_order = HVS_PIXEL_ORDER_ABGR,
117 }, 116 },
118 { 117 {
119 .drm = DRM_FORMAT_XRGB1555, .hvs = HVS_PIXEL_FORMAT_RGBA5551, 118 .drm = DRM_FORMAT_XRGB1555, .hvs = HVS_PIXEL_FORMAT_RGBA5551,
120 .pixel_order = HVS_PIXEL_ORDER_ABGR, .has_alpha = false, 119 .pixel_order = HVS_PIXEL_ORDER_ABGR,
121 }, 120 },
122 { 121 {
123 .drm = DRM_FORMAT_RGB888, .hvs = HVS_PIXEL_FORMAT_RGB888, 122 .drm = DRM_FORMAT_RGB888, .hvs = HVS_PIXEL_FORMAT_RGB888,
124 .pixel_order = HVS_PIXEL_ORDER_XRGB, .has_alpha = false, 123 .pixel_order = HVS_PIXEL_ORDER_XRGB,
125 }, 124 },
126 { 125 {
127 .drm = DRM_FORMAT_BGR888, .hvs = HVS_PIXEL_FORMAT_RGB888, 126 .drm = DRM_FORMAT_BGR888, .hvs = HVS_PIXEL_FORMAT_RGB888,
128 .pixel_order = HVS_PIXEL_ORDER_XBGR, .has_alpha = false, 127 .pixel_order = HVS_PIXEL_ORDER_XBGR,
129 }, 128 },
130 { 129 {
131 .drm = DRM_FORMAT_YUV422, 130 .drm = DRM_FORMAT_YUV422,
@@ -622,7 +621,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
622 /* Position Word 2: Source Image Size, Alpha Mode */ 621 /* Position Word 2: Source Image Size, Alpha Mode */
623 vc4_state->pos2_offset = vc4_state->dlist_count; 622 vc4_state->pos2_offset = vc4_state->dlist_count;
624 vc4_dlist_write(vc4_state, 623 vc4_dlist_write(vc4_state,
625 VC4_SET_FIELD(format->has_alpha ? 624 VC4_SET_FIELD(fb->format->has_alpha ?
626 SCALER_POS2_ALPHA_MODE_PIPELINE : 625 SCALER_POS2_ALPHA_MODE_PIPELINE :
627 SCALER_POS2_ALPHA_MODE_FIXED, 626 SCALER_POS2_ALPHA_MODE_FIXED,
628 SCALER_POS2_ALPHA_MODE) | 627 SCALER_POS2_ALPHA_MODE) |
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index 55677bd50f66..b9749cb24063 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -122,38 +122,9 @@
122#define V3D_VPMBASE 0x00504 122#define V3D_VPMBASE 0x00504
123#define V3D_PCTRC 0x00670 123#define V3D_PCTRC 0x00670
124#define V3D_PCTRE 0x00674 124#define V3D_PCTRE 0x00674
125#define V3D_PCTR0 0x00680 125# define V3D_PCTRE_EN BIT(31)
126#define V3D_PCTRS0 0x00684 126#define V3D_PCTR(x) (0x00680 + ((x) * 8))
127#define V3D_PCTR1 0x00688 127#define V3D_PCTRS(x) (0x00684 + ((x) * 8))
128#define V3D_PCTRS1 0x0068c
129#define V3D_PCTR2 0x00690
130#define V3D_PCTRS2 0x00694
131#define V3D_PCTR3 0x00698
132#define V3D_PCTRS3 0x0069c
133#define V3D_PCTR4 0x006a0
134#define V3D_PCTRS4 0x006a4
135#define V3D_PCTR5 0x006a8
136#define V3D_PCTRS5 0x006ac
137#define V3D_PCTR6 0x006b0
138#define V3D_PCTRS6 0x006b4
139#define V3D_PCTR7 0x006b8
140#define V3D_PCTRS7 0x006bc
141#define V3D_PCTR8 0x006c0
142#define V3D_PCTRS8 0x006c4
143#define V3D_PCTR9 0x006c8
144#define V3D_PCTRS9 0x006cc
145#define V3D_PCTR10 0x006d0
146#define V3D_PCTRS10 0x006d4
147#define V3D_PCTR11 0x006d8
148#define V3D_PCTRS11 0x006dc
149#define V3D_PCTR12 0x006e0
150#define V3D_PCTRS12 0x006e4
151#define V3D_PCTR13 0x006e8
152#define V3D_PCTRS13 0x006ec
153#define V3D_PCTR14 0x006f0
154#define V3D_PCTRS14 0x006f4
155#define V3D_PCTR15 0x006f8
156#define V3D_PCTRS15 0x006fc
157#define V3D_DBGE 0x00f00 128#define V3D_DBGE 0x00f00
158#define V3D_FDBGO 0x00f04 129#define V3D_FDBGO 0x00f04
159#define V3D_FDBGB 0x00f08 130#define V3D_FDBGB 0x00f08
diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c
index 493f392b3a0a..bfc2fa73d2ae 100644
--- a/drivers/gpu/drm/vc4/vc4_v3d.c
+++ b/drivers/gpu/drm/vc4/vc4_v3d.c
@@ -68,38 +68,38 @@ static const struct {
68 REGDEF(V3D_VPMBASE), 68 REGDEF(V3D_VPMBASE),
69 REGDEF(V3D_PCTRC), 69 REGDEF(V3D_PCTRC),
70 REGDEF(V3D_PCTRE), 70 REGDEF(V3D_PCTRE),
71 REGDEF(V3D_PCTR0), 71 REGDEF(V3D_PCTR(0)),
72 REGDEF(V3D_PCTRS0), 72 REGDEF(V3D_PCTRS(0)),
73 REGDEF(V3D_PCTR1), 73 REGDEF(V3D_PCTR(1)),
74 REGDEF(V3D_PCTRS1), 74 REGDEF(V3D_PCTRS(1)),
75 REGDEF(V3D_PCTR2), 75 REGDEF(V3D_PCTR(2)),
76 REGDEF(V3D_PCTRS2), 76 REGDEF(V3D_PCTRS(2)),
77 REGDEF(V3D_PCTR3), 77 REGDEF(V3D_PCTR(3)),
78 REGDEF(V3D_PCTRS3), 78 REGDEF(V3D_PCTRS(3)),
79 REGDEF(V3D_PCTR4), 79 REGDEF(V3D_PCTR(4)),
80 REGDEF(V3D_PCTRS4), 80 REGDEF(V3D_PCTRS(4)),
81 REGDEF(V3D_PCTR5), 81 REGDEF(V3D_PCTR(5)),
82 REGDEF(V3D_PCTRS5), 82 REGDEF(V3D_PCTRS(5)),
83 REGDEF(V3D_PCTR6), 83 REGDEF(V3D_PCTR(6)),
84 REGDEF(V3D_PCTRS6), 84 REGDEF(V3D_PCTRS(6)),
85 REGDEF(V3D_PCTR7), 85 REGDEF(V3D_PCTR(7)),
86 REGDEF(V3D_PCTRS7), 86 REGDEF(V3D_PCTRS(7)),
87 REGDEF(V3D_PCTR8), 87 REGDEF(V3D_PCTR(8)),
88 REGDEF(V3D_PCTRS8), 88 REGDEF(V3D_PCTRS(8)),
89 REGDEF(V3D_PCTR9), 89 REGDEF(V3D_PCTR(9)),
90 REGDEF(V3D_PCTRS9), 90 REGDEF(V3D_PCTRS(9)),
91 REGDEF(V3D_PCTR10), 91 REGDEF(V3D_PCTR(10)),
92 REGDEF(V3D_PCTRS10), 92 REGDEF(V3D_PCTRS(10)),
93 REGDEF(V3D_PCTR11), 93 REGDEF(V3D_PCTR(11)),
94 REGDEF(V3D_PCTRS11), 94 REGDEF(V3D_PCTRS(11)),
95 REGDEF(V3D_PCTR12), 95 REGDEF(V3D_PCTR(12)),
96 REGDEF(V3D_PCTRS12), 96 REGDEF(V3D_PCTRS(12)),
97 REGDEF(V3D_PCTR13), 97 REGDEF(V3D_PCTR(13)),
98 REGDEF(V3D_PCTRS13), 98 REGDEF(V3D_PCTRS(13)),
99 REGDEF(V3D_PCTR14), 99 REGDEF(V3D_PCTR(14)),
100 REGDEF(V3D_PCTRS14), 100 REGDEF(V3D_PCTRS(14)),
101 REGDEF(V3D_PCTR15), 101 REGDEF(V3D_PCTR(15)),
102 REGDEF(V3D_PCTRS15), 102 REGDEF(V3D_PCTRS(15)),
103 REGDEF(V3D_DBGE), 103 REGDEF(V3D_DBGE),
104 REGDEF(V3D_FDBGO), 104 REGDEF(V3D_FDBGO),
105 REGDEF(V3D_FDBGB), 105 REGDEF(V3D_FDBGB),
diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
index 5720a0d4ac0a..355569a9b5cb 100644
--- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c
+++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
@@ -518,6 +518,8 @@ static int virtio_gpu_get_caps_ioctl(struct drm_device *dev,
518 518
519 ret = wait_event_timeout(vgdev->resp_wq, 519 ret = wait_event_timeout(vgdev->resp_wq,
520 atomic_read(&cache_ent->is_valid), 5 * HZ); 520 atomic_read(&cache_ent->is_valid), 5 * HZ);
521 if (!ret)
522 return -EBUSY;
521 523
522 ptr = cache_ent->caps_cache; 524 ptr = cache_ent->caps_cache;
523 525
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index ead61015cd79..1107d6d03506 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -449,10 +449,9 @@ int vmw_du_primary_plane_atomic_check(struct drm_plane *plane,
449 if (state->crtc) 449 if (state->crtc)
450 crtc_state = drm_atomic_get_new_crtc_state(state->state, state->crtc); 450 crtc_state = drm_atomic_get_new_crtc_state(state->state, state->crtc);
451 451
452 if (crtc_state && crtc_state->enable) { 452 if (crtc_state && crtc_state->enable)
453 clip.x2 = crtc_state->adjusted_mode.hdisplay; 453 drm_mode_get_hv_timing(&crtc_state->mode,
454 clip.y2 = crtc_state->adjusted_mode.vdisplay; 454 &clip.x2, &clip.y2);
455 }
456 455
457 ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip, 456 ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
458 DRM_PLANE_HELPER_NO_SCALING, 457 DRM_PLANE_HELPER_NO_SCALING,
diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c
index 68fd2e2dc78a..8e1f34274e24 100644
--- a/drivers/gpu/drm/zte/zx_plane.c
+++ b/drivers/gpu/drm/zte/zx_plane.c
@@ -55,7 +55,7 @@ static int zx_vl_plane_atomic_check(struct drm_plane *plane,
55 struct drm_framebuffer *fb = plane_state->fb; 55 struct drm_framebuffer *fb = plane_state->fb;
56 struct drm_crtc *crtc = plane_state->crtc; 56 struct drm_crtc *crtc = plane_state->crtc;
57 struct drm_crtc_state *crtc_state; 57 struct drm_crtc_state *crtc_state;
58 struct drm_rect clip; 58 struct drm_rect clip = {};
59 int min_scale = FRAC_16_16(1, 8); 59 int min_scale = FRAC_16_16(1, 8);
60 int max_scale = FRAC_16_16(8, 1); 60 int max_scale = FRAC_16_16(8, 1);
61 61
@@ -75,10 +75,9 @@ static int zx_vl_plane_atomic_check(struct drm_plane *plane,
75 if (!plane_state->crtc) 75 if (!plane_state->crtc)
76 return -EINVAL; 76 return -EINVAL;
77 77
78 clip.x1 = 0; 78 if (crtc_state->enable)
79 clip.y1 = 0; 79 drm_mode_get_hv_timing(&crtc_state->mode,
80 clip.x2 = crtc_state->adjusted_mode.hdisplay; 80 &clip.x2, &clip.y2);
81 clip.y2 = crtc_state->adjusted_mode.vdisplay;
82 81
83 return drm_atomic_helper_check_plane_state(plane_state, crtc_state, 82 return drm_atomic_helper_check_plane_state(plane_state, crtc_state,
84 &clip, min_scale, max_scale, 83 &clip, min_scale, max_scale,
@@ -292,7 +291,7 @@ static int zx_gl_plane_atomic_check(struct drm_plane *plane,
292 struct drm_framebuffer *fb = plane_state->fb; 291 struct drm_framebuffer *fb = plane_state->fb;
293 struct drm_crtc *crtc = plane_state->crtc; 292 struct drm_crtc *crtc = plane_state->crtc;
294 struct drm_crtc_state *crtc_state; 293 struct drm_crtc_state *crtc_state;
295 struct drm_rect clip; 294 struct drm_rect clip = {};
296 295
297 if (!crtc || !fb) 296 if (!crtc || !fb)
298 return 0; 297 return 0;
@@ -310,10 +309,9 @@ static int zx_gl_plane_atomic_check(struct drm_plane *plane,
310 if (!plane_state->crtc) 309 if (!plane_state->crtc)
311 return -EINVAL; 310 return -EINVAL;
312 311
313 clip.x1 = 0; 312 if (crtc_state->enable)
314 clip.y1 = 0; 313 drm_mode_get_hv_timing(&crtc_state->mode,
315 clip.x2 = crtc_state->adjusted_mode.hdisplay; 314 &clip.x2, &clip.y2);
316 clip.y2 = crtc_state->adjusted_mode.vdisplay;
317 315
318 return drm_atomic_helper_check_plane_state(plane_state, crtc_state, 316 return drm_atomic_helper_check_plane_state(plane_state, crtc_state,
319 &clip, 317 &clip,
diff --git a/include/drm/bridge/dw_mipi_dsi.h b/include/drm/bridge/dw_mipi_dsi.h
index 9b30fec302c8..d9c6d549f971 100644
--- a/include/drm/bridge/dw_mipi_dsi.h
+++ b/include/drm/bridge/dw_mipi_dsi.h
@@ -10,6 +10,8 @@
10#ifndef __DW_MIPI_DSI__ 10#ifndef __DW_MIPI_DSI__
11#define __DW_MIPI_DSI__ 11#define __DW_MIPI_DSI__
12 12
13struct dw_mipi_dsi;
14
13struct dw_mipi_dsi_phy_ops { 15struct dw_mipi_dsi_phy_ops {
14 int (*init)(void *priv_data); 16 int (*init)(void *priv_data);
15 int (*get_lane_mbps)(void *priv_data, struct drm_display_mode *mode, 17 int (*get_lane_mbps)(void *priv_data, struct drm_display_mode *mode,
@@ -29,11 +31,14 @@ struct dw_mipi_dsi_plat_data {
29 void *priv_data; 31 void *priv_data;
30}; 32};
31 33
32int dw_mipi_dsi_probe(struct platform_device *pdev, 34struct dw_mipi_dsi *dw_mipi_dsi_probe(struct platform_device *pdev,
33 const struct dw_mipi_dsi_plat_data *plat_data); 35 const struct dw_mipi_dsi_plat_data
34void dw_mipi_dsi_remove(struct platform_device *pdev); 36 *plat_data);
35int dw_mipi_dsi_bind(struct platform_device *pdev, struct drm_encoder *encoder, 37void dw_mipi_dsi_remove(struct dw_mipi_dsi *dsi);
36 const struct dw_mipi_dsi_plat_data *plat_data); 38struct dw_mipi_dsi *dw_mipi_dsi_bind(struct platform_device *pdev,
37void dw_mipi_dsi_unbind(struct device *dev); 39 struct drm_encoder *encoder,
40 const struct dw_mipi_dsi_plat_data
41 *plat_data);
42void dw_mipi_dsi_unbind(struct dw_mipi_dsi *dsi);
38 43
39#endif /* __DW_MIPI_DSI__ */ 44#endif /* __DW_MIPI_DSI__ */
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 1c27526c499e..cf13842a6dbd 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -134,6 +134,15 @@ struct drm_crtc_commit {
134 * &drm_pending_vblank_event pointer to clean up private events. 134 * &drm_pending_vblank_event pointer to clean up private events.
135 */ 135 */
136 struct drm_pending_vblank_event *event; 136 struct drm_pending_vblank_event *event;
137
138 /**
139 * @abort_completion:
140 *
141 * A flag that's set after drm_atomic_helper_setup_commit takes a second
142 * reference for the completion of $drm_crtc_state.event. It's used by
143 * the free code to remove the second reference if commit fails.
144 */
145 bool abort_completion;
137}; 146};
138 147
139struct __drm_planes_state { 148struct __drm_planes_state {
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 682d01ba920c..3270fec46979 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -29,6 +29,7 @@
29#include <drm/drm_modes.h> 29#include <drm/drm_modes.h>
30 30
31struct drm_bridge; 31struct drm_bridge;
32struct drm_bridge_timings;
32struct drm_panel; 33struct drm_panel;
33 34
34/** 35/**
@@ -90,7 +91,7 @@ struct drm_bridge_funcs {
90 * 91 *
91 * drm_mode_status Enum 92 * drm_mode_status Enum
92 */ 93 */
93 enum drm_mode_status (*mode_valid)(struct drm_bridge *crtc, 94 enum drm_mode_status (*mode_valid)(struct drm_bridge *bridge,
94 const struct drm_display_mode *mode); 95 const struct drm_display_mode *mode);
95 96
96 /** 97 /**
@@ -223,12 +224,43 @@ struct drm_bridge_funcs {
223}; 224};
224 225
225/** 226/**
227 * struct drm_bridge_timings - timing information for the bridge
228 */
229struct drm_bridge_timings {
230 /**
231 * @sampling_edge:
232 *
233 * Tells whether the bridge samples the digital input signal
234 * from the display engine on the positive or negative edge of the
235 * clock, this should reuse the DRM_BUS_FLAG_PIXDATA_[POS|NEG]EDGE
236 * bitwise flags from the DRM connector (bit 2 and 3 valid).
237 */
238 u32 sampling_edge;
239 /**
240 * @setup_time_ps:
241 *
242 * Defines the time in picoseconds the input data lines must be
243 * stable before the clock edge.
244 */
245 u32 setup_time_ps;
246 /**
247 * @hold_time_ps:
248 *
249 * Defines the time in picoseconds taken for the bridge to sample the
250 * input signal after the clock edge.
251 */
252 u32 hold_time_ps;
253};
254
255/**
226 * struct drm_bridge - central DRM bridge control structure 256 * struct drm_bridge - central DRM bridge control structure
227 * @dev: DRM device this bridge belongs to 257 * @dev: DRM device this bridge belongs to
228 * @encoder: encoder to which this bridge is connected 258 * @encoder: encoder to which this bridge is connected
229 * @next: the next bridge in the encoder chain 259 * @next: the next bridge in the encoder chain
230 * @of_node: device node pointer to the bridge 260 * @of_node: device node pointer to the bridge
231 * @list: to keep track of all added bridges 261 * @list: to keep track of all added bridges
262 * @timings: the timing specification for the bridge, if any (may
263 * be NULL)
232 * @funcs: control functions 264 * @funcs: control functions
233 * @driver_private: pointer to the bridge driver's internal context 265 * @driver_private: pointer to the bridge driver's internal context
234 */ 266 */
@@ -240,6 +272,7 @@ struct drm_bridge {
240 struct device_node *of_node; 272 struct device_node *of_node;
241#endif 273#endif
242 struct list_head list; 274 struct list_head list;
275 const struct drm_bridge_timings *timings;
243 276
244 const struct drm_bridge_funcs *funcs; 277 const struct drm_bridge_funcs *funcs;
245 void *driver_private; 278 void *driver_private;
diff --git a/include/drm/drm_cache.h b/include/drm/drm_cache.h
index beab0f0d0cfb..bfe1639df02d 100644
--- a/include/drm/drm_cache.h
+++ b/include/drm/drm_cache.h
@@ -38,6 +38,8 @@
38void drm_clflush_pages(struct page *pages[], unsigned long num_pages); 38void drm_clflush_pages(struct page *pages[], unsigned long num_pages);
39void drm_clflush_sg(struct sg_table *st); 39void drm_clflush_sg(struct sg_table *st);
40void drm_clflush_virt_range(void *addr, unsigned long length); 40void drm_clflush_virt_range(void *addr, unsigned long length);
41u64 drm_get_max_iomem(void);
42
41 43
42static inline bool drm_arch_can_wc_memory(void) 44static inline bool drm_arch_can_wc_memory(void)
43{ 45{
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index da58a428c8d7..768d9eda06cb 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -75,6 +75,7 @@
75#define DP_MAX_DOWNSPREAD 0x003 75#define DP_MAX_DOWNSPREAD 0x003
76# define DP_MAX_DOWNSPREAD_0_5 (1 << 0) 76# define DP_MAX_DOWNSPREAD_0_5 (1 << 0)
77# define DP_NO_AUX_HANDSHAKE_LINK_TRAINING (1 << 6) 77# define DP_NO_AUX_HANDSHAKE_LINK_TRAINING (1 << 6)
78# define DP_TPS4_SUPPORTED (1 << 7)
78 79
79#define DP_NORP 0x004 80#define DP_NORP 0x004
80 81
@@ -334,6 +335,7 @@
334# define DP_LINK_BW_1_62 0x06 335# define DP_LINK_BW_1_62 0x06
335# define DP_LINK_BW_2_7 0x0a 336# define DP_LINK_BW_2_7 0x0a
336# define DP_LINK_BW_5_4 0x14 /* 1.2 */ 337# define DP_LINK_BW_5_4 0x14 /* 1.2 */
338# define DP_LINK_BW_8_1 0x1e /* 1.4 */
337 339
338#define DP_LANE_COUNT_SET 0x101 340#define DP_LANE_COUNT_SET 0x101
339# define DP_LANE_COUNT_MASK 0x0f 341# define DP_LANE_COUNT_MASK 0x0f
@@ -344,7 +346,9 @@
344# define DP_TRAINING_PATTERN_1 1 346# define DP_TRAINING_PATTERN_1 1
345# define DP_TRAINING_PATTERN_2 2 347# define DP_TRAINING_PATTERN_2 2
346# define DP_TRAINING_PATTERN_3 3 /* 1.2 */ 348# define DP_TRAINING_PATTERN_3 3 /* 1.2 */
349# define DP_TRAINING_PATTERN_4 7 /* 1.4 */
347# define DP_TRAINING_PATTERN_MASK 0x3 350# define DP_TRAINING_PATTERN_MASK 0x3
351# define DP_TRAINING_PATTERN_MASK_1_4 0xf
348 352
349/* DPCD 1.1 only. For DPCD >= 1.2 see per-lane DP_LINK_QUAL_LANEn_SET */ 353/* DPCD 1.1 only. For DPCD >= 1.2 see per-lane DP_LINK_QUAL_LANEn_SET */
350# define DP_LINK_QUAL_PATTERN_11_DISABLE (0 << 2) 354# define DP_LINK_QUAL_PATTERN_11_DISABLE (0 << 2)
@@ -971,6 +975,20 @@ drm_dp_tps3_supported(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
971} 975}
972 976
973static inline bool 977static inline bool
978drm_dp_tps4_supported(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
979{
980 return dpcd[DP_DPCD_REV] >= 0x14 &&
981 dpcd[DP_MAX_DOWNSPREAD] & DP_TPS4_SUPPORTED;
982}
983
984static inline u8
985drm_dp_training_pattern_mask(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
986{
987 return (dpcd[DP_DPCD_REV] >= 0x14) ? DP_TRAINING_PATTERN_MASK_1_4 :
988 DP_TRAINING_PATTERN_MASK;
989}
990
991static inline bool
974drm_dp_is_branch(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) 992drm_dp_is_branch(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
975{ 993{
976 return dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT; 994 return dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT;
diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h
index 6942e84b6edd..3e86408dac9f 100644
--- a/include/drm/drm_fourcc.h
+++ b/include/drm/drm_fourcc.h
@@ -38,6 +38,7 @@ struct drm_mode_fb_cmd2;
38 * @cpp: Number of bytes per pixel (per plane) 38 * @cpp: Number of bytes per pixel (per plane)
39 * @hsub: Horizontal chroma subsampling factor 39 * @hsub: Horizontal chroma subsampling factor
40 * @vsub: Vertical chroma subsampling factor 40 * @vsub: Vertical chroma subsampling factor
41 * @has_alpha: Does the format embeds an alpha component?
41 */ 42 */
42struct drm_format_info { 43struct drm_format_info {
43 u32 format; 44 u32 format;
@@ -46,6 +47,7 @@ struct drm_format_info {
46 u8 cpp[3]; 47 u8 cpp[3];
47 u8 hsub; 48 u8 hsub;
48 u8 vsub; 49 u8 vsub;
50 bool has_alpha;
49}; 51};
50 52
51/** 53/**
diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
index 2cb6f02df64a..7569f22ffef6 100644
--- a/include/drm/drm_mode_config.h
+++ b/include/drm/drm_mode_config.h
@@ -36,6 +36,7 @@ struct drm_device;
36struct drm_atomic_state; 36struct drm_atomic_state;
37struct drm_mode_fb_cmd2; 37struct drm_mode_fb_cmd2;
38struct drm_format_info; 38struct drm_format_info;
39struct drm_display_mode;
39 40
40/** 41/**
41 * struct drm_mode_config_funcs - basic driver provided mode setting functions 42 * struct drm_mode_config_funcs - basic driver provided mode setting functions
@@ -102,6 +103,17 @@ struct drm_mode_config_funcs {
102 void (*output_poll_changed)(struct drm_device *dev); 103 void (*output_poll_changed)(struct drm_device *dev);
103 104
104 /** 105 /**
106 * @mode_valid:
107 *
108 * Device specific validation of display modes. Can be used to reject
109 * modes that can never be supported. Only device wide constraints can
110 * be checked here. crtc/encoder/bridge/connector specific constraints
111 * should be checked in the .mode_valid() hook for each specific object.
112 */
113 enum drm_mode_status (*mode_valid)(struct drm_device *dev,
114 const struct drm_display_mode *mode);
115
116 /**
105 * @atomic_check: 117 * @atomic_check:
106 * 118 *
107 * This is the only hook to validate an atomic modeset update. This 119 * This is the only hook to validate an atomic modeset update. This
diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
index 9f3421c8efcd..0d310beae6af 100644
--- a/include/drm/drm_modes.h
+++ b/include/drm/drm_modes.h
@@ -131,9 +131,6 @@ enum drm_mode_status {
131 MODE_ERROR = -1 131 MODE_ERROR = -1
132}; 132};
133 133
134#define DRM_MODE_TYPE_CLOCK_CRTC_C (DRM_MODE_TYPE_CLOCK_C | \
135 DRM_MODE_TYPE_CRTC_C)
136
137#define DRM_MODE(nm, t, c, hd, hss, hse, ht, hsk, vd, vss, vse, vt, vs, f) \ 134#define DRM_MODE(nm, t, c, hd, hss, hse, ht, hsk, vd, vss, vse, vt, vs, f) \
138 .name = nm, .status = 0, .type = (t), .clock = (c), \ 135 .name = nm, .status = 0, .type = (t), .clock = (c), \
139 .hdisplay = (hd), .hsync_start = (hss), .hsync_end = (hse), \ 136 .hdisplay = (hd), .hsync_start = (hss), .hsync_end = (hse), \
@@ -245,26 +242,25 @@ struct drm_display_mode {
245 * A bitmask of flags, mostly about the source of a mode. Possible flags 242 * A bitmask of flags, mostly about the source of a mode. Possible flags
246 * are: 243 * are:
247 * 244 *
248 * - DRM_MODE_TYPE_BUILTIN: Meant for hard-coded modes, effectively
249 * unused.
250 * - DRM_MODE_TYPE_PREFERRED: Preferred mode, usually the native 245 * - DRM_MODE_TYPE_PREFERRED: Preferred mode, usually the native
251 * resolution of an LCD panel. There should only be one preferred 246 * resolution of an LCD panel. There should only be one preferred
252 * mode per connector at any given time. 247 * mode per connector at any given time.
253 * - DRM_MODE_TYPE_DRIVER: Mode created by the driver, which is all of 248 * - DRM_MODE_TYPE_DRIVER: Mode created by the driver, which is all of
254 * them really. Drivers must set this bit for all modes they create 249 * them really. Drivers must set this bit for all modes they create
255 * and expose to userspace. 250 * and expose to userspace.
251 * - DRM_MODE_TYPE_USERDEF: Mode defined via kernel command line
256 * 252 *
257 * Plus a big list of flags which shouldn't be used at all, but are 253 * Plus a big list of flags which shouldn't be used at all, but are
258 * still around since these flags are also used in the userspace ABI: 254 * still around since these flags are also used in the userspace ABI.
255 * We no longer accept modes with these types though:
259 * 256 *
257 * - DRM_MODE_TYPE_BUILTIN: Meant for hard-coded modes, unused.
258 * Use DRM_MODE_TYPE_DRIVER instead.
260 * - DRM_MODE_TYPE_DEFAULT: Again a leftover, use 259 * - DRM_MODE_TYPE_DEFAULT: Again a leftover, use
261 * DRM_MODE_TYPE_PREFERRED instead. 260 * DRM_MODE_TYPE_PREFERRED instead.
262 * - DRM_MODE_TYPE_CLOCK_C and DRM_MODE_TYPE_CRTC_C: Define leftovers 261 * - DRM_MODE_TYPE_CLOCK_C and DRM_MODE_TYPE_CRTC_C: Define leftovers
263 * which are stuck around for hysterical raisins only. No one has an 262 * which are stuck around for hysterical raisins only. No one has an
264 * idea what they were meant for. Don't use. 263 * idea what they were meant for. Don't use.
265 * - DRM_MODE_TYPE_USERDEF: Mode defined by userspace, again a vestige
266 * from older kms designs where userspace had to first add a custom
267 * mode to the kernel's mode list before it could use it. Don't use.
268 */ 264 */
269 unsigned int type; 265 unsigned int type;
270 266
@@ -299,8 +295,8 @@ struct drm_display_mode {
299 * - DRM_MODE_FLAG_PCSYNC: composite sync is active high. 295 * - DRM_MODE_FLAG_PCSYNC: composite sync is active high.
300 * - DRM_MODE_FLAG_NCSYNC: composite sync is active low. 296 * - DRM_MODE_FLAG_NCSYNC: composite sync is active low.
301 * - DRM_MODE_FLAG_HSKEW: hskew provided (not used?). 297 * - DRM_MODE_FLAG_HSKEW: hskew provided (not used?).
302 * - DRM_MODE_FLAG_BCAST: not used? 298 * - DRM_MODE_FLAG_BCAST: <deprecated>
303 * - DRM_MODE_FLAG_PIXMUX: not used? 299 * - DRM_MODE_FLAG_PIXMUX: <deprecated>
304 * - DRM_MODE_FLAG_DBLCLK: double-clocked mode. 300 * - DRM_MODE_FLAG_DBLCLK: double-clocked mode.
305 * - DRM_MODE_FLAG_CLKDIV2: half-clocked mode. 301 * - DRM_MODE_FLAG_CLKDIV2: half-clocked mode.
306 * 302 *
@@ -448,7 +444,8 @@ struct drm_display_mode *drm_mode_create(struct drm_device *dev);
448void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode); 444void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode);
449void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out, 445void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out,
450 const struct drm_display_mode *in); 446 const struct drm_display_mode *in);
451int drm_mode_convert_umode(struct drm_display_mode *out, 447int drm_mode_convert_umode(struct drm_device *dev,
448 struct drm_display_mode *out,
452 const struct drm_mode_modeinfo *in); 449 const struct drm_mode_modeinfo *in);
453void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode); 450void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode);
454void drm_mode_debug_printmodeline(const struct drm_display_mode *mode); 451void drm_mode_debug_printmodeline(const struct drm_display_mode *mode);
@@ -501,7 +498,8 @@ bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1,
501 const struct drm_display_mode *mode2); 498 const struct drm_display_mode *mode2);
502 499
503/* for use by the crtc helper probe functions */ 500/* for use by the crtc helper probe functions */
504enum drm_mode_status drm_mode_validate_basic(const struct drm_display_mode *mode); 501enum drm_mode_status drm_mode_validate_driver(struct drm_device *dev,
502 const struct drm_display_mode *mode);
505enum drm_mode_status drm_mode_validate_size(const struct drm_display_mode *mode, 503enum drm_mode_status drm_mode_validate_size(const struct drm_display_mode *mode,
506 int maxX, int maxY); 504 int maxX, int maxY);
507enum drm_mode_status 505enum drm_mode_status
diff --git a/include/drm/drm_prime.h b/include/drm/drm_prime.h
index 9cd9e36f77b5..4d5f5d6cf6a6 100644
--- a/include/drm/drm_prime.h
+++ b/include/drm/drm_prime.h
@@ -54,6 +54,9 @@ struct device;
54 54
55struct dma_buf_export_info; 55struct dma_buf_export_info;
56struct dma_buf; 56struct dma_buf;
57struct dma_buf_attachment;
58
59enum dma_data_direction;
57 60
58struct drm_device; 61struct drm_device;
59struct drm_gem_object; 62struct drm_gem_object;
@@ -79,6 +82,25 @@ int drm_gem_prime_fd_to_handle(struct drm_device *dev,
79struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev, 82struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev,
80 struct dma_buf_export_info *exp_info); 83 struct dma_buf_export_info *exp_info);
81void drm_gem_dmabuf_release(struct dma_buf *dma_buf); 84void drm_gem_dmabuf_release(struct dma_buf *dma_buf);
85int drm_gem_map_attach(struct dma_buf *dma_buf, struct device *target_dev,
86 struct dma_buf_attachment *attach);
87void drm_gem_map_detach(struct dma_buf *dma_buf,
88 struct dma_buf_attachment *attach);
89struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach,
90 enum dma_data_direction dir);
91void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
92 struct sg_table *sgt,
93 enum dma_data_direction dir);
94void *drm_gem_dmabuf_vmap(struct dma_buf *dma_buf);
95void drm_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr);
96void *drm_gem_dmabuf_kmap_atomic(struct dma_buf *dma_buf,
97 unsigned long page_num);
98void drm_gem_dmabuf_kunmap_atomic(struct dma_buf *dma_buf,
99 unsigned long page_num, void *addr);
100void *drm_gem_dmabuf_kmap(struct dma_buf *dma_buf, unsigned long page_num);
101void drm_gem_dmabuf_kunmap(struct dma_buf *dma_buf, unsigned long page_num,
102 void *addr);
103int drm_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma);
82 104
83int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages, 105int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages,
84 dma_addr_t *addrs, int max_pages); 106 dma_addr_t *addrs, int max_pages);
diff --git a/include/drm/tinydrm/ili9341.h b/include/drm/tinydrm/ili9341.h
deleted file mode 100644
index 807a09f43cad..000000000000
--- a/include/drm/tinydrm/ili9341.h
+++ /dev/null
@@ -1,54 +0,0 @@
1/*
2 * ILI9341 LCD controller
3 *
4 * Copyright 2016 Noralf Trønnes
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#ifndef __LINUX_ILI9341_H
13#define __LINUX_ILI9341_H
14
15#define ILI9341_FRMCTR1 0xb1
16#define ILI9341_FRMCTR2 0xb2
17#define ILI9341_FRMCTR3 0xb3
18#define ILI9341_INVTR 0xb4
19#define ILI9341_PRCTR 0xb5
20#define ILI9341_DISCTRL 0xb6
21#define ILI9341_ETMOD 0xb7
22
23#define ILI9341_PWCTRL1 0xc0
24#define ILI9341_PWCTRL2 0xc1
25#define ILI9341_VMCTRL1 0xc5
26#define ILI9341_VMCTRL2 0xc7
27#define ILI9341_PWCTRLA 0xcb
28#define ILI9341_PWCTRLB 0xcf
29
30#define ILI9341_RDID1 0xda
31#define ILI9341_RDID2 0xdb
32#define ILI9341_RDID3 0xdc
33#define ILI9341_RDID4 0xd3
34
35#define ILI9341_PGAMCTRL 0xe0
36#define ILI9341_NGAMCTRL 0xe1
37#define ILI9341_DGAMCTRL1 0xe2
38#define ILI9341_DGAMCTRL2 0xe3
39#define ILI9341_DTCTRLA 0xe8
40#define ILI9341_DTCTRLB 0xea
41#define ILI9341_PWRSEQ 0xed
42
43#define ILI9341_EN3GAM 0xf2
44#define ILI9341_IFCTRL 0xf6
45#define ILI9341_PUMPCTRL 0xf7
46
47#define ILI9341_MADCTL_MH BIT(2)
48#define ILI9341_MADCTL_BGR BIT(3)
49#define ILI9341_MADCTL_ML BIT(4)
50#define ILI9341_MADCTL_MV BIT(5)
51#define ILI9341_MADCTL_MX BIT(6)
52#define ILI9341_MADCTL_MY BIT(7)
53
54#endif /* __LINUX_ILI9341_H */
diff --git a/include/drm/tinydrm/mipi-dbi.h b/include/drm/tinydrm/mipi-dbi.h
index 5d0e82b36eaf..44e824af2ef6 100644
--- a/include/drm/tinydrm/mipi-dbi.h
+++ b/include/drm/tinydrm/mipi-dbi.h
@@ -67,11 +67,12 @@ int mipi_dbi_init(struct device *dev, struct mipi_dbi *mipi,
67 const struct drm_simple_display_pipe_funcs *pipe_funcs, 67 const struct drm_simple_display_pipe_funcs *pipe_funcs,
68 struct drm_driver *driver, 68 struct drm_driver *driver,
69 const struct drm_display_mode *mode, unsigned int rotation); 69 const struct drm_display_mode *mode, unsigned int rotation);
70void mipi_dbi_pipe_enable(struct drm_simple_display_pipe *pipe, 70void mipi_dbi_enable_flush(struct mipi_dbi *mipi);
71 struct drm_crtc_state *crtc_state);
72void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe); 71void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe);
73void mipi_dbi_hw_reset(struct mipi_dbi *mipi); 72void mipi_dbi_hw_reset(struct mipi_dbi *mipi);
74bool mipi_dbi_display_is_on(struct mipi_dbi *mipi); 73bool mipi_dbi_display_is_on(struct mipi_dbi *mipi);
74int mipi_dbi_poweron_reset(struct mipi_dbi *mipi);
75int mipi_dbi_poweron_conditional_reset(struct mipi_dbi *mipi);
75u32 mipi_dbi_spi_cmd_max_speed(struct spi_device *spi, size_t len); 76u32 mipi_dbi_spi_cmd_max_speed(struct spi_device *spi, size_t len);
76 77
77int mipi_dbi_command_read(struct mipi_dbi *mipi, u8 cmd, u8 *val); 78int mipi_dbi_command_read(struct mipi_dbi *mipi, u8 cmd, u8 *val);
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index 5597a87154e5..eb9b68c7c218 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -38,14 +38,18 @@ extern "C" {
38#define DRM_DISPLAY_MODE_LEN 32 38#define DRM_DISPLAY_MODE_LEN 32
39#define DRM_PROP_NAME_LEN 32 39#define DRM_PROP_NAME_LEN 32
40 40
41#define DRM_MODE_TYPE_BUILTIN (1<<0) 41#define DRM_MODE_TYPE_BUILTIN (1<<0) /* deprecated */
42#define DRM_MODE_TYPE_CLOCK_C ((1<<1) | DRM_MODE_TYPE_BUILTIN) 42#define DRM_MODE_TYPE_CLOCK_C ((1<<1) | DRM_MODE_TYPE_BUILTIN) /* deprecated */
43#define DRM_MODE_TYPE_CRTC_C ((1<<2) | DRM_MODE_TYPE_BUILTIN) 43#define DRM_MODE_TYPE_CRTC_C ((1<<2) | DRM_MODE_TYPE_BUILTIN) /* deprecated */
44#define DRM_MODE_TYPE_PREFERRED (1<<3) 44#define DRM_MODE_TYPE_PREFERRED (1<<3)
45#define DRM_MODE_TYPE_DEFAULT (1<<4) 45#define DRM_MODE_TYPE_DEFAULT (1<<4) /* deprecated */
46#define DRM_MODE_TYPE_USERDEF (1<<5) 46#define DRM_MODE_TYPE_USERDEF (1<<5)
47#define DRM_MODE_TYPE_DRIVER (1<<6) 47#define DRM_MODE_TYPE_DRIVER (1<<6)
48 48
49#define DRM_MODE_TYPE_ALL (DRM_MODE_TYPE_PREFERRED | \
50 DRM_MODE_TYPE_USERDEF | \
51 DRM_MODE_TYPE_DRIVER)
52
49/* Video mode flags */ 53/* Video mode flags */
50/* bit compatible with the xrandr RR_ definitions (bits 0-13) 54/* bit compatible with the xrandr RR_ definitions (bits 0-13)
51 * 55 *
@@ -66,8 +70,8 @@ extern "C" {
66#define DRM_MODE_FLAG_PCSYNC (1<<7) 70#define DRM_MODE_FLAG_PCSYNC (1<<7)
67#define DRM_MODE_FLAG_NCSYNC (1<<8) 71#define DRM_MODE_FLAG_NCSYNC (1<<8)
68#define DRM_MODE_FLAG_HSKEW (1<<9) /* hskew provided */ 72#define DRM_MODE_FLAG_HSKEW (1<<9) /* hskew provided */
69#define DRM_MODE_FLAG_BCAST (1<<10) 73#define DRM_MODE_FLAG_BCAST (1<<10) /* deprecated */
70#define DRM_MODE_FLAG_PIXMUX (1<<11) 74#define DRM_MODE_FLAG_PIXMUX (1<<11) /* deprecated */
71#define DRM_MODE_FLAG_DBLCLK (1<<12) 75#define DRM_MODE_FLAG_DBLCLK (1<<12)
72#define DRM_MODE_FLAG_CLKDIV2 (1<<13) 76#define DRM_MODE_FLAG_CLKDIV2 (1<<13)
73 /* 77 /*
@@ -99,6 +103,20 @@ extern "C" {
99#define DRM_MODE_FLAG_PIC_AR_16_9 \ 103#define DRM_MODE_FLAG_PIC_AR_16_9 \
100 (DRM_MODE_PICTURE_ASPECT_16_9<<19) 104 (DRM_MODE_PICTURE_ASPECT_16_9<<19)
101 105
106#define DRM_MODE_FLAG_ALL (DRM_MODE_FLAG_PHSYNC | \
107 DRM_MODE_FLAG_NHSYNC | \
108 DRM_MODE_FLAG_PVSYNC | \
109 DRM_MODE_FLAG_NVSYNC | \
110 DRM_MODE_FLAG_INTERLACE | \
111 DRM_MODE_FLAG_DBLSCAN | \
112 DRM_MODE_FLAG_CSYNC | \
113 DRM_MODE_FLAG_PCSYNC | \
114 DRM_MODE_FLAG_NCSYNC | \
115 DRM_MODE_FLAG_HSKEW | \
116 DRM_MODE_FLAG_DBLCLK | \
117 DRM_MODE_FLAG_CLKDIV2 | \
118 DRM_MODE_FLAG_3D_MASK)
119
102/* DPMS flags */ 120/* DPMS flags */
103/* bit compatible with the xorg definitions. */ 121/* bit compatible with the xorg definitions. */
104#define DRM_MODE_DPMS_ON 0 122#define DRM_MODE_DPMS_ON 0
diff --git a/include/uapi/drm/vc4_drm.h b/include/uapi/drm/vc4_drm.h
index 52263b575bdc..b95a0e11cb07 100644
--- a/include/uapi/drm/vc4_drm.h
+++ b/include/uapi/drm/vc4_drm.h
@@ -42,6 +42,9 @@ extern "C" {
42#define DRM_VC4_GET_TILING 0x09 42#define DRM_VC4_GET_TILING 0x09
43#define DRM_VC4_LABEL_BO 0x0a 43#define DRM_VC4_LABEL_BO 0x0a
44#define DRM_VC4_GEM_MADVISE 0x0b 44#define DRM_VC4_GEM_MADVISE 0x0b
45#define DRM_VC4_PERFMON_CREATE 0x0c
46#define DRM_VC4_PERFMON_DESTROY 0x0d
47#define DRM_VC4_PERFMON_GET_VALUES 0x0e
45 48
46#define DRM_IOCTL_VC4_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_SUBMIT_CL, struct drm_vc4_submit_cl) 49#define DRM_IOCTL_VC4_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_SUBMIT_CL, struct drm_vc4_submit_cl)
47#define DRM_IOCTL_VC4_WAIT_SEQNO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_WAIT_SEQNO, struct drm_vc4_wait_seqno) 50#define DRM_IOCTL_VC4_WAIT_SEQNO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_WAIT_SEQNO, struct drm_vc4_wait_seqno)
@@ -55,6 +58,9 @@ extern "C" {
55#define DRM_IOCTL_VC4_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_TILING, struct drm_vc4_get_tiling) 58#define DRM_IOCTL_VC4_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_TILING, struct drm_vc4_get_tiling)
56#define DRM_IOCTL_VC4_LABEL_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_LABEL_BO, struct drm_vc4_label_bo) 59#define DRM_IOCTL_VC4_LABEL_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_LABEL_BO, struct drm_vc4_label_bo)
57#define DRM_IOCTL_VC4_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GEM_MADVISE, struct drm_vc4_gem_madvise) 60#define DRM_IOCTL_VC4_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GEM_MADVISE, struct drm_vc4_gem_madvise)
61#define DRM_IOCTL_VC4_PERFMON_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_PERFMON_CREATE, struct drm_vc4_perfmon_create)
62#define DRM_IOCTL_VC4_PERFMON_DESTROY DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_PERFMON_DESTROY, struct drm_vc4_perfmon_destroy)
63#define DRM_IOCTL_VC4_PERFMON_GET_VALUES DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_PERFMON_GET_VALUES, struct drm_vc4_perfmon_get_values)
58 64
59struct drm_vc4_submit_rcl_surface { 65struct drm_vc4_submit_rcl_surface {
60 __u32 hindex; /* Handle index, or ~0 if not present. */ 66 __u32 hindex; /* Handle index, or ~0 if not present. */
@@ -173,6 +179,15 @@ struct drm_vc4_submit_cl {
173 * wait ioctl). 179 * wait ioctl).
174 */ 180 */
175 __u64 seqno; 181 __u64 seqno;
182
183 /* ID of the perfmon to attach to this job. 0 means no perfmon. */
184 __u32 perfmonid;
185
186 /* Unused field to align this struct on 64 bits. Must be set to 0.
187 * If one ever needs to add an u32 field to this struct, this field
188 * can be used.
189 */
190 __u32 pad2;
176}; 191};
177 192
178/** 193/**
@@ -308,6 +323,7 @@ struct drm_vc4_get_hang_state {
308#define DRM_VC4_PARAM_SUPPORTS_THREADED_FS 5 323#define DRM_VC4_PARAM_SUPPORTS_THREADED_FS 5
309#define DRM_VC4_PARAM_SUPPORTS_FIXED_RCL_ORDER 6 324#define DRM_VC4_PARAM_SUPPORTS_FIXED_RCL_ORDER 6
310#define DRM_VC4_PARAM_SUPPORTS_MADVISE 7 325#define DRM_VC4_PARAM_SUPPORTS_MADVISE 7
326#define DRM_VC4_PARAM_SUPPORTS_PERFMON 8
311 327
312struct drm_vc4_get_param { 328struct drm_vc4_get_param {
313 __u32 param; 329 __u32 param;
@@ -352,6 +368,66 @@ struct drm_vc4_gem_madvise {
352 __u32 pad; 368 __u32 pad;
353}; 369};
354 370
371enum {
372 VC4_PERFCNT_FEP_VALID_PRIMS_NO_RENDER,
373 VC4_PERFCNT_FEP_VALID_PRIMS_RENDER,
374 VC4_PERFCNT_FEP_CLIPPED_QUADS,
375 VC4_PERFCNT_FEP_VALID_QUADS,
376 VC4_PERFCNT_TLB_QUADS_NOT_PASSING_STENCIL,
377 VC4_PERFCNT_TLB_QUADS_NOT_PASSING_Z_AND_STENCIL,
378 VC4_PERFCNT_TLB_QUADS_PASSING_Z_AND_STENCIL,
379 VC4_PERFCNT_TLB_QUADS_ZERO_COVERAGE,
380 VC4_PERFCNT_TLB_QUADS_NON_ZERO_COVERAGE,
381 VC4_PERFCNT_TLB_QUADS_WRITTEN_TO_COLOR_BUF,
382 VC4_PERFCNT_PLB_PRIMS_OUTSIDE_VIEWPORT,
383 VC4_PERFCNT_PLB_PRIMS_NEED_CLIPPING,
384 VC4_PERFCNT_PSE_PRIMS_REVERSED,
385 VC4_PERFCNT_QPU_TOTAL_IDLE_CYCLES,
386 VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_VERTEX_COORD_SHADING,
387 VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_FRAGMENT_SHADING,
388 VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_EXEC_VALID_INST,
389 VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_WAITING_TMUS,
390 VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_WAITING_SCOREBOARD,
391 VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_WAITING_VARYINGS,
392 VC4_PERFCNT_QPU_TOTAL_INST_CACHE_HIT,
393 VC4_PERFCNT_QPU_TOTAL_INST_CACHE_MISS,
394 VC4_PERFCNT_QPU_TOTAL_UNIFORM_CACHE_HIT,
395 VC4_PERFCNT_QPU_TOTAL_UNIFORM_CACHE_MISS,
396 VC4_PERFCNT_TMU_TOTAL_TEXT_QUADS_PROCESSED,
397 VC4_PERFCNT_TMU_TOTAL_TEXT_CACHE_MISS,
398 VC4_PERFCNT_VPM_TOTAL_CLK_CYCLES_VDW_STALLED,
399 VC4_PERFCNT_VPM_TOTAL_CLK_CYCLES_VCD_STALLED,
400 VC4_PERFCNT_L2C_TOTAL_L2_CACHE_HIT,
401 VC4_PERFCNT_L2C_TOTAL_L2_CACHE_MISS,
402 VC4_PERFCNT_NUM_EVENTS,
403};
404
405#define DRM_VC4_MAX_PERF_COUNTERS 16
406
407struct drm_vc4_perfmon_create {
408 __u32 id;
409 __u32 ncounters;
410 __u8 events[DRM_VC4_MAX_PERF_COUNTERS];
411};
412
413struct drm_vc4_perfmon_destroy {
414 __u32 id;
415};
416
417/*
418 * Returns the values of the performance counters tracked by this
419 * perfmon (as an array of ncounters u64 values).
420 *
421 * No implicit synchronization is performed, so the user has to
422 * guarantee that any jobs using this perfmon have already been
423 * completed (probably by blocking on the seqno returned by the
424 * last exec that used the perfmon).
425 */
426struct drm_vc4_perfmon_get_values {
427 __u32 id;
428 __u64 values_ptr;
429};
430
355#if defined(__cplusplus) 431#if defined(__cplusplus)
356} 432}
357#endif 433#endif