[PATCH AUTOSEL 4.9 02/16] drm/msm: Set dma maximum segment size for mdss

2020-02-22 Thread Sasha Levin
From: Sean Paul 

[ Upstream commit db735fc4036bbe1fbe606819b5f0ff26cc76cdff ]

Turning on CONFIG_DMA_API_DEBUG_SG results in the following error:

[   12.078665] msm ae0.mdss: DMA-API: mapping sg segment longer than device 
claims to support [len=3526656] [max=65536]
[   12.089870] WARNING: CPU: 6 PID: 334 at 
/mnt/host/source/src/third_party/kernel/v4.19/kernel/dma/debug.c:1301 
debug_dma_map_sg+0x1dc/0x318
[   12.102655] Modules linked in: joydev
[   12.106442] CPU: 6 PID: 334 Comm: frecon Not tainted 4.19.0 #2
[   12.112450] Hardware name: Google Cheza (rev3+) (DT)
[   12.117566] pstate: 6049 (nZCv daif +PAN -UAO)
[   12.122506] pc : debug_dma_map_sg+0x1dc/0x318
[   12.126995] lr : debug_dma_map_sg+0x1dc/0x318
[   12.131487] sp : ff800cc3ba80
[   12.134913] x29: ff800cc3ba80 x28: 
[   12.140395] x27: 0004 x26: 0004
[   12.145868] x25: ff8008e55b18 x24: 
[   12.151337] x23:  x22: ff800921c000
[   12.156809] x21: ffc0fa75b080 x20: ffc0f7195090
[   12.162280] x19: ffc0f1c53280 x18: 
[   12.167749] x17:  x16: 
[   12.173218] x15:  x14: 0720072007200720
[   12.178689] x13: 0720072007200720 x12: 0720072007200720
[   12.184161] x11: 0720072007200720 x10: 0720072007200720
[   12.189641] x9 : ffc0f1fc6b60 x8 : 
[   12.195110] x7 : ff8008132ce0 x6 : 
[   12.200585] x5 :  x4 : ff8008134734
[   12.206058] x3 : ff800cc3b830 x2 : ffc0f1fc6240
[   12.211532] x1 : 25045a74f48a7400 x0 : 25045a74f48a7400
[   12.217006] Call trace:
[   12.219535]  debug_dma_map_sg+0x1dc/0x318
[   12.223671]  get_pages+0x19c/0x20c
[   12.227177]  msm_gem_fault+0x64/0xfc
[   12.230874]  __do_fault+0x3c/0x140
[   12.234383]  __handle_mm_fault+0x70c/0xdb8
[   12.238603]  handle_mm_fault+0xac/0xc4
[   12.242473]  do_page_fault+0x1bc/0x3d4
[   12.246342]  do_translation_fault+0x54/0x88
[   12.250652]  do_mem_abort+0x60/0xf0
[   12.254250]  el0_da+0x20/0x24
[   12.257317] irq event stamp: 67260
[   12.260828] hardirqs last  enabled at (67259): [] 
console_unlock+0x214/0x608
[   12.269693] hardirqs last disabled at (67260): [] 
do_debug_exception+0x5c/0x178
[   12.278820] softirqs last  enabled at (67256): [] 
__do_softirq+0x4d4/0x520
[   12.287510] softirqs last disabled at (67249): [] 
irq_exit+0xa8/0x100
[   12.295742] ---[ end trace e63cfc40c313ffab ]---

The root of the problem is that the default segment size for sgt is
(UINT_MAX & PAGE_MASK), and the default segment size for device dma is
64K. As such, if you compare the 2, you would deduce that the sg segment
will overflow the device's capacity. In reality, the hardware can
accommodate the larger sg segments, it's just not initializing its max
segment properly. This patch initializes the max segment size for the
mdss device, which gets rid of that pesky warning.

Reported-by: Stephen Boyd 
Tested-by: Stephen Boyd 
Tested-by: Sai Prakash Ranjan 
Reviewed-by: Rob Clark 
Signed-off-by: Sean Paul 
Signed-off-by: Douglas Anderson 
Link: 
https://patchwork.freedesktop.org/patch/msgid/2020012813.REPOST.1.I92c66a35fb13f368095b05287bdabdbe88ca6922@changeid
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/msm/msm_drv.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 6abf315fd6da1..ce32f41fc28aa 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -396,6 +396,14 @@ static int msm_drm_init(struct device *dev, struct 
drm_driver *drv)
if (ret)
goto fail;
 
+   if (!dev->dma_parms) {
+   dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms),
+ GFP_KERNEL);
+   if (!dev->dma_parms)
+   return -ENOMEM;
+   }
+   dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
+
msm_gem_shrinker_init(ddev);
 
switch (get_mdp_ver(pdev)) {
-- 
2.20.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH AUTOSEL 4.14 02/21] drm/msm: Set dma maximum segment size for mdss

2020-02-22 Thread Sasha Levin
From: Sean Paul 

[ Upstream commit db735fc4036bbe1fbe606819b5f0ff26cc76cdff ]

Turning on CONFIG_DMA_API_DEBUG_SG results in the following error:

[   12.078665] msm ae0.mdss: DMA-API: mapping sg segment longer than device 
claims to support [len=3526656] [max=65536]
[   12.089870] WARNING: CPU: 6 PID: 334 at 
/mnt/host/source/src/third_party/kernel/v4.19/kernel/dma/debug.c:1301 
debug_dma_map_sg+0x1dc/0x318
[   12.102655] Modules linked in: joydev
[   12.106442] CPU: 6 PID: 334 Comm: frecon Not tainted 4.19.0 #2
[   12.112450] Hardware name: Google Cheza (rev3+) (DT)
[   12.117566] pstate: 6049 (nZCv daif +PAN -UAO)
[   12.122506] pc : debug_dma_map_sg+0x1dc/0x318
[   12.126995] lr : debug_dma_map_sg+0x1dc/0x318
[   12.131487] sp : ff800cc3ba80
[   12.134913] x29: ff800cc3ba80 x28: 
[   12.140395] x27: 0004 x26: 0004
[   12.145868] x25: ff8008e55b18 x24: 
[   12.151337] x23:  x22: ff800921c000
[   12.156809] x21: ffc0fa75b080 x20: ffc0f7195090
[   12.162280] x19: ffc0f1c53280 x18: 
[   12.167749] x17:  x16: 
[   12.173218] x15:  x14: 0720072007200720
[   12.178689] x13: 0720072007200720 x12: 0720072007200720
[   12.184161] x11: 0720072007200720 x10: 0720072007200720
[   12.189641] x9 : ffc0f1fc6b60 x8 : 
[   12.195110] x7 : ff8008132ce0 x6 : 
[   12.200585] x5 :  x4 : ff8008134734
[   12.206058] x3 : ff800cc3b830 x2 : ffc0f1fc6240
[   12.211532] x1 : 25045a74f48a7400 x0 : 25045a74f48a7400
[   12.217006] Call trace:
[   12.219535]  debug_dma_map_sg+0x1dc/0x318
[   12.223671]  get_pages+0x19c/0x20c
[   12.227177]  msm_gem_fault+0x64/0xfc
[   12.230874]  __do_fault+0x3c/0x140
[   12.234383]  __handle_mm_fault+0x70c/0xdb8
[   12.238603]  handle_mm_fault+0xac/0xc4
[   12.242473]  do_page_fault+0x1bc/0x3d4
[   12.246342]  do_translation_fault+0x54/0x88
[   12.250652]  do_mem_abort+0x60/0xf0
[   12.254250]  el0_da+0x20/0x24
[   12.257317] irq event stamp: 67260
[   12.260828] hardirqs last  enabled at (67259): [] 
console_unlock+0x214/0x608
[   12.269693] hardirqs last disabled at (67260): [] 
do_debug_exception+0x5c/0x178
[   12.278820] softirqs last  enabled at (67256): [] 
__do_softirq+0x4d4/0x520
[   12.287510] softirqs last disabled at (67249): [] 
irq_exit+0xa8/0x100
[   12.295742] ---[ end trace e63cfc40c313ffab ]---

The root of the problem is that the default segment size for sgt is
(UINT_MAX & PAGE_MASK), and the default segment size for device dma is
64K. As such, if you compare the 2, you would deduce that the sg segment
will overflow the device's capacity. In reality, the hardware can
accommodate the larger sg segments, it's just not initializing its max
segment properly. This patch initializes the max segment size for the
mdss device, which gets rid of that pesky warning.

Reported-by: Stephen Boyd 
Tested-by: Stephen Boyd 
Tested-by: Sai Prakash Ranjan 
Reviewed-by: Rob Clark 
Signed-off-by: Sean Paul 
Signed-off-by: Douglas Anderson 
Link: 
https://patchwork.freedesktop.org/patch/msgid/2020012813.REPOST.1.I92c66a35fb13f368095b05287bdabdbe88ca6922@changeid
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/msm/msm_drv.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 77c45a2ebd833..d9c0687435a05 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -420,6 +420,14 @@ static int msm_drm_init(struct device *dev, struct 
drm_driver *drv)
if (ret)
goto fail;
 
+   if (!dev->dma_parms) {
+   dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms),
+ GFP_KERNEL);
+   if (!dev->dma_parms)
+   return -ENOMEM;
+   }
+   dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
+
msm_gem_shrinker_init(ddev);
 
switch (get_mdp_ver(pdev)) {
-- 
2.20.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH AUTOSEL 5.4 24/50] drm/amd/display: Limit minimum DPPCLK to 100MHz.

2020-02-22 Thread Sasha Levin
From: Yongqiang Sun 

[ Upstream commit 6c81917a0485ee2a1be0dc23321ac10ecfd9578b ]

[Why]
Underflow is observed when plug in a 4K@60 monitor with
1366x768 eDP due to DPPCLK is too low.

[How]
Limit minimum DPPCLK to 100MHz.

Signed-off-by: Yongqiang Sun 
Reviewed-by: Eric Yang 
Acked-by: Bhawanpreet Lakha 
Signed-off-by: Alex Deucher 
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c 
b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
index 787f94d815f42..dd92f9c295b45 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
@@ -91,6 +91,12 @@ void rn_update_clocks(struct clk_mgr *clk_mgr_base,
rn_vbios_smu_set_min_deep_sleep_dcfclk(clk_mgr, 
clk_mgr_base->clks.dcfclk_deep_sleep_khz);
}
 
+   // workaround: Limit dppclk to 100Mhz to avoid lower eDP panel switch 
to plus 4K monitor underflow.
+   if (!IS_DIAG_DC(dc->ctx->dce_environment)) {
+   if (new_clocks->dppclk_khz < 10)
+   new_clocks->dppclk_khz = 10;
+   }
+
if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, 
clk_mgr->base.clks.dppclk_khz)) {
if (clk_mgr->base.clks.dppclk_khz > new_clocks->dppclk_khz)
dpp_clock_lowered = true;
-- 
2.20.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH AUTOSEL 4.19 02/25] drm/msm: Set dma maximum segment size for mdss

2020-02-22 Thread Sasha Levin
From: Sean Paul 

[ Upstream commit db735fc4036bbe1fbe606819b5f0ff26cc76cdff ]

Turning on CONFIG_DMA_API_DEBUG_SG results in the following error:

[   12.078665] msm ae0.mdss: DMA-API: mapping sg segment longer than device 
claims to support [len=3526656] [max=65536]
[   12.089870] WARNING: CPU: 6 PID: 334 at 
/mnt/host/source/src/third_party/kernel/v4.19/kernel/dma/debug.c:1301 
debug_dma_map_sg+0x1dc/0x318
[   12.102655] Modules linked in: joydev
[   12.106442] CPU: 6 PID: 334 Comm: frecon Not tainted 4.19.0 #2
[   12.112450] Hardware name: Google Cheza (rev3+) (DT)
[   12.117566] pstate: 6049 (nZCv daif +PAN -UAO)
[   12.122506] pc : debug_dma_map_sg+0x1dc/0x318
[   12.126995] lr : debug_dma_map_sg+0x1dc/0x318
[   12.131487] sp : ff800cc3ba80
[   12.134913] x29: ff800cc3ba80 x28: 
[   12.140395] x27: 0004 x26: 0004
[   12.145868] x25: ff8008e55b18 x24: 
[   12.151337] x23:  x22: ff800921c000
[   12.156809] x21: ffc0fa75b080 x20: ffc0f7195090
[   12.162280] x19: ffc0f1c53280 x18: 
[   12.167749] x17:  x16: 
[   12.173218] x15:  x14: 0720072007200720
[   12.178689] x13: 0720072007200720 x12: 0720072007200720
[   12.184161] x11: 0720072007200720 x10: 0720072007200720
[   12.189641] x9 : ffc0f1fc6b60 x8 : 
[   12.195110] x7 : ff8008132ce0 x6 : 
[   12.200585] x5 :  x4 : ff8008134734
[   12.206058] x3 : ff800cc3b830 x2 : ffc0f1fc6240
[   12.211532] x1 : 25045a74f48a7400 x0 : 25045a74f48a7400
[   12.217006] Call trace:
[   12.219535]  debug_dma_map_sg+0x1dc/0x318
[   12.223671]  get_pages+0x19c/0x20c
[   12.227177]  msm_gem_fault+0x64/0xfc
[   12.230874]  __do_fault+0x3c/0x140
[   12.234383]  __handle_mm_fault+0x70c/0xdb8
[   12.238603]  handle_mm_fault+0xac/0xc4
[   12.242473]  do_page_fault+0x1bc/0x3d4
[   12.246342]  do_translation_fault+0x54/0x88
[   12.250652]  do_mem_abort+0x60/0xf0
[   12.254250]  el0_da+0x20/0x24
[   12.257317] irq event stamp: 67260
[   12.260828] hardirqs last  enabled at (67259): [] 
console_unlock+0x214/0x608
[   12.269693] hardirqs last disabled at (67260): [] 
do_debug_exception+0x5c/0x178
[   12.278820] softirqs last  enabled at (67256): [] 
__do_softirq+0x4d4/0x520
[   12.287510] softirqs last disabled at (67249): [] 
irq_exit+0xa8/0x100
[   12.295742] ---[ end trace e63cfc40c313ffab ]---

The root of the problem is that the default segment size for sgt is
(UINT_MAX & PAGE_MASK), and the default segment size for device dma is
64K. As such, if you compare the 2, you would deduce that the sg segment
will overflow the device's capacity. In reality, the hardware can
accommodate the larger sg segments, it's just not initializing its max
segment properly. This patch initializes the max segment size for the
mdss device, which gets rid of that pesky warning.

Reported-by: Stephen Boyd 
Tested-by: Stephen Boyd 
Tested-by: Sai Prakash Ranjan 
Reviewed-by: Rob Clark 
Signed-off-by: Sean Paul 
Signed-off-by: Douglas Anderson 
Link: 
https://patchwork.freedesktop.org/patch/msgid/2020012813.REPOST.1.I92c66a35fb13f368095b05287bdabdbe88ca6922@changeid
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/msm/msm_drv.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index dbfd2c006f740..6f81de85fb860 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -492,6 +492,14 @@ static int msm_drm_init(struct device *dev, struct 
drm_driver *drv)
if (ret)
goto err_msm_uninit;
 
+   if (!dev->dma_parms) {
+   dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms),
+ GFP_KERNEL);
+   if (!dev->dma_parms)
+   return -ENOMEM;
+   }
+   dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
+
msm_gem_shrinker_init(ddev);
 
switch (get_mdp_ver(pdev)) {
-- 
2.20.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH AUTOSEL 5.4 25/50] drm/amd/display: Add initialitions for PLL2 clock source

2020-02-22 Thread Sasha Levin
From: Isabel Zhang 

[ Upstream commit c134c3cabae46a56ab2e1f5e5fa49405e1758838 ]

[Why]
Starting from 14nm, the PLL is built into the PHY and the PLL is mapped
to PHY on 1 to 1 basis. In the code, the DP port is mapped to a PLL that was not
initialized. This causes DP to HDMI dongle to not light up the display.

[How]
Initializations added for PLL2 when creating resources.

Signed-off-by: Isabel Zhang 
Reviewed-by: Eric Yang 
Acked-by: Bhawanpreet Lakha 
Signed-off-by: Alex Deucher 
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c 
b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
index b0e5e64df2127..161bf7caf3ae0 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
@@ -57,6 +57,7 @@
 #include "dcn20/dcn20_dccg.h"
 #include "dcn21_hubbub.h"
 #include "dcn10/dcn10_resource.h"
+#include "dce110/dce110_resource.h"
 
 #include "dcn20/dcn20_dwb.h"
 #include "dcn20/dcn20_mmhubbub.h"
@@ -824,6 +825,7 @@ static const struct dc_debug_options debug_defaults_diags = 
{
 enum dcn20_clk_src_array_id {
DCN20_CLK_SRC_PLL0,
DCN20_CLK_SRC_PLL1,
+   DCN20_CLK_SRC_PLL2,
DCN20_CLK_SRC_TOTAL_DCN21
 };
 
@@ -1492,6 +1494,10 @@ static bool construct(
dcn21_clock_source_create(ctx, ctx->dc_bios,
CLOCK_SOURCE_COMBO_PHY_PLL1,
_src_regs[1], false);
+   pool->base.clock_sources[DCN20_CLK_SRC_PLL2] =
+   dcn21_clock_source_create(ctx, ctx->dc_bios,
+   CLOCK_SOURCE_COMBO_PHY_PLL2,
+   _src_regs[2], false);
 
pool->base.clk_src_count = DCN20_CLK_SRC_TOTAL_DCN21;
 
-- 
2.20.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH AUTOSEL 5.4 26/50] amdgpu: Prevent build errors regarding soft/hard-float FP ABI tags

2020-02-22 Thread Sasha Levin
From: Daniel Kolesa 

[ Upstream commit 416611d9b6eebaeae58ed26cc7d23131c69126b1 ]

On PowerPC, the compiler will tag object files with whether they
use hard or soft float FP ABI and whether they use 64 or 128-bit
long double ABI. On systems with 64-bit long double ABI, a tag
will get emitted whenever a double is used, as on those systems
a long double is the same as a double. This will prevent linkage
as other files are being compiled with hard-float.

On ppc64, this code will never actually get used for the time
being, as the only currently existing hardware using it are the
Renoir APUs. Therefore, until this is testable and can be fixed
properly, at least make sure the build will not fail.

Signed-off-by: Daniel Kolesa 
Signed-off-by: Alex Deucher 
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile 
b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile
index b864869cc7e3e..6fa7422c51da5 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile
@@ -91,6 +91,12 @@ ifdef CONFIG_DRM_AMD_DC_DCN2_1
 ###
 CLK_MGR_DCN21 = rn_clk_mgr.o rn_clk_mgr_vbios_smu.o
 
+# prevent build errors regarding soft-float vs hard-float FP ABI tags
+# this code is currently unused on ppc64, as it applies to Renoir APUs only
+ifdef CONFIG_PPC64
+CFLAGS_$(AMDDALPATH)/dc/clk_mgr/dcn21/rn_clk_mgr.o := $(call 
cc-option,-mno-gnu-attribute)
+endif
+
 AMD_DAL_CLK_MGR_DCN21 = $(addprefix 
$(AMDDALPATH)/dc/clk_mgr/dcn21/,$(CLK_MGR_DCN21))
 
 AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN21)
-- 
2.20.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH AUTOSEL 5.4 23/50] drm/amd/display: Check engine is not NULL before acquiring

2020-02-22 Thread Sasha Levin
From: Aric Cyr 

[ Upstream commit 2b63d0ec0daf79ba503fa8bfa25e07dc3da274f3 ]

[Why]
Engine can be NULL in some cases, so we must not acquire it.

[How]
Check for NULL engine before acquiring.

Signed-off-by: Aric Cyr 
Reviewed-by: Harry Wentland 
Acked-by: Bhawanpreet Lakha 
Signed-off-by: Alex Deucher 
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/amd/display/dc/dce/dce_aux.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c 
b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
index c3f9f4185ce8d..cf877238fff9d 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
@@ -386,7 +386,7 @@ static bool acquire(
 {
enum gpio_result result;
 
-   if (!is_engine_available(engine))
+   if ((engine == NULL) || !is_engine_available(engine))
return false;
 
result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE,
-- 
2.20.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH AUTOSEL 5.4 21/50] drm/amd/display: Do not set optimized_require to false after plane disable

2020-02-22 Thread Sasha Levin
From: Sung Lee 

[ Upstream commit df36f6cf23ada812930afa8ee76681d4ad307c61 ]

[WHY]
The optimized_require flag is needed to set watermarks and clocks lower
in certain conditions. This flag is set to true and then set to false
while programming front end in dcn20.

[HOW]
Do not set the flag to false while disabling plane.

Signed-off-by: Sung Lee 
Reviewed-by: Tony Cheng 
Acked-by: Bhawanpreet Lakha 
Signed-off-by: Alex Deucher 
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
index 937a8ba811603..e933f6a369f92 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
@@ -493,7 +493,6 @@ static void dcn20_plane_atomic_disable(struct dc *dc, 
struct pipe_ctx *pipe_ctx)
dpp->funcs->dpp_dppclk_control(dpp, false, false);
 
hubp->power_gated = true;
-   dc->optimized_required = false; /* We're powering off, no need to 
optimize */
 
dc->hwss.plane_atomic_power_down(dc,
pipe_ctx->plane_res.dpp,
-- 
2.20.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH AUTOSEL 5.5 22/58] drm/amd/display: Do not set optimized_require to false after plane disable

2020-02-22 Thread Sasha Levin
From: Sung Lee 

[ Upstream commit df36f6cf23ada812930afa8ee76681d4ad307c61 ]

[WHY]
The optimized_require flag is needed to set watermarks and clocks lower
in certain conditions. This flag is set to true and then set to false
while programming front end in dcn20.

[HOW]
Do not set the flag to false while disabling plane.

Signed-off-by: Sung Lee 
Reviewed-by: Tony Cheng 
Acked-by: Bhawanpreet Lakha 
Signed-off-by: Alex Deucher 
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
index ac8c18fadefce..448bc9b39942f 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
@@ -493,7 +493,6 @@ static void dcn20_plane_atomic_disable(struct dc *dc, 
struct pipe_ctx *pipe_ctx)
dpp->funcs->dpp_dppclk_control(dpp, false, false);
 
hubp->power_gated = true;
-   dc->optimized_required = false; /* We're powering off, no need to 
optimize */
 
dc->hwss.plane_atomic_power_down(dc,
pipe_ctx->plane_res.dpp,
-- 
2.20.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH AUTOSEL 5.4 02/50] drm/msm: Set dma maximum segment size for mdss

2020-02-22 Thread Sasha Levin
From: Sean Paul 

[ Upstream commit db735fc4036bbe1fbe606819b5f0ff26cc76cdff ]

Turning on CONFIG_DMA_API_DEBUG_SG results in the following error:

[   12.078665] msm ae0.mdss: DMA-API: mapping sg segment longer than device 
claims to support [len=3526656] [max=65536]
[   12.089870] WARNING: CPU: 6 PID: 334 at 
/mnt/host/source/src/third_party/kernel/v4.19/kernel/dma/debug.c:1301 
debug_dma_map_sg+0x1dc/0x318
[   12.102655] Modules linked in: joydev
[   12.106442] CPU: 6 PID: 334 Comm: frecon Not tainted 4.19.0 #2
[   12.112450] Hardware name: Google Cheza (rev3+) (DT)
[   12.117566] pstate: 6049 (nZCv daif +PAN -UAO)
[   12.122506] pc : debug_dma_map_sg+0x1dc/0x318
[   12.126995] lr : debug_dma_map_sg+0x1dc/0x318
[   12.131487] sp : ff800cc3ba80
[   12.134913] x29: ff800cc3ba80 x28: 
[   12.140395] x27: 0004 x26: 0004
[   12.145868] x25: ff8008e55b18 x24: 
[   12.151337] x23:  x22: ff800921c000
[   12.156809] x21: ffc0fa75b080 x20: ffc0f7195090
[   12.162280] x19: ffc0f1c53280 x18: 
[   12.167749] x17:  x16: 
[   12.173218] x15:  x14: 0720072007200720
[   12.178689] x13: 0720072007200720 x12: 0720072007200720
[   12.184161] x11: 0720072007200720 x10: 0720072007200720
[   12.189641] x9 : ffc0f1fc6b60 x8 : 
[   12.195110] x7 : ff8008132ce0 x6 : 
[   12.200585] x5 :  x4 : ff8008134734
[   12.206058] x3 : ff800cc3b830 x2 : ffc0f1fc6240
[   12.211532] x1 : 25045a74f48a7400 x0 : 25045a74f48a7400
[   12.217006] Call trace:
[   12.219535]  debug_dma_map_sg+0x1dc/0x318
[   12.223671]  get_pages+0x19c/0x20c
[   12.227177]  msm_gem_fault+0x64/0xfc
[   12.230874]  __do_fault+0x3c/0x140
[   12.234383]  __handle_mm_fault+0x70c/0xdb8
[   12.238603]  handle_mm_fault+0xac/0xc4
[   12.242473]  do_page_fault+0x1bc/0x3d4
[   12.246342]  do_translation_fault+0x54/0x88
[   12.250652]  do_mem_abort+0x60/0xf0
[   12.254250]  el0_da+0x20/0x24
[   12.257317] irq event stamp: 67260
[   12.260828] hardirqs last  enabled at (67259): [] 
console_unlock+0x214/0x608
[   12.269693] hardirqs last disabled at (67260): [] 
do_debug_exception+0x5c/0x178
[   12.278820] softirqs last  enabled at (67256): [] 
__do_softirq+0x4d4/0x520
[   12.287510] softirqs last disabled at (67249): [] 
irq_exit+0xa8/0x100
[   12.295742] ---[ end trace e63cfc40c313ffab ]---

The root of the problem is that the default segment size for sgt is
(UINT_MAX & PAGE_MASK), and the default segment size for device dma is
64K. As such, if you compare the 2, you would deduce that the sg segment
will overflow the device's capacity. In reality, the hardware can
accommodate the larger sg segments, it's just not initializing its max
segment properly. This patch initializes the max segment size for the
mdss device, which gets rid of that pesky warning.

Reported-by: Stephen Boyd 
Tested-by: Stephen Boyd 
Tested-by: Sai Prakash Ranjan 
Reviewed-by: Rob Clark 
Signed-off-by: Sean Paul 
Signed-off-by: Douglas Anderson 
Link: 
https://patchwork.freedesktop.org/patch/msgid/2020012813.REPOST.1.I92c66a35fb13f368095b05287bdabdbe88ca6922@changeid
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/msm/msm_drv.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index c84f0a8b3f2ce..b73fbb65e14b2 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -441,6 +441,14 @@ static int msm_drm_init(struct device *dev, struct 
drm_driver *drv)
if (ret)
goto err_msm_uninit;
 
+   if (!dev->dma_parms) {
+   dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms),
+ GFP_KERNEL);
+   if (!dev->dma_parms)
+   return -ENOMEM;
+   }
+   dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
+
msm_gem_shrinker_init(ddev);
 
switch (get_mdp_ver(pdev)) {
-- 
2.20.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH AUTOSEL 5.5 25/58] drm/amd/display: Limit minimum DPPCLK to 100MHz.

2020-02-22 Thread Sasha Levin
From: Yongqiang Sun 

[ Upstream commit 6c81917a0485ee2a1be0dc23321ac10ecfd9578b ]

[Why]
Underflow is observed when plug in a 4K@60 monitor with
1366x768 eDP due to DPPCLK is too low.

[How]
Limit minimum DPPCLK to 100MHz.

Signed-off-by: Yongqiang Sun 
Reviewed-by: Eric Yang 
Acked-by: Bhawanpreet Lakha 
Signed-off-by: Alex Deucher 
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c 
b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
index 35c55e54eac01..619b1a18b0441 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
@@ -149,6 +149,12 @@ void rn_update_clocks(struct clk_mgr *clk_mgr_base,
rn_vbios_smu_set_min_deep_sleep_dcfclk(clk_mgr, 
clk_mgr_base->clks.dcfclk_deep_sleep_khz);
}
 
+   // workaround: Limit dppclk to 100Mhz to avoid lower eDP panel switch 
to plus 4K monitor underflow.
+   if (!IS_DIAG_DC(dc->ctx->dce_environment)) {
+   if (new_clocks->dppclk_khz < 10)
+   new_clocks->dppclk_khz = 10;
+   }
+
if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, 
clk_mgr->base.clks.dppclk_khz)) {
if (clk_mgr->base.clks.dppclk_khz > new_clocks->dppclk_khz)
dpp_clock_lowered = true;
-- 
2.20.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH AUTOSEL 5.5 27/58] amdgpu: Prevent build errors regarding soft/hard-float FP ABI tags

2020-02-22 Thread Sasha Levin
From: Daniel Kolesa 

[ Upstream commit 416611d9b6eebaeae58ed26cc7d23131c69126b1 ]

On PowerPC, the compiler will tag object files with whether they
use hard or soft float FP ABI and whether they use 64 or 128-bit
long double ABI. On systems with 64-bit long double ABI, a tag
will get emitted whenever a double is used, as on those systems
a long double is the same as a double. This will prevent linkage
as other files are being compiled with hard-float.

On ppc64, this code will never actually get used for the time
being, as the only currently existing hardware using it are the
Renoir APUs. Therefore, until this is testable and can be fixed
properly, at least make sure the build will not fail.

Signed-off-by: Daniel Kolesa 
Signed-off-by: Alex Deucher 
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile 
b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile
index b864869cc7e3e..6fa7422c51da5 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile
@@ -91,6 +91,12 @@ ifdef CONFIG_DRM_AMD_DC_DCN2_1
 ###
 CLK_MGR_DCN21 = rn_clk_mgr.o rn_clk_mgr_vbios_smu.o
 
+# prevent build errors regarding soft-float vs hard-float FP ABI tags
+# this code is currently unused on ppc64, as it applies to Renoir APUs only
+ifdef CONFIG_PPC64
+CFLAGS_$(AMDDALPATH)/dc/clk_mgr/dcn21/rn_clk_mgr.o := $(call 
cc-option,-mno-gnu-attribute)
+endif
+
 AMD_DAL_CLK_MGR_DCN21 = $(addprefix 
$(AMDDALPATH)/dc/clk_mgr/dcn21/,$(CLK_MGR_DCN21))
 
 AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN21)
-- 
2.20.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH AUTOSEL 5.5 24/58] drm/amd/display: Check engine is not NULL before acquiring

2020-02-22 Thread Sasha Levin
From: Aric Cyr 

[ Upstream commit 2b63d0ec0daf79ba503fa8bfa25e07dc3da274f3 ]

[Why]
Engine can be NULL in some cases, so we must not acquire it.

[How]
Check for NULL engine before acquiring.

Signed-off-by: Aric Cyr 
Reviewed-by: Harry Wentland 
Acked-by: Bhawanpreet Lakha 
Signed-off-by: Alex Deucher 
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/amd/display/dc/dce/dce_aux.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c 
b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
index 793c0cec407f9..5fcffb29317e3 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
@@ -398,7 +398,7 @@ static bool acquire(
 {
enum gpio_result result;
 
-   if (!is_engine_available(engine))
+   if ((engine == NULL) || !is_engine_available(engine))
return false;
 
result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE,
-- 
2.20.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH AUTOSEL 5.5 02/58] drm/msm: Set dma maximum segment size for mdss

2020-02-22 Thread Sasha Levin
From: Sean Paul 

[ Upstream commit db735fc4036bbe1fbe606819b5f0ff26cc76cdff ]

Turning on CONFIG_DMA_API_DEBUG_SG results in the following error:

[   12.078665] msm ae0.mdss: DMA-API: mapping sg segment longer than device 
claims to support [len=3526656] [max=65536]
[   12.089870] WARNING: CPU: 6 PID: 334 at 
/mnt/host/source/src/third_party/kernel/v4.19/kernel/dma/debug.c:1301 
debug_dma_map_sg+0x1dc/0x318
[   12.102655] Modules linked in: joydev
[   12.106442] CPU: 6 PID: 334 Comm: frecon Not tainted 4.19.0 #2
[   12.112450] Hardware name: Google Cheza (rev3+) (DT)
[   12.117566] pstate: 6049 (nZCv daif +PAN -UAO)
[   12.122506] pc : debug_dma_map_sg+0x1dc/0x318
[   12.126995] lr : debug_dma_map_sg+0x1dc/0x318
[   12.131487] sp : ff800cc3ba80
[   12.134913] x29: ff800cc3ba80 x28: 
[   12.140395] x27: 0004 x26: 0004
[   12.145868] x25: ff8008e55b18 x24: 
[   12.151337] x23:  x22: ff800921c000
[   12.156809] x21: ffc0fa75b080 x20: ffc0f7195090
[   12.162280] x19: ffc0f1c53280 x18: 
[   12.167749] x17:  x16: 
[   12.173218] x15:  x14: 0720072007200720
[   12.178689] x13: 0720072007200720 x12: 0720072007200720
[   12.184161] x11: 0720072007200720 x10: 0720072007200720
[   12.189641] x9 : ffc0f1fc6b60 x8 : 
[   12.195110] x7 : ff8008132ce0 x6 : 
[   12.200585] x5 :  x4 : ff8008134734
[   12.206058] x3 : ff800cc3b830 x2 : ffc0f1fc6240
[   12.211532] x1 : 25045a74f48a7400 x0 : 25045a74f48a7400
[   12.217006] Call trace:
[   12.219535]  debug_dma_map_sg+0x1dc/0x318
[   12.223671]  get_pages+0x19c/0x20c
[   12.227177]  msm_gem_fault+0x64/0xfc
[   12.230874]  __do_fault+0x3c/0x140
[   12.234383]  __handle_mm_fault+0x70c/0xdb8
[   12.238603]  handle_mm_fault+0xac/0xc4
[   12.242473]  do_page_fault+0x1bc/0x3d4
[   12.246342]  do_translation_fault+0x54/0x88
[   12.250652]  do_mem_abort+0x60/0xf0
[   12.254250]  el0_da+0x20/0x24
[   12.257317] irq event stamp: 67260
[   12.260828] hardirqs last  enabled at (67259): [] 
console_unlock+0x214/0x608
[   12.269693] hardirqs last disabled at (67260): [] 
do_debug_exception+0x5c/0x178
[   12.278820] softirqs last  enabled at (67256): [] 
__do_softirq+0x4d4/0x520
[   12.287510] softirqs last disabled at (67249): [] 
irq_exit+0xa8/0x100
[   12.295742] ---[ end trace e63cfc40c313ffab ]---

The root of the problem is that the default segment size for sgt is
(UINT_MAX & PAGE_MASK), and the default segment size for device dma is
64K. As such, if you compare the 2, you would deduce that the sg segment
will overflow the device's capacity. In reality, the hardware can
accommodate the larger sg segments, it's just not initializing its max
segment properly. This patch initializes the max segment size for the
mdss device, which gets rid of that pesky warning.

Reported-by: Stephen Boyd 
Tested-by: Stephen Boyd 
Tested-by: Sai Prakash Ranjan 
Reviewed-by: Rob Clark 
Signed-off-by: Sean Paul 
Signed-off-by: Douglas Anderson 
Link: 
https://patchwork.freedesktop.org/patch/msgid/2020012813.REPOST.1.I92c66a35fb13f368095b05287bdabdbe88ca6922@changeid
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/msm/msm_drv.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index c84f0a8b3f2ce..b73fbb65e14b2 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -441,6 +441,14 @@ static int msm_drm_init(struct device *dev, struct 
drm_driver *drv)
if (ret)
goto err_msm_uninit;
 
+   if (!dev->dma_parms) {
+   dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms),
+ GFP_KERNEL);
+   if (!dev->dma_parms)
+   return -ENOMEM;
+   }
+   dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
+
msm_gem_shrinker_init(ddev);
 
switch (get_mdp_ver(pdev)) {
-- 
2.20.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH AUTOSEL 5.5 26/58] drm/amd/display: Add initialitions for PLL2 clock source

2020-02-22 Thread Sasha Levin
From: Isabel Zhang 

[ Upstream commit c134c3cabae46a56ab2e1f5e5fa49405e1758838 ]

[Why]
Starting from 14nm, the PLL is built into the PHY and the PLL is mapped
to PHY on 1 to 1 basis. In the code, the DP port is mapped to a PLL that was not
initialized. This causes DP to HDMI dongle to not light up the display.

[How]
Initializations added for PLL2 when creating resources.

Signed-off-by: Isabel Zhang 
Reviewed-by: Eric Yang 
Acked-by: Bhawanpreet Lakha 
Signed-off-by: Alex Deucher 
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c 
b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
index b29b2c99a564e..554062859866d 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
@@ -57,6 +57,7 @@
 #include "dcn20/dcn20_dccg.h"
 #include "dcn21_hubbub.h"
 #include "dcn10/dcn10_resource.h"
+#include "dce110/dce110_resource.h"
 
 #include "dcn20/dcn20_dwb.h"
 #include "dcn20/dcn20_mmhubbub.h"
@@ -866,6 +867,7 @@ static const struct dc_debug_options debug_defaults_diags = 
{
 enum dcn20_clk_src_array_id {
DCN20_CLK_SRC_PLL0,
DCN20_CLK_SRC_PLL1,
+   DCN20_CLK_SRC_PLL2,
DCN20_CLK_SRC_TOTAL_DCN21
 };
 
@@ -1736,6 +1738,10 @@ static bool construct(
dcn21_clock_source_create(ctx, ctx->dc_bios,
CLOCK_SOURCE_COMBO_PHY_PLL1,
_src_regs[1], false);
+   pool->base.clock_sources[DCN20_CLK_SRC_PLL2] =
+   dcn21_clock_source_create(ctx, ctx->dc_bios,
+   CLOCK_SOURCE_COMBO_PHY_PLL2,
+   _src_regs[2], false);
 
pool->base.clk_src_count = DCN20_CLK_SRC_TOTAL_DCN21;
 
-- 
2.20.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH 3/5] drm/lima: save task info dump when task fail

2020-02-22 Thread kbuild test robot
Hi Qiang,

I love your patch! Yet something to improve:

[auto build test ERROR on drm-tip/drm-tip]
[cannot apply to drm-exynos/exynos-drm-next drm-intel/for-linux-next 
tegra-drm/drm/tegra/for-next linus/master v5.6-rc2 next-20200221]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:
https://github.com/0day-ci/linux/commits/Qiang-Yu/drm-lima-add-error-debug-functionality/20200223-054634
base:   git://anongit.freedesktop.org/drm/drm-tip drm-tip
config: mips-allyesconfig (attached as .config)
compiler: mips-linux-gcc (GCC) 7.5.0
reproduce:
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=7.5.0 make.cross ARCH=mips 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot 

All errors (new ones prefixed by >>):

   drivers/gpu/drm/lima/lima_sched.c: In function 
'lima_sched_build_error_task_list':
>> drivers/gpu/drm/lima/lima_sched.c:347:11: error: implicit declaration of 
>> function 'vmap'; did you mean 'bmap'? [-Werror=implicit-function-declaration]
   data = vmap(bo->base.pages, bo->heap_size >> PAGE_SHIFT,
  ^~~~
  bmap
>> drivers/gpu/drm/lima/lima_sched.c:348:9: error: 'VM_MAP' undeclared (first 
>> use in this function); did you mean 'VM_MPX'?
VM_MAP, pgprot_writecombine(PAGE_KERNEL));
^~
VM_MPX
   drivers/gpu/drm/lima/lima_sched.c:348:9: note: each undeclared identifier is 
reported only once for each function it appears in
>> drivers/gpu/drm/lima/lima_sched.c:356:4: error: implicit declaration of 
>> function 'vunmap'; did you mean 'kunmap'? 
>> [-Werror=implicit-function-declaration]
   vunmap(data);
   ^~
   kunmap
   cc1: some warnings being treated as errors

vim +347 drivers/gpu/drm/lima/lima_sched.c

   258  
   259  static void lima_sched_build_error_task_list(struct lima_sched_task 
*task)
   260  {
   261  struct lima_sched_error_task *et;
   262  struct lima_sched_pipe *pipe = to_lima_pipe(task->base.sched);
   263  struct lima_ip *ip = pipe->processor[0];
   264  int pipe_id = ip->id == lima_ip_gp ? lima_pipe_gp : 
lima_pipe_pp;
   265  struct lima_device *dev = ip->dev;
   266  struct lima_sched_context *sched_ctx =
   267  container_of(task->base.entity, struct 
lima_sched_context, base);
   268  struct lima_ctx *ctx =
   269  container_of(sched_ctx, struct lima_ctx, 
context[pipe_id]);
   270  struct lima_dump_task *dt;
   271  struct lima_dump_chunk *chunk;
   272  struct lima_dump_chunk_pid *pid_chunk;
   273  struct lima_dump_chunk_buffer *buffer_chunk;
   274  uint32_t size, task_size, mem_size;
   275  int i;
   276  
   277  mutex_lock(>error_task_list_lock);
   278  
   279  if (dev->dump.num_tasks >= lima_max_error_tasks) {
   280  dev_info(dev->dev, "fail to save task state: error task 
list is full\n");
   281  goto out;
   282  }
   283  
   284  /* frame chunk */
   285  size = sizeof(struct lima_dump_chunk) + pipe->frame_size;
   286  /* process name chunk */
   287  size += sizeof(struct lima_dump_chunk) + sizeof(ctx->pname);
   288  /* pid chunk */
   289  size += sizeof(struct lima_dump_chunk);
   290  /* buffer chunks */
   291  for (i = 0; i < task->num_bos; i++) {
   292  struct lima_bo *bo = task->bos[i];
   293  
   294  size += sizeof(struct lima_dump_chunk);
   295  size += bo->heap_size ? bo->heap_size : 
lima_bo_size(bo);
   296  }
   297  
   298  task_size = size + sizeof(struct lima_dump_task);
   299  mem_size = task_size + sizeof(*et);
   300  et = kvmalloc(mem_size, GFP_KERNEL);
   301  if (!et) {
   302  dev_err(dev->dev, "fail to alloc task dump buffer of 
size %x\n",
   303  mem_size);
   304  goto out;
   305  }
   306  
   307  et->data = et + 1;
   308  et->size = task_size;
   309  
   310  dt = et->data;
   311  memset(dt, 0, sizeof(*dt));
   312  dt->id = pipe_id;
   313  dt->size = size;
   314  
   315  chunk = (struct lima_dump_chunk *)(dt + 1);
   316  memset(chunk, 0, sizeof(*chunk));
   317  chunk->id = LIMA_DUMP_CHUNK_FRAME;
   318  chunk->size = pipe->frame_size;
   319  memcpy(chunk + 1, task->frame, pipe->frame_size);
   320  dt->num_chunks++;
   321  
   322  chunk = 

Re: [PATCH RFC v3 2/6] drm/sprd: add Unisoc's drm kms master

2020-02-22 Thread Sam Ravnborg
Hi Kevin/tang.

Thanks for the quick and detailed feedback.
Your questions are addressed below.

Sam


> > > +static int sprd_drm_bind(struct device *dev)
> > > +{
> > > + struct drm_device *drm;
> > > + struct sprd_drm *sprd;
> > > + int err;
> > > +
> > > + drm = drm_dev_alloc(_drm_drv, dev);
> > > + if (IS_ERR(drm))
> > > + return PTR_ERR(drm);
> > You should embed drm_device in struct sprd_drm.
> > See example code in drm/drm_drv.c
> >
> > This is what modern drm drivers do.
> >
> > I *think* you can drop the component framework if you do this.
> >
> I have read it(drm/drm_drv.c) carefully, if drop the component framework,
> the whole our drm driver maybe need to redesign, so i still want to keep
> current design.
OK, fine.

> > > + sprd_drm_mode_config_init(drm);
> > > +
> > > + /* bind and init sub drivers */
> > > + err = component_bind_all(drm->dev, drm);
> > > + if (err) {
> > > + DRM_ERROR("failed to bind all component.\n");
> > > + goto err_dc_cleanup;
> > > + }
> > When you have a drm_device - which you do here.
> > Then please use drm_err() and friends for error messages.
> > Please verify all uses of DRM_XXX
> >
>   modern drm drivers need drm_xxx to replace DRM_XXX?
Yes, use of DRM_XXX is deprecated - when you have a drm_device.

> >
> > > + /* with irq_enabled = true, we can use the vblank feature. */
> > > + drm->irq_enabled = true;
> > I cannot see any irq being installed. This looks wrong.
> >
> Our display controller isr is been register on crtc driver(sprd_dpu.c), not
> here.

I think you just need to move this to next patch and then it is fine.

Sam

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: Support for early wakeup in DRM

2020-02-22 Thread jsanka

On 2020-02-21 09:20, Daniel Vetter wrote:

On Thu, Feb 20, 2020 at 01:24:00PM -0800, jsa...@codeaurora.org wrote:

On 2020-02-20 12:14, Daniel Vetter wrote:
> On Thu, Feb 20, 2020 at 10:45:57AM -0800, jsa...@codeaurora.org wrote:
> > Hello All,
> >
> > I am seeking recommendations for DRM compatible methods of updating
> > the
> HW
> > other than frame commit path. When exiting idle/runtime_suspend, the
> driver
> > votes for a bunch of resources including power/clk/bandwidth as a

part

> of
> > first commit handling. This usually adds a few millisecond delay
> > before
> > processing the frame. The requirement is to find possible ways to
> > reduce
> > this delay by providing an early intimation to the framework to
> "prepare"
> > the HW by voting for the resources and keep the HW ready to process

an

> > imminent frame commit. Especially in performance oriented Automotive
> world,
> > these delays are very time critical and we are working on ways to
> mitigate
> > them.
> >
> >
> >
> > DRM framework converges all the parameters affecting the HW in terms
> > of
> DRM
> > properties in a single COMMIT call. To address the above issue, we
> > need
> a
> > parallel channel which should allow the framework to make necessary
> changes
> > to the HW without violating the master access privileges.
> >
> >
> >
> > Before resorting to custom downstream ways, I want to check with the
> > community for folks who might have encountered and resolved such
> > issues.
>
> Just enable the display, which will grab all the clocks and

everything?

> Once the display is on a commit should be possible on the next frame,

at

> least for well-working drivers.
> -Daniel
>
I believe even to turn on the display, DRM will need an explicit 
commit

(probably without any planes/pixel buffers). For cases like smart

panels,

where we can keep the panel on(panel internal RAM refresh) and power
collapse the display HW, resuming back with an explicit commit will 
push

a

black (or default color programmed in the HW) frame causing a glitch.


Uh, you might want to look into the self-refresh helpers, which do this
without black frames and stuff.



I believe you are referring to Sean's PSR changes: 
https://patchwork.freedesktop.org/series/57366/

Will take a look.

Thanks and Regards,
Jeykumar S.

But yeah if there's really a gap here (and not just you folks 
creatively
abusing atomic kms in ways that it was not meant to be used) then we 
can
add a property that forbids power optimization and guarantee that you 
can
do the next screen update immediately. And then we can merge that with 
all

the usual requirements (driver implementation that works, open source
userspace, igt testcase, the full deal).

But it still feels like you're trying to do something automatically 
that's

not meant to work like this.

Cheers, Daniel



Thanks and Regards,
Jeykumar S.
> >
> >
> >
> > Thanks and Regards,
> >
> > Jeykumar S
> >
> > Qualcomm Inc.
> >
> >
> >
>
> > ___
> > dri-devel mailing list
> > dri-devel@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/dri-devel

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH/RFC 3/3] drm: rcar_du: Constify drm_driver

2020-02-22 Thread Daniel Vetter
On Sat, Feb 22, 2020 at 05:24:30PM +0200, Laurent Pinchart wrote:
> The drm_driver structure is never modified, make it const. The improves
> security by avoiding writable function pointers.
> 
> Signed-off-by: Laurent Pinchart 

I wonder whether there's some magic somewhere we could do to enlist the
cocci army to create the constify patches for us ...


Reviewed-by: Daniel Vetter 

> ---
>  drivers/gpu/drm/rcar-du/rcar_du_drv.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c 
> b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
> index 654e2dd08146..039eee3ef661 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
> @@ -474,7 +474,7 @@ MODULE_DEVICE_TABLE(of, rcar_du_of_table);
>  
>  DEFINE_DRM_GEM_CMA_FOPS(rcar_du_fops);
>  
> -static struct drm_driver rcar_du_driver = {
> +static const struct drm_driver rcar_du_driver = {
>   .driver_features= DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
>   .gem_free_object_unlocked = drm_gem_cma_free_object,
>   .gem_vm_ops = _gem_cma_vm_ops,
> -- 
> Regards,
> 
> Laurent Pinchart
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH/RFC 2/3] drm: Use a const drm_driver through the DRM core

2020-02-22 Thread Daniel Vetter
On Sat, Feb 22, 2020 at 05:24:29PM +0200, Laurent Pinchart wrote:
> The drm_driver structure contains pointers to functions, which can be an
> attack vector if an attacker can corrupt the structure. The DRM core
> however never modifies the structure, so it could be declared as const
> in drivers. Modify the DRM core to take const struct drm_driver
> pointers in all APIs.
> 
> Signed-off-by: Laurent Pinchart 

Assuming everything still compiles properly:

Acked-by: Daniel Vetter 

> ---
>  drivers/gpu/drm/drm_drv.c| 10 +-
>  drivers/gpu/drm/drm_pci.c|  8 +---
>  drivers/gpu/drm/drm_vram_helper_common.c |  4 ++--
>  include/drm/drm_device.h |  2 +-
>  include/drm/drm_drv.h|  6 +++---
>  include/drm/drm_legacy.h | 10 ++
>  include/drm/drm_pci.h|  4 ++--
>  7 files changed, 24 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> index 7b1a628d1f6e..41654427d258 100644
> --- a/drivers/gpu/drm/drm_drv.c
> +++ b/drivers/gpu/drm/drm_drv.c
> @@ -300,7 +300,7 @@ void drm_minor_release(struct drm_minor *minor)
>   *   kfree(priv);
>   *   }
>   *
> - *   static struct drm_driver driver_drm_driver = {
> + *   static const struct drm_driver driver_drm_driver = {
>   *   [...]
>   *   .release = driver_drm_release,
>   *   };
> @@ -612,7 +612,7 @@ static void drm_fs_inode_free(struct inode *inode)
>   * 0 on success, or error code on failure.
>   */
>  int drm_dev_init(struct drm_device *dev,
> -  struct drm_driver *driver,
> +  const struct drm_driver *driver,
>struct device *parent)
>  {
>   int ret;
> @@ -722,7 +722,7 @@ static void devm_drm_dev_init_release(void *data)
>   */
>  int devm_drm_dev_init(struct device *parent,
> struct drm_device *dev,
> -   struct drm_driver *driver)
> +   const struct drm_driver *driver)
>  {
>   int ret;
>  
> @@ -800,7 +800,7 @@ EXPORT_SYMBOL(drm_dev_fini);
>   * RETURNS:
>   * Pointer to new DRM device, or ERR_PTR on failure.
>   */
> -struct drm_device *drm_dev_alloc(struct drm_driver *driver,
> +struct drm_device *drm_dev_alloc(const struct drm_driver *driver,
>struct device *parent)
>  {
>   struct drm_device *dev;
> @@ -943,7 +943,7 @@ static void remove_compat_control_link(struct drm_device 
> *dev)
>   */
>  int drm_dev_register(struct drm_device *dev, unsigned long flags)
>  {
> - struct drm_driver *driver = dev->driver;
> + const struct drm_driver *driver = dev->driver;
>   int ret;
>  
>   if (drm_dev_needs_global_mutex(dev))
> diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c
> index 44805ac3177c..2ca7adf270c6 100644
> --- a/drivers/gpu/drm/drm_pci.c
> +++ b/drivers/gpu/drm/drm_pci.c
> @@ -215,7 +215,7 @@ void drm_pci_agp_destroy(struct drm_device *dev)
>   * Return: 0 on success or a negative error code on failure.
>   */
>  int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
> - struct drm_driver *driver)
> + const struct drm_driver *driver)
>  {
>   struct drm_device *dev;
>   int ret;
> @@ -274,7 +274,8 @@ EXPORT_SYMBOL(drm_get_pci_dev);
>   *
>   * Return: 0 on success or a negative error code on failure.
>   */
> -int drm_legacy_pci_init(struct drm_driver *driver, struct pci_driver 
> *pdriver)
> +int drm_legacy_pci_init(const struct drm_driver *driver,
> + struct pci_driver *pdriver)
>  {
>   struct pci_dev *pdev = NULL;
>   const struct pci_device_id *pid;
> @@ -319,7 +320,8 @@ EXPORT_SYMBOL(drm_legacy_pci_init);
>   * Unregister a DRM driver shadow-attached through drm_legacy_pci_init(). 
> This
>   * is deprecated and only used by dri1 drivers.
>   */
> -void drm_legacy_pci_exit(struct drm_driver *driver, struct pci_driver 
> *pdriver)
> +void drm_legacy_pci_exit(const struct drm_driver *driver,
> +  struct pci_driver *pdriver)
>  {
>   struct drm_device *dev, *tmp;
>   DRM_DEBUG("\n");
> diff --git a/drivers/gpu/drm/drm_vram_helper_common.c 
> b/drivers/gpu/drm/drm_vram_helper_common.c
> index 2000d9b33fd5..e93b04bbe2de 100644
> --- a/drivers/gpu/drm/drm_vram_helper_common.c
> +++ b/drivers/gpu/drm/drm_vram_helper_common.c
> @@ -29,11 +29,11 @@
>   *
>   * .. code-block:: c
>   *
> - *   struct file_operations fops ={
> + *   const struct file_operations fops ={
>   *   .owner = THIS_MODULE,
>   *   DRM_VRAM_MM_FILE_OPERATION
>   *   };
> - *   struct drm_driver drv = {
> + *   const struct drm_driver drv = {
>   *   .driver_feature = DRM_ ... ,
>   *   .fops = ,
>   *   DRM_GEM_VRAM_DRIVER
> diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h
> index 215b3472c773..6ed5d84e5f5d 100644
> --- a/include/drm/drm_device.h
> +++ 

Re: [PATCH/RFC 1/3] drm: Move legacy device list out of drm_driver

2020-02-22 Thread Daniel Vetter
On Sat, Feb 22, 2020 at 05:24:28PM +0200, Laurent Pinchart wrote:
> The drm_driver structure contains a single field (legacy_dev_list) that
> is modified by the DRM core, used to store a linked list of legacy DRM
> devices associated with the driver. In order to make the structure
> const, move the field out to a global variable. This requires locking
> access to the global where the local field didn't require serialization,
> but this only affects legacy drivers, and isn't in any hot path.
> 
> While at it, compile-out the legacy_dev_list field when DRM_LEGACY isn't
> defined.
> 
> Signed-off-by: Laurent Pinchart 
> ---
>  drivers/gpu/drm/drm_pci.c | 30 ++
>  include/drm/drm_device.h  |  2 ++
>  include/drm/drm_drv.h |  2 --
>  3 files changed, 24 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c
> index c6bb98729a26..44805ac3177c 100644
> --- a/drivers/gpu/drm/drm_pci.c
> +++ b/drivers/gpu/drm/drm_pci.c
> @@ -24,6 +24,8 @@
>  
>  #include 
>  #include 
> +#include 
> +#include 
>  #include 
>  #include 
>  
> @@ -36,6 +38,12 @@
>  #include "drm_internal.h"
>  #include "drm_legacy.h"
>  
> +#ifdef CONFIG_DRM_LEGACY
> +/* List of devices hanging off drivers with stealth attach. */
> +static LIST_HEAD(legacy_dev_list);
> +static DEFINE_MUTEX(legacy_dev_list_lock);
> +#endif
> +
>  /**
>   * drm_pci_alloc - Allocate a PCI consistent memory block, for DMA.
>   * @dev: DRM device
> @@ -236,10 +244,13 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct 
> pci_device_id *ent,
>   if (ret)
>   goto err_agp;
>  
> - /* No locking needed since shadow-attach is single-threaded since it may
> -  * only be called from the per-driver module init hook. */
> - if (drm_core_check_feature(dev, DRIVER_LEGACY))
> - list_add_tail(>legacy_dev_list, >legacy_dev_list);
> +#ifdef CONFIG_DRM_LEGACY
> + if (drm_core_check_feature(dev, DRIVER_LEGACY)) {
> + mutex_lock(_dev_list_lock);
> + list_add_tail(>legacy_dev_list, _dev_list);
> + mutex_unlock(_dev_list_lock);
> + }
> +#endif
>  
>   return 0;
>  
> @@ -275,7 +286,6 @@ int drm_legacy_pci_init(struct drm_driver *driver, struct 
> pci_driver *pdriver)
>   return -EINVAL;
>  
>   /* If not using KMS, fall back to stealth mode manual scanning. */
> - INIT_LIST_HEAD(>legacy_dev_list);
>   for (i = 0; pdriver->id_table[i].vendor != 0; i++) {
>   pid = >id_table[i];
>  
> @@ -317,11 +327,15 @@ void drm_legacy_pci_exit(struct drm_driver *driver, 
> struct pci_driver *pdriver)
>   if (!(driver->driver_features & DRIVER_LEGACY)) {
>   WARN_ON(1);
>   } else {
> - list_for_each_entry_safe(dev, tmp, >legacy_dev_list,
> + mutex_lock(_dev_list_lock);
> + list_for_each_entry_safe(dev, tmp, _dev_list,
>legacy_dev_list) {
> - list_del(>legacy_dev_list);
> - drm_put_dev(dev);
> + if (dev->driver == driver) {
> + list_del(>legacy_dev_list);
> + drm_put_dev(dev);

I checked whether this would result in any issues with the new mutex_lock,
but with the legacy model there's no hotunplug or anything like that, so
we never need to remove ourselves from this list coming from the other
direction. We just oops :-)

> + }
>   }
> + mutex_unlock(_dev_list_lock);
>   }
>   DRM_INFO("Module unloaded\n");
>  }
> diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h
> index bb60a949f416..215b3472c773 100644
> --- a/include/drm/drm_device.h
> +++ b/include/drm/drm_device.h
> @@ -51,12 +51,14 @@ enum switch_power_state {
>   * may contain multiple heads.
>   */
>  struct drm_device {
> +#ifdef CONFIG_DRM_LEGACY
>   /**
>* @legacy_dev_list:
>*
>* List of devices per driver for stealth attach cleanup
>*/
>   struct list_head legacy_dev_list;
> +#endif

We have a CONFIG_DRM_LEGACY dungeon already at the end of this struct, can
you pls move it there? Also drop the kerneldoc comment, we want to hide
this for good :-)

With that tiny bikeshed:

Reviewed-by: Daniel Vetter 

>  
>   /** @if_version: Highest interface version set */
>   int if_version;
> diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h
> index 97109df5beac..7dcf3b7bb5e6 100644
> --- a/include/drm/drm_drv.h
> +++ b/include/drm/drm_drv.h
> @@ -601,8 +601,6 @@ struct drm_driver {
>   /* Everything below here is for legacy driver, never use! */
>   /* private: */
>  
> - /* List of devices hanging off this driver with stealth attach. */
> - struct list_head legacy_dev_list;
>   int (*firstopen) (struct drm_device *);
>   void (*preclose) (struct drm_device *, struct drm_file *file_priv);
>   

[PATCH 3/3] drm/pci: Unexport drm_get_pci_dev

2020-02-22 Thread Daniel Vetter
Only user left is the shadow attach for legacy drivers.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_pci.c | 22 +++---
 include/drm/drm_pci.h | 11 ---
 2 files changed, 3 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c
index c6bb98729a26..cc5af271a1b1 100644
--- a/drivers/gpu/drm/drm_pci.c
+++ b/drivers/gpu/drm/drm_pci.c
@@ -75,7 +75,6 @@ drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, 
size_t size, size_t ali
 
return dmah;
 }
-
 EXPORT_SYMBOL(drm_pci_alloc);
 
 /**
@@ -191,23 +190,9 @@ void drm_pci_agp_destroy(struct drm_device *dev)
}
 }
 
-/**
- * drm_get_pci_dev - Register a PCI device with the DRM subsystem
- * @pdev: PCI device
- * @ent: entry from the PCI ID table that matches @pdev
- * @driver: DRM device driver
- *
- * Attempt to gets inter module "drm" information. If we are first
- * then register the character device and inter module information.
- * Try and register, if we fail to register, backout previous work.
- *
- * NOTE: This function is deprecated, please use drm_dev_alloc() and
- * drm_dev_register() instead and remove your _driver.load callback.
- *
- * Return: 0 on success or a negative error code on failure.
- */
-int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
-   struct drm_driver *driver)
+static int drm_get_pci_dev(struct pci_dev *pdev,
+  const struct pci_device_id *ent,
+  struct drm_driver *driver)
 {
struct drm_device *dev;
int ret;
@@ -250,7 +235,6 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct 
pci_device_id *ent,
drm_dev_put(dev);
return ret;
 }
-EXPORT_SYMBOL(drm_get_pci_dev);
 
 #ifdef CONFIG_DRM_LEGACY
 
diff --git a/include/drm/drm_pci.h b/include/drm/drm_pci.h
index 9031e217b506..3941b0255ecf 100644
--- a/include/drm/drm_pci.h
+++ b/include/drm/drm_pci.h
@@ -45,10 +45,6 @@ struct drm_dma_handle *drm_pci_alloc(struct drm_device *dev, 
size_t size,
 size_t align);
 void drm_pci_free(struct drm_device *dev, struct drm_dma_handle * dmah);
 
-int drm_get_pci_dev(struct pci_dev *pdev,
-   const struct pci_device_id *ent,
-   struct drm_driver *driver);
-
 #else
 
 static inline struct drm_dma_handle *drm_pci_alloc(struct drm_device *dev,
@@ -62,13 +58,6 @@ static inline void drm_pci_free(struct drm_device *dev,
 {
 }
 
-static inline int drm_get_pci_dev(struct pci_dev *pdev,
- const struct pci_device_id *ent,
- struct drm_driver *driver)
-{
-   return -ENOSYS;
-}
-
 #endif
 
 #endif /* _DRM_PCI_H_ */
-- 
2.24.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 2/3] drm/radeon: Inline drm_get_pci_dev

2020-02-22 Thread Daniel Vetter
It's the last user, and more importantly, it's the last non-legacy
user of anything in drm_pci.c.

The only tricky bit is the agp initialization. But a close look shows
that radeon does not use the drm_agp midlayer (the main use of that is
drm_bufs for legacy drivers), and instead could use the agp subsystem
directly (like nouveau does already). Hence we can just pull this in
too.

A further step would be to entirely drop the use of drm_device->agp,
but feels like too much churn just for this patch.

Signed-off-by: Daniel Vetter 
Cc: Alex Deucher 
Cc: "Christian König" 
Cc: "David (ChunMing) Zhou" 
Cc: amd-...@lists.freedesktop.org
---
 drivers/gpu/drm/radeon/radeon_drv.c | 43 +++--
 drivers/gpu/drm/radeon/radeon_kms.c |  6 
 2 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_drv.c 
b/drivers/gpu/drm/radeon/radeon_drv.c
index 49ce2e7d5f9e..59f8186a2415 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -37,6 +37,7 @@
 #include 
 #include 
 
+#include 
 #include 
 #include 
 #include 
@@ -322,6 +323,7 @@ static int radeon_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
 {
unsigned long flags = 0;
+   struct drm_device *dev;
int ret;
 
if (!ent)
@@ -362,7 +364,44 @@ static int radeon_pci_probe(struct pci_dev *pdev,
if (ret)
return ret;
 
-   return drm_get_pci_dev(pdev, ent, _driver);
+   dev = drm_dev_alloc(_driver, >dev);
+   if (IS_ERR(dev))
+   return PTR_ERR(dev);
+
+   ret = pci_enable_device(pdev);
+   if (ret)
+   goto err_free;
+
+   dev->pdev = pdev;
+#ifdef __alpha__
+   dev->hose = pdev->sysdata;
+#endif
+
+   pci_set_drvdata(pdev, dev);
+
+   if (pci_find_capability(dev->pdev, PCI_CAP_ID_AGP))
+   dev->agp = drm_agp_init(dev);
+   if (dev->agp) {
+   dev->agp->agp_mtrr = arch_phys_wc_add(
+   dev->agp->agp_info.aper_base,
+   dev->agp->agp_info.aper_size *
+   1024 * 1024);
+   }
+
+   ret = drm_dev_register(dev, ent->driver_data);
+   if (ret)
+   goto err_agp;
+
+   return 0;
+
+err_agp:
+   if (dev->agp)
+   arch_phys_wc_del(dev->agp->agp_mtrr);
+   kfree(dev->agp);
+   pci_disable_device(pdev);
+err_free:
+   drm_dev_put(dev);
+   return ret;
 }
 
 static void
@@ -562,7 +601,7 @@ static const struct file_operations radeon_driver_kms_fops 
= {
 
 static struct drm_driver kms_driver = {
.driver_features =
-   DRIVER_USE_AGP | DRIVER_GEM | DRIVER_RENDER,
+   DRIVER_GEM | DRIVER_RENDER,
.load = radeon_driver_load_kms,
.open = radeon_driver_open_kms,
.postclose = radeon_driver_postclose_kms,
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c 
b/drivers/gpu/drm/radeon/radeon_kms.c
index cab891f86dc0..58176db85952 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -32,6 +32,7 @@
 #include 
 #include 
 
+#include 
 #include 
 #include 
 #include 
@@ -77,6 +78,11 @@ void radeon_driver_unload_kms(struct drm_device *dev)
radeon_modeset_fini(rdev);
radeon_device_fini(rdev);
 
+   if (dev->agp)
+   arch_phys_wc_del(dev->agp->agp_mtrr);
+   kfree(dev->agp);
+   dev->agp = NULL;
+
 done_free:
kfree(rdev);
dev->dev_private = NULL;
-- 
2.24.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 1/3] drm/amdgpu: Drop DRIVER_USE_AGP

2020-02-22 Thread Daniel Vetter
This doesn't do anything except auto-init drm_agp support when you
call drm_get_pci_dev(). Which amdgpu stopped doing with

commit b58c11314a1706bf094c489ef5cb28f76478c704
Author: Alex Deucher 
Date:   Fri Jun 2 17:16:31 2017 -0400

drm/amdgpu: drop deprecated drm_get_pci_dev and drm_put_dev

No idea whether this was intentional or accidental breakage, but I
guess anyone who manages to boot a this modern gpu behind an agp
bridge deserves a price. A price I never expect anyone to ever collect
:-)

Cc: Alex Deucher 
Cc: "Christian König" 
Cc: Hawking Zhang 
Cc: Xiaojie Yuan 
Cc: Evan Quan 
Cc: "Tianci.Yin" 
Cc: "Marek Olšák" 
Cc: Hans de Goede 
Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 4598836c5fa4..6cea92017109 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -1379,7 +1379,7 @@ int amdgpu_file_to_fpriv(struct file *filp, struct 
amdgpu_fpriv **fpriv)
 
 static struct drm_driver kms_driver = {
.driver_features =
-   DRIVER_USE_AGP | DRIVER_ATOMIC |
+   DRIVER_ATOMIC |
DRIVER_GEM |
DRIVER_RENDER | DRIVER_MODESET | DRIVER_SYNCOBJ |
DRIVER_SYNCOBJ_TIMELINE,
-- 
2.24.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH 3/7] docs: fix broken references to text files

2020-02-22 Thread Daniel Vetter
On Sat, Feb 22, 2020 at 10:00:03AM +0100, Mauro Carvalho Chehab wrote:
> Several references got broken due to txt to ReST conversion.
> 
> Several of them can be automatically fixed with:
> 
>   scripts/documentation-file-ref-check --fix
> 
> Signed-off-by: Mauro Carvalho Chehab 
> ---
>  Documentation/admin-guide/kernel-parameters.txt  | 10 +-
>  Documentation/filesystems/cifs/cifsroot.txt  |  2 +-
>  Documentation/memory-barriers.txt|  2 +-
>  Documentation/process/submit-checklist.rst   |  2 +-
>  .../translations/it_IT/process/submit-checklist.rst  |  2 +-
>  Documentation/translations/ko_KR/memory-barriers.txt |  2 +-
>  .../translations/zh_CN/filesystems/sysfs.txt |  2 +-
>  .../translations/zh_CN/process/submit-checklist.rst  |  2 +-
>  Documentation/virt/kvm/arm/pvtime.rst|  2 +-
>  Documentation/virt/kvm/devices/vcpu.rst  |  2 +-
>  Documentation/virt/kvm/hypercalls.rst|  4 ++--
>  arch/powerpc/include/uapi/asm/kvm_para.h |  2 +-
>  drivers/gpu/drm/Kconfig  |  2 +-
>  drivers/gpu/drm/drm_ioctl.c  |  2 +-

These two look very correct. The patch that moved edid.rst seems to have
not updated a lot of references :-/

Acked-by: Daniel Vetter 

>  drivers/hwtracing/coresight/Kconfig  |  2 +-
>  fs/fat/Kconfig   |  8 
>  fs/fuse/Kconfig  |  2 +-
>  fs/fuse/dev.c|  2 +-
>  fs/nfs/Kconfig   |  2 +-
>  fs/overlayfs/Kconfig |  6 +++---
>  include/linux/mm.h   |  4 ++--
>  include/uapi/linux/ethtool_netlink.h |  2 +-
>  include/uapi/rdma/rdma_user_ioctl_cmds.h |  2 +-
>  mm/gup.c | 12 ++--
>  net/ipv4/Kconfig |  6 +++---
>  net/ipv4/ipconfig.c  |  2 +-
>  virt/kvm/arm/vgic/vgic-mmio-v3.c |  2 +-
>  virt/kvm/arm/vgic/vgic.h |  4 ++--
>  28 files changed, 47 insertions(+), 47 deletions(-)
> 
> diff --git a/Documentation/admin-guide/kernel-parameters.txt 
> b/Documentation/admin-guide/kernel-parameters.txt
> index 8be1d0bbfd16..e0fe9f70d22b 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -957,7 +957,7 @@
>   edid/1680x1050.bin, or edid/1920x1080.bin is given
>   and no file with the same name exists. Details and
>   instructions how to build your own EDID data are
> - available in Documentation/driver-api/edid.rst. An EDID
> + available in Documentation/admin-guide/edid.rst. An EDID
>   data set will only be used for a particular connector,
>   if its name and a colon are prepended to the EDID
>   name. Each connector may use a unique EDID data
> @@ -1884,7 +1884,7 @@
>   No delay
>  
>   ip= [IP_PNP]
> - See Documentation/filesystems/nfs/nfsroot.txt.
> + See Documentation/admin-guide/nfs/nfsroot.rst.
>  
>   ipcmni_extend   [KNL] Extend the maximum number of unique System V
>   IPC identifiers from 32,768 to 16,777,216.
> @@ -2863,13 +2863,13 @@
>   Default value is 0.
>  
>   nfsaddrs=   [NFS] Deprecated.  Use ip= instead.
> - See Documentation/filesystems/nfs/nfsroot.txt.
> + See Documentation/admin-guide/nfs/nfsroot.rst.
>  
>   nfsroot=[NFS] nfs root filesystem for disk-less boxes.
> - See Documentation/filesystems/nfs/nfsroot.txt.
> + See Documentation/admin-guide/nfs/nfsroot.rst.
>  
>   nfsrootdebug[NFS] enable nfsroot debugging messages.
> - See Documentation/filesystems/nfs/nfsroot.txt.
> + See Documentation/admin-guide/nfs/nfsroot.rst.
>  
>   nfs.callback_nr_threads=
>   [NFSv4] set the total number of threads that the
> diff --git a/Documentation/filesystems/cifs/cifsroot.txt 
> b/Documentation/filesystems/cifs/cifsroot.txt
> index 0fa1a2c36a40..947b7ec6ce9e 100644
> --- a/Documentation/filesystems/cifs/cifsroot.txt
> +++ b/Documentation/filesystems/cifs/cifsroot.txt
> @@ -13,7 +13,7 @@ network by utilizing SMB or CIFS protocol.
>  
>  In order to mount, the network stack will also need to be set up by
>  using 'ip=' config option. For more details, see
> -Documentation/filesystems/nfs/nfsroot.txt.
> +Documentation/admin-guide/nfs/nfsroot.rst.
>  
>  A CIFS root mount currently requires the 

[PATCH v7.1 09/54] drm/bridge: Extend bridge API to disable connector creation

2020-02-22 Thread Laurent Pinchart
Most bridge drivers create a DRM connector to model the connector at the
output of the bridge. This model is historical and has worked pretty
well so far, but causes several issues:

- It prevents supporting more complex display pipelines where DRM
connector operations are split over multiple components. For instance a
pipeline with a bridge connected to the DDC signals to read EDID data,
and another one connected to the HPD signal to detect connection and
disconnection, will not be possible to support through this model.

- It requires every bridge driver to implement similar connector
handling code, resulting in code duplication.

- It assumes that a bridge will either be wired to a connector or to
another bridge, but doesn't support bridges that can be used in both
positions very well (although there is some ad-hoc support for this in
the analogix_dp bridge driver).

In order to solve these issues, ownership of the connector should be
moved to the display controller driver (where it can be implemented
using helpers provided by the core).

Extend the bridge API to allow disabling connector creation in bridge
drivers as a first step towards the new model. The new flags argument to
the bridge .attach() operation allows instructing the bridge driver to
skip creating a connector. Unconditionally set the new flags argument to
0 for now to keep the existing behaviour, and modify all existing bridge
drivers to return an error when connector creation is not requested as
they don't support this feature yet.

The change is based on the following semantic patch, with manual review
and edits.

@ rule1 @
identifier funcs;
identifier fn;
@@
 struct drm_bridge_funcs funcs = {
...,
.attach = fn
 };

@ depends on rule1 @
identifier rule1.fn;
identifier bridge;
statement S, S1;
@@
 int fn(
struct drm_bridge *bridge
+   , enum drm_bridge_attach_flags flags
 )
 {
... when != S
+   if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
+   DRM_ERROR("Fix bridge driver to make connector optional!");
+   return -EINVAL;
+   }
+
S1
...
 }

@ depends on rule1 @
identifier rule1.fn;
identifier bridge, flags;
expression E1, E2, E3;
@@
 int fn(
struct drm_bridge *bridge,
enum drm_bridge_attach_flags flags
 ) {
 <...
 drm_bridge_attach(E1, E2, E3
+   , flags
 )
 ...>
 }

@@
expression E1, E2, E3;
@@
 drm_bridge_attach(E1, E2, E3
+   , 0
 )

Signed-off-by: Laurent Pinchart 
Reviewed-by: Boris Brezillon 
Acked-by: Sam Ravnborg 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
Acked-by: Daniel Vetter 
---
Changes since v7:

- Properly annotate DRM_BRIDGE_ATTACH_NO_CONNECTOR with %

Changes since v6:

- Update the drm_bridge overview documentation

Changes since v5:

- Handle parade-ps8640, tc358768 and tidss

Changes since v3:

- Print error message when DRM_BRIDGE_ATTACH_NO_CONNECTOR can't be
  honoured
- Fix semantic patch to correctly handle drm_bridge_attach() calls from
  within a bridge .attach() handler
- Include drm_print.h in tc358767.c and rcar_lvds.c

Changes since v2:

- Update commit message to the new flags argument
- Replace a leftover 'true' with 0
- Update msm edp and hdmi

Changes since v1:

- Replace the create_connector boolean with a flags bitmask
- Update ingenic driver
- Add semantic patch to commit message
---
 drivers/gpu/drm/arc/arcpgu_hdmi.c |  2 +-
 .../gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c  |  2 +-
 drivers/gpu/drm/bridge/adv7511/adv7511_drv.c  |  8 +++-
 .../drm/bridge/analogix/analogix-anx6345.c|  8 +++-
 .../drm/bridge/analogix/analogix-anx78xx.c|  8 +++-
 .../drm/bridge/analogix/analogix_dp_core.c| 10 --
 drivers/gpu/drm/bridge/cdns-dsi.c |  6 --
 drivers/gpu/drm/bridge/dumb-vga-dac.c |  8 +++-
 drivers/gpu/drm/bridge/lvds-codec.c   |  5 +++--
 .../bridge/megachips-stdp-ge-b850v3-fw.c  |  8 +++-
 drivers/gpu/drm/bridge/nxp-ptn3460.c  |  8 +++-
 drivers/gpu/drm/bridge/panel.c|  8 +++-
 drivers/gpu/drm/bridge/parade-ps8622.c|  8 +++-
 drivers/gpu/drm/bridge/parade-ps8640.c|  5 +++--
 drivers/gpu/drm/bridge/sii902x.c  |  8 +++-
 drivers/gpu/drm/bridge/sil-sii8620.c  |  3 ++-
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 10 --
 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c |  8 +---
 drivers/gpu/drm/bridge/tc358764.c |  8 +++-
 drivers/gpu/drm/bridge/tc358767.c |  9 -
 drivers/gpu/drm/bridge/tc358768.c |  6 --
 drivers/gpu/drm/bridge/thc63lvd1024.c |  5 +++--
 drivers/gpu/drm/bridge/ti-sn65dsi86.c |  8 +++-
 drivers/gpu/drm/bridge/ti-tfp410.c|  8 +++-
 drivers/gpu/drm/drm_bridge.c  | 20 +--
 drivers/gpu/drm/drm_simple_kms_helper.c   |  2 +-
 

[PATCH v7.1 20/54] drm: Add helper to create a connector for a chain of bridges

2020-02-22 Thread Laurent Pinchart
Most bridge drivers create a DRM connector to model the connector at the
output of the bridge. This model is historical and has worked pretty
well so far, but causes several issues:

- It prevents supporting more complex display pipelines where DRM
connector operations are split over multiple components. For instance a
pipeline with a bridge connected to the DDC signals to read EDID data,
and another one connected to the HPD signal to detect connection and
disconnection, will not be possible to support through this model.

- It requires every bridge driver to implement similar connector
handling code, resulting in code duplication.

- It assumes that a bridge will either be wired to a connector or to
another bridge, but doesn't support bridges that can be used in both
positions very well (although there is some ad-hoc support for this in
the analogix_dp bridge driver).

In order to solve these issues, ownership of the connector needs to be
moved to the display controller driver.

To avoid code duplication in display controller drivers, add a new
helper to create and manage a DRM connector backed by a chain of
bridges. All connector operations are delegating to the appropriate
bridge in the chain.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Boris Brezillon 
Acked-by: Sam Ravnborg 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
Changes since v7:

- Add a mention of drm_bridge_connector_init() in the bridge overview
  documentation

Changes since v5:

- Fix the interlace_allowed flag logic

Changes since v4:

- Set the connector interlace_allowed flag based on interlaced support
  in bridges

Changes since v2:

- Fixed typo in documentation
- Rebased on top of Boris' drm_bridge chaining rework
- Pass drm_encoder instead of brm_bridge to drm_bridge_connector_init()

Changes since v1:

- Removed the unused MAX_EDID macro
- Removed the unused drm_bridge_connector.hdmi_mode field
- Use drm_connector_init_with_ddc()
---
 Documentation/gpu/drm-kms-helpers.rst  |  12 +
 drivers/gpu/drm/Makefile   |   3 +-
 drivers/gpu/drm/drm_bridge.c   |   6 +
 drivers/gpu/drm/drm_bridge_connector.c | 379 +
 include/drm/drm_bridge_connector.h |  18 ++
 5 files changed, 417 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/drm_bridge_connector.c
 create mode 100644 include/drm/drm_bridge_connector.h

diff --git a/Documentation/gpu/drm-kms-helpers.rst 
b/Documentation/gpu/drm-kms-helpers.rst
index fe155c6ae175..ee730457bf4e 100644
--- a/Documentation/gpu/drm-kms-helpers.rst
+++ b/Documentation/gpu/drm-kms-helpers.rst
@@ -145,6 +145,12 @@ Bridge Operations
 .. kernel-doc:: drivers/gpu/drm/drm_bridge.c
:doc: bridge operations
 
+Bridge Connector Helper
+---
+
+.. kernel-doc:: drivers/gpu/drm/drm_bridge_connector.c
+   :doc: overview
+
 
 Bridge Helper Reference
 -
@@ -155,6 +161,12 @@ Bridge Helper Reference
 .. kernel-doc:: drivers/gpu/drm/drm_bridge.c
:export:
 
+Bridge Connector Helper Reference
+-
+
+.. kernel-doc:: drivers/gpu/drm/drm_bridge_connector.c
+   :export:
+
 Panel-Bridge Helper Reference
 -
 
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index ca0ca775d37f..7f72ef5e7811 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -39,7 +39,8 @@ obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o
 drm_ttm_helper-y := drm_gem_ttm_helper.o
 obj-$(CONFIG_DRM_TTM_HELPER) += drm_ttm_helper.o
 
-drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_dsc.o 
drm_probe_helper.o \
+drm_kms_helper-y := drm_bridge_connector.o drm_crtc_helper.o drm_dp_helper.o \
+   drm_dsc.o drm_probe_helper.o \
drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
drm_kms_helper_common.o drm_dp_dual_mode_helper.o \
drm_simple_kms_helper.o drm_modeset_helper.o \
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index dae33fc1b05b..9be11f383440 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -79,6 +79,12 @@
  * requires no intervention from the driver. For other drivers, the relevant
  * DRM bridge chain functions shall be called manually.
  *
+ * Bridges also participate in implementing the _connector at the end of
+ * the bridge chain. Display drivers may use the drm_bridge_connector_init()
+ * helper to create the _connector, or implement it manually on top of the
+ * connector-related operations exposed by the bridge (see the overview
+ * documentation of bridge operations for more details).
+ *
  * _bridge, like _panel, aren't _mode_object entities like planes,
  * CRTCs, encoders or connectors and hence are not visible to userspace. They
  * just provide additional hooks to get the desired output at the end of the
diff --git a/drivers/gpu/drm/drm_bridge_connector.c 

[PATCH v7.1 06/54] drm/bridge: Improve overview documentation

2020-02-22 Thread Laurent Pinchart
Clean up the drm_bridge overview documentation, and expand the
operations documentation to provide more details on API usage.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Daniel Vetter 
---
Change since v7:

- Detail how bridge operations are used by atomic helpers
---
 Documentation/gpu/drm-kms-helpers.rst |   6 +-
 drivers/gpu/drm/drm_bridge.c  | 101 +++---
 2 files changed, 79 insertions(+), 28 deletions(-)

diff --git a/Documentation/gpu/drm-kms-helpers.rst 
b/Documentation/gpu/drm-kms-helpers.rst
index 9668a7fe2408..fe155c6ae175 100644
--- a/Documentation/gpu/drm-kms-helpers.rst
+++ b/Documentation/gpu/drm-kms-helpers.rst
@@ -139,11 +139,11 @@ Overview
 .. kernel-doc:: drivers/gpu/drm/drm_bridge.c
:doc: overview
 
-Default bridge callback sequence
-
+Bridge Operations
+-
 
 .. kernel-doc:: drivers/gpu/drm/drm_bridge.c
-   :doc: bridge callbacks
+   :doc: bridge operations
 
 
 Bridge Helper Reference
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 68ab933ee430..52dfc67a6cf8 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -39,26 +39,50 @@
  * encoder chain.
  *
  * A bridge is always attached to a single _encoder at a time, but can be
- * either connected to it directly, or through an intermediate bridge::
- *
- * encoder ---> bridge B ---> bridge A
- *
- * Here, the output of the encoder feeds to bridge B, and that furthers feeds 
to
- * bridge A.
- *
- * The driver using the bridge is responsible to make the associations between
- * the encoder and bridges. Once these links are made, the bridges will
- * participate along with encoder functions to perform mode_set/enable/disable
- * through the ops provided in _bridge_funcs.
- *
- * drm_bridge, like drm_panel, aren't drm_mode_object entities like planes,
+ * either connected to it directly, or through a chain of bridges::
+ *
+ * [ CRTC ---> ] Encoder ---> Bridge A ---> Bridge B
+ *
+ * Here, the output of the encoder feeds to bridge A, and that furthers feeds 
to
+ * bridge B. Bridge chains can be arbitrarily long, and shall be fully linear:
+ * Chaining multiple bridges to the output of a bridge, or the same bridge to
+ * the output of different bridges, is not supported.
+ *
+ * Display drivers are responsible for linking encoders with the first bridge
+ * in the chains. This is done by acquiring the appropriate bridge with
+ * of_drm_find_bridge() or drm_of_find_panel_or_bridge(), or creating it for a
+ * panel with drm_panel_bridge_add_typed() (or the managed version
+ * devm_drm_panel_bridge_add_typed()). Once acquired, the bridge shall be
+ * attached to the encoder with a call to drm_bridge_attach().
+ *
+ * Bridges are responsible for linking themselves with the next bridge in the
+ * chain, if any. This is done the same way as for encoders, with the call to
+ * drm_bridge_attach() occurring in the _bridge_funcs.attach operation.
+ *
+ * Once these links are created, the bridges can participate along with encoder
+ * functions to perform mode validation and fixup (through
+ * drm_bridge_chain_mode_valid() and drm_atomic_bridge_chain_check()), mode
+ * setting (through drm_bridge_chain_mode_set()), enable (through
+ * drm_atomic_bridge_chain_pre_enable() and drm_atomic_bridge_chain_enable())
+ * and disable (through drm_atomic_bridge_chain_disable() and
+ * drm_atomic_bridge_chain_post_disable()). Those functions call the
+ * corresponding operations provided in _bridge_funcs in sequence for all
+ * bridges in the chain.
+ *
+ * For display drivers that use the atomic helpers
+ * drm_atomic_helper_check_modeset(),
+ * drm_atomic_helper_commit_modeset_enables() and
+ * drm_atomic_helper_commit_modeset_disables() (either directly in hand-rolled
+ * commit check and commit tail handlers, or through the higher-level
+ * drm_atomic_helper_check() and drm_atomic_helper_commit_tail() or
+ * drm_atomic_helper_commit_tail_rpm() helpers), this is done transparently and
+ * requires no intervention from the driver. For other drivers, the relevant
+ * DRM bridge chain functions shall be called manually.
+ *
+ * _bridge, like _panel, aren't _mode_object entities like planes,
  * CRTCs, encoders or connectors and hence are not visible to userspace. They
  * just provide additional hooks to get the desired output at the end of the
  * encoder chain.
- *
- * Bridges can also be chained up using the _bridge.chain_node field.
- *
- * Both legacy CRTC helpers and the new atomic modeset helpers support bridges.
  */
 
 static DEFINE_MUTEX(bridge_lock);
@@ -212,14 +236,41 @@ void drm_bridge_detach(struct drm_bridge *bridge)
 }
 
 /**
- * DOC: bridge callbacks
- *
- * The _bridge_funcs ops are populated by the bridge driver. The DRM
- * internals (atomic and CRTC helpers) use the helpers defined in drm_bridge.c
- * These helpers call a specific _bridge_funcs op for all the bridges
- * during encoder 

Re: [PATCH v7 20/54] drm: Add helper to create a connector for a chain of bridges

2020-02-22 Thread Daniel Vetter
On Sat, Feb 22, 2020 at 4:01 PM Laurent Pinchart
 wrote:
>
> Most bridge drivers create a DRM connector to model the connector at the
> output of the bridge. This model is historical and has worked pretty
> well so far, but causes several issues:
>
> - It prevents supporting more complex display pipelines where DRM
> connector operations are split over multiple components. For instance a
> pipeline with a bridge connected to the DDC signals to read EDID data,
> and another one connected to the HPD signal to detect connection and
> disconnection, will not be possible to support through this model.
>
> - It requires every bridge driver to implement similar connector
> handling code, resulting in code duplication.
>
> - It assumes that a bridge will either be wired to a connector or to
> another bridge, but doesn't support bridges that can be used in both
> positions very well (although there is some ad-hoc support for this in
> the analogix_dp bridge driver).
>
> In order to solve these issues, ownership of the connector needs to be
> moved to the display controller driver.
>
> To avoid code duplication in display controller drivers, add a new
> helper to create and manage a DRM connector backed by a chain of
> bridges. All connector operations are delegating to the appropriate
> bridge in the chain.
>
> Signed-off-by: Laurent Pinchart 
> Reviewed-by: Boris Brezillon 
> Acked-by: Sam Ravnborg 
> Tested-by: Sebastian Reichel 
> Reviewed-by: Sebastian Reichel 

So in your updated bridge doc patch I pointed out that a clarification
is missing, and that the automatic stuff only happens if you use the
right atomic helpers.

I think in exact that place this patch here should also add a new
paragraph explaining that the output probing magic of bridges only
happens if you use it, pointing at  this connector helper here. Some
of the kerneldoc in here could then in turn point at the underlying
bridge functions they're building on top of.

With that I think all the (new) pieces are well documented, and more
importantly, well-connected in the docs.

Cheers, Daniel

> ---
> Changes since v5:
>
> - Fix the interlace_allowed flag logic
>
> Changes since v4:
>
> - Set the connector interlace_allowed flag based on interlaced support
>   in bridges
>
> Changes since v2:
>
> - Fixed typo in documentation
> - Rebased on top of Boris' drm_bridge chaining rework
> - Pass drm_encoder instead of brm_bridge to drm_bridge_connector_init()
>
> Changes since v1:
>
> - Removed the unused MAX_EDID macro
> - Removed the unused drm_bridge_connector.hdmi_mode field
> - Use drm_connector_init_with_ddc()
> ---
>  Documentation/gpu/drm-kms-helpers.rst  |  12 +
>  drivers/gpu/drm/Makefile   |   3 +-
>  drivers/gpu/drm/drm_bridge_connector.c | 379 +
>  include/drm/drm_bridge_connector.h |  18 ++
>  4 files changed, 411 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpu/drm/drm_bridge_connector.c
>  create mode 100644 include/drm/drm_bridge_connector.h
>
> diff --git a/Documentation/gpu/drm-kms-helpers.rst 
> b/Documentation/gpu/drm-kms-helpers.rst
> index fe155c6ae175..ee730457bf4e 100644
> --- a/Documentation/gpu/drm-kms-helpers.rst
> +++ b/Documentation/gpu/drm-kms-helpers.rst
> @@ -145,6 +145,12 @@ Bridge Operations
>  .. kernel-doc:: drivers/gpu/drm/drm_bridge.c
> :doc: bridge operations
>
> +Bridge Connector Helper
> +---
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_bridge_connector.c
> +   :doc: overview
> +
>
>  Bridge Helper Reference
>  -
> @@ -155,6 +161,12 @@ Bridge Helper Reference
>  .. kernel-doc:: drivers/gpu/drm/drm_bridge.c
> :export:
>
> +Bridge Connector Helper Reference
> +-
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_bridge_connector.c
> +   :export:
> +
>  Panel-Bridge Helper Reference
>  -
>
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index ca0ca775d37f..7f72ef5e7811 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -39,7 +39,8 @@ obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o
>  drm_ttm_helper-y := drm_gem_ttm_helper.o
>  obj-$(CONFIG_DRM_TTM_HELPER) += drm_ttm_helper.o
>
> -drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_dsc.o 
> drm_probe_helper.o \
> +drm_kms_helper-y := drm_bridge_connector.o drm_crtc_helper.o drm_dp_helper.o 
> \
> +   drm_dsc.o drm_probe_helper.o \
> drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
> drm_kms_helper_common.o drm_dp_dual_mode_helper.o \
> drm_simple_kms_helper.o drm_modeset_helper.o \
> diff --git a/drivers/gpu/drm/drm_bridge_connector.c 
> b/drivers/gpu/drm/drm_bridge_connector.c
> new file mode 100644
> index ..c6994fe673f3
> --- /dev/null
> +++ b/drivers/gpu/drm/drm_bridge_connector.c
> @@ -0,0 +1,379 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 

Re: [PATCH v7 07/54] drm/bridge: Add connector-related bridge operations and data

2020-02-22 Thread Daniel Vetter
On Sat, Feb 22, 2020 at 4:01 PM Laurent Pinchart
 wrote:
>
> To support implementation of DRM connectors on top of DRM bridges
> instead of by bridges, the drm_bridge needs to expose new operations and
> data:
>
> - Output detection, hot-plug notification, mode retrieval and EDID
>   retrieval operations
> - Bitmask of supported operations
> - Bridge output type
> - I2C adapter for DDC access
>
> Add and document these.
>
> Three new bridge helper functions are also added to handle hot plug
> notification in a way that is as transparent as possible for the
> bridges.
>
> Signed-off-by: Laurent Pinchart 
> Reviewed-by: Boris Brezillon 
> Reviewed-by: Sam Ravnborg 
> Tested-by: Sebastian Reichel 
> Reviewed-by: Sebastian Reichel 
> ---
> Changes since v6:
>
> - Don't check for NULL bridge in drm_bridge_hpd_enable() and
>   drm_bridge_hpd_disable()
>
> Changes since v3:
>
> - Fix typos
>
> Changes since v2:
>
> - Add wrappers around the .detect(), .get_modes() and .get_edid()
>   operations
> - Warn bridge drivers about valid usage of the connector argument to
>   .get_modes() and .get_edid()
>
> Changes since v1:
>
> - Make .hpd_enable() and .hpd_disable() optional
> - Rename .lost_hotplug() to .hpd_notify()
> - Add ddc field to drm_bridge
> ---
>  drivers/gpu/drm/drm_bridge.c | 201 ++-
>  include/drm/drm_bridge.h | 192 -
>  2 files changed, 391 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index 5f55a9e17a7c..d236984a963e 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -82,6 +82,8 @@ static LIST_HEAD(bridge_list);
>   */
>  void drm_bridge_add(struct drm_bridge *bridge)
>  {
> +   mutex_init(>hpd_mutex);
> +
> mutex_lock(_lock);
> list_add_tail(>list, _list);
> mutex_unlock(_lock);
> @@ -98,6 +100,8 @@ void drm_bridge_remove(struct drm_bridge *bridge)
> mutex_lock(_lock);
> list_del_init(>list);
> mutex_unlock(_lock);
> +
> +   mutex_destroy(>hpd_mutex);
>  }
>  EXPORT_SYMBOL(drm_bridge_remove);
>
> @@ -228,7 +232,7 @@ void drm_bridge_detach(struct drm_bridge *bridge)
>   * Bridge drivers expose operations through the _bridge_funcs structure.
>   * The DRM internals (atomic and CRTC helpers) use the helpers defined in
>   * drm_bridge.c to call bridge operations. Those operations are divided in
> - * two big categories to support different parts of the bridge usage.
> + * three big categories to support different parts of the bridge usage.
>   *
>   * - The encoder-related operations support control of the bridges in the
>   *   chain, and are roughly counterparts to the _encoder_helper_funcs
> @@ -258,6 +262,43 @@ void drm_bridge_detach(struct drm_bridge *bridge)
>   *   implement them shall thus also implement the atomic version of the
>   *   encoder-related operations. This feature is not supported by the legacy
>   *   CRTC helpers.
> + *
> + * - The connector-related operations support implementing a _connector
> + *   based on a chain of bridges. DRM bridges traditionally create a
> + *   _connector for bridges meant to be used at the end of the chain. 
> This
> + *   puts additional burden on bridge drivers, especially for bridges that 
> may
> + *   be used in the middle of a chain or at the end of it. Furthermore, it
> + *   requires all operations of the _connector to be handled by a single
> + *   bridge, which doesn't always match the hardware architecture.
> + *
> + *   To simplify bridge drivers and make the connector implementation more
> + *   flexible, a new model allows bridges to unconditionally skip creation of
> + *   _connector and instead expose _bridge_funcs operations to 
> support
> + *   an externally-implemented _connector. Those operations are
> + *   _bridge_funcs.detect, _bridge_funcs.get_modes,
> + *   _bridge_funcs.get_edid, _bridge_funcs.hpd_notify,
> + *   _bridge_funcs.hpd_enable and _bridge_funcs.hpd_disable. When
> + *   implemented, display drivers shall create a _connector instance for
> + *   each chain of bridges, and implement those connector instances based on
> + *   the bridge connector operations.
> + *
> + *   Bridge drivers shall implement the connector-related operations for all
> + *   the features that the bridge hardware support. For instance, if a bridge
> + *   supports reading EDID, the _bridge_funcs.get_edid shall be
> + *   implemented. This however doesn't mean that the DDC lines are wired to 
> the
> + *   bridge on a particular platform, as they could also be connected to an 
> I2C
> + *   controller of the SoC. Support for the connector-related operations on 
> the
> + *   running platform is reported through the _bridge.ops flags. Bridge
> + *   drivers shall detect which operations they can support on the platform
> + *   (usually this information is provided by ACPI or DT), and set the
> + *   _bridge.ops flags for all 

Re: [PATCH v7 06/54] drm/bridge: Improve overview documentation

2020-02-22 Thread Laurent Pinchart
Hi Daniel,

On Sat, Feb 22, 2020 at 04:32:58PM +0100, Daniel Vetter wrote:
> On Sat, Feb 22, 2020 at 4:01 PM Laurent Pinchart wrote:
> >
> > Clean up the drm_bridge overview documentation, and expand the
> > operations documentation to provide more details on API usage.
> >
> > Signed-off-by: Laurent Pinchart 
> > ---
> >  Documentation/gpu/drm-kms-helpers.rst |  6 +--
> >  drivers/gpu/drm/drm_bridge.c  | 76 ---
> >  2 files changed, 60 insertions(+), 22 deletions(-)
> >
> > diff --git a/Documentation/gpu/drm-kms-helpers.rst 
> > b/Documentation/gpu/drm-kms-helpers.rst
> > index 9668a7fe2408..fe155c6ae175 100644
> > --- a/Documentation/gpu/drm-kms-helpers.rst
> > +++ b/Documentation/gpu/drm-kms-helpers.rst
> > @@ -139,11 +139,11 @@ Overview
> >  .. kernel-doc:: drivers/gpu/drm/drm_bridge.c
> > :doc: overview
> >
> > -Default bridge callback sequence
> > -
> > +Bridge Operations
> > +-
> >
> >  .. kernel-doc:: drivers/gpu/drm/drm_bridge.c
> > -   :doc: bridge callbacks
> > +   :doc: bridge operations
> >
> >
> >  Bridge Helper Reference
> > diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> > index 68ab933ee430..5f55a9e17a7c 100644
> > --- a/drivers/gpu/drm/drm_bridge.c
> > +++ b/drivers/gpu/drm/drm_bridge.c
> > @@ -39,25 +39,36 @@
> >   * encoder chain.
> >   *
> >   * A bridge is always attached to a single _encoder at a time, but can 
> > be
> > - * either connected to it directly, or through an intermediate bridge::
> > + * either connected to it directly, or through a chain of bridges::
> >   *
> > - * encoder ---> bridge B ---> bridge A
> > + * [ CRTC ---> ] Encoder ---> Bridge A ---> Bridge B
> >   *
> > - * Here, the output of the encoder feeds to bridge B, and that furthers 
> > feeds to
> > - * bridge A.
> > + * Here, the output of the encoder feeds to bridge A, and that furthers 
> > feeds to
> > + * bridge B. Bridge chains can be arbitrarily long, and shall be fully 
> > linear:
> > + * Chaining multiple bridges to the output of a bridge, or the same bridge 
> > to
> > + * the output of different bridges, is not supported.
> >   *
> > - * The driver using the bridge is responsible to make the associations 
> > between
> > - * the encoder and bridges. Once these links are made, the bridges will
> > - * participate along with encoder functions to perform 
> > mode_set/enable/disable
> > - * through the ops provided in _bridge_funcs.
> > + * Display drivers are responsible for linking encoders with the first 
> > bridge
> > + * in the chains. This is done by acquiring the appropriate bridge with
> > + * of_drm_find_bridge() or drm_of_find_panel_or_bridge(), or creating it 
> > for a
> > + * panel with drm_panel_bridge_add_typed() (or the managed version
> > + * devm_drm_panel_bridge_add_typed()). Once acquired, the bridge shall be
> > + * attached to the encoder with a call to drm_bridge_attach().
> >   *
> > - * drm_bridge, like drm_panel, aren't drm_mode_object entities like planes,
> > + * Bridges are responsible for linking themselves with the next bridge in 
> > the
> > + * chain, if any. This is done the same way as for encoders, with the call 
> > to
> > + * drm_bridge_attach() occurring in the _bridge_funcs.attach operation.
> > + *
> > + * Once these links are created, the bridges will automatically participate
> > + * along with encoder functions to perform mode setting, enable and disable
> > + * through the corresponding operations provided in _bridge_funcs. This
> > + * requires no intervention from display drivers.
> 
> This is not quite correct, since this fully automatic behaviour only
> happens if you're using the drm_atomic_helper_modeset_disables and
> drm_atomic_helper_modeset_enables functions. If you roll your own
> (which is totally fine, that's why atomic helpers are modular), you
> need to call the relevant bridge functions yourself. I think would be
> good to clarify that and add links to the relevant bridge functions in
> a sentence here too. At least the bridge chain functions involved in
> this modeset stuff. Also, probe side only happens if you use
> drm_atomic_helper_check_modeset(), good to mention that too and the
> set of relevant bridge chain helpers for ti.

Very good point, I'll fix this in v7.1.

> > + * _bridge, like _panel, aren't _mode_object entities like 
> > planes,
> >   * CRTCs, encoders or connectors and hence are not visible to userspace. 
> > They
> >   * just provide additional hooks to get the desired output at the end of 
> > the
> >   * encoder chain.
> >   *
> > - * Bridges can also be chained up using the _bridge.chain_node field.
> > - *
> >   * Both legacy CRTC helpers and the new atomic modeset helpers support 
> > bridges.
> >   */
> >
> > @@ -212,14 +223,41 @@ void drm_bridge_detach(struct drm_bridge *bridge)
> >  }
> >
> >  /**
> > - * DOC: bridge callbacks
> > - *
> > - * The _bridge_funcs ops are populated by the bridge 

Re: [PATCH v7 06/54] drm/bridge: Improve overview documentation

2020-02-22 Thread Daniel Vetter
On Sat, Feb 22, 2020 at 4:01 PM Laurent Pinchart
 wrote:
>
> Clean up the drm_bridge overview documentation, and expand the
> operations documentation to provide more details on API usage.
>
> Signed-off-by: Laurent Pinchart 
> ---
>  Documentation/gpu/drm-kms-helpers.rst |  6 +--
>  drivers/gpu/drm/drm_bridge.c  | 76 ---
>  2 files changed, 60 insertions(+), 22 deletions(-)
>
> diff --git a/Documentation/gpu/drm-kms-helpers.rst 
> b/Documentation/gpu/drm-kms-helpers.rst
> index 9668a7fe2408..fe155c6ae175 100644
> --- a/Documentation/gpu/drm-kms-helpers.rst
> +++ b/Documentation/gpu/drm-kms-helpers.rst
> @@ -139,11 +139,11 @@ Overview
>  .. kernel-doc:: drivers/gpu/drm/drm_bridge.c
> :doc: overview
>
> -Default bridge callback sequence
> -
> +Bridge Operations
> +-
>
>  .. kernel-doc:: drivers/gpu/drm/drm_bridge.c
> -   :doc: bridge callbacks
> +   :doc: bridge operations
>
>
>  Bridge Helper Reference
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index 68ab933ee430..5f55a9e17a7c 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -39,25 +39,36 @@
>   * encoder chain.
>   *
>   * A bridge is always attached to a single _encoder at a time, but can be
> - * either connected to it directly, or through an intermediate bridge::
> + * either connected to it directly, or through a chain of bridges::
>   *
> - * encoder ---> bridge B ---> bridge A
> + * [ CRTC ---> ] Encoder ---> Bridge A ---> Bridge B
>   *
> - * Here, the output of the encoder feeds to bridge B, and that furthers 
> feeds to
> - * bridge A.
> + * Here, the output of the encoder feeds to bridge A, and that furthers 
> feeds to
> + * bridge B. Bridge chains can be arbitrarily long, and shall be fully 
> linear:
> + * Chaining multiple bridges to the output of a bridge, or the same bridge to
> + * the output of different bridges, is not supported.
>   *
> - * The driver using the bridge is responsible to make the associations 
> between
> - * the encoder and bridges. Once these links are made, the bridges will
> - * participate along with encoder functions to perform 
> mode_set/enable/disable
> - * through the ops provided in _bridge_funcs.
> + * Display drivers are responsible for linking encoders with the first bridge
> + * in the chains. This is done by acquiring the appropriate bridge with
> + * of_drm_find_bridge() or drm_of_find_panel_or_bridge(), or creating it for 
> a
> + * panel with drm_panel_bridge_add_typed() (or the managed version
> + * devm_drm_panel_bridge_add_typed()). Once acquired, the bridge shall be
> + * attached to the encoder with a call to drm_bridge_attach().
>   *
> - * drm_bridge, like drm_panel, aren't drm_mode_object entities like planes,
> + * Bridges are responsible for linking themselves with the next bridge in the
> + * chain, if any. This is done the same way as for encoders, with the call to
> + * drm_bridge_attach() occurring in the _bridge_funcs.attach operation.
> + *
> + * Once these links are created, the bridges will automatically participate
> + * along with encoder functions to perform mode setting, enable and disable
> + * through the corresponding operations provided in _bridge_funcs. This
> + * requires no intervention from display drivers.

This is not quite correct, since this fully automatic behaviour only
happens if you're using the drm_atomic_helper_modeset_disables and
drm_atomic_helper_modeset_enables functions. If you roll your own
(which is totally fine, that's why atomic helpers are modular), you
need to call the relevant bridge functions yourself. I think would be
good to clarify that and add links to the relevant bridge functions in
a sentence here too. At least the bridge chain functions involved in
this modeset stuff. Also, probe side only happens if you use
drm_atomic_helper_check_modeset(), good to mention that too and the
set of relevant bridge chain helpers for ti.

> + * _bridge, like _panel, aren't _mode_object entities like 
> planes,
>   * CRTCs, encoders or connectors and hence are not visible to userspace. They
>   * just provide additional hooks to get the desired output at the end of the
>   * encoder chain.
>   *
> - * Bridges can also be chained up using the _bridge.chain_node field.
> - *
>   * Both legacy CRTC helpers and the new atomic modeset helpers support 
> bridges.
>   */
>
> @@ -212,14 +223,41 @@ void drm_bridge_detach(struct drm_bridge *bridge)
>  }
>
>  /**
> - * DOC: bridge callbacks
> - *
> - * The _bridge_funcs ops are populated by the bridge driver. The DRM
> - * internals (atomic and CRTC helpers) use the helpers defined in 
> drm_bridge.c
> - * These helpers call a specific _bridge_funcs op for all the bridges
> - * during encoder configuration.
> - *
> - * For detailed specification of the bridge callbacks see _bridge_funcs.
> + * DOC: bridge operations
> + *
> + * Bridge drivers expose operations 

[PATCH/RFC 1/3] drm: Move legacy device list out of drm_driver

2020-02-22 Thread Laurent Pinchart
The drm_driver structure contains a single field (legacy_dev_list) that
is modified by the DRM core, used to store a linked list of legacy DRM
devices associated with the driver. In order to make the structure
const, move the field out to a global variable. This requires locking
access to the global where the local field didn't require serialization,
but this only affects legacy drivers, and isn't in any hot path.

While at it, compile-out the legacy_dev_list field when DRM_LEGACY isn't
defined.

Signed-off-by: Laurent Pinchart 
---
 drivers/gpu/drm/drm_pci.c | 30 ++
 include/drm/drm_device.h  |  2 ++
 include/drm/drm_drv.h |  2 --
 3 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c
index c6bb98729a26..44805ac3177c 100644
--- a/drivers/gpu/drm/drm_pci.c
+++ b/drivers/gpu/drm/drm_pci.c
@@ -24,6 +24,8 @@
 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 
@@ -36,6 +38,12 @@
 #include "drm_internal.h"
 #include "drm_legacy.h"
 
+#ifdef CONFIG_DRM_LEGACY
+/* List of devices hanging off drivers with stealth attach. */
+static LIST_HEAD(legacy_dev_list);
+static DEFINE_MUTEX(legacy_dev_list_lock);
+#endif
+
 /**
  * drm_pci_alloc - Allocate a PCI consistent memory block, for DMA.
  * @dev: DRM device
@@ -236,10 +244,13 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct 
pci_device_id *ent,
if (ret)
goto err_agp;
 
-   /* No locking needed since shadow-attach is single-threaded since it may
-* only be called from the per-driver module init hook. */
-   if (drm_core_check_feature(dev, DRIVER_LEGACY))
-   list_add_tail(>legacy_dev_list, >legacy_dev_list);
+#ifdef CONFIG_DRM_LEGACY
+   if (drm_core_check_feature(dev, DRIVER_LEGACY)) {
+   mutex_lock(_dev_list_lock);
+   list_add_tail(>legacy_dev_list, _dev_list);
+   mutex_unlock(_dev_list_lock);
+   }
+#endif
 
return 0;
 
@@ -275,7 +286,6 @@ int drm_legacy_pci_init(struct drm_driver *driver, struct 
pci_driver *pdriver)
return -EINVAL;
 
/* If not using KMS, fall back to stealth mode manual scanning. */
-   INIT_LIST_HEAD(>legacy_dev_list);
for (i = 0; pdriver->id_table[i].vendor != 0; i++) {
pid = >id_table[i];
 
@@ -317,11 +327,15 @@ void drm_legacy_pci_exit(struct drm_driver *driver, 
struct pci_driver *pdriver)
if (!(driver->driver_features & DRIVER_LEGACY)) {
WARN_ON(1);
} else {
-   list_for_each_entry_safe(dev, tmp, >legacy_dev_list,
+   mutex_lock(_dev_list_lock);
+   list_for_each_entry_safe(dev, tmp, _dev_list,
 legacy_dev_list) {
-   list_del(>legacy_dev_list);
-   drm_put_dev(dev);
+   if (dev->driver == driver) {
+   list_del(>legacy_dev_list);
+   drm_put_dev(dev);
+   }
}
+   mutex_unlock(_dev_list_lock);
}
DRM_INFO("Module unloaded\n");
 }
diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h
index bb60a949f416..215b3472c773 100644
--- a/include/drm/drm_device.h
+++ b/include/drm/drm_device.h
@@ -51,12 +51,14 @@ enum switch_power_state {
  * may contain multiple heads.
  */
 struct drm_device {
+#ifdef CONFIG_DRM_LEGACY
/**
 * @legacy_dev_list:
 *
 * List of devices per driver for stealth attach cleanup
 */
struct list_head legacy_dev_list;
+#endif
 
/** @if_version: Highest interface version set */
int if_version;
diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h
index 97109df5beac..7dcf3b7bb5e6 100644
--- a/include/drm/drm_drv.h
+++ b/include/drm/drm_drv.h
@@ -601,8 +601,6 @@ struct drm_driver {
/* Everything below here is for legacy driver, never use! */
/* private: */
 
-   /* List of devices hanging off this driver with stealth attach. */
-   struct list_head legacy_dev_list;
int (*firstopen) (struct drm_device *);
void (*preclose) (struct drm_device *, struct drm_file *file_priv);
int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file 
*file_priv);
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH/RFC 3/3] drm: rcar_du: Constify drm_driver

2020-02-22 Thread Laurent Pinchart
The drm_driver structure is never modified, make it const. The improves
security by avoiding writable function pointers.

Signed-off-by: Laurent Pinchart 
---
 drivers/gpu/drm/rcar-du/rcar_du_drv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c 
b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 654e2dd08146..039eee3ef661 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -474,7 +474,7 @@ MODULE_DEVICE_TABLE(of, rcar_du_of_table);
 
 DEFINE_DRM_GEM_CMA_FOPS(rcar_du_fops);
 
-static struct drm_driver rcar_du_driver = {
+static const struct drm_driver rcar_du_driver = {
.driver_features= DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
.gem_free_object_unlocked = drm_gem_cma_free_object,
.gem_vm_ops = _gem_cma_vm_ops,
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH/RFC 0/3] Constify drm_driver

2020-02-22 Thread Laurent Pinchart
Hello,

This patch series makes it possible for DRM drivers to declare their
struct drm_driver as a static const. This improves security by avoiding
function pointers in writable memory.

The change turned out to be fairly easy, with preparation in patch 1/3
that moves the only non-const field out of drm_driver, and patch 2/3
that performs the constification in the DRM core. Patch 3/3 is an
example of driver conversion to const drm_driver. If the series is
accepted, I'll write a coccinelle patch that handles all drivers.

Laurent Pinchart (3):
  drm: Move legacy device list out of drm_driver
  drm: Use a const drm_driver through the DRM core
  drm: rcar_du: Constify drm_driver

 drivers/gpu/drm/drm_drv.c| 10 +++
 drivers/gpu/drm/drm_pci.c| 38 +---
 drivers/gpu/drm/drm_vram_helper_common.c |  4 +--
 drivers/gpu/drm/rcar-du/rcar_du_drv.c|  2 +-
 include/drm/drm_device.h |  4 ++-
 include/drm/drm_drv.h|  8 ++---
 include/drm/drm_legacy.h | 10 ---
 include/drm/drm_pci.h|  4 +--
 8 files changed, 49 insertions(+), 31 deletions(-)

-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH/RFC 2/3] drm: Use a const drm_driver through the DRM core

2020-02-22 Thread Laurent Pinchart
The drm_driver structure contains pointers to functions, which can be an
attack vector if an attacker can corrupt the structure. The DRM core
however never modifies the structure, so it could be declared as const
in drivers. Modify the DRM core to take const struct drm_driver
pointers in all APIs.

Signed-off-by: Laurent Pinchart 
---
 drivers/gpu/drm/drm_drv.c| 10 +-
 drivers/gpu/drm/drm_pci.c|  8 +---
 drivers/gpu/drm/drm_vram_helper_common.c |  4 ++--
 include/drm/drm_device.h |  2 +-
 include/drm/drm_drv.h|  6 +++---
 include/drm/drm_legacy.h | 10 ++
 include/drm/drm_pci.h|  4 ++--
 7 files changed, 24 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 7b1a628d1f6e..41654427d258 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -300,7 +300,7 @@ void drm_minor_release(struct drm_minor *minor)
  * kfree(priv);
  * }
  *
- * static struct drm_driver driver_drm_driver = {
+ * static const struct drm_driver driver_drm_driver = {
  * [...]
  * .release = driver_drm_release,
  * };
@@ -612,7 +612,7 @@ static void drm_fs_inode_free(struct inode *inode)
  * 0 on success, or error code on failure.
  */
 int drm_dev_init(struct drm_device *dev,
-struct drm_driver *driver,
+const struct drm_driver *driver,
 struct device *parent)
 {
int ret;
@@ -722,7 +722,7 @@ static void devm_drm_dev_init_release(void *data)
  */
 int devm_drm_dev_init(struct device *parent,
  struct drm_device *dev,
- struct drm_driver *driver)
+ const struct drm_driver *driver)
 {
int ret;
 
@@ -800,7 +800,7 @@ EXPORT_SYMBOL(drm_dev_fini);
  * RETURNS:
  * Pointer to new DRM device, or ERR_PTR on failure.
  */
-struct drm_device *drm_dev_alloc(struct drm_driver *driver,
+struct drm_device *drm_dev_alloc(const struct drm_driver *driver,
 struct device *parent)
 {
struct drm_device *dev;
@@ -943,7 +943,7 @@ static void remove_compat_control_link(struct drm_device 
*dev)
  */
 int drm_dev_register(struct drm_device *dev, unsigned long flags)
 {
-   struct drm_driver *driver = dev->driver;
+   const struct drm_driver *driver = dev->driver;
int ret;
 
if (drm_dev_needs_global_mutex(dev))
diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c
index 44805ac3177c..2ca7adf270c6 100644
--- a/drivers/gpu/drm/drm_pci.c
+++ b/drivers/gpu/drm/drm_pci.c
@@ -215,7 +215,7 @@ void drm_pci_agp_destroy(struct drm_device *dev)
  * Return: 0 on success or a negative error code on failure.
  */
 int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
-   struct drm_driver *driver)
+   const struct drm_driver *driver)
 {
struct drm_device *dev;
int ret;
@@ -274,7 +274,8 @@ EXPORT_SYMBOL(drm_get_pci_dev);
  *
  * Return: 0 on success or a negative error code on failure.
  */
-int drm_legacy_pci_init(struct drm_driver *driver, struct pci_driver *pdriver)
+int drm_legacy_pci_init(const struct drm_driver *driver,
+   struct pci_driver *pdriver)
 {
struct pci_dev *pdev = NULL;
const struct pci_device_id *pid;
@@ -319,7 +320,8 @@ EXPORT_SYMBOL(drm_legacy_pci_init);
  * Unregister a DRM driver shadow-attached through drm_legacy_pci_init(). This
  * is deprecated and only used by dri1 drivers.
  */
-void drm_legacy_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver)
+void drm_legacy_pci_exit(const struct drm_driver *driver,
+struct pci_driver *pdriver)
 {
struct drm_device *dev, *tmp;
DRM_DEBUG("\n");
diff --git a/drivers/gpu/drm/drm_vram_helper_common.c 
b/drivers/gpu/drm/drm_vram_helper_common.c
index 2000d9b33fd5..e93b04bbe2de 100644
--- a/drivers/gpu/drm/drm_vram_helper_common.c
+++ b/drivers/gpu/drm/drm_vram_helper_common.c
@@ -29,11 +29,11 @@
  *
  * .. code-block:: c
  *
- * struct file_operations fops ={
+ * const struct file_operations fops ={
  * .owner = THIS_MODULE,
  * DRM_VRAM_MM_FILE_OPERATION
  * };
- * struct drm_driver drv = {
+ * const struct drm_driver drv = {
  * .driver_feature = DRM_ ... ,
  * .fops = ,
  * DRM_GEM_VRAM_DRIVER
diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h
index 215b3472c773..6ed5d84e5f5d 100644
--- a/include/drm/drm_device.h
+++ b/include/drm/drm_device.h
@@ -70,7 +70,7 @@ struct drm_device {
struct device *dev;
 
/** @driver: DRM driver managing the device */
-   struct drm_driver *driver;
+   const struct drm_driver *driver;
 
/**
 * @dev_private:
diff --git a/include/drm/drm_drv.h 

Re: [PATCH 18/51] drm/: Use drmm_add_final_kfree

2020-02-22 Thread Russell King - ARM Linux admin
On Fri, Feb 21, 2020 at 10:02:46PM +0100, Daniel Vetter wrote:
> These are the leftover drivers that didn't have a ->release hook that
> needed to be updated.
> 
> Signed-off-by: Daniel Vetter 
> Cc: "James (Qian) Wang" 
> Cc: Liviu Dudau 
> Cc: Mihail Atanassov 
> Cc: Russell King 
> Cc: Hans de Goede 
> ---
>  drivers/gpu/drm/arm/display/komeda/komeda_kms.c | 2 ++
>  drivers/gpu/drm/armada/armada_drv.c | 2 ++
>  drivers/gpu/drm/vboxvideo/vbox_drv.c| 2 ++
>  3 files changed, 6 insertions(+)
> 
> diff --git a/drivers/gpu/drm/armada/armada_drv.c 
> b/drivers/gpu/drm/armada/armada_drv.c
> index 197dca3fc84c..dd9ed71ed942 100644
> --- a/drivers/gpu/drm/armada/armada_drv.c
> +++ b/drivers/gpu/drm/armada/armada_drv.c
> @@ -12,6 +12,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -103,6 +104,7 @@ static int armada_drm_bind(struct device *dev)
>   kfree(priv);
>   return ret;
>   }
> + drmm_add_final_kfree(>drm, priv);
>  
>   /* Remove early framebuffers */
>   ret = drm_fb_helper_remove_conflicting_framebuffers(NULL,

I have no visibility of what the changes behind this are, so I
can't ack this change.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up
According to speedtest.net: 11.9Mbps down 500kbps up
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 51/54] drm/omap: Hardcode omap_connector type to DSI

2020-02-22 Thread Laurent Pinchart
The omap_connector implementation is now used for DSI only. Hardcode its
type and drop unused code.

Signed-off-by: Laurent Pinchart 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
Reviewed-by: Tomi Valkeinen 
---
 drivers/gpu/drm/omapdrm/dss/base.c   | 23 --
 drivers/gpu/drm/omapdrm/dss/omapdss.h|  1 -
 drivers/gpu/drm/omapdrm/omap_connector.c | 31 ++--
 3 files changed, 2 insertions(+), 53 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/base.c 
b/drivers/gpu/drm/omapdrm/dss/base.c
index 2db3bd2f19db..455b410f7401 100644
--- a/drivers/gpu/drm/omapdrm/dss/base.c
+++ b/drivers/gpu/drm/omapdrm/dss/base.c
@@ -286,29 +286,6 @@ void omapdss_device_post_disable(struct omap_dss_device 
*dssdev)
 }
 EXPORT_SYMBOL_GPL(omapdss_device_post_disable);
 
-unsigned int omapdss_device_connector_type(enum omap_display_type type)
-{
-   switch (type) {
-   case OMAP_DISPLAY_TYPE_HDMI:
-   return DRM_MODE_CONNECTOR_HDMIA;
-   case OMAP_DISPLAY_TYPE_DVI:
-   return DRM_MODE_CONNECTOR_DVID;
-   case OMAP_DISPLAY_TYPE_DSI:
-   return DRM_MODE_CONNECTOR_DSI;
-   case OMAP_DISPLAY_TYPE_DPI:
-   case OMAP_DISPLAY_TYPE_DBI:
-   return DRM_MODE_CONNECTOR_DPI;
-   case OMAP_DISPLAY_TYPE_VENC:
-   /* TODO: This could also be composite */
-   return DRM_MODE_CONNECTOR_SVIDEO;
-   case OMAP_DISPLAY_TYPE_SDI:
-   return DRM_MODE_CONNECTOR_LVDS;
-   default:
-   return DRM_MODE_CONNECTOR_Unknown;
-   }
-}
-EXPORT_SYMBOL_GPL(omapdss_device_connector_type);
-
 /* 
-
  * Components Handling
  */
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h 
b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index cb79e05c902d..2e5453df2293 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -454,7 +454,6 @@ void omapdss_device_pre_enable(struct omap_dss_device 
*dssdev);
 void omapdss_device_enable(struct omap_dss_device *dssdev);
 void omapdss_device_disable(struct omap_dss_device *dssdev);
 void omapdss_device_post_disable(struct omap_dss_device *dssdev);
-unsigned int omapdss_device_connector_type(enum omap_display_type type);
 
 int omap_dss_get_num_overlay_managers(void);
 
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c 
b/drivers/gpu/drm/omapdrm/omap_connector.c
index baa31ed1f993..528764566b17 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -24,22 +24,7 @@ struct omap_connector {
 static enum drm_connector_status omap_connector_detect(
struct drm_connector *connector, bool force)
 {
-   enum drm_connector_status status;
-
-   switch (connector->connector_type) {
-   case DRM_MODE_CONNECTOR_DPI:
-   case DRM_MODE_CONNECTOR_LVDS:
-   case DRM_MODE_CONNECTOR_DSI:
-   status = connector_status_connected;
-   break;
-   default:
-   status = connector_status_unknown;
-   break;
-   }
-
-   VERB("%s: %d (force=%d)", connector->name, status, force);
-
-   return status;
+   return connector_status_connected;
 }
 
 static void omap_connector_destroy(struct drm_connector *connector)
@@ -138,18 +123,6 @@ static const struct drm_connector_helper_funcs 
omap_connector_helper_funcs = {
.mode_valid = omap_connector_mode_valid,
 };
 
-static int omap_connector_get_type(struct omap_dss_device *output)
-{
-   struct omap_dss_device *display;
-   enum omap_display_type type;
-
-   display = omapdss_display_get(output);
-   type = display->type;
-   omapdss_device_put(display);
-
-   return omapdss_device_connector_type(type);
-}
-
 /* initialize connector */
 struct drm_connector *omap_connector_init(struct drm_device *dev,
  struct omap_dss_device *output,
@@ -171,7 +144,7 @@ struct drm_connector *omap_connector_init(struct drm_device 
*dev,
connector->doublescan_allowed = 0;
 
drm_connector_init(dev, connector, _connector_funcs,
-  omap_connector_get_type(output));
+  DRM_MODE_CONNECTOR_DSI);
drm_connector_helper_add(connector, _connector_helper_funcs);
 
return connector;
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 54/54] drm/omap: dss: Remove unused omap_dss_device operations

2020-02-22 Thread Laurent Pinchart
The omap_dss_device .pre_enable(), .post_disable() and .set_timings()
are not used anymore. Remove them.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
 drivers/gpu/drm/omapdrm/dss/base.c | 26 ---
 drivers/gpu/drm/omapdrm/dss/omapdss.h  |  6 
 drivers/gpu/drm/omapdrm/omap_encoder.c | 44 +++---
 3 files changed, 5 insertions(+), 71 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/base.c 
b/drivers/gpu/drm/omapdrm/dss/base.c
index 455b410f7401..c7650a7c155d 100644
--- a/drivers/gpu/drm/omapdrm/dss/base.c
+++ b/drivers/gpu/drm/omapdrm/dss/base.c
@@ -234,18 +234,6 @@ void omapdss_device_disconnect(struct omap_dss_device *src,
 }
 EXPORT_SYMBOL_GPL(omapdss_device_disconnect);
 
-void omapdss_device_pre_enable(struct omap_dss_device *dssdev)
-{
-   if (!dssdev)
-   return;
-
-   omapdss_device_pre_enable(dssdev->next);
-
-   if (dssdev->ops && dssdev->ops->pre_enable)
-   dssdev->ops->pre_enable(dssdev);
-}
-EXPORT_SYMBOL_GPL(omapdss_device_pre_enable);
-
 void omapdss_device_enable(struct omap_dss_device *dssdev)
 {
if (!dssdev)
@@ -272,20 +260,6 @@ void omapdss_device_disable(struct omap_dss_device *dssdev)
 }
 EXPORT_SYMBOL_GPL(omapdss_device_disable);
 
-void omapdss_device_post_disable(struct omap_dss_device *dssdev)
-{
-   if (!dssdev)
-   return;
-
-   if (dssdev->ops && dssdev->ops->post_disable)
-   dssdev->ops->post_disable(dssdev);
-
-   omapdss_device_post_disable(dssdev->next);
-
-   dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-}
-EXPORT_SYMBOL_GPL(omapdss_device_post_disable);
-
 /* 
-
  * Components Handling
  */
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h 
b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index cbbe10b2b60d..ab19d4af8de7 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -342,15 +342,11 @@ struct omap_dss_device_ops {
void (*disconnect)(struct omap_dss_device *dssdev,
struct omap_dss_device *dst);
 
-   void (*pre_enable)(struct omap_dss_device *dssdev);
void (*enable)(struct omap_dss_device *dssdev);
void (*disable)(struct omap_dss_device *dssdev);
-   void (*post_disable)(struct omap_dss_device *dssdev);
 
int (*check_timings)(struct omap_dss_device *dssdev,
 struct drm_display_mode *mode);
-   void (*set_timings)(struct omap_dss_device *dssdev,
-   const struct drm_display_mode *mode);
 
int (*get_modes)(struct omap_dss_device *dssdev,
 struct drm_connector *connector);
@@ -449,10 +445,8 @@ int omapdss_device_connect(struct dss_device *dss,
   struct omap_dss_device *dst);
 void omapdss_device_disconnect(struct omap_dss_device *src,
   struct omap_dss_device *dst);
-void omapdss_device_pre_enable(struct omap_dss_device *dssdev);
 void omapdss_device_enable(struct omap_dss_device *dssdev);
 void omapdss_device_disable(struct omap_dss_device *dssdev);
-void omapdss_device_post_disable(struct omap_dss_device *dssdev);
 
 int omap_dss_get_num_overlay_managers(void);
 
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c 
b/drivers/gpu/drm/omapdrm/omap_encoder.c
index 18a79dde6815..ae4b867a67a3 100644
--- a/drivers/gpu/drm/omapdrm/omap_encoder.c
+++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
@@ -113,13 +113,8 @@ static void omap_encoder_mode_set(struct drm_encoder 
*encoder,
bus_flags = connector->display_info.bus_flags;
omap_encoder_update_videomode_flags(, bus_flags);
 
-   /* Set timings for all devices in the display pipeline. */
+   /* Set timings for the dss manager. */
dss_mgr_set_timings(output, );
-
-   for (dssdev = output; dssdev; dssdev = dssdev->next) {
-   if (dssdev->ops && dssdev->ops->set_timings)
-   dssdev->ops->set_timings(dssdev, adjusted_mode);
-   }
 }
 
 static void omap_encoder_disable(struct drm_encoder *encoder)
@@ -132,26 +127,10 @@ static void omap_encoder_disable(struct drm_encoder 
*encoder)
 
/*
 * Disable the chain of external devices, starting at the one at the
-* internal encoder's output.
+* internal encoder's output. This is used for DSI outputs only, as
+* dssdev->next is NULL for all other outputs.
 */
omapdss_device_disable(dssdev->next);
-
-   /*
-* Disable the internal encoder. This will disable the DSS output. The
-* DSI is treated as an exception as DSI pipelines still use the legacy
-* flow where the pipeline output controls the encoder.
-*/
-   if (dssdev->type != OMAP_DISPLAY_TYPE_DSI) {
-   if (dssdev->ops && dssdev->ops->disable)
-

[PATCH v7 21/54] drm/omap: dss: Cleanup DSS ports on initialisation failure

2020-02-22 Thread Laurent Pinchart
When the DSS initialises its output DPI and SDI ports, failures don't
clean up previous successfully initialised ports. This can lead to
resource leak or memory corruption. Fix it.

Reported-by: Hans Verkuil 
Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Acked-by: Sam Ravnborg 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
 drivers/gpu/drm/omapdrm/dss/dss.c | 43 +++
 1 file changed, 26 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c 
b/drivers/gpu/drm/omapdrm/dss/dss.c
index 225ec808b01a..67b92b5d8dd7 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss.c
+++ b/drivers/gpu/drm/omapdrm/dss/dss.c
@@ -1151,46 +1151,38 @@ static const struct dss_features dra7xx_dss_feats = {
.has_lcd_clk_src=   true,
 };
 
-static int dss_init_ports(struct dss_device *dss)
+static void __dss_uninit_ports(struct dss_device *dss, unsigned int num_ports)
 {
struct platform_device *pdev = dss->pdev;
struct device_node *parent = pdev->dev.of_node;
struct device_node *port;
unsigned int i;
-   int r;
 
-   for (i = 0; i < dss->feat->num_ports; i++) {
+   for (i = 0; i < num_ports; i++) {
port = of_graph_get_port_by_id(parent, i);
if (!port)
continue;
 
switch (dss->feat->ports[i]) {
case OMAP_DISPLAY_TYPE_DPI:
-   r = dpi_init_port(dss, pdev, port, dss->feat->model);
-   if (r)
-   return r;
+   dpi_uninit_port(port);
break;
-
case OMAP_DISPLAY_TYPE_SDI:
-   r = sdi_init_port(dss, pdev, port);
-   if (r)
-   return r;
+   sdi_uninit_port(port);
break;
-
default:
break;
}
}
-
-   return 0;
 }
 
-static void dss_uninit_ports(struct dss_device *dss)
+static int dss_init_ports(struct dss_device *dss)
 {
struct platform_device *pdev = dss->pdev;
struct device_node *parent = pdev->dev.of_node;
struct device_node *port;
-   int i;
+   unsigned int i;
+   int r;
 
for (i = 0; i < dss->feat->num_ports; i++) {
port = of_graph_get_port_by_id(parent, i);
@@ -1199,15 +1191,32 @@ static void dss_uninit_ports(struct dss_device *dss)
 
switch (dss->feat->ports[i]) {
case OMAP_DISPLAY_TYPE_DPI:
-   dpi_uninit_port(port);
+   r = dpi_init_port(dss, pdev, port, dss->feat->model);
+   if (r)
+   goto error;
break;
+
case OMAP_DISPLAY_TYPE_SDI:
-   sdi_uninit_port(port);
+   r = sdi_init_port(dss, pdev, port);
+   if (r)
+   goto error;
break;
+
default:
break;
}
}
+
+   return 0;
+
+error:
+   __dss_uninit_ports(dss, i);
+   return r;
+}
+
+static void dss_uninit_ports(struct dss_device *dss)
+{
+   __dss_uninit_ports(dss, dss->feat->num_ports);
 }
 
 static int dss_video_pll_probe(struct dss_device *dss)
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 53/54] drm/omap: dss: Remove unused omapdss_of_find_connected_device() function

2020-02-22 Thread Laurent Pinchart
The omapdss_of_find_connected_device() function isn't used anymore,
remove it.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
 drivers/gpu/drm/omapdrm/dss/Makefile  |  2 +-
 drivers/gpu/drm/omapdrm/dss/dss-of.c  | 28 ---
 drivers/gpu/drm/omapdrm/dss/omapdss.h |  3 ---
 3 files changed, 1 insertion(+), 32 deletions(-)
 delete mode 100644 drivers/gpu/drm/omapdrm/dss/dss-of.c

diff --git a/drivers/gpu/drm/omapdrm/dss/Makefile 
b/drivers/gpu/drm/omapdrm/dss/Makefile
index 5950c3f52c2e..f967e6948f2e 100644
--- a/drivers/gpu/drm/omapdrm/dss/Makefile
+++ b/drivers/gpu/drm/omapdrm/dss/Makefile
@@ -2,7 +2,7 @@
 obj-$(CONFIG_OMAP2_DSS_INIT) += omapdss-boot-init.o
 
 obj-$(CONFIG_OMAP_DSS_BASE) += omapdss-base.o
-omapdss-base-y := base.o display.o dss-of.o output.o
+omapdss-base-y := base.o display.o output.o
 
 obj-$(CONFIG_OMAP2_DSS) += omapdss.o
 # Core DSS files
diff --git a/drivers/gpu/drm/omapdrm/dss/dss-of.c 
b/drivers/gpu/drm/omapdrm/dss/dss-of.c
deleted file mode 100644
index b7981f3b80ad..
--- a/drivers/gpu/drm/omapdrm/dss/dss-of.c
+++ /dev/null
@@ -1,28 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
- * Author: Tomi Valkeinen 
- */
-
-#include 
-#include 
-#include 
-
-#include "omapdss.h"
-
-struct omap_dss_device *
-omapdss_of_find_connected_device(struct device_node *node, unsigned int port)
-{
-   struct device_node *remote_node;
-   struct omap_dss_device *dssdev;
-
-   remote_node = of_graph_get_remote_node(node, port, 0);
-   if (!remote_node)
-   return NULL;
-
-   dssdev = omapdss_find_device_by_node(remote_node);
-   of_node_put(remote_node);
-
-   return dssdev ? dssdev : ERR_PTR(-EPROBE_DEFER);
-}
-EXPORT_SYMBOL_GPL(omapdss_of_find_connected_device);
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h 
b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index 315a356fa0c0..cbbe10b2b60d 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -477,9 +477,6 @@ static inline bool omapdss_device_is_enabled(struct 
omap_dss_device *dssdev)
return dssdev->state == OMAP_DSS_DISPLAY_ACTIVE;
 }
 
-struct omap_dss_device *
-omapdss_of_find_connected_device(struct device_node *node, unsigned int port);
-
 enum dss_writeback_channel {
DSS_WB_LCD1_MGR =   0,
DSS_WB_LCD2_MGR =   1,
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 52/54] drm/omap: dss: Inline the omapdss_display_get() function

2020-02-22 Thread Laurent Pinchart
Inline the omapdss_display_get() in its only caller to simplify the
code.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
 drivers/gpu/drm/omapdrm/dss/display.c | 9 -
 drivers/gpu/drm/omapdrm/dss/omapdss.h | 1 -
 drivers/gpu/drm/omapdrm/omap_drv.c| 7 ---
 3 files changed, 4 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/display.c 
b/drivers/gpu/drm/omapdrm/dss/display.c
index 8a3f61f5825f..3b82158b1bfd 100644
--- a/drivers/gpu/drm/omapdrm/dss/display.c
+++ b/drivers/gpu/drm/omapdrm/dss/display.c
@@ -40,15 +40,6 @@ void omapdss_display_init(struct omap_dss_device *dssdev)
 }
 EXPORT_SYMBOL_GPL(omapdss_display_init);
 
-struct omap_dss_device *omapdss_display_get(struct omap_dss_device *output)
-{
-   while (output->next)
-   output = output->next;
-
-   return omapdss_device_get(output);
-}
-EXPORT_SYMBOL_GPL(omapdss_display_get);
-
 int omapdss_display_get_modes(struct drm_connector *connector,
  const struct videomode *vm)
 {
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h 
b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index 2e5453df2293..315a356fa0c0 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -436,7 +436,6 @@ static inline bool omapdss_is_initialized(void)
 }
 
 void omapdss_display_init(struct omap_dss_device *dssdev);
-struct omap_dss_device *omapdss_display_get(struct omap_dss_device *output);
 int omapdss_display_get_modes(struct drm_connector *connector,
  const struct videomode *vm);
 
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c 
b/drivers/gpu/drm/omapdrm/omap_drv.c
index e6a065030523..cdafd7ef1c32 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -207,11 +207,12 @@ static int omap_display_id(struct omap_dss_device *output)
struct device_node *node = NULL;
 
if (output->next) {
-   struct omap_dss_device *display;
+   struct omap_dss_device *display = output;
+
+   while (display->next)
+   display = display->next;
 
-   display = omapdss_display_get(output);
node = display->dev->of_node;
-   omapdss_device_put(display);
} else if (output->bridge) {
struct drm_bridge *bridge = output->bridge;
 
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 40/54] drm/omap: Remove HPD, detect and EDID omapdss operations

2020-02-22 Thread Laurent Pinchart
Due to the removal of several omapdrm display drivers, the omapdss HPD,
detected and EDID operations are not used anymore. Remove them and all
related code.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
 drivers/gpu/drm/omapdrm/dss/hdmi4.c  |  61 
 drivers/gpu/drm/omapdrm/dss/hdmi5.c  |  46 --
 drivers/gpu/drm/omapdrm/dss/omapdss.h|  25 +--
 drivers/gpu/drm/omapdrm/omap_connector.c | 190 +++
 drivers/gpu/drm/omapdrm/omap_connector.h |   2 -
 drivers/gpu/drm/omapdrm/omap_drv.c   |   8 +-
 6 files changed, 22 insertions(+), 310 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index 52daae36935a..b9bcd6e681e8 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -321,47 +321,6 @@ static void hdmi_disconnect(struct omap_dss_device *src,
omapdss_device_disconnect(dst, dst->next);
 }
 
-#define MAX_EDID   512
-
-static struct edid *hdmi_read_edid_data(struct omap_hdmi *hdmi,
-   struct drm_connector *connector)
-{
-   u8 *edid;
-   int r;
-
-   edid = kzalloc(MAX_EDID, GFP_KERNEL);
-   if (!edid)
-   return NULL;
-
-   r = hdmi4_core_ddc_read(>core, edid, 0, EDID_LENGTH);
-   if (r)
-   goto error;
-
-   if (edid[0x7e] > 0) {
-   char checksum = 0;
-   unsigned int i;
-
-   r = hdmi4_core_ddc_read(>core, edid + EDID_LENGTH, 1,
-   EDID_LENGTH);
-   if (r)
-   goto error;
-
-   for (i = 0; i < EDID_LENGTH; ++i)
-   checksum += edid[EDID_LENGTH + i];
-
-   if (checksum != 0) {
-   DSSERR("E-EDID checksum failed!!\n");
-   goto error;
-   }
-   }
-
-   return (struct edid *)edid;
-
-error:
-   kfree(edid);
-   return NULL;
-}
-
 static struct edid *
 hdmi_do_read_edid(struct omap_hdmi *hdmi,
  struct edid *(*read)(struct omap_hdmi *hdmi,
@@ -411,28 +370,9 @@ hdmi_do_read_edid(struct omap_hdmi *hdmi,
return edid;
 }
 
-static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
-{
-   return hdmi_do_read_edid(dssdev_to_hdmi(dssdev), hdmi_read_edid_data,
-NULL);
-}
-
-static void hdmi_lost_hotplug(struct omap_dss_device *dssdev)
-{
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
-   hdmi4_cec_set_phys_addr(>core, CEC_PHYS_ADDR_INVALID);
-}
-
 static const struct omap_dss_device_ops hdmi_ops = {
.connect= hdmi_connect,
.disconnect = hdmi_disconnect,
-
-   .read_edid  = hdmi_read_edid,
-
-   .hdmi = {
-   .lost_hotplug   = hdmi_lost_hotplug,
-   },
 };
 
 /* 
-
@@ -804,7 +744,6 @@ static int hdmi4_init_output(struct omap_hdmi *hdmi)
out->ops = _ops;
out->owner = THIS_MODULE;
out->of_port = 0;
-   out->ops_flags = OMAP_DSS_DEVICE_OP_EDID;
 
r = omapdss_device_init_output(out, >bridge);
if (r < 0) {
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index f07fd5c6dc39..effe4a9401ff 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -319,43 +319,6 @@ static void hdmi_disconnect(struct omap_dss_device *src,
omapdss_device_disconnect(dst, dst->next);
 }
 
-#define MAX_EDID   512
-
-static struct edid *hdmi_read_edid_data(struct omap_hdmi *hdmi,
-   struct drm_connector *connector)
-{
-   struct hdmi_core_data *core = >core;
-   int max_ext_blocks = 3;
-   int r, n, i;
-   u8 *edid;
-
-   edid = kzalloc(MAX_EDID, GFP_KERNEL);
-   if (!edid)
-   return NULL;
-
-   r = hdmi5_core_ddc_read(core, edid, 0, EDID_LENGTH);
-   if (r)
-   goto error;
-
-   n = edid[0x7e];
-
-   if (n > max_ext_blocks)
-   n = max_ext_blocks;
-
-   for (i = 1; i <= n; i++) {
-   r = hdmi5_core_ddc_read(core, edid + i * EDID_LENGTH, i,
-   EDID_LENGTH);
-   if (r)
-   goto error;
-   }
-
-   return (struct edid *)edid;
-
-error:
-   kfree(edid);
-   return NULL;
-}
-
 static struct edid *
 hdmi_do_read_edid(struct omap_hdmi *hdmi,
  struct edid *(*read)(struct omap_hdmi *hdmi,
@@ -400,17 +363,9 @@ hdmi_do_read_edid(struct omap_hdmi *hdmi,
return (struct edid *)edid;
 }
 
-static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
-{
-   return hdmi_do_read_edid(dssdev_to_hdmi(dssdev), 

[PATCH v7 39/54] drm/omap: Switch the HDMI and VENC outputs to drm_bridge

2020-02-22 Thread Laurent Pinchart
The TPD12S015, OPA362 and analog and HDMI connectors are now supported
by DRM bridge drivers, and the omapdrm HDMI and VENC outputs can be
handled through the drm_bridge API. Switch the outputs to drm_bridge by
making the next bridge mandatory and removing the related
omapdrm-specific display drivers.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
Changes since v3:

- Update arch/arm/configs/omap2plus_defconfig
---
 arch/arm/configs/omap2plus_defconfig  |   7 +-
 drivers/gpu/drm/omapdrm/displays/Kconfig  |  22 --
 drivers/gpu/drm/omapdrm/displays/Makefile |   4 -
 .../omapdrm/displays/connector-analog-tv.c|  97 
 .../gpu/drm/omapdrm/displays/connector-hdmi.c | 183 ---
 .../gpu/drm/omapdrm/displays/encoder-opa362.c | 137 ---
 .../drm/omapdrm/displays/encoder-tpd12s015.c  | 217 --
 drivers/gpu/drm/omapdrm/dss/hdmi4.c   |   4 +-
 drivers/gpu/drm/omapdrm/dss/hdmi5.c   |   4 +-
 .../gpu/drm/omapdrm/dss/omapdss-boot-init.c   |   5 -
 drivers/gpu/drm/omapdrm/dss/output.c  |   5 +
 drivers/gpu/drm/omapdrm/dss/venc.c|   4 +-
 12 files changed, 14 insertions(+), 675 deletions(-)
 delete mode 100644 drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c
 delete mode 100644 drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
 delete mode 100644 drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
 delete mode 100644 drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c

diff --git a/arch/arm/configs/omap2plus_defconfig 
b/arch/arm/configs/omap2plus_defconfig
index c32c338f7704..b9698e217aa7 100644
--- a/arch/arm/configs/omap2plus_defconfig
+++ b/arch/arm/configs/omap2plus_defconfig
@@ -350,14 +350,13 @@ CONFIG_DRM_OMAP=m
 CONFIG_OMAP5_DSS_HDMI=y
 CONFIG_OMAP2_DSS_SDI=y
 CONFIG_OMAP2_DSS_DSI=y
-CONFIG_DRM_OMAP_ENCODER_OPA362=m
-CONFIG_DRM_OMAP_ENCODER_TPD12S015=m
-CONFIG_DRM_OMAP_CONNECTOR_HDMI=m
-CONFIG_DRM_OMAP_CONNECTOR_ANALOG_TV=m
 CONFIG_DRM_OMAP_PANEL_DSI_CM=m
 CONFIG_DRM_TILCDC=m
 CONFIG_DRM_PANEL_SIMPLE=m
+CONFIG_DRM_DISPLAY_CONNECTOR=m
+CONFIG_DRM_SIMPLE_BRIDGE=m
 CONFIG_DRM_TI_TFP410=m
+CONFIG_DRM_TI_TPD12S015=m
 CONFIG_DRM_PANEL_LG_LB035Q02=m
 CONFIG_DRM_PANEL_NEC_NL8048HL11=m
 CONFIG_DRM_PANEL_SHARP_LS037V7DW01=m
diff --git a/drivers/gpu/drm/omapdrm/displays/Kconfig 
b/drivers/gpu/drm/omapdrm/displays/Kconfig
index b562a8cd61bf..f2be594c7eff 100644
--- a/drivers/gpu/drm/omapdrm/displays/Kconfig
+++ b/drivers/gpu/drm/omapdrm/displays/Kconfig
@@ -1,28 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 menu "OMAPDRM External Display Device Drivers"
 
-config DRM_OMAP_ENCODER_OPA362
-   tristate "OPA362 external analog amplifier"
-   help
- Driver for OPA362 external analog TV amplifier controlled
- through a GPIO.
-
-config DRM_OMAP_ENCODER_TPD12S015
-   tristate "TPD12S015 HDMI ESD protection and level shifter"
-   help
- Driver for TPD12S015, which offers HDMI ESD protection and level
- shifting.
-
-config DRM_OMAP_CONNECTOR_HDMI
-   tristate "HDMI Connector"
-   help
- Driver for a generic HDMI connector.
-
-config DRM_OMAP_CONNECTOR_ANALOG_TV
-   tristate "Analog TV Connector"
-   help
- Driver for a generic analog TV connector.
-
 config DRM_OMAP_PANEL_DSI_CM
tristate "Generic DSI Command Mode Panel"
depends on BACKLIGHT_CLASS_DEVICE
diff --git a/drivers/gpu/drm/omapdrm/displays/Makefile 
b/drivers/gpu/drm/omapdrm/displays/Makefile
index cb76859dc574..488ddf153613 100644
--- a/drivers/gpu/drm/omapdrm/displays/Makefile
+++ b/drivers/gpu/drm/omapdrm/displays/Makefile
@@ -1,6 +1,2 @@
 # SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_DRM_OMAP_ENCODER_OPA362) += encoder-opa362.o
-obj-$(CONFIG_DRM_OMAP_ENCODER_TPD12S015) += encoder-tpd12s015.o
-obj-$(CONFIG_DRM_OMAP_CONNECTOR_HDMI) += connector-hdmi.o
-obj-$(CONFIG_DRM_OMAP_CONNECTOR_ANALOG_TV) += connector-analog-tv.o
 obj-$(CONFIG_DRM_OMAP_PANEL_DSI_CM) += panel-dsi-cm.o
diff --git a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c 
b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c
deleted file mode 100644
index f36aa1885d39..
--- a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c
+++ /dev/null
@@ -1,97 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Analog TV Connector driver
- *
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
- * Author: Tomi Valkeinen 
- */
-
-#include 
-#include 
-#include 
-#include 
-
-#include "../dss/omapdss.h"
-
-struct panel_drv_data {
-   struct omap_dss_device dssdev;
-
-   struct device *dev;
-};
-
-#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
-
-static int tvc_connect(struct omap_dss_device *src,
-  struct omap_dss_device *dst)
-{
-   return 0;
-}
-
-static void tvc_disconnect(struct omap_dss_device *src,
-  

[PATCH v7 20/54] drm: Add helper to create a connector for a chain of bridges

2020-02-22 Thread Laurent Pinchart
Most bridge drivers create a DRM connector to model the connector at the
output of the bridge. This model is historical and has worked pretty
well so far, but causes several issues:

- It prevents supporting more complex display pipelines where DRM
connector operations are split over multiple components. For instance a
pipeline with a bridge connected to the DDC signals to read EDID data,
and another one connected to the HPD signal to detect connection and
disconnection, will not be possible to support through this model.

- It requires every bridge driver to implement similar connector
handling code, resulting in code duplication.

- It assumes that a bridge will either be wired to a connector or to
another bridge, but doesn't support bridges that can be used in both
positions very well (although there is some ad-hoc support for this in
the analogix_dp bridge driver).

In order to solve these issues, ownership of the connector needs to be
moved to the display controller driver.

To avoid code duplication in display controller drivers, add a new
helper to create and manage a DRM connector backed by a chain of
bridges. All connector operations are delegating to the appropriate
bridge in the chain.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Boris Brezillon 
Acked-by: Sam Ravnborg 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
Changes since v5:

- Fix the interlace_allowed flag logic

Changes since v4:

- Set the connector interlace_allowed flag based on interlaced support
  in bridges

Changes since v2:

- Fixed typo in documentation
- Rebased on top of Boris' drm_bridge chaining rework
- Pass drm_encoder instead of brm_bridge to drm_bridge_connector_init()

Changes since v1:

- Removed the unused MAX_EDID macro
- Removed the unused drm_bridge_connector.hdmi_mode field
- Use drm_connector_init_with_ddc()
---
 Documentation/gpu/drm-kms-helpers.rst  |  12 +
 drivers/gpu/drm/Makefile   |   3 +-
 drivers/gpu/drm/drm_bridge_connector.c | 379 +
 include/drm/drm_bridge_connector.h |  18 ++
 4 files changed, 411 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/drm_bridge_connector.c
 create mode 100644 include/drm/drm_bridge_connector.h

diff --git a/Documentation/gpu/drm-kms-helpers.rst 
b/Documentation/gpu/drm-kms-helpers.rst
index fe155c6ae175..ee730457bf4e 100644
--- a/Documentation/gpu/drm-kms-helpers.rst
+++ b/Documentation/gpu/drm-kms-helpers.rst
@@ -145,6 +145,12 @@ Bridge Operations
 .. kernel-doc:: drivers/gpu/drm/drm_bridge.c
:doc: bridge operations
 
+Bridge Connector Helper
+---
+
+.. kernel-doc:: drivers/gpu/drm/drm_bridge_connector.c
+   :doc: overview
+
 
 Bridge Helper Reference
 -
@@ -155,6 +161,12 @@ Bridge Helper Reference
 .. kernel-doc:: drivers/gpu/drm/drm_bridge.c
:export:
 
+Bridge Connector Helper Reference
+-
+
+.. kernel-doc:: drivers/gpu/drm/drm_bridge_connector.c
+   :export:
+
 Panel-Bridge Helper Reference
 -
 
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index ca0ca775d37f..7f72ef5e7811 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -39,7 +39,8 @@ obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o
 drm_ttm_helper-y := drm_gem_ttm_helper.o
 obj-$(CONFIG_DRM_TTM_HELPER) += drm_ttm_helper.o
 
-drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_dsc.o 
drm_probe_helper.o \
+drm_kms_helper-y := drm_bridge_connector.o drm_crtc_helper.o drm_dp_helper.o \
+   drm_dsc.o drm_probe_helper.o \
drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
drm_kms_helper_common.o drm_dp_dual_mode_helper.o \
drm_simple_kms_helper.o drm_modeset_helper.o \
diff --git a/drivers/gpu/drm/drm_bridge_connector.c 
b/drivers/gpu/drm/drm_bridge_connector.c
new file mode 100644
index ..c6994fe673f3
--- /dev/null
+++ b/drivers/gpu/drm/drm_bridge_connector.c
@@ -0,0 +1,379 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Laurent Pinchart 
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/**
+ * DOC: overview
+ *
+ * The DRM bridge connector helper object provides a DRM connector
+ * implementation that wraps a chain of  drm_bridge. The connector
+ * operations are fully implemented based on the operations of the bridges in
+ * the chain, and don't require any intervention from the display controller
+ * driver at runtime.
+ *
+ * To use the helper, display controller drivers create a bridge connector with
+ * a call to drm_bridge_connector_init(). This associates the newly created
+ * connector with the chain of bridges passed to the function and registers it
+ * with the DRM device. At that point the connector becomes fully usable, no
+ * further operation is needed.
+ *
+ * The DRM bridge 

[PATCH v7 34/54] drm/omap: hdmi5: Move mode set, enable and disable operations to bridge

2020-02-22 Thread Laurent Pinchart
Move the omap_dss_device .set_timings(), .enable() and .disable()
operations to the drm_bridge functions. As the drm_bridge for the HDMI
encoder is unconditionally registered and attached, those operations
will be called at the appropriate time.

The omapdss device .set_infoframe() and .set_hdmi_mode() operations have
no equivalent in drm_bridge. Thir content is thus moved to the bridge
.enable() operation as the data they store is not needed before the HDMI
encoder gets enabled.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
Changes since v5:

- Rebased on top of drm_bridge_state

Changes since v2:

- Detail .set_infoframe() and .set_hdmi_mode() handling in the commit
  message
---
 drivers/gpu/drm/omapdrm/dss/hdmi5.c | 209 +++-
 1 file changed, 111 insertions(+), 98 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index e7fe2a24a3e1..52184797c858 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -31,6 +31,9 @@
 #include 
 #include 
 
+#include 
+#include 
+
 #include "omapdss.h"
 #include "hdmi5_core.h"
 #include "dss.h"
@@ -236,20 +239,6 @@ static void hdmi_power_off_full(struct omap_hdmi *hdmi)
hdmi_power_off_core(hdmi);
 }
 
-static void hdmi_display_set_timings(struct omap_dss_device *dssdev,
-const struct drm_display_mode *mode)
-{
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
-   mutex_lock(>lock);
-
-   drm_display_mode_to_videomode(mode, >cfg.vm);
-
-   dispc_set_tv_pclk(hdmi->dss->dispc, mode->clock * 1000);
-
-   mutex_unlock(>lock);
-}
-
 static int hdmi_dump_regs(struct seq_file *s, void *p)
 {
struct omap_hdmi *hdmi = s->private;
@@ -285,62 +274,6 @@ static void hdmi_stop_audio_stream(struct omap_hdmi *hd)
REG_FLD_MOD(hd->wp.base, HDMI_WP_SYSCONFIG, hd->wp_idlemode, 3, 2);
 }
 
-static void hdmi_display_enable(struct omap_dss_device *dssdev)
-{
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-   unsigned long flags;
-   int r;
-
-   DSSDBG("ENTER hdmi_display_enable\n");
-
-   mutex_lock(>lock);
-
-   r = hdmi_power_on_full(hdmi);
-   if (r) {
-   DSSERR("failed to power on device\n");
-   goto done;
-   }
-
-   if (hdmi->audio_configured) {
-   r = hdmi5_audio_config(>core, >wp,
-  >audio_config,
-  hdmi->cfg.vm.pixelclock);
-   if (r) {
-   DSSERR("Error restoring audio configuration: %d", r);
-   hdmi->audio_abort_cb(>pdev->dev);
-   hdmi->audio_configured = false;
-   }
-   }
-
-   spin_lock_irqsave(>audio_playing_lock, flags);
-   if (hdmi->audio_configured && hdmi->audio_playing)
-   hdmi_start_audio_stream(hdmi);
-   hdmi->display_enabled = true;
-   spin_unlock_irqrestore(>audio_playing_lock, flags);
-
-done:
-   mutex_unlock(>lock);
-}
-
-static void hdmi_display_disable(struct omap_dss_device *dssdev)
-{
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-   unsigned long flags;
-
-   DSSDBG("Enter hdmi_display_disable\n");
-
-   mutex_lock(>lock);
-
-   spin_lock_irqsave(>audio_playing_lock, flags);
-   hdmi_stop_audio_stream(hdmi);
-   hdmi->display_enabled = false;
-   spin_unlock_irqrestore(>audio_playing_lock, flags);
-
-   hdmi_power_off_full(hdmi);
-
-   mutex_unlock(>lock);
-}
-
 static int hdmi_core_enable(struct omap_hdmi *hdmi)
 {
int r = 0;
@@ -473,39 +406,11 @@ static struct edid *hdmi_read_edid(struct omap_dss_device 
*dssdev)
 NULL);
 }
 
-static int hdmi_set_infoframe(struct omap_dss_device *dssdev,
-   const struct hdmi_avi_infoframe *avi)
-{
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
-   hdmi->cfg.infoframe = *avi;
-   return 0;
-}
-
-static int hdmi_set_hdmi_mode(struct omap_dss_device *dssdev,
-   bool hdmi_mode)
-{
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
-   hdmi->cfg.hdmi_dvi_mode = hdmi_mode ? HDMI_HDMI : HDMI_DVI;
-   return 0;
-}
-
 static const struct omap_dss_device_ops hdmi_ops = {
.connect= hdmi_connect,
.disconnect = hdmi_disconnect,
 
-   .enable = hdmi_display_enable,
-   .disable= hdmi_display_disable,
-
-   .set_timings= hdmi_display_set_timings,
-
.read_edid  = hdmi_read_edid,
-
-   .hdmi = {
-   .set_infoframe  = hdmi_set_infoframe,
-   .set_hdmi_mode  = hdmi_set_hdmi_mode,
-   },
 };
 
 /* 
-
@@ 

[PATCH v7 48/54] drm/omap: dpi: Register a drm_bridge

2020-02-22 Thread Laurent Pinchart
In order to integrate with a chain of drm_bridge, the internal DPI
output has to expose its operations through the drm_bridge API.
Register a bridge at initialisation time to do so and remove the
omap_dss_device operations that are now unused.

Signed-off-by: Laurent Pinchart 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
Reviewed-by: Tomi Valkeinen 
---
Changes since v5:

- Rebased on top of drm_bridge_state

Changes since v3:

- Drop unneeded lock

Changes since v2:

- Unregister bridge if port initialisation fails
---
 drivers/gpu/drm/omapdrm/dss/dpi.c | 209 +-
 1 file changed, 116 insertions(+), 93 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c 
b/drivers/gpu/drm/omapdrm/dss/dpi.c
index c167bd1116ec..5110acb0c6c1 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -21,6 +21,8 @@
 #include 
 #include 
 
+#include 
+
 #include "dss.h"
 #include "omapdss.h"
 
@@ -34,19 +36,15 @@ struct dpi_data {
enum dss_clk_source clk_src;
struct dss_pll *pll;
 
-   struct mutex lock;
-
struct dss_lcd_mgr_config mgr_config;
unsigned long pixelclock;
int data_lines;
 
struct omap_dss_device output;
+   struct drm_bridge bridge;
 };
 
-static struct dpi_data *dpi_get_data_from_dssdev(struct omap_dss_device 
*dssdev)
-{
-   return container_of(dssdev, struct dpi_data, output);
-}
+#define drm_bridge_to_dpi(bridge) container_of(bridge, struct dpi_data, bridge)
 
 /* 
-
  * Clock Handling and PLL
@@ -354,6 +352,32 @@ static void dpi_config_lcd_manager(struct dpi_data *dpi)
dss_mgr_set_lcd_config(>output, >mgr_config);
 }
 
+static int dpi_clock_update(struct dpi_data *dpi, unsigned long *clock)
+{
+   int lck_div, pck_div;
+   unsigned long fck;
+   struct dpi_clk_calc_ctx ctx;
+
+   if (dpi->pll) {
+   if (!dpi_pll_clk_calc(dpi, *clock, ))
+   return -EINVAL;
+
+   fck = ctx.pll_cinfo.clkout[ctx.clkout_idx];
+   } else {
+   if (!dpi_dss_clk_calc(dpi, *clock, ))
+   return -EINVAL;
+
+   fck = ctx.fck;
+   }
+
+   lck_div = ctx.dispc_cinfo.lck_div;
+   pck_div = ctx.dispc_cinfo.pck_div;
+
+   *clock = fck / lck_div / pck_div;
+
+   return 0;
+}
+
 static int dpi_verify_pll(struct dss_pll *pll)
 {
int r;
@@ -391,44 +415,86 @@ static void dpi_init_pll(struct dpi_data *dpi)
 }
 
 /* 
-
- * omap_dss_device Operations
+ * DRM Bridge Operations
  */
 
-static int dpi_connect(struct omap_dss_device *src,
-  struct omap_dss_device *dst)
+static int dpi_bridge_attach(struct drm_bridge *bridge,
+enum drm_bridge_attach_flags flags)
 {
-   struct dpi_data *dpi = dpi_get_data_from_dssdev(dst);
+   struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
+
+   if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
+   return -EINVAL;
 
dpi_init_pll(dpi);
 
-   return omapdss_device_connect(dst->dss, dst, dst->next);
+   return drm_bridge_attach(bridge->encoder, dpi->output.next_bridge,
+bridge, flags);
 }
 
-static void dpi_disconnect(struct omap_dss_device *src,
-  struct omap_dss_device *dst)
+static enum drm_mode_status
+dpi_bridge_mode_valid(struct drm_bridge *bridge,
+  const struct drm_display_mode *mode)
 {
-   omapdss_device_disconnect(dst, dst->next);
+   struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
+   unsigned long clock = mode->clock * 1000;
+   int ret;
+
+   if (mode->hdisplay % 8 != 0)
+   return MODE_BAD_WIDTH;
+
+   if (mode->clock == 0)
+   return MODE_NOCLOCK;
+
+   ret = dpi_clock_update(dpi, );
+   if (ret < 0)
+   return MODE_CLOCK_RANGE;
+
+   return MODE_OK;
 }
 
-static void dpi_display_enable(struct omap_dss_device *dssdev)
+static bool dpi_bridge_mode_fixup(struct drm_bridge *bridge,
+  const struct drm_display_mode *mode,
+  struct drm_display_mode *adjusted_mode)
 {
-   struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
-   struct omap_dss_device *out = >output;
-   int r;
+   struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
+   unsigned long clock = mode->clock * 1000;
+   int ret;
+
+   ret = dpi_clock_update(dpi, );
+   if (ret < 0)
+   return false;
+
+   adjusted_mode->clock = clock / 1000;
+
+   return true;
+}
 
-   mutex_lock(>lock);
+static void dpi_bridge_mode_set(struct drm_bridge *bridge,
+const struct drm_display_mode *mode,
+const struct 

[PATCH v7 50/54] drm/omap: sdi: Register a drm_bridge

2020-02-22 Thread Laurent Pinchart
In order to integrate with a chain of drm_bridge, the internal SDI
output has to expose its operations through the drm_bridge API.
Register a bridge at initialisation time to do so and remove the
omap_dss_device operations that are now unused.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
Changes since v5:

- Rebased on top of drm_bridge_state

Changes since v3:

- Split dss/base.h and omap_connector.c cleanups to a separate patch

Changes since v2:

- Remove unused omapdss_device_connector_type() function
- Unregister bridge if port initialisation fails
---
 drivers/gpu/drm/omapdrm/dss/sdi.c | 168 +++---
 1 file changed, 109 insertions(+), 59 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c 
b/drivers/gpu/drm/omapdrm/dss/sdi.c
index 7dedfcc86922..417a8740ad0a 100644
--- a/drivers/gpu/drm/omapdrm/dss/sdi.c
+++ b/drivers/gpu/drm/omapdrm/dss/sdi.c
@@ -15,6 +15,8 @@
 #include 
 #include 
 
+#include 
+
 #include "dss.h"
 #include "omapdss.h"
 
@@ -30,9 +32,11 @@ struct sdi_device {
int datapairs;
 
struct omap_dss_device output;
+   struct drm_bridge bridge;
 };
 
-#define dssdev_to_sdi(dssdev) container_of(dssdev, struct sdi_device, output)
+#define drm_bridge_to_sdi(bridge) \
+   container_of(bridge, struct sdi_device, bridge)
 
 struct sdi_clk_calc_ctx {
struct sdi_device *sdi;
@@ -118,9 +122,82 @@ static void sdi_config_lcd_manager(struct sdi_device *sdi)
dss_mgr_set_lcd_config(>output, >mgr_config);
 }
 
-static void sdi_display_enable(struct omap_dss_device *dssdev)
+/* 
-
+ * DRM Bridge Operations
+ */
+
+static int sdi_bridge_attach(struct drm_bridge *bridge,
+enum drm_bridge_attach_flags flags)
+{
+   struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
+
+   if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
+   return -EINVAL;
+
+   return drm_bridge_attach(bridge->encoder, sdi->output.next_bridge,
+bridge, flags);
+}
+
+static enum drm_mode_status
+sdi_bridge_mode_valid(struct drm_bridge *bridge,
+ const struct drm_display_mode *mode)
+{
+   struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
+   unsigned long pixelclock = mode->clock * 1000;
+   struct dispc_clock_info dispc_cinfo;
+   unsigned long fck;
+   int ret;
+
+   if (pixelclock == 0)
+   return MODE_NOCLOCK;
+
+   ret = sdi_calc_clock_div(sdi, pixelclock, , _cinfo);
+   if (ret < 0)
+   return MODE_CLOCK_RANGE;
+
+   return MODE_OK;
+}
+
+static bool sdi_bridge_mode_fixup(struct drm_bridge *bridge,
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+   struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
+   unsigned long pixelclock = mode->clock * 1000;
+   struct dispc_clock_info dispc_cinfo;
+   unsigned long fck;
+   unsigned long pck;
+   int ret;
+
+   ret = sdi_calc_clock_div(sdi, pixelclock, , _cinfo);
+   if (ret < 0)
+   return false;
+
+   pck = fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div;
+
+   if (pck != pixelclock)
+   dev_dbg(>pdev->dev,
+   "pixel clock adjusted from %lu Hz to %lu Hz\n",
+   pixelclock, pck);
+
+   adjusted_mode->clock = pck / 1000;
+
+   return true;
+}
+
+static void sdi_bridge_mode_set(struct drm_bridge *bridge,
+   const struct drm_display_mode *mode,
+   const struct drm_display_mode *adjusted_mode)
+{
+   struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
+
+   sdi->pixelclock = adjusted_mode->clock * 1000;
+}
+
+static void sdi_bridge_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state)
 {
-   struct sdi_device *sdi = dssdev_to_sdi(dssdev);
+   struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
struct dispc_clock_info dispc_cinfo;
unsigned long fck;
int r;
@@ -181,9 +258,10 @@ static void sdi_display_enable(struct omap_dss_device 
*dssdev)
regulator_disable(sdi->vdds_sdi_reg);
 }
 
-static void sdi_display_disable(struct omap_dss_device *dssdev)
+static void sdi_bridge_disable(struct drm_bridge *bridge,
+  struct drm_bridge_state *bridge_state)
 {
-   struct sdi_device *sdi = dssdev_to_sdi(dssdev);
+   struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
 
dss_mgr_disable(>output);
 
@@ -194,71 +272,40 @@ static void sdi_display_disable(struct omap_dss_device 
*dssdev)
regulator_disable(sdi->vdds_sdi_reg);
 }
 
-static void sdi_set_timings(struct omap_dss_device *dssdev,
-   

[PATCH v7 23/54] drm/omap: Factor out display type to connector type conversion

2020-02-22 Thread Laurent Pinchart
Move the code that computes the DRM connector type for the
omapdss_device display type to a new omapdss_device_connector_type()
function for later reuse.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Acked-by: Sam Ravnborg 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
 drivers/gpu/drm/omapdrm/dss/base.c   | 23 +++
 drivers/gpu/drm/omapdrm/dss/omapdss.h|  1 +
 drivers/gpu/drm/omapdrm/omap_connector.c | 19 +--
 3 files changed, 25 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/base.c 
b/drivers/gpu/drm/omapdrm/dss/base.c
index a1970b9db6ab..cae5687822e2 100644
--- a/drivers/gpu/drm/omapdrm/dss/base.c
+++ b/drivers/gpu/drm/omapdrm/dss/base.c
@@ -285,6 +285,29 @@ void omapdss_device_post_disable(struct omap_dss_device 
*dssdev)
 }
 EXPORT_SYMBOL_GPL(omapdss_device_post_disable);
 
+unsigned int omapdss_device_connector_type(enum omap_display_type type)
+{
+   switch (type) {
+   case OMAP_DISPLAY_TYPE_HDMI:
+   return DRM_MODE_CONNECTOR_HDMIA;
+   case OMAP_DISPLAY_TYPE_DVI:
+   return DRM_MODE_CONNECTOR_DVID;
+   case OMAP_DISPLAY_TYPE_DSI:
+   return DRM_MODE_CONNECTOR_DSI;
+   case OMAP_DISPLAY_TYPE_DPI:
+   case OMAP_DISPLAY_TYPE_DBI:
+   return DRM_MODE_CONNECTOR_DPI;
+   case OMAP_DISPLAY_TYPE_VENC:
+   /* TODO: This could also be composite */
+   return DRM_MODE_CONNECTOR_SVIDEO;
+   case OMAP_DISPLAY_TYPE_SDI:
+   return DRM_MODE_CONNECTOR_LVDS;
+   default:
+   return DRM_MODE_CONNECTOR_Unknown;
+   }
+}
+EXPORT_SYMBOL_GPL(omapdss_device_connector_type);
+
 /* 
-
  * Components Handling
  */
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h 
b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index 79f6b195c7cf..c5672e5174c5 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -479,6 +479,7 @@ void omapdss_device_pre_enable(struct omap_dss_device 
*dssdev);
 void omapdss_device_enable(struct omap_dss_device *dssdev);
 void omapdss_device_disable(struct omap_dss_device *dssdev);
 void omapdss_device_post_disable(struct omap_dss_device *dssdev);
+unsigned int omapdss_device_connector_type(enum omap_display_type type);
 
 int omap_dss_get_num_overlay_managers(void);
 
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c 
b/drivers/gpu/drm/omapdrm/omap_connector.c
index 88dbf3fa473f..38c7a79c5d4a 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -296,24 +296,7 @@ static int omap_connector_get_type(struct omap_dss_device 
*output)
type = display->type;
omapdss_device_put(display);
 
-   switch (type) {
-   case OMAP_DISPLAY_TYPE_HDMI:
-   return DRM_MODE_CONNECTOR_HDMIA;
-   case OMAP_DISPLAY_TYPE_DVI:
-   return DRM_MODE_CONNECTOR_DVID;
-   case OMAP_DISPLAY_TYPE_DSI:
-   return DRM_MODE_CONNECTOR_DSI;
-   case OMAP_DISPLAY_TYPE_DPI:
-   case OMAP_DISPLAY_TYPE_DBI:
-   return DRM_MODE_CONNECTOR_DPI;
-   case OMAP_DISPLAY_TYPE_VENC:
-   /* TODO: This could also be composite */
-   return DRM_MODE_CONNECTOR_SVIDEO;
-   case OMAP_DISPLAY_TYPE_SDI:
-   return DRM_MODE_CONNECTOR_LVDS;
-   default:
-   return DRM_MODE_CONNECTOR_Unknown;
-   }
+   return omapdss_device_connector_type(type);
 }
 
 /* initialize connector */
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 43/54] drm/omap: hdmi4: Simplify EDID read

2020-02-22 Thread Laurent Pinchart
Now that the omap_dss_device EDID read operation has been removed,
simplify the bridge-based EDID access by merging multiple functions
together.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
 drivers/gpu/drm/omapdrm/dss/hdmi4.c | 96 -
 1 file changed, 40 insertions(+), 56 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index 96ef7bd52199..2578c95570f6 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -309,55 +309,6 @@ void hdmi4_core_disable(struct hdmi_core_data *core)
mutex_unlock(>lock);
 }
 
-static struct edid *
-hdmi_do_read_edid(struct omap_hdmi *hdmi,
- struct edid *(*read)(struct omap_hdmi *hdmi,
-  struct drm_connector *connector),
- struct drm_connector *connector)
-{
-   struct edid *edid = NULL;
-   unsigned int cec_addr;
-   bool need_enable;
-   int r;
-
-   need_enable = hdmi->core_enabled == false;
-
-   if (need_enable) {
-   r = hdmi4_core_enable(>core);
-   if (r)
-   return NULL;
-   }
-
-   mutex_lock(>lock);
-   r = hdmi_runtime_get(hdmi);
-   BUG_ON(r);
-
-   r = hdmi4_core_ddc_init(>core);
-   if (r)
-   goto done;
-
-   edid = read(hdmi, connector);
-
-done:
-   hdmi_runtime_put(hdmi);
-   mutex_unlock(>lock);
-
-   if (edid && edid->extensions) {
-   unsigned int len = (edid->extensions + 1) * EDID_LENGTH;
-
-   cec_addr = cec_get_edid_phys_addr((u8 *)edid, len, NULL);
-   } else {
-   cec_addr = CEC_PHYS_ADDR_INVALID;
-   }
-
-   hdmi4_cec_set_phys_addr(>core, cec_addr);
-
-   if (need_enable)
-   hdmi4_core_disable(>core);
-
-   return edid;
-}
-
 /* 
-
  * DRM Bridge Operations
  */
@@ -485,18 +436,51 @@ static void hdmi4_bridge_hpd_notify(struct drm_bridge 
*bridge,
hdmi4_cec_set_phys_addr(>core, CEC_PHYS_ADDR_INVALID);
 }
 
-static struct edid *hdmi4_bridge_read_edid(struct omap_hdmi *hdmi,
-  struct drm_connector *connector)
-{
-   return drm_do_get_edid(connector, hdmi4_core_ddc_read, >core);
-}
-
 static struct edid *hdmi4_bridge_get_edid(struct drm_bridge *bridge,
  struct drm_connector *connector)
 {
struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+   struct edid *edid = NULL;
+   unsigned int cec_addr;
+   bool need_enable;
+   int r;
+
+   need_enable = hdmi->core_enabled == false;
+
+   if (need_enable) {
+   r = hdmi4_core_enable(>core);
+   if (r)
+   return NULL;
+   }
+
+   mutex_lock(>lock);
+   r = hdmi_runtime_get(hdmi);
+   BUG_ON(r);
+
+   r = hdmi4_core_ddc_init(>core);
+   if (r)
+   goto done;
+
+   edid = drm_do_get_edid(connector, hdmi4_core_ddc_read, >core);
 
-   return hdmi_do_read_edid(hdmi, hdmi4_bridge_read_edid, connector);
+done:
+   hdmi_runtime_put(hdmi);
+   mutex_unlock(>lock);
+
+   if (edid && edid->extensions) {
+   unsigned int len = (edid->extensions + 1) * EDID_LENGTH;
+
+   cec_addr = cec_get_edid_phys_addr((u8 *)edid, len, NULL);
+   } else {
+   cec_addr = CEC_PHYS_ADDR_INVALID;
+   }
+
+   hdmi4_cec_set_phys_addr(>core, cec_addr);
+
+   if (need_enable)
+   hdmi4_core_disable(>core);
+
+   return edid;
 }
 
 static const struct drm_bridge_funcs hdmi4_bridge_funcs = {
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 44/54] drm/omap: hdmi5: Simplify EDID read

2020-02-22 Thread Laurent Pinchart
Now that the omap_dss_device EDID read operation has been removed,
simplify the bridge-based EDID access by merging multiple functions
together.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
 drivers/gpu/drm/omapdrm/dss/hdmi5.c | 86 -
 1 file changed, 35 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index 6cb709c775d6..4d4c1fabd0a1 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -307,50 +307,6 @@ static void hdmi_core_disable(struct omap_hdmi *hdmi)
mutex_unlock(>lock);
 }
 
-static struct edid *
-hdmi_do_read_edid(struct omap_hdmi *hdmi,
- struct edid *(*read)(struct omap_hdmi *hdmi,
-  struct drm_connector *connector),
- struct drm_connector *connector)
-{
-   struct edid *edid;
-   bool need_enable;
-   int idlemode;
-   int r;
-
-   need_enable = hdmi->core_enabled == false;
-
-   if (need_enable) {
-   r = hdmi_core_enable(hdmi);
-   if (r)
-   return NULL;
-   }
-
-   mutex_lock(>lock);
-   r = hdmi_runtime_get(hdmi);
-   BUG_ON(r);
-
-   idlemode = REG_GET(hdmi->wp.base, HDMI_WP_SYSCONFIG, 3, 2);
-   /* No-idle mode */
-   REG_FLD_MOD(hdmi->wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2);
-
-   hdmi5_core_ddc_init(>core);
-
-   edid = read(hdmi, connector);
-
-   hdmi5_core_ddc_uninit(>core);
-
-   REG_FLD_MOD(hdmi->wp.base, HDMI_WP_SYSCONFIG, idlemode, 3, 2);
-
-   hdmi_runtime_put(hdmi);
-   mutex_unlock(>lock);
-
-   if (need_enable)
-   hdmi_core_disable(hdmi);
-
-   return (struct edid *)edid;
-}
-
 /* 
-
  * DRM Bridge Operations
  */
@@ -469,18 +425,46 @@ static void hdmi5_bridge_disable(struct drm_bridge 
*bridge,
mutex_unlock(>lock);
 }
 
-static struct edid *hdmi5_bridge_read_edid(struct omap_hdmi *hdmi,
-  struct drm_connector *connector)
-{
-   return drm_do_get_edid(connector, hdmi5_core_ddc_read, >core);
-}
-
 static struct edid *hdmi5_bridge_get_edid(struct drm_bridge *bridge,
  struct drm_connector *connector)
 {
struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+   struct edid *edid;
+   bool need_enable;
+   int idlemode;
+   int r;
+
+   need_enable = hdmi->core_enabled == false;
+
+   if (need_enable) {
+   r = hdmi_core_enable(hdmi);
+   if (r)
+   return NULL;
+   }
+
+   mutex_lock(>lock);
+   r = hdmi_runtime_get(hdmi);
+   BUG_ON(r);
 
-   return hdmi_do_read_edid(hdmi, hdmi5_bridge_read_edid, connector);
+   idlemode = REG_GET(hdmi->wp.base, HDMI_WP_SYSCONFIG, 3, 2);
+   /* No-idle mode */
+   REG_FLD_MOD(hdmi->wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2);
+
+   hdmi5_core_ddc_init(>core);
+
+   edid = drm_do_get_edid(connector, hdmi5_core_ddc_read, >core);
+
+   hdmi5_core_ddc_uninit(>core);
+
+   REG_FLD_MOD(hdmi->wp.base, HDMI_WP_SYSCONFIG, idlemode, 3, 2);
+
+   hdmi_runtime_put(hdmi);
+   mutex_unlock(>lock);
+
+   if (need_enable)
+   hdmi_core_disable(hdmi);
+
+   return (struct edid *)edid;
 }
 
 static const struct drm_bridge_funcs hdmi5_bridge_funcs = {
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 49/54] drm/omap: sdi: Sort includes alphabetically

2020-02-22 Thread Laurent Pinchart
This makes it easier to quickly locate duplicate includes.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
 drivers/gpu/drm/omapdrm/dss/sdi.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c 
b/drivers/gpu/drm/omapdrm/dss/sdi.c
index 11aa2f712ff4..7dedfcc86922 100644
--- a/drivers/gpu/drm/omapdrm/dss/sdi.c
+++ b/drivers/gpu/drm/omapdrm/dss/sdi.c
@@ -6,17 +6,17 @@
 
 #define DSS_SUBSYS_NAME "SDI"
 
-#include 
 #include 
 #include 
-#include 
 #include 
+#include 
+#include 
 #include 
+#include 
 #include 
-#include 
 
-#include "omapdss.h"
 #include "dss.h"
+#include "omapdss.h"
 
 struct sdi_device {
struct platform_device *pdev;
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 33/54] drm/omap: hdmi4: Move mode set, enable and disable operations to bridge

2020-02-22 Thread Laurent Pinchart
Move the omap_dss_device .set_timings(), .enable() and .disable()
operations to the drm_bridge functions. As the drm_bridge for the HDMI
encoder is unconditionally registered and attached, those operations
will be called at the appropriate time.

The omapdss device .set_infoframe() and .set_hdmi_mode() operations have
no equivalent in drm_bridge. Thir content is thus moved to the bridge
.enable() operation as the data they store is not needed before the HDMI
encoder gets enabled.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
Changes since v5:

- Rebased on top of drm_bridge_state

Changes since v2:

- Detail .set_infoframe() and .set_hdmi_mode() handling in the commit
  message
---
 drivers/gpu/drm/omapdrm/dss/hdmi4.c | 206 +++-
 1 file changed, 111 insertions(+), 95 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index 67994287447b..a8d13a081a9a 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -28,6 +28,9 @@
 #include 
 #include 
 
+#include 
+#include 
+
 #include "omapdss.h"
 #include "hdmi4_core.h"
 #include "hdmi4_cec.h"
@@ -237,20 +240,6 @@ static void hdmi_power_off_full(struct omap_hdmi *hdmi)
hdmi_power_off_core(hdmi);
 }
 
-static void hdmi_display_set_timings(struct omap_dss_device *dssdev,
-const struct drm_display_mode *mode)
-{
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
-   mutex_lock(>lock);
-
-   drm_display_mode_to_videomode(mode, >cfg.vm);
-
-   dispc_set_tv_pclk(hdmi->dss->dispc, mode->clock * 1000);
-
-   mutex_unlock(>lock);
-}
-
 static int hdmi_dump_regs(struct seq_file *s, void *p)
 {
struct omap_hdmi *hdmi = s->private;
@@ -284,62 +273,6 @@ static void hdmi_stop_audio_stream(struct omap_hdmi *hd)
hdmi_wp_audio_enable(>wp, false);
 }
 
-static void hdmi_display_enable(struct omap_dss_device *dssdev)
-{
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-   unsigned long flags;
-   int r;
-
-   DSSDBG("ENTER hdmi_display_enable\n");
-
-   mutex_lock(>lock);
-
-   r = hdmi_power_on_full(hdmi);
-   if (r) {
-   DSSERR("failed to power on device\n");
-   goto done;
-   }
-
-   if (hdmi->audio_configured) {
-   r = hdmi4_audio_config(>core, >wp,
-  >audio_config,
-  hdmi->cfg.vm.pixelclock);
-   if (r) {
-   DSSERR("Error restoring audio configuration: %d", r);
-   hdmi->audio_abort_cb(>pdev->dev);
-   hdmi->audio_configured = false;
-   }
-   }
-
-   spin_lock_irqsave(>audio_playing_lock, flags);
-   if (hdmi->audio_configured && hdmi->audio_playing)
-   hdmi_start_audio_stream(hdmi);
-   hdmi->display_enabled = true;
-   spin_unlock_irqrestore(>audio_playing_lock, flags);
-
-done:
-   mutex_unlock(>lock);
-}
-
-static void hdmi_display_disable(struct omap_dss_device *dssdev)
-{
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-   unsigned long flags;
-
-   DSSDBG("Enter hdmi_display_disable\n");
-
-   mutex_lock(>lock);
-
-   spin_lock_irqsave(>audio_playing_lock, flags);
-   hdmi_stop_audio_stream(hdmi);
-   hdmi->display_enabled = false;
-   spin_unlock_irqrestore(>audio_playing_lock, flags);
-
-   hdmi_power_off_full(hdmi);
-
-   mutex_unlock(>lock);
-}
-
 int hdmi4_core_enable(struct hdmi_core_data *core)
 {
struct omap_hdmi *hdmi = container_of(core, struct omap_hdmi, core);
@@ -491,39 +424,14 @@ static void hdmi_lost_hotplug(struct omap_dss_device 
*dssdev)
hdmi4_cec_set_phys_addr(>core, CEC_PHYS_ADDR_INVALID);
 }
 
-static int hdmi_set_infoframe(struct omap_dss_device *dssdev,
-   const struct hdmi_avi_infoframe *avi)
-{
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
-   hdmi->cfg.infoframe = *avi;
-   return 0;
-}
-
-static int hdmi_set_hdmi_mode(struct omap_dss_device *dssdev,
-   bool hdmi_mode)
-{
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
-   hdmi->cfg.hdmi_dvi_mode = hdmi_mode ? HDMI_HDMI : HDMI_DVI;
-   return 0;
-}
-
 static const struct omap_dss_device_ops hdmi_ops = {
.connect= hdmi_connect,
.disconnect = hdmi_disconnect,
 
-   .enable = hdmi_display_enable,
-   .disable= hdmi_display_disable,
-
-   .set_timings= hdmi_display_set_timings,
-
.read_edid  = hdmi_read_edid,
 
.hdmi = {
.lost_hotplug   = hdmi_lost_hotplug,
-   .set_infoframe  = hdmi_set_infoframe,
-   .set_hdmi_mode  = hdmi_set_hdmi_mode,
 

[PATCH v7 35/54] drm/omap: hdmi4: Implement drm_bridge .hpd_notify() operation

2020-02-22 Thread Laurent Pinchart
The HDMI4 encoder is transitioning to the drm_bridge API, implement the
last missing operation.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
 drivers/gpu/drm/omapdrm/dss/hdmi4.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index a8d13a081a9a..73f1fab346e9 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -553,6 +553,15 @@ static void hdmi4_bridge_disable(struct drm_bridge *bridge,
mutex_unlock(>lock);
 }
 
+static void hdmi4_bridge_hpd_notify(struct drm_bridge *bridge,
+   enum drm_connector_status status)
+{
+   struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+
+   if (status == connector_status_disconnected)
+   hdmi4_cec_set_phys_addr(>core, CEC_PHYS_ADDR_INVALID);
+}
+
 static struct edid *hdmi4_bridge_read_edid(struct omap_hdmi *hdmi,
   struct drm_connector *connector)
 {
@@ -575,6 +584,7 @@ static const struct drm_bridge_funcs hdmi4_bridge_funcs = {
.atomic_reset = drm_atomic_helper_bridge_reset,
.atomic_enable = hdmi4_bridge_enable,
.atomic_disable = hdmi4_bridge_disable,
+   .hpd_notify = hdmi4_bridge_hpd_notify,
.get_edid = hdmi4_bridge_get_edid,
 };
 
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 38/54] drm/omap: Create connector for bridges

2020-02-22 Thread Laurent Pinchart
Use the drm_bridge_connector helper to create a connector for pipelines
that use drm_bridge. This allows splitting connector operations across
multiple bridges when necessary, instead of having the last bridge in
the chain creating the connector and handling all connector operations
internally.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
Changes since v3:

- Remove outdated comment

Changes since v1:

- Squash with patch "drm/omap: Detach from panels at remove time"
---
 drivers/gpu/drm/omapdrm/omap_drv.c | 74 +-
 1 file changed, 62 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c 
b/drivers/gpu/drm/omapdrm/omap_drv.c
index 1df509342b5d..47afa37055b3 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -12,10 +12,12 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -291,9 +293,14 @@ static int omap_modeset_init(struct drm_device *dev)
 
if (pipe->output->bridge) {
ret = drm_bridge_attach(pipe->encoder,
-   pipe->output->bridge, NULL, 0);
-   if (ret < 0)
+   pipe->output->bridge, NULL,
+   DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+   if (ret < 0) {
+   dev_err(priv->dev,
+   "unable to attach bridge %pOF\n",
+   pipe->output->bridge->of_node);
return ret;
+   }
}
 
id = omap_display_id(pipe->output);
@@ -329,8 +336,23 @@ static int omap_modeset_init(struct drm_device *dev)
  encoder);
if (!pipe->connector)
return -ENOMEM;
+   } else {
+   pipe->connector = drm_bridge_connector_init(dev, 
encoder);
+   if (IS_ERR(pipe->connector)) {
+   dev_err(priv->dev,
+   "unable to create bridge connector for 
%s\n",
+   pipe->output->name);
+   return PTR_ERR(pipe->connector);
+   }
+   }
 
-   drm_connector_attach_encoder(pipe->connector, encoder);
+   drm_connector_attach_encoder(pipe->connector, encoder);
+
+   if (pipe->output->panel) {
+   ret = drm_panel_attach(pipe->output->panel,
+  pipe->connector);
+   if (ret < 0)
+   return ret;
}
 
crtc = omap_crtc_init(dev, pipe, priv->planes[i]);
@@ -369,6 +391,23 @@ static int omap_modeset_init(struct drm_device *dev)
return 0;
 }
 
+static void omap_modeset_fini(struct drm_device *ddev)
+{
+   struct omap_drm_private *priv = ddev->dev_private;
+   unsigned int i;
+
+   omap_drm_irq_uninstall(ddev);
+
+   for (i = 0; i < priv->num_pipes; i++) {
+   struct omap_drm_pipeline *pipe = >pipes[i];
+
+   if (pipe->output->panel)
+   drm_panel_detach(pipe->output->panel);
+   }
+
+   drm_mode_config_cleanup(ddev);
+}
+
 /*
  * Enable the HPD in external components if supported
  */
@@ -378,8 +417,15 @@ static void omap_modeset_enable_external_hpd(struct 
drm_device *ddev)
unsigned int i;
 
for (i = 0; i < priv->num_pipes; i++) {
-   if (priv->pipes[i].connector)
-   omap_connector_enable_hpd(priv->pipes[i].connector);
+   struct drm_connector *connector = priv->pipes[i].connector;
+
+   if (!connector)
+   continue;
+
+   if (priv->pipes[i].output->next)
+   omap_connector_enable_hpd(connector);
+   else
+   drm_bridge_connector_enable_hpd(connector);
}
 }
 
@@ -392,8 +438,15 @@ static void omap_modeset_disable_external_hpd(struct 
drm_device *ddev)
unsigned int i;
 
for (i = 0; i < priv->num_pipes; i++) {
-   if (priv->pipes[i].connector)
-   omap_connector_disable_hpd(priv->pipes[i].connector);
+   struct drm_connector *connector = priv->pipes[i].connector;
+
+   if (!connector)
+   continue;
+
+   if (priv->pipes[i].output->next)
+   omap_connector_disable_hpd(connector);
+   else
+   drm_bridge_connector_disable_hpd(connector);

[PATCH v7 42/54] drm/omap: venc: Remove omap_dss_device operations

2020-02-22 Thread Laurent Pinchart
Now that the VENC output is driven fully through the drm_bridge API its
omap_dss_device operations are not used anymore. Remove them.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
 drivers/gpu/drm/omapdrm/dss/venc.c | 45 --
 1 file changed, 45 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c 
b/drivers/gpu/drm/omapdrm/dss/venc.c
index c8c19967a42f..766553bb2f87 100644
--- a/drivers/gpu/drm/omapdrm/dss/venc.c
+++ b/drivers/gpu/drm/omapdrm/dss/venc.c
@@ -306,7 +306,6 @@ struct venc_device {
struct drm_bridge bridge;
 };
 
-#define dssdev_to_venc(dssdev) container_of(dssdev, struct venc_device, output)
 #define drm_bridge_to_venc(b) container_of(b, struct venc_device, bridge)
 
 static inline void venc_write_reg(struct venc_device *venc, int idx, u32 val)
@@ -479,30 +478,6 @@ static void venc_power_off(struct venc_device *venc)
venc_runtime_put(venc);
 }
 
-static int venc_get_modes(struct omap_dss_device *dssdev,
- struct drm_connector *connector)
-{
-   static const struct drm_display_mode *modes[] = {
-   _dss_pal_mode,
-   _dss_ntsc_mode,
-   };
-   unsigned int i;
-
-   for (i = 0; i < ARRAY_SIZE(modes); ++i) {
-   struct drm_display_mode *mode;
-
-   mode = drm_mode_duplicate(connector->dev, modes[i]);
-   if (!mode)
-   return i;
-
-   mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
-   drm_mode_set_name(mode);
-   drm_mode_probed_add(connector, mode);
-   }
-
-   return ARRAY_SIZE(modes);
-}
-
 static enum venc_videomode venc_get_videomode(const struct drm_display_mode 
*mode)
 {
if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
@@ -598,25 +573,6 @@ static int venc_get_clocks(struct venc_device *venc)
return 0;
 }
 
-static int venc_connect(struct omap_dss_device *src,
-   struct omap_dss_device *dst)
-{
-   return omapdss_device_connect(dst->dss, dst, dst->next);
-}
-
-static void venc_disconnect(struct omap_dss_device *src,
-   struct omap_dss_device *dst)
-{
-   omapdss_device_disconnect(dst, dst->next);
-}
-
-static const struct omap_dss_device_ops venc_ops = {
-   .connect = venc_connect,
-   .disconnect = venc_disconnect,
-
-   .get_modes = venc_get_modes,
-};
-
 /* 
-
  * DRM Bridge Operations
  */
@@ -816,7 +772,6 @@ static int venc_init_output(struct venc_device *venc)
out->type = OMAP_DISPLAY_TYPE_VENC;
out->name = "venc.0";
out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
-   out->ops = _ops;
out->owner = THIS_MODULE;
out->of_port = 0;
out->ops_flags = OMAP_DSS_DEVICE_OP_MODES;
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 32/54] drm/omap: hdmi5: Register a drm_bridge for EDID read

2020-02-22 Thread Laurent Pinchart
In order to integrate with a chain of drm_bridge, the internal HDMI5
encoder has to expose the EDID read operation through the drm_bridge
API. Register a bridge at initialisation time to do so.

For the time being make the next bridge in the chain optional as the
HDMI output is still based on omap_dss_device. The create_connector
argument to the bridge attach function is also ignored for the same
reason. This will be changed later when removing the related
omapdrm-specific display drivers.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
Changes since v2:

- Unregister bridge if output initialisation fails
---
 drivers/gpu/drm/omapdrm/dss/hdmi5.c | 79 ++---
 1 file changed, 73 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index 2b02b0a11696..e7fe2a24a3e1 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -388,8 +388,10 @@ static void hdmi_disconnect(struct omap_dss_device *src,
 
 #define MAX_EDID   512
 
-static struct edid *hdmi_read_edid_data(struct hdmi_core_data *core)
+static struct edid *hdmi_read_edid_data(struct omap_hdmi *hdmi,
+   struct drm_connector *connector)
 {
+   struct hdmi_core_data *core = >core;
int max_ext_blocks = 3;
int r, n, i;
u8 *edid;
@@ -421,9 +423,12 @@ static struct edid *hdmi_read_edid_data(struct 
hdmi_core_data *core)
return NULL;
 }
 
-static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
+static struct edid *
+hdmi_do_read_edid(struct omap_hdmi *hdmi,
+ struct edid *(*read)(struct omap_hdmi *hdmi,
+  struct drm_connector *connector),
+ struct drm_connector *connector)
 {
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
struct edid *edid;
bool need_enable;
int idlemode;
@@ -447,7 +452,7 @@ static struct edid *hdmi_read_edid(struct omap_dss_device 
*dssdev)
 
hdmi5_core_ddc_init(>core);
 
-   edid = hdmi_read_edid_data(>core);
+   edid = read(hdmi, connector);
 
hdmi5_core_ddc_uninit(>core);
 
@@ -462,6 +467,12 @@ static struct edid *hdmi_read_edid(struct omap_dss_device 
*dssdev)
return (struct edid *)edid;
 }
 
+static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
+{
+   return hdmi_do_read_edid(dssdev_to_hdmi(dssdev), hdmi_read_edid_data,
+NULL);
+}
+
 static int hdmi_set_infoframe(struct omap_dss_device *dssdev,
const struct hdmi_avi_infoframe *avi)
 {
@@ -497,6 +508,56 @@ static const struct omap_dss_device_ops hdmi_ops = {
},
 };
 
+/* 
-
+ * DRM Bridge Operations
+ */
+
+static int hdmi5_bridge_attach(struct drm_bridge *bridge,
+  enum drm_bridge_attach_flags flags)
+{
+   struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+
+   if (!hdmi->output.next_bridge)
+   return 0;
+
+   return drm_bridge_attach(bridge->encoder, hdmi->output.next_bridge,
+bridge, flags);
+}
+
+static struct edid *hdmi5_bridge_read_edid(struct omap_hdmi *hdmi,
+  struct drm_connector *connector)
+{
+   return drm_do_get_edid(connector, hdmi5_core_ddc_read, >core);
+}
+
+static struct edid *hdmi5_bridge_get_edid(struct drm_bridge *bridge,
+ struct drm_connector *connector)
+{
+   struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+
+   return hdmi_do_read_edid(hdmi, hdmi5_bridge_read_edid, connector);
+}
+
+static const struct drm_bridge_funcs hdmi5_bridge_funcs = {
+   .attach = hdmi5_bridge_attach,
+   .get_edid = hdmi5_bridge_get_edid,
+};
+
+static void hdmi5_bridge_init(struct omap_hdmi *hdmi)
+{
+   hdmi->bridge.funcs = _bridge_funcs;
+   hdmi->bridge.of_node = hdmi->pdev->dev.of_node;
+   hdmi->bridge.ops = DRM_BRIDGE_OP_EDID;
+   hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
+
+   drm_bridge_add(>bridge);
+}
+
+static void hdmi5_bridge_cleanup(struct omap_hdmi *hdmi)
+{
+   drm_bridge_remove(>bridge);
+}
+
 /* 
-
  * Audio Callbacks
  */
@@ -679,6 +740,8 @@ static int hdmi5_init_output(struct omap_hdmi *hdmi)
struct omap_dss_device *out = >output;
int r;
 
+   hdmi5_bridge_init(hdmi);
+
out->dev = >pdev->dev;
out->id = OMAP_DSS_OUTPUT_HDMI;
out->type = OMAP_DISPLAY_TYPE_HDMI;
@@ -689,9 +752,11 @@ static int hdmi5_init_output(struct omap_hdmi *hdmi)
out->of_port = 0;
out->ops_flags = OMAP_DSS_DEVICE_OP_EDID;
 
-   r = omapdss_device_init_output(out, NULL);
-   

[PATCH v7 45/54] drm/omap: dpi: Sort includes alphabetically

2020-02-22 Thread Laurent Pinchart
This makes it easier to quickly locate duplicate includes.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
 drivers/gpu/drm/omapdrm/dss/dpi.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c 
b/drivers/gpu/drm/omapdrm/dss/dpi.c
index 2d0eb5fcbb5b..f8354271ce6f 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -9,20 +9,20 @@
 
 #define DSS_SUBSYS_NAME "DPI"
 
-#include 
+#include 
 #include 
-#include 
 #include 
 #include 
+#include 
+#include 
+#include 
 #include 
 #include 
 #include 
-#include 
-#include 
 #include 
 
-#include "omapdss.h"
 #include "dss.h"
+#include "omapdss.h"
 
 struct dpi_data {
struct platform_device *pdev;
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 30/54] drm/omap: hdmi5: Rework EDID read to isolate data read

2020-02-22 Thread Laurent Pinchart
In preparation of adding DRM bridge support to the hdmi5 encoder code,
rework the EDID read to isolate data read.

The hdmi_read_edid() function is the main entry point. It performs all
initialisation steps required prior to reading the EDID (such as
ensuring the device is powered on), as well as corresponding cleanup
steps afterwards. EDID read itself is handled by hdmi_read_edid_data()
that calls the hdmi5_core_ddc_read() function to read individual blocks.

This new code architecture will allow reusing hdmi_read_edid() and
hdmi5_core_ddc_read() for the drm_bridge EDID read implementation, while
swapping out hdmi_read_edid_data() for the DRM drm_do_get_edid()
function.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
Changes since v2:

- Expand commit message
---
 drivers/gpu/drm/omapdrm/dss/hdmi5.c  | 89 ++--
 drivers/gpu/drm/omapdrm/dss/hdmi5_core.c | 48 +++--
 drivers/gpu/drm/omapdrm/dss/hdmi5_core.h |  5 +-
 3 files changed, 65 insertions(+), 77 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index 99720dfc5769..2b02b0a11696 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -271,30 +271,6 @@ static int hdmi_dump_regs(struct seq_file *s, void *p)
return 0;
 }
 
-static int read_edid(struct omap_hdmi *hdmi, u8 *buf, int len)
-{
-   int r;
-   int idlemode;
-
-   mutex_lock(>lock);
-
-   r = hdmi_runtime_get(hdmi);
-   BUG_ON(r);
-
-   idlemode = REG_GET(hdmi->wp.base, HDMI_WP_SYSCONFIG, 3, 2);
-   /* No-idle mode */
-   REG_FLD_MOD(hdmi->wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2);
-
-   r = hdmi5_read_edid(>core,  buf, len);
-
-   REG_FLD_MOD(hdmi->wp.base, HDMI_WP_SYSCONFIG, idlemode, 3, 2);
-
-   hdmi_runtime_put(hdmi);
-   mutex_unlock(>lock);
-
-   return r;
-}
-
 static void hdmi_start_audio_stream(struct omap_hdmi *hd)
 {
REG_FLD_MOD(hd->wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2);
@@ -412,32 +388,73 @@ static void hdmi_disconnect(struct omap_dss_device *src,
 
 #define MAX_EDID   512
 
-static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
+static struct edid *hdmi_read_edid_data(struct hdmi_core_data *core)
 {
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-   bool need_enable;
+   int max_ext_blocks = 3;
+   int r, n, i;
u8 *edid;
-   int r;
 
edid = kzalloc(MAX_EDID, GFP_KERNEL);
if (!edid)
return NULL;
 
+   r = hdmi5_core_ddc_read(core, edid, 0, EDID_LENGTH);
+   if (r)
+   goto error;
+
+   n = edid[0x7e];
+
+   if (n > max_ext_blocks)
+   n = max_ext_blocks;
+
+   for (i = 1; i <= n; i++) {
+   r = hdmi5_core_ddc_read(core, edid + i * EDID_LENGTH, i,
+   EDID_LENGTH);
+   if (r)
+   goto error;
+   }
+
+   return (struct edid *)edid;
+
+error:
+   kfree(edid);
+   return NULL;
+}
+
+static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
+{
+   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
+   struct edid *edid;
+   bool need_enable;
+   int idlemode;
+   int r;
+
need_enable = hdmi->core_enabled == false;
 
if (need_enable) {
r = hdmi_core_enable(hdmi);
-   if (r) {
-   kfree(edid);
+   if (r)
return NULL;
-   }
}
 
-   r = read_edid(hdmi, edid, MAX_EDID);
-   if (r < 0) {
-   kfree(edid);
-   edid = NULL;
-   }
+   mutex_lock(>lock);
+   r = hdmi_runtime_get(hdmi);
+   BUG_ON(r);
+
+   idlemode = REG_GET(hdmi->wp.base, HDMI_WP_SYSCONFIG, 3, 2);
+   /* No-idle mode */
+   REG_FLD_MOD(hdmi->wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2);
+
+   hdmi5_core_ddc_init(>core);
+
+   edid = hdmi_read_edid_data(>core);
+
+   hdmi5_core_ddc_uninit(>core);
+
+   REG_FLD_MOD(hdmi->wp.base, HDMI_WP_SYSCONFIG, idlemode, 3, 2);
+
+   hdmi_runtime_put(hdmi);
+   mutex_unlock(>lock);
 
if (need_enable)
hdmi_core_disable(hdmi);
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c
index ff4d35c8771f..7dd587035160 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c
@@ -23,7 +23,7 @@
 
 #include "hdmi5_core.h"
 
-static void hdmi_core_ddc_init(struct hdmi_core_data *core)
+void hdmi5_core_ddc_init(struct hdmi_core_data *core)
 {
void __iomem *base = core->base;
const unsigned long long iclk = 26600;  /* DSS L3 ICLK */
@@ -102,7 +102,7 @@ static void hdmi_core_ddc_init(struct hdmi_core_data *core)
REG_FLD_MOD(base, HDMI_CORE_I2CM_INT, 0x0, 2, 2);
 }
 
-static 

[PATCH v7 31/54] drm/omap: hdmi4: Register a drm_bridge for EDID read

2020-02-22 Thread Laurent Pinchart
In order to integrate with a chain of drm_bridge, the internal HDMI4
encoder has to expose the EDID read operation through the drm_bridge
API. Register a bridge at initialisation time to do so.

For the time being make the next bridge in the chain optional as the
HDMI output is still based on omap_dss_device. The create_connector
argument to the bridge attach function is also ignored for the same
reason. This will be changed later when removing the related
omapdrm-specific display drivers.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
Changes since v2:

- Unregister bridge if output initialisation fails
---
 drivers/gpu/drm/omapdrm/dss/hdmi.h  |  3 ++
 drivers/gpu/drm/omapdrm/dss/hdmi4.c | 78 ++---
 2 files changed, 75 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi.h 
b/drivers/gpu/drm/omapdrm/dss/hdmi.h
index c867552c925c..bd43f6abf27b 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi.h
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi.h
@@ -14,6 +14,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "omapdss.h"
 #include "dss.h"
@@ -364,6 +365,7 @@ struct omap_hdmi {
bool core_enabled;
 
struct omap_dss_device output;
+   struct drm_bridge bridge;
 
struct platform_device *audio_pdev;
void (*audio_abort_cb)(struct device *dev);
@@ -379,5 +381,6 @@ struct omap_hdmi {
 };
 
 #define dssdev_to_hdmi(dssdev) container_of(dssdev, struct omap_hdmi, output)
+#define drm_bridge_to_hdmi(b) container_of(b, struct omap_hdmi, bridge)
 
 #endif
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index 37536b9f3114..67994287447b 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -390,7 +390,8 @@ static void hdmi_disconnect(struct omap_dss_device *src,
 
 #define MAX_EDID   512
 
-static struct edid *hdmi_read_edid_data(struct omap_hdmi *hdmi)
+static struct edid *hdmi_read_edid_data(struct omap_hdmi *hdmi,
+   struct drm_connector *connector)
 {
u8 *edid;
int r;
@@ -428,9 +429,12 @@ static struct edid *hdmi_read_edid_data(struct omap_hdmi 
*hdmi)
return NULL;
 }
 
-static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
+static struct edid *
+hdmi_do_read_edid(struct omap_hdmi *hdmi,
+ struct edid *(*read)(struct omap_hdmi *hdmi,
+  struct drm_connector *connector),
+ struct drm_connector *connector)
 {
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
struct edid *edid = NULL;
unsigned int cec_addr;
bool need_enable;
@@ -452,7 +456,7 @@ static struct edid *hdmi_read_edid(struct omap_dss_device 
*dssdev)
if (r)
goto done;
 
-   edid = hdmi_read_edid_data(hdmi);
+   edid = read(hdmi, connector);
 
 done:
hdmi_runtime_put(hdmi);
@@ -474,6 +478,12 @@ static struct edid *hdmi_read_edid(struct omap_dss_device 
*dssdev)
return edid;
 }
 
+static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
+{
+   return hdmi_do_read_edid(dssdev_to_hdmi(dssdev), hdmi_read_edid_data,
+NULL);
+}
+
 static void hdmi_lost_hotplug(struct omap_dss_device *dssdev)
 {
struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
@@ -517,6 +527,56 @@ static const struct omap_dss_device_ops hdmi_ops = {
},
 };
 
+/* 
-
+ * DRM Bridge Operations
+ */
+
+static int hdmi4_bridge_attach(struct drm_bridge *bridge,
+  enum drm_bridge_attach_flags flags)
+{
+   struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+
+   if (!hdmi->output.next_bridge)
+   return 0;
+
+   return drm_bridge_attach(bridge->encoder, hdmi->output.next_bridge,
+bridge, flags);
+}
+
+static struct edid *hdmi4_bridge_read_edid(struct omap_hdmi *hdmi,
+  struct drm_connector *connector)
+{
+   return drm_do_get_edid(connector, hdmi4_core_ddc_read, >core);
+}
+
+static struct edid *hdmi4_bridge_get_edid(struct drm_bridge *bridge,
+ struct drm_connector *connector)
+{
+   struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+
+   return hdmi_do_read_edid(hdmi, hdmi4_bridge_read_edid, connector);
+}
+
+static const struct drm_bridge_funcs hdmi4_bridge_funcs = {
+   .attach = hdmi4_bridge_attach,
+   .get_edid = hdmi4_bridge_get_edid,
+};
+
+static void hdmi4_bridge_init(struct omap_hdmi *hdmi)
+{
+   hdmi->bridge.funcs = _bridge_funcs;
+   hdmi->bridge.of_node = hdmi->pdev->dev.of_node;
+   hdmi->bridge.ops = DRM_BRIDGE_OP_EDID;
+   hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
+
+   

[PATCH v7 24/54] drm/omap: Use the drm_panel_bridge API

2020-02-22 Thread Laurent Pinchart
Replace the manual panel handling code by a drm_panel_bridge. This
simplifies the driver and allows all components in the display pipeline
to be treated as bridges, paving the way to generic connector handling.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
Changes since v1:

- Keep #include 
---
 drivers/gpu/drm/omapdrm/dss/base.c   | 12 -
 drivers/gpu/drm/omapdrm/dss/output.c | 31 +---
 drivers/gpu/drm/omapdrm/omap_connector.c | 10 
 drivers/gpu/drm/omapdrm/omap_drv.c   | 13 --
 drivers/gpu/drm/omapdrm/omap_encoder.c   | 13 --
 5 files changed, 32 insertions(+), 47 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/base.c 
b/drivers/gpu/drm/omapdrm/dss/base.c
index cae5687822e2..80d48936d177 100644
--- a/drivers/gpu/drm/omapdrm/dss/base.c
+++ b/drivers/gpu/drm/omapdrm/dss/base.c
@@ -149,8 +149,7 @@ struct omap_dss_device *omapdss_device_next_output(struct 
omap_dss_device *from)
goto done;
}
 
-   if (dssdev->id &&
-   (dssdev->next || dssdev->bridge || dssdev->panel))
+   if (dssdev->id && (dssdev->next || dssdev->bridge))
goto done;
}
 
@@ -185,11 +184,10 @@ int omapdss_device_connect(struct dss_device *dss,
if (!dst) {
/*
 * The destination is NULL when the source is connected to a
-* bridge or panel instead of a DSS device. Stop here, we will
-* attach the bridge or panel later when we will have a DRM
-* encoder.
+* bridge instead of a DSS device. Stop here, we will attach
+* the bridge later when we will have a DRM encoder.
 */
-   return src && (src->bridge || src->panel) ? 0 : -EINVAL;
+   return src && src->bridge ? 0 : -EINVAL;
}
 
if (omapdss_device_is_connected(dst))
@@ -217,7 +215,7 @@ void omapdss_device_disconnect(struct omap_dss_device *src,
dst ? dev_name(dst->dev) : "NULL");
 
if (!dst) {
-   WARN_ON(!src->bridge && !src->panel);
+   WARN_ON(!src->bridge);
return;
}
 
diff --git a/drivers/gpu/drm/omapdrm/dss/output.c 
b/drivers/gpu/drm/omapdrm/dss/output.c
index 0693d34fca1b..99a253a424c1 100644
--- a/drivers/gpu/drm/omapdrm/dss/output.c
+++ b/drivers/gpu/drm/omapdrm/dss/output.c
@@ -21,6 +21,7 @@
 int omapdss_device_init_output(struct omap_dss_device *out)
 {
struct device_node *remote_node;
+   int ret;
 
remote_node = of_graph_get_remote_node(out->dev->of_node,
   ffs(out->of_ports) - 1, 0);
@@ -39,17 +40,39 @@ int omapdss_device_init_output(struct omap_dss_device *out)
 
if (out->next && out->type != out->next->type) {
dev_err(out->dev, "output type and display type don't match\n");
-   omapdss_device_put(out->next);
-   out->next = NULL;
-   return -EINVAL;
+   ret = -EINVAL;
+   goto error;
}
 
-   return out->next || out->bridge || out->panel ? 0 : -EPROBE_DEFER;
+   if (out->panel) {
+   struct drm_bridge *bridge;
+
+   bridge = drm_panel_bridge_add(out->panel);
+   if (IS_ERR(bridge)) {
+   dev_err(out->dev,
+   "unable to create panel bridge (%ld)\n",
+   PTR_ERR(bridge));
+   ret = PTR_ERR(bridge);
+   goto error;
+   }
+
+   out->bridge = bridge;
+   }
+
+   return out->next || out->bridge ? 0 : -EPROBE_DEFER;
+
+error:
+   omapdss_device_put(out->next);
+   out->next = NULL;
+   return ret;
 }
 EXPORT_SYMBOL(omapdss_device_init_output);
 
 void omapdss_device_cleanup_output(struct omap_dss_device *out)
 {
+   if (out->bridge && out->panel)
+   drm_panel_bridge_remove(out->bridge);
+
if (out->next)
omapdss_device_put(out->next);
 }
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c 
b/drivers/gpu/drm/omapdrm/omap_connector.c
index 38c7a79c5d4a..b0cb2ecb30ab 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -6,7 +6,6 @@
 
 #include 
 #include 
-#include 
 #include 
 
 #include "omap_drv.h"
@@ -190,7 +189,6 @@ static int omap_connector_get_modes_edid(struct 
drm_connector *connector,
 
 static int omap_connector_get_modes(struct drm_connector *connector)
 {
-   struct omap_connector *omap_connector = to_omap_connector(connector);
struct omap_dss_device *dssdev;
 
DBG("%s", connector->name);
@@ -213,14 +211,6 @@ static int omap_connector_get_modes(struct drm_connector 
*connector)
if (dssdev)
  

[PATCH v7 37/54] drm/omap: venc: Register a drm_bridge

2020-02-22 Thread Laurent Pinchart
In order to integrate with a chain of drm_bridge, the internal VENC
encoder has to expose the mode valid, fixup and set, the enable and
disable and the get modes operations through the drm_bridge API.
Register a bridge at initialisation time to do so.

Most of those operations are removed from the omap_dss_device as they
are now called through the drm_bridge API by the DRM atomic helpers. The
only exception is the .get_modes() operation that is still invoked
through the omap_dss_device-based pipeline.

For the time being make the next bridge in the chain optional as the
VENC output is still based on omap_dss_device. The create_connector
argument to the bridge attach function is also ignored for the same
reason. This will be changed later when removing the related
omapdrm-specific display drivers.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
Changes since v5:

- Rebased on top of drm_bridge_state

Changes since v4:

- Set bridge interlace_allowed flag

Changes since v3:

- Drop unneeded venc_lock

Changes since v2:

- Unregister bridge if output initialisation fails
---
 drivers/gpu/drm/omapdrm/dss/venc.c | 242 ++---
 1 file changed, 154 insertions(+), 88 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c 
b/drivers/gpu/drm/omapdrm/dss/venc.c
index 977d8d525b43..cb9a689ed612 100644
--- a/drivers/gpu/drm/omapdrm/dss/venc.c
+++ b/drivers/gpu/drm/omapdrm/dss/venc.c
@@ -13,7 +13,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -26,6 +25,8 @@
 #include 
 #include 
 
+#include 
+
 #include "omapdss.h"
 #include "dss.h"
 
@@ -289,7 +290,6 @@ static const struct drm_display_mode omap_dss_ntsc_mode = {
 struct venc_device {
struct platform_device *pdev;
void __iomem *base;
-   struct mutex venc_lock;
struct regulator *vdda_dac_reg;
struct dss_device *dss;
 
@@ -303,9 +303,11 @@ struct venc_device {
bool requires_tv_dac_clk;
 
struct omap_dss_device output;
+   struct drm_bridge bridge;
 };
 
 #define dssdev_to_venc(dssdev) container_of(dssdev, struct venc_device, output)
+#define drm_bridge_to_venc(b) container_of(b, struct venc_device, bridge)
 
 static inline void venc_write_reg(struct venc_device *venc, int idx, u32 val)
 {
@@ -477,32 +479,6 @@ static void venc_power_off(struct venc_device *venc)
venc_runtime_put(venc);
 }
 
-static void venc_display_enable(struct omap_dss_device *dssdev)
-{
-   struct venc_device *venc = dssdev_to_venc(dssdev);
-
-   DSSDBG("venc_display_enable\n");
-
-   mutex_lock(>venc_lock);
-
-   venc_power_on(venc);
-
-   mutex_unlock(>venc_lock);
-}
-
-static void venc_display_disable(struct omap_dss_device *dssdev)
-{
-   struct venc_device *venc = dssdev_to_venc(dssdev);
-
-   DSSDBG("venc_display_disable\n");
-
-   mutex_lock(>venc_lock);
-
-   venc_power_off(venc);
-
-   mutex_unlock(>venc_lock);
-}
-
 static int venc_get_modes(struct omap_dss_device *dssdev,
  struct drm_connector *connector)
 {
@@ -545,57 +521,6 @@ static enum venc_videomode venc_get_videomode(const struct 
drm_display_mode *mod
return VENC_MODE_UNKNOWN;
 }
 
-static void venc_set_timings(struct omap_dss_device *dssdev,
-const struct drm_display_mode *mode)
-{
-   struct venc_device *venc = dssdev_to_venc(dssdev);
-   enum venc_videomode venc_mode = venc_get_videomode(mode);
-
-   DSSDBG("venc_set_timings\n");
-
-   mutex_lock(>venc_lock);
-
-   switch (venc_mode) {
-   default:
-   WARN_ON_ONCE(1);
-   /* Fall-through */
-   case VENC_MODE_PAL:
-   venc->config = _config_pal_trm;
-   break;
-
-   case VENC_MODE_NTSC:
-   venc->config = _config_ntsc_trm;
-   break;
-   }
-
-   dispc_set_tv_pclk(venc->dss->dispc, 1350);
-
-   mutex_unlock(>venc_lock);
-}
-
-static int venc_check_timings(struct omap_dss_device *dssdev,
- struct drm_display_mode *mode)
-{
-   DSSDBG("venc_check_timings\n");
-
-   switch (venc_get_videomode(mode)) {
-   case VENC_MODE_PAL:
-   drm_mode_copy(mode, _dss_pal_mode);
-   break;
-
-   case VENC_MODE_NTSC:
-   drm_mode_copy(mode, _dss_ntsc_mode);
-   break;
-
-   default:
-   return -EINVAL;
-   }
-
-   drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
-   drm_mode_set_name(mode);
-   return 0;
-}
-
 static int venc_dump_regs(struct seq_file *s, void *p)
 {
struct venc_device *venc = s->private;
@@ -689,15 +614,152 @@ static const struct omap_dss_device_ops venc_ops = {
.connect = venc_connect,
.disconnect = venc_disconnect,
 
-   .enable = venc_display_enable,
-   .disable = venc_display_disable,
+   

[PATCH v7 08/54] drm/bridge: Add interlace_allowed flag to drm_bridge

2020-02-22 Thread Laurent Pinchart
In preparation for a connector creation helper based on a chain of
bridges, add a flag to the drm_bridge structure to report support for
interlaced modes. This will be used to set the connector's
interlace_allowed flag.

Signed-off-by: Laurent Pinchart 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
 include/drm/drm_bridge.h | 5 +
 1 file changed, 5 insertions(+)

diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 9d5d750973e9..018e195c4808 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -721,6 +721,11 @@ struct drm_bridge {
 * identifies the type of connected display.
 */
int type;
+   /**
+* @interlace_allowed: Indicate that the bridge can handle interlaced
+* modes.
+*/
+   bool interlace_allowed;
/**
 * @ddc: Associated I2C adapter for DDC access, if any.
 */
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 46/54] drm/omap: dpi: Reorder functions in sections

2020-02-22 Thread Laurent Pinchart
Group functions based on their purpose and split them in sections to
make the source code easier to navigate.

No functional change is included.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
 drivers/gpu/drm/omapdrm/dss/dpi.c | 146 --
 1 file changed, 79 insertions(+), 67 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c 
b/drivers/gpu/drm/omapdrm/dss/dpi.c
index f8354271ce6f..dccf81e4ce64 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -48,6 +48,10 @@ static struct dpi_data *dpi_get_data_from_dssdev(struct 
omap_dss_device *dssdev)
return container_of(dssdev, struct dpi_data, output);
 }
 
+/* 
-
+ * Clock Handling and PLL
+ */
+
 static enum dss_clk_source dpi_get_clk_src_dra7xx(struct dpi_data *dpi,
  enum omap_channel channel)
 {
@@ -366,6 +370,62 @@ static void dpi_config_lcd_manager(struct dpi_data *dpi)
dss_mgr_set_lcd_config(>output, >mgr_config);
 }
 
+static int dpi_verify_pll(struct dss_pll *pll)
+{
+   int r;
+
+   /* do initial setup with the PLL to see if it is operational */
+
+   r = dss_pll_enable(pll);
+   if (r)
+   return r;
+
+   dss_pll_disable(pll);
+
+   return 0;
+}
+
+static void dpi_init_pll(struct dpi_data *dpi)
+{
+   struct dss_pll *pll;
+
+   if (dpi->pll)
+   return;
+
+   dpi->clk_src = dpi_get_clk_src(dpi);
+
+   pll = dss_pll_find_by_src(dpi->dss, dpi->clk_src);
+   if (!pll)
+   return;
+
+   if (dpi_verify_pll(pll)) {
+   DSSWARN("PLL not operational\n");
+   return;
+   }
+
+   dpi->pll = pll;
+}
+
+/* 
-
+ * omap_dss_device Operations
+ */
+
+static int dpi_connect(struct omap_dss_device *src,
+  struct omap_dss_device *dst)
+{
+   struct dpi_data *dpi = dpi_get_data_from_dssdev(dst);
+
+   dpi_init_pll(dpi);
+
+   return omapdss_device_connect(dst->dss, dst, dst->next);
+}
+
+static void dpi_disconnect(struct omap_dss_device *src,
+  struct omap_dss_device *dst)
+{
+   omapdss_device_disconnect(dst, dst->next);
+}
+
 static void dpi_display_enable(struct omap_dss_device *dssdev)
 {
struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
@@ -446,20 +506,6 @@ static void dpi_display_disable(struct omap_dss_device 
*dssdev)
mutex_unlock(>lock);
 }
 
-static void dpi_set_timings(struct omap_dss_device *dssdev,
-   const struct drm_display_mode *mode)
-{
-   struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
-
-   DSSDBG("dpi_set_timings\n");
-
-   mutex_lock(>lock);
-
-   dpi->pixelclock = mode->clock * 1000;
-
-   mutex_unlock(>lock);
-}
-
 static int dpi_check_timings(struct omap_dss_device *dssdev,
 struct drm_display_mode *mode)
 {
@@ -500,41 +546,30 @@ static int dpi_check_timings(struct omap_dss_device 
*dssdev,
return 0;
 }
 
-static int dpi_verify_pll(struct dss_pll *pll)
+static void dpi_set_timings(struct omap_dss_device *dssdev,
+   const struct drm_display_mode *mode)
 {
-   int r;
+   struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
 
-   /* do initial setup with the PLL to see if it is operational */
+   DSSDBG("dpi_set_timings\n");
 
-   r = dss_pll_enable(pll);
-   if (r)
-   return r;
+   mutex_lock(>lock);
 
-   dss_pll_disable(pll);
+   dpi->pixelclock = mode->clock * 1000;
 
-   return 0;
+   mutex_unlock(>lock);
 }
 
-static void dpi_init_pll(struct dpi_data *dpi)
-{
-   struct dss_pll *pll;
-
-   if (dpi->pll)
-   return;
-
-   dpi->clk_src = dpi_get_clk_src(dpi);
-
-   pll = dss_pll_find_by_src(dpi->dss, dpi->clk_src);
-   if (!pll)
-   return;
+static const struct omap_dss_device_ops dpi_ops = {
+   .connect = dpi_connect,
+   .disconnect = dpi_disconnect,
 
-   if (dpi_verify_pll(pll)) {
-   DSSWARN("PLL not operational\n");
-   return;
-   }
+   .enable = dpi_display_enable,
+   .disable = dpi_display_disable,
 
-   dpi->pll = pll;
-}
+   .check_timings = dpi_check_timings,
+   .set_timings = dpi_set_timings,
+};
 
 /*
  * Return a hardcoded channel for the DPI output. This should work for
@@ -572,33 +607,6 @@ static enum omap_channel dpi_get_channel(struct dpi_data 
*dpi)
}
 }
 
-static int dpi_connect(struct omap_dss_device *src,
-  struct omap_dss_device *dst)
-{
-   struct dpi_data *dpi = dpi_get_data_from_dssdev(dst);
-
-   dpi_init_pll(dpi);
-
-   return 

[PATCH v7 26/54] drm/omap: Add infrastructure to support drm_bridge local to DSS outputs

2020-02-22 Thread Laurent Pinchart
In order to support drm_bridge-based pipeline, the internal HDMI
encoders will need to expose the EDID read operation through the
drm_bridge API, and thus to expose a drm_bridge instance corresponding
to the encoder. The HDMI encoders are however handled as omap_dss_device
instances, which conflicts with this requirement.

In order to move forward with the drm_bridge transition, add support for
creating drm_bridge instances local to DSS outputs. If a local bridge is
passed to the omapdss_device_init_output() function, it is used as the
first bridge in the chain, and the omap_dss_device.next_bridge field is
set to the next bridge for the use of the internal encoders' bridges.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
 drivers/gpu/drm/omapdrm/dss/dpi.c |  2 +-
 drivers/gpu/drm/omapdrm/dss/dsi.c |  2 +-
 drivers/gpu/drm/omapdrm/dss/hdmi4.c   |  2 +-
 drivers/gpu/drm/omapdrm/dss/hdmi5.c   |  2 +-
 drivers/gpu/drm/omapdrm/dss/omapdss.h |  4 +++-
 drivers/gpu/drm/omapdrm/dss/output.c  | 20 
 drivers/gpu/drm/omapdrm/dss/sdi.c |  2 +-
 drivers/gpu/drm/omapdrm/dss/venc.c|  2 +-
 drivers/gpu/drm/omapdrm/omap_drv.c|  2 +-
 9 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c 
b/drivers/gpu/drm/omapdrm/dss/dpi.c
index 462ed6f3118a..2d0eb5fcbb5b 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -629,7 +629,7 @@ static int dpi_init_output_port(struct dpi_data *dpi, 
struct device_node *port)
out->ops = _ops;
out->owner = THIS_MODULE;
 
-   r = omapdss_device_init_output(out);
+   r = omapdss_device_init_output(out, NULL);
if (r < 0)
return r;
 
diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c 
b/drivers/gpu/drm/omapdrm/dss/dsi.c
index 6379eea124d1..79ddfbfd1b58 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -5121,7 +5121,7 @@ static int dsi_init_output(struct dsi_data *dsi)
   | DRM_BUS_FLAG_DE_HIGH
   | DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE;
 
-   r = omapdss_device_init_output(out);
+   r = omapdss_device_init_output(out, NULL);
if (r < 0)
return r;
 
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index 44075718407b..dd4a14fe7e59 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -676,7 +676,7 @@ static int hdmi4_init_output(struct omap_hdmi *hdmi)
out->of_port = 0;
out->ops_flags = OMAP_DSS_DEVICE_OP_EDID;
 
-   r = omapdss_device_init_output(out);
+   r = omapdss_device_init_output(out, NULL);
if (r < 0)
return r;
 
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index 1b5bd44ee09d..8e3790dd8b98 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -660,7 +660,7 @@ static int hdmi5_init_output(struct omap_hdmi *hdmi)
out->of_port = 0;
out->ops_flags = OMAP_DSS_DEVICE_OP_EDID;
 
-   r = omapdss_device_init_output(out);
+   r = omapdss_device_init_output(out, NULL);
if (r < 0)
return r;
 
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h 
b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index b48a51d11310..82e9bfa5530a 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -400,6 +400,7 @@ struct omap_dss_device {
struct dss_device *dss;
struct omap_dss_device *next;
struct drm_bridge *bridge;
+   struct drm_bridge *next_bridge;
struct drm_panel *panel;
 
struct list_head list;
@@ -488,7 +489,8 @@ int omap_dss_get_num_overlays(void);
 #define for_each_dss_output(d) \
while ((d = omapdss_device_next_output(d)) != NULL)
 struct omap_dss_device *omapdss_device_next_output(struct omap_dss_device 
*from);
-int omapdss_device_init_output(struct omap_dss_device *out);
+int omapdss_device_init_output(struct omap_dss_device *out,
+  struct drm_bridge *local_bridge);
 void omapdss_device_cleanup_output(struct omap_dss_device *out);
 
 typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
diff --git a/drivers/gpu/drm/omapdrm/dss/output.c 
b/drivers/gpu/drm/omapdrm/dss/output.c
index c1ec9d343e53..9ba7cc8539a1 100644
--- a/drivers/gpu/drm/omapdrm/dss/output.c
+++ b/drivers/gpu/drm/omapdrm/dss/output.c
@@ -17,7 +17,8 @@
 #include "dss.h"
 #include "omapdss.h"
 
-int omapdss_device_init_output(struct omap_dss_device *out)
+int omapdss_device_init_output(struct omap_dss_device *out,
+  struct drm_bridge *local_bridge)
 {
struct device_node *remote_node;
int ret;
@@ -58,10 +59,20 @@ int omapdss_device_init_output(struct omap_dss_device *out)

[PATCH v7 22/54] drm/omap: Simplify HDMI mode and infoframe configuration

2020-02-22 Thread Laurent Pinchart
Remove the omap_connector_get_hdmi_mode() function as the HDMI mode can
be accessed directly from the connector's display info.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Acked-by: Sam Ravnborg 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
 drivers/gpu/drm/omapdrm/omap_connector.c | 11 ---
 drivers/gpu/drm/omapdrm/omap_connector.h |  1 -
 drivers/gpu/drm/omapdrm/omap_encoder.c   |  4 +---
 3 files changed, 1 insertion(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c 
b/drivers/gpu/drm/omapdrm/omap_connector.c
index 94cded387174..88dbf3fa473f 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -21,7 +21,6 @@ struct omap_connector {
struct drm_connector base;
struct omap_dss_device *output;
struct omap_dss_device *hpd;
-   bool hdmi_mode;
 };
 
 static void omap_connector_hpd_notify(struct drm_connector *connector,
@@ -84,13 +83,6 @@ void omap_connector_disable_hpd(struct drm_connector 
*connector)
hpd->ops->unregister_hpd_cb(hpd);
 }
 
-bool omap_connector_get_hdmi_mode(struct drm_connector *connector)
-{
-   struct omap_connector *omap_connector = to_omap_connector(connector);
-
-   return omap_connector->hdmi_mode;
-}
-
 static struct omap_dss_device *
 omap_connector_find_device(struct drm_connector *connector,
   enum omap_dss_device_ops_flag op)
@@ -167,7 +159,6 @@ static void omap_connector_destroy(struct drm_connector 
*connector)
 static int omap_connector_get_modes_edid(struct drm_connector *connector,
 struct omap_dss_device *dssdev)
 {
-   struct omap_connector *omap_connector = to_omap_connector(connector);
enum drm_connector_status status;
void *edid;
int n;
@@ -189,8 +180,6 @@ static int omap_connector_get_modes_edid(struct 
drm_connector *connector,
drm_connector_update_edid_property(connector, edid);
n = drm_add_edid_modes(connector, edid);
 
-   omap_connector->hdmi_mode = drm_detect_hdmi_monitor(edid);
-
kfree(edid);
return n;
 
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.h 
b/drivers/gpu/drm/omapdrm/omap_connector.h
index 13607bda33d8..4aa5608f4bbe 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.h
+++ b/drivers/gpu/drm/omapdrm/omap_connector.h
@@ -21,7 +21,6 @@ struct omap_dss_device;
 struct drm_connector *omap_connector_init(struct drm_device *dev,
  struct omap_dss_device *output,
  struct drm_encoder *encoder);
-bool omap_connector_get_hdmi_mode(struct drm_connector *connector);
 void omap_connector_enable_hpd(struct drm_connector *connector);
 void omap_connector_disable_hpd(struct drm_connector *connector);
 enum drm_mode_status omap_connector_mode_fixup(struct omap_dss_device *dssdev,
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c 
b/drivers/gpu/drm/omapdrm/omap_encoder.c
index 4f2165a37795..cb5aa01d2f87 100644
--- a/drivers/gpu/drm/omapdrm/omap_encoder.c
+++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
@@ -76,9 +76,7 @@ static void omap_encoder_hdmi_mode_set(struct drm_connector 
*connector,
 {
struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
struct omap_dss_device *dssdev = omap_encoder->output;
-   bool hdmi_mode;
-
-   hdmi_mode = omap_connector_get_hdmi_mode(connector);
+   bool hdmi_mode = connector->display_info.is_hdmi;
 
if (dssdev->ops->hdmi.set_hdmi_mode)
dssdev->ops->hdmi.set_hdmi_mode(dssdev, hdmi_mode);
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 47/54] drm/omap: dpi: Simplify clock setting API

2020-02-22 Thread Laurent Pinchart
The dpi_set_pll_clk() and dpi_set_dispc_clk() return various information
through pointer arguments that are never used by the callers. Remove
them to simplify the clock setting API.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
 drivers/gpu/drm/omapdrm/dss/dpi.c | 32 ---
 1 file changed, 8 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c 
b/drivers/gpu/drm/omapdrm/dss/dpi.c
index dccf81e4ce64..c167bd1116ec 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -287,9 +287,7 @@ static bool dpi_dss_clk_calc(struct dpi_data *dpi, unsigned 
long pck,
 
 
 
-static int dpi_set_pll_clk(struct dpi_data *dpi, enum omap_channel channel,
-   unsigned long pck_req, unsigned long *fck, int *lck_div,
-   int *pck_div)
+static int dpi_set_pll_clk(struct dpi_data *dpi, unsigned long pck_req)
 {
struct dpi_clk_calc_ctx ctx;
int r;
@@ -303,19 +301,15 @@ static int dpi_set_pll_clk(struct dpi_data *dpi, enum 
omap_channel channel,
if (r)
return r;
 
-   dss_select_lcd_clk_source(dpi->dss, channel, dpi->clk_src);
+   dss_select_lcd_clk_source(dpi->dss, dpi->output.dispc_channel,
+ dpi->clk_src);
 
dpi->mgr_config.clock_info = ctx.dispc_cinfo;
 
-   *fck = ctx.pll_cinfo.clkout[ctx.clkout_idx];
-   *lck_div = ctx.dispc_cinfo.lck_div;
-   *pck_div = ctx.dispc_cinfo.pck_div;
-
return 0;
 }
 
-static int dpi_set_dispc_clk(struct dpi_data *dpi, unsigned long pck_req,
-   unsigned long *fck, int *lck_div, int *pck_div)
+static int dpi_set_dispc_clk(struct dpi_data *dpi, unsigned long pck_req)
 {
struct dpi_clk_calc_ctx ctx;
int r;
@@ -331,29 +325,19 @@ static int dpi_set_dispc_clk(struct dpi_data *dpi, 
unsigned long pck_req,
 
dpi->mgr_config.clock_info = ctx.dispc_cinfo;
 
-   *fck = ctx.fck;
-   *lck_div = ctx.dispc_cinfo.lck_div;
-   *pck_div = ctx.dispc_cinfo.pck_div;
-
return 0;
 }
 
 static int dpi_set_mode(struct dpi_data *dpi)
 {
-   int lck_div = 0, pck_div = 0;
-   unsigned long fck = 0;
-   int r = 0;
+   int r;
 
if (dpi->pll)
-   r = dpi_set_pll_clk(dpi, dpi->output.dispc_channel,
-   dpi->pixelclock, , _div, _div);
+   r = dpi_set_pll_clk(dpi, dpi->pixelclock);
else
-   r = dpi_set_dispc_clk(dpi, dpi->pixelclock, ,
-   _div, _div);
-   if (r)
-   return r;
+   r = dpi_set_dispc_clk(dpi, dpi->pixelclock);
 
-   return 0;
+   return r;
 }
 
 static void dpi_config_lcd_manager(struct dpi_data *dpi)
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 25/54] drm/omap: dss: Fix output next device lookup in DT

2020-02-22 Thread Laurent Pinchart
The DSS core looks up the next device connected to an output by
traversing the OF graph. It currently hardcodes the local port number to
0, which breaks any output with a different port number (SDI on OMAP3
and any DPI output but the first one). Fix this by repurposing the
currently unused of_ports bitmask in omap_dss_device with an of_port
output port number, and use it to traverse the OF graph.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
 drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c | 2 +-
 drivers/gpu/drm/omapdrm/displays/connector-hdmi.c  | 2 +-
 drivers/gpu/drm/omapdrm/displays/encoder-opa362.c  | 2 +-
 drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c   | 2 +-
 drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c| 2 +-
 drivers/gpu/drm/omapdrm/dss/dpi.c  | 2 +-
 drivers/gpu/drm/omapdrm/dss/dsi.c  | 2 +-
 drivers/gpu/drm/omapdrm/dss/hdmi4.c| 2 +-
 drivers/gpu/drm/omapdrm/dss/hdmi5.c| 2 +-
 drivers/gpu/drm/omapdrm/dss/omapdss.h  | 4 ++--
 drivers/gpu/drm/omapdrm/dss/output.c   | 3 +--
 drivers/gpu/drm/omapdrm/dss/sdi.c  | 2 +-
 drivers/gpu/drm/omapdrm/dss/venc.c | 2 +-
 13 files changed, 14 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c 
b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c
index 0d20fab605d7..f36aa1885d39 100644
--- a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c
+++ b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c
@@ -55,7 +55,7 @@ static int tvc_probe(struct platform_device *pdev)
dssdev->type = OMAP_DISPLAY_TYPE_VENC;
dssdev->display = true;
dssdev->owner = THIS_MODULE;
-   dssdev->of_ports = BIT(0);
+   dssdev->of_port = 0;
 
omapdss_display_init(dssdev);
omapdss_device_register(dssdev);
diff --git a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c 
b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
index f5d69d810bb8..37c212491cd3 100644
--- a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
+++ b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
@@ -139,7 +139,7 @@ static int hdmic_probe(struct platform_device *pdev)
dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
dssdev->display = true;
dssdev->owner = THIS_MODULE;
-   dssdev->of_ports = BIT(0);
+   dssdev->of_port = 0;
dssdev->ops_flags = ddata->hpd_gpio
  ? OMAP_DSS_DEVICE_OP_DETECT | OMAP_DSS_DEVICE_OP_HPD
  : 0;
diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c 
b/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
index b992387ed674..252705222ef1 100644
--- a/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
+++ b/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
@@ -86,7 +86,7 @@ static int opa362_probe(struct platform_device *pdev)
dssdev->dev = >dev;
dssdev->type = OMAP_DISPLAY_TYPE_VENC;
dssdev->owner = THIS_MODULE;
-   dssdev->of_ports = BIT(1) | BIT(0);
+   dssdev->of_port = 1;
 
dssdev->next = omapdss_of_find_connected_device(pdev->dev.of_node, 1);
if (IS_ERR(dssdev->next)) {
diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c 
b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
index 089105c5aa0a..857ae84cd7d1 100644
--- a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
+++ b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
@@ -165,7 +165,7 @@ static int tpd_probe(struct platform_device *pdev)
dssdev->dev = >dev;
dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
dssdev->owner = THIS_MODULE;
-   dssdev->of_ports = BIT(1) | BIT(0);
+   dssdev->of_port = 1;
dssdev->ops_flags = OMAP_DSS_DEVICE_OP_DETECT
  | OMAP_DSS_DEVICE_OP_HPD;
 
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c 
b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
index 3ec6a55e932a..3484b5d4a91c 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
@@ -1265,7 +1265,7 @@ static int dsicm_probe(struct platform_device *pdev)
dssdev->type = OMAP_DISPLAY_TYPE_DSI;
dssdev->display = true;
dssdev->owner = THIS_MODULE;
-   dssdev->of_ports = BIT(0);
+   dssdev->of_port = 0;
dssdev->ops_flags = OMAP_DSS_DEVICE_OP_MODES;
 
dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c 
b/drivers/gpu/drm/omapdrm/dss/dpi.c
index 95147437b990..462ed6f3118a 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -625,7 +625,7 @@ static int dpi_init_output_port(struct dpi_data *dpi, 
struct device_node *port)
out->id = OMAP_DSS_OUTPUT_DPI;
out->type = 

[PATCH v7 36/54] drm/omap: dss: Remove .set_hdmi_mode() and .set_infoframe() operations

2020-02-22 Thread Laurent Pinchart
The omapdss_hdmi_ops .set_hdmi_mode() and .set_infoframe() operations
operations are not used anymore, remove them.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
 drivers/gpu/drm/omapdrm/dss/omapdss.h  |  3 ---
 drivers/gpu/drm/omapdrm/omap_encoder.c | 26 --
 2 files changed, 29 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h 
b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index 269e143d57be..30a12cf91cbb 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -287,9 +287,6 @@ struct omap_dss_writeback_info {
 
 struct omapdss_hdmi_ops {
void (*lost_hotplug)(struct omap_dss_device *dssdev);
-   int (*set_hdmi_mode)(struct omap_dss_device *dssdev, bool hdmi_mode);
-   int (*set_infoframe)(struct omap_dss_device *dssdev,
-   const struct hdmi_avi_infoframe *avi);
 };
 
 struct omapdss_dsi_ops {
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c 
b/drivers/gpu/drm/omapdrm/omap_encoder.c
index b232acd3bc3d..18a79dde6815 100644
--- a/drivers/gpu/drm/omapdrm/omap_encoder.c
+++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
@@ -69,28 +69,6 @@ static void omap_encoder_update_videomode_flags(struct 
videomode *vm,
}
 }
 
-static void omap_encoder_hdmi_mode_set(struct drm_connector *connector,
-  struct drm_encoder *encoder,
-  struct drm_display_mode *adjusted_mode)
-{
-   struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
-   struct omap_dss_device *dssdev = omap_encoder->output;
-   bool hdmi_mode = connector->display_info.is_hdmi;
-
-   if (dssdev->ops && dssdev->ops->hdmi.set_hdmi_mode)
-   dssdev->ops->hdmi.set_hdmi_mode(dssdev, hdmi_mode);
-
-   if (hdmi_mode && dssdev->ops && dssdev->ops->hdmi.set_infoframe) {
-   struct hdmi_avi_infoframe avi;
-   int r;
-
-   r = drm_hdmi_avi_infoframe_from_display_mode(, connector,
-adjusted_mode);
-   if (r == 0)
-   dssdev->ops->hdmi.set_infoframe(dssdev, );
-   }
-}
-
 static void omap_encoder_mode_set(struct drm_encoder *encoder,
  struct drm_display_mode *mode,
  struct drm_display_mode *adjusted_mode)
@@ -142,10 +120,6 @@ static void omap_encoder_mode_set(struct drm_encoder 
*encoder,
if (dssdev->ops && dssdev->ops->set_timings)
dssdev->ops->set_timings(dssdev, adjusted_mode);
}
-
-   /* Set the HDMI mode and HDMI infoframe if applicable. */
-   if (output->type == OMAP_DISPLAY_TYPE_HDMI)
-   omap_encoder_hdmi_mode_set(connector, encoder, adjusted_mode);
 }
 
 static void omap_encoder_disable(struct drm_encoder *encoder)
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 16/54] drm/bridge: Add driver for the TI TPD12S015 HDMI level shifter

2020-02-22 Thread Laurent Pinchart
The TI TPD12S015 is an HDMI level shifter and ESD protector controlled
through GPIOs. Add a DRM bridge driver for the device.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Acked-by: Sam Ravnborg 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
Changes since v2:

- Control CT_CP_HPD GPIO from .hpd_enable() and .hpd_disable()
- Remove unneeded hpd_gpio zero check
- Update copyright notice

Changes since v1:

- Remove empty .hpd_enable() and .hpd_disable() operations
---
 drivers/gpu/drm/bridge/Kconfig|   8 +
 drivers/gpu/drm/bridge/Makefile   |   1 +
 drivers/gpu/drm/bridge/ti-tpd12s015.c | 211 ++
 3 files changed, 220 insertions(+)
 create mode 100644 drivers/gpu/drm/bridge/ti-tpd12s015.c

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index d63283661850..aaed2347ace9 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -172,6 +172,14 @@ config DRM_TI_SN65DSI86
help
  Texas Instruments SN65DSI86 DSI to eDP Bridge driver
 
+config DRM_TI_TPD12S015
+   tristate "TI TPD12S015 HDMI level shifter and ESD protection"
+   depends on OF
+   select DRM_KMS_HELPER
+   help
+ Texas Instruments TPD12S015 HDMI level shifter and ESD protection
+ driver.
+
 source "drivers/gpu/drm/bridge/analogix/Kconfig"
 
 source "drivers/gpu/drm/bridge/adv7511/Kconfig"
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index 17f1f155e803..6fb062b5b0f0 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_DRM_TOSHIBA_TC358768) += tc358768.o
 obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/
 obj-$(CONFIG_DRM_TI_SN65DSI86) += ti-sn65dsi86.o
 obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o
+obj-$(CONFIG_DRM_TI_TPD12S015) += ti-tpd12s015.o
 
 obj-y += analogix/
 obj-y += synopsys/
diff --git a/drivers/gpu/drm/bridge/ti-tpd12s015.c 
b/drivers/gpu/drm/bridge/ti-tpd12s015.c
new file mode 100644
index ..514cbf0eac75
--- /dev/null
+++ b/drivers/gpu/drm/bridge/ti-tpd12s015.c
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * TPD12S015 HDMI ESD protection & level shifter chip driver
+ *
+ * Copyright (C) 2019 Texas Instruments Incorporated
+ *
+ * Based on the omapdrm-specific encoder-opa362 driver
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated
+ * Author: Tomi Valkeinen 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+struct tpd12s015_device {
+   struct drm_bridge bridge;
+
+   struct gpio_desc *ct_cp_hpd_gpio;
+   struct gpio_desc *ls_oe_gpio;
+   struct gpio_desc *hpd_gpio;
+   int hpd_irq;
+
+   struct drm_bridge *next_bridge;
+};
+
+static inline struct tpd12s015_device *to_tpd12s015(struct drm_bridge *bridge)
+{
+   return container_of(bridge, struct tpd12s015_device, bridge);
+}
+
+static int tpd12s015_attach(struct drm_bridge *bridge,
+   enum drm_bridge_attach_flags flags)
+{
+   struct tpd12s015_device *tpd = to_tpd12s015(bridge);
+   int ret;
+
+   if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
+   return -EINVAL;
+
+   ret = drm_bridge_attach(bridge->encoder, tpd->next_bridge,
+   bridge, flags);
+   if (ret < 0)
+   return ret;
+
+   gpiod_set_value_cansleep(tpd->ls_oe_gpio, 1);
+
+   /* DC-DC converter needs at max 300us to get to 90% of 5V. */
+   usleep_range(300, 1000);
+
+   return 0;
+}
+
+static void tpd12s015_detach(struct drm_bridge *bridge)
+{
+   struct tpd12s015_device *tpd = to_tpd12s015(bridge);
+
+   gpiod_set_value_cansleep(tpd->ls_oe_gpio, 0);
+}
+
+static enum drm_connector_status tpd12s015_detect(struct drm_bridge *bridge)
+{
+   struct tpd12s015_device *tpd = to_tpd12s015(bridge);
+
+   if (gpiod_get_value_cansleep(tpd->hpd_gpio))
+   return connector_status_connected;
+   else
+   return connector_status_disconnected;
+}
+
+static void tpd12s015_hpd_enable(struct drm_bridge *bridge)
+{
+   struct tpd12s015_device *tpd = to_tpd12s015(bridge);
+
+   gpiod_set_value_cansleep(tpd->ct_cp_hpd_gpio, 1);
+}
+
+static void tpd12s015_hpd_disable(struct drm_bridge *bridge)
+{
+   struct tpd12s015_device *tpd = to_tpd12s015(bridge);
+
+   gpiod_set_value_cansleep(tpd->ct_cp_hpd_gpio, 0);
+}
+
+static const struct drm_bridge_funcs tpd12s015_bridge_funcs = {
+   .attach = tpd12s015_attach,
+   .detach = tpd12s015_detach,
+   .detect = tpd12s015_detect,
+   .hpd_enable = tpd12s015_hpd_enable,
+   .hpd_disable= tpd12s015_hpd_disable,
+};
+
+static irqreturn_t tpd12s015_hpd_isr(int irq, void *data)
+{
+   struct tpd12s015_device *tpd = data;
+   struct drm_bridge *bridge = >bridge;
+
+   

[PATCH v7 19/54] drm/bridge: tfp410: Allow operation without drm_connector

2020-02-22 Thread Laurent Pinchart
The tfp410 driver can operate as part of a pipeline where the
drm_connector is created by the display controller. Enable this mode of
operation by skipping creation of a drm_connector internally.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Boris Brezillon 
Acked-by: Sam Ravnborg 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
 drivers/gpu/drm/bridge/ti-tfp410.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c 
b/drivers/gpu/drm/bridge/ti-tfp410.c
index 2b8741ebc696..40c4d4a5517b 100644
--- a/drivers/gpu/drm/bridge/ti-tfp410.c
+++ b/drivers/gpu/drm/bridge/ti-tfp410.c
@@ -124,10 +124,8 @@ static int tfp410_attach(struct drm_bridge *bridge,
if (ret < 0)
return ret;
 
-   if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
-   DRM_ERROR("Fix bridge driver to make connector optional!");
-   return -EINVAL;
-   }
+   if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
+   return 0;
 
if (!bridge->encoder) {
dev_err(dvi->dev, "Missing encoder\n");
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 12/54] drm/bridge: simple-bridge: Add support for non-VGA bridges

2020-02-22 Thread Laurent Pinchart
Create a new simple_bridge_info structure that stores information about
the bridge model, and store the bridge timings in there, along with the
connector type. Use that new structure for of_device_id data. This
enables support for non-VGA bridges.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Andrzej Hajda 
Reviewed-by: Stefan Agner 
Reviewed-by: Boris Brezillon 
Reviewed-by: Maxime Ripard 
Acked-by: Sam Ravnborg 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
Changes since v1:

- Renamed simple_bridge_info.type field to connector_type
---
 drivers/gpu/drm/bridge/simple-bridge.c | 41 ++
 1 file changed, 29 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/bridge/simple-bridge.c 
b/drivers/gpu/drm/bridge/simple-bridge.c
index 00d810c99193..20866c1230de 100644
--- a/drivers/gpu/drm/bridge/simple-bridge.c
+++ b/drivers/gpu/drm/bridge/simple-bridge.c
@@ -17,10 +17,17 @@
 #include 
 #include 
 
+struct simple_bridge_info {
+   const struct drm_bridge_timings *timings;
+   unsigned int connector_type;
+};
+
 struct simple_bridge {
struct drm_bridge   bridge;
struct drm_connectorconnector;
 
+   const struct simple_bridge_info *info;
+
struct i2c_adapter  *ddc;
struct regulator*vdd;
 };
@@ -120,7 +127,7 @@ static int simple_bridge_attach(struct drm_bridge *bridge,
 _bridge_con_helper_funcs);
ret = drm_connector_init_with_ddc(bridge->dev, >connector,
  _bridge_con_funcs,
- DRM_MODE_CONNECTOR_VGA,
+ sbridge->info->connector_type,
  sbridge->ddc);
if (ret) {
DRM_ERROR("Failed to initialize connector\n");
@@ -190,6 +197,8 @@ static int simple_bridge_probe(struct platform_device *pdev)
return -ENOMEM;
platform_set_drvdata(pdev, sbridge);
 
+   sbridge->info = of_device_get_match_data(>dev);
+
sbridge->vdd = devm_regulator_get_optional(>dev, "vdd");
if (IS_ERR(sbridge->vdd)) {
int ret = PTR_ERR(sbridge->vdd);
@@ -213,7 +222,7 @@ static int simple_bridge_probe(struct platform_device *pdev)
 
sbridge->bridge.funcs = _bridge_bridge_funcs;
sbridge->bridge.of_node = pdev->dev.of_node;
-   sbridge->bridge.timings = of_device_get_match_data(>dev);
+   sbridge->bridge.timings = sbridge->info->timings;
 
drm_bridge_add(>bridge);
 
@@ -273,19 +282,27 @@ static const struct drm_bridge_timings 
ti_ths8135_bridge_timings = {
 static const struct of_device_id simple_bridge_match[] = {
{
.compatible = "dumb-vga-dac",
-   .data = NULL,
-   },
-   {
+   .data = &(const struct simple_bridge_info) {
+   .connector_type = DRM_MODE_CONNECTOR_VGA,
+   },
+   }, {
.compatible = "adi,adv7123",
-   .data = _bridge_timings,
-   },
-   {
+   .data = &(const struct simple_bridge_info) {
+   .timings = _bridge_timings,
+   .connector_type = DRM_MODE_CONNECTOR_VGA,
+   },
+   }, {
.compatible = "ti,ths8135",
-   .data = _ths8135_bridge_timings,
-   },
-   {
+   .data = &(const struct simple_bridge_info) {
+   .timings = _ths8135_bridge_timings,
+   .connector_type = DRM_MODE_CONNECTOR_VGA,
+   },
+   }, {
.compatible = "ti,ths8134",
-   .data = _ths8134_bridge_timings,
+   .data = &(const struct simple_bridge_info) {
+   .timings = _ths8134_bridge_timings,
+   .connector_type = DRM_MODE_CONNECTOR_VGA,
+   },
},
{},
 };
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 17/54] drm/bridge: panel: Implement bridge connector operations

2020-02-22 Thread Laurent Pinchart
Implement the newly added bridge connector operations, allowing the
usage of drm_bridge_panel with drm_bridge_connector.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Boris Brezillon 
Reviewed-by: Sam Ravnborg 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
Changes since v2:

- Use the connector type from the panel instead of hardcoding it to DPI
- Rebased on top top of Sam's panel .get_modes() rework
---
 drivers/gpu/drm/bridge/panel.c | 17 +
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
index 81017b4afe25..bbc212cc53ac 100644
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -60,10 +60,8 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
struct drm_connector *connector = _bridge->connector;
int ret;
 
-   if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
-   DRM_ERROR("Fix bridge driver to make connector optional!");
-   return -EINVAL;
-   }
+   if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
+   return 0;
 
if (!bridge->encoder) {
DRM_ERROR("Missing encoder\n");
@@ -126,6 +124,14 @@ static void panel_bridge_post_disable(struct drm_bridge 
*bridge)
drm_panel_unprepare(panel_bridge->panel);
 }
 
+static int panel_bridge_get_modes(struct drm_bridge *bridge,
+ struct drm_connector *connector)
+{
+   struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
+
+   return drm_panel_get_modes(panel_bridge->panel, connector);
+}
+
 static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
.attach = panel_bridge_attach,
.detach = panel_bridge_detach,
@@ -133,6 +139,7 @@ static const struct drm_bridge_funcs 
panel_bridge_bridge_funcs = {
.enable = panel_bridge_enable,
.disable = panel_bridge_disable,
.post_disable = panel_bridge_post_disable,
+   .get_modes = panel_bridge_get_modes,
 };
 
 /**
@@ -202,6 +209,8 @@ struct drm_bridge *drm_panel_bridge_add_typed(struct 
drm_panel *panel,
 #ifdef CONFIG_OF
panel_bridge->bridge.of_node = panel->dev->of_node;
 #endif
+   panel_bridge->bridge.ops = DRM_BRIDGE_OP_MODES;
+   panel_bridge->bridge.type = connector_type;
 
drm_bridge_add(_bridge->bridge);
 
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 28/54] drm/omap: hdmi: Allocate EDID in the .read_edid() operation

2020-02-22 Thread Laurent Pinchart
Bring the omapdss-specific .read_edid() operation in sync with the
drm_bridge .get_edid() operation to ease code reuse.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
Changes since v1:

- Keep MAX_EDID macro
---
 drivers/gpu/drm/omapdrm/dss/hdmi4.c  | 36 
 drivers/gpu/drm/omapdrm/dss/hdmi5.c  | 24 
 drivers/gpu/drm/omapdrm/dss/omapdss.h|  2 +-
 drivers/gpu/drm/omapdrm/omap_connector.c | 12 ++--
 4 files changed, 47 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index dd4a14fe7e59..e15fa3862922 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -405,31 +405,45 @@ static void hdmi_disconnect(struct omap_dss_device *src,
omapdss_device_disconnect(dst, dst->next);
 }
 
-static int hdmi_read_edid(struct omap_dss_device *dssdev,
-   u8 *edid, int len)
+#define MAX_EDID   512
+
+static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
 {
struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
bool need_enable;
+   u8 *edid;
int r;
 
+   edid = kzalloc(MAX_EDID, GFP_KERNEL);
+   if (!edid)
+   return NULL;
+
need_enable = hdmi->core_enabled == false;
 
if (need_enable) {
r = hdmi4_core_enable(>core);
-   if (r)
-   return r;
+   if (r) {
+   kfree(edid);
+   return NULL;
+   }
+   }
+
+   r = read_edid(hdmi, edid, MAX_EDID);
+   if (r < 0) {
+   kfree(edid);
+   edid = NULL;
+   } else {
+   unsigned int cec_addr;
+
+   cec_addr = r >= 256 ? cec_get_edid_phys_addr(edid, r, NULL)
+: CEC_PHYS_ADDR_INVALID;
+   hdmi4_cec_set_phys_addr(>core, cec_addr);
}
 
-   r = read_edid(hdmi, edid, len);
-   if (r >= 256)
-   hdmi4_cec_set_phys_addr(>core,
-   cec_get_edid_phys_addr(edid, r, NULL));
-   else
-   hdmi4_cec_set_phys_addr(>core, CEC_PHYS_ADDR_INVALID);
if (need_enable)
hdmi4_core_disable(>core);
 
-   return r;
+   return (struct edid *)edid;
 }
 
 static void hdmi_lost_hotplug(struct omap_dss_device *dssdev)
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index 8e3790dd8b98..99720dfc5769 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -410,27 +410,39 @@ static void hdmi_disconnect(struct omap_dss_device *src,
omapdss_device_disconnect(dst, dst->next);
 }
 
-static int hdmi_read_edid(struct omap_dss_device *dssdev,
-   u8 *edid, int len)
+#define MAX_EDID   512
+
+static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
 {
struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
bool need_enable;
+   u8 *edid;
int r;
 
+   edid = kzalloc(MAX_EDID, GFP_KERNEL);
+   if (!edid)
+   return NULL;
+
need_enable = hdmi->core_enabled == false;
 
if (need_enable) {
r = hdmi_core_enable(hdmi);
-   if (r)
-   return r;
+   if (r) {
+   kfree(edid);
+   return NULL;
+   }
}
 
-   r = read_edid(hdmi, edid, len);
+   r = read_edid(hdmi, edid, MAX_EDID);
+   if (r < 0) {
+   kfree(edid);
+   edid = NULL;
+   }
 
if (need_enable)
hdmi_core_disable(hdmi);
 
-   return r;
+   return (struct edid *)edid;
 }
 
 static int hdmi_set_infoframe(struct omap_dss_device *dssdev,
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h 
b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index 82e9bfa5530a..269e143d57be 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -367,7 +367,7 @@ struct omap_dss_device_ops {
void *cb_data);
void (*unregister_hpd_cb)(struct omap_dss_device *dssdev);
 
-   int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
+   struct edid *(*read_edid)(struct omap_dss_device *dssdev);
 
int (*get_modes)(struct omap_dss_device *dssdev,
 struct drm_connector *connector);
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c 
b/drivers/gpu/drm/omapdrm/omap_connector.c
index a24cec4b0bb9..c636ae228130 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -153,25 +153,19 @@ static void omap_connector_destroy(struct drm_connector 
*connector)
kfree(omap_connector);
 }
 
-#define MAX_EDID  512
-
 static int 

[PATCH v7 03/54] drm/edid: Add flag to drm_display_info to identify HDMI sinks

2020-02-22 Thread Laurent Pinchart
The drm_display_info structure contains many fields related to HDMI
sinks, but none that identifies if a sink compliant with CEA-861 (EDID)
shall be treated as an HDMI sink or a DVI sink. Add such a flag, and
populate it according to section 8.3.3 ("DVI/HDMI Device
Discrimination") of the HDMI v1.3 specification.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Andrzej Hajda 
Reviewed-by: Ville Syrjälä 
Reviewed-by: Daniel Vetter 
Reviewed-by: Boris Brezillon 
Acked-by: Sam Ravnborg 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
Changes since v1:

- Link the is_hdmi field doc with drm_detect_hdmi_monitor()
- Add a conversion task in todo.rst
---
 Documentation/gpu/todo.rst  | 14 ++
 drivers/gpu/drm/drm_edid.c  |  6 ++
 include/drm/drm_connector.h |  8 
 3 files changed, 28 insertions(+)

diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
index 370ac678106e..ccf5e8e34222 100644
--- a/Documentation/gpu/todo.rst
+++ b/Documentation/gpu/todo.rst
@@ -407,6 +407,20 @@ Contact: Daniel Vetter
 
 Level: Intermediate
 
+Replace drm_detect_hdmi_monitor() with drm_display_info.is_hdmi
+---
+
+Once EDID is parsed, the monitor HDMI support information is available through
+drm_display_info.is_hdmi. Many drivers still call drm_detect_hdmi_monitor() to
+retrieve the same information, which is less efficient.
+
+Audit each individual driver calling drm_detect_hdmi_monitor() and switch to
+drm_display_info.is_hdmi if applicable.
+
+Contact: Laurent Pinchart, respective driver maintainers
+
+Level: Intermediate
+
 Core refactorings
 =
 
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 5f3bc3486fde..ad41764a4ebe 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -4647,6 +4647,9 @@ EXPORT_SYMBOL(drm_av_sync_delay);
  *
  * Parse the CEA extension according to CEA-861-B.
  *
+ * Drivers that have added the modes parsed from EDID to drm_display_info
+ * should use _display_info.is_hdmi instead of calling this function.
+ *
  * Return: True if the monitor is HDMI, false if not or unknown.
  */
 bool drm_detect_hdmi_monitor(struct edid *edid)
@@ -4881,6 +4884,8 @@ drm_parse_hdmi_vsdb_video(struct drm_connector 
*connector, const u8 *db)
struct drm_display_info *info = >display_info;
u8 len = cea_db_payload_len(db);
 
+   info->is_hdmi = true;
+
if (len >= 6)
info->dvi_dual = db[6] & 1;
if (len >= 7)
@@ -4949,6 +4954,7 @@ drm_reset_display_info(struct drm_connector *connector)
info->cea_rev = 0;
info->max_tmds_clock = 0;
info->dvi_dual = false;
+   info->is_hdmi = false;
info->has_hdmi_infoframe = false;
info->rgb_quant_range_selectable = false;
memset(>hdmi, 0, sizeof(info->hdmi));
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index c3bd5262db9c..0df7a95ca5d9 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -434,6 +434,14 @@ struct drm_display_info {
 */
bool dvi_dual;
 
+   /**
+* @is_hdmi: True if the sink is an HDMI device.
+*
+* This field shall be used instead of calling
+* drm_detect_hdmi_monitor() when possible.
+*/
+   bool is_hdmi;
+
/**
 * @has_hdmi_infoframe: Does the sink support the HDMI infoframe?
 */
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 02/54] drm/connector: Add helper to get a connector type name

2020-02-22 Thread Laurent Pinchart
drm_connector.c contains a map of connector types (DRM_MODE_CONNECTOR_*)
to name strings, but doesn't expose it. This leads to drivers having to
store a similar map.

Add a new drm_get_connector_type_name() helper function that return a
name string for a connector type.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Boris Brezillon 
Reviewed-by: Sam Ravnborg 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
 drivers/gpu/drm/drm_connector.c | 15 +++
 include/drm/drm_connector.h |  1 +
 2 files changed, 16 insertions(+)

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index f632ca05960e..644f0ad10671 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -111,6 +111,21 @@ void drm_connector_ida_destroy(void)
ida_destroy(_connector_enum_list[i].ida);
 }
 
+/**
+ * drm_get_connector_type_name - return a string for connector type
+ * @type: The connector type (DRM_MODE_CONNECTOR_*)
+ *
+ * Returns: the name of the connector type, or NULL if the type is not valid.
+ */
+const char *drm_get_connector_type_name(unsigned int type)
+{
+   if (type < ARRAY_SIZE(drm_connector_enum_list))
+   return drm_connector_enum_list[type].name;
+
+   return NULL;
+}
+EXPORT_SYMBOL(drm_get_connector_type_name);
+
 /**
  * drm_connector_get_cmdline_mode - reads the user's cmdline mode
  * @connector: connector to quwery
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index b3815371c271..c3bd5262db9c 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1518,6 +1518,7 @@ drm_connector_is_unregistered(struct drm_connector 
*connector)
DRM_CONNECTOR_UNREGISTERED;
 }
 
+const char *drm_get_connector_type_name(unsigned int connector_type);
 const char *drm_get_connector_status_name(enum drm_connector_status status);
 const char *drm_get_subpixel_order_name(enum subpixel_order order);
 const char *drm_get_dpms_name(int val);
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 29/54] drm/omap: hdmi4: Rework EDID read to isolate data read

2020-02-22 Thread Laurent Pinchart
In preparation of adding DRM bridge support to the hdmi4 encoder code,
rework the EDID read to isolate data read.

The hdmi_read_edid() function is the main entry point. It performs all
initialisation steps required prior to reading the EDID (such as
ensuring the device is powered on), as well as corresponding cleanup
steps afterwards. EDID read itself is handled by hdmi_read_edid_data()
that calls the hdmi4_core_ddc_read() function to read individual blocks.

This new code architecture will allow reusing hdmi_read_edid() and
hdmi4_core_ddc_read() for the drm_bridge EDID read implementation, while
swapping out hdmi_read_edid_data() for the DRM drm_do_get_edid()
function.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
Changes since v2:

- Expand commit message
---
 drivers/gpu/drm/omapdrm/dss/hdmi4.c  | 94 +++-
 drivers/gpu/drm/omapdrm/dss/hdmi4_core.c | 59 +++
 drivers/gpu/drm/omapdrm/dss/hdmi4_core.h |  4 +-
 3 files changed, 73 insertions(+), 84 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index e15fa3862922..37536b9f3114 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -272,23 +272,6 @@ static int hdmi_dump_regs(struct seq_file *s, void *p)
return 0;
 }
 
-static int read_edid(struct omap_hdmi *hdmi, u8 *buf, int len)
-{
-   int r;
-
-   mutex_lock(>lock);
-
-   r = hdmi_runtime_get(hdmi);
-   BUG_ON(r);
-
-   r = hdmi4_read_edid(>core,  buf, len);
-
-   hdmi_runtime_put(hdmi);
-   mutex_unlock(>lock);
-
-   return r;
-}
-
 static void hdmi_start_audio_stream(struct omap_hdmi *hd)
 {
hdmi_wp_audio_enable(>wp, true);
@@ -407,10 +390,8 @@ static void hdmi_disconnect(struct omap_dss_device *src,
 
 #define MAX_EDID   512
 
-static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
+static struct edid *hdmi_read_edid_data(struct omap_hdmi *hdmi)
 {
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-   bool need_enable;
u8 *edid;
int r;
 
@@ -418,32 +399,79 @@ static struct edid *hdmi_read_edid(struct omap_dss_device 
*dssdev)
if (!edid)
return NULL;
 
+   r = hdmi4_core_ddc_read(>core, edid, 0, EDID_LENGTH);
+   if (r)
+   goto error;
+
+   if (edid[0x7e] > 0) {
+   char checksum = 0;
+   unsigned int i;
+
+   r = hdmi4_core_ddc_read(>core, edid + EDID_LENGTH, 1,
+   EDID_LENGTH);
+   if (r)
+   goto error;
+
+   for (i = 0; i < EDID_LENGTH; ++i)
+   checksum += edid[EDID_LENGTH + i];
+
+   if (checksum != 0) {
+   DSSERR("E-EDID checksum failed!!\n");
+   goto error;
+   }
+   }
+
+   return (struct edid *)edid;
+
+error:
+   kfree(edid);
+   return NULL;
+}
+
+static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
+{
+   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
+   struct edid *edid = NULL;
+   unsigned int cec_addr;
+   bool need_enable;
+   int r;
+
need_enable = hdmi->core_enabled == false;
 
if (need_enable) {
r = hdmi4_core_enable(>core);
-   if (r) {
-   kfree(edid);
+   if (r)
return NULL;
-   }
}
 
-   r = read_edid(hdmi, edid, MAX_EDID);
-   if (r < 0) {
-   kfree(edid);
-   edid = NULL;
-   } else {
-   unsigned int cec_addr;
+   mutex_lock(>lock);
+   r = hdmi_runtime_get(hdmi);
+   BUG_ON(r);
+
+   r = hdmi4_core_ddc_init(>core);
+   if (r)
+   goto done;
 
-   cec_addr = r >= 256 ? cec_get_edid_phys_addr(edid, r, NULL)
-: CEC_PHYS_ADDR_INVALID;
-   hdmi4_cec_set_phys_addr(>core, cec_addr);
+   edid = hdmi_read_edid_data(hdmi);
+
+done:
+   hdmi_runtime_put(hdmi);
+   mutex_unlock(>lock);
+
+   if (edid && edid->extensions) {
+   unsigned int len = (edid->extensions + 1) * EDID_LENGTH;
+
+   cec_addr = cec_get_edid_phys_addr((u8 *)edid, len, NULL);
+   } else {
+   cec_addr = CEC_PHYS_ADDR_INVALID;
}
 
+   hdmi4_cec_set_phys_addr(>core, cec_addr);
+
if (need_enable)
hdmi4_core_disable(>core);
 
-   return (struct edid *)edid;
+   return edid;
 }
 
 static void hdmi_lost_hotplug(struct omap_dss_device *dssdev)
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c
index ea5d5c228534..751985a2679a 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c
@@ -32,7 +32,7 

[PATCH v7 41/54] drm/omap: hdmi: Remove omap_dss_device operations

2020-02-22 Thread Laurent Pinchart
Now that the HDMI outputs are driven fully through the drm_bridge API
their omap_dss_device operations are not used anymore. Remove them.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
 drivers/gpu/drm/omapdrm/dss/hdmi.h  |  1 -
 drivers/gpu/drm/omapdrm/dss/hdmi4.c | 18 --
 drivers/gpu/drm/omapdrm/dss/hdmi5.c | 18 --
 3 files changed, 37 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi.h 
b/drivers/gpu/drm/omapdrm/dss/hdmi.h
index bd43f6abf27b..3a40833d3368 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi.h
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi.h
@@ -380,7 +380,6 @@ struct omap_hdmi {
bool display_enabled;
 };
 
-#define dssdev_to_hdmi(dssdev) container_of(dssdev, struct omap_hdmi, output)
 #define drm_bridge_to_hdmi(b) container_of(b, struct omap_hdmi, bridge)
 
 #endif
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index b9bcd6e681e8..96ef7bd52199 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -309,18 +309,6 @@ void hdmi4_core_disable(struct hdmi_core_data *core)
mutex_unlock(>lock);
 }
 
-static int hdmi_connect(struct omap_dss_device *src,
-   struct omap_dss_device *dst)
-{
-   return omapdss_device_connect(dst->dss, dst, dst->next);
-}
-
-static void hdmi_disconnect(struct omap_dss_device *src,
-   struct omap_dss_device *dst)
-{
-   omapdss_device_disconnect(dst, dst->next);
-}
-
 static struct edid *
 hdmi_do_read_edid(struct omap_hdmi *hdmi,
  struct edid *(*read)(struct omap_hdmi *hdmi,
@@ -370,11 +358,6 @@ hdmi_do_read_edid(struct omap_hdmi *hdmi,
return edid;
 }
 
-static const struct omap_dss_device_ops hdmi_ops = {
-   .connect= hdmi_connect,
-   .disconnect = hdmi_disconnect,
-};
-
 /* 
-
  * DRM Bridge Operations
  */
@@ -741,7 +724,6 @@ static int hdmi4_init_output(struct omap_hdmi *hdmi)
out->type = OMAP_DISPLAY_TYPE_HDMI;
out->name = "hdmi.0";
out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
-   out->ops = _ops;
out->owner = THIS_MODULE;
out->of_port = 0;
 
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index effe4a9401ff..6cb709c775d6 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -307,18 +307,6 @@ static void hdmi_core_disable(struct omap_hdmi *hdmi)
mutex_unlock(>lock);
 }
 
-static int hdmi_connect(struct omap_dss_device *src,
-   struct omap_dss_device *dst)
-{
-   return omapdss_device_connect(dst->dss, dst, dst->next);
-}
-
-static void hdmi_disconnect(struct omap_dss_device *src,
-   struct omap_dss_device *dst)
-{
-   omapdss_device_disconnect(dst, dst->next);
-}
-
 static struct edid *
 hdmi_do_read_edid(struct omap_hdmi *hdmi,
  struct edid *(*read)(struct omap_hdmi *hdmi,
@@ -363,11 +351,6 @@ hdmi_do_read_edid(struct omap_hdmi *hdmi,
return (struct edid *)edid;
 }
 
-static const struct omap_dss_device_ops hdmi_ops = {
-   .connect= hdmi_connect,
-   .disconnect = hdmi_disconnect,
-};
-
 /* 
-
  * DRM Bridge Operations
  */
@@ -715,7 +698,6 @@ static int hdmi5_init_output(struct omap_hdmi *hdmi)
out->type = OMAP_DISPLAY_TYPE_HDMI;
out->name = "hdmi.0";
out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
-   out->ops = _ops;
out->owner = THIS_MODULE;
out->of_port = 0;
 
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 00/54] drm/omap: Replace custom display drivers with drm_bridge and drm_panel

2020-02-22 Thread Laurent Pinchart
Hello,

This patch series is the sixth attempt to (nearly, see [1]) complete the
rework of the omapdrm driver to move to drm_bridge and drm_panel.

Version 2, available at [2], explains in its long cover letter the
rationale for the changes. I won't duplicate it here as it is still
valid as-is.

Compared to v6, available at [3], this version has been rebased on top
of drm-misc-next, and documentation of the bridge overview and operation
usage has been improved. The "drm/omap: dss: Remove unused
omap_dss_device operations" patch has been moved to the end of the
series and isn't meant to be merged yet, as it gets in the way of
Sebastian's DSI rework.

Boris, could you have a look at the small fixes to the drm_bridge
documentation in patches 04/54 and 05/54 ? Daniel, patch 06/54, as well
as the documentation improvements in 07/54 and 09/54 are for you.

The patches can be found at

git://linuxtv.org/pinchartl/media.git omapdrm/bridge/devel

[1] The only notable exception is the omapdrm-specific DSI panel driver
that implements a large number of custom operations. This is being
addressed separately.

[2] https://patchwork.kernel.org/cover/11102445/

[3] https://patchwork.kernel.org/cover/11384691/

Laurent Pinchart (54):
  video: hdmi: Change return type of hdmi_avi_infoframe_init() to void
  drm/connector: Add helper to get a connector type name
  drm/edid: Add flag to drm_display_info to identify HDMI sinks
  drm/bridge: Document the drm_encoder.bridge_chain field as private
  drm/bridge: Fix atomic state ops documentation
  drm/bridge: Improve overview documentation
  drm/bridge: Add connector-related bridge operations and data
  drm/bridge: Add interlace_allowed flag to drm_bridge
  drm/bridge: Extend bridge API to disable connector creation
  drm/bridge: dumb-vga-dac: Rename internal symbols to simple-bridge
  drm/bridge: dumb-vga-dac: Rename driver to simple-bridge
  drm/bridge: simple-bridge: Add support for non-VGA bridges
  drm/bridge: simple-bridge: Add support for enable GPIO
  drm/bridge: simple-bridge: Add support for the TI OPA362
  drm/bridge: Add bridge driver for display connectors
  drm/bridge: Add driver for the TI TPD12S015 HDMI level shifter
  drm/bridge: panel: Implement bridge connector operations
  drm/bridge: tfp410: Replace manual connector handling with bridge
  drm/bridge: tfp410: Allow operation without drm_connector
  drm: Add helper to create a connector for a chain of bridges
  drm/omap: dss: Cleanup DSS ports on initialisation failure
  drm/omap: Simplify HDMI mode and infoframe configuration
  drm/omap: Factor out display type to connector type conversion
  drm/omap: Use the drm_panel_bridge API
  drm/omap: dss: Fix output next device lookup in DT
  drm/omap: Add infrastructure to support drm_bridge local to DSS
outputs
  drm/omap: dss: Make omap_dss_device_ops optional
  drm/omap: hdmi: Allocate EDID in the .read_edid() operation
  drm/omap: hdmi4: Rework EDID read to isolate data read
  drm/omap: hdmi5: Rework EDID read to isolate data read
  drm/omap: hdmi4: Register a drm_bridge for EDID read
  drm/omap: hdmi5: Register a drm_bridge for EDID read
  drm/omap: hdmi4: Move mode set, enable and disable operations to
bridge
  drm/omap: hdmi5: Move mode set, enable and disable operations to
bridge
  drm/omap: hdmi4: Implement drm_bridge .hpd_notify() operation
  drm/omap: dss: Remove .set_hdmi_mode() and .set_infoframe() operations
  drm/omap: venc: Register a drm_bridge
  drm/omap: Create connector for bridges
  drm/omap: Switch the HDMI and VENC outputs to drm_bridge
  drm/omap: Remove HPD, detect and EDID omapdss operations
  drm/omap: hdmi: Remove omap_dss_device operations
  drm/omap: venc: Remove omap_dss_device operations
  drm/omap: hdmi4: Simplify EDID read
  drm/omap: hdmi5: Simplify EDID read
  drm/omap: dpi: Sort includes alphabetically
  drm/omap: dpi: Reorder functions in sections
  drm/omap: dpi: Simplify clock setting API
  drm/omap: dpi: Register a drm_bridge
  drm/omap: sdi: Sort includes alphabetically
  drm/omap: sdi: Register a drm_bridge
  drm/omap: Hardcode omap_connector type to DSI
  drm/omap: dss: Inline the omapdss_display_get() function
  drm/omap: dss: Remove unused omapdss_of_find_connected_device()
function
  drm/omap: dss: Remove unused omap_dss_device operations

 Documentation/gpu/drm-kms-helpers.rst |  18 +-
 Documentation/gpu/todo.rst|  14 +
 arch/arm/configs/davinci_all_defconfig|   2 +-
 arch/arm/configs/integrator_defconfig |   2 +-
 arch/arm/configs/multi_v7_defconfig   |   2 +-
 arch/arm/configs/omap2plus_defconfig  |   7 +-
 arch/arm/configs/shmobile_defconfig   |   2 +-
 arch/arm/configs/sunxi_defconfig  |   2 +-
 arch/arm/configs/versatile_defconfig  |   2 +-
 drivers/gpu/drm/Makefile  |   3 +-
 drivers/gpu/drm/arc/arcpgu_hdmi.c |   2 +-
 .../gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c  |   2 +-
 

[PATCH v7 11/54] drm/bridge: dumb-vga-dac: Rename driver to simple-bridge

2020-02-22 Thread Laurent Pinchart
The dumb-vga-dac driver can support simple DRM bridges without being
limited to VGA DACs. Rename it to simple-bridge.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Andrzej Hajda 
Reviewed-by: Boris Brezillon 
Acked-by: Maxime Ripard 
Acked-by: Sam Ravnborg 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
 arch/arm/configs/davinci_all_defconfig   |  2 +-
 arch/arm/configs/integrator_defconfig|  2 +-
 arch/arm/configs/multi_v7_defconfig  |  2 +-
 arch/arm/configs/shmobile_defconfig  |  2 +-
 arch/arm/configs/sunxi_defconfig |  2 +-
 arch/arm/configs/versatile_defconfig |  2 +-
 drivers/gpu/drm/bridge/Kconfig   | 16 
 drivers/gpu/drm/bridge/Makefile  |  2 +-
 .../bridge/{dumb-vga-dac.c => simple-bridge.c}   |  2 +-
 9 files changed, 16 insertions(+), 16 deletions(-)
 rename drivers/gpu/drm/bridge/{dumb-vga-dac.c => simple-bridge.c} (99%)

diff --git a/arch/arm/configs/davinci_all_defconfig 
b/arch/arm/configs/davinci_all_defconfig
index b5ba8d731a25..e849367c0566 100644
--- a/arch/arm/configs/davinci_all_defconfig
+++ b/arch/arm/configs/davinci_all_defconfig
@@ -158,7 +158,7 @@ CONFIG_VIDEO_TVP514X=m
 CONFIG_VIDEO_ADV7343=m
 CONFIG_DRM=m
 CONFIG_DRM_TILCDC=m
-CONFIG_DRM_DUMB_VGA_DAC=m
+CONFIG_DRM_SIMPLE_BRIDGE=m
 CONFIG_DRM_TINYDRM=m
 CONFIG_TINYDRM_ST7586=m
 CONFIG_FB=y
diff --git a/arch/arm/configs/integrator_defconfig 
b/arch/arm/configs/integrator_defconfig
index 2f0a762dc3a0..a9755c501bec 100644
--- a/arch/arm/configs/integrator_defconfig
+++ b/arch/arm/configs/integrator_defconfig
@@ -55,7 +55,7 @@ CONFIG_SMC91X=y
 # CONFIG_KEYBOARD_ATKBD is not set
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_DRM=y
-CONFIG_DRM_DUMB_VGA_DAC=y
+CONFIG_DRM_SIMPLE_BRIDGE=y
 CONFIG_DRM_PL111=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_MATROX=y
diff --git a/arch/arm/configs/multi_v7_defconfig 
b/arch/arm/configs/multi_v7_defconfig
index 017d65f86eba..0b020863abdb 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -670,11 +670,11 @@ CONFIG_DRM_PANEL_ORISETECH_OTM8009A=m
 CONFIG_DRM_PANEL_RAYDIUM_RM68200=m
 CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03=m
 CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0=m
-CONFIG_DRM_DUMB_VGA_DAC=m
 CONFIG_DRM_NXP_PTN3460=m
 CONFIG_DRM_PARADE_PS8622=m
 CONFIG_DRM_SII902X=m
 CONFIG_DRM_SII9234=m
+CONFIG_DRM_SIMPLE_BRIDGE=m
 CONFIG_DRM_TOSHIBA_TC358764=m
 CONFIG_DRM_I2C_ADV7511=m
 CONFIG_DRM_I2C_ADV7511_AUDIO=y
diff --git a/arch/arm/configs/shmobile_defconfig 
b/arch/arm/configs/shmobile_defconfig
index 64fa849f8bbe..838307a9bb92 100644
--- a/arch/arm/configs/shmobile_defconfig
+++ b/arch/arm/configs/shmobile_defconfig
@@ -125,9 +125,9 @@ CONFIG_VIDEO_ML86V7667=y
 CONFIG_DRM=y
 CONFIG_DRM_RCAR_DU=y
 CONFIG_DRM_PANEL_SIMPLE=y
-CONFIG_DRM_DUMB_VGA_DAC=y
 CONFIG_DRM_LVDS_CODEC=y
 CONFIG_DRM_SII902X=y
+CONFIG_DRM_SIMPLE_BRIDGE=y
 CONFIG_DRM_I2C_ADV7511=y
 CONFIG_DRM_I2C_ADV7511_AUDIO=y
 CONFIG_FB_SH_MOBILE_LCDC=y
diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig
index e9fb57374b9f..61b8be19e527 100644
--- a/arch/arm/configs/sunxi_defconfig
+++ b/arch/arm/configs/sunxi_defconfig
@@ -101,7 +101,7 @@ CONFIG_RC_DEVICES=y
 CONFIG_IR_SUNXI=y
 CONFIG_DRM=y
 CONFIG_DRM_SUN4I=y
-CONFIG_DRM_DUMB_VGA_DAC=y
+CONFIG_DRM_SIMPLE_BRIDGE=y
 CONFIG_FB_SIMPLE=y
 CONFIG_SOUND=y
 CONFIG_SND=y
diff --git a/arch/arm/configs/versatile_defconfig 
b/arch/arm/configs/versatile_defconfig
index fe4d4b596585..767935337413 100644
--- a/arch/arm/configs/versatile_defconfig
+++ b/arch/arm/configs/versatile_defconfig
@@ -59,7 +59,7 @@ CONFIG_GPIO_PL061=y
 CONFIG_DRM=y
 CONFIG_DRM_PANEL_ARM_VERSATILE=y
 CONFIG_DRM_PANEL_SIMPLE=y
-CONFIG_DRM_DUMB_VGA_DAC=y
+CONFIG_DRM_SIMPLE_BRIDGE=y
 CONFIG_DRM_PL111=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 20a439199cb8..10073ad88283 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -27,14 +27,6 @@ config DRM_CDNS_DSI
  Support Cadence DPI to DSI bridge. This is an internal
  bridge and is meant to be directly embedded in a SoC.
 
-config DRM_DUMB_VGA_DAC
-   tristate "Dumb VGA DAC Bridge support"
-   depends on OF
-   select DRM_KMS_HELPER
-   help
- Support for non-programmable RGB to VGA DAC bridges, such as ADI
- ADV7123, TI THS8134 and THS8135 or passive resistor ladder DACs.
-
 config DRM_LVDS_CODEC
tristate "Transparent LVDS encoders and decoders support"
depends on OF
@@ -110,6 +102,14 @@ config DRM_SII9234
  It is an I2C driver, that detects connection of MHL bridge
  and starts encapsulation of HDMI signal.
 
+config DRM_SIMPLE_BRIDGE
+   tristate "Simple DRM bridge support"
+   depends on OF
+   select DRM_KMS_HELPER
+   help
+ Support for non-programmable DRM bridges, such 

[PATCH v7 06/54] drm/bridge: Improve overview documentation

2020-02-22 Thread Laurent Pinchart
Clean up the drm_bridge overview documentation, and expand the
operations documentation to provide more details on API usage.

Signed-off-by: Laurent Pinchart 
---
 Documentation/gpu/drm-kms-helpers.rst |  6 +--
 drivers/gpu/drm/drm_bridge.c  | 76 ---
 2 files changed, 60 insertions(+), 22 deletions(-)

diff --git a/Documentation/gpu/drm-kms-helpers.rst 
b/Documentation/gpu/drm-kms-helpers.rst
index 9668a7fe2408..fe155c6ae175 100644
--- a/Documentation/gpu/drm-kms-helpers.rst
+++ b/Documentation/gpu/drm-kms-helpers.rst
@@ -139,11 +139,11 @@ Overview
 .. kernel-doc:: drivers/gpu/drm/drm_bridge.c
:doc: overview
 
-Default bridge callback sequence
-
+Bridge Operations
+-
 
 .. kernel-doc:: drivers/gpu/drm/drm_bridge.c
-   :doc: bridge callbacks
+   :doc: bridge operations
 
 
 Bridge Helper Reference
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 68ab933ee430..5f55a9e17a7c 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -39,25 +39,36 @@
  * encoder chain.
  *
  * A bridge is always attached to a single _encoder at a time, but can be
- * either connected to it directly, or through an intermediate bridge::
+ * either connected to it directly, or through a chain of bridges::
  *
- * encoder ---> bridge B ---> bridge A
+ * [ CRTC ---> ] Encoder ---> Bridge A ---> Bridge B
  *
- * Here, the output of the encoder feeds to bridge B, and that furthers feeds 
to
- * bridge A.
+ * Here, the output of the encoder feeds to bridge A, and that furthers feeds 
to
+ * bridge B. Bridge chains can be arbitrarily long, and shall be fully linear:
+ * Chaining multiple bridges to the output of a bridge, or the same bridge to
+ * the output of different bridges, is not supported.
  *
- * The driver using the bridge is responsible to make the associations between
- * the encoder and bridges. Once these links are made, the bridges will
- * participate along with encoder functions to perform mode_set/enable/disable
- * through the ops provided in _bridge_funcs.
+ * Display drivers are responsible for linking encoders with the first bridge
+ * in the chains. This is done by acquiring the appropriate bridge with
+ * of_drm_find_bridge() or drm_of_find_panel_or_bridge(), or creating it for a
+ * panel with drm_panel_bridge_add_typed() (or the managed version
+ * devm_drm_panel_bridge_add_typed()). Once acquired, the bridge shall be
+ * attached to the encoder with a call to drm_bridge_attach().
  *
- * drm_bridge, like drm_panel, aren't drm_mode_object entities like planes,
+ * Bridges are responsible for linking themselves with the next bridge in the
+ * chain, if any. This is done the same way as for encoders, with the call to
+ * drm_bridge_attach() occurring in the _bridge_funcs.attach operation.
+ *
+ * Once these links are created, the bridges will automatically participate
+ * along with encoder functions to perform mode setting, enable and disable
+ * through the corresponding operations provided in _bridge_funcs. This
+ * requires no intervention from display drivers.
+ *
+ * _bridge, like _panel, aren't _mode_object entities like planes,
  * CRTCs, encoders or connectors and hence are not visible to userspace. They
  * just provide additional hooks to get the desired output at the end of the
  * encoder chain.
  *
- * Bridges can also be chained up using the _bridge.chain_node field.
- *
  * Both legacy CRTC helpers and the new atomic modeset helpers support bridges.
  */
 
@@ -212,14 +223,41 @@ void drm_bridge_detach(struct drm_bridge *bridge)
 }
 
 /**
- * DOC: bridge callbacks
- *
- * The _bridge_funcs ops are populated by the bridge driver. The DRM
- * internals (atomic and CRTC helpers) use the helpers defined in drm_bridge.c
- * These helpers call a specific _bridge_funcs op for all the bridges
- * during encoder configuration.
- *
- * For detailed specification of the bridge callbacks see _bridge_funcs.
+ * DOC: bridge operations
+ *
+ * Bridge drivers expose operations through the _bridge_funcs structure.
+ * The DRM internals (atomic and CRTC helpers) use the helpers defined in
+ * drm_bridge.c to call bridge operations. Those operations are divided in
+ * two big categories to support different parts of the bridge usage.
+ *
+ * - The encoder-related operations support control of the bridges in the
+ *   chain, and are roughly counterparts to the _encoder_helper_funcs
+ *   operations. They are used by the legacy CRTC and the atomic modeset
+ *   helpers to perform mode validation, fixup and setting, and enable and
+ *   disable the bridge automatically.
+ *
+ *   The enable and disable operations are split in
+ *   _bridge_funcs.pre_enable, _bridge_funcs.enable,
+ *   _bridge_funcs.disable and _bridge_funcs.post_disable to provide
+ *   finer-grained control.
+ *
+ *   Bridge drivers may implement the legacy version of those operations, or
+ *   the atomic 

[PATCH v7 09/54] drm/bridge: Extend bridge API to disable connector creation

2020-02-22 Thread Laurent Pinchart
Most bridge drivers create a DRM connector to model the connector at the
output of the bridge. This model is historical and has worked pretty
well so far, but causes several issues:

- It prevents supporting more complex display pipelines where DRM
connector operations are split over multiple components. For instance a
pipeline with a bridge connected to the DDC signals to read EDID data,
and another one connected to the HPD signal to detect connection and
disconnection, will not be possible to support through this model.

- It requires every bridge driver to implement similar connector
handling code, resulting in code duplication.

- It assumes that a bridge will either be wired to a connector or to
another bridge, but doesn't support bridges that can be used in both
positions very well (although there is some ad-hoc support for this in
the analogix_dp bridge driver).

In order to solve these issues, ownership of the connector should be
moved to the display controller driver (where it can be implemented
using helpers provided by the core).

Extend the bridge API to allow disabling connector creation in bridge
drivers as a first step towards the new model. The new flags argument to
the bridge .attach() operation allows instructing the bridge driver to
skip creating a connector. Unconditionally set the new flags argument to
0 for now to keep the existing behaviour, and modify all existing bridge
drivers to return an error when connector creation is not requested as
they don't support this feature yet.

The change is based on the following semantic patch, with manual review
and edits.

@ rule1 @
identifier funcs;
identifier fn;
@@
 struct drm_bridge_funcs funcs = {
...,
.attach = fn
 };

@ depends on rule1 @
identifier rule1.fn;
identifier bridge;
statement S, S1;
@@
 int fn(
struct drm_bridge *bridge
+   , enum drm_bridge_attach_flags flags
 )
 {
... when != S
+   if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
+   DRM_ERROR("Fix bridge driver to make connector optional!");
+   return -EINVAL;
+   }
+
S1
...
 }

@ depends on rule1 @
identifier rule1.fn;
identifier bridge, flags;
expression E1, E2, E3;
@@
 int fn(
struct drm_bridge *bridge,
enum drm_bridge_attach_flags flags
 ) {
 <...
 drm_bridge_attach(E1, E2, E3
+   , flags
 )
 ...>
 }

@@
expression E1, E2, E3;
@@
 drm_bridge_attach(E1, E2, E3
+   , 0
 )

Signed-off-by: Laurent Pinchart 
Reviewed-by: Boris Brezillon 
Acked-by: Sam Ravnborg 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
Changes since v6:

- Update the drm_bridge overview documentation

Changes since v5:

- Handle parade-ps8640, tc358768 and tidss

Changes since v3:

- Print error message when DRM_BRIDGE_ATTACH_NO_CONNECTOR can't be
  honoured
- Fix semantic patch to correctly handle drm_bridge_attach() calls from
  within a bridge .attach() handler
- Include drm_print.h in tc358767.c and rcar_lvds.c

Changes since v2:

- Update commit message to the new flags argument
- Replace a leftover 'true' with 0
- Update msm edp and hdmi

Changes since v1:

- Replace the create_connector boolean with a flags bitmask
- Update ingenic driver
- Add semantic patch to commit message
---
 drivers/gpu/drm/arc/arcpgu_hdmi.c |  2 +-
 .../gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c  |  2 +-
 drivers/gpu/drm/bridge/adv7511/adv7511_drv.c  |  8 +++-
 .../drm/bridge/analogix/analogix-anx6345.c|  8 +++-
 .../drm/bridge/analogix/analogix-anx78xx.c|  8 +++-
 .../drm/bridge/analogix/analogix_dp_core.c| 10 --
 drivers/gpu/drm/bridge/cdns-dsi.c |  6 --
 drivers/gpu/drm/bridge/dumb-vga-dac.c |  8 +++-
 drivers/gpu/drm/bridge/lvds-codec.c   |  5 +++--
 .../bridge/megachips-stdp-ge-b850v3-fw.c  |  8 +++-
 drivers/gpu/drm/bridge/nxp-ptn3460.c  |  8 +++-
 drivers/gpu/drm/bridge/panel.c|  8 +++-
 drivers/gpu/drm/bridge/parade-ps8622.c|  8 +++-
 drivers/gpu/drm/bridge/parade-ps8640.c|  5 +++--
 drivers/gpu/drm/bridge/sii902x.c  |  8 +++-
 drivers/gpu/drm/bridge/sil-sii8620.c  |  3 ++-
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 10 --
 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c |  8 +---
 drivers/gpu/drm/bridge/tc358764.c |  8 +++-
 drivers/gpu/drm/bridge/tc358767.c |  9 -
 drivers/gpu/drm/bridge/tc358768.c |  6 --
 drivers/gpu/drm/bridge/thc63lvd1024.c |  5 +++--
 drivers/gpu/drm/bridge/ti-sn65dsi86.c |  8 +++-
 drivers/gpu/drm/bridge/ti-tfp410.c|  8 +++-
 drivers/gpu/drm/drm_bridge.c  | 20 +--
 drivers/gpu/drm/drm_simple_kms_helper.c   |  2 +-
 drivers/gpu/drm/exynos/exynos_dp.c|  3 ++-
 drivers/gpu/drm/exynos/exynos_drm_dsi.c   |  4 ++--
 

[PATCH v7 07/54] drm/bridge: Add connector-related bridge operations and data

2020-02-22 Thread Laurent Pinchart
To support implementation of DRM connectors on top of DRM bridges
instead of by bridges, the drm_bridge needs to expose new operations and
data:

- Output detection, hot-plug notification, mode retrieval and EDID
  retrieval operations
- Bitmask of supported operations
- Bridge output type
- I2C adapter for DDC access

Add and document these.

Three new bridge helper functions are also added to handle hot plug
notification in a way that is as transparent as possible for the
bridges.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Boris Brezillon 
Reviewed-by: Sam Ravnborg 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
Changes since v6:

- Don't check for NULL bridge in drm_bridge_hpd_enable() and
  drm_bridge_hpd_disable()

Changes since v3:

- Fix typos

Changes since v2:

- Add wrappers around the .detect(), .get_modes() and .get_edid()
  operations
- Warn bridge drivers about valid usage of the connector argument to
  .get_modes() and .get_edid()

Changes since v1:

- Make .hpd_enable() and .hpd_disable() optional
- Rename .lost_hotplug() to .hpd_notify()
- Add ddc field to drm_bridge
---
 drivers/gpu/drm/drm_bridge.c | 201 ++-
 include/drm/drm_bridge.h | 192 -
 2 files changed, 391 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 5f55a9e17a7c..d236984a963e 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -82,6 +82,8 @@ static LIST_HEAD(bridge_list);
  */
 void drm_bridge_add(struct drm_bridge *bridge)
 {
+   mutex_init(>hpd_mutex);
+
mutex_lock(_lock);
list_add_tail(>list, _list);
mutex_unlock(_lock);
@@ -98,6 +100,8 @@ void drm_bridge_remove(struct drm_bridge *bridge)
mutex_lock(_lock);
list_del_init(>list);
mutex_unlock(_lock);
+
+   mutex_destroy(>hpd_mutex);
 }
 EXPORT_SYMBOL(drm_bridge_remove);
 
@@ -228,7 +232,7 @@ void drm_bridge_detach(struct drm_bridge *bridge)
  * Bridge drivers expose operations through the _bridge_funcs structure.
  * The DRM internals (atomic and CRTC helpers) use the helpers defined in
  * drm_bridge.c to call bridge operations. Those operations are divided in
- * two big categories to support different parts of the bridge usage.
+ * three big categories to support different parts of the bridge usage.
  *
  * - The encoder-related operations support control of the bridges in the
  *   chain, and are roughly counterparts to the _encoder_helper_funcs
@@ -258,6 +262,43 @@ void drm_bridge_detach(struct drm_bridge *bridge)
  *   implement them shall thus also implement the atomic version of the
  *   encoder-related operations. This feature is not supported by the legacy
  *   CRTC helpers.
+ *
+ * - The connector-related operations support implementing a _connector
+ *   based on a chain of bridges. DRM bridges traditionally create a
+ *   _connector for bridges meant to be used at the end of the chain. This
+ *   puts additional burden on bridge drivers, especially for bridges that may
+ *   be used in the middle of a chain or at the end of it. Furthermore, it
+ *   requires all operations of the _connector to be handled by a single
+ *   bridge, which doesn't always match the hardware architecture.
+ *
+ *   To simplify bridge drivers and make the connector implementation more
+ *   flexible, a new model allows bridges to unconditionally skip creation of
+ *   _connector and instead expose _bridge_funcs operations to support
+ *   an externally-implemented _connector. Those operations are
+ *   _bridge_funcs.detect, _bridge_funcs.get_modes,
+ *   _bridge_funcs.get_edid, _bridge_funcs.hpd_notify,
+ *   _bridge_funcs.hpd_enable and _bridge_funcs.hpd_disable. When
+ *   implemented, display drivers shall create a _connector instance for
+ *   each chain of bridges, and implement those connector instances based on
+ *   the bridge connector operations.
+ *
+ *   Bridge drivers shall implement the connector-related operations for all
+ *   the features that the bridge hardware support. For instance, if a bridge
+ *   supports reading EDID, the _bridge_funcs.get_edid shall be
+ *   implemented. This however doesn't mean that the DDC lines are wired to the
+ *   bridge on a particular platform, as they could also be connected to an I2C
+ *   controller of the SoC. Support for the connector-related operations on the
+ *   running platform is reported through the _bridge.ops flags. Bridge
+ *   drivers shall detect which operations they can support on the platform
+ *   (usually this information is provided by ACPI or DT), and set the
+ *   _bridge.ops flags for all supported operations. A flag shall only be
+ *   set if the corresponding _bridge_funcs operation is implemented, but
+ *   an implemented operation doesn't necessarily imply that the corresponding
+ *   flag will be set. Display drivers shall use the _bridge.ops flags to
+ *   decide 

[PATCH v7 27/54] drm/omap: dss: Make omap_dss_device_ops optional

2020-02-22 Thread Laurent Pinchart
As part of the move to drm_bridge ops, the dssdev ops will become empty
for some of the internal encoders. Make them optional in the driver to
allow them to be removed completely, easing the transition.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
 drivers/gpu/drm/omapdrm/dss/base.c   | 21 -
 drivers/gpu/drm/omapdrm/dss/dss.c|  3 ++-
 drivers/gpu/drm/omapdrm/omap_connector.c |  2 +-
 drivers/gpu/drm/omapdrm/omap_encoder.c   | 12 +++-
 4 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/base.c 
b/drivers/gpu/drm/omapdrm/dss/base.c
index 80d48936d177..2db3bd2f19db 100644
--- a/drivers/gpu/drm/omapdrm/dss/base.c
+++ b/drivers/gpu/drm/omapdrm/dss/base.c
@@ -195,10 +195,12 @@ int omapdss_device_connect(struct dss_device *dss,
 
dst->dss = dss;
 
-   ret = dst->ops->connect(src, dst);
-   if (ret < 0) {
-   dst->dss = NULL;
-   return ret;
+   if (dst->ops && dst->ops->connect) {
+   ret = dst->ops->connect(src, dst);
+   if (ret < 0) {
+   dst->dss = NULL;
+   return ret;
+   }
}
 
return 0;
@@ -226,7 +228,8 @@ void omapdss_device_disconnect(struct omap_dss_device *src,
 
WARN_ON(dst->state != OMAP_DSS_DISPLAY_DISABLED);
 
-   dst->ops->disconnect(src, dst);
+   if (dst->ops && dst->ops->disconnect)
+   dst->ops->disconnect(src, dst);
dst->dss = NULL;
 }
 EXPORT_SYMBOL_GPL(omapdss_device_disconnect);
@@ -238,7 +241,7 @@ void omapdss_device_pre_enable(struct omap_dss_device 
*dssdev)
 
omapdss_device_pre_enable(dssdev->next);
 
-   if (dssdev->ops->pre_enable)
+   if (dssdev->ops && dssdev->ops->pre_enable)
dssdev->ops->pre_enable(dssdev);
 }
 EXPORT_SYMBOL_GPL(omapdss_device_pre_enable);
@@ -248,7 +251,7 @@ void omapdss_device_enable(struct omap_dss_device *dssdev)
if (!dssdev)
return;
 
-   if (dssdev->ops->enable)
+   if (dssdev->ops && dssdev->ops->enable)
dssdev->ops->enable(dssdev);
 
omapdss_device_enable(dssdev->next);
@@ -264,7 +267,7 @@ void omapdss_device_disable(struct omap_dss_device *dssdev)
 
omapdss_device_disable(dssdev->next);
 
-   if (dssdev->ops->disable)
+   if (dssdev->ops && dssdev->ops->disable)
dssdev->ops->disable(dssdev);
 }
 EXPORT_SYMBOL_GPL(omapdss_device_disable);
@@ -274,7 +277,7 @@ void omapdss_device_post_disable(struct omap_dss_device 
*dssdev)
if (!dssdev)
return;
 
-   if (dssdev->ops->post_disable)
+   if (dssdev->ops && dssdev->ops->post_disable)
dssdev->ops->post_disable(dssdev);
 
omapdss_device_post_disable(dssdev->next);
diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c 
b/drivers/gpu/drm/omapdrm/dss/dss.c
index 67b92b5d8dd7..b76fc2b56227 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss.c
+++ b/drivers/gpu/drm/omapdrm/dss/dss.c
@@ -1552,7 +1552,8 @@ static void dss_shutdown(struct platform_device *pdev)
DSSDBG("shutdown\n");
 
for_each_dss_output(dssdev) {
-   if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+   if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE &&
+   dssdev->ops && dssdev->ops->disable)
dssdev->ops->disable(dssdev);
}
 }
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c 
b/drivers/gpu/drm/omapdrm/omap_connector.c
index b0cb2ecb30ab..a24cec4b0bb9 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -228,7 +228,7 @@ enum drm_mode_status omap_connector_mode_fixup(struct 
omap_dss_device *dssdev,
drm_mode_copy(adjusted_mode, mode);
 
for (; dssdev; dssdev = dssdev->next) {
-   if (!dssdev->ops->check_timings)
+   if (!dssdev->ops || !dssdev->ops->check_timings)
continue;
 
ret = dssdev->ops->check_timings(dssdev, adjusted_mode);
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c 
b/drivers/gpu/drm/omapdrm/omap_encoder.c
index a270173a2411..b232acd3bc3d 100644
--- a/drivers/gpu/drm/omapdrm/omap_encoder.c
+++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
@@ -77,10 +77,10 @@ static void omap_encoder_hdmi_mode_set(struct drm_connector 
*connector,
struct omap_dss_device *dssdev = omap_encoder->output;
bool hdmi_mode = connector->display_info.is_hdmi;
 
-   if (dssdev->ops->hdmi.set_hdmi_mode)
+   if (dssdev->ops && dssdev->ops->hdmi.set_hdmi_mode)
dssdev->ops->hdmi.set_hdmi_mode(dssdev, hdmi_mode);
 
-   if (hdmi_mode && dssdev->ops->hdmi.set_infoframe) {
+   if (hdmi_mode && dssdev->ops && dssdev->ops->hdmi.set_infoframe) {
struct hdmi_avi_infoframe avi;
int r;
 
@@ -139,7 

[PATCH v7 14/54] drm/bridge: simple-bridge: Add support for the TI OPA362

2020-02-22 Thread Laurent Pinchart
The TI OPA362 is an analog video amplifier controlled through a GPIO. Add
support for it to the simple-bridge driver.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Andrzej Hajda 
Reviewed-by: Boris Brezillon 
Reviewed-by: Maxime Ripard 
Reviewed-by: Tomi Valkeinen 
Acked-by: Sam Ravnborg 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
Changes since v3:

- Fix device name in commit message
---
 drivers/gpu/drm/bridge/simple-bridge.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/bridge/simple-bridge.c 
b/drivers/gpu/drm/bridge/simple-bridge.c
index 70e6092bdf6c..a2dca7a3ef03 100644
--- a/drivers/gpu/drm/bridge/simple-bridge.c
+++ b/drivers/gpu/drm/bridge/simple-bridge.c
@@ -305,6 +305,11 @@ static const struct of_device_id simple_bridge_match[] = {
.timings = _bridge_timings,
.connector_type = DRM_MODE_CONNECTOR_VGA,
},
+   }, {
+   .compatible = "ti,opa362",
+   .data = &(const struct simple_bridge_info) {
+   .connector_type = DRM_MODE_CONNECTOR_Composite,
+   },
}, {
.compatible = "ti,ths8135",
.data = &(const struct simple_bridge_info) {
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 18/54] drm/bridge: tfp410: Replace manual connector handling with bridge

2020-02-22 Thread Laurent Pinchart
Now that a driver is available for display connectors, replace the
manual connector handling code with usage of the DRM bridge API. The
tfp410 driver doesn't deal with the display connector directly anymore,
but still delegates drm_connector operations to the next bridge. This
brings us one step closer to having the tfp410 driver handling the
TFP410 only.

Signed-off-by: Laurent Pinchart 
Acked-by: Sam Ravnborg 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
Changes since v2:

- Use drm_bridge_get_edid() and drm_bridge_detect() helpers
---
 drivers/gpu/drm/bridge/ti-tfp410.c | 216 ++---
 1 file changed, 75 insertions(+), 141 deletions(-)

diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c 
b/drivers/gpu/drm/bridge/ti-tfp410.c
index 193c9368f664..2b8741ebc696 100644
--- a/drivers/gpu/drm/bridge/ti-tfp410.c
+++ b/drivers/gpu/drm/bridge/ti-tfp410.c
@@ -4,14 +4,12 @@
  * Author: Jyri Sarha 
  */
 
-#include 
-#include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -24,16 +22,13 @@
 struct tfp410 {
struct drm_bridge   bridge;
struct drm_connectorconnector;
-   unsigned intconnector_type;
 
u32 bus_format;
-   struct i2c_adapter  *ddc;
-   struct gpio_desc*hpd;
-   int hpd_irq;
struct delayed_work hpd_work;
struct gpio_desc*powerdown;
 
struct drm_bridge_timings timings;
+   struct drm_bridge   *next_bridge;
 
struct device *dev;
 };
@@ -56,13 +51,18 @@ static int tfp410_get_modes(struct drm_connector *connector)
struct edid *edid;
int ret;
 
-   if (!dvi->ddc)
-   goto fallback;
+   edid = drm_bridge_get_edid(dvi->next_bridge, connector);
+   if (IS_ERR_OR_NULL(edid)) {
+   if (edid != ERR_PTR(-ENOTSUPP))
+   DRM_INFO("EDID read failed. Fallback to standard 
modes\n");
 
-   edid = drm_get_edid(connector, dvi->ddc);
-   if (!edid) {
-   DRM_INFO("EDID read failed. Fallback to standard modes\n");
-   goto fallback;
+   /*
+* No EDID, fallback on the XGA standard modes and prefer a mode
+* pretty much anything can handle.
+*/
+   ret = drm_add_modes_noedid(connector, 1920, 1200);
+   drm_set_preferred_mode(connector, 1024, 768);
+   return ret;
}
 
drm_connector_update_edid_property(connector, edid);
@@ -71,15 +71,6 @@ static int tfp410_get_modes(struct drm_connector *connector)
 
kfree(edid);
 
-   return ret;
-
-fallback:
-   /* No EDID, fallback on the XGA standard modes */
-   ret = drm_add_modes_noedid(connector, 1920, 1200);
-
-   /* And prefer a mode pretty much anything can handle */
-   drm_set_preferred_mode(connector, 1024, 768);
-
return ret;
 }
 
@@ -92,21 +83,7 @@ tfp410_connector_detect(struct drm_connector *connector, 
bool force)
 {
struct tfp410 *dvi = drm_connector_to_tfp410(connector);
 
-   if (dvi->hpd) {
-   if (gpiod_get_value_cansleep(dvi->hpd))
-   return connector_status_connected;
-   else
-   return connector_status_disconnected;
-   }
-
-   if (dvi->ddc) {
-   if (drm_probe_ddc(dvi->ddc))
-   return connector_status_connected;
-   else
-   return connector_status_disconnected;
-   }
-
-   return connector_status_unknown;
+   return drm_bridge_detect(dvi->next_bridge);
 }
 
 static const struct drm_connector_funcs tfp410_con_funcs = {
@@ -118,12 +95,35 @@ static const struct drm_connector_funcs tfp410_con_funcs = 
{
.atomic_destroy_state   = drm_atomic_helper_connector_destroy_state,
 };
 
+static void tfp410_hpd_work_func(struct work_struct *work)
+{
+   struct tfp410 *dvi;
+
+   dvi = container_of(work, struct tfp410, hpd_work.work);
+
+   if (dvi->bridge.dev)
+   drm_helper_hpd_irq_event(dvi->bridge.dev);
+}
+
+static void tfp410_hpd_callback(void *arg, enum drm_connector_status status)
+{
+   struct tfp410 *dvi = arg;
+
+   mod_delayed_work(system_wq, >hpd_work,
+msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS));
+}
+
 static int tfp410_attach(struct drm_bridge *bridge,
 enum drm_bridge_attach_flags flags)
 {
struct tfp410 *dvi = drm_bridge_to_tfp410(bridge);
int ret;
 
+   ret = drm_bridge_attach(bridge->encoder, dvi->next_bridge, bridge,
+   DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+   if (ret < 0)
+   return ret;
+
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
DRM_ERROR("Fix bridge driver to make connector optional!");
return -EINVAL;
@@ -134,17 

[PATCH v7 15/54] drm/bridge: Add bridge driver for display connectors

2020-02-22 Thread Laurent Pinchart
Display connectors are modelled in DT as a device node, but have so far
been handled manually in several bridge drivers. This resulted in
duplicate code in several bridge drivers, with slightly different (and
thus confusing) logics.

In order to fix this, implement a bridge driver for display connectors.
The driver centralises logic for the DVI, HDMI, VGAn composite and
S-video connectors and exposes corresponding bridge operations.

This driver in itself doesn't solve the issue completely, changes in
bridge and display controller drivers are needed to make use of the new
connector driver.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Maxime Ripard 
Reviewed-by: Boris Brezillon 
Acked-by: Sam Ravnborg 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
Changes since v5:

- Set the drm_bridge.interlace_allowed flag

Changes since v3:

- Turn probe confirmation message into a dev_dbg()

Changes since v2:

- Fall back to polling if the GPIO IRQ chip doesn't support
  edge-triggered interrupts

Changes since v1:

- Use drm_get_connector_type_name() instead of open-coding
  display_connector_type_name()
- Remove empty .hpd_enable() and .hpd_disable() operations
- Set bridge.ddc
---
 drivers/gpu/drm/bridge/Kconfig |  11 +
 drivers/gpu/drm/bridge/Makefile|   1 +
 drivers/gpu/drm/bridge/display-connector.c | 295 +
 3 files changed, 307 insertions(+)
 create mode 100644 drivers/gpu/drm/bridge/display-connector.c

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 10073ad88283..d63283661850 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -27,6 +27,17 @@ config DRM_CDNS_DSI
  Support Cadence DPI to DSI bridge. This is an internal
  bridge and is meant to be directly embedded in a SoC.
 
+config DRM_DISPLAY_CONNECTOR
+   tristate "Display connector support"
+   depends on OF
+   help
+ Driver for display connectors with support for DDC and hot-plug
+ detection. Most display controller handle display connectors
+ internally and don't need this driver, but the DRM subsystem is
+ moving towards separating connector handling from display controllers
+ on ARM-based platforms. Saying Y here when this driver is not needed
+ will not cause any issue.
+
 config DRM_LVDS_CODEC
tristate "Transparent LVDS encoders and decoders support"
depends on OF
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index b6b2e7029a78..17f1f155e803 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o
+obj-$(CONFIG_DRM_DISPLAY_CONNECTOR) += display-connector.o
 obj-$(CONFIG_DRM_LVDS_CODEC) += lvds-codec.o
 obj-$(CONFIG_DRM_MEGACHIPS_STDP_GE_B850V3_FW) += 
megachips-stdp-ge-b850v3-fw.o
 obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
diff --git a/drivers/gpu/drm/bridge/display-connector.c 
b/drivers/gpu/drm/bridge/display-connector.c
new file mode 100644
index ..4d278573cdb9
--- /dev/null
+++ b/drivers/gpu/drm/bridge/display-connector.c
@@ -0,0 +1,295 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Laurent Pinchart 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+struct display_connector {
+   struct drm_bridge   bridge;
+
+   struct gpio_desc*hpd_gpio;
+   int hpd_irq;
+};
+
+static inline struct display_connector *
+to_display_connector(struct drm_bridge *bridge)
+{
+   return container_of(bridge, struct display_connector, bridge);
+}
+
+static int display_connector_attach(struct drm_bridge *bridge,
+   enum drm_bridge_attach_flags flags)
+{
+   return flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR ? 0 : -EINVAL;
+}
+
+static enum drm_connector_status
+display_connector_detect(struct drm_bridge *bridge)
+{
+   struct display_connector *conn = to_display_connector(bridge);
+
+   if (conn->hpd_gpio) {
+   if (gpiod_get_value_cansleep(conn->hpd_gpio))
+   return connector_status_connected;
+   else
+   return connector_status_disconnected;
+   }
+
+   if (conn->bridge.ddc && drm_probe_ddc(conn->bridge.ddc))
+   return connector_status_connected;
+
+   switch (conn->bridge.type) {
+   case DRM_MODE_CONNECTOR_DVIA:
+   case DRM_MODE_CONNECTOR_DVID:
+   case DRM_MODE_CONNECTOR_DVII:
+   case DRM_MODE_CONNECTOR_HDMIA:
+   case DRM_MODE_CONNECTOR_HDMIB:
+   /*
+* For DVI and HDMI connectors a DDC probe failure indicates
+* that no cable is connected.
+*/
+   return connector_status_disconnected;
+
+   case 

[PATCH v7 01/54] video: hdmi: Change return type of hdmi_avi_infoframe_init() to void

2020-02-22 Thread Laurent Pinchart
The hdmi_avi_infoframe_init() never needs to return an error, change its
return type to void.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Andrzej Hajda 
Acked-by: Bartlomiej Zolnierkiewicz 
Reviewed-by: Boris Brezillon 
Acked-by: Sam Ravnborg 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
Changes since v1:

- Removed documentation of the return value

Cc: Bartlomiej Zolnierkiewicz 
---
 drivers/gpu/drm/drm_edid.c |  5 +
 drivers/video/hdmi.c   | 11 ++-
 include/linux/hdmi.h   |  2 +-
 3 files changed, 4 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index ec10dc3e859c..5f3bc3486fde 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -5449,14 +5449,11 @@ drm_hdmi_avi_infoframe_from_display_mode(struct 
hdmi_avi_infoframe *frame,
 {
enum hdmi_picture_aspect picture_aspect;
u8 vic, hdmi_vic;
-   int err;
 
if (!frame || !mode)
return -EINVAL;
 
-   err = hdmi_avi_infoframe_init(frame);
-   if (err < 0)
-   return err;
+   hdmi_avi_infoframe_init(frame);
 
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
frame->pixel_repeat = 1;
diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
index 9c82e2a0a411..856a8c4e84a2 100644
--- a/drivers/video/hdmi.c
+++ b/drivers/video/hdmi.c
@@ -53,18 +53,14 @@ static void hdmi_infoframe_set_checksum(void *buffer, 
size_t size)
 /**
  * hdmi_avi_infoframe_init() - initialize an HDMI AVI infoframe
  * @frame: HDMI AVI infoframe
- *
- * Returns 0 on success or a negative error code on failure.
  */
-int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame)
+void hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame)
 {
memset(frame, 0, sizeof(*frame));
 
frame->type = HDMI_INFOFRAME_TYPE_AVI;
frame->version = 2;
frame->length = HDMI_AVI_INFOFRAME_SIZE;
-
-   return 0;
 }
 EXPORT_SYMBOL(hdmi_avi_infoframe_init);
 
@@ -1553,7 +1549,6 @@ static int hdmi_avi_infoframe_unpack(struct 
hdmi_avi_infoframe *frame,
 const void *buffer, size_t size)
 {
const u8 *ptr = buffer;
-   int ret;
 
if (size < HDMI_INFOFRAME_SIZE(AVI))
return -EINVAL;
@@ -1566,9 +1561,7 @@ static int hdmi_avi_infoframe_unpack(struct 
hdmi_avi_infoframe *frame,
if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(AVI)) != 0)
return -EINVAL;
 
-   ret = hdmi_avi_infoframe_init(frame);
-   if (ret)
-   return ret;
+   hdmi_avi_infoframe_init(frame);
 
ptr += HDMI_INFOFRAME_HEADER_SIZE;
 
diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h
index 9918a6c910c5..9613d796cfb1 100644
--- a/include/linux/hdmi.h
+++ b/include/linux/hdmi.h
@@ -207,7 +207,7 @@ struct hdmi_drm_infoframe {
u16 max_fall;
 };
 
-int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame);
+void hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame);
 ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer,
size_t size);
 ssize_t hdmi_avi_infoframe_pack_only(const struct hdmi_avi_infoframe *frame,
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 04/54] drm/bridge: Document the drm_encoder.bridge_chain field as private

2020-02-22 Thread Laurent Pinchart
The drm_encoder.bridge_chain is not meant to be touched manually by
drivers. Make this clear in the documentation.

Signed-off-by: Laurent Pinchart 
---
 include/drm/drm_encoder.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
index 5623994b6e9e..4370e039c015 100644
--- a/include/drm/drm_encoder.h
+++ b/include/drm/drm_encoder.h
@@ -174,7 +174,8 @@ struct drm_encoder {
struct drm_crtc *crtc;
 
/**
-* @bridge_chain: Bridges attached to this encoder.
+* @bridge_chain: Bridges attached to this encoder. Drivers shall not
+* access this field directly.
 */
struct list_head bridge_chain;
 
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 10/54] drm/bridge: dumb-vga-dac: Rename internal symbols to simple-bridge

2020-02-22 Thread Laurent Pinchart
The dumb-vga-dac driver is a simple DRM bridge driver for simple VGA
DACs that don't require configuration. Other non-VGA bridges fall in a
similar category, and would benefit from a common driver. Prepare for
this by renaming the internal symbols from dumb-vga-dac to
simple-bridge.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Andrzej Hajda 
Reviewed-by: Boris Brezillon 
Reviewed-by: Maxime Ripard 
Acked-by: Sam Ravnborg 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
 drivers/gpu/drm/bridge/dumb-vga-dac.c | 154 +-
 1 file changed, 77 insertions(+), 77 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c 
b/drivers/gpu/drm/bridge/dumb-vga-dac.c
index ad5b5a849e43..7287be2d3220 100644
--- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
+++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
@@ -17,7 +17,7 @@
 #include 
 #include 
 
-struct dumb_vga {
+struct simple_bridge {
struct drm_bridge   bridge;
struct drm_connectorconnector;
 
@@ -25,28 +25,28 @@ struct dumb_vga {
struct regulator*vdd;
 };
 
-static inline struct dumb_vga *
-drm_bridge_to_dumb_vga(struct drm_bridge *bridge)
+static inline struct simple_bridge *
+drm_bridge_to_simple_bridge(struct drm_bridge *bridge)
 {
-   return container_of(bridge, struct dumb_vga, bridge);
+   return container_of(bridge, struct simple_bridge, bridge);
 }
 
-static inline struct dumb_vga *
-drm_connector_to_dumb_vga(struct drm_connector *connector)
+static inline struct simple_bridge *
+drm_connector_to_simple_bridge(struct drm_connector *connector)
 {
-   return container_of(connector, struct dumb_vga, connector);
+   return container_of(connector, struct simple_bridge, connector);
 }
 
-static int dumb_vga_get_modes(struct drm_connector *connector)
+static int simple_bridge_get_modes(struct drm_connector *connector)
 {
-   struct dumb_vga *vga = drm_connector_to_dumb_vga(connector);
+   struct simple_bridge *sbridge = 
drm_connector_to_simple_bridge(connector);
struct edid *edid;
int ret;
 
-   if (!vga->ddc)
+   if (!sbridge->ddc)
goto fallback;
 
-   edid = drm_get_edid(connector, vga->ddc);
+   edid = drm_get_edid(connector, sbridge->ddc);
if (!edid) {
DRM_INFO("EDID readout failed, falling back to standard 
modes\n");
goto fallback;
@@ -70,14 +70,14 @@ static int dumb_vga_get_modes(struct drm_connector 
*connector)
return ret;
 }
 
-static const struct drm_connector_helper_funcs dumb_vga_con_helper_funcs = {
-   .get_modes  = dumb_vga_get_modes,
+static const struct drm_connector_helper_funcs simple_bridge_con_helper_funcs 
= {
+   .get_modes  = simple_bridge_get_modes,
 };
 
 static enum drm_connector_status
-dumb_vga_connector_detect(struct drm_connector *connector, bool force)
+simple_bridge_connector_detect(struct drm_connector *connector, bool force)
 {
-   struct dumb_vga *vga = drm_connector_to_dumb_vga(connector);
+   struct simple_bridge *sbridge = 
drm_connector_to_simple_bridge(connector);
 
/*
 * Even if we have an I2C bus, we can't assume that the cable
@@ -85,14 +85,14 @@ dumb_vga_connector_detect(struct drm_connector *connector, 
bool force)
 * wire the DDC pins, or the I2C bus might not be working at
 * all.
 */
-   if (vga->ddc && drm_probe_ddc(vga->ddc))
+   if (sbridge->ddc && drm_probe_ddc(sbridge->ddc))
return connector_status_connected;
 
return connector_status_unknown;
 }
 
-static const struct drm_connector_funcs dumb_vga_con_funcs = {
-   .detect = dumb_vga_connector_detect,
+static const struct drm_connector_funcs simple_bridge_con_funcs = {
+   .detect = simple_bridge_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy= drm_connector_cleanup,
.reset  = drm_atomic_helper_connector_reset,
@@ -100,10 +100,10 @@ static const struct drm_connector_funcs 
dumb_vga_con_funcs = {
.atomic_destroy_state   = drm_atomic_helper_connector_destroy_state,
 };
 
-static int dumb_vga_attach(struct drm_bridge *bridge,
-  enum drm_bridge_attach_flags flags)
+static int simple_bridge_attach(struct drm_bridge *bridge,
+   enum drm_bridge_attach_flags flags)
 {
-   struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
+   struct simple_bridge *sbridge = drm_bridge_to_simple_bridge(bridge);
int ret;
 
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
@@ -116,50 +116,50 @@ static int dumb_vga_attach(struct drm_bridge *bridge,
return -ENODEV;
}
 
-   drm_connector_helper_add(>connector,
-_vga_con_helper_funcs);
-   ret = drm_connector_init_with_ddc(bridge->dev, >connector,
-   

[PATCH v7 13/54] drm/bridge: simple-bridge: Add support for enable GPIO

2020-02-22 Thread Laurent Pinchart
If an enable GPIO is declared in the firmware, assert it when enabling
the bridge and deassert it when disabling it.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Andrzej Hajda 
Reviewed-by: Stefan Agner 
Reviewed-by: Boris Brezillon 
Reviewed-by: Maxime Ripard 
Acked-by: Sam Ravnborg 
Tested-by: Sebastian Reichel 
Reviewed-by: Sebastian Reichel 
---
 drivers/gpu/drm/bridge/simple-bridge.c | 22 ++
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/bridge/simple-bridge.c 
b/drivers/gpu/drm/bridge/simple-bridge.c
index 20866c1230de..70e6092bdf6c 100644
--- a/drivers/gpu/drm/bridge/simple-bridge.c
+++ b/drivers/gpu/drm/bridge/simple-bridge.c
@@ -6,6 +6,7 @@
  * Maxime Ripard 
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -30,6 +31,7 @@ struct simple_bridge {
 
struct i2c_adapter  *ddc;
struct regulator*vdd;
+   struct gpio_desc*enable;
 };
 
 static inline struct simple_bridge *
@@ -143,19 +145,23 @@ static int simple_bridge_attach(struct drm_bridge *bridge,
 static void simple_bridge_enable(struct drm_bridge *bridge)
 {
struct simple_bridge *sbridge = drm_bridge_to_simple_bridge(bridge);
-   int ret = 0;
+   int ret;
 
-   if (sbridge->vdd)
+   if (sbridge->vdd) {
ret = regulator_enable(sbridge->vdd);
+   if (ret)
+   DRM_ERROR("Failed to enable vdd regulator: %d\n", ret);
+   }
 
-   if (ret)
-   DRM_ERROR("Failed to enable vdd regulator: %d\n", ret);
+   gpiod_set_value_cansleep(sbridge->enable, 1);
 }
 
 static void simple_bridge_disable(struct drm_bridge *bridge)
 {
struct simple_bridge *sbridge = drm_bridge_to_simple_bridge(bridge);
 
+   gpiod_set_value_cansleep(sbridge->enable, 0);
+
if (sbridge->vdd)
regulator_disable(sbridge->vdd);
 }
@@ -208,6 +214,14 @@ static int simple_bridge_probe(struct platform_device 
*pdev)
dev_dbg(>dev, "No vdd regulator found: %d\n", ret);
}
 
+   sbridge->enable = devm_gpiod_get_optional(>dev, "enable",
+ GPIOD_OUT_LOW);
+   if (IS_ERR(sbridge->enable)) {
+   if (PTR_ERR(sbridge->enable) != -EPROBE_DEFER)
+   dev_err(>dev, "Unable to retrieve enable GPIO\n");
+   return PTR_ERR(sbridge->enable);
+   }
+
sbridge->ddc = simple_bridge_retrieve_ddc(>dev);
if (IS_ERR(sbridge->ddc)) {
if (PTR_ERR(sbridge->ddc) == -ENODEV) {
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 05/54] drm/bridge: Fix atomic state ops documentation

2020-02-22 Thread Laurent Pinchart
The drm_bridge_funcs atomic_state_duplicate and atomic_state_destroy
operations are erroneously documented as having a default implementation
if not implemented in bridge drivers. This isn't correct, fix the
documentation.

Signed-off-by: Laurent Pinchart 
---
 include/drm/drm_bridge.h | 20 ++--
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 999fb9a1..38de129d5947 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -349,9 +349,11 @@ struct drm_bridge_funcs {
 * Duplicate the current bridge state object (which is guaranteed to be
 * non-NULL).
 *
-* The atomic_duplicate_state() hook is optional. When not implemented
-* the core allocates a drm_bridge_state object and calls
-* __drm_atomic_helper_bridge_duplicate_state() to initialize it.
+* The atomic_duplicate_state hook is mandatory if the bridge
+* implements any of the atomic hooks, and should be left unassigned
+* otherwise. For bridges that don't subclass _bridge_state, the
+* drm_atomic_helper_bridge_duplicate_state() helper function shall be
+* used to implement this hook.
 *
 * RETURNS:
 * A valid drm_bridge_state object or NULL if the allocation fails.
@@ -364,8 +366,11 @@ struct drm_bridge_funcs {
 * Destroy a bridge state object previously allocated by
 * _bridge_funcs.atomic_duplicate_state().
 *
-* The atomic_destroy_state hook is optional. When not implemented the
-* core calls kfree() on the state.
+* The atomic_destroy_state hook is mandatory if the bridge implements
+* any of the atomic hooks, and should be left unassigned otherwise.
+* For bridges that don't subclass _bridge_state, the
+* drm_atomic_helper_bridge_destroy_state() helper function shall be
+* used to implement this hook.
 */
void (*atomic_destroy_state)(struct drm_bridge *bridge,
 struct drm_bridge_state *state);
@@ -474,7 +479,10 @@ struct drm_bridge_funcs {
 * This function is called at attach time.
 *
 * The atomic_reset hook is mandatory if the bridge implements any of
-* the atomic hooks, and should be left unassigned otherwise.
+* the atomic hooks, and should be left unassigned otherwise. For
+* bridges that don't subclass _bridge_state, the
+* drm_atomic_helper_bridge_reset() helper function shall be used to
+* implement this hook.
 *
 * Note that the atomic_reset() semantics is not exactly matching the
 * reset() semantics found on other components (connector, plane, ...).
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH] drm/i915/gt: remove redundant assignment to variable dw

2020-02-22 Thread Chris Wilson
Quoting Colin King (2020-02-22 13:47:55)
> From: Colin Ian King 
> 
> Variable dw is being initialized with a value that is never read,
> it is assigned a new value later on. The assignment is redundant
> and can be removed.
> 
> Addresses-Coverity: ("Unused value")
> Signed-off-by: Colin Ian King 
Reviewed-by: Chris Wilson 
-Chris
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH] drm/i915/gt: remove redundant assignment to variable dw

2020-02-22 Thread Colin King
From: Colin Ian King 

Variable dw is being initialized with a value that is never read,
it is assigned a new value later on. The assignment is redundant
and can be removed.

Addresses-Coverity: ("Unused value")
Signed-off-by: Colin Ian King 
---
 drivers/gpu/drm/i915/gt/intel_engine_cs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c 
b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
index e46e55354e95..119c9cb24fd4 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
@@ -639,7 +639,7 @@ static int measure_breadcrumb_dw(struct intel_context *ce)
 {
struct intel_engine_cs *engine = ce->engine;
struct measure_breadcrumb *frame;
-   int dw = -ENOMEM;
+   int dw;
 
GEM_BUG_ON(!engine->gt->scratch);
 
-- 
2.25.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH 45/51] drm/gm12u320: Simplify upload work

2020-02-22 Thread Daniel Vetter
On Sat, Feb 22, 2020 at 1:30 PM Hans de Goede  wrote:
>
> Hi,
>
> On 2/21/20 10:03 PM, Daniel Vetter wrote:
> > Instead of having a work item that never stops (which really should be
> > a kthread), with a dedicated workqueue to not upset anyone else, use a
> > delayed work. A bunch of changes:
> >
> > - We can throw out all the custom wakeup and requeue logic and state
> >tracking. If we schedule the work with a 0 delay it'll get
> >scheduled immediately.
>
> I'm afraid that that is not true, from the kdoc of
> queue_delayed_work_on()  (which the other functions are wrappers of) :
>
>   * Return: %false if @work was already on a queue, %true otherwise.  If
>   * @delay is zero and @dwork is idle, it will be scheduled for immediate
>   * execution.
>
> And since the work gets scheduled with IDLE_TIMEOUT at the end of
> the (modified) gm12u320_fb_update_work, it will not be idle when
> gm12u320_fb_mark_dirty() does the schedule with 0 timeout, so it
> will stay scheduled at the old IDLE_TIMEOUT and we will get a
> very low framerate.
>
> Instead we could use mod_delayed_work_on in the case where we want
> 0 timeout, that will behave as queue_delayed_work_on() when the work
> has not been scheduled yet and it will modify the timeout otherwise.
>
> This will still allow us to get rid of the waitq.

Hm I missed that, will fix.

> ###
>
> More in general though I'm not sure if getting rid of having our own
> workqueue is a good idea (getting rid of the waitq is still a nice
> cleanup). These projectors can be connected over USB2, and we send 20
> blocks for a frame update. For each block we send a command + data
> + readback status, the data part does not fit in a single USB 2 timeslice
> so that takes 2 ms + 1 ms for the command + 1ms of the status, so this
> takes aprox. 80 ms on an idle USB-2 bus, if the bus is in use things get
> worse and this assumes instant turn around for all the commands from the
> projector.
>
> schedule_delayed_work() uses the system_wq and that is described in
> the docs as:
>
>   * system_wq is the one used by schedule[_delayed]_work[_on]().
>   * Multi-CPU multi-threaded.  There are users which expect relatively
>   * short queue flush time.  Don't queue works which can run for too
>   * long.
>
> Arguably 80 ms is way too long, which would bring us to:

tbh I have no idea what's considered "long" in this context.

>   * system_long_wq is similar to system_wq but may host long running
>   * works.  Queue flushing might take relatively long.
>
> But when connected over USB-3 we can easily do 60 FPS and we really
> don't want frame updates to be delayed by other long running works.

This is not what happens, the worker subsystem spools up new threads
in that case. If you're worried about latency then use
system_unbound_wq. The only reason you want your own workqueue is if
you need to flush the entire queue (instead of individual work items)
maybe because you don't want to deadlock with random other work items
that run there. As long as all you do is run a single work item, you
can just flush that, so no concern. Iirc the worker subsystem even
internally merges the actual worker threads, so your own wq is just
book-keeping for queue flushes.

> So neither of the standard available queues is really suitable
> and thus we really should keep using our own queue for this IMHO.

We can pick another one, but your own is imo still overkill. We don't
even do that in atomic helpers, and those hang out for at least a full
frame on the worker thread too. Thus far no screaming (but yeah it's
maybe not 80ms).

btw, can you give this a spin with your hw? Testing this stuff,
especially hotunplug and driver load would be really good.

Thanks, Daniel

>
> Regards,
>
> Hans
>
>
>
>
>
>
>
> >
> > - Persistent state (frame & draw_status_timeout) need to be moved out
> >of the work.
> >
> > - diff is bigger than the changes, biggest chunk is reindenting the
> >work fn because it lost its while loop.
> >
> > Lots of code deleting as consequence all over. Specifically we can
> > delete the drm_driver.release code now!
> >
> > Signed-off-by: Daniel Vetter 
> > Cc: Hans de Goede 
> > Cc: "Noralf Trønnes" 
> > ---
> >   drivers/gpu/drm/tiny/gm12u320.c | 170 +---
> >   1 file changed, 67 insertions(+), 103 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/tiny/gm12u320.c 
> > b/drivers/gpu/drm/tiny/gm12u320.c
> > index c22b2ee470eb..46f5cea335a7 100644
> > --- a/drivers/gpu/drm/tiny/gm12u320.c
> > +++ b/drivers/gpu/drm/tiny/gm12u320.c
> > @@ -89,13 +89,12 @@ struct gm12u320_device {
> >   unsigned char   *cmd_buf;
> >   unsigned char   *data_buf[GM12U320_BLOCK_COUNT];
> >   struct {
> > - bool run;
> > - struct workqueue_struct *workq;
> > - struct work_struct   work;
> > - wait_queue_head_twaitq;
> > + struct delayed_work   

Re: [PATCH 04/12] drm: Nuke mode->vrefresh

2020-02-22 Thread Sam Ravnborg
Hi Ville.

Nice patch - and diffstat looks good:
>  63 files changed, 217 insertions(+), 392 deletions(-)

There is an item in the Documentation/gpu/todo.rst that
describes this.
Could you drop this from todo.rst in this patch too.

> diff --git a/drivers/gpu/drm/mcde/mcde_dsi.c b/drivers/gpu/drm/mcde/mcde_dsi.c
> index bb6528b01cd0..6dca5344c0b3 100644
> --- a/drivers/gpu/drm/mcde/mcde_dsi.c
> +++ b/drivers/gpu/drm/mcde/mcde_dsi.c
> @@ -538,7 +538,7 @@ static void mcde_dsi_setup_video_mode(struct mcde_dsi *d,
>*/
>   /* (ps/s) / (pixels/s) = ps/pixels */
>   pclk = DIV_ROUND_UP_ULL(1,
> - (mode->vrefresh * mode->htotal * mode->vtotal));
> + (drm_mode_vrefresh(mode) * mode->htotal * 
> mode->vtotal));
>   dev_dbg(d->dev, "picoseconds between two pixels: %llu\n",
>   pclk);
>  

This just caught my eye while browsing the patch.
It looks like a backward way to get the clock.

But patch is fine, it was just a drive-by comment.

Whole patch is:
Reviewed-by: Sam Ravnborg 
(with or without removal of todo item added)

Sam
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH 45/51] drm/gm12u320: Simplify upload work

2020-02-22 Thread Hans de Goede

Hi,

On 2/21/20 10:03 PM, Daniel Vetter wrote:

Instead of having a work item that never stops (which really should be
a kthread), with a dedicated workqueue to not upset anyone else, use a
delayed work. A bunch of changes:

- We can throw out all the custom wakeup and requeue logic and state
   tracking. If we schedule the work with a 0 delay it'll get
   scheduled immediately.


I'm afraid that that is not true, from the kdoc of
queue_delayed_work_on()  (which the other functions are wrappers of) :

 * Return: %false if @work was already on a queue, %true otherwise.  If
 * @delay is zero and @dwork is idle, it will be scheduled for immediate
 * execution.

And since the work gets scheduled with IDLE_TIMEOUT at the end of
the (modified) gm12u320_fb_update_work, it will not be idle when
gm12u320_fb_mark_dirty() does the schedule with 0 timeout, so it
will stay scheduled at the old IDLE_TIMEOUT and we will get a
very low framerate.

Instead we could use mod_delayed_work_on in the case where we want
0 timeout, that will behave as queue_delayed_work_on() when the work
has not been scheduled yet and it will modify the timeout otherwise.

This will still allow us to get rid of the waitq.

###

More in general though I'm not sure if getting rid of having our own
workqueue is a good idea (getting rid of the waitq is still a nice
cleanup). These projectors can be connected over USB2, and we send 20
blocks for a frame update. For each block we send a command + data
+ readback status, the data part does not fit in a single USB 2 timeslice
so that takes 2 ms + 1 ms for the command + 1ms of the status, so this
takes aprox. 80 ms on an idle USB-2 bus, if the bus is in use things get
worse and this assumes instant turn around for all the commands from the
projector.

schedule_delayed_work() uses the system_wq and that is described in
the docs as:

 * system_wq is the one used by schedule[_delayed]_work[_on]().
 * Multi-CPU multi-threaded.  There are users which expect relatively
 * short queue flush time.  Don't queue works which can run for too
 * long.

Arguably 80 ms is way too long, which would bring us to:

 * system_long_wq is similar to system_wq but may host long running
 * works.  Queue flushing might take relatively long.

But when connected over USB-3 we can easily do 60 FPS and we really
don't want frame updates to be delayed by other long running works.

So neither of the standard available queues is really suitable
and thus we really should keep using our own queue for this IMHO.

Regards,

Hans









- Persistent state (frame & draw_status_timeout) need to be moved out
   of the work.

- diff is bigger than the changes, biggest chunk is reindenting the
   work fn because it lost its while loop.

Lots of code deleting as consequence all over. Specifically we can
delete the drm_driver.release code now!

Signed-off-by: Daniel Vetter 
Cc: Hans de Goede 
Cc: "Noralf Trønnes" 
---
  drivers/gpu/drm/tiny/gm12u320.c | 170 +---
  1 file changed, 67 insertions(+), 103 deletions(-)

diff --git a/drivers/gpu/drm/tiny/gm12u320.c b/drivers/gpu/drm/tiny/gm12u320.c
index c22b2ee470eb..46f5cea335a7 100644
--- a/drivers/gpu/drm/tiny/gm12u320.c
+++ b/drivers/gpu/drm/tiny/gm12u320.c
@@ -89,13 +89,12 @@ struct gm12u320_device {
unsigned char   *cmd_buf;
unsigned char   *data_buf[GM12U320_BLOCK_COUNT];
struct {
-   bool run;
-   struct workqueue_struct *workq;
-   struct work_struct   work;
-   wait_queue_head_twaitq;
+   struct delayed_work   work;
struct mutex lock;
struct drm_framebuffer  *fb;
struct drm_rect  rect;
+   int frame;
+   int draw_status_timeout;
} fb_update;
  };
  
@@ -183,19 +182,9 @@ static int gm12u320_usb_alloc(struct gm12u320_device *gm12u320)

   data_block_footer, DATA_BLOCK_FOOTER_SIZE);
}
  
-	gm12u320->fb_update.workq = create_singlethread_workqueue(DRIVER_NAME);

-   if (!gm12u320->fb_update.workq)
-   return -ENOMEM;
-
return 0;
  }
  
-static void gm12u320_usb_free(struct gm12u320_device *gm12u320)

-{
-   if (gm12u320->fb_update.workq)
-   destroy_workqueue(gm12u320->fb_update.workq);
-}
-
  static int gm12u320_misc_request(struct gm12u320_device *gm12u320,
 u8 req_a, u8 req_b,
 u8 arg_a, u8 arg_b, u8 arg_c, u8 arg_d)
@@ -338,80 +327,76 @@ static void gm12u320_copy_fb_to_blocks(struct 
gm12u320_device *gm12u320)
  static void gm12u320_fb_update_work(struct work_struct *work)
  {
struct gm12u320_device *gm12u320 =
-   container_of(work, struct gm12u320_device, fb_update.work);
-   int draw_status_timeout = FIRST_FRAME_TIMEOUT;
+   

Re: [PATCH] drm/panel: ld9040: add MODULE_DEVICE_TABLE with SPI IDs

2020-02-22 Thread Sam Ravnborg
Hi Marek.

On Thu, Feb 20, 2020 at 01:07:00PM +0100, Marek Szyprowski wrote:
> Add proper MODULE_DEVICE_TABLE structure with SPI IDs to allow proper
> creation of SPI modalias string and fix autoloading module for this driver.
> 
> Signed-off-by: Marek Szyprowski 

Thanks,

applied to drm-misc-next.

Sam
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH 3/3] drm/panel: simple: fix osd070t1718_19ts sync drive edge

2020-02-22 Thread Sam Ravnborg
Hi Tomi.

>  +++ b/drivers/gpu/drm/panel/panel-simple.c
>  @@ -2397,7 +2397,8 @@ static const struct panel_desc 
>  osddisplays_osd070t1718_19ts = {
>   .height = 91,
>   },
>   .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
>  -.bus_flags = DRM_BUS_FLAG_DE_HIGH | 
>  DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
>  +.bus_flags = DRM_BUS_FLAG_DE_HIGH | 
>  DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE |
>  +DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE,
>   .connector_type = DRM_MODE_CONNECTOR_DPI,
> };
> >>
> >> Can this be merged?
> > 
> > I have lost the original mail.
> > Can you re-send or provide a patchwork pointer or similar.
> > Then I will apply.
> 
> Here are lore and patchwork links. Note that the first two patches in the 
> series have already been handled.
> 
> https://lore.kernel.org/dri-devel/20191114093950.rT5m86Xh0-a9FZGq7JipQ3O3vldctJYcvRdhxUMGBVE@z/#t
> 
> https://patchwork.freedesktop.org/series/69459/

Thanks for the pointers. It is now applied to drm-misc-next.

Sam
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH 44/51] drm/gm12u320: Use helpers for shutdown/suspend/resume

2020-02-22 Thread Hans de Goede

Hi,

On 2/21/20 10:03 PM, Daniel Vetter wrote:

Also there's a race in the disconnect implemenation. First shut
down, then unplug, leaves a window where userspace could sneak
in and restart the entire machinery.

With this we can also delete the very un-atomic global pipe_enabled
tracking.


Patch looks good to me:

Reviewed-by: Hans de Goede 

Regards,

Hans






Signed-off-by: Daniel Vetter 
Cc: Hans de Goede 
Cc: "Noralf Trønnes" 
---
  drivers/gpu/drm/tiny/gm12u320.c | 16 +++-
  1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/tiny/gm12u320.c b/drivers/gpu/drm/tiny/gm12u320.c
index 65dfb87ccb13..c22b2ee470eb 100644
--- a/drivers/gpu/drm/tiny/gm12u320.c
+++ b/drivers/gpu/drm/tiny/gm12u320.c
@@ -88,7 +88,6 @@ struct gm12u320_device {
struct usb_device   *udev;
unsigned char   *cmd_buf;
unsigned char   *data_buf[GM12U320_BLOCK_COUNT];
-   bool pipe_enabled;
struct {
bool run;
struct workqueue_struct *workq;
@@ -589,7 +588,6 @@ static void gm12u320_pipe_enable(struct 
drm_simple_display_pipe *pipe,
  
  	gm12u320_fb_mark_dirty(plane_state->fb, );

gm12u320_start_fb_update(gm12u320);
-   gm12u320->pipe_enabled = true;
  }
  
  static void gm12u320_pipe_disable(struct drm_simple_display_pipe *pipe)

@@ -597,7 +595,6 @@ static void gm12u320_pipe_disable(struct 
drm_simple_display_pipe *pipe)
struct gm12u320_device *gm12u320 = pipe->crtc.dev->dev_private;
  
  	gm12u320_stop_fb_update(gm12u320);

-   gm12u320->pipe_enabled = false;
  }
  
  static void gm12u320_pipe_update(struct drm_simple_display_pipe *pipe,

@@ -733,22 +730,17 @@ static int gm12u320_usb_probe(struct usb_interface 
*interface,
  static void gm12u320_usb_disconnect(struct usb_interface *interface)
  {
struct drm_device *dev = usb_get_intfdata(interface);
-   struct gm12u320_device *gm12u320 = dev->dev_private;
  
-	gm12u320_stop_fb_update(gm12u320);

drm_dev_unplug(dev);
+   drm_atomic_helper_shutdown(dev);
  }
  
  static __maybe_unused int gm12u320_suspend(struct usb_interface *interface,

   pm_message_t message)
  {
struct drm_device *dev = usb_get_intfdata(interface);
-   struct gm12u320_device *gm12u320 = dev->dev_private;
  
-	if (gm12u320->pipe_enabled)

-   gm12u320_stop_fb_update(gm12u320);
-
-   return 0;
+   return drm_mode_config_helper_suspend(dev);
  }
  
  static __maybe_unused int gm12u320_resume(struct usb_interface *interface)

@@ -757,10 +749,8 @@ static __maybe_unused int gm12u320_resume(struct 
usb_interface *interface)
struct gm12u320_device *gm12u320 = dev->dev_private;
  
  	gm12u320_set_ecomode(gm12u320);

-   if (gm12u320->pipe_enabled)
-   gm12u320_start_fb_update(gm12u320);
  
-	return 0;

+   return drm_mode_config_helper_resume(dev);
  }
  
  static const struct usb_device_id id_table[] = {




___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


  1   2   >