[PATCH v4 2/2] drm/mediatek: add devlink to cmdq dev

2021-12-01 Thread jason-jh . lin
Add devlink to cmdq to make sure the order of suspend and resume
is correct.

Signed-off-by: jason-jh.lin 
---
 drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 43 ++---
 1 file changed, 31 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c 
b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index 0b4012335e7a..612d1d69c16c 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -60,6 +60,7 @@ struct mtk_drm_crtc {
 #endif
 
struct device   *mmsys_dev;
+   struct device   *drm_dev;
struct mtk_mutex*mutex;
unsigned intddp_comp_nr;
struct mtk_ddp_comp **ddp_comp;
@@ -159,6 +160,7 @@ static void mtk_drm_crtc_destroy(struct drm_crtc *crtc)
mtk_drm_cmdq_pkt_destroy(&mtk_crtc->cmdq_handle);
 
if (mtk_crtc->cmdq_client.chan) {
+   device_link_remove(mtk_crtc->drm_dev, 
mtk_crtc->cmdq_client.chan->mbox->dev);
mbox_free_channel(mtk_crtc->cmdq_client.chan);
mtk_crtc->cmdq_client.chan = NULL;
}
@@ -902,6 +904,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
return -ENOMEM;
 
mtk_crtc->mmsys_dev = priv->mmsys_dev;
+   mtk_crtc->drm_dev = priv->dev;
mtk_crtc->ddp_comp_nr = path_len;
mtk_crtc->ddp_comp = devm_kmalloc_array(dev, mtk_crtc->ddp_comp_nr,
sizeof(*mtk_crtc->ddp_comp),
@@ -969,6 +972,18 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
}
 
if (mtk_crtc->cmdq_client.chan) {
+   struct device_link *link;
+
+   /* add devlink to cmdq dev to make sure suspend/resume order is 
correct */
+   link = device_link_add(priv->dev, 
mtk_crtc->cmdq_client.chan->mbox->dev,
+  DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS);
+   if (!link) {
+   dev_err(priv->dev, "Unable to link dev=%s\n",
+   
dev_name(mtk_crtc->cmdq_client.chan->mbox->dev));
+   ret = -ENODEV;
+   goto cmdq_err;
+   }
+
ret = of_property_read_u32_index(priv->mutex_node,
 "mediatek,gce-events",
 i,
@@ -976,22 +991,26 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
if (ret) {
dev_dbg(dev, "mtk_crtc %d failed to get 
mediatek,gce-events property\n",
drm_crtc_index(&mtk_crtc->base));
-   mbox_free_channel(mtk_crtc->cmdq_client.chan);
-   mtk_crtc->cmdq_client.chan = NULL;
-   } else {
-   ret = mtk_drm_cmdq_pkt_create(&mtk_crtc->cmdq_client,
- &mtk_crtc->cmdq_handle,
- PAGE_SIZE);
-   if (ret) {
-   dev_dbg(dev, "mtk_crtc %d failed to create cmdq 
packet\n",
-   drm_crtc_index(&mtk_crtc->base));
-   mbox_free_channel(mtk_crtc->cmdq_client.chan);
-   mtk_crtc->cmdq_client.chan = NULL;
-   }
+   goto cmdq_err;
+   }
+
+   ret = mtk_drm_cmdq_pkt_create(&mtk_crtc->cmdq_client,
+ &mtk_crtc->cmdq_handle,
+ PAGE_SIZE);
+   if (ret) {
+   dev_dbg(dev, "mtk_crtc %d failed to create cmdq 
packet\n",
+   drm_crtc_index(&mtk_crtc->base));
+   goto cmdq_err;
}
 
/* for sending blocking cmd in crtc disable */
init_waitqueue_head(&mtk_crtc->cb_blocking_queue);
+
+cmdq_err:
+   if (ret) {
+   mbox_free_channel(mtk_crtc->cmdq_client.chan);
+   mtk_crtc->cmdq_client.chan = NULL;
+   }
}
 #endif
return 0;
-- 
2.18.0



[PATCH v4 0/2] Fix mediatek-drm suspend and resume issue

2021-12-01 Thread jason-jh . lin
Change in v4:
- change completment function to wait_for_event.
- release the mbox channel when device_link_add fail with cmdq
  and still return 0 because drm can configure register by cpu.

Change in v3:
- fix return typo: modify -NOEDV to -ENODEV.
- add missing complete function in ddp_cmdq_cb.

Change in v2:
- rollback adding cmdq_mbox_flush in cmdq_suspend and add
  blocking config mode for mtk_drm_crtc_atomic_disable.
- add return error when device_link_add fail.
- change the first parameter of device_link_add from dev
  to priv->dev.

jason-jh.lin (2):
  drm/mediatek: add wait_for_event for crtc disable by cmdq
  drm/mediatek: add devlink to cmdq dev

 drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 51 -
 1 file changed, 41 insertions(+), 10 deletions(-)

-- 
2.18.0



[PATCH v4 1/2] drm/mediatek: add wait_for_event for crtc disable by cmdq

2021-12-01 Thread jason-jh . lin
mtk_drm_crtc_atomic_disable will send an async cmd to cmdq driver,
so it may not finish when cmdq_suspend is called sometimes.

Add wait_for_event after sending async disable plane cmd to make
sure the lastest cmd is done before cmdq_suspend.

Signed-off-by: jason-jh.lin 
---
 drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c 
b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index 62529a954b62..0b4012335e7a 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -56,6 +56,7 @@ struct mtk_drm_crtc {
struct cmdq_pkt cmdq_handle;
u32 cmdq_event;
u32 cmdq_vblank_cnt;
+   wait_queue_head_t   cb_blocking_queue;
 #endif
 
struct device   *mmsys_dev;
@@ -314,6 +315,7 @@ static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg)
}
 
mtk_crtc->cmdq_vblank_cnt = 0;
+   wake_up(&mtk_crtc->cb_blocking_queue);
 }
 #endif
 
@@ -700,6 +702,13 @@ static void mtk_drm_crtc_atomic_disable(struct drm_crtc 
*crtc,
mtk_crtc->pending_planes = true;
 
mtk_drm_crtc_update_config(mtk_crtc, false);
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+   /* Wait for planes to be disabled by cmdq */
+   if (mtk_crtc->cmdq_client.chan)
+   wait_event_timeout(mtk_crtc->cb_blocking_queue,
+  mtk_crtc->cmdq_vblank_cnt == 0,
+  msecs_to_jiffies(500));
+#endif
/* Wait for planes to be disabled */
drm_crtc_wait_one_vblank(crtc);
 
@@ -980,6 +989,9 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
mtk_crtc->cmdq_client.chan = NULL;
}
}
+
+   /* for sending blocking cmd in crtc disable */
+   init_waitqueue_head(&mtk_crtc->cb_blocking_queue);
}
 #endif
return 0;
-- 
2.18.0



[PATCH] drm/i915: Fix error pointer dereference in i915_gem_do_execbuffer()

2021-12-01 Thread Matthew Brost
From: Dan Carpenter 

Originally "out_fence" was set using out_fence = sync_file_create() but
which returns NULL, but now it is set with out_fence = eb_requests_create()
which returns error pointers.  The error path needs to be modified to
avoid an Oops in the "goto err_request;" path.

Fixes: 544460c33821 ("drm/i915: Multi-BB execbuf")
Signed-off-by: Dan Carpenter 
Signed-off-by: Matthew Brost 
---
 drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c 
b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index 9f7c6ecadb90..6db588b9a30e 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -3288,6 +3288,7 @@ i915_gem_do_execbuffer(struct drm_device *dev,
out_fence = eb_requests_create(&eb, in_fence, out_fence_fd);
if (IS_ERR(out_fence)) {
err = PTR_ERR(out_fence);
+   out_fence = NULL;
if (eb.requests[0])
goto err_request;
else
-- 
2.33.1



Re: [PATCH v4 1/6] drm: move the buddy allocator from i915 into common drm

2021-12-01 Thread kernel test robot
Hi Arunpravin,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on drm-intel/for-linux-next]
[also build test ERROR on v5.16-rc3]
[cannot apply to drm/drm-next drm-tip/drm-tip next-20211201]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:
https://github.com/0day-ci/linux/commits/Arunpravin/drm-move-the-buddy-allocator-from-i915-into-common-drm/20211202-004327
base:   git://anongit.freedesktop.org/drm-intel for-linux-next
config: i386-allyesconfig 
(https://download.01.org/0day-ci/archive/20211202/202112021239.jptbrhi2-...@intel.com/config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce (this is a W=1 build):
# 
https://github.com/0day-ci/linux/commit/afbc900c0399e8c6220abd729932e877e81f37c8
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review 
Arunpravin/drm-move-the-buddy-allocator-from-i915-into-common-drm/20211202-004327
git checkout afbc900c0399e8c6220abd729932e877e81f37c8
# save the config file to linux build tree
mkdir build_dir
make W=1 O=build_dir ARCH=i386 SHELL=/bin/bash

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

All errors (new ones prefixed by >>):

   In file included from drivers/gpu/drm/i915/intel_memory_region.c:242:
>> drivers/gpu/drm/i915/selftests/intel_memory_region.c:23:10: fatal error: 
>> i915_buddy.h: No such file or directory
  23 | #include "i915_buddy.h"
 |  ^~
   compilation terminated.


vim +23 drivers/gpu/drm/i915/selftests/intel_memory_region.c

232a6ebae41919 Matthew Auld 2019-10-08  14  
340be48f2c5a3c Matthew Auld 2019-10-25  15  #include 
"gem/i915_gem_context.h"
b908be543e4441 Matthew Auld 2019-10-25  16  #include "gem/i915_gem_lmem.h"
232a6ebae41919 Matthew Auld 2019-10-08  17  #include "gem/i915_gem_region.h"
340be48f2c5a3c Matthew Auld 2019-10-25  18  #include 
"gem/selftests/igt_gem_utils.h"
232a6ebae41919 Matthew Auld 2019-10-08  19  #include 
"gem/selftests/mock_context.h"
99919be74aa375 Thomas Hellström 2021-06-17  20  #include "gt/intel_engine_pm.h"
6804da20bb549e Chris Wilson 2019-10-27  21  #include 
"gt/intel_engine_user.h"
b908be543e4441 Matthew Auld 2019-10-25  22  #include "gt/intel_gt.h"
d53ec322dc7de3 Matthew Auld 2021-06-16 @23  #include "i915_buddy.h"
99919be74aa375 Thomas Hellström 2021-06-17  24  #include "gt/intel_migrate.h"
ba12993c522801 Matthew Auld 2020-01-29  25  #include "i915_memcpy.h"
d53ec322dc7de3 Matthew Auld 2021-06-16  26  #include 
"i915_ttm_buddy_manager.h"
01377a0d7e6648 Abdiel Janulgue  2019-10-25  27  #include 
"selftests/igt_flush_test.h"
2f0b97ca021186 Matthew Auld 2019-10-08  28  #include 
"selftests/i915_random.h"
232a6ebae41919 Matthew Auld 2019-10-08  29  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-...@lists.01.org


[PATCH v12, 18/19] media: mtk-vcodec: Remove mtk_vcodec_release_dec_pm

2021-12-01 Thread Yunfei Dong
There are only two lines in mtk_vcodec_release_dec_pm, using
pm_runtime_disable and put_device instead directly.

Move pm_runtime_enable outside mtk_vcodec_init_dec_pm to symmetry with
pm_runtime_disable, after that, rename mtk_vcodec_init_dec_pm to *_clk since
it only has clock operations now.

Reviewed-by: AngeloGioacchino Del Regno 

Signed-off-by: Yunfei Dong 
Co-developed-by: Yong Wu 
---
 .../media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c   | 10 +++---
 .../media/platform/mtk-vcodec/mtk_vcodec_dec_hw.c|  7 +--
 .../media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c| 12 ++--
 .../media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h|  3 +--
 4 files changed, 15 insertions(+), 17 deletions(-)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
index cdbe5ffeae26..512ab5084041 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -156,12 +157,13 @@ static int mtk_vcodec_init_dec_resources(struct 
mtk_vcodec_dev *dev)
return ret;
}
 
-   ret = mtk_vcodec_init_dec_pm(pdev, &dev->pm);
+   ret = mtk_vcodec_init_dec_clk(pdev, &dev->pm);
if (ret < 0) {
dev_err(&pdev->dev, "failed to get mt vcodec clock source");
return ret;
}
 
+   pm_runtime_enable(&pdev->dev);
return 0;
 }
 
@@ -473,7 +475,8 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
if (IS_VDEC_LAT_ARCH(dev->vdec_pdata->hw_arch))
destroy_workqueue(dev->core_workqueue);
 err_res:
-   mtk_vcodec_release_dec_pm(&dev->pm);
+   pm_runtime_disable(dev->pm.dev);
+   put_device(dev->pm.larbvdec);
 err_dec_pm:
mtk_vcodec_fw_release(dev->fw_handler);
return ret;
@@ -517,7 +520,8 @@ static int mtk_vcodec_dec_remove(struct platform_device 
*pdev)
video_unregister_device(dev->vfd_dec);
 
v4l2_device_unregister(&dev->v4l2_dev);
-   mtk_vcodec_release_dec_pm(&dev->pm);
+   pm_runtime_disable(dev->pm.dev);
+   put_device(dev->pm.larbvdec);
mtk_vcodec_fw_release(dev->fw_handler);
return 0;
 }
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_hw.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_hw.c
index 389a17eb4085..34dd178e07d7 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_hw.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_hw.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "mtk_vcodec_drv.h"
@@ -117,9 +118,10 @@ static int mtk_vdec_hw_probe(struct platform_device *pdev)
return -ENOMEM;
 
subdev_dev->plat_dev = pdev;
-   ret = mtk_vcodec_init_dec_pm(pdev, &subdev_dev->pm);
+   ret = mtk_vcodec_init_dec_clk(pdev, &subdev_dev->pm);
if (ret)
return ret;
+   pm_runtime_enable(&pdev->dev);
 
subdev_dev->reg_base[VDEC_HW_MISC] =
devm_platform_ioremap_resource(pdev, 0);
@@ -155,7 +157,8 @@ static int mtk_vdec_hw_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, subdev_dev);
return 0;
 err:
-   mtk_vcodec_release_dec_pm(&subdev_dev->pm);
+   pm_runtime_disable(subdev_dev->pm.dev);
+   put_device(subdev_dev->pm.larbvdec);
return ret;
 }
 
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
index 4cf03d38d141..b9f5ef979c69 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
@@ -15,7 +15,7 @@
 #include "mtk_vcodec_dec_pm.h"
 #include "mtk_vcodec_util.h"
 
-int mtk_vcodec_init_dec_pm(struct platform_device *pdev,
+int mtk_vcodec_init_dec_clk(struct platform_device *pdev,
struct mtk_vcodec_pm *pm)
 {
struct device_node *node;
@@ -73,20 +73,12 @@ int mtk_vcodec_init_dec_pm(struct platform_device *pdev,
}
}
 
-   pm_runtime_enable(&pdev->dev);
return 0;
 put_device:
put_device(pm->larbvdec);
return ret;
 }
-EXPORT_SYMBOL_GPL(mtk_vcodec_init_dec_pm);
-
-void mtk_vcodec_release_dec_pm(struct mtk_vcodec_pm *pm)
-{
-   pm_runtime_disable(pm->dev);
-   put_device(pm->larbvdec);
-}
-EXPORT_SYMBOL_GPL(mtk_vcodec_release_dec_pm);
+EXPORT_SYMBOL_GPL(mtk_vcodec_init_dec_clk);
 
 int mtk_vcodec_dec_pw_on(struct mtk_vcodec_dev *vdec_dev, int hw_idx)
 {
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
index 6ae29fea4e7f..c4121df9764f 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
@@ -9,9 +9,8 @@
 
 #include "mtk_vcodec_drv.h"
 
-int mtk_vcodec_init_dec_

[PATCH v12, 19/19] media: mtk-vcodec: Remove mtk_vcodec_release_enc_pm

2021-12-01 Thread Yunfei Dong
There are only two lines in mtk_vcodec_release_enc_pm, using
pm_runtime_disable and put_device instead directly.

Move pm_runtime_enable outside mtk_vcodec_release_enc_pm to symmetry with
pm_runtime_disable, after that, rename mtk_vcodec_init_enc_pm to *_clk since
it only has clock operations now.

Reviewed-by: AngeloGioacchino Del Regno 

Signed-off-by: Yunfei Dong 
Co-developed-by: Yong Wu 
---
 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 9 ++---
 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c  | 9 +
 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h  | 3 +--
 3 files changed, 8 insertions(+), 13 deletions(-)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
index 0f326d82dea0..7816efb90cbe 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -260,7 +261,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
return PTR_ERR(dev->fw_handler);
 
dev->venc_pdata = of_device_get_match_data(&pdev->dev);
-   ret = mtk_vcodec_init_enc_pm(dev);
+   ret = mtk_vcodec_init_enc_clk(dev);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to get mtk vcodec clock source!");
goto err_enc_pm;
@@ -372,7 +373,8 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
 err_enc_alloc:
v4l2_device_unregister(&dev->v4l2_dev);
 err_res:
-   mtk_vcodec_release_enc_pm(dev);
+   pm_runtime_disable(dev->pm.dev);
+   put_device(dev->pm.larbvenc);
 err_enc_pm:
mtk_vcodec_fw_release(dev->fw_handler);
return ret;
@@ -462,7 +464,8 @@ static int mtk_vcodec_enc_remove(struct platform_device 
*pdev)
video_unregister_device(dev->vfd_enc);
 
v4l2_device_unregister(&dev->v4l2_dev);
-   mtk_vcodec_release_enc_pm(dev);
+   pm_runtime_disable(dev->pm.dev);
+   put_device(dev->pm.larbvenc);
mtk_vcodec_fw_release(dev->fw_handler);
return 0;
 }
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
index 0c8c8f86788c..0825c6ec4eb7 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
@@ -13,7 +13,7 @@
 #include "mtk_vcodec_enc_pm.h"
 #include "mtk_vcodec_util.h"
 
-int mtk_vcodec_init_enc_pm(struct mtk_vcodec_dev *mtkdev)
+int mtk_vcodec_init_enc_clk(struct mtk_vcodec_dev *mtkdev)
 {
struct device_node *node;
struct platform_device *pdev;
@@ -86,13 +86,6 @@ int mtk_vcodec_init_enc_pm(struct mtk_vcodec_dev *mtkdev)
return ret;
 }
 
-void mtk_vcodec_release_enc_pm(struct mtk_vcodec_dev *mtkdev)
-{
-   pm_runtime_disable(mtkdev->pm.dev);
-   put_device(mtkdev->pm.larbvenc);
-}
-
-
 void mtk_vcodec_enc_clock_on(struct mtk_vcodec_pm *pm)
 {
struct mtk_vcodec_clk *enc_clk = &pm->venc_clk;
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h
index b7ecdfd74823..bc455cefc0cd 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h
@@ -9,8 +9,7 @@
 
 #include "mtk_vcodec_drv.h"
 
-int mtk_vcodec_init_enc_pm(struct mtk_vcodec_dev *dev);
-void mtk_vcodec_release_enc_pm(struct mtk_vcodec_dev *dev);
+int mtk_vcodec_init_enc_clk(struct mtk_vcodec_dev *dev);
 
 void mtk_vcodec_enc_clock_on(struct mtk_vcodec_pm *pm);
 void mtk_vcodec_enc_clock_off(struct mtk_vcodec_pm *pm);
-- 
2.25.1



[PATCH v12, 15/19] dt-bindings: media: mtk-vcodec: Adds decoder dt-bindings for mt8192

2021-12-01 Thread Yunfei Dong
Adds decoder dt-bindings for mt8192.

Signed-off-by: Yunfei Dong 
---
 .../media/mediatek,vcodec-subdev-decoder.yaml | 266 ++
 1 file changed, 266 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/media/mediatek,vcodec-subdev-decoder.yaml

diff --git 
a/Documentation/devicetree/bindings/media/mediatek,vcodec-subdev-decoder.yaml 
b/Documentation/devicetree/bindings/media/mediatek,vcodec-subdev-decoder.yaml
new file mode 100644
index ..67cbcf8b3373
--- /dev/null
+++ 
b/Documentation/devicetree/bindings/media/mediatek,vcodec-subdev-decoder.yaml
@@ -0,0 +1,266 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/media/mediatek,vcodec-subdev-decoder.yaml#";
+$schema: "http://devicetree.org/meta-schemas/core.yaml#";
+
+title: Mediatek Video Decode Accelerator With Multi Hardware
+
+maintainers:
+  - Yunfei Dong 
+
+description: |
+  Mediatek Video Decode is the video decode hardware present in Mediatek
+  SoCs which supports high resolution decoding functionalities. Required
+  parent and child device node.
+
+  About the Decoder Hardware Block Diagram, please check below:
+
++-++
+| ||
+| input -> lat HW -> lat buffer --|--> lat buffer -> core HW -> output |
+|||   | || |
++||---+-||-+
+  lat workqueue   |  core workqueue 

+
-||-||--
+ || ||  
+ \/ \/
+   +--+
+   |enable/disable|
+   |   clk powerirqiommu  |
+   | (lat/lat soc/core0/core1)|
+   +--+
+
+  As above, there are parent and child devices, child mean each hardware. The 
child device
+  controls the information of each hardware independent which include 
clk/power/irq.
+
+  There are two workqueues in parent device: lat workqueue and core workqueue. 
They are used
+  to lat and core hardware deocder. Lat workqueue need to get input bitstream 
and lat buffer,
+  then enable lat to decode, writing the result to lat buffer, dislabe 
hardware when lat decode
+  done. Core workqueue need to get lat buffer and output buffer, then enable 
core to decode,
+  writing the result to output buffer, disable hardware when core decode done. 
These two
+  hardwares will decode each frame cyclically.
+
+  For the smi common may not the same for each hardware, can't combine all 
hardware in one node,
+  or leading to iommu fault when access dram data.
+
+properties:
+  compatible:
+const: mediatek,mt8192-vcodec-dec
+
+  reg:
+maxItems: 1
+
+  iommus:
+minItems: 1
+maxItems: 32
+description: |
+  List of the hardware port in respective IOMMU block for current Socs.
+  Refer to bindings/iommu/mediatek,iommu.yaml.
+
+  mediatek,scp:
+$ref: /schemas/types.yaml#/definitions/phandle
+maxItems: 1
+description: |
+  The node of system control processor (SCP), using
+  the remoteproc & rpmsg framework.
+  $ref: /schemas/remoteproc/mtk,scp.yaml
+
+  dma-ranges:
+maxItems: 1
+description: |
+  Describes the physical address space of IOMMU maps to memory.
+
+  "#address-cells":
+const: 1
+
+  "#size-cells":
+const: 1
+
+  ranges: true
+
+# Required child node:
+patternProperties:
+  vcodec-lat:
+type: object
+
+properties:
+  compatible:
+const: mediatek,mtk-vcodec-lat
+
+  reg:
+maxItems: 1
+
+  interrupts:
+maxItems: 1
+
+  iommus:
+minItems: 1
+maxItems: 32
+description: |
+  List of the hardware port in respective IOMMU block for current Socs.
+  Refer to bindings/iommu/mediatek,iommu.yaml.
+
+  clocks:
+maxItems: 5
+
+  clock-names:
+items:
+  - const: sel
+  - const: soc-vdec
+  - const: soc-lat
+  - const: vdec
+  - const: top
+
+  assigned-clocks:
+maxItems: 1
+
+  assigned-clock-parents:
+maxItems: 1
+
+  power-domains:
+maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - iommus
+  - clocks
+  - clock-names
+  - assigned-clocks
+  - assigned-clock-parents
+  - power-domains
+
+additionalProperties: false
+
+  vcodec-core:
+type: object
+
+properties:
+  compatible:
+const: mediatek,mtk-vcodec

[PATCH v12, 17/19] media: mtk-vcodec: Use codec type to separate different hardware

2021-12-01 Thread Yunfei Dong
There is just one core thread, in order to separate different
hardware, using codec type to separeate it in scp driver.

Signed-off-by: Yunfei Dong 
Reviewed-by: AngeloGioacchino Del Regno 

---
 .../media/platform/mtk-vcodec/vdec_ipi_msg.h  | 12 ---
 .../media/platform/mtk-vcodec/vdec_vpu_if.c   | 34 ---
 .../media/platform/mtk-vcodec/vdec_vpu_if.h   |  4 +++
 3 files changed, 41 insertions(+), 9 deletions(-)

diff --git a/drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h 
b/drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h
index 9d8079c4f976..5daca8d52ebb 100644
--- a/drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h
+++ b/drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h
@@ -35,6 +35,8 @@ enum vdec_ipi_msgid {
  * @msg_id : vdec_ipi_msgid
  * @vpu_inst_addr : VPU decoder instance address. Used if ABI version < 2.
  * @inst_id : instance ID. Used if the ABI version >= 2.
+ * @codec_type : codec fourcc
+ * @reserved   : reserved param
  */
 struct vdec_ap_ipi_cmd {
uint32_t msg_id;
@@ -42,6 +44,8 @@ struct vdec_ap_ipi_cmd {
uint32_t vpu_inst_addr;
uint32_t inst_id;
};
+   uint32_t codec_type;
+   uint32_t reserved;
 };
 
 /**
@@ -59,12 +63,12 @@ struct vdec_vpu_ipi_ack {
 /**
  * struct vdec_ap_ipi_init - for AP_IPIMSG_DEC_INIT
  * @msg_id : AP_IPIMSG_DEC_INIT
- * @reserved   : Reserved field
+ * @codec_type : codec fourcc
  * @ap_inst_addr   : AP video decoder instance address
  */
 struct vdec_ap_ipi_init {
uint32_t msg_id;
-   uint32_t reserved;
+   uint32_t codec_type;
uint64_t ap_inst_addr;
 };
 
@@ -77,7 +81,7 @@ struct vdec_ap_ipi_init {
  * H264 decoder [0]:buf_sz [1]:nal_start
  * VP8 decoder  [0]:width/height
  * VP9 decoder  [0]:profile, [1][2] width/height
- * @reserved   : Reserved field
+ * @codec_type : codec fourcc
  */
 struct vdec_ap_ipi_dec_start {
uint32_t msg_id;
@@ -86,7 +90,7 @@ struct vdec_ap_ipi_dec_start {
uint32_t inst_id;
};
uint32_t data[3];
-   uint32_t reserved;
+   uint32_t codec_type;
 };
 
 /**
diff --git a/drivers/media/platform/mtk-vcodec/vdec_vpu_if.c 
b/drivers/media/platform/mtk-vcodec/vdec_vpu_if.c
index bfd8e87dceff..c84fac52fe26 100644
--- a/drivers/media/platform/mtk-vcodec/vdec_vpu_if.c
+++ b/drivers/media/platform/mtk-vcodec/vdec_vpu_if.c
@@ -100,18 +100,29 @@ static void vpu_dec_ipi_handler(void *data, unsigned int 
len, void *priv)
 
 static int vcodec_vpu_send_msg(struct vdec_vpu_inst *vpu, void *msg, int len)
 {
-   int err;
+   int err, id, msgid;
 
-   mtk_vcodec_debug(vpu, "id=%X", *(uint32_t *)msg);
+   msgid = *(uint32_t *)msg;
+   mtk_vcodec_debug(vpu, "id=%X", msgid);
 
vpu->failure = 0;
vpu->signaled = 0;
 
-   err = mtk_vcodec_fw_ipi_send(vpu->ctx->dev->fw_handler, vpu->id, msg,
+   if (vpu->ctx->dev->vdec_pdata->hw_arch == MTK_VDEC_LAT_SINGLE_CORE) {
+   if (msgid == AP_IPIMSG_DEC_CORE ||
+   msgid == AP_IPIMSG_DEC_CORE_END)
+   id = vpu->core_id;
+   else
+   id = vpu->id;
+   } else {
+   id = vpu->id;
+   }
+
+   err = mtk_vcodec_fw_ipi_send(vpu->ctx->dev->fw_handler, id, msg,
 len, 2000);
if (err) {
mtk_vcodec_err(vpu, "send fail vpu_id=%d msg_id=%X status=%d",
-  vpu->id, *(uint32_t *)msg, err);
+  id, msgid, err);
return err;
}
 
@@ -131,6 +142,7 @@ static int vcodec_send_ap_ipi(struct vdec_vpu_inst *vpu, 
unsigned int msg_id)
msg.vpu_inst_addr = vpu->inst_addr;
else
msg.inst_id = vpu->inst_id;
+   msg.codec_type = vpu->codec_type;
 
err = vcodec_vpu_send_msg(vpu, &msg, sizeof(msg));
mtk_vcodec_debug(vpu, "- id=%X ret=%d", msg_id, err);
@@ -149,14 +161,25 @@ int vpu_dec_init(struct vdec_vpu_inst *vpu)
 
err = mtk_vcodec_fw_ipi_register(vpu->ctx->dev->fw_handler, vpu->id,
 vpu->handler, "vdec", NULL);
-   if (err != 0) {
+   if (err) {
mtk_vcodec_err(vpu, "vpu_ipi_register fail status=%d", err);
return err;
}
 
+   if (vpu->ctx->dev->vdec_pdata->hw_arch == MTK_VDEC_LAT_SINGLE_CORE) {
+   err = mtk_vcodec_fw_ipi_register(vpu->ctx->dev->fw_handler,
+vpu->core_id, vpu->handler,
+"vdec", NULL);
+   if (err) {
+   mtk_vcodec_err(vpu, "vpu_ipi_register core fail 
status=%d", err);
+   return err;
+   }
+   }
+
memset(&msg, 0, sizeof(msg));
msg.msg_id = AP_IPIMSG_DEC_INIT;
msg.ap_inst_addr = (unsigned long)vpu;
+   msg.codec_type = vpu->codec_type;
 
  

[PATCH v12, 16/19] media: mtk-vcodec: Add core dec and dec end ipi msg

2021-12-01 Thread Yunfei Dong
Add core dec and dec end ipi msg: AP_IPIMSG_DEC_CORE/AP_IPIMSG_DEC_CORE_END.

Signed-off-by: Yunfei Dong 
Reviewed-by: AngeloGioacchino Del Regno 

---
 .../media/platform/mtk-vcodec/vdec_ipi_msg.h   |  4 
 .../media/platform/mtk-vcodec/vdec_vpu_if.c| 12 
 .../media/platform/mtk-vcodec/vdec_vpu_if.h| 18 ++
 3 files changed, 34 insertions(+)

diff --git a/drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h 
b/drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h
index 5f45a537beb4..9d8079c4f976 100644
--- a/drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h
+++ b/drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h
@@ -18,12 +18,16 @@ enum vdec_ipi_msgid {
AP_IPIMSG_DEC_END = 0xA002,
AP_IPIMSG_DEC_DEINIT = 0xA003,
AP_IPIMSG_DEC_RESET = 0xA004,
+   AP_IPIMSG_DEC_CORE = 0xA005,
+   AP_IPIMSG_DEC_CORE_END = 0xA006,
 
VPU_IPIMSG_DEC_INIT_ACK = 0xB000,
VPU_IPIMSG_DEC_START_ACK = 0xB001,
VPU_IPIMSG_DEC_END_ACK = 0xB002,
VPU_IPIMSG_DEC_DEINIT_ACK = 0xB003,
VPU_IPIMSG_DEC_RESET_ACK = 0xB004,
+   VPU_IPIMSG_DEC_CORE_ACK = 0xB005,
+   VPU_IPIMSG_DEC_CORE_END_ACK = 0xB006,
 };
 
 /**
diff --git a/drivers/media/platform/mtk-vcodec/vdec_vpu_if.c 
b/drivers/media/platform/mtk-vcodec/vdec_vpu_if.c
index 5dffc459a33d..bfd8e87dceff 100644
--- a/drivers/media/platform/mtk-vcodec/vdec_vpu_if.c
+++ b/drivers/media/platform/mtk-vcodec/vdec_vpu_if.c
@@ -85,6 +85,8 @@ static void vpu_dec_ipi_handler(void *data, unsigned int len, 
void *priv)
case VPU_IPIMSG_DEC_END_ACK:
case VPU_IPIMSG_DEC_DEINIT_ACK:
case VPU_IPIMSG_DEC_RESET_ACK:
+   case VPU_IPIMSG_DEC_CORE_ACK:
+   case VPU_IPIMSG_DEC_CORE_END_ACK:
break;
 
default:
@@ -191,11 +193,21 @@ int vpu_dec_start(struct vdec_vpu_inst *vpu, uint32_t 
*data, unsigned int len)
return err;
 }
 
+int vpu_dec_core(struct vdec_vpu_inst *vpu)
+{
+   return vcodec_send_ap_ipi(vpu, AP_IPIMSG_DEC_CORE);
+}
+
 int vpu_dec_end(struct vdec_vpu_inst *vpu)
 {
return vcodec_send_ap_ipi(vpu, AP_IPIMSG_DEC_END);
 }
 
+int vpu_dec_core_end(struct vdec_vpu_inst *vpu)
+{
+   return vcodec_send_ap_ipi(vpu, AP_IPIMSG_DEC_CORE_END);
+}
+
 int vpu_dec_deinit(struct vdec_vpu_inst *vpu)
 {
return vcodec_send_ap_ipi(vpu, AP_IPIMSG_DEC_DEINIT);
diff --git a/drivers/media/platform/mtk-vcodec/vdec_vpu_if.h 
b/drivers/media/platform/mtk-vcodec/vdec_vpu_if.h
index c2ed5b6cab8b..ae24b75d1649 100644
--- a/drivers/media/platform/mtk-vcodec/vdec_vpu_if.h
+++ b/drivers/media/platform/mtk-vcodec/vdec_vpu_if.h
@@ -82,4 +82,22 @@ int vpu_dec_deinit(struct vdec_vpu_inst *vpu);
  */
 int vpu_dec_reset(struct vdec_vpu_inst *vpu);
 
+/**
+ * vpu_dec_core - core start decoding, basically the function will be invoked 
once
+ * every frame.
+ *
+ * @vpu : instance for vdec_vpu_inst
+ */
+int vpu_dec_core(struct vdec_vpu_inst *vpu);
+
+/**
+ * vpu_dec_core_end - core end decoding, basically the function will be 
invoked once
+ *   when core HW decoding done and receive interrupt 
successfully. The
+ *   decoder in VPU will updata hardware information and deinit 
hardware
+ *   and check if there is a new decoded frame available to 
display.
+ *
+ * @vpu : instance for vdec_vpu_inst
+ */
+int vpu_dec_core_end(struct vdec_vpu_inst *vpu);
+
 #endif
-- 
2.25.1



[PATCH v12, 14/19] media: mtk-vcodec: Support 34bits dma address for vdec

2021-12-01 Thread Yunfei Dong
Use the dma_set_mask_and_coherent helper to set vdec
DMA bit mask to support 34bits iova space(16GB) that
the mt8192 iommu HW support.

Whole the iova range separate to 0~4G/4G~8G/8G~12G/12G~16G,
regarding which iova range VDEC actually locate, it
depends on the dma-ranges property of vdec dtsi node.

Reviewed-by: AngeloGioacchino Del Regno 

Signed-off-by: Yunfei Dong 
---
 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
index 4fbff61d2334..cdbe5ffeae26 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
@@ -352,6 +352,14 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
}
}
 
+   if (of_get_property(pdev->dev.of_node, "dma-ranges", NULL)) {
+   ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(34));
+   if (ret) {
+   mtk_v4l2_err("Failed to set mask");
+   goto err_core_workq;
+   }
+   }
+
for (i = 0; i < MTK_VDEC_HW_MAX; i++)
mutex_init(&dev->dec_mutex[i]);
spin_lock_init(&dev->irqlock);
-- 
2.25.1



[PATCH v12, 12/19] media: mtk-vcodec: Add new interface to lock different hardware

2021-12-01 Thread Yunfei Dong
For add new hardware, not only need to lock lat hardware, also
need to lock core hardware in case of different instance start
to decoder at the same time.

Signed-off-by: Yunfei Dong 
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c | 4 ++--
 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c | 6 +++---
 drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h | 2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
index 2b334a8a81c6..130ecef2e766 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
@@ -105,12 +105,12 @@ static int vidioc_decoder_cmd(struct file *file, void 
*priv,
 
 void mtk_vdec_unlock(struct mtk_vcodec_ctx *ctx)
 {
-   mutex_unlock(&ctx->dev->dec_mutex);
+   mutex_unlock(&ctx->dev->dec_mutex[ctx->hw_id]);
 }
 
 void mtk_vdec_lock(struct mtk_vcodec_ctx *ctx)
 {
-   mutex_lock(&ctx->dev->dec_mutex);
+   mutex_lock(&ctx->dev->dec_mutex[ctx->hw_id]);
 }
 
 void mtk_vcodec_dec_release(struct mtk_vcodec_ctx *ctx)
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
index 81b5ea98201e..d460703f335d 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
@@ -309,7 +309,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
struct video_device *vfd_dec;
phandle rproc_phandle;
enum mtk_vcodec_fw_type fw_type;
-   int ret;
+   int i, ret;
 
dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
if (!dev)
@@ -341,8 +341,8 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
goto err_dec_pm;
}
 
-   mutex_init(&dev->dec_mutex);
-   mutex_init(&dev->dev_mutex);
+   for (i = 0; i < MTK_VDEC_HW_MAX; i++)
+   mutex_init(&dev->dec_mutex[i]);
spin_lock_init(&dev->irqlock);
 
snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s",
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
index 5d5376fcf0a7..cbaed96dcfa2 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
@@ -499,7 +499,7 @@ struct mtk_vcodec_dev {
int dec_irq;
int enc_irq;
 
-   struct mutex dec_mutex;
+   struct mutex dec_mutex[MTK_VDEC_HW_MAX];
struct mutex enc_mutex;
 
struct mtk_vcodec_pm pm;
-- 
2.25.1



[PATCH v12, 10/19] media: mtk-vcodec: Add msg queue feature for lat and core architecture

2021-12-01 Thread Yunfei Dong
For lat and core architecture, lat thread will send message to core
thread when lat decode done. Core hardware will use the message
from lat to decode, then free message to lat thread when decode done.

Signed-off-by: Yunfei Dong 
---
fix comments from Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/media/platform/mtk-vcodec/Makefile|   1 +
 .../platform/mtk-vcodec/mtk_vcodec_drv.h  |   9 +
 .../platform/mtk-vcodec/vdec_msg_queue.c  | 260 ++
 .../platform/mtk-vcodec/vdec_msg_queue.h  | 143 ++
 4 files changed, 413 insertions(+)
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec_msg_queue.c
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec_msg_queue.h

diff --git a/drivers/media/platform/mtk-vcodec/Makefile 
b/drivers/media/platform/mtk-vcodec/Makefile
index c61bfb179bcc..359619653a0e 100644
--- a/drivers/media/platform/mtk-vcodec/Makefile
+++ b/drivers/media/platform/mtk-vcodec/Makefile
@@ -12,6 +12,7 @@ mtk-vcodec-dec-y := vdec/vdec_h264_if.o \
mtk_vcodec_dec_drv.o \
vdec_drv_if.o \
vdec_vpu_if.o \
+   vdec_msg_queue.o \
mtk_vcodec_dec.o \
mtk_vcodec_dec_stateful.o \
mtk_vcodec_dec_stateless.o \
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
index 7fc106df039b..610b0af13879 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
@@ -15,7 +15,9 @@
 #include 
 #include 
 #include 
+
 #include "mtk_vcodec_util.h"
+#include "vdec_msg_queue.h"
 
 #define MTK_VCODEC_DRV_NAME"mtk_vcodec_drv"
 #define MTK_VCODEC_DEC_NAME"mtk-vcodec-dec"
@@ -282,6 +284,8 @@ struct vdec_pic_info {
  * @decoded_frame_cnt: number of decoded frames
  * @lock: protect variables accessed by V4L2 threads and worker thread such as
  *   mtk_video_dec_buf.
+ *
+ * @msg_queue: msg queue used to store lat buffer information.
  */
 struct mtk_vcodec_ctx {
enum mtk_instance_type type;
@@ -325,6 +329,7 @@ struct mtk_vcodec_ctx {
int decoded_frame_cnt;
struct mutex lock;
 
+   struct vdec_msg_queue msg_queue;
 };
 
 enum mtk_chip {
@@ -457,6 +462,8 @@ struct mtk_vcodec_enc_pdata {
  * @dec_capability: used to identify decode capability, ex: 4k
  * @enc_capability: used to identify encode capability
  *
+ * @msg_queue_core_ctx: msg queue context used for core workqueue
+ *
  * @subdev_dev: subdev hardware device
  * @subdev_bitmap: used to record hardware is ready or not
  */
@@ -497,6 +504,8 @@ struct mtk_vcodec_dev {
unsigned int dec_capability;
unsigned int enc_capability;
 
+   struct vdec_msg_queue_ctx msg_queue_core_ctx;
+
void *subdev_dev[MTK_VDEC_HW_MAX];
DECLARE_BITMAP(subdev_bitmap, MTK_VDEC_HW_MAX);
 };
diff --git a/drivers/media/platform/mtk-vcodec/vdec_msg_queue.c 
b/drivers/media/platform/mtk-vcodec/vdec_msg_queue.c
new file mode 100644
index ..913aefa67618
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/vdec_msg_queue.c
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Yunfei Dong 
+ */
+
+#include 
+#include 
+#include 
+
+#include "mtk_vcodec_dec_pm.h"
+#include "mtk_vcodec_drv.h"
+#include "vdec_msg_queue.h"
+
+#define VDEC_MSG_QUEUE_TIMEOUT_MS 1500
+
+/* the size used to store lat slice header information */
+#define VDEC_LAT_SLICE_HEADER_SZ(640 * SZ_1K)
+
+/* the size used to store avc error information */
+#define VDEC_ERR_MAP_SZ_AVC (17 * SZ_1K)
+
+/* core will read the trans buffer which decoded by lat to decode again.
+ * The trans buffer size of FHD and 4K bitstreams are different.
+ */
+static int vde_msg_queue_get_trans_size(int width, int height)
+{
+   if (width > 1920 || height > 1088)
+   return 30 * SZ_1M;
+   else
+   return 6 * SZ_1M;
+}
+
+void vdec_msg_queue_init_ctx(struct vdec_msg_queue_ctx *ctx, int 
hardware_index)
+{
+   init_waitqueue_head(&ctx->ready_to_use);
+   INIT_LIST_HEAD(&ctx->ready_queue);
+   spin_lock_init(&ctx->ready_lock);
+   ctx->ready_num = 0;
+   ctx->hardware_index = hardware_index;
+}
+
+static struct list_head *vdec_get_buf_list(int hardware_index, struct 
vdec_lat_buf *buf)
+{
+   switch (hardware_index) {
+   case MTK_VDEC_CORE:
+   return &buf->core_list;
+   case MTK_VDEC_LAT0:
+   return &buf->lat_list;
+   default:
+   return NULL;
+   }
+}
+
+int vdec_msg_queue_qbuf(struct vdec_msg_queue_ctx *msg_ctx, struct 
vdec_lat_buf *buf)
+{
+   struct list_head *head;
+
+   head = vdec_get_buf_list(msg_ctx->hardware_index, buf);
+   if (!head) {
+   mtk_v4l2_err("fail to qbuf: %d",msg_ctx->hardware_index);
+   return -EINVAL;
+   }
+
+   spin_lock(&msg_ctx->ready_lock);
+ 

[PATCH v12, 13/19] media: mtk-vcodec: Add work queue for core hardware decode

2021-12-01 Thread Yunfei Dong
Add work queue to process core hardware information.
First, get lat_buf from message queue, then call core
hardware of each codec(H264/VP9/AV1) to decode, finally
puts lat_buf back to the message.

Signed-off-by: Yunfei Dong 
---
 .../platform/mtk-vcodec/mtk_vcodec_dec_drv.c  | 16 +++-
 .../platform/mtk-vcodec/mtk_vcodec_drv.h  |  3 ++
 .../platform/mtk-vcodec/vdec_msg_queue.c  | 41 ---
 .../platform/mtk-vcodec/vdec_msg_queue.h  |  8 ++--
 4 files changed, 57 insertions(+), 11 deletions(-)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
index d460703f335d..4fbff61d2334 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
@@ -341,6 +341,17 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
goto err_dec_pm;
}
 
+   if (IS_VDEC_LAT_ARCH(dev->vdec_pdata->hw_arch)) {
+   vdec_msg_queue_init_ctx(&dev->msg_queue_core_ctx, 
MTK_VDEC_CORE);
+   dev->core_workqueue = alloc_ordered_workqueue("core-decoder",
+   WQ_MEM_RECLAIM | WQ_FREEZABLE);
+   if (!dev->core_workqueue) {
+   mtk_v4l2_err("Failed to create core workqueue");
+   ret = -EINVAL;
+   goto err_res;
+   }
+   }
+
for (i = 0; i < MTK_VDEC_HW_MAX; i++)
mutex_init(&dev->dec_mutex[i]);
spin_lock_init(&dev->irqlock);
@@ -351,7 +362,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
if (ret) {
mtk_v4l2_err("v4l2_device_register err=%d", ret);
-   goto err_res;
+   goto err_core_workq;
}
 
init_waitqueue_head(&dev->queue);
@@ -450,6 +461,9 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
video_unregister_device(vfd_dec);
 err_dec_alloc:
v4l2_device_unregister(&dev->v4l2_dev);
+err_core_workq:
+   if (IS_VDEC_LAT_ARCH(dev->vdec_pdata->hw_arch))
+   destroy_workqueue(dev->core_workqueue);
 err_res:
mtk_vcodec_release_dec_pm(&dev->pm);
 err_dec_pm:
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
index cbaed96dcfa2..a558cc16026d 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
@@ -27,6 +27,7 @@
 #define MTK_VCODEC_MAX_PLANES  3
 #define MTK_V4L2_BENCHMARK 0
 #define WAIT_INTR_TIMEOUT_MS   1000
+#define IS_VDEC_LAT_ARCH(hw_arch) ((hw_arch) >= MTK_VDEC_LAT_SINGLE_CORE)
 
 /*
  * enum mtk_hw_reg_idx - MTK hw register base index
@@ -464,6 +465,7 @@ struct mtk_vcodec_enc_pdata {
  * @dec_capability: used to identify decode capability, ex: 4k
  * @enc_capability: used to identify encode capability
  *
+ * @core_workqueue: queue used for core hardware decode
  * @msg_queue_core_ctx: msg queue context used for core workqueue
  *
  * @subdev_dev: subdev hardware device
@@ -506,6 +508,7 @@ struct mtk_vcodec_dev {
unsigned int dec_capability;
unsigned int enc_capability;
 
+   struct workqueue_struct *core_workqueue;
struct vdec_msg_queue_ctx msg_queue_core_ctx;
 
void *subdev_dev[MTK_VDEC_HW_MAX];
diff --git a/drivers/media/platform/mtk-vcodec/vdec_msg_queue.c 
b/drivers/media/platform/mtk-vcodec/vdec_msg_queue.c
index 913aefa67618..24f1d03df9f1 100644
--- a/drivers/media/platform/mtk-vcodec/vdec_msg_queue.c
+++ b/drivers/media/platform/mtk-vcodec/vdec_msg_queue.c
@@ -68,6 +68,9 @@ int vdec_msg_queue_qbuf(struct vdec_msg_queue_ctx *msg_ctx, 
struct vdec_lat_buf
 
if (msg_ctx->hardware_index != MTK_VDEC_CORE)
wake_up_all(&msg_ctx->ready_to_use);
+   else
+   queue_work(buf->ctx->dev->core_workqueue,
+   &buf->ctx->msg_queue.core_work);
 
mtk_v4l2_debug(3, "enqueue buf type: %d addr: 0x%p num: %d",
msg_ctx->hardware_index, buf, msg_ctx->ready_num);
@@ -169,8 +172,7 @@ bool vdec_msg_queue_wait_lat_buf_full(struct vdec_msg_queue 
*msg_queue)
return false;
 }
 
-void vdec_msg_queue_deinit(
-   struct vdec_msg_queue *msg_queue,
+void vdec_msg_queue_deinit(struct vdec_msg_queue *msg_queue,
struct mtk_vcodec_ctx *ctx)
 {
struct vdec_lat_buf *lat_buf;
@@ -196,10 +198,36 @@ void vdec_msg_queue_deinit(
}
 }
 
-int vdec_msg_queue_init(
-   struct vdec_msg_queue *msg_queue,
-   struct mtk_vcodec_ctx *ctx,
-   core_decode_cb_t core_decode,
+static void vdec_msg_queue_core_work(struct work_struct *work)
+{
+   struct vdec_msg_queue *msg_queue =
+   container_of(work, struct vdec_msg_queue, core_work);
+   struct mtk_vcodec_ctx *ctx =
+   container_of(msg_queue, struct mtk_vcodec_c

[PATCH v12, 09/19] media: mtk-vcodec: Add irq interface for multi hardware

2021-12-01 Thread Yunfei Dong
Adds irq interface for multi hardware.

Signed-off-by: Yunfei Dong 
---
fix comments from Reviewed-by: AngeloGioacchino Del Regno 

---
 .../platform/mtk-vcodec/mtk_vcodec_dec_drv.c  | 32 ---
 .../platform/mtk-vcodec/mtk_vcodec_dec_hw.c   |  2 +-
 .../platform/mtk-vcodec/mtk_vcodec_drv.h  | 25 +++
 .../platform/mtk-vcodec/mtk_vcodec_enc_drv.c  |  4 +--
 .../platform/mtk-vcodec/mtk_vcodec_intr.c | 27 +++-
 .../platform/mtk-vcodec/mtk_vcodec_intr.h |  4 +--
 .../platform/mtk-vcodec/vdec/vdec_h264_if.c   |  2 +-
 .../mtk-vcodec/vdec/vdec_h264_req_if.c|  2 +-
 .../platform/mtk-vcodec/vdec/vdec_vp8_if.c|  2 +-
 .../platform/mtk-vcodec/vdec/vdec_vp9_if.c|  2 +-
 .../platform/mtk-vcodec/venc/venc_h264_if.c   |  2 +-
 .../platform/mtk-vcodec/venc/venc_vp8_if.c|  2 +-
 12 files changed, 69 insertions(+), 37 deletions(-)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
index 95fbe9be3f6d..aa16e3f9ad5d 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
@@ -52,6 +52,19 @@ static int mtk_vcodec_subdev_device_check(struct 
mtk_vcodec_dev *vdec_dev)
return 0;
 }
 
+static int mtk_vcodec_get_hw_count(struct mtk_vcodec_dev *dev)
+{
+   switch (dev->vdec_pdata->hw_arch) {
+   case MTK_VDEC_PURE_SINGLE_CORE:
+return MTK_VDEC_ONE_CORE;
+   case MTK_VDEC_LAT_SINGLE_CORE:
+   return MTK_VDEC_ONE_LAT_ONE_CORE;
+   default:
+   mtk_v4l2_err("hw arch %d not supported", 
dev->vdec_pdata->hw_arch);
+   return MTK_VDEC_NO_HW;
+   }
+}
+
 static irqreturn_t mtk_vcodec_dec_irq_handler(int irq, void *priv)
 {
struct mtk_vcodec_dev *dev = priv;
@@ -83,7 +96,7 @@ static irqreturn_t mtk_vcodec_dec_irq_handler(int irq, void 
*priv)
writel((readl(vdec_misc_addr) & ~VDEC_IRQ_CLR),
dev->reg_base[VDEC_MISC] + VDEC_IRQ_CFG_REG);
 
-   wake_up_ctx(ctx, MTK_INST_IRQ_RECEIVED);
+   wake_up_ctx(ctx, MTK_INST_IRQ_RECEIVED, 0);
 
mtk_v4l2_debug(3,
"mtk_vcodec_dec_irq_handler :wake up ctx %d, 
dec_done_status=%x",
@@ -156,7 +169,7 @@ static int fops_vcodec_open(struct file *file)
 {
struct mtk_vcodec_dev *dev = video_drvdata(file);
struct mtk_vcodec_ctx *ctx = NULL;
-   int ret = 0;
+   int ret = 0, i, hw_count;
struct vb2_queue *src_vq;
 
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
@@ -170,9 +183,20 @@ static int fops_vcodec_open(struct file *file)
v4l2_fh_add(&ctx->fh);
INIT_LIST_HEAD(&ctx->list);
ctx->dev = dev;
-   init_waitqueue_head(&ctx->queue);
-   mutex_init(&ctx->lock);
 
+   if (ctx->dev->vdec_pdata->is_subdev_supported) {
+   hw_count = mtk_vcodec_get_hw_count(dev);
+   if (!hw_count) {
+   ret = -EINVAL;
+   goto err_ctrls_setup;
+   }
+   for (i = 0; i < hw_count; i++)
+   init_waitqueue_head(&ctx->queue[i]);
+   } else {
+   init_waitqueue_head(&ctx->queue[0]);
+   }
+
+   mutex_init(&ctx->lock);
ret = mtk_vcodec_subdev_device_check(dev);
if (ret) {
mtk_v4l2_err("Failed to check vdec comp device.");
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_hw.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_hw.c
index 025a103008ba..8bd23504cf4c 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_hw.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_hw.c
@@ -61,7 +61,7 @@ static irqreturn_t mtk_vdec_hw_irq_handler(int irq, void 
*priv)
writel(dec_done_status | VDEC_IRQ_CFG, vdec_misc_addr);
writel(dec_done_status & ~VDEC_IRQ_CLR, vdec_misc_addr);
 
-   wake_up_ctx(ctx, MTK_INST_IRQ_RECEIVED);
+   wake_up_ctx(ctx, MTK_INST_IRQ_RECEIVED, dev->hw_idx);
 
mtk_v4l2_debug(3, "wake up ctx %d, dec_done_status=%x",
ctx->id, dec_done_status);
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
index 79957222c979..7fc106df039b 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
@@ -104,6 +104,16 @@ enum mtk_vdec_hw_id {
MTK_VDEC_HW_MAX,
 };
 
+/**
+ * struct mtk_vdec_hw_count - Supported hardware count
+ */
+enum mtk_vdec_hw_count {
+   MTK_VDEC_NO_HW = 0,
+   MTK_VDEC_ONE_CORE,
+   MTK_VDEC_ONE_LAT_ONE_CORE,
+   MTK_VDEC_MAX_HW_COUNT,
+};
+
 /*
  * struct mtk_video_fmt - Structure used to store information about 
pixelformats
  */
@@ -293,9 +303,9 @@ struct mtk_vcodec_ctx {
struct vdec_pic_info picinfo;
int dpb_size;
 
-   int int_cond;
-   int int_type;
-   wait_queue_head_t queue;
+

[PATCH v12, 11/19] media: mtk-vcodec: Generalize power and clock on/off interfaces

2021-12-01 Thread Yunfei Dong
Generalizes power and clock on/off interfaces to support different hardware.

Signed-off-by: Yunfei Dong 
---
fix comments from Reviewed-by: AngeloGioacchino Del Regno 

---
 .../platform/mtk-vcodec/mtk_vcodec_dec_drv.c  |  6 +-
 .../platform/mtk-vcodec/mtk_vcodec_dec_hw.c   |  2 +-
 .../platform/mtk-vcodec/mtk_vcodec_dec_hw.h   |  4 +
 .../platform/mtk-vcodec/mtk_vcodec_dec_pm.c   | 76 +--
 .../platform/mtk-vcodec/mtk_vcodec_dec_pm.h   |  8 +-
 .../platform/mtk-vcodec/mtk_vcodec_drv.h  |  2 +
 .../platform/mtk-vcodec/mtk_vcodec_util.c | 59 +++---
 .../platform/mtk-vcodec/mtk_vcodec_util.h |  8 +-
 .../media/platform/mtk-vcodec/vdec_drv_if.c   | 21 ++---
 9 files changed, 146 insertions(+), 40 deletions(-)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
index aa16e3f9ad5d..81b5ea98201e 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
@@ -74,7 +74,7 @@ static irqreturn_t mtk_vcodec_dec_irq_handler(int irq, void 
*priv)
void __iomem *vdec_misc_addr = dev->reg_base[VDEC_MISC] +
VDEC_IRQ_CFG_REG;
 
-   ctx = mtk_vcodec_get_curr_ctx(dev);
+   ctx = mtk_vcodec_get_curr_ctx(dev, MTK_VDEC_CORE);
 
/* check if HW active or not */
cg_status = readl(dev->reg_base[0]);
@@ -223,7 +223,7 @@ static int fops_vcodec_open(struct file *file)
mtk_vcodec_dec_set_default_params(ctx);
 
if (v4l2_fh_is_singular(&ctx->fh)) {
-   ret = mtk_vcodec_dec_pw_on(&dev->pm);
+   ret = mtk_vcodec_dec_pw_on(dev, MTK_VDEC_LAT0);
if (ret < 0)
goto err_load_fw;
/*
@@ -283,7 +283,7 @@ static int fops_vcodec_release(struct file *file)
mtk_vcodec_dec_release(ctx);
 
if (v4l2_fh_is_singular(&ctx->fh))
-   mtk_vcodec_dec_pw_off(&dev->pm);
+   mtk_vcodec_dec_pw_off(dev, MTK_VDEC_LAT0);
v4l2_fh_del(&ctx->fh);
v4l2_fh_exit(&ctx->fh);
v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_hw.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_hw.c
index 8bd23504cf4c..389a17eb4085 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_hw.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_hw.c
@@ -42,7 +42,7 @@ static irqreturn_t mtk_vdec_hw_irq_handler(int irq, void 
*priv)
void __iomem *vdec_misc_addr = dev->reg_base[VDEC_HW_MISC] +
VDEC_IRQ_CFG_REG;
 
-   ctx = mtk_vcodec_get_curr_ctx(dev->main_dev);
+   ctx = mtk_vcodec_get_curr_ctx(dev->main_dev, dev->hw_idx);
 
/* check if HW active or not */
cg_status = readl(dev->reg_base[VDEC_HW_SYS]);
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_hw.h 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_hw.h
index f7f36790629d..fdf1435fc932 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_hw.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_hw.h
@@ -34,6 +34,8 @@ enum mtk_vdec_hw_reg_idx {
  * @main_dev: main device
  * @reg_base: Mapped address of MTK Vcodec registers.
  *
+ * @curr_ctx: the context that is waiting for codec hardware
+ *
  * @dec_irq: decoder irq resource
  * @pm: power management control
  * @hw_idx: each hardware index
@@ -43,6 +45,8 @@ struct mtk_vdec_hw_dev {
struct mtk_vcodec_dev *main_dev;
void __iomem *reg_base[VDEC_HW_MAX];
 
+   struct mtk_vcodec_ctx *curr_ctx;
+
int dec_irq;
struct mtk_vcodec_pm pm;
int hw_idx;
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
index 221cf60e9fbf..4cf03d38d141 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
@@ -5,11 +5,13 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 
+#include "mtk_vcodec_dec_hw.h"
 #include "mtk_vcodec_dec_pm.h"
 #include "mtk_vcodec_util.h"
 
@@ -86,10 +88,23 @@ void mtk_vcodec_release_dec_pm(struct mtk_vcodec_pm *pm)
 }
 EXPORT_SYMBOL_GPL(mtk_vcodec_release_dec_pm);
 
-int mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm)
+int mtk_vcodec_dec_pw_on(struct mtk_vcodec_dev *vdec_dev, int hw_idx)
 {
+   struct mtk_vdec_hw_dev *subdev_dev;
+   struct mtk_vcodec_pm *pm;
int ret;
 
+   if (vdec_dev->vdec_pdata->is_subdev_supported) {
+   subdev_dev = mtk_vcodec_get_hw_dev(vdec_dev, hw_idx);
+   if (!subdev_dev) {
+   mtk_v4l2_err("Failed to get hw dev\n");
+   return -EINVAL;
+   }
+   pm = &subdev_dev->pm;
+   } else {
+   pm = &vdec_dev->pm;
+   }
+
ret = pm_runtime_resume_and_get(pm->dev);

[PATCH v12, 02/19] media: mtk-vcodec: Align vcodec wake up interrupt interface

2021-12-01 Thread Yunfei Dong
Vdec and venc can use the same function to wake up interrupt event.

Reviewed-by: Tzung-Bi Shih 
Reviewed-by: AngeloGioacchino Del Regno 

Reviewed-by: Steve Cho 
Signed-off-by: Yunfei Dong 
---
 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c | 9 +
 drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h | 8 
 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 8 
 3 files changed, 9 insertions(+), 16 deletions(-)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
index 59caf2163349..055d50e52720 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
@@ -31,13 +31,6 @@
 module_param(mtk_v4l2_dbg_level, int, 0644);
 module_param(mtk_vcodec_dbg, bool, 0644);
 
-/* Wake up context wait_queue */
-static void wake_up_ctx(struct mtk_vcodec_ctx *ctx)
-{
-   ctx->int_cond = 1;
-   wake_up_interruptible(&ctx->queue);
-}
-
 static irqreturn_t mtk_vcodec_dec_irq_handler(int irq, void *priv)
 {
struct mtk_vcodec_dev *dev = priv;
@@ -69,7 +62,7 @@ static irqreturn_t mtk_vcodec_dec_irq_handler(int irq, void 
*priv)
writel((readl(vdec_misc_addr) & ~VDEC_IRQ_CLR),
dev->reg_base[VDEC_MISC] + VDEC_IRQ_CFG_REG);
 
-   wake_up_ctx(ctx);
+   wake_up_ctx(ctx, MTK_INST_IRQ_RECEIVED);
 
mtk_v4l2_debug(3,
"mtk_vcodec_dec_irq_handler :wake up ctx %d, 
dec_done_status=%x",
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
index 581522177308..1d2370608d0d 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
@@ -473,4 +473,12 @@ static inline struct mtk_vcodec_ctx *ctrl_to_ctx(struct 
v4l2_ctrl *ctrl)
return container_of(ctrl->handler, struct mtk_vcodec_ctx, ctrl_hdl);
 }
 
+/* Wake up context wait_queue */
+static inline void wake_up_ctx(struct mtk_vcodec_ctx *ctx, unsigned int reason)
+{
+   ctx->int_cond = 1;
+   ctx->int_type = reason;
+   wake_up_interruptible(&ctx->queue);
+}
+
 #endif /* _MTK_VCODEC_DRV_H_ */
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
index eed67394cf46..7c3487fb3498 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
@@ -65,14 +65,6 @@ static const struct mtk_video_fmt 
mtk_video_formats_capture_vp8[] =  {
},
 };
 
-/* Wake up context wait_queue */
-static void wake_up_ctx(struct mtk_vcodec_ctx *ctx, unsigned int reason)
-{
-   ctx->int_cond = 1;
-   ctx->int_type = reason;
-   wake_up_interruptible(&ctx->queue);
-}
-
 static void clean_irq_status(unsigned int irq_status, void __iomem *addr)
 {
if (irq_status & MTK_VENC_IRQ_STATUS_PAUSE)
-- 
2.25.1



[PATCH v12, 07/19] dt-bindings: media: mtk-vcodec: Separate video encoder and decoder dt-bindings

2021-12-01 Thread Yunfei Dong
Separate decoder and encoder document for the dts are big difference.

Reviewed-by: Rob Herring
Signed-off-by: Yunfei Dong 
---
 .../media/mediatek,vcodec-decoder.yaml| 176 +
 .../media/mediatek,vcodec-encoder.yaml| 187 ++
 .../bindings/media/mediatek-vcodec.txt| 131 
 3 files changed, 363 insertions(+), 131 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/media/mediatek,vcodec-decoder.yaml
 create mode 100644 
Documentation/devicetree/bindings/media/mediatek,vcodec-encoder.yaml
 delete mode 100644 Documentation/devicetree/bindings/media/mediatek-vcodec.txt

diff --git 
a/Documentation/devicetree/bindings/media/mediatek,vcodec-decoder.yaml 
b/Documentation/devicetree/bindings/media/mediatek,vcodec-decoder.yaml
new file mode 100644
index ..df1d677098fd
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/mediatek,vcodec-decoder.yaml
@@ -0,0 +1,176 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/mediatek,vcodec-decoder.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek Video Decode Accelerator
+
+maintainers:
+  - Yunfei Dong 
+
+description: |+
+  Mediatek Video Decode is the video decode hardware present in Mediatek
+  SoCs which supports high resolution decoding functionalities.
+
+properties:
+  compatible:
+enum:
+  - mediatek,mt8173-vcodec-dec
+  - mediatek,mt8183-vcodec-dec
+
+  reg:
+maxItems: 12
+
+  interrupts:
+maxItems: 1
+
+  clocks:
+maxItems: 8
+
+  clock-names:
+items:
+  - const: vcodecpll
+  - const: univpll_d2
+  - const: clk_cci400_sel
+  - const: vdec_sel
+  - const: vdecpll
+  - const: vencpll
+  - const: venc_lt_sel
+  - const: vdec_bus_clk_src
+
+  assigned-clocks: true
+
+  assigned-clock-parents: true
+
+  assigned-clock-rates: true
+
+  power-domains:
+maxItems: 1
+
+  iommus:
+minItems: 1
+maxItems: 32
+description: |
+  List of the hardware port in respective IOMMU block for current Socs.
+  Refer to bindings/iommu/mediatek,iommu.yaml.
+
+  dma-ranges:
+maxItems: 1
+description: |
+  Describes the physical address space of IOMMU maps to memory.
+
+  mediatek,larb:
+$ref: /schemas/types.yaml#/definitions/phandle
+maxItems: 1
+description: |
+  Must contain the local arbiters in the current Socs.
+
+  mediatek,vpu:
+$ref: /schemas/types.yaml#/definitions/phandle
+maxItems: 1
+description:
+  Describes point to vpu.
+
+  mediatek,scp:
+$ref: /schemas/types.yaml#/definitions/phandle
+maxItems: 1
+description:
+  Describes point to scp.
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+  - iommus
+  - assigned-clocks
+  - assigned-clock-parents
+
+allOf:
+  - if:
+  properties:
+compatible:
+  contains:
+enum:
+  - mediatek,mt8183-vcodec-dec
+
+then:
+  required:
+- mediatek,scp
+
+  - if:
+  properties:
+compatible:
+  contains:
+enum:
+  - mediatek,mt8173-vcodec-dec
+
+then:
+  required:
+- mediatek,vpu
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+#include 
+#include 
+#include 
+#include 
+
+vcodec_dec: vcodec@1600 {
+  compatible = "mediatek,mt8173-vcodec-dec";
+  reg = <0x1600 0x100>,   /*VDEC_SYS*/
+  <0x1602 0x1000>,  /*VDEC_MISC*/
+  <0x16021000 0x800>,   /*VDEC_LD*/
+  <0x16021800 0x800>,   /*VDEC_TOP*/
+  <0x16022000 0x1000>,  /*VDEC_CM*/
+  <0x16023000 0x1000>,  /*VDEC_AD*/
+  <0x16024000 0x1000>,  /*VDEC_AV*/
+  <0x16025000 0x1000>,  /*VDEC_PP*/
+  <0x16026800 0x800>,   /*VP8_VD*/
+  <0x16027000 0x800>,   /*VP6_VD*/
+  <0x16027800 0x800>,   /*VP8_VL*/
+  <0x16028400 0x400>;   /*VP9_VD*/
+  interrupts = ;
+  mediatek,larb = <&larb1>;
+  iommus = <&iommu M4U_PORT_HW_VDEC_MC_EXT>,
+ <&iommu M4U_PORT_HW_VDEC_PP_EXT>,
+ <&iommu M4U_PORT_HW_VDEC_AVC_MV_EXT>,
+ <&iommu M4U_PORT_HW_VDEC_PRED_RD_EXT>,
+ <&iommu M4U_PORT_HW_VDEC_PRED_WR_EXT>,
+ <&iommu M4U_PORT_HW_VDEC_UFO_EXT>,
+ <&iommu M4U_PORT_HW_VDEC_VLD_EXT>,
+ <&iommu M4U_PORT_HW_VDEC_VLD2_EXT>;
+  mediatek,vpu = <&vpu>;
+  power-domains = <&scpsys MT8173_POWER_DOMAIN_VDEC>;
+  clocks = <&apmixedsys CLK_APMIXED_VCODECPLL>,
+ <&topckgen CLK_TOP_UNIVPLL_D2>,
+ <&topckgen CLK_TOP_CCI400_SEL>,
+ <&topckgen CLK_TOP_VDEC_SEL>,
+ <&topckgen CLK_TOP_VCODECPLL>,
+ <&apmixedsys CLK_APMIXED_VENCPLL>,
+ <&topckgen CLK_TOP_VENC_LT_SEL>,
+ <&topckgen CLK_TOP_VCODECPLL_370P5>;
+  clock-names = "vcodecpl

[PATCH v12, 08/19] media: mtk-vcodec: Use pure single core for MT8183

2021-12-01 Thread Yunfei Dong
Separates different architecture for hardware: pure_sin_core
and lat_sin_core. MT8183 is pure single core. Uses .hw_arch to
distinguish.

Reviewed-by: AngeloGioacchino Del Regno 

Signed-off-by: Yunfei Dong 
---
 .../platform/mtk-vcodec/mtk_vcodec_dec_stateful.c  |  1 +
 .../platform/mtk-vcodec/mtk_vcodec_dec_stateless.c |  2 ++
 drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h | 10 ++
 3 files changed, 13 insertions(+)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_stateful.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_stateful.c
index c7f9259ad094..04ca43c77e5f 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_stateful.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_stateful.c
@@ -626,4 +626,5 @@ const struct mtk_vcodec_dec_pdata mtk_vdec_8173_pdata = {
.worker = mtk_vdec_worker,
.flush_decoder = mtk_vdec_flush_decoder,
.is_subdev_supported = false,
+   .hw_arch = MTK_VDEC_PURE_SINGLE_CORE,
 };
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_stateless.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_stateless.c
index 2d285515b625..d98f49fbbc3b 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_stateless.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_stateless.c
@@ -358,6 +358,7 @@ const struct mtk_vcodec_dec_pdata mtk_vdec_8183_pdata = {
.worker = mtk_vdec_worker,
.flush_decoder = mtk_vdec_flush_decoder,
.is_subdev_supported = false,
+   .hw_arch = MTK_VDEC_PURE_SINGLE_CORE,
 };
 
 const struct mtk_vcodec_dec_pdata mtk_lat_sig_core_pdata = {
@@ -375,4 +376,5 @@ const struct mtk_vcodec_dec_pdata mtk_lat_sig_core_pdata = {
.worker = mtk_vdec_worker,
.flush_decoder = mtk_vdec_flush_decoder,
.is_subdev_supported = true,
+   .hw_arch = MTK_VDEC_LAT_SINGLE_CORE,
 };
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
index 2160f26263ef..79957222c979 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
@@ -324,6 +324,14 @@ enum mtk_chip {
MTK_MT8195,
 };
 
+/**
+ * struct mtk_vdec_hw_arch - Used to separate different hardware architecture
+ */
+enum mtk_vdec_hw_arch {
+   MTK_VDEC_PURE_SINGLE_CORE,
+   MTK_VDEC_LAT_SINGLE_CORE,
+};
+
 /**
  * struct mtk_vcodec_dec_pdata - compatible data for each IC
  * @init_vdec_params: init vdec params
@@ -342,6 +350,7 @@ enum mtk_chip {
  * @num_framesizes: count of video decoder frame sizes
  *
  * @chip: chip this decoder is compatible with
+ * @hw_arch: hardware arch is used to separate pure_sin_core and lat_sin_core
  *
  * @is_subdev_supported: whether support parent-node architecture(subdev)
  * @uses_stateless_api: whether the decoder uses the stateless API with 
requests
@@ -364,6 +373,7 @@ struct mtk_vcodec_dec_pdata {
const int num_framesizes;
 
enum mtk_chip chip;
+   enum mtk_vdec_hw_arch hw_arch;
 
bool is_subdev_supported;
bool uses_stateless_api;
-- 
2.25.1



[PATCH v12, 06/19] media: mtk-vcodec: Add to support multi hardware decode

2021-12-01 Thread Yunfei Dong
There are more than two hardwares for decoder: LAT0, LAT1 and CORE. In order to
manage these hardwares, register each hardware as independent platform device
for the larbs are different.

Each hardware module controls its own information which includes 
interrupt/power/
clocks/registers.

Calling of_platform_populate in parent device, and use subdev_bitmap to record
whether the hardwares are registered done.

Signed-off-by: Yunfei Dong 
---
 drivers/media/platform/mtk-vcodec/Makefile|   5 +-
 .../platform/mtk-vcodec/mtk_vcodec_dec_drv.c  | 111 +++
 .../platform/mtk-vcodec/mtk_vcodec_dec_hw.c   | 172 ++
 .../platform/mtk-vcodec/mtk_vcodec_dec_hw.h   |  51 ++
 .../mtk-vcodec/mtk_vcodec_dec_stateful.c  |   1 +
 .../mtk-vcodec/mtk_vcodec_dec_stateless.c |   2 +
 .../platform/mtk-vcodec/mtk_vcodec_drv.h  |  19 ++
 7 files changed, 329 insertions(+), 32 deletions(-)
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_hw.c
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_hw.h

diff --git a/drivers/media/platform/mtk-vcodec/Makefile 
b/drivers/media/platform/mtk-vcodec/Makefile
index ca8e9e7a9c4e..c61bfb179bcc 100644
--- a/drivers/media/platform/mtk-vcodec/Makefile
+++ b/drivers/media/platform/mtk-vcodec/Makefile
@@ -2,7 +2,8 @@
 
 obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec-dec.o \
   mtk-vcodec-enc.o \
-  mtk-vcodec-common.o
+  mtk-vcodec-common.o \
+  mtk-vcodec-dec-hw.o
 
 mtk-vcodec-dec-y := vdec/vdec_h264_if.o \
vdec/vdec_vp8_if.o \
@@ -16,6 +17,8 @@ mtk-vcodec-dec-y := vdec/vdec_h264_if.o \
mtk_vcodec_dec_stateless.o \
mtk_vcodec_dec_pm.o \
 
+mtk-vcodec-dec-hw-y := mtk_vcodec_dec_hw.o
+
 mtk-vcodec-enc-y := venc/venc_vp8_if.o \
venc/venc_h264_if.o \
mtk_vcodec_enc.o \
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
index b7a51e96d4ba..95fbe9be3f6d 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
@@ -18,19 +18,40 @@
 
 #include "mtk_vcodec_drv.h"
 #include "mtk_vcodec_dec.h"
+#include "mtk_vcodec_dec_hw.h"
 #include "mtk_vcodec_dec_pm.h"
 #include "mtk_vcodec_intr.h"
 #include "mtk_vcodec_util.h"
 #include "mtk_vcodec_fw.h"
 
-#define VDEC_HW_ACTIVE 0x10
-#define VDEC_IRQ_CFG   0x11
-#define VDEC_IRQ_CLR   0x10
-#define VDEC_IRQ_CFG_REG   0xa4
-
 module_param(mtk_v4l2_dbg_level, int, 0644);
 module_param(mtk_vcodec_dbg, bool, 0644);
 
+static int mtk_vcodec_subdev_device_check(struct mtk_vcodec_dev *vdec_dev)
+{
+   struct platform_device *pdev = vdec_dev->plat_dev;
+   struct device_node *subdev_node;
+   enum mtk_vdec_hw_id hw_idx;
+   const struct of_device_id *of_id;
+   int i;
+
+   for (i = 0; i < ARRAY_SIZE(mtk_vdec_hw_match); i++) {
+   of_id = &mtk_vdec_hw_match[i];
+   subdev_node = of_find_compatible_node(NULL, NULL,
+   of_id->compatible);
+   if (!subdev_node)
+   continue;
+
+   hw_idx = (enum mtk_vdec_hw_id)(uintptr_t)of_id->data;
+   if (!test_bit(hw_idx, vdec_dev->subdev_bitmap)) {
+   dev_err(&pdev->dev, "Vdec %d is not ready", hw_idx);
+   return -EAGAIN;
+   }
+   }
+
+   return 0;
+}
+
 static irqreturn_t mtk_vcodec_dec_irq_handler(int irq, void *priv)
 {
struct mtk_vcodec_dev *dev = priv;
@@ -95,6 +116,42 @@ static int mtk_vcodec_get_reg_bases(struct mtk_vcodec_dev 
*dev)
return 0;
 }
 
+static int mtk_vcodec_init_dec_resources(struct mtk_vcodec_dev *dev)
+{
+   struct platform_device *pdev = dev->plat_dev;
+   int ret;
+
+   ret = mtk_vcodec_get_reg_bases(dev);
+   if (ret)
+   return ret;
+
+   if (dev->vdec_pdata->is_subdev_supported)
+   return 0;
+
+   dev->dec_irq = platform_get_irq(pdev, 0);
+   if (dev->dec_irq < 0) {
+   dev_err(&pdev->dev, "failed to get irq number");
+   return dev->dec_irq;
+   }
+
+   irq_set_status_flags(dev->dec_irq, IRQ_NOAUTOEN);
+   ret = devm_request_irq(&pdev->dev, dev->dec_irq,
+   mtk_vcodec_dec_irq_handler, 0, pdev->name, dev);
+   if (ret) {
+   dev_err(&pdev->dev, "failed to install dev->dec_irq %d (%d)",
+   dev->dec_irq, ret);
+   return ret;
+   }
+
+   ret = mtk_vcodec_init_dec_pm(pdev, &dev->pm);
+   if (ret < 0) {
+   dev_err(&pdev->dev, "failed to get mt vcodec clock source");
+   return ret;
+   }
+
+   return 0;
+}
+
 static int fops_vcodec_open(struct file *file)
 {
struct mtk_v

[PATCH v12, 03/19] media: mtk-vcodec: Refactor vcodec pm interface

2021-12-01 Thread Yunfei Dong
Using the needed params for pm init/release function and remove unused
param mtkdev in 'struct mtk_vcodec_pm'.

Reviewed-by: Tzung-Bi Shih 
Reviewed-by: AngeloGioacchino Del Regno 

Reviewed-by: Steve Cho 
Signed-off-by: Yunfei Dong 
---
 .../platform/mtk-vcodec/mtk_vcodec_dec_drv.c  |  6 ++---
 .../platform/mtk-vcodec/mtk_vcodec_dec_pm.c   | 22 ---
 .../platform/mtk-vcodec/mtk_vcodec_dec_pm.h   |  5 +++--
 .../platform/mtk-vcodec/mtk_vcodec_drv.h  |  1 -
 .../platform/mtk-vcodec/mtk_vcodec_enc_pm.c   |  1 -
 5 files changed, 15 insertions(+), 20 deletions(-)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
index 055d50e52720..3ac4c3935e4e 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
@@ -249,7 +249,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
if (IS_ERR(dev->fw_handler))
return PTR_ERR(dev->fw_handler);
 
-   ret = mtk_vcodec_init_dec_pm(dev);
+   ret = mtk_vcodec_init_dec_pm(dev->plat_dev, &dev->pm);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to get mt vcodec clock source");
goto err_dec_pm;
@@ -378,7 +378,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
 err_dec_alloc:
v4l2_device_unregister(&dev->v4l2_dev);
 err_res:
-   mtk_vcodec_release_dec_pm(dev);
+   mtk_vcodec_release_dec_pm(&dev->pm);
 err_dec_pm:
mtk_vcodec_fw_release(dev->fw_handler);
return ret;
@@ -418,7 +418,7 @@ static int mtk_vcodec_dec_remove(struct platform_device 
*pdev)
video_unregister_device(dev->vfd_dec);
 
v4l2_device_unregister(&dev->v4l2_dev);
-   mtk_vcodec_release_dec_pm(dev);
+   mtk_vcodec_release_dec_pm(&dev->pm);
mtk_vcodec_fw_release(dev->fw_handler);
return 0;
 }
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
index 6038db96f71c..20bd157a855c 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
@@ -13,18 +13,15 @@
 #include "mtk_vcodec_dec_pm.h"
 #include "mtk_vcodec_util.h"
 
-int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev)
+int mtk_vcodec_init_dec_pm(struct platform_device *pdev,
+   struct mtk_vcodec_pm *pm)
 {
struct device_node *node;
-   struct platform_device *pdev;
-   struct mtk_vcodec_pm *pm;
+   struct platform_device *larb_pdev;
struct mtk_vcodec_clk *dec_clk;
struct mtk_vcodec_clk_info *clk_info;
int i = 0, ret = 0;
 
-   pdev = mtkdev->plat_dev;
-   pm = &mtkdev->pm;
-   pm->mtkdev = mtkdev;
dec_clk = &pm->vdec_clk;
node = of_parse_phandle(pdev->dev.of_node, "mediatek,larb", 0);
if (!node) {
@@ -32,13 +29,12 @@ int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev)
return -1;
}
 
-   pdev = of_find_device_by_node(node);
+   larb_pdev = of_find_device_by_node(node);
of_node_put(node);
-   if (WARN_ON(!pdev)) {
+   if (WARN_ON(!larb_pdev)) {
return -1;
}
-   pm->larbvdec = &pdev->dev;
-   pdev = mtkdev->plat_dev;
+   pm->larbvdec = &larb_pdev->dev;
pm->dev = &pdev->dev;
 
dec_clk->clk_num =
@@ -82,10 +78,10 @@ int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev)
return ret;
 }
 
-void mtk_vcodec_release_dec_pm(struct mtk_vcodec_dev *dev)
+void mtk_vcodec_release_dec_pm(struct mtk_vcodec_pm *pm)
 {
-   pm_runtime_disable(dev->pm.dev);
-   put_device(dev->pm.larbvdec);
+   pm_runtime_disable(pm->dev);
+   put_device(pm->larbvdec);
 }
 
 int mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm)
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
index 280aeaefdb65..a3df6aef6cb9 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
@@ -9,8 +9,9 @@
 
 #include "mtk_vcodec_drv.h"
 
-int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *dev);
-void mtk_vcodec_release_dec_pm(struct mtk_vcodec_dev *dev);
+int mtk_vcodec_init_dec_pm(struct platform_device *pdev,
+   struct mtk_vcodec_pm *pm);
+void mtk_vcodec_release_dec_pm(struct mtk_vcodec_pm *pm);
 
 int mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm);
 void mtk_vcodec_dec_pw_off(struct mtk_vcodec_pm *pm);
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
index 1d2370608d0d..0fa9d85114b9 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
@@ -195,7 +195,6 @@ struct mtk_vcodec_pm {
struct mtk_vcodec_clk   venc_clk;
struct device   *larbvenc;
struc

[PATCH v12, 05/19] media: mtk-vcodec: Support MT8192

2021-12-01 Thread Yunfei Dong
From: Yunfei Dong 

Adds MT8192's compatible "mediatek,mt8192-vcodec-dec".
Adds MT8192's device private data mtk_lat_sig_core_pdata.

Reviewed-by: AngeloGioacchino Del Regno 

Signed-off-by: Yunfei Dong 
---
 .../media/platform/mtk-vcodec/mtk_vcodec_dec.h   |  1 +
 .../platform/mtk-vcodec/mtk_vcodec_dec_drv.c |  4 
 .../mtk-vcodec/mtk_vcodec_dec_stateless.c| 16 
 3 files changed, 21 insertions(+)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h
index 46783516b84a..e30806c1faea 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h
@@ -67,6 +67,7 @@ extern const struct v4l2_m2m_ops mtk_vdec_m2m_ops;
 extern const struct media_device_ops mtk_vcodec_media_ops;
 extern const struct mtk_vcodec_dec_pdata mtk_vdec_8173_pdata;
 extern const struct mtk_vcodec_dec_pdata mtk_vdec_8183_pdata;
+extern const struct mtk_vcodec_dec_pdata mtk_lat_sig_core_pdata;
 
 
 /*
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
index 3ac4c3935e4e..b7a51e96d4ba 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
@@ -393,6 +393,10 @@ static const struct of_device_id mtk_vcodec_match[] = {
.compatible = "mediatek,mt8183-vcodec-dec",
.data = &mtk_vdec_8183_pdata,
},
+   {
+   .compatible = "mediatek,mt8192-vcodec-dec",
+   .data = &mtk_lat_sig_core_pdata,
+   },
{},
 };
 
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_stateless.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_stateless.c
index 8f4a1f0a0769..26e4d6f4ec04 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_stateless.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_stateless.c
@@ -358,3 +358,19 @@ const struct mtk_vcodec_dec_pdata mtk_vdec_8183_pdata = {
.worker = mtk_vdec_worker,
.flush_decoder = mtk_vdec_flush_decoder,
 };
+
+const struct mtk_vcodec_dec_pdata mtk_lat_sig_core_pdata = {
+   .chip = MTK_MT8192,
+   .init_vdec_params = mtk_init_vdec_params,
+   .ctrls_setup = mtk_vcodec_dec_ctrls_setup,
+   .vdec_vb2_ops = &mtk_vdec_request_vb2_ops,
+   .vdec_formats = mtk_video_formats,
+   .num_formats = NUM_FORMATS,
+   .default_out_fmt = &mtk_video_formats[DEFAULT_OUT_FMT_IDX],
+   .default_cap_fmt = &mtk_video_formats[DEFAULT_CAP_FMT_IDX],
+   .vdec_framesizes = mtk_vdec_framesizes,
+   .num_framesizes = NUM_SUPPORTED_FRAMESIZE,
+   .uses_stateless_api = true,
+   .worker = mtk_vdec_worker,
+   .flush_decoder = mtk_vdec_flush_decoder,
+};
-- 
2.25.1



[PATCH v12, 04/19] media: mtk-vcodec: export decoder pm functions

2021-12-01 Thread Yunfei Dong
When mtk vcodec decoder is build as a module, we need to export
mtk-vcodec-dec pm functions to make them visible by the other components.

Reviewed-by: AngeloGioacchino Del Regno 

Reviewed-by: Benjamin Gaignard 
Signed-off-by: Yunfei Dong 
---
 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
index 20bd157a855c..221cf60e9fbf 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
@@ -77,12 +77,14 @@ int mtk_vcodec_init_dec_pm(struct platform_device *pdev,
put_device(pm->larbvdec);
return ret;
 }
+EXPORT_SYMBOL_GPL(mtk_vcodec_init_dec_pm);
 
 void mtk_vcodec_release_dec_pm(struct mtk_vcodec_pm *pm)
 {
pm_runtime_disable(pm->dev);
put_device(pm->larbvdec);
 }
+EXPORT_SYMBOL_GPL(mtk_vcodec_release_dec_pm);
 
 int mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm)
 {
@@ -94,6 +96,7 @@ int mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm)
 
return ret;
 }
+EXPORT_SYMBOL_GPL(mtk_vcodec_dec_pw_on);
 
 void mtk_vcodec_dec_pw_off(struct mtk_vcodec_pm *pm)
 {
@@ -103,6 +106,7 @@ void mtk_vcodec_dec_pw_off(struct mtk_vcodec_pm *pm)
if (ret)
mtk_v4l2_err("pm_runtime_put_sync fail %d", ret);
 }
+EXPORT_SYMBOL_GPL(mtk_vcodec_dec_pw_off);
 
 void mtk_vcodec_dec_clock_on(struct mtk_vcodec_pm *pm)
 {
@@ -129,6 +133,7 @@ void mtk_vcodec_dec_clock_on(struct mtk_vcodec_pm *pm)
for (i -= 1; i >= 0; i--)
clk_disable_unprepare(dec_clk->clk_info[i].vcodec_clk);
 }
+EXPORT_SYMBOL_GPL(mtk_vcodec_dec_clock_on);
 
 void mtk_vcodec_dec_clock_off(struct mtk_vcodec_pm *pm)
 {
@@ -139,3 +144,4 @@ void mtk_vcodec_dec_clock_off(struct mtk_vcodec_pm *pm)
for (i = dec_clk->clk_num - 1; i >= 0; i--)
clk_disable_unprepare(dec_clk->clk_info[i].vcodec_clk);
 }
+EXPORT_SYMBOL_GPL(mtk_vcodec_dec_clock_off);
-- 
2.25.1



[PATCH v12, 00/19] Support multi hardware decode using of_platform_populate

2021-12-01 Thread Yunfei Dong
This series adds support for multi hardware decode into mtk-vcodec, by first 
adding use
of_platform_populate to manage each hardware information: interrupt, clock, 
register
bases and power. Secondly add core work queue to deal with core hardware 
message,
at the same time, add msg queue for different hardware share messages. Lastly, 
the
architecture of different specs are not the same, using specs type to separate 
them.

This series has been tested with both MT8183 and MT8173. Decoding was working 
for both chips.

Patches 1~3 rewrite get register bases and power on/off interface.
Patches 4 export decoder pm interfaces.
Patches 5 add to support 8192.
Patch 6 support multi hardware.
Patch 7 separate video encoder and decoder document
Patch 8-17 add interfaces to support core hardware.
Patch 18-19 remove mtk_vcodec_release_dec/enc_pm interfaces.
---
changes compared with v11:
- fix comments from AngeloGioacchino for patch 09~11/19.
- fix comments from steve for patch 03/19.

changes compared with v10:
- fix comments from tzung-bi for patch 06/19.
- add more detail information for hardware block diagram 15/19

changes compared with v9:
- need not to build ko, just export pm interfaces for patch 04/19.
- fix comments for patch 06/19

changes compared with v8:
- add new patch 18~19 to remove mtk_vcodec_release_de/enc_pm interfaces.
- fix spelling mistakes for patch 17/19
- fix yaml comments for patch 15/19

Changes compared with v7:
- add new patch 4 to build decoder pm file as module
- add new patch 5 to support 8192
- fix comments for patch 6/17
- change some logic for using work queue instead of create thread for core 
hardware decode for patch 10/17
- using work queue for hardware decode instead of create thread for patch 13/17
- add returen value for patch 14/17
- fix yaml check fail 15/17

Changes compared with v6:
- Use of_platform_populate to manage multi hardware, not component framework 
for patch 4/15
- Re-write dtsi document for hardware architecture changed for patch 13/15 -The 
dtsi will write like below in patch 13/15:
vcodec_dec: vcodec_dec@1600 {
compatible = "mediatek,mt8192-vcodec-dec";
#address-cells = <2>;
#size-cells = <2>;
ranges;
reg = <0 0x1600 0 0x1000>;  /* VDEC_SYS */
mediatek,scp = <&scp>;
iommus = <&iommu0 M4U_PORT_L4_VDEC_MC_EXT>;
dma-ranges = <0x1 0x0 0x0 0x4000 0x0 0xfff0>;
vcodec_lat {
compatible = "mediatek,mtk-vcodec-lat";
reg = <0 0x1601 0 0x800>;   /* VDEC_MISC */
reg-name = "reg-misc";
interrupts = ;
iommus = <&iommu0 M4U_PORT_L5_VDEC_LAT0_VLD_EXT>,
 <&iommu0 M4U_PORT_L5_VDEC_LAT0_VLD2_EXT>,
 <&iommu0 M4U_PORT_L5_VDEC_LAT0_AVC_MV_EXT>,
 <&iommu0 M4U_PORT_L5_VDEC_LAT0_PRED_RD_EXT>,
 <&iommu0 M4U_PORT_L5_VDEC_LAT0_TILE_EXT>,
 <&iommu0 M4U_PORT_L5_VDEC_LAT0_WDMA_EXT>,
 <&iommu0 M4U_PORT_L5_VDEC_LAT0_RG_CTRL_DMA_EXT>,
 <&iommu0 M4U_PORT_L5_VDEC_UFO_ENC_EXT>;
clocks = <&topckgen CLK_TOP_VDEC_SEL>,
 <&vdecsys_soc CLK_VDEC_SOC_VDEC>,
 <&vdecsys_soc CLK_VDEC_SOC_LAT>,
 <&vdecsys_soc CLK_VDEC_SOC_LARB1>,
 <&topckgen CLK_TOP_MAINPLL_D4>;
clock-names = "vdec-sel", "vdec-soc-vdec", "vdec-soc-lat",
  "vdec-vdec", "vdec-top";
assigned-clocks = <&topckgen CLK_TOP_VDEC_SEL>;
assigned-clock-parents = <&topckgen CLK_TOP_MAINPLL_D4>;
power-domains = <&spm MT8192_POWER_DOMAIN_VDEC>;
};

vcodec_core {
compatible = "mediatek,mtk-vcodec-core";
reg = <0 0x16025000 0 0x1000>;  /* VDEC_CORE_MISC */
reg-names = "reg-misc";
interrupts = ;
iommus = <&iommu0 M4U_PORT_L4_VDEC_MC_EXT>,
 <&iommu0 M4U_PORT_L4_VDEC_UFO_EXT>,
 <&iommu0 M4U_PORT_L4_VDEC_PP_EXT>,
 <&iommu0 M4U_PORT_L4_VDEC_PRED_RD_EXT>,
 <&iommu0 M4U_PORT_L4_VDEC_PRED_WR_EXT>,
 <&iommu0 M4U_PORT_L4_VDEC_PPWRAP_EXT>,
 <&iommu0 M4U_PORT_L4_VDEC_TILE_EXT>,
 <&iommu0 M4U_PORT_L4_VDEC_VLD_EXT>,
 <&iommu0 M4U_PORT_L4_VDEC_VLD2_EXT>,
 <&iommu0 M4U_PORT_L4_VDEC_AVC_MV_EXT>,
 <&iommu0 M4U_PORT_L4_VDEC_RG_CTRL_DMA_EXT>;
clocks = <&topckgen CLK_TOP_VDEC_SEL>,
 <&vdecsys CLK_VDEC_VDEC>,
 <&vdecsys CLK_VDEC_LAT>,
 <&vdecsys CLK_VDEC_LARB1>,
 <&topckgen CLK_TOP_MAINPLL_D4>;
clock-names = "vdec-sel", "vdec-soc-vdec", "vdec-soc-lat",
  "vdec-vdec", "vdec-top";
assigned-clocks = <&topckgen CLK_TOP_VDEC_SEL>;
assigned-clock-parents = <&topckgen CLK_TOP_MAINPLL_D4>;
   

[PATCH v12, 01/19] media: mtk-vcodec: Get numbers of register bases from DT

2021-12-01 Thread Yunfei Dong
Different platforms may have different numbers of register bases. Gets the
numbers of register bases from dts (sizeof(u32) * 4 bytes for each).

Reviewed-by: Tzung-Bi Shih
Signed-off-by: Yunfei Dong 
---
 .../platform/mtk-vcodec/mtk_vcodec_dec_drv.c  | 37 ++-
 1 file changed, 28 insertions(+), 9 deletions(-)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
index e6e6a8203eeb..59caf2163349 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
@@ -78,6 +78,30 @@ static irqreturn_t mtk_vcodec_dec_irq_handler(int irq, void 
*priv)
return IRQ_HANDLED;
 }
 
+static int mtk_vcodec_get_reg_bases(struct mtk_vcodec_dev *dev)
+{
+   struct platform_device *pdev = dev->plat_dev;
+   int reg_num, i;
+
+   /* Sizeof(u32) * 4 bytes for each register base. */
+   reg_num = of_property_count_elems_of_size(pdev->dev.of_node, "reg",
+   sizeof(u32) * 4);
+   if (reg_num <= 0 || reg_num > NUM_MAX_VDEC_REG_BASE) {
+   dev_err(&pdev->dev, "Invalid register property size: %d\n", 
reg_num);
+   return -EINVAL;
+   }
+
+   for (i = 0; i < reg_num; i++) {
+   dev->reg_base[i] = devm_platform_ioremap_resource(pdev, i);
+   if (IS_ERR(dev->reg_base[i]))
+   return PTR_ERR(dev->reg_base[i]);
+
+   mtk_v4l2_debug(2, "reg[%d] base=%p", i, dev->reg_base[i]);
+   }
+
+   return 0;
+}
+
 static int fops_vcodec_open(struct file *file)
 {
struct mtk_vcodec_dev *dev = video_drvdata(file);
@@ -206,7 +230,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
struct resource *res;
phandle rproc_phandle;
enum mtk_vcodec_fw_type fw_type;
-   int i, ret;
+   int ret;
 
dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
if (!dev)
@@ -238,14 +262,9 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
goto err_dec_pm;
}
 
-   for (i = 0; i < NUM_MAX_VDEC_REG_BASE; i++) {
-   dev->reg_base[i] = devm_platform_ioremap_resource(pdev, i);
-   if (IS_ERR((__force void *)dev->reg_base[i])) {
-   ret = PTR_ERR((__force void *)dev->reg_base[i]);
-   goto err_res;
-   }
-   mtk_v4l2_debug(2, "reg[%d] base=%p", i, dev->reg_base[i]);
-   }
+   ret = mtk_vcodec_get_reg_bases(dev);
+   if (ret)
+   goto err_res;
 
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (res == NULL) {
-- 
2.25.1



Re: [PATCH v11, 01/19] media: mtk-vcodec: Get numbers of register bases from DT

2021-12-01 Thread yunfei.d...@mediatek.com
Hi Steve,
Thanks for your suggestion.On Wed, 2021-12-01 at 15:36 -0800, Steve Cho
wrote:
> LGTM with few nits. 
> 
> Thanks,Steve
> 
> On Sun, Nov 28, 2021 at 7:44 PM Yunfei Dong  > wrote:
> > Different platform may has different numbers of register bases.
> > Gets the
> > 
> > numbers of register bases from DT (sizeof(u32) * 4 bytes for each)
> Few nits.
> s/platform/platforms/
> s/has/have/
> 
> Fix, DT is dts.
> Btw, what is DT?
> >  
> > 
> > Reviewed-by: Tzung-Bi Shih
> > 
> > Signed-off-by: Yunfei Dong 
> > 
> > ---
> > 
> >  .../platform/mtk-vcodec/mtk_vcodec_dec_drv.c  | 37 ++-
> > 
> > 
> >  1 file changed, 28 insertions(+), 9 deletions(-)
> > 
> > 
> > 
> > diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c 
> > b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
> > 
> > index e6e6a8203eeb..59caf2163349 100644
> > 
> > --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
> > 
> > +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
> > 
> > @@ -78,6 +78,30 @@ static irqreturn_t
> > mtk_vcodec_dec_irq_handler(int irq, void *priv)
> > 
> > return IRQ_HANDLED;
> > 
> >  }
> > 
> > 
> > 
> > +static int mtk_vcodec_get_reg_bases(struct mtk_vcodec_dev *dev)
> > 
> > +{
> I see that dev is already checked before entering into this function,
> but null check for dev would still be nice. 
>  
Dev is never null in this function, whether it looks not very
reasonable?
Best Regards,Yunfei Dong
> > +   struct platform_device *pdev = dev->plat_dev;
> > 
> > +   int reg_num, i;
> > 
> > +
> > 
> > +   /* Sizeof(u32) * 4 bytes for each register base. */
> > 
> > +   reg_num = of_property_count_elems_of_size(pdev-
> > >dev.of_node, "reg",
> > 
> > +   sizeof(u32) * 4);
> > 
> > +   if (reg_num <= 0 || reg_num > NUM_MAX_VDEC_REG_BASE) {
> > 
> > +   dev_err(&pdev->dev, "Invalid register property
> > size: %d\n", reg_num);
> > 
> > +   return -EINVAL;
> > 
> > +   }
> > 
> > +
> > 
> > +   for (i = 0; i < reg_num; i++) {
> > 
> > +   dev->reg_base[i] =
> > devm_platform_ioremap_resource(pdev, i);
> > 
> > +   if (IS_ERR(dev->reg_base[i]))
> > 
> > +   return PTR_ERR(dev->reg_base[i]);
> > 
> > +
> > 
> > +   mtk_v4l2_debug(2, "reg[%d] base=%p", i, dev-
> > >reg_base[i]);
> > 
> > +   }
> > 
> > +
> > 
> > +   return 0;
> > 
> > +}
> > 
> > +
> > 
> >  static int fops_vcodec_open(struct file *file)
> > 
> >  {
> > 
> > struct mtk_vcodec_dev *dev = video_drvdata(file);
> > 
> > @@ -206,7 +230,7 @@ static int mtk_vcodec_probe(struct
> > platform_device *pdev)
> > 
> > struct resource *res;
> > 
> > phandle rproc_phandle;
> > 
> > enum mtk_vcodec_fw_type fw_type;
> > 
> > -   int i, ret;
> > 
> > +   int ret;
> > 
> > 
> > 
> > dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
> > 
> > if (!dev)
> > 
> > @@ -238,14 +262,9 @@ static int mtk_vcodec_probe(struct
> > platform_device *pdev)
> > 
> > goto err_dec_pm;
> > 
> > }
> > 
> > 
> > 
> > -   for (i = 0; i < NUM_MAX_VDEC_REG_BASE; i++) {
> > 
> > -   dev->reg_base[i] =
> > devm_platform_ioremap_resource(pdev, i);
> > 
> > -   if (IS_ERR((__force void *)dev->reg_base[i])) {
> > 
> > -   ret = PTR_ERR((__force void *)dev-
> > >reg_base[i]);
> > 
> > -   goto err_res;
> > 
> > -   }
> > 
> > -   mtk_v4l2_debug(2, "reg[%d] base=%p", i, dev-
> > >reg_base[i]);
> > 
> > -   }
> > 
> > +   ret = mtk_vcodec_get_reg_bases(dev);
> > 
> > +   if (ret)
> > 
> > +   goto err_res;
> > 
> > 
> > 
> > res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> > 
> > if (res == NULL) {
> > 


Re: [PATCH v11, 01/19] media: mtk-vcodec: Get numbers of register bases from DT

2021-12-01 Thread yunfei.d...@mediatek.com
Hi Benjamin,

Thanks for your suggestion.
On Tue, 2021-11-30 at 14:20 +0100, Benjamin Gaignard wrote:
> Le 29/11/2021 à 04:41, Yunfei Dong a écrit :
> > Different platform may has different numbers of register bases.
> > Gets the
> > numbers of register bases from DT (sizeof(u32) * 4 bytes for each).
> > 
> > Reviewed-by: Tzung-Bi Shih
> > Signed-off-by: Yunfei Dong 
> > ---
> >   .../platform/mtk-vcodec/mtk_vcodec_dec_drv.c  | 37
> > ++-
> >   1 file changed, 28 insertions(+), 9 deletions(-)
> > 
> > diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c 
> > b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
> > index e6e6a8203eeb..59caf2163349 100644
> > --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
> > +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
> > @@ -78,6 +78,30 @@ static irqreturn_t
> > mtk_vcodec_dec_irq_handler(int irq, void *priv)
> > return IRQ_HANDLED;
> >   }
> >   
> > +static int mtk_vcodec_get_reg_bases(struct mtk_vcodec_dev *dev)
> > +{
> > +   struct platform_device *pdev = dev->plat_dev;
> > +   int reg_num, i;
> > +
> > +   /* Sizeof(u32) * 4 bytes for each register base. */
> > +   reg_num = of_property_count_elems_of_size(pdev->dev.of_node,
> > "reg",
> > +   sizeof(u32) * 4);
> 
> It looks strange for me to have a "reg" size equal to sizeof(u32) *
> 4. Usually
> we more see reg size = sizeof(u32).
> 
For the definition of reg in dtsi is reg = <0 0x1600 0 0x800>,
Need to using sizeof(u32) * 4, not sizeof(u32).
> > +   if (reg_num <= 0 || reg_num > NUM_MAX_VDEC_REG_BASE) {
> 
> If reg_num = NUM_MAX_VDEC_REG_BASE you will iterate out of bounds of
> dev->reg_base array.
> That never happens because dev->reg_base size equal
> NUM_MAX_VCODEC_REG_BASE.
> The question is what is the real needed size for dev->reg_base array
> ? NUM_MAX_VDEC_REG_BASE or
> NUM_MAX_VCODEC_REG_BASE ?
> 
> NUM_MAX_VDEC_REG_BASE is used for video decoder, and
> NUM_MAX_VCODEC_REG_BASE is used for encoder.

The max register number of video decoder is NUM_MAX_VDEC_REG_BASE, and
the ranges is 0 ~ NUM_MAX_VDEC_REG_BASE - 1.

> Regards,
> Benjamin
> 
Best Regards,
Yunfei Dong
> > +   dev_err(&pdev->dev, "Invalid register property size:
> > %d\n", reg_num);
> > +   return -EINVAL;
> > +   }
> > +
> > +   for (i = 0; i < reg_num; i++) {
> > +   dev->reg_base[i] = devm_platform_ioremap_resource(pdev,
> > i);
> > +   if (IS_ERR(dev->reg_base[i]))
> > +   return PTR_ERR(dev->reg_base[i]);
> > +
> > +   mtk_v4l2_debug(2, "reg[%d] base=%p", i, dev-
> > >reg_base[i]);
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> >   static int fops_vcodec_open(struct file *file)
> >   {
> > struct mtk_vcodec_dev *dev = video_drvdata(file);
> > @@ -206,7 +230,7 @@ static int mtk_vcodec_probe(struct
> > platform_device *pdev)
> > struct resource *res;
> > phandle rproc_phandle;
> > enum mtk_vcodec_fw_type fw_type;
> > -   int i, ret;
> > +   int ret;
> >   
> > dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
> > if (!dev)
> > @@ -238,14 +262,9 @@ static int mtk_vcodec_probe(struct
> > platform_device *pdev)
> > goto err_dec_pm;
> > }
> >   
> > -   for (i = 0; i < NUM_MAX_VDEC_REG_BASE; i++) {
> > -   dev->reg_base[i] = devm_platform_ioremap_resource(pdev,
> > i);
> > -   if (IS_ERR((__force void *)dev->reg_base[i])) {
> > -   ret = PTR_ERR((__force void *)dev-
> > >reg_base[i]);
> > -   goto err_res;
> > -   }
> > -   mtk_v4l2_debug(2, "reg[%d] base=%p", i, dev-
> > >reg_base[i]);
> > -   }
> > +   ret = mtk_vcodec_get_reg_bases(dev);
> > +   if (ret)
> > +   goto err_res;
> >   
> > res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> > if (res == NULL) {


Re: [PATCH v4 1/6] drm: move the buddy allocator from i915 into common drm

2021-12-01 Thread kernel test robot
Hi Arunpravin,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on drm-intel/for-linux-next]
[also build test ERROR on v5.16-rc3]
[cannot apply to drm/drm-next drm-tip/drm-tip next-20211201]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:
https://github.com/0day-ci/linux/commits/Arunpravin/drm-move-the-buddy-allocator-from-i915-into-common-drm/20211202-004327
base:   git://anongit.freedesktop.org/drm-intel for-linux-next
config: x86_64-randconfig-a012-20211130 
(https://download.01.org/0day-ci/archive/20211202/202112020812.si0y9psy-...@intel.com/config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 
4b553297ef3ee4dc2119d5429adf3072e90fac38)
reproduce (this is a W=1 build):
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# 
https://github.com/0day-ci/linux/commit/afbc900c0399e8c6220abd729932e877e81f37c8
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review 
Arunpravin/drm-move-the-buddy-allocator-from-i915-into-common-drm/20211202-004327
git checkout afbc900c0399e8c6220abd729932e877e81f37c8
# save the config file to linux build tree
mkdir build_dir
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 
O=build_dir ARCH=x86_64 SHELL=/bin/bash drivers/gpu/

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

All errors (new ones prefixed by >>):

   In file included from drivers/gpu/drm/i915/intel_memory_region.c:242:
>> drivers/gpu/drm/i915/selftests/intel_memory_region.c:23:10: fatal error: 
>> 'i915_buddy.h' file not found
   #include "i915_buddy.h"
^~
   1 error generated.


vim +23 drivers/gpu/drm/i915/selftests/intel_memory_region.c

232a6ebae419193 Matthew Auld 2019-10-08  14  
340be48f2c5a3c0 Matthew Auld 2019-10-25  15  #include 
"gem/i915_gem_context.h"
b908be543e44414 Matthew Auld 2019-10-25  16  #include "gem/i915_gem_lmem.h"
232a6ebae419193 Matthew Auld 2019-10-08  17  #include 
"gem/i915_gem_region.h"
340be48f2c5a3c0 Matthew Auld 2019-10-25  18  #include 
"gem/selftests/igt_gem_utils.h"
232a6ebae419193 Matthew Auld 2019-10-08  19  #include 
"gem/selftests/mock_context.h"
99919be74aa3753 Thomas Hellström 2021-06-17  20  #include "gt/intel_engine_pm.h"
6804da20bb549e3 Chris Wilson 2019-10-27  21  #include 
"gt/intel_engine_user.h"
b908be543e44414 Matthew Auld 2019-10-25  22  #include "gt/intel_gt.h"
d53ec322dc7de32 Matthew Auld 2021-06-16 @23  #include "i915_buddy.h"
99919be74aa3753 Thomas Hellström 2021-06-17  24  #include "gt/intel_migrate.h"
ba12993c5228015 Matthew Auld 2020-01-29  25  #include "i915_memcpy.h"
d53ec322dc7de32 Matthew Auld 2021-06-16  26  #include 
"i915_ttm_buddy_manager.h"
01377a0d7e6648b Abdiel Janulgue  2019-10-25  27  #include 
"selftests/igt_flush_test.h"
2f0b97ca0211863 Matthew Auld 2019-10-08  28  #include 
"selftests/i915_random.h"
232a6ebae419193 Matthew Auld 2019-10-08  29  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-...@lists.01.org


linux-next: manual merge of the drm-intel-gt tree with the drm-intel tree

2021-12-01 Thread Stephen Rothwell
Hi all,

Today's linux-next merge of the drm-intel-gt tree got a conflict in:

  drivers/gpu/drm/i915/display/intel_fbc.c

between commit:

  d06188234427 ("drm/i915/fbc: s/dev_priv/i915/")

from the drm-intel tree and commit:

  cca084692394 ("drm/i915: Use per device iommu check")

from the drm-intel-gt tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

-- 
Cheers,
Stephen Rothwell

diff --cc drivers/gpu/drm/i915/display/intel_fbc.c
index d0c34bc3af6c,c40444206425..
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@@ -1674,12 -1536,12 +1674,12 @@@ static int intel_sanitize_fbc_option(st
return 0;
  }
  
 -static bool need_fbc_vtd_wa(struct drm_i915_private *dev_priv)
 +static bool need_fbc_vtd_wa(struct drm_i915_private *i915)
  {
/* WaFbcTurnOffFbcWhenHyperVisorIsUsed:skl,bxt */
-   if (intel_vtd_active() &&
 -  if (intel_vtd_active(dev_priv) &&
 -  (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))) {
 -  drm_info(&dev_priv->drm,
++  if (intel_vtd_active(i915) &&
 +  (IS_SKYLAKE(i915) || IS_BROXTON(i915))) {
 +  drm_info(&i915->drm,
 "Disabling framebuffer compression (FBC) to prevent 
screen flicker with VT-d enabled\n");
return true;
}


pgp2XbAlpaq8A.pgp
Description: OpenPGP digital signature


[PATCH] drm/i915: replace X86_FEATURE_PAT with pat_enabled()

2021-12-01 Thread Lucas De Marchi
PAT can be disabled on boot with "nopat" in the command line. Replace
one x86-ism with another, which is slightly more correct to prepare for
supporting other architectures.

Cc: Matt Roper 
Signed-off-by: Lucas De Marchi 
---
 drivers/gpu/drm/i915/gem/i915_gem_mman.c  | 8 
 drivers/gpu/drm/i915/gem/i915_gem_pages.c | 3 +--
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c 
b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
index 65fc6ff5f59d..c0c509e5c0ae 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
@@ -72,7 +72,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
if (args->flags & ~(I915_MMAP_WC))
return -EINVAL;
 
-   if (args->flags & I915_MMAP_WC && !boot_cpu_has(X86_FEATURE_PAT))
+   if (args->flags & I915_MMAP_WC && !pat_enabled())
return -ENODEV;
 
obj = i915_gem_object_lookup(file, args->handle);
@@ -736,7 +736,7 @@ i915_gem_dumb_mmap_offset(struct drm_file *file,
 
if (HAS_LMEM(to_i915(dev)))
mmap_type = I915_MMAP_TYPE_FIXED;
-   else if (boot_cpu_has(X86_FEATURE_PAT))
+   else if (pat_enabled())
mmap_type = I915_MMAP_TYPE_WC;
else if (!i915_ggtt_has_aperture(&to_i915(dev)->ggtt))
return -ENODEV;
@@ -792,7 +792,7 @@ i915_gem_mmap_offset_ioctl(struct drm_device *dev, void 
*data,
break;
 
case I915_MMAP_OFFSET_WC:
-   if (!boot_cpu_has(X86_FEATURE_PAT))
+   if (!pat_enabled())
return -ENODEV;
type = I915_MMAP_TYPE_WC;
break;
@@ -802,7 +802,7 @@ i915_gem_mmap_offset_ioctl(struct drm_device *dev, void 
*data,
break;
 
case I915_MMAP_OFFSET_UC:
-   if (!boot_cpu_has(X86_FEATURE_PAT))
+   if (!pat_enabled())
return -ENODEV;
type = I915_MMAP_TYPE_UC;
break;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c 
b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
index 49c6e55c68ce..89b70f5cde7a 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
@@ -424,8 +424,7 @@ void *i915_gem_object_pin_map(struct drm_i915_gem_object 
*obj,
goto err_unpin;
}
 
-   if (GEM_WARN_ON(type == I915_MAP_WC &&
-   !static_cpu_has(X86_FEATURE_PAT)))
+   if (GEM_WARN_ON(type == I915_MAP_WC && !pat_enabled()))
ptr = ERR_PTR(-ENODEV);
else if (i915_gem_object_has_struct_page(obj))
ptr = i915_gem_object_map_page(obj, type);
-- 
2.33.1



Re: [PATCH v11, 03/19] media: mtk-vcodec: Refactor vcodec pm interface

2021-12-01 Thread Steve Cho
Reviewed-by: Steve Cho 

On Sun, Nov 28, 2021 at 7:44 PM Yunfei Dong  wrote:
>
> Using the needed param for pm init/release function and remove unused
> param mtkdev in 'struct mtk_vcodec_pm'.

nit: How about s/needed param/needed params |pdev| and |pm|/ ?


> Reviewed-by: Tzung-Bi Shih 
> Reviewed-by: AngeloGioacchino Del Regno 
> 
> Signed-off-by: Yunfei Dong 
> ---
>  .../platform/mtk-vcodec/mtk_vcodec_dec_drv.c  |  6 ++---
>  .../platform/mtk-vcodec/mtk_vcodec_dec_pm.c   | 22 ---
>  .../platform/mtk-vcodec/mtk_vcodec_dec_pm.h   |  5 +++--
>  .../platform/mtk-vcodec/mtk_vcodec_drv.h  |  1 -
>  .../platform/mtk-vcodec/mtk_vcodec_enc_pm.c   |  1 -
>  5 files changed, 15 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c 
> b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
> index 055d50e52720..3ac4c3935e4e 100644
> --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
> +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
> @@ -249,7 +249,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
> if (IS_ERR(dev->fw_handler))
> return PTR_ERR(dev->fw_handler);
>
> -   ret = mtk_vcodec_init_dec_pm(dev);
> +   ret = mtk_vcodec_init_dec_pm(dev->plat_dev, &dev->pm);
> if (ret < 0) {
> dev_err(&pdev->dev, "Failed to get mt vcodec clock source");
> goto err_dec_pm;
> @@ -378,7 +378,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
>  err_dec_alloc:
> v4l2_device_unregister(&dev->v4l2_dev);
>  err_res:
> -   mtk_vcodec_release_dec_pm(dev);
> +   mtk_vcodec_release_dec_pm(&dev->pm);
>  err_dec_pm:
> mtk_vcodec_fw_release(dev->fw_handler);
> return ret;
> @@ -418,7 +418,7 @@ static int mtk_vcodec_dec_remove(struct platform_device 
> *pdev)
> video_unregister_device(dev->vfd_dec);
>
> v4l2_device_unregister(&dev->v4l2_dev);
> -   mtk_vcodec_release_dec_pm(dev);
> +   mtk_vcodec_release_dec_pm(&dev->pm);
> mtk_vcodec_fw_release(dev->fw_handler);
> return 0;
>  }
> diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c 
> b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
> index 6038db96f71c..20bd157a855c 100644
> --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
> +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
> @@ -13,18 +13,15 @@
>  #include "mtk_vcodec_dec_pm.h"
>  #include "mtk_vcodec_util.h"
>
> -int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev)
> +int mtk_vcodec_init_dec_pm(struct platform_device *pdev,
> +   struct mtk_vcodec_pm *pm)
>  {
> struct device_node *node;
> -   struct platform_device *pdev;
> -   struct mtk_vcodec_pm *pm;
> +   struct platform_device *larb_pdev;
> struct mtk_vcodec_clk *dec_clk;
> struct mtk_vcodec_clk_info *clk_info;
> int i = 0, ret = 0;
>
> -   pdev = mtkdev->plat_dev;
> -   pm = &mtkdev->pm;
> -   pm->mtkdev = mtkdev;
> dec_clk = &pm->vdec_clk;
> node = of_parse_phandle(pdev->dev.of_node, "mediatek,larb", 0);
> if (!node) {
> @@ -32,13 +29,12 @@ int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev)
> return -1;
> }
>
> -   pdev = of_find_device_by_node(node);
> +   larb_pdev = of_find_device_by_node(node);
> of_node_put(node);
> -   if (WARN_ON(!pdev)) {
> +   if (WARN_ON(!larb_pdev)) {
> return -1;
> }
> -   pm->larbvdec = &pdev->dev;
> -   pdev = mtkdev->plat_dev;
> +   pm->larbvdec = &larb_pdev->dev;
> pm->dev = &pdev->dev;
>
> dec_clk->clk_num =
> @@ -82,10 +78,10 @@ int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev)
> return ret;
>  }
>
> -void mtk_vcodec_release_dec_pm(struct mtk_vcodec_dev *dev)
> +void mtk_vcodec_release_dec_pm(struct mtk_vcodec_pm *pm)
>  {
> -   pm_runtime_disable(dev->pm.dev);
> -   put_device(dev->pm.larbvdec);
> +   pm_runtime_disable(pm->dev);
> +   put_device(pm->larbvdec);
>  }
>
>  int mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm)
> diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h 
> b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
> index 280aeaefdb65..a3df6aef6cb9 100644
> --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
> +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
> @@ -9,8 +9,9 @@
>
>  #include "mtk_vcodec_drv.h"
>
> -int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *dev);
> -void mtk_vcodec_release_dec_pm(struct mtk_vcodec_dev *dev);
> +int mtk_vcodec_init_dec_pm(struct platform_device *pdev,
> +   struct mtk_vcodec_pm *pm);
> +void mtk_vcodec_release_dec_pm(struct mtk_vcodec_pm *pm);
>
>  int mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm);
>  void mtk_vcodec_dec_pw_off(struct mtk_vcodec_pm *pm);
> diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h

Re: [PATCH v11, 04/19] media: mtk-vcodec: export decoder pm functions

2021-12-01 Thread Steve Cho
Reviewed-by: Steve Cho 

On Wed, Dec 1, 2021 at 4:09 AM AngeloGioacchino Del Regno
 wrote:
>
> Il 29/11/21 04:41, Yunfei Dong ha scritto:
> > Register each hardware as platform device, need to call pm functions
> > to open/close power and clock from module mtk-vcodec-dec, export these
> > functions.
> >
> > Signed-off-by: Yunfei Dong 
> > Reviewed-by: Benjamin Gaignard 
>
>
> Reviewed-by: AngeloGioacchino Del Regno 
> 


Re: [PATCH v11, 02/19] media: mtk-vcodec: Align vcodec wake up interrupt interface

2021-12-01 Thread Steve Cho
Reviewed-by: Steve Cho 

On Wed, Dec 1, 2021 at 3:55 PM Steve Cho  wrote:
>
> LGTM.
>
> On Sun, Nov 28, 2021 at 7:44 PM Yunfei Dong  wrote:
> >
> > Vdec and venc can use the same function to wake up interrupt event.
> >
> > Reviewed-by: Tzung-Bi Shih 
> > Reviewed-by: AngeloGioacchino Del Regno 
> > 
> > Signed-off-by: Yunfei Dong 
> > ---
> >  drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c | 9 +
> >  drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h | 8 
> >  drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 8 
> >  3 files changed, 9 insertions(+), 16 deletions(-)
> >
> > diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c 
> > b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
> > index 59caf2163349..055d50e52720 100644
> > --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
> > +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
> > @@ -31,13 +31,6 @@
> >  module_param(mtk_v4l2_dbg_level, int, 0644);
> >  module_param(mtk_vcodec_dbg, bool, 0644);
> >
> > -/* Wake up context wait_queue */
> > -static void wake_up_ctx(struct mtk_vcodec_ctx *ctx)
> > -{
> > -   ctx->int_cond = 1;
> > -   wake_up_interruptible(&ctx->queue);
> > -}
> > -
> >  static irqreturn_t mtk_vcodec_dec_irq_handler(int irq, void *priv)
> >  {
> > struct mtk_vcodec_dev *dev = priv;
> > @@ -69,7 +62,7 @@ static irqreturn_t mtk_vcodec_dec_irq_handler(int irq, 
> > void *priv)
> > writel((readl(vdec_misc_addr) & ~VDEC_IRQ_CLR),
> > dev->reg_base[VDEC_MISC] + VDEC_IRQ_CFG_REG);
> >
> > -   wake_up_ctx(ctx);
> > +   wake_up_ctx(ctx, MTK_INST_IRQ_RECEIVED);
>
> Assuming setting up reason doesn't change functionality.
>
> >
> > mtk_v4l2_debug(3,
> > "mtk_vcodec_dec_irq_handler :wake up ctx %d, 
> > dec_done_status=%x",
> > diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h 
> > b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
> > index 581522177308..1d2370608d0d 100644
> > --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
> > +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
> > @@ -473,4 +473,12 @@ static inline struct mtk_vcodec_ctx 
> > *ctrl_to_ctx(struct v4l2_ctrl *ctrl)
> > return container_of(ctrl->handler, struct mtk_vcodec_ctx, ctrl_hdl);
> >  }
> >
> > +/* Wake up context wait_queue */
> > +static inline void wake_up_ctx(struct mtk_vcodec_ctx *ctx, unsigned int 
> > reason)
> > +{
> > +   ctx->int_cond = 1;
> > +   ctx->int_type = reason;
> > +   wake_up_interruptible(&ctx->queue);
> > +}
> > +
> >  #endif /* _MTK_VCODEC_DRV_H_ */
> > diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c 
> > b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
> > index eed67394cf46..7c3487fb3498 100644
> > --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
> > +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
> > @@ -65,14 +65,6 @@ static const struct mtk_video_fmt 
> > mtk_video_formats_capture_vp8[] =  {
> > },
> >  };
> >
> > -/* Wake up context wait_queue */
> > -static void wake_up_ctx(struct mtk_vcodec_ctx *ctx, unsigned int reason)
> > -{
> > -   ctx->int_cond = 1;
> > -   ctx->int_type = reason;
> > -   wake_up_interruptible(&ctx->queue);
> > -}
> > -
> >  static void clean_irq_status(unsigned int irq_status, void __iomem *addr)
> >  {
> > if (irq_status & MTK_VENC_IRQ_STATUS_PAUSE)
> > --
> > 2.25.1
> >


Re: [PATCH v11, 05/19] media: mtk-vcodec: Support MT8192

2021-12-01 Thread Steve Cho
Reviewed-by: Steve Cho 

On Wed, Dec 1, 2021 at 4:10 AM AngeloGioacchino Del Regno
 wrote:
>
> Il 29/11/21 04:41, Yunfei Dong ha scritto:
> > From: Yunfei Dong 
> >
> > Adds MT8192's compatible "mediatek,mt8192-vcodec-dec".
> > Adds MT8192's device private data mtk_lat_sig_core_pdata.
> >
> > Signed-off-by: Yunfei Dong 
>
> Reviewed-by: AngeloGioacchino Del Regno 
> 


Re: [PATCH v11, 02/19] media: mtk-vcodec: Align vcodec wake up interrupt interface

2021-12-01 Thread Steve Cho
LGTM.

On Sun, Nov 28, 2021 at 7:44 PM Yunfei Dong  wrote:
>
> Vdec and venc can use the same function to wake up interrupt event.
>
> Reviewed-by: Tzung-Bi Shih 
> Reviewed-by: AngeloGioacchino Del Regno 
> 
> Signed-off-by: Yunfei Dong 
> ---
>  drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c | 9 +
>  drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h | 8 
>  drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 8 
>  3 files changed, 9 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c 
> b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
> index 59caf2163349..055d50e52720 100644
> --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
> +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
> @@ -31,13 +31,6 @@
>  module_param(mtk_v4l2_dbg_level, int, 0644);
>  module_param(mtk_vcodec_dbg, bool, 0644);
>
> -/* Wake up context wait_queue */
> -static void wake_up_ctx(struct mtk_vcodec_ctx *ctx)
> -{
> -   ctx->int_cond = 1;
> -   wake_up_interruptible(&ctx->queue);
> -}
> -
>  static irqreturn_t mtk_vcodec_dec_irq_handler(int irq, void *priv)
>  {
> struct mtk_vcodec_dev *dev = priv;
> @@ -69,7 +62,7 @@ static irqreturn_t mtk_vcodec_dec_irq_handler(int irq, void 
> *priv)
> writel((readl(vdec_misc_addr) & ~VDEC_IRQ_CLR),
> dev->reg_base[VDEC_MISC] + VDEC_IRQ_CFG_REG);
>
> -   wake_up_ctx(ctx);
> +   wake_up_ctx(ctx, MTK_INST_IRQ_RECEIVED);

Assuming setting up reason doesn't change functionality.

>
> mtk_v4l2_debug(3,
> "mtk_vcodec_dec_irq_handler :wake up ctx %d, 
> dec_done_status=%x",
> diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h 
> b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
> index 581522177308..1d2370608d0d 100644
> --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
> +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
> @@ -473,4 +473,12 @@ static inline struct mtk_vcodec_ctx *ctrl_to_ctx(struct 
> v4l2_ctrl *ctrl)
> return container_of(ctrl->handler, struct mtk_vcodec_ctx, ctrl_hdl);
>  }
>
> +/* Wake up context wait_queue */
> +static inline void wake_up_ctx(struct mtk_vcodec_ctx *ctx, unsigned int 
> reason)
> +{
> +   ctx->int_cond = 1;
> +   ctx->int_type = reason;
> +   wake_up_interruptible(&ctx->queue);
> +}
> +
>  #endif /* _MTK_VCODEC_DRV_H_ */
> diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c 
> b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
> index eed67394cf46..7c3487fb3498 100644
> --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
> +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
> @@ -65,14 +65,6 @@ static const struct mtk_video_fmt 
> mtk_video_formats_capture_vp8[] =  {
> },
>  };
>
> -/* Wake up context wait_queue */
> -static void wake_up_ctx(struct mtk_vcodec_ctx *ctx, unsigned int reason)
> -{
> -   ctx->int_cond = 1;
> -   ctx->int_type = reason;
> -   wake_up_interruptible(&ctx->queue);
> -}
> -
>  static void clean_irq_status(unsigned int irq_status, void __iomem *addr)
>  {
> if (irq_status & MTK_VENC_IRQ_STATUS_PAUSE)
> --
> 2.25.1
>


Re: [PATCH v2 04/20] dt-bindings: host1x: Document optional HDMI sound-dai-cells

2021-12-01 Thread Rob Herring
On Fri, 26 Nov 2021 19:17:51 +0300, Dmitry Osipenko wrote:
> Document new optional sound-dai-cells property of HDMI node. This node will
> be used as endpoint of HDMI sound DAI graph.
> 
> Signed-off-by: Dmitry Osipenko 
> ---
>  .../devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt  | 1 +
>  1 file changed, 1 insertion(+)
> 

Acked-by: Rob Herring 


Re: [PATCH v2 03/20] ASoC: dt-bindings: tegra20-i2s: Document new nvidia,fixed-parent-rate property

2021-12-01 Thread Rob Herring
On Fri, 26 Nov 2021 19:17:50 +0300, Dmitry Osipenko wrote:
> Document new nvidia,fixed-parent-rate property which instructs that this
> board wants parent clock to stay at a fixed rate. It allows to prevent
> conflicts between audio components that share same parent PLL. For
> instance, this property allows to have HDMI audio, speaker and headphones
> in the system playing audio simultaneously, which is a common pattern for
> consumer devices.
> 
> Signed-off-by: Dmitry Osipenko 
> ---
>  .../devicetree/bindings/sound/nvidia,tegra20-i2s.yaml  | 7 +++
>  1 file changed, 7 insertions(+)
> 

Reviewed-by: Rob Herring 


Re: [PATCH v2 02/20] ASoC: dt-bindings: tegra20-i2s: Convert to schema

2021-12-01 Thread Rob Herring
On Fri, 26 Nov 2021 19:17:49 +0300, Dmitry Osipenko wrote:
> Convert NVIDIA Tegra20 I2S binding to schema.
> 
> Signed-off-by: Dmitry Osipenko 
> ---
>  .../bindings/sound/nvidia,tegra20-i2s.txt | 30 
>  .../bindings/sound/nvidia,tegra20-i2s.yaml| 70 +++
>  2 files changed, 70 insertions(+), 30 deletions(-)
>  delete mode 100644 
> Documentation/devicetree/bindings/sound/nvidia,tegra20-i2s.txt
>  create mode 100644 
> Documentation/devicetree/bindings/sound/nvidia,tegra20-i2s.yaml
> 

Reviewed-by: Rob Herring 


Re: [PATCH v2 01/20] ASoC: dt-bindings: Add binding for Tegra20 S/PDIF

2021-12-01 Thread Rob Herring
On Fri, Nov 26, 2021 at 07:17:48PM +0300, Dmitry Osipenko wrote:
> Add device-tree binding for Tegra20 S/PDIF controller.
> 
> Signed-off-by: Dmitry Osipenko 
> ---
>  .../bindings/sound/nvidia,tegra20-spdif.yaml  | 85 +++
>  1 file changed, 85 insertions(+)
>  create mode 100644 
> Documentation/devicetree/bindings/sound/nvidia,tegra20-spdif.yaml
> 
> diff --git 
> a/Documentation/devicetree/bindings/sound/nvidia,tegra20-spdif.yaml 
> b/Documentation/devicetree/bindings/sound/nvidia,tegra20-spdif.yaml
> new file mode 100644
> index ..00240205817d
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra20-spdif.yaml
> @@ -0,0 +1,85 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/sound/nvidia,tegra20-spdif.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: NVIDIA Tegra20 S/PDIF Controller
> +
> +description: |
> +  The S/PDIF controller supports both input and output in serial audio
> +  digital interface format. The input controller can digitally recover
> +  a clock from the received stream. The S/PDIF controller is also used
> +  to generate the embedded audio for HDMI output channel.
> +
> +maintainers:
> +  - Thierry Reding 
> +  - Jon Hunter 
> +
> +properties:
> +  compatible:
> +const: nvidia,tegra20-spdif
> +
> +  reg:
> +maxItems: 1
> +
> +  resets:
> +maxItems: 1
> +
> +  interrupts:
> +maxItems: 1
> +
> +  clocks:
> +minItems: 2
> +
> +  clock-names:
> +items:
> +  - const: spdif_out
> +  - const: spdif_in

'spdif_' is redundant.

Otherwise,

Reviewed-by: Rob Herring 


[pull] amdgpu, amdkfd drm-fixes-5.16

2021-12-01 Thread Alex Deucher
Hi Dave, Daniel,

Fixes for 5.16.

The following changes since commit d58071a8a76d779eedab38033ae4c821c30295a5:

  Linux 5.16-rc3 (2021-11-28 14:09:19 -0800)

are available in the Git repository at:

  https://gitlab.freedesktop.org/agd5f/linux.git 
tags/amd-drm-fixes-5.16-2021-12-01

for you to fetch changes up to 3abfe30d803e62cc75dec254eefab3b04d69219b:

  drm/amdkfd: process_info lock not needed for svm (2021-12-01 17:09:58 -0500)


amd-drm-fixes-5.16-2021-12-01:

amdgpu:
- IP discovery based enumeration fixes
- vkms fixes
- DSC fixes for DP MST
- Audio fix for hotplug with tiled displays
- Misc display fixes
- DP tunneling fix
- DP fix
- Aldebaran fix

amdkfd:
- Locking fix
- Static checker fix
- Fix double free


Flora Cui (2):
  drm/amdgpu: cancel the correct hrtimer on exit
  drm/amdgpu: check atomic flag to differeniate with legacy path

Guchun Chen (1):
  drm/amdgpu: fix the missed handling for SDMA2 and SDMA3

Jane Jian (1):
  drm/amdgpu/sriov/vcn: add new vcn ip revision check case for 
SIENNA_CICHLID

Jimmy Kizito (1):
  drm/amd/display: Add work around for tunneled MST.

Lijo Lazar (1):
  drm/amdgpu: Don't halt RLC on GFX suspend

Mustapha Ghaddar (1):
  drm/amd/display: Fix for the no Audio bug with Tiled Displays

Nicholas Kazlauskas (1):
  drm/amd/display: Allow DSC on supported MST branch devices

Perry Yuan (1):
  drm/amd/display: add connector type check for CRC source set

Philip Yang (3):
  drm/amdkfd: set "r = 0" explicitly before goto
  drm/amdkfd: fix double free mem structure
  drm/amdkfd: process_info lock not needed for svm

Shen, George (1):
  drm/amd/display: Clear DPCD lane settings after repeater training

shaoyunl (1):
  drm/amdgpu: adjust the kfd reset sequence in reset sriov function

 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c   |  8 +---
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 16 +--
 drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c  |  3 +++
 drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c|  1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c   |  4 ++--
 drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c  |  7 ---
 drivers/gpu/drm/amd/amdgpu/nv.c|  1 +
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c   | 13 
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c  |  8 
 .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c| 20 ++
 drivers/gpu/drm/amd/display/dc/core/dc_link.c  | 16 +++
 drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c   |  2 +-
 drivers/gpu/drm/amd/display/dc/core/dc_resource.c  | 24 +-
 drivers/gpu/drm/amd/display/dc/dc.h|  3 ++-
 drivers/gpu/drm/amd/display/dc/dc_link.h   |  2 ++
 drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c  |  2 +-
 16 files changed, 90 insertions(+), 40 deletions(-)


[PATCH v2 4/4] drm/msm/dpu: fix CDP setup to account for multirect index

2021-12-01 Thread Dmitry Baryshkov
Client driven prefetch (CDP) is properly setup only for SSPP REC0
currently. Enable client driven prefetch also for SSPP REC1.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c | 12 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h |  4 +++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c   |  2 +-
 3 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
index 7235605bfc9e..75aa47835214 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
@@ -75,6 +75,7 @@
 #define SSPP_TRAFFIC_SHAPER0x130
 #define SSPP_CDP_CNTL  0x134
 #define SSPP_UBWC_ERROR_STATUS 0x138
+#define SSPP_CDP_CNTL_REC1 0x13c
 #define SSPP_TRAFFIC_SHAPER_PREFILL0x150
 #define SSPP_TRAFFIC_SHAPER_REC1_PREFILL   0x154
 #define SSPP_TRAFFIC_SHAPER_REC1   0x158
@@ -624,10 +625,12 @@ static void dpu_hw_sspp_setup_qos_ctrl(struct dpu_hw_pipe 
*ctx,
 }
 
 static void dpu_hw_sspp_setup_cdp(struct dpu_hw_pipe *ctx,
-   struct dpu_hw_pipe_cdp_cfg *cfg)
+   struct dpu_hw_pipe_cdp_cfg *cfg,
+   enum dpu_sspp_multirect_index index)
 {
u32 idx;
u32 cdp_cntl = 0;
+   u32 cdp_cntl_offset = 0;
 
if (!ctx || !cfg)
return;
@@ -635,6 +638,11 @@ static void dpu_hw_sspp_setup_cdp(struct dpu_hw_pipe *ctx,
if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx))
return;
 
+   if (index == DPU_SSPP_RECT_SOLO || index == DPU_SSPP_RECT_0)
+   cdp_cntl_offset = SSPP_CDP_CNTL;
+   else
+   cdp_cntl_offset = SSPP_CDP_CNTL_REC1;
+
if (cfg->enable)
cdp_cntl |= BIT(0);
if (cfg->ubwc_meta_enable)
@@ -644,7 +652,7 @@ static void dpu_hw_sspp_setup_cdp(struct dpu_hw_pipe *ctx,
if (cfg->preload_ahead == DPU_SSPP_CDP_PRELOAD_AHEAD_64)
cdp_cntl |= BIT(3);
 
-   DPU_REG_WRITE(&ctx->hw, SSPP_CDP_CNTL, cdp_cntl);
+   DPU_REG_WRITE(&ctx->hw, cdp_cntl_offset, cdp_cntl);
 }
 
 static void _setup_layer_ops(struct dpu_hw_pipe *c,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
index 3c53bd03bdeb..227b09fa4689 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
@@ -356,9 +356,11 @@ struct dpu_hw_sspp_ops {
 * setup_cdp - setup client driven prefetch
 * @ctx: Pointer to pipe context
 * @cfg: Pointer to cdp configuration
+* @index: rectangle index in multirect
 */
void (*setup_cdp)(struct dpu_hw_pipe *ctx,
-   struct dpu_hw_pipe_cdp_cfg *cfg);
+   struct dpu_hw_pipe_cdp_cfg *cfg,
+   enum dpu_sspp_multirect_index index);
 };
 
 /**
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index 911f5f0b41d8..1134171f4d1c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -1191,7 +1191,7 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane 
*plane)
DPU_FORMAT_IS_TILE(fmt);
cdp_cfg.preload_ahead = DPU_SSPP_CDP_PRELOAD_AHEAD_64;
 
-   pdpu->pipe_hw->ops.setup_cdp(pdpu->pipe_hw, &cdp_cfg);
+   pdpu->pipe_hw->ops.setup_cdp(pdpu->pipe_hw, &cdp_cfg, 
pstate->multirect_index);
}
}
 
-- 
2.33.0



[PATCH v2 3/4] drm/msm/dpu: simplify DPU_SSPP features checks

2021-12-01 Thread Dmitry Baryshkov
Add DPU_SSPP_CSC_ANY denoting any CSC block. As we are at it, rewrite
DPU_SSPP_SCALER (any scaler) to use BIT(x) instead of hand-coded
bitshifts.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h | 16 +++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c   |  3 +--
 2 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
index ad2002d75739..3c53bd03bdeb 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
@@ -25,11 +25,17 @@ struct dpu_hw_pipe;
 /**
  * Define all scaler feature bits in catalog
  */
-#define DPU_SSPP_SCALER ((1UL << DPU_SSPP_SCALER_RGB) | \
-   (1UL << DPU_SSPP_SCALER_QSEED2) | \
-(1UL << DPU_SSPP_SCALER_QSEED3) | \
-(1UL << DPU_SSPP_SCALER_QSEED3LITE) | \
- (1UL << DPU_SSPP_SCALER_QSEED4))
+#define DPU_SSPP_SCALER (BIT(DPU_SSPP_SCALER_RGB) | \
+BIT(DPU_SSPP_SCALER_QSEED2) | \
+BIT(DPU_SSPP_SCALER_QSEED3) | \
+BIT(DPU_SSPP_SCALER_QSEED3LITE) | \
+BIT(DPU_SSPP_SCALER_QSEED4))
+
+/*
+ * Define all CSC feature bits in catalog
+ */
+#define DPU_SSPP_CSC_ANY (BIT(DPU_SSPP_CSC) | \
+ BIT(DPU_SSPP_CSC_10BIT))
 
 /**
  * Component indices
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index c7b065b14c5c..911f5f0b41d8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -1010,8 +1010,7 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
 
if (DPU_FORMAT_IS_YUV(fmt) &&
(!(pdpu->pipe_hw->cap->features & DPU_SSPP_SCALER) ||
-!(pdpu->pipe_hw->cap->features & (BIT(DPU_SSPP_CSC)
-| BIT(DPU_SSPP_CSC_10BIT) {
+!(pdpu->pipe_hw->cap->features & DPU_SSPP_CSC_ANY))) {
DPU_DEBUG_PLANE(pdpu,
"plane doesn't have scaler/csc for yuv\n");
return -EINVAL;
-- 
2.33.0



[PATCH v2 2/4] drm/msm/dpu: drop pe argument from _dpu_hw_sspp_setup_scaler3

2021-12-01 Thread Dmitry Baryshkov
The _dpu_hw_sspp_setup_scaler3 (hw_sspp->setup_scaler) does not use pe
argument. Let's remove it while we are cleaning scaled configuration.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c | 2 --
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h | 2 --
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c   | 2 +-
 3 files changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
index d77eb7da5daf..7235605bfc9e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
@@ -413,13 +413,11 @@ static void dpu_hw_sspp_setup_pe_config(struct 
dpu_hw_pipe *ctx,
 
 static void _dpu_hw_sspp_setup_scaler3(struct dpu_hw_pipe *ctx,
struct dpu_hw_pipe_cfg *sspp,
-   struct dpu_hw_pixel_ext *pe,
void *scaler_cfg)
 {
u32 idx;
struct dpu_hw_scaler3_cfg *scaler3_cfg = scaler_cfg;
 
-   (void)pe;
if (_sspp_subblk_offset(ctx, DPU_SSPP_SCALER_QSEED3, &idx) || !sspp
|| !scaler3_cfg)
return;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
index e8939d7387cb..ad2002d75739 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
@@ -334,12 +334,10 @@ struct dpu_hw_sspp_ops {
 * setup_scaler - setup scaler
 * @ctx: Pointer to pipe context
 * @pipe_cfg: Pointer to pipe configuration
-* @pe_cfg: Pointer to pixel extension configuration
 * @scaler_cfg: Pointer to scaler configuration
 */
void (*setup_scaler)(struct dpu_hw_pipe *ctx,
struct dpu_hw_pipe_cfg *pipe_cfg,
-   struct dpu_hw_pixel_ext *pe_cfg,
void *scaler_cfg);
 
/**
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index 4c373abbe89c..c7b065b14c5c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -688,7 +688,7 @@ static void _dpu_plane_setup_scaler(struct dpu_plane *pdpu,
if (pdpu->pipe_hw->ops.setup_scaler &&
pstate->multirect_index != DPU_SSPP_RECT_1)
pdpu->pipe_hw->ops.setup_scaler(pdpu->pipe_hw,
-   pipe_cfg, &pixel_ext,
+   pipe_cfg,
&scaler3_cfg);
 }
 
-- 
2.33.0



[PATCH v2 1/4] drm/msm/dpu: drop scaler config from plane state

2021-12-01 Thread Dmitry Baryshkov
Scaler and pixel_ext configuration does not contain a long living state,
it is used only during plane update, so remove these two fiels from
dpu_plane_state and allocate them on stack.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 59 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h |  6 ---
 2 files changed, 26 insertions(+), 39 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index ca190d92f0d5..4c373abbe89c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -536,14 +536,12 @@ static void _dpu_plane_setup_scaler3(struct dpu_plane 
*pdpu,
struct dpu_plane_state *pstate,
uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h,
struct dpu_hw_scaler3_cfg *scale_cfg,
+   struct dpu_hw_pixel_ext *pixel_ext,
const struct dpu_format *fmt,
uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v)
 {
uint32_t i;
 
-   memset(scale_cfg, 0, sizeof(*scale_cfg));
-   memset(&pstate->pixel_ext, 0, sizeof(struct dpu_hw_pixel_ext));
-
scale_cfg->phase_step_x[DPU_SSPP_COMP_0] =
mult_frac((1 << PHASE_STEP_SHIFT), src_w, dst_w);
scale_cfg->phase_step_y[DPU_SSPP_COMP_0] =
@@ -582,9 +580,9 @@ static void _dpu_plane_setup_scaler3(struct dpu_plane *pdpu,
scale_cfg->preload_y[i] = DPU_QSEED3_DEFAULT_PRELOAD_V;
}
 
-   pstate->pixel_ext.num_ext_pxls_top[i] =
+   pixel_ext->num_ext_pxls_top[i] =
scale_cfg->src_height[i];
-   pstate->pixel_ext.num_ext_pxls_left[i] =
+   pixel_ext->num_ext_pxls_left[i] =
scale_cfg->src_width[i];
}
if (!(DPU_FORMAT_IS_YUV(fmt)) && (src_h == dst_h)
@@ -662,6 +660,11 @@ static void _dpu_plane_setup_scaler(struct dpu_plane *pdpu,
struct dpu_hw_pipe_cfg *pipe_cfg)
 {
const struct drm_format_info *info = 
drm_format_info(fmt->base.pixel_format);
+   struct dpu_hw_scaler3_cfg scaler3_cfg;
+   struct dpu_hw_pixel_ext pixel_ext;
+
+   memset(&scaler3_cfg, 0, sizeof(scaler3_cfg));
+   memset(&pixel_ext, 0, sizeof(pixel_ext));
 
/* don't chroma subsample if decimating */
/* update scaler. calculate default config for QSEED3 */
@@ -670,8 +673,23 @@ static void _dpu_plane_setup_scaler(struct dpu_plane *pdpu,
drm_rect_height(&pipe_cfg->src_rect),
drm_rect_width(&pipe_cfg->dst_rect),
drm_rect_height(&pipe_cfg->dst_rect),
-   &pstate->scaler3_cfg, fmt,
+   &scaler3_cfg, &pixel_ext, fmt,
info->hsub, info->vsub);
+
+   if (pdpu->pipe_hw->ops.setup_pe)
+   pdpu->pipe_hw->ops.setup_pe(pdpu->pipe_hw,
+   &pixel_ext);
+
+   /**
+* when programmed in multirect mode, scalar block will be
+* bypassed. Still we need to update alpha and bitwidth
+* ONLY for RECT0
+*/
+   if (pdpu->pipe_hw->ops.setup_scaler &&
+   pstate->multirect_index != DPU_SSPP_RECT_1)
+   pdpu->pipe_hw->ops.setup_scaler(pdpu->pipe_hw,
+   pipe_cfg, &pixel_ext,
+   &scaler3_cfg);
 }
 
 /**
@@ -712,7 +730,6 @@ static int _dpu_plane_color_fill(struct dpu_plane *pdpu,
drm_rect_width(&pipe_cfg.dst_rect);
pipe_cfg.src_rect.y2 =
drm_rect_height(&pipe_cfg.dst_rect);
-   _dpu_plane_setup_scaler(pdpu, pstate, fmt, true, &pipe_cfg);
 
if (pdpu->pipe_hw->ops.setup_format)
pdpu->pipe_hw->ops.setup_format(pdpu->pipe_hw,
@@ -724,15 +741,7 @@ static int _dpu_plane_color_fill(struct dpu_plane *pdpu,
&pipe_cfg,
pstate->multirect_index);
 
-   if (pdpu->pipe_hw->ops.setup_pe)
-   pdpu->pipe_hw->ops.setup_pe(pdpu->pipe_hw,
-   &pstate->pixel_ext);
-
-   if (pdpu->pipe_hw->ops.setup_scaler &&
-   pstate->multirect_index != DPU_SSPP_RECT_1)
-   pdpu->pipe_hw->ops.setup_scaler(pdpu->pipe_hw,
-   &pipe_cfg, &pstate->pixel_ext,
-   &pstate->scaler3_cfg);
+   _dpu_plane_setup_scaler(pdpu, pstate, fmt, true, &pipe_cfg);
}
 
return 0;
@@ -1129,8 +1138,6 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane 
*plane)
 
pipe_cfg.dst_rect = state->dst;
 
-   _dpu_plane_setup_scaler(pdpu, pstate, fmt, false, &pipe_cfg);
-
/* ov

[PATCH v2 0/4] drm/msm/dpu: cleanup plane state

2021-12-01 Thread Dmitry Baryshkov
This is a cleanup part of the DPU multirect patchset [1], split away to
ease review and merging per Abhinav's request.

Changes in v2:
- Drop patches that were accepted
- Removed pe argument from _dpu_hw_sspp_setup_scaler3
- Add CDP setup and DPU_SSPP features checks patches that were left from the 
previous series

[1] 
https://lore.kernel.org/linux-arm-msm/20210705012115.4179824-1-dmitry.barysh...@linaro.org/

The following changes since commit fee32807633395e666f0951d6b7b6546e9b76c3d:

  mailmap: add and update email addresses (2021-11-29 16:19:58 -0800)

are available in the Git repository at:

  https://git.linaro.org/people/dmitry.baryshkov/kernel.git dpu-cleanup-more

for you to fetch changes up to 5f4622c2324756e942e6e40227997713cdd0a03a:

  drm/msm/dpu: fix CDP setup to account for multirect index (2021-12-02 
01:29:18 +0300)


Dmitry Baryshkov (4):
  drm/msm/dpu: drop scaler config from plane state
  drm/msm/dpu: drop pe argument from _dpu_hw_sspp_setup_scaler3
  drm/msm/dpu: simplify DPU_SSPP features checks
  drm/msm/dpu: fix CDP setup to account for multirect index

 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c | 14 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h | 22 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c   | 64 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h   |  6 ---
 4 files changed, 52 insertions(+), 54 deletions(-)




[PATCH v1 8/8] drm/msm/dpu: move SSPP debugfs support from plane to SSPP code

2021-12-01 Thread Dmitry Baryshkov
We are preparing to change DPU plane implementation. Move SSPP debugfs
code from dpu_plane.c to dpu_hw_sspp.c, where it belongs.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c | 67 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h |  4 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c |  1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c   | 82 +++--
 4 files changed, 84 insertions(+), 70 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
index d77eb7da5daf..ae3cf2e4d7d9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
@@ -8,6 +8,8 @@
 #include "dpu_hw_sspp.h"
 #include "dpu_kms.h"
 
+#include 
+
 #define DPU_FETCH_CONFIG_RESET_VALUE   0x0087
 
 /* DPU_SSPP_SRC */
@@ -686,6 +688,71 @@ static void _setup_layer_ops(struct dpu_hw_pipe *c,
c->ops.setup_cdp = dpu_hw_sspp_setup_cdp;
 }
 
+#ifdef CONFIG_DEBUG_FS
+int _dpu_hw_sspp_init_debugfs(struct dpu_hw_pipe *hw_pipe, struct dpu_kms 
*kms, struct dentry *entry)
+{
+   const struct dpu_sspp_cfg *cfg = hw_pipe->cap;
+   const struct dpu_sspp_sub_blks *sblk = cfg->sblk;
+   struct dentry *debugfs_root;
+   char sspp_name[32];
+
+   snprintf(sspp_name, sizeof(sspp_name), "%d", hw_pipe->idx);
+
+   /* create overall sub-directory for the pipe */
+   debugfs_root =
+   debugfs_create_dir(sspp_name, entry);
+
+   /* don't error check these */
+   debugfs_create_xul("features", 0600,
+   debugfs_root, (unsigned long *)&hw_pipe->cap->features);
+
+   /* add register dump support */
+   dpu_debugfs_create_regset32("src_blk", 0400,
+   debugfs_root,
+   sblk->src_blk.base + cfg->base,
+   sblk->src_blk.len,
+   kms);
+
+   if (cfg->features & BIT(DPU_SSPP_SCALER_QSEED3) ||
+   cfg->features & BIT(DPU_SSPP_SCALER_QSEED3LITE) ||
+   cfg->features & BIT(DPU_SSPP_SCALER_QSEED2) ||
+   cfg->features & BIT(DPU_SSPP_SCALER_QSEED4))
+   dpu_debugfs_create_regset32("scaler_blk", 0400,
+   debugfs_root,
+   sblk->scaler_blk.base + cfg->base,
+   sblk->scaler_blk.len,
+   kms);
+
+   if (cfg->features & BIT(DPU_SSPP_CSC) ||
+   cfg->features & BIT(DPU_SSPP_CSC_10BIT))
+   dpu_debugfs_create_regset32("csc_blk", 0400,
+   debugfs_root,
+   sblk->csc_blk.base + cfg->base,
+   sblk->csc_blk.len,
+   kms);
+
+   debugfs_create_u32("xin_id",
+   0400,
+   debugfs_root,
+   (u32 *) &cfg->xin_id);
+   debugfs_create_u32("clk_ctrl",
+   0400,
+   debugfs_root,
+   (u32 *) &cfg->clk_ctrl);
+   debugfs_create_x32("creq_vblank",
+   0600,
+   debugfs_root,
+   (u32 *) &sblk->creq_vblank);
+   debugfs_create_x32("danger_vblank",
+   0600,
+   debugfs_root,
+   (u32 *) &sblk->danger_vblank);
+
+   return 0;
+}
+#endif
+
+
 static const struct dpu_sspp_cfg *_sspp_offset(enum dpu_sspp sspp,
void __iomem *addr,
struct dpu_mdss_cfg *catalog,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
index e8939d7387cb..cef281687bab 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
@@ -381,6 +381,7 @@ struct dpu_hw_pipe {
struct dpu_hw_sspp_ops ops;
 };
 
+struct dpu_kms;
 /**
  * dpu_hw_sspp_init - initializes the sspp hw driver object.
  * Should be called once before accessing every pipe.
@@ -400,5 +401,8 @@ struct dpu_hw_pipe *dpu_hw_sspp_init(enum dpu_sspp idx,
  */
 void dpu_hw_sspp_destroy(struct dpu_hw_pipe *ctx);
 
+void dpu_debugfs_sspp_init(struct dpu_kms *dpu_kms, struct dentry 
*debugfs_root);
+int _dpu_hw_sspp_init_debugfs(struct dpu_hw_pipe *hw_pipe, struct dpu_kms 
*kms, struct dentry *entry);
+
 #endif /*_DPU_HW_SSPP_H */
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 7e7a619769a8..de9efe6dcf7c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -281,6 +281,7 @@ static int dpu_kms_debugfs_init(struct msm_kms *kms, struct 
drm_minor *minor)
dpu_debugfs_danger_init(dpu_kms, entry);
dpu_debugfs_vbif_init(dpu_kms, entry);
dpu_debugfs_core_irq_init(dpu_kms, entry);
+   dpu_debugfs

[PATCH v1 7/8] drm/msm/dpu: simplify DPU's regset32 code

2021-12-01 Thread Dmitry Baryshkov
Squash dpu_debugfs_setup_regset32() into dpu_debugfs_create_regset32().
it makes little sense to have separate function to just setup the
structure.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   | 32 ---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h   | 38 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 27 +---
 3 files changed, 33 insertions(+), 64 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 4c04982c71b2..7e7a619769a8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -182,6 +182,15 @@ static void dpu_debugfs_danger_init(struct dpu_kms 
*dpu_kms,
 
 }
 
+/*
+ * Companion structure for dpu_debugfs_create_regset32.
+ */
+struct dpu_debugfs_regset32 {
+   uint32_t offset;
+   uint32_t blk_len;
+   struct dpu_kms *dpu_kms;
+};
+
 static int _dpu_debugfs_show_regset32(struct seq_file *s, void *data)
 {
struct dpu_debugfs_regset32 *regset = s->private;
@@ -229,24 +238,23 @@ static const struct file_operations dpu_fops_regset32 = {
.release =  single_release,
 };
 
-void dpu_debugfs_setup_regset32(struct dpu_debugfs_regset32 *regset,
+void dpu_debugfs_create_regset32(const char *name, umode_t mode,
+   void *parent,
uint32_t offset, uint32_t length, struct dpu_kms *dpu_kms)
 {
-   if (regset) {
-   regset->offset = offset;
-   regset->blk_len = length;
-   regset->dpu_kms = dpu_kms;
-   }
-}
+   struct dpu_debugfs_regset32 *regset;
 
-void dpu_debugfs_create_regset32(const char *name, umode_t mode,
-   void *parent, struct dpu_debugfs_regset32 *regset)
-{
-   if (!name || !regset || !regset->dpu_kms || !regset->blk_len)
+   if (WARN_ON(!name || !dpu_kms || !length))
+   return;
+
+   regset = devm_kzalloc(&dpu_kms->pdev->dev, sizeof(*regset), GFP_KERNEL);
+   if (!regset)
return;
 
/* make sure offset is a multiple of 4 */
-   regset->offset = round_down(regset->offset, 4);
+   regset->offset = round_down(offset, 4);
+   regset->blk_len = length;
+   regset->dpu_kms = dpu_kms;
 
debugfs_create_file(name, mode, parent, regset, &dpu_fops_regset32);
 }
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index 775bcbda860f..b53cdeb1b5c4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -160,33 +160,9 @@ struct dpu_global_state
  *
  * Documentation/filesystems/debugfs.rst
  *
- * @dpu_debugfs_setup_regset32: Initialize data for dpu_debugfs_create_regset32
  * @dpu_debugfs_create_regset32: Create 32-bit register dump file
- * @dpu_debugfs_get_root: Get root dentry for DPU_KMS's debugfs node
  */
 
-/**
- * Companion structure for dpu_debugfs_create_regset32. Do not initialize the
- * members of this structure explicitly; use dpu_debugfs_setup_regset32 
instead.
- */
-struct dpu_debugfs_regset32 {
-   uint32_t offset;
-   uint32_t blk_len;
-   struct dpu_kms *dpu_kms;
-};
-
-/**
- * dpu_debugfs_setup_regset32 - Initialize register block definition for 
debugfs
- * This function is meant to initialize dpu_debugfs_regset32 structures for use
- * with dpu_debugfs_create_regset32.
- * @regset: opaque register definition structure
- * @offset: sub-block offset
- * @length: sub-block length, in bytes
- * @dpu_kms: pointer to dpu kms structure
- */
-void dpu_debugfs_setup_regset32(struct dpu_debugfs_regset32 *regset,
-   uint32_t offset, uint32_t length, struct dpu_kms *dpu_kms);
-
 /**
  * dpu_debugfs_create_regset32 - Create register read back file for debugfs
  *
@@ -195,20 +171,16 @@ void dpu_debugfs_setup_regset32(struct 
dpu_debugfs_regset32 *regset,
  * names/offsets do not need to be provided. The 'read' function simply outputs
  * sequential register values over a specified range.
  *
- * Similar to the related debugfs_create_regset32 API, the structure pointed to
- * by regset needs to persist for the lifetime of the created file. The calling
- * code is responsible for initialization/management of this structure.
- *
- * The structure pointed to by regset is meant to be opaque. Please use
- * dpu_debugfs_setup_regset32 to initialize it.
- *
  * @name:   File name within debugfs
  * @mode:   File mode within debugfs
  * @parent: Parent directory entry within debugfs, can be NULL
- * @regset: Pointer to persistent register block definition
+ * @offset: sub-block offset
+ * @length: sub-block length, in bytes
+ * @dpu_kms: pointer to dpu kms structure
  */
 void dpu_debugfs_create_regset32(const char *name, umode_t mode,
-   void *parent, struct dpu_debugfs_regset32 *regset);
+   void *parent,
+   uint32_t offset, uint32_t length, struct dpu_kms *dpu_kms);
 
 /**
  * dpu_de

[PATCH v1 6/8] drm/msm/dpu: stop manually removing debugfs files for the DPU CRTC

2021-12-01 Thread Dmitry Baryshkov
DRM code handles removing all debugfs recursively. Drop CRTC-specific
code to perform that.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 15 ---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h |  3 ---
 2 files changed, 4 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index d290809d59bd..9899f7424131 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1424,15 +1424,16 @@ DEFINE_SHOW_ATTRIBUTE(dpu_crtc_debugfs_state);
 static int _dpu_crtc_init_debugfs(struct drm_crtc *crtc)
 {
struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
+   struct dentry *debugfs_root;
 
-   dpu_crtc->debugfs_root = debugfs_create_dir(dpu_crtc->name,
+   debugfs_root = debugfs_create_dir(dpu_crtc->name,
crtc->dev->primary->debugfs_root);
 
debugfs_create_file("status", 0400,
-   dpu_crtc->debugfs_root,
+   debugfs_root,
dpu_crtc, &_dpu_debugfs_status_fops);
debugfs_create_file("state", 0600,
-   dpu_crtc->debugfs_root,
+   debugfs_root,
&dpu_crtc->base,
&dpu_crtc_debugfs_state_fops);
 
@@ -1450,13 +1451,6 @@ static int dpu_crtc_late_register(struct drm_crtc *crtc)
return _dpu_crtc_init_debugfs(crtc);
 }
 
-static void dpu_crtc_early_unregister(struct drm_crtc *crtc)
-{
-   struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
-
-   debugfs_remove_recursive(dpu_crtc->debugfs_root);
-}
-
 static const struct drm_crtc_funcs dpu_crtc_funcs = {
.set_config = drm_atomic_helper_set_config,
.destroy = dpu_crtc_destroy,
@@ -1465,7 +1459,6 @@ static const struct drm_crtc_funcs dpu_crtc_funcs = {
.atomic_duplicate_state = dpu_crtc_duplicate_state,
.atomic_destroy_state = dpu_crtc_destroy_state,
.late_register = dpu_crtc_late_register,
-   .early_unregister = dpu_crtc_early_unregister,
.verify_crc_source = dpu_crtc_verify_crc_source,
.set_crc_source = dpu_crtc_set_crc_source,
.enable_vblank  = msm_crtc_enable_vblank,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
index 4328e133d71c..b8785c394fcc 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
@@ -129,7 +129,6 @@ struct dpu_crtc_frame_event {
  * @drm_requested_vblank : Whether vblanks have been enabled in the encoder
  * @property_info : Opaque structure for generic property support
  * @property_defaults : Array of default values for generic property support
- * @debugfs_root  : Parent of debugfs node
  * @vblank_cb_count : count of vblank callback since last reset
  * @play_count: frame count between crtc enable and disable
  * @vblank_cb_time  : ktime at vblank count reset
@@ -160,8 +159,6 @@ struct dpu_crtc {
struct drm_pending_vblank_event *event;
u32 vsync_count;
 
-   struct dentry *debugfs_root;
-
u32 vblank_cb_count;
u64 play_count;
ktime_t vblank_cb_time;
-- 
2.33.0



[PATCH v1 5/8] drm/msm/dpu: stop manually removing debugfs files for the DPU plane

2021-12-01 Thread Dmitry Baryshkov
DRM code handles removing all debugfs recursively. Drop plane-specific
code to perform that.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 28 ---
 1 file changed, 10 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index f80ee3ba9a8a..d3176f58708e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -110,7 +110,6 @@ struct dpu_plane {
struct dpu_mdss_cfg *catalog;
 
/* debugfs related stuff */
-   struct dentry *debugfs_root;
struct dpu_debugfs_regset32 debugfs_src;
struct dpu_debugfs_regset32 debugfs_scaler;
struct dpu_debugfs_regset32 debugfs_csc;
@@ -1368,15 +1367,16 @@ static int _dpu_plane_init_debugfs(struct drm_plane 
*plane)
struct dpu_kms *kms = _dpu_plane_get_kms(plane);
const struct dpu_sspp_cfg *cfg = pdpu->pipe_hw->cap;
const struct dpu_sspp_sub_blks *sblk = cfg->sblk;
+   struct dentry *debugfs_root;
 
/* create overall sub-directory for the pipe */
-   pdpu->debugfs_root =
+   debugfs_root =
debugfs_create_dir(plane->name,
plane->dev->primary->debugfs_root);
 
/* don't error check these */
debugfs_create_xul("features", 0600,
-   pdpu->debugfs_root, (unsigned long 
*)&pdpu->pipe_hw->cap->features);
+   debugfs_root, (unsigned long 
*)&pdpu->pipe_hw->cap->features);
 
/* add register dump support */
dpu_debugfs_setup_regset32(&pdpu->debugfs_src,
@@ -1384,7 +1384,7 @@ static int _dpu_plane_init_debugfs(struct drm_plane 
*plane)
sblk->src_blk.len,
kms);
dpu_debugfs_create_regset32("src_blk", 0400,
-   pdpu->debugfs_root, &pdpu->debugfs_src);
+   debugfs_root, &pdpu->debugfs_src);
 
if (cfg->features & BIT(DPU_SSPP_SCALER_QSEED3) ||
cfg->features & BIT(DPU_SSPP_SCALER_QSEED3LITE) ||
@@ -1395,7 +1395,7 @@ static int _dpu_plane_init_debugfs(struct drm_plane 
*plane)
sblk->scaler_blk.len,
kms);
dpu_debugfs_create_regset32("scaler_blk", 0400,
-   pdpu->debugfs_root,
+   debugfs_root,
&pdpu->debugfs_scaler);
}
 
@@ -1406,24 +1406,24 @@ static int _dpu_plane_init_debugfs(struct drm_plane 
*plane)
sblk->csc_blk.len,
kms);
dpu_debugfs_create_regset32("csc_blk", 0400,
-   pdpu->debugfs_root, &pdpu->debugfs_csc);
+   debugfs_root, &pdpu->debugfs_csc);
}
 
debugfs_create_u32("xin_id",
0400,
-   pdpu->debugfs_root,
+   debugfs_root,
(u32 *) &cfg->xin_id);
debugfs_create_u32("clk_ctrl",
0400,
-   pdpu->debugfs_root,
+   debugfs_root,
(u32 *) &cfg->clk_ctrl);
debugfs_create_x32("creq_vblank",
0600,
-   pdpu->debugfs_root,
+   debugfs_root,
(u32 *) &sblk->creq_vblank);
debugfs_create_x32("danger_vblank",
0600,
-   pdpu->debugfs_root,
+   debugfs_root,
(u32 *) &sblk->danger_vblank);
 
return 0;
@@ -1440,13 +1440,6 @@ static int dpu_plane_late_register(struct drm_plane 
*plane)
return _dpu_plane_init_debugfs(plane);
 }
 
-static void dpu_plane_early_unregister(struct drm_plane *plane)
-{
-   struct dpu_plane *pdpu = to_dpu_plane(plane);
-
-   debugfs_remove_recursive(pdpu->debugfs_root);
-}
-
 static bool dpu_plane_format_mod_supported(struct drm_plane *plane,
uint32_t format, uint64_t modifier)
 {
@@ -1472,7 +1465,6 @@ static const struct drm_plane_funcs dpu_plane_funcs = {
.atomic_duplicate_state = dpu_plane_duplicate_state,
.atomic_destroy_state = dpu_plane_destroy_state,
.late_register = dpu_plane_late_register,
-   .early_unregister = dpu_plane_early_unregister,
.format_mod_supported = dpu_plane_format_mod_supported,
 };
 
-- 
2.33.0



[PATCH v1 4/8] drm/msm/dpu: drop plane's default_scaling debugfs file

2021-12-01 Thread Dmitry Baryshkov
Proper support for the 'default_scaling' debugfs file was removed during
DPU driver pre-merge cleanup. Remove leftover file.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 5 -
 1 file changed, 5 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index 6ea4db061c9f..f80ee3ba9a8a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -114,7 +114,6 @@ struct dpu_plane {
struct dpu_debugfs_regset32 debugfs_src;
struct dpu_debugfs_regset32 debugfs_scaler;
struct dpu_debugfs_regset32 debugfs_csc;
-   bool debugfs_default_scale;
 };
 
 static const uint64_t supported_format_modifiers[] = {
@@ -1398,10 +1397,6 @@ static int _dpu_plane_init_debugfs(struct drm_plane 
*plane)
dpu_debugfs_create_regset32("scaler_blk", 0400,
pdpu->debugfs_root,
&pdpu->debugfs_scaler);
-   debugfs_create_bool("default_scaling",
-   0600,
-   pdpu->debugfs_root,
-   &pdpu->debugfs_default_scale);
}
 
if (cfg->features & BIT(DPU_SSPP_CSC) ||
-- 
2.33.0



[PATCH v1 3/8] drm/msm/dpu: make danger_status/safe_status readable

2021-12-01 Thread Dmitry Baryshkov
Change \t to \n in the print format to stop putting all SSPP status in a
single line. Splitting it to one SSPP per line is much more readable.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index e7f0cded2c6b..4c04982c71b2 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -82,7 +82,7 @@ static int _dpu_danger_signal_status(struct seq_file *s,
seq_printf(s, "MDP :  0x%x\n", status.mdp);
 
for (i = SSPP_VIG0; i < SSPP_MAX; i++)
-   seq_printf(s, "SSPP%d   :  0x%x  \t", i - SSPP_VIG0,
+   seq_printf(s, "SSPP%d   :  0x%x  \n", i - SSPP_VIG0,
status.sspp[i]);
seq_puts(s, "\n");
 
-- 
2.33.0



[PATCH v1 2/8] drm/msm/dpu: fix safe status debugfs file

2021-12-01 Thread Dmitry Baryshkov
Make safe_status debugfs fs file actually return safe status rather than
danger status data.

Fixes: 25fdd5933e4c ("drm/msm: Add SDM845 DPU support")
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 259d438bc6e8..e7f0cded2c6b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -73,8 +73,8 @@ static int _dpu_danger_signal_status(struct seq_file *s,
&status);
} else {
seq_puts(s, "\nSafe signal status:\n");
-   if (kms->hw_mdp->ops.get_danger_status)
-   kms->hw_mdp->ops.get_danger_status(kms->hw_mdp,
+   if (kms->hw_mdp->ops.get_safe_status)
+   kms->hw_mdp->ops.get_safe_status(kms->hw_mdp,
&status);
}
pm_runtime_put_sync(&kms->pdev->dev);
-- 
2.33.0



[PATCH v1 0/8] drm/msm/dpu: cleanup debugfs code

2021-12-01 Thread Dmitry Baryshkov
This patchset provides a partial rework/cleanup/fixup of debugfs code in
DPU driver. It started as a single patch removing (and then just moving)
SSPP debugfs code from the plane (as planes are going to be less
connected with SSPP blocks soon). However the more I touched this code,
the more patches were generated as more and more issues arrive on the
surface.

The following changes since commit fee32807633395e666f0951d6b7b6546e9b76c3d:

  mailmap: add and update email addresses (2021-11-29 16:19:58 -0800)

are available in the Git repository at:

  https://git.linaro.org/people/dmitry.baryshkov/kernel.git dpu-cleanup-debugfs

for you to fetch changes up to 7f3598ee9ea525920cd6fa65b498604a9ff8b36a:

  drm/msm/dpu: move SSPP debugfs support from plane to SSPP code (2021-12-02 
01:03:49 +0300)


Dmitry Baryshkov (8):
  drm/msm/dpu: move disable_danger out of plane subdir
  drm/msm/dpu: fix safe status debugfs file
  drm/msm/dpu: make danger_status/safe_status readable
  drm/msm/dpu: drop plane's default_scaling debugfs file
  drm/msm/dpu: stop manually removing debugfs files for the DPU plane
  drm/msm/dpu: stop manually removing debugfs files for the DPU CRTC
  drm/msm/dpu: simplify DPU's regset32 code
  drm/msm/dpu: move SSPP debugfs support from plane to SSPP code

 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c|  15 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h|   3 -
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c |  67 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h |   4 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 109 +++---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |  38 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c   | 172 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h   |   6 +
 8 files changed, 189 insertions(+), 225 deletions(-)




[PATCH v1 1/8] drm/msm/dpu: move disable_danger out of plane subdir

2021-12-01 Thread Dmitry Baryshkov
The disable_danger debugfs file is not related to a single plane.
Instead it is used by all registered planes. Move it from plane subtree
to the global subtree next to danger_status and safe_status files,
so that the new file supplements them.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   | 70 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 74 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h |  6 ++
 3 files changed, 77 insertions(+), 73 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 6c457c419412..259d438bc6e8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -101,6 +101,73 @@ static int dpu_debugfs_safe_stats_show(struct seq_file *s, 
void *v)
 }
 DEFINE_SHOW_ATTRIBUTE(dpu_debugfs_safe_stats);
 
+static ssize_t _dpu_plane_danger_read(struct file *file,
+   char __user *buff, size_t count, loff_t *ppos)
+{
+   struct dpu_kms *kms = file->private_data;
+   int len;
+   char buf[40];
+
+   len = scnprintf(buf, sizeof(buf), "%d\n", !kms->has_danger_ctrl);
+
+   return simple_read_from_buffer(buff, count, ppos, buf, len);
+}
+
+static void _dpu_plane_set_danger_state(struct dpu_kms *kms, bool enable)
+{
+   struct drm_plane *plane;
+
+   drm_for_each_plane(plane, kms->dev) {
+   if (plane->fb && plane->state) {
+   dpu_plane_danger_signal_ctrl(plane, enable);
+   DPU_DEBUG("plane:%d img:%dx%d ",
+   plane->base.id, plane->fb->width,
+   plane->fb->height);
+   DPU_DEBUG("src[%d,%d,%d,%d] dst[%d,%d,%d,%d]\n",
+   plane->state->src_x >> 16,
+   plane->state->src_y >> 16,
+   plane->state->src_w >> 16,
+   plane->state->src_h >> 16,
+   plane->state->crtc_x, plane->state->crtc_y,
+   plane->state->crtc_w, plane->state->crtc_h);
+   } else {
+   DPU_DEBUG("Inactive plane:%d\n", plane->base.id);
+   }
+   }
+}
+
+static ssize_t _dpu_plane_danger_write(struct file *file,
+   const char __user *user_buf, size_t count, loff_t *ppos)
+{
+   struct dpu_kms *kms = file->private_data;
+   int disable_panic;
+   int ret;
+
+   ret = kstrtouint_from_user(user_buf, count, 0, &disable_panic);
+   if (ret)
+   return ret;
+
+   if (disable_panic) {
+   /* Disable panic signal for all active pipes */
+   DPU_DEBUG("Disabling danger:\n");
+   _dpu_plane_set_danger_state(kms, false);
+   kms->has_danger_ctrl = false;
+   } else {
+   /* Enable panic signal for all active pipes */
+   DPU_DEBUG("Enabling danger:\n");
+   kms->has_danger_ctrl = true;
+   _dpu_plane_set_danger_state(kms, true);
+   }
+
+   return count;
+}
+
+static const struct file_operations dpu_plane_danger_enable = {
+   .open = simple_open,
+   .read = _dpu_plane_danger_read,
+   .write = _dpu_plane_danger_write,
+};
+
 static void dpu_debugfs_danger_init(struct dpu_kms *dpu_kms,
struct dentry *parent)
 {
@@ -110,6 +177,9 @@ static void dpu_debugfs_danger_init(struct dpu_kms *dpu_kms,
dpu_kms, &dpu_debugfs_danger_stats_fops);
debugfs_create_file("safe_status", 0600, entry,
dpu_kms, &dpu_debugfs_safe_stats_fops);
+   debugfs_create_file("disable_danger", 0600, entry,
+   dpu_kms, &dpu_plane_danger_enable);
+
 }
 
 static int _dpu_debugfs_show_regset32(struct seq_file *s, void *data)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index ca190d92f0d5..6ea4db061c9f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -1350,7 +1350,7 @@ static void dpu_plane_reset(struct drm_plane *plane)
 }
 
 #ifdef CONFIG_DEBUG_FS
-static void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
+void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
 {
struct dpu_plane *pdpu = to_dpu_plane(plane);
struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
@@ -1363,73 +1363,6 @@ static void dpu_plane_danger_signal_ctrl(struct 
drm_plane *plane, bool enable)
pm_runtime_put_sync(&dpu_kms->pdev->dev);
 }
 
-static ssize_t _dpu_plane_danger_read(struct file *file,
-   char __user *buff, size_t count, loff_t *ppos)
-{
-   struct dpu_kms *kms = file->private_data;
-   int len;
-   char buf[40];
-
-   len = scnprintf(buf, sizeof(buf), "%d\n", !kms->has_danger_ctr

Re: [PATCH 4/6] dt-bindings: display: sitronix,st7735r: Add initialization properties

2021-12-01 Thread Rob Herring
On Wed, Nov 24, 2021 at 04:07:55PM +0100, Noralf Trønnes wrote:
> Add initialization properties that are commonly used to initialize the
> controller for a specific display panel. It is common for displays to have
> a datasheet listing the necessary controller settings or some example code
> doing the same. These settings can be matched directly to the DT
> properties.
> 
> The commands FRMCTR2, FRMCTR3, PWCTR4 and PWCTR5 are usually part of the
> setup examples but they are skipped here since they deal with partial and
> idle mode which are powersaving modes for very special use cases.
> 
> dc-gpios is made optional because its absence indicates 3-line mode.
> 
> Signed-off-by: Noralf Trønnes 
> ---
>  .../bindings/display/sitronix,st7735r.yaml| 118 +-
>  1 file changed, 116 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/display/sitronix,st7735r.yaml 
> b/Documentation/devicetree/bindings/display/sitronix,st7735r.yaml
> index 157b1a7b18f9..2db1cfe6ae30 100644
> --- a/Documentation/devicetree/bindings/display/sitronix,st7735r.yaml
> +++ b/Documentation/devicetree/bindings/display/sitronix,st7735r.yaml
> @@ -19,6 +19,10 @@ allOf:
>  properties:
>compatible:
>  oneOf:
> +  - description:
> +  Sitronix ST7735R 262K Color Single-Chip TFT Controller/Driver
> +items:
> +  - const: sitronix,st7735r
>- description:
>Adafruit 1.8" 160x128 Color TFT LCD (Product ID 358 or 618)
>  items:
> @@ -32,20 +36,99 @@ properties:
>- okaya,rh128128t
>- const: sitronix,st7715r
>  
> +  width:
> +description:
> +  Width of display panel in pixels
> +
> +  height:
> +description:
> +  Height of display panel in pixels


We already have width-mm and height-mm for physical size so this might 
be a bit confusing. There's also panel-timing 'vactive' and 'hactive' 
which is effectively the same thing you are defining.

> +
> +  frmctr1:

Are all these standardized by MIPI or otherwise common? If not, they 
need vendor prefixes.

> +$ref: /schemas/types.yaml#definitions/uint8-array
> +description:
> +  Frame Rate Control (In normal mode/Full colors) (B1h)
> +minItems: 3
> +maxItems: 3
> +
> +  invctr:
> +$ref: /schemas/types.yaml#definitions/uint8-array
> +description:
> +  Display Inversion Control (B4h)
> +minItems: 1
> +maxItems: 1
> +
> +  pwctr1:
> +$ref: /schemas/types.yaml#definitions/uint8-array
> +description:
> +  Power Control 1 (C0h)
> +minItems: 3
> +maxItems: 3
> +
> +  pwctr2:
> +$ref: /schemas/types.yaml#definitions/uint8-array
> +description:
> +  Power Control 2 (C1h)
> +minItems: 1
> +maxItems: 1
> +
> +  pwctr3:
> +$ref: /schemas/types.yaml#definitions/uint8-array
> +description:
> +  Power Control 3 (in Normal mode/Full colors) (C2h)
> +minItems: 2
> +maxItems: 2
> +
> +  vmctr1:
> +$ref: /schemas/types.yaml#definitions/uint8-array
> +description:
> +  VCOM Control 1 (C5h)
> +minItems: 1
> +maxItems: 1
> +
> +  madctl:
> +$ref: /schemas/types.yaml#definitions/uint8-array
> +description:
> +  Memory Data Access Control (36h)
> +minItems: 1
> +maxItems: 1
> +
> +  gamctrp1:
> +$ref: /schemas/types.yaml#definitions/uint8-array
> +description:
> +  Gamma Positive Polarity Correction Characteristics Setting (E0h)
> +minItems: 16
> +maxItems: 16
> +
> +  gamctrn1:
> +$ref: /schemas/types.yaml#definitions/uint8-array
> +description:
> +  Gamma Negative Polarity Correction Characteristics Setting (E1h)
> +minItems: 16
> +maxItems: 16
> +
> +  write-only:
> +type: boolean
> +description:
> +  Controller is not readable (ie. MISO is not wired up).
> +
>dc-gpios:
>  maxItems: 1
> -description: Display data/command selection (D/CX)
> +description: |
> +  Controller data/command selection (D/CX) in 4-line SPI mode.
> +  If not set, the controller is in 3-line SPI mode.
>  
>backlight: true
>reg: true
>spi-max-frequency: true
>reset-gpios: true
>rotation: true
> +  width-mm: true
> +  height-mm: true
>  
>  required:
>- compatible
>- reg
> -  - dc-gpios
>  
>  additionalProperties: false
>  
> @@ -72,5 +155,36 @@ examples:
>  backlight = <&backlight>;
>  };
>  };
> +  - |
> +#include 
> +
> +spi {
> +#address-cells = <1>;
> +#size-cells = <0>;
> +
> +sainsmart18@0{
> +compatible = "sitronix,st7735r";
> +reg = <0>;
> +spi-max-frequency = <4000>;
> +
> +width = <160>;
> +height = <128>;
> +
> +frmctr1 = [ 01 2C 2D ];
> +invctr = [ 07 ];
> +pwctr1 = [ A2 02 84 ];
> +pwctr2 

Re: [PATCH v3 2/2] drm: rcar-du: Add R-Car DSI driver

2021-12-01 Thread Laurent Pinchart
Hi Kieran,

On Wed, Dec 01, 2021 at 10:40:07AM +, Kieran Bingham wrote:
> Quoting Laurent Pinchart (2021-12-01 05:24:06)
> > From: LUU HOAI 
> > 
> > The driver supports the MIPI DSI/CSI-2 TX encoder found in the R-Car V3U
> > SoC. It currently supports DSI mode only.
> > 
> > Signed-off-by: LUU HOAI 
> > Signed-off-by: Laurent Pinchart 
> > Reviewed-by: Kieran Bingham 
> > Tested-by: Kieran Bingham 
> 
> And as there have been some changes to the probe / bridge handling:
> 
> (Re)Tested-by: Kieran Bingham 

I'm afraid I've posted a v3.1 that needs testing too :-)

> > Acked-by: Sam Ravnborg 
> > ---
> > Changes since v2:
> > 
> > - Support probing of child DSI devices
> > - Use devm_drm_of_get_bridge() helper
> > 
> > Changes since v1:
> > 
> > - Use U suffix for unsigned constants
> > - Fix indentation in Makefile
> > - Select DRM_MIPI_DSI
> > - Report correct fout frequency in debug message
> > - Move dsi_setup_info.err to local variable
> > ---
> >  drivers/gpu/drm/rcar-du/Kconfig  |   7 +
> >  drivers/gpu/drm/rcar-du/Makefile |   1 +
> >  drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c  | 817 +++
> >  drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h | 172 
> >  4 files changed, 997 insertions(+)
> >  create mode 100644 drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c
> >  create mode 100644 drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h
> > 
> > diff --git a/drivers/gpu/drm/rcar-du/Kconfig 
> > b/drivers/gpu/drm/rcar-du/Kconfig
> > index 3e588ddba245..1675df21d91f 100644
> > --- a/drivers/gpu/drm/rcar-du/Kconfig
> > +++ b/drivers/gpu/drm/rcar-du/Kconfig
> > @@ -45,6 +45,13 @@ config DRM_RCAR_LVDS
> > select OF_FLATTREE
> > select OF_OVERLAY
> >  
> > +config DRM_RCAR_MIPI_DSI
> > +   tristate "R-Car DU MIPI DSI Encoder Support"
> > +   depends on DRM && DRM_BRIDGE && OF
> > +   select DRM_MIPI_DSI
> > +   help
> > + Enable support for the R-Car Display Unit embedded MIPI DSI 
> > encoders.
> > +
> >  config DRM_RCAR_VSP
> > bool "R-Car DU VSP Compositor Support" if ARM
> > default y if ARM64
> > diff --git a/drivers/gpu/drm/rcar-du/Makefile 
> > b/drivers/gpu/drm/rcar-du/Makefile
> > index 4d1187ccc3e5..286bc81b3e7c 100644
> > --- a/drivers/gpu/drm/rcar-du/Makefile
> > +++ b/drivers/gpu/drm/rcar-du/Makefile
> > @@ -19,6 +19,7 @@ obj-$(CONFIG_DRM_RCAR_CMM)+= rcar_cmm.o
> >  obj-$(CONFIG_DRM_RCAR_DU)  += rcar-du-drm.o
> >  obj-$(CONFIG_DRM_RCAR_DW_HDMI) += rcar_dw_hdmi.o
> >  obj-$(CONFIG_DRM_RCAR_LVDS)+= rcar_lvds.o
> > +obj-$(CONFIG_DRM_RCAR_MIPI_DSI)+= rcar_mipi_dsi.o
> >  
> >  # 'remote-endpoint' is fixed up at run-time
> >  DTC_FLAGS_rcar_du_of_lvds_r8a7790 += -Wno-graph_endpoint
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c 
> > b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c
> > new file mode 100644
> > index ..fcaec3308d68
> > --- /dev/null
> > +++ b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c
> > @@ -0,0 +1,817 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * rcar_mipi_dsi.c  --  R-Car MIPI DSI Encoder
> > + *
> > + * Copyright (C) 2020 Renesas Electronics Corporation
> > + */
> > +
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +
> > +#include "rcar_mipi_dsi_regs.h"
> > +
> > +struct rcar_mipi_dsi {
> > +   struct device *dev;
> > +   const struct rcar_mipi_dsi_device_info *info;
> > +   struct reset_control *rstc;
> > +
> > +   struct mipi_dsi_host host;
> > +   struct drm_bridge bridge;
> > +   struct drm_bridge *next_bridge;
> > +   struct drm_connector connector;
> > +
> > +   void __iomem *mmio;
> > +   struct {
> > +   struct clk *mod;
> > +   struct clk *pll;
> > +   struct clk *dsi;
> > +   } clocks;
> > +
> > +   struct drm_display_mode display_mode;
> > +   enum mipi_dsi_pixel_format format;
> > +   unsigned int num_data_lanes;
> > +   unsigned int lanes;
> > +};
> > +
> > +static inline struct rcar_mipi_dsi *
> > +bridge_to_rcar_mipi_dsi(struct drm_bridge *bridge)
> > +{
> > +   return container_of(bridge, struct rcar_mipi_dsi, bridge);
> > +}
> > +
> > +static inline struct rcar_mipi_dsi *
> > +host_to_rcar_mipi_dsi(struct mipi_dsi_host *host)
> > +{
> > +   return container_of(host, struct rcar_mipi_dsi, host);
> > +}
> > +
> > +static const u32 phtw[] = {
> > +   0x01020114, 0x01600115, /* General testing */
> > +   0x01030116, 0x0102011d, /* General testing */
> > +   0x011101a4, 0x018601a4, /* 1Gbps testing */
> > +   0x014201a0, 0x010001a3, /* 1Gbps testing */
> > +   0x0101011f, /* 1Gbps testing */
> > +};
> > +
> > +static const u32 phtw2[] = {
> > +

[PATCH v3.1 2/2] drm: rcar-du: Add R-Car DSI driver

2021-12-01 Thread Laurent Pinchart
From: LUU HOAI 

The driver supports the MIPI DSI/CSI-2 TX encoder found in the R-Car V3U
SoC. It currently supports DSI mode only.

Signed-off-by: LUU HOAI 
Signed-off-by: Laurent Pinchart 
Reviewed-by: Kieran Bingham 
Tested-by: Kieran Bingham 
Acked-by: Sam Ravnborg 
---
Changes since v3:

- Use bridge atomic ops

Changes since v2:

- Support probing of child DSI devices
- Use devm_drm_of_get_bridge() helper

Changes since v1:

- Use U suffix for unsigned constants
- Fix indentation in Makefile
- Select DRM_MIPI_DSI
- Report correct fout frequency in debug message
- Move dsi_setup_info.err to local variable
---
 drivers/gpu/drm/rcar-du/Kconfig  |   7 +
 drivers/gpu/drm/rcar-du/Makefile |   1 +
 drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c  | 820 +++
 drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h | 172 
 4 files changed, 1000 insertions(+)
 create mode 100644 drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c
 create mode 100644 drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h

diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
index 3e588ddba245..1675df21d91f 100644
--- a/drivers/gpu/drm/rcar-du/Kconfig
+++ b/drivers/gpu/drm/rcar-du/Kconfig
@@ -45,6 +45,13 @@ config DRM_RCAR_LVDS
select OF_FLATTREE
select OF_OVERLAY
 
+config DRM_RCAR_MIPI_DSI
+   tristate "R-Car DU MIPI DSI Encoder Support"
+   depends on DRM && DRM_BRIDGE && OF
+   select DRM_MIPI_DSI
+   help
+ Enable support for the R-Car Display Unit embedded MIPI DSI encoders.
+
 config DRM_RCAR_VSP
bool "R-Car DU VSP Compositor Support" if ARM
default y if ARM64
diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile
index 4d1187ccc3e5..286bc81b3e7c 100644
--- a/drivers/gpu/drm/rcar-du/Makefile
+++ b/drivers/gpu/drm/rcar-du/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_DRM_RCAR_CMM)+= rcar_cmm.o
 obj-$(CONFIG_DRM_RCAR_DU)  += rcar-du-drm.o
 obj-$(CONFIG_DRM_RCAR_DW_HDMI) += rcar_dw_hdmi.o
 obj-$(CONFIG_DRM_RCAR_LVDS)+= rcar_lvds.o
+obj-$(CONFIG_DRM_RCAR_MIPI_DSI)+= rcar_mipi_dsi.o
 
 # 'remote-endpoint' is fixed up at run-time
 DTC_FLAGS_rcar_du_of_lvds_r8a7790 += -Wno-graph_endpoint
diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c 
b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c
new file mode 100644
index ..faf993eae564
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c
@@ -0,0 +1,820 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * rcar_mipi_dsi.c  --  R-Car MIPI DSI Encoder
+ *
+ * Copyright (C) 2020 Renesas Electronics Corporation
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "rcar_mipi_dsi_regs.h"
+
+struct rcar_mipi_dsi {
+   struct device *dev;
+   const struct rcar_mipi_dsi_device_info *info;
+   struct reset_control *rstc;
+
+   struct mipi_dsi_host host;
+   struct drm_bridge bridge;
+   struct drm_bridge *next_bridge;
+   struct drm_connector connector;
+
+   void __iomem *mmio;
+   struct {
+   struct clk *mod;
+   struct clk *pll;
+   struct clk *dsi;
+   } clocks;
+
+   enum mipi_dsi_pixel_format format;
+   unsigned int num_data_lanes;
+   unsigned int lanes;
+};
+
+static inline struct rcar_mipi_dsi *
+bridge_to_rcar_mipi_dsi(struct drm_bridge *bridge)
+{
+   return container_of(bridge, struct rcar_mipi_dsi, bridge);
+}
+
+static inline struct rcar_mipi_dsi *
+host_to_rcar_mipi_dsi(struct mipi_dsi_host *host)
+{
+   return container_of(host, struct rcar_mipi_dsi, host);
+}
+
+static const u32 phtw[] = {
+   0x01020114, 0x01600115, /* General testing */
+   0x01030116, 0x0102011d, /* General testing */
+   0x011101a4, 0x018601a4, /* 1Gbps testing */
+   0x014201a0, 0x010001a3, /* 1Gbps testing */
+   0x0101011f, /* 1Gbps testing */
+};
+
+static const u32 phtw2[] = {
+   0x010c0130, 0x010c0140, /* General testing */
+   0x010c0150, 0x010c0180, /* General testing */
+   0x010c0190,
+   0x010a0160, 0x010a0170,
+   0x01800164, 0x01800174, /* 1Gbps testing */
+};
+
+static const u32 hsfreqrange_table[][2] = {
+   { 8000U,   0x00 }, { 9000U,   0x10 }, { 1U,  0x20 },
+   { 11000U,  0x30 }, { 12000U,  0x01 }, { 13000U,  0x11 },
+   { 14000U,  0x21 }, { 15000U,  0x31 }, { 16000U,  0x02 },
+   { 17000U,  0x12 }, { 18000U,  0x22 }, { 19000U,  0x32 },
+   { 20500U,  0x03 }, { 22000U,  0x13 }, { 23500U,  0x23 },
+   { 25000U,  0x33 }, { 27500U,  0x04 }, { 3U,  0x14 },
+   { 32500U,  0x25 }, { 35000U,  0x35 }, { 4U,  0x05 },
+   { 45000U,  0x16 }, { 5U,  0x26 }, { 55000U,  0x37 },
+  

Re: [PATCH 3/6] dt-bindings: display: sitronix,st7735r: Remove spi-max-frequency limit

2021-12-01 Thread Rob Herring
On Wed, 24 Nov 2021 16:07:54 +0100, Noralf Trønnes wrote:
> The datasheet lists the minimum Serial clock cycle (Write) as 66ns which is
> 15MHz. Mostly it can do much better than that and is in fact often run at
> 32MHz. With a clever driver that runs configuration commands at a low speed
> and only the pixel data at the maximum speed the configuration can't be
> messed up by transfer errors and the speed is only limited by the amount of
> pixel glitches that one is able to tolerate.
> 
> Signed-off-by: Noralf Trønnes 
> ---
>  .../devicetree/bindings/display/sitronix,st7735r.yaml | 4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)
> 

Acked-by: Rob Herring 


Re: [PATCH 2/6] dt-bindings: display: sitronix,st7735r: Make reset-gpios optional

2021-12-01 Thread Rob Herring
On Wed, 24 Nov 2021 16:07:53 +0100, Noralf Trønnes wrote:
> There are other ways than using a gpio to reset the controller so make
> this property optional.
> 
> Signed-off-by: Noralf Trønnes 
> ---
>  Documentation/devicetree/bindings/display/sitronix,st7735r.yaml | 1 -
>  1 file changed, 1 deletion(-)
> 

Acked-by: Rob Herring 


Re: [PATCH 1/6] dt-bindings: display: sitronix,st7735r: Fix backlight in example

2021-12-01 Thread Rob Herring
On Wed, 24 Nov 2021 16:07:52 +0100, Noralf Trønnes wrote:
> The backlight property was lost during conversion to yaml in commit
> abdd9e3705c8 ("dt-bindings: display: sitronix,st7735r: Convert to DT schema").
> Put it back.
> 
> Fixes: abdd9e3705c8 ("dt-bindings: display: sitronix,st7735r: Convert to DT 
> schema")
> Signed-off-by: Noralf Trønnes 
> ---
>  Documentation/devicetree/bindings/display/sitronix,st7735r.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 

Acked-by: Rob Herring 


Re: [PATCH] drm/komeda: Fix an undefined behavior bug in komeda_plane_add()

2021-12-01 Thread Liviu Dudau
On Wed, Dec 01, 2021 at 03:44:03PM +, Steven Price wrote:
> On 30/11/2021 14:25, Zhou Qingyang wrote:
> > In komeda_plane_add(), komeda_get_layer_fourcc_list() is assigned to
> > formats and used in drm_universal_plane_init().
> > drm_universal_plane_init() passes formats to
> > __drm_universal_plane_init(). __drm_universal_plane_init() further
> > passes formats to memcpy() as src parameter, which could lead to an
> > undefined behavior bug on failure of komeda_get_layer_fourcc_list().
> > 
> > Fix this bug by adding a check of formats.
> > 
> > This bug was found by a static analyzer. The analysis employs
> > differential checking to identify inconsistent security operations
> > (e.g., checks or kfrees) between two code paths and confirms that the
> > inconsistent operations are not recovered in the current function or
> > the callers, so they constitute bugs.
> > 
> > Note that, as a bug found by static analysis, it can be a false
> > positive or hard to trigger. Multiple researchers have cross-reviewed
> > the bug.
> > 
> > Builds with CONFIG_DRM_KOMEDA=m show no new warnings,
> > and our static analyzer no longer warns about this code.
> > 
> > Fixes: 61f1c4a8ab75 ("drm/komeda: Attach komeda_dev to DRM-KMS")
> > Signed-off-by: Zhou Qingyang 
> > ---
> >  drivers/gpu/drm/arm/display/komeda/komeda_plane.c | 4 
> >  1 file changed, 4 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c 
> > b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
> > index d63d83800a8a..dd3f17e970dd 100644
> > --- a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
> > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
> > @@ -265,6 +265,10 @@ static int komeda_plane_add(struct komeda_kms_dev *kms,
> >  
> > formats = komeda_get_layer_fourcc_list(&mdev->fmt_tbl,
> >layer->layer_type, &n_formats);
> > +   if (!formats) {
> > +   err = -ENOMEM;
> > +   goto cleanup;
> > +   }
> 
> If this executes it will cause undefined behaviour...
> 
> The cleanup code calls komeda_plane_destroy() which calls
> drm_plane_cleanup() which does (amongst other things) a
> list_del(&plane->head). But the plane hasn't been put on a list yet as
> that's done in drm_universal_plane_init().
> 
> So in this case we simple want to do:
> 
> if (!formats) {
>   kfree(kplane);
>   return -ENOMEM;
> }

Zhou has already posted v2 that contains this fix.

> 
> Note that without this 'fix' a NULL return from
> komeda_get_layer_fourcc_list() would leave n_formats==0, so while the
> NULL pointer is passed into memcpy() it is also passed a length of 0.
> Which I believe is safe.
> 
> However while looking at this function...
> 
> >  
> > err = drm_universal_plane_init(&kms->base, plane,
> > get_possible_crtcs(kms, c->pipeline),
> > 
> 
> This call to drm_universal_plane_init() can fail early before
> plane->head has been initialised. In which case the following:
> 
> > komeda_put_fourcc_list(formats);
> > 
> > if (err)
> > goto cleanup;
> 
> commits the exact same sin and would cause a similar NULL dereference in
> drm_plane_cleanup().

I will come up with a patch for this case and post it to the list tomorrow.

Best regards,
Liviu



> 
> Steve

-- 

| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---
¯\_(ツ)_/¯


[PATCH v2 2/2] staging: fbtft: sh1106: use new macro FBTFT_REGISTER_SPI_DRIVER

2021-12-01 Thread Heiner Kallweit
Make fb_sh1106 the first user of new macro FBTFT_REGISTER_SPI_DRIVER.
In addition the MODULE_ALIASes can be removed. Module auto-loading
was successfully tested with a SH1106-based OLED module connected
to an Odroid C2.

Signed-off-by: Heiner Kallweit 
---
 drivers/staging/fbtft/fb_sh1106.c | 7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/staging/fbtft/fb_sh1106.c 
b/drivers/staging/fbtft/fb_sh1106.c
index 7b9ab39e1..9685ca516 100644
--- a/drivers/staging/fbtft/fb_sh1106.c
+++ b/drivers/staging/fbtft/fb_sh1106.c
@@ -173,12 +173,7 @@ static struct fbtft_display display = {
},
 };
 
-FBTFT_REGISTER_DRIVER(DRVNAME, "sinowealth,sh1106", &display);
-
-MODULE_ALIAS("spi:" DRVNAME);
-MODULE_ALIAS("platform:" DRVNAME);
-MODULE_ALIAS("spi:sh1106");
-MODULE_ALIAS("platform:sh1106");
+FBTFT_REGISTER_SPI_DRIVER(DRVNAME, "sinowealth", "sh1106", &display);
 
 MODULE_DESCRIPTION("SH1106 OLED Driver");
 MODULE_AUTHOR("Heiner Kallweit");
-- 
2.34.1




[PATCH v2 1/2] staging: fbtft: add macro FBTFT_REGISTER_SPI_DRIVER

2021-12-01 Thread Heiner Kallweit
After 5fa6863ba692 ("spi: Check we have a spi_device_id for each DT
compatible") we need to add spi id_tables. Changing existing macro
FBTFT_REGISTER_DRIVER would have meant to change arguments and
therefore adjust all fbtft drivers.

This patch adds a new and simplified macro FBTFT_REGISTER_SPI_DRIVER
that includes a spi id_table, and in addition to that:
- does not define a platform driver
- uses macro module_spi_driver()

Signed-off-by: Heiner Kallweit 
---
 drivers/staging/fbtft/fbtft.h | 41 +++
 1 file changed, 41 insertions(+)

diff --git a/drivers/staging/fbtft/fbtft.h b/drivers/staging/fbtft/fbtft.h
index 6869f3603..4cdec34e2 100644
--- a/drivers/staging/fbtft/fbtft.h
+++ b/drivers/staging/fbtft/fbtft.h
@@ -346,6 +346,47 @@ static void __exit fbtft_driver_module_exit(void)  
\
 module_init(fbtft_driver_module_init); \
 module_exit(fbtft_driver_module_exit);
 
+#define FBTFT_REGISTER_SPI_DRIVER(_name, _comp_vend, _comp_dev, _display)  
\
+   
\
+static int fbtft_driver_probe_spi(struct spi_device *spi)  
\
+{  
\
+   return fbtft_probe_common(_display, spi, NULL); 
\
+}  
\
+   
\
+static int fbtft_driver_remove_spi(struct spi_device *spi) 
\
+{  
\
+   struct fb_info *info = spi_get_drvdata(spi);
\
+   
\
+   fbtft_remove_common(&spi->dev, info);   
\
+   return 0;   
\
+}  
\
+   
\
+static const struct of_device_id dt_ids[] = {  
\
+   { .compatible = _comp_vend "," _comp_dev }, 
\
+   {}, 
\
+}; 
\
+   
\
+MODULE_DEVICE_TABLE(of, dt_ids);   
\
+   
\
+static const struct spi_device_id spi_ids[] = {
\
+   { .name = _comp_dev },  
\
+   {}, 
\
+}; 
\
+   
\
+MODULE_DEVICE_TABLE(spi, spi_ids); 
\
+   
\
+static struct spi_driver fbtft_driver_spi_driver = {   
\
+   .driver = { 
\
+   .name  = _name, 
\
+   .of_match_table = dt_ids,   
\
+   },  
\
+   .id_table = spi_ids,
\
+   .probe  = fbtft_driver_probe_spi,   
\
+   .remove = fbtft_driver_remove_spi,  
\
+}; 
\
+   
\
+module_spi_driver(fbtft_driver_spi_driver);
+
 /* Debug macros */
 
 /* shorthand debug levels */
-- 
2.34.1




[PATCH v2 0/2] staging: fbtft: add and use macro FBTFT_REGISTER_SPI_DRIVER

2021-12-01 Thread Heiner Kallweit
After 5fa6863ba692 ("spi: Check we have a spi_device_id for each DT
compatible") we need to add spi id_tables. Changing existing macro
FBTFT_REGISTER_DRIVER would have meant to change arguments and
therefore adjust all fbtft drivers.

This series adds a new and simplified macro FBTFT_REGISTER_SPI_DRIVER
that includes a spi id_table, and in addition to that:
- does not define a platform driver
- uses macro module_spi_driver()

Also the MODULE_ALIASes can be removed.

Works for me with a SH1106-based OLED display incl. module autoload.
For now I changed this driver only because I have hw to test it.

v2:
- consider that spi id_table name consists of device part of compatible string 
only
- instead of changing the existing macro, add a new one and make fb_sh1106 the 
first user

Heiner Kallweit (2):
  staging: fbtft: add macro FBTFT_REGISTER_SPI_DRIVER
  staging: fbtft: sh1106: use new macro FBTFT_REGISTER_SPI_DRIVER

 drivers/staging/fbtft/fb_sh1106.c |  7 +-
 drivers/staging/fbtft/fbtft.h | 41 +++
 2 files changed, 42 insertions(+), 6 deletions(-)

-- 
2.34.1




Re: [PATCH v4 4/4] drm/msm/dp: dp_link_parse_sink_count() return immediately if aux read failed

2021-12-01 Thread khsieh

On 2021-11-24 23:32, Dmitry Baryshkov wrote:

On 04/05/2021 07:35, Stephen Boyd wrote:

Quoting Kuogee Hsieh (2021-04-21 16:37:38)

Add checking aux read/write status at both dp_link_parse_sink_count()
and dp_link_parse_sink_status_filed() to avoid long timeout delay if


s/filed/field/


dp aux read/write failed at timeout due to cable unplugged.

Changes in V4:
-- split this patch as stand alone patch

Signed-off-by: Kuogee Hsieh 


Can this patch come before the one previously? And then some fixes tag
be added? Otherwise looks good to me.

Reviewed-by: Stephen Boyd 
Tested-by: Stephen Boyd 


Is this something that we still need to pursue/merge?

There were changes requested for this and for the previous patch, but
no new versions were posted.


It is my fault to miss this one.
The first two patches of this serial are merged.
I will rebase and re submit this one to V5.10.




[PATCH] drm/msm: Initialize MDSS irq domain at probe time

2021-12-01 Thread Dmitry Baryshkov
Since commit 8f59ee9a570c ("drm/msm/dsi: Adjust probe order"), the
DSI host gets initialized earlier, but this caused unability to probe
the entire stack of components because they all depend on interrupts
coming from the main `mdss` node (mdp5, or dpu1).

To fix this issue, move mdss device initialization (which include irq
domain setup) to msm_mdev_probe() time, as to make sure that the
interrupt controller is available before dsi and/or other components try
to initialize, finally satisfying the dependency.

Fixes: 8f59ee9a570c ("drm/msm/dsi: Adjust probe order")
Co-Developed-By: AngeloGioacchino Del Regno 

Signed-off-by: Dmitry Baryshkov 
---

When checking your patch, I noticed that IRQ domain is created before
respective MDSS clocks are enabled. This does not look like causing any
issues at this time, but it did not look good. So I started moving
clocks parsing to early_init() callbacks. And at some point it looked
like we can drop the init()/destroy() callbacks in favour of
early_init() and remove(). Which promted me to move init()/destroy() in
place of early_init()/remove() with few minor fixes here and there.

---
 drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c  | 25 +-
 drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c | 32 ++---
 drivers/gpu/drm/msm/msm_drv.c | 56 ---
 drivers/gpu/drm/msm/msm_kms.h |  8 ++--
 4 files changed, 59 insertions(+), 62 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
index b466784d9822..131c1f1a869c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
@@ -111,7 +111,7 @@ static int _dpu_mdss_irq_domain_add(struct dpu_mdss 
*dpu_mdss)
struct device *dev;
struct irq_domain *domain;
 
-   dev = dpu_mdss->base.dev->dev;
+   dev = dpu_mdss->base.dev;
 
domain = irq_domain_add_linear(dev->of_node, 32,
&dpu_mdss_irqdomain_ops, dpu_mdss);
@@ -184,16 +184,15 @@ static int dpu_mdss_disable(struct msm_mdss *mdss)
return ret;
 }
 
-static void dpu_mdss_destroy(struct drm_device *dev)
+static void dpu_mdss_destroy(struct msm_mdss *mdss)
 {
-   struct platform_device *pdev = to_platform_device(dev->dev);
-   struct msm_drm_private *priv = dev->dev_private;
-   struct dpu_mdss *dpu_mdss = to_dpu_mdss(priv->mdss);
+   struct platform_device *pdev = to_platform_device(mdss->dev);
+   struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss);
struct dss_module_power *mp = &dpu_mdss->mp;
int irq;
 
-   pm_runtime_suspend(dev->dev);
-   pm_runtime_disable(dev->dev);
+   pm_runtime_suspend(mdss->dev);
+   pm_runtime_disable(mdss->dev);
_dpu_mdss_irq_domain_fini(dpu_mdss);
irq = platform_get_irq(pdev, 0);
irq_set_chained_handler_and_data(irq, NULL, NULL);
@@ -203,7 +202,6 @@ static void dpu_mdss_destroy(struct drm_device *dev)
if (dpu_mdss->mmio)
devm_iounmap(&pdev->dev, dpu_mdss->mmio);
dpu_mdss->mmio = NULL;
-   priv->mdss = NULL;
 }
 
 static const struct msm_mdss_funcs mdss_funcs = {
@@ -212,16 +210,15 @@ static const struct msm_mdss_funcs mdss_funcs = {
.destroy = dpu_mdss_destroy,
 };
 
-int dpu_mdss_init(struct drm_device *dev)
+int dpu_mdss_init(struct platform_device *pdev)
 {
-   struct platform_device *pdev = to_platform_device(dev->dev);
-   struct msm_drm_private *priv = dev->dev_private;
+   struct msm_drm_private *priv = platform_get_drvdata(pdev);
struct dpu_mdss *dpu_mdss;
struct dss_module_power *mp;
int ret;
int irq;
 
-   dpu_mdss = devm_kzalloc(dev->dev, sizeof(*dpu_mdss), GFP_KERNEL);
+   dpu_mdss = devm_kzalloc(&pdev->dev, sizeof(*dpu_mdss), GFP_KERNEL);
if (!dpu_mdss)
return -ENOMEM;
 
@@ -238,7 +235,7 @@ int dpu_mdss_init(struct drm_device *dev)
goto clk_parse_err;
}
 
-   dpu_mdss->base.dev = dev;
+   dpu_mdss->base.dev = &pdev->dev;
dpu_mdss->base.funcs = &mdss_funcs;
 
ret = _dpu_mdss_irq_domain_add(dpu_mdss);
@@ -256,7 +253,7 @@ int dpu_mdss_init(struct drm_device *dev)
 
priv->mdss = &dpu_mdss->base;
 
-   pm_runtime_enable(dev->dev);
+   pm_runtime_enable(&pdev->dev);
 
return 0;
 
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c 
b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c
index c34760d981b8..b3f79c2277e9 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c
@@ -112,7 +112,7 @@ static const struct irq_domain_ops mdss_hw_irqdomain_ops = {
 
 static int mdss_irq_domain_init(struct mdp5_mdss *mdp5_mdss)
 {
-   struct device *dev = mdp5_mdss->base.dev->dev;
+   struct device *dev = mdp5_mdss->base.dev;
struct irq_domain *d;
 
d = irq_domain_add_linear(dev->of_node, 32, &mdss_hw_irqdomain_ops,
@@ -155,7 +155,7 @@ stat

Re: [PATCH] drm/radeon/radeon_connectors: Fix a NULL pointer dereference in radeon_fp_native_mode()

2021-12-01 Thread Alex Deucher
On Tue, Nov 30, 2021 at 9:49 AM Zhou Qingyang  wrote:
>
> In radeon_fp_native_mode(), the return value of drm_mode_duplicate() is
> assigned to mode and there is a dereference of it in
> radeon_fp_native_mode(), which could lead to a NULL pointer
> dereference on failure of drm_mode_duplicate().
>
> Fix this bug by adding a check of mode.
>
> This bug was found by a static analyzer. The analysis employs
> differential checking to identify inconsistent security operations
> (e.g., checks or kfrees) between two code paths and confirms that the
> inconsistent operations are not recovered in the current function or
> the callers, so they constitute bugs.
>
> Note that, as a bug found by static analysis, it can be a false
> positive or hard to trigger. Multiple researchers have cross-reviewed
> the bug.
>
> Builds with CONFIG_DRM_RADEON=m show no new warnings,
> and our static analyzer no longer warns about this code.
>
> Fixes: d2efdf6d6f42 ("drm/radeon/kms: add cvt mode if we only have lvds w/h 
> and no edid (v4)")
> Signed-off-by: Zhou Qingyang 
> ---
>  drivers/gpu/drm/radeon/radeon_connectors.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c 
> b/drivers/gpu/drm/radeon/radeon_connectors.c
> index 607ad5620bd9..49f187614f96 100644
> --- a/drivers/gpu/drm/radeon/radeon_connectors.c
> +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
> @@ -473,6 +473,9 @@ static struct drm_display_mode 
> *radeon_fp_native_mode(struct drm_encoder *encode
> native_mode->vdisplay != 0 &&
> native_mode->clock != 0) {
> mode = drm_mode_duplicate(dev, native_mode);
> +   if (!mode)
> +   return NULL;
> +

The else if clause needs a similar check.  Care to fix that up as well?

Alex

> mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
> drm_mode_set_name(mode);
>
> --
> 2.25.1
>


Re: [PATCH] fix a NULL pointer dereference in amdgpu_connector_lcd_native_mode()

2021-12-01 Thread Alex Deucher
On Tue, Nov 30, 2021 at 6:24 AM Zhou Qingyang  wrote:
>
> In amdgpu_connector_lcd_native_mode(), the return value of
> drm_mode_duplicate() is assigned to mode, and there is a dereference
> of it in amdgpu_connector_lcd_native_mode(), which will lead to a NULL
> pointer dereference on failure of drm_mode_duplicate().
>
> Fix this bug add a check of mode.
>
> This bug was found by a static analyzer. The analysis employs
> differential checking to identify inconsistent security operations
> (e.g., checks or kfrees) between two code paths and confirms that the
> inconsistent operations are not recovered in the current function or
> the callers, so they constitute bugs.
>
> Note that, as a bug found by static analysis, it can be a false
> positive or hard to trigger. Multiple researchers have cross-reviewed
> the bug.
>
> Builds with CONFIG_DRM_AMDGPU=m show no new warnings, and
> our static analyzer no longer warns about this code.
>
> Fixes: d38ceaf99ed0 ("drm/amdgpu: add core driver (v4)")
> Signed-off-by: Zhou Qingyang 
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
> index 0de66f59adb8..0170aa84c5e6 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
> @@ -387,6 +387,9 @@ amdgpu_connector_lcd_native_mode(struct drm_encoder 
> *encoder)
> native_mode->vdisplay != 0 &&
> native_mode->clock != 0) {
> mode = drm_mode_duplicate(dev, native_mode);
> +   if (!mode)
> +   return NULL;
> +

The else if clause needs a similar check.  Care to fix that up as well?

Alex

> mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
> drm_mode_set_name(mode);
>
> --
> 2.25.1
>


Re: [PATCH v2 2/3] drm/etnaviv: add pci device driver support

2021-12-01 Thread Lucas Stach
Hi Sui,

Am Mittwoch, dem 01.12.2021 um 19:35 +0800 schrieb Sui Jingfeng:
> From: suijingfeng 
> 
>   v2: update commits and provide more material.
> 
>   There is a Vivante GC1000 V5037 in LS2K1000 and LS7A1000,
>   the gpu in those chip is a PCI device not platform one.
>   This GPU have 2D and 3D in the same core, so component
>   framework can be avoid, in fact we find it is diffcult to
>   use it with a pci device driver.
> 
>   Therefore, this patch try to provide PCI device driver wrapper
>   for it by mimic the platform counterpart.
> 
>   LS7A1000 is a bridge chip, brief user manual can be read on line
>   form[1]. This bridge chip typically use with LS3A4000 (4 core 1.8gHz,
>   Mips64r5) and LS3A5000 (4 core loongarch 2.5Ghz)[2].
> 
>   While LS2K1000[3] is a double core 1.0Ghz Mips64r2 SoC.
> 
>   Loongson CPU's cache coherency is maintained by the hardware,
>   this is tramendous difference from other Mips or ARM, as the
>   cohercecy problems can be ignored when using cached coherent
>   BOs.
> 
>   On the other hand, current Mips kernel's writecombine support
>   is not being implemented correctly under the hardware maintained
>   cache coherency framework. At lease this is true for loongson's cpu.

Can you please explain in some more detail what is the issue with
writecombined memory on your platform? I'm asking because we use WC not
just to get around missing hardware cache coherence on other platforms,
but also for performance reasons. Graphics buffers can be quite huge
and in a lot of cases it makes no sense to cache them on the CPU side
an sacrifice other valuable cached data for it. WC allows us to
efficiently write graphics buffers without polluting the cache.

Is the coherency issue that you don't have a proper way to invalidate
the cached alias? Do you hit speculatively loaded cache lines even if
you access the writecombined alias?

Regards,
Lucas

> 
>   In other words, ETNA_BO_WC is NOT usable on our platform, it suffer
>   from cache coherency problem. Howerver use ETNA_BO_CACHED_COHERENT
>   instead of ETNA_BO_WC, etnaviv driver works well on our platform.
> 
>   Both LS7A1000 and LS2K1000 have a display controller integrated,
>   named lsdc. By using KMS-RO framework, lsdc and gc1000 made a
>   compatible pair.
> 
>   I have write xf86-video-loongson[4] DDX driver which make etnaviv works
>   with lsdc on our custom debian and fedora, glmark2-es2 and glxgears
>   can be hardware accelerated under X11 environment. (Mesa-18.3.6 and
>   Mesa-18.05 are tested and it works)
> 
>   See https://github.com/suijingfeng/xf86-video-loongson.
> 
> [1] 
> https://loongson.github.io/LoongArch-Documentation/Loongson-7A1000-usermanual-EN.html
> [2] 
> https://loongson.github.io/LoongArch-Documentation/Loongson-3A5000-usermanual-EN.html
> [3] https://wiki.debian.org/InstallingDebianOn/Lemote/Loongson2K1000
> 
> Signed-off-by: suijingfeng 
> Signed-off-by: Sui Jingfeng <15330273...@189.cn>
> ---
>  drivers/gpu/drm/etnaviv/Kconfig   |  12 ++
>  drivers/gpu/drm/etnaviv/Makefile  |   2 +
>  drivers/gpu/drm/etnaviv/etnaviv_drv.c | 113 ---
>  drivers/gpu/drm/etnaviv/etnaviv_drv.h |   8 +
>  drivers/gpu/drm/etnaviv/etnaviv_gem.c |  28 ++-
>  drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 106 +++
>  drivers/gpu/drm/etnaviv/etnaviv_gpu.h |   6 +
>  drivers/gpu/drm/etnaviv/etnaviv_pci_drv.c | 218 ++
>  include/uapi/drm/etnaviv_drm.h|  11 +-
>  9 files changed, 430 insertions(+), 74 deletions(-)
>  create mode 100644 drivers/gpu/drm/etnaviv/etnaviv_pci_drv.c
> 
> diff --git a/drivers/gpu/drm/etnaviv/Kconfig b/drivers/gpu/drm/etnaviv/Kconfig
> index faa7fc68b009..5858eec59025 100644
> --- a/drivers/gpu/drm/etnaviv/Kconfig
> +++ b/drivers/gpu/drm/etnaviv/Kconfig
> @@ -15,6 +15,18 @@ config DRM_ETNAVIV
>   help
> DRM driver for Vivante GPUs.
>  
> +config DRM_ETNAVIV_PCI_DRIVER
> + bool "Enable PCI device driver support"
> + depends on DRM_ETNAVIV
> + depends on PCI
> + depends on MACH_LOONGSON64
> + default y
> + help
> +   DRM PCI driver for the Vivante GPU in LS7A1000 north bridge
> +   and LS2K1000 SoC. The GC1000 in LS2K1000 and LS7A1000 is a
> +   PCI device.
> +   If in doubt, say "n".
> +
>  config DRM_ETNAVIV_THERMAL
>   bool "enable ETNAVIV thermal throttling"
>   depends on DRM_ETNAVIV
> diff --git a/drivers/gpu/drm/etnaviv/Makefile 
> b/drivers/gpu/drm/etnaviv/Makefile
> index 46e5ffad69a6..6829e1ebf2db 100644
> --- a/drivers/gpu/drm/etnaviv/Makefile
> +++ b/drivers/gpu/drm/etnaviv/Makefile
> @@ -16,4 +16,6 @@ etnaviv-y := \
>   etnaviv_perfmon.o \
>   etnaviv_sched.o
>  
> +etnaviv-$(CONFIG_DRM_ETNAVIV_PCI_DRIVER) += etnaviv_pci_drv.o
> +
>  obj-$(CONFIG_DRM_ETNAVIV)+= etnaviv.o
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c 
> b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
> index 7dcc6392792d..dc2bb3a6efe6 100644
> --- a/drivers/gpu/drm/etnaviv/etna

Re: [PATCH v10 4/8] drm/ingenic: Add dw-hdmi driver for jz4780

2021-12-01 Thread Mark Brown
On Wed, Dec 01, 2021 at 05:53:03PM +0100, H. Nikolaus Schaller wrote:
> > Am 01.12.2021 um 16:10 schrieb Mark Brown :

> > Again, if the supply can be physically absent that is a sensible use
> > case but that means completely absent, not just not software
> > controllable.  We can represent fixed voltage regulators just fine.

> The question may be how we can know for a more generic driver that there is 
> always a regulator.
> In the present case we know the schematics but it is just one example.

The datasheet will generally explicitly call out if a supply can be
disconnected.  In general it is astonishingly rare for this to be the
case, supporting that case will tend to make designing the chip harder
(you have to cope with what happens where the power domains meet) and
results in whatever functionality the supplies power not working.  If
not otherwise specified it's safer to assume that the supplies must be
connected.


signature.asc
Description: PGP signature


Re: [PATCH v10 4/8] drm/ingenic: Add dw-hdmi driver for jz4780

2021-12-01 Thread H. Nikolaus Schaller
Hi Mark,


> Am 01.12.2021 um 16:10 schrieb Mark Brown :
> 
> On Wed, Dec 01, 2021 at 03:33:24PM +0100, H. Nikolaus Schaller wrote:
>>> Am 01.12.2021 um 15:03 schrieb Paul Cercueil :
> 
>>> Please make it mandatory in DTS then, and use devm_regulator_get() in the 
>>> driver.
> 
>> Well, I just wonder why the elegant devm_regulator_get_optional() exists at 
>> all
>> and seems to be used in ca. 80 places.
> 
> Frankly because half of them are broken usages like this since people
> seem determined to have the most fragile error handling they can :/

I see. I had made the mistake myself to not check for NULL pointer on
regulator_disable here...

> There are valid use cases for it, with things like SD cards where some
> supplies are genuinely optional and simply constrain what features are
> available if they're omitted from the design.  You also see some devices
> with the ability to replace internal regulators with external ones.
> 
>> And if it is not allowed, why some DTS should be forced to add not 
>> physically existing dummy-regulators.
> 
> Again, if the supply can be physically absent that is a sensible use
> case but that means completely absent, not just not software
> controllable.  We can represent fixed voltage regulators just fine.

The question may be how we can know for a more generic driver that there is 
always a regulator.
In the present case we know the schematics but it is just one example.

> 
>> AFAIR drivers should implement functionality defined by DTS but not the 
>> other way round: enforce DTS style.
>> BTW: there is no +5 mains dummy regulator defined in ci20.dts.
> 
> It wouldn't be the first time a DTS were incomplete, and I'm sure it
> won't be the last.
> 
>> What I fear is that if we always have to define the mains +5V (which is for 
>> example not
>> defined in ci20.dts), which rules stops us from asking to add a 
>> dummy-regulator from 110/230V to +5V as well.
> 
> It is good practice to specify the full tree of supplies all the way to
> the main supply rail of the board, this ensures that if we need the
> information for something we've got it (even if that thing is just that
> we've got to the root of the tree).  There's potential applications in
> battery supplied devices for managing very low power situations.

Indeed. So let's modify it as you have suggested.

BR and thanks,
Nikolaus



[PATCH v4 5/6] drm/amdgpu: move vram inline functions into a header

2021-12-01 Thread Arunpravin
Move shared vram inline functions and structs
into a header file

Signed-off-by: Arunpravin 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h | 51 
 1 file changed, 51 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h
new file mode 100644
index ..59983464cce5
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: MIT
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __AMDGPU_VRAM_MGR_H__
+#define __AMDGPU_VRAM_MGR_H__
+
+#include 
+
+struct amdgpu_vram_mgr_node {
+   struct ttm_resource base;
+   struct list_head blocks;
+   unsigned long flags;
+};
+
+static inline u64 amdgpu_node_start(struct drm_buddy_block *block)
+{
+   return drm_buddy_block_offset(block);
+}
+
+static inline u64 amdgpu_node_size(struct drm_buddy_block *block)
+{
+   return PAGE_SIZE << drm_buddy_block_order(block);
+}
+
+static inline struct amdgpu_vram_mgr_node *
+to_amdgpu_vram_mgr_node(struct ttm_resource *res)
+{
+   return container_of(res, struct amdgpu_vram_mgr_node, base);
+}
+
+#endif
-- 
2.25.1



[PATCH v4 6/6] drm/amdgpu: add drm buddy support to amdgpu

2021-12-01 Thread Arunpravin
- Remove drm_mm references and replace with drm buddy functionalities
- Add res cursor support for drm buddy

v2(Matthew Auld):
  - replace spinlock with mutex as we call kmem_cache_zalloc
(..., GFP_KERNEL) in drm_buddy_alloc() function

  - lock drm_buddy_block_trim() function as it calls
mark_free/mark_split are all globally visible

v3:
  - remove drm_buddy_block_trim() error handling and
print a warn message if it fails

Signed-off-by: Arunpravin 
---
 drivers/gpu/drm/Kconfig   |   1 +
 .../gpu/drm/amd/amdgpu/amdgpu_res_cursor.h|  97 +--
 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h   |   6 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c  | 261 ++
 4 files changed, 232 insertions(+), 133 deletions(-)

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 7a4a66d54782..dd880910282b 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -276,6 +276,7 @@ config DRM_AMDGPU
select HWMON
select BACKLIGHT_CLASS_DEVICE
select INTERVAL_TREE
+   select DRM_BUDDY
help
  Choose this option if you have a recent AMD Radeon graphics card.
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h
index acfa207cf970..da12b4ff2e45 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h
@@ -30,12 +30,15 @@
 #include 
 #include 
 
+#include "amdgpu_vram_mgr.h"
+
 /* state back for walking over vram_mgr and gtt_mgr allocations */
 struct amdgpu_res_cursor {
uint64_tstart;
uint64_tsize;
uint64_tremaining;
-   struct drm_mm_node  *node;
+   void*node;
+   uint32_tmem_type;
 };
 
 /**
@@ -52,27 +55,63 @@ static inline void amdgpu_res_first(struct ttm_resource 
*res,
uint64_t start, uint64_t size,
struct amdgpu_res_cursor *cur)
 {
+   struct drm_buddy_block *block;
+   struct list_head *head, *next;
struct drm_mm_node *node;
 
-   if (!res || res->mem_type == TTM_PL_SYSTEM) {
-   cur->start = start;
-   cur->size = size;
-   cur->remaining = size;
-   cur->node = NULL;
-   WARN_ON(res && start + size > res->num_pages << PAGE_SHIFT);
-   return;
-   }
+   if (!res)
+   goto err_out;
 
BUG_ON(start + size > res->num_pages << PAGE_SHIFT);
 
-   node = to_ttm_range_mgr_node(res)->mm_nodes;
-   while (start >= node->size << PAGE_SHIFT)
-   start -= node++->size << PAGE_SHIFT;
+   cur->mem_type = res->mem_type;
+
+   switch (cur->mem_type) {
+   case TTM_PL_VRAM:
+   head = &to_amdgpu_vram_mgr_node(res)->blocks;
+
+   block = list_first_entry_or_null(head,
+struct drm_buddy_block,
+link);
+   if (!block)
+   goto err_out;
+
+   while (start >= amdgpu_node_size(block)) {
+   start -= amdgpu_node_size(block);
+
+   next = block->link.next;
+   if (next != head)
+   block = list_entry(next, struct 
drm_buddy_block, link);
+   }
+
+   cur->start = amdgpu_node_start(block) + start;
+   cur->size = min(amdgpu_node_size(block) - start, size);
+   cur->remaining = size;
+   cur->node = block;
+   break;
+   case TTM_PL_TT:
+   node = to_ttm_range_mgr_node(res)->mm_nodes;
+   while (start >= node->size << PAGE_SHIFT)
+   start -= node++->size << PAGE_SHIFT;
+
+   cur->start = (node->start << PAGE_SHIFT) + start;
+   cur->size = min((node->size << PAGE_SHIFT) - start, size);
+   cur->remaining = size;
+   cur->node = node;
+   break;
+   default:
+   goto err_out;
+   }
 
-   cur->start = (node->start << PAGE_SHIFT) + start;
-   cur->size = min((node->size << PAGE_SHIFT) - start, size);
+   return;
+
+err_out:
+   cur->start = start;
+   cur->size = size;
cur->remaining = size;
-   cur->node = node;
+   cur->node = NULL;
+   WARN_ON(res && start + size > res->num_pages << PAGE_SHIFT);
+   return;
 }
 
 /**
@@ -85,7 +124,9 @@ static inline void amdgpu_res_first(struct ttm_resource *res,
  */
 static inline void amdgpu_res_next(struct amdgpu_res_cursor *cur, uint64_t 
size)
 {
-   struct drm_mm_node *node = cur->node;
+   struct drm_buddy_block *block;
+   struct drm_mm_node *node;
+   struct list_head *next;
 
BUG_ON(size > cur->remaining);
 
@@ -99,9 +140

[PATCH v4 4/6] drm: implement a method to free unused pages

2021-12-01 Thread Arunpravin
On contiguous allocation, we round up the size
to the *next* power of 2, implement a function
to free the unused pages after the newly allocate block.

v2(Matthew Auld):
  - replace function name 'drm_buddy_free_unused_pages' with
drm_buddy_block_trim
  - replace input argument name 'actual_size' with 'new_size'
  - add more validation checks for input arguments
  - add overlaps check to avoid needless searching and splitting
  - merged the below patch to see the feature in action
- add free unused pages support to i915 driver
  - lock drm_buddy_block_trim() function as it calls mark_free/mark_split
are all globally visible

v3:
  - remove drm_buddy_block_trim() error handling and
print a warn message if it fails

Signed-off-by: Arunpravin 
---
 drivers/gpu/drm/drm_buddy.c   | 72 ++-
 drivers/gpu/drm/i915/i915_ttm_buddy_manager.c | 10 +++
 include/drm/drm_buddy.h   |  4 ++
 3 files changed, 83 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c
index eddc1eeda02e..707efc82216d 100644
--- a/drivers/gpu/drm/drm_buddy.c
+++ b/drivers/gpu/drm/drm_buddy.c
@@ -434,7 +434,8 @@ alloc_from_freelist(struct drm_buddy_mm *mm,
 static int __alloc_range(struct drm_buddy_mm *mm,
 struct list_head *dfs,
 u64 start, u64 size,
-struct list_head *blocks)
+struct list_head *blocks,
+bool trim_path)
 {
struct drm_buddy_block *block;
struct drm_buddy_block *buddy;
@@ -480,8 +481,20 @@ static int __alloc_range(struct drm_buddy_mm *mm,
 
if (!drm_buddy_block_is_split(block)) {
err = split_block(mm, block);
-   if (unlikely(err))
+   if (unlikely(err)) {
+   if (trim_path)
+   /*
+* Here in case of trim, we return and 
dont goto
+* split failure path as it removes 
from the
+* original list and potentially also 
freeing
+* the block. so we could leave as it 
is,
+* worse case we get some internal 
fragmentation
+* and leave the decision to the user
+*/
+   return err;
+
goto err_undo;
+   }
}
 
list_add(&block->right->tmp_link, dfs);
@@ -535,8 +548,61 @@ static int __drm_buddy_alloc_range(struct drm_buddy_mm *mm,
for (i = 0; i < mm->n_roots; ++i)
list_add_tail(&mm->roots[i]->tmp_link, &dfs);
 
-   return __alloc_range(mm, &dfs, start, size, blocks);
+   return __alloc_range(mm, &dfs, start, size, blocks, 0);
+}
+
+/**
+ * drm_buddy_block_trim - free unused pages
+ *
+ * @mm: DRM buddy manager
+ * @new_size: original size requested
+ * @blocks: output list head to add allocated blocks
+ *
+ * For contiguous allocation, we round up the size to the nearest
+ * power of two value, drivers consume *actual* size, so remaining
+ * portions are unused and it can be freed.
+ *
+ * Returns:
+ * 0 on success, error code on failure.
+ */
+int drm_buddy_block_trim(struct drm_buddy_mm *mm,
+u64 new_size,
+struct list_head *blocks)
+{
+   struct drm_buddy_block *block;
+   u64 new_start;
+   LIST_HEAD(dfs);
+
+   if (!list_is_singular(blocks))
+   return -EINVAL;
+
+   block = list_first_entry(blocks,
+struct drm_buddy_block,
+link);
+
+   if (!drm_buddy_block_is_allocated(block))
+   return -EINVAL;
+
+   if (new_size > drm_buddy_block_size(mm, block))
+   return -EINVAL;
+
+   if (!new_size && !IS_ALIGNED(new_size, mm->chunk_size))
+   return -EINVAL;
+
+   if (new_size == drm_buddy_block_size(mm, block))
+   return 0;
+
+   list_del(&block->link);
+
+   new_start = drm_buddy_block_offset(block);
+
+   mark_free(mm, block);
+
+   list_add(&block->tmp_link, &dfs);
+
+   return __alloc_range(mm, &dfs, new_start, new_size, blocks, 1);
 }
+EXPORT_SYMBOL(drm_buddy_block_trim);
 
 /**
  * drm_buddy_alloc - allocate power-of-two blocks
diff --git a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c 
b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
index 7c58efb60dba..c5831c27fe82 100644
--- a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
+++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
@@ -97,6 +97,16 @@ static int i915_ttm_buddy_man_alloc(struct 
ttm_resource_manager *man,
if (unlikely(err))
   

[PATCH v4 1/6] drm: move the buddy allocator from i915 into common drm

2021-12-01 Thread Arunpravin
Move the base i915 buddy allocator code into drm
- Move i915_buddy.h to include/drm
- Move i915_buddy.c to drm root folder
- Rename "i915" string with "drm" string wherever applicable
- Rename "I915" string with "DRM" string wherever applicable
- Fix header file dependencies
- Fix alignment issues
- add Makefile support for drm buddy
- export functions and write kerneldoc description
- Remove i915 selftest config check condition as buddy selftest
  will be moved to drm selftest folder

cleanup i915 buddy references in i915 driver module
and replace with drm buddy

v2:
  - include header file in alphabetical order(Thomas)
  - merged changes listed in the body section into a single patch
to keep the build intact(Christian, Jani)

v3:
  - make drm buddy a separate module(Thomas, Christian)

Signed-off-by: Arunpravin 
---
 drivers/gpu/drm/Kconfig   |   6 +
 drivers/gpu/drm/Makefile  |   2 +
 drivers/gpu/drm/drm_buddy.c   | 516 ++
 drivers/gpu/drm/i915/Kconfig  |   1 +
 drivers/gpu/drm/i915/Makefile |   1 -
 drivers/gpu/drm/i915/i915_buddy.c | 466 
 drivers/gpu/drm/i915/i915_buddy.h | 143 -
 drivers/gpu/drm/i915/i915_module.c|   3 -
 drivers/gpu/drm/i915/i915_scatterlist.c   |  11 +-
 drivers/gpu/drm/i915/i915_ttm_buddy_manager.c |  33 +-
 drivers/gpu/drm/i915/i915_ttm_buddy_manager.h |   4 +-
 include/drm/drm_buddy.h   | 154 ++
 12 files changed, 703 insertions(+), 637 deletions(-)
 create mode 100644 drivers/gpu/drm/drm_buddy.c
 delete mode 100644 drivers/gpu/drm/i915/i915_buddy.c
 delete mode 100644 drivers/gpu/drm/i915/i915_buddy.h
 create mode 100644 include/drm/drm_buddy.h

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 0039df26854b..7a4a66d54782 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -197,6 +197,12 @@ config DRM_TTM
  GPU memory types. Will be enabled automatically if a device driver
  uses it.
 
+config DRM_BUDDY
+   tristate
+   depends on DRM
+   help
+ A page based buddy allocator
+
 config DRM_VRAM_HELPER
tristate
depends on DRM
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 0dff40bb863c..e62e432bf1e5 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -35,6 +35,8 @@ drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
 
 obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.o
 
+obj-$(CONFIG_DRM_BUDDY) += drm_buddy.o
+
 drm_vram_helper-y := drm_gem_vram_helper.o
 obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o
 
diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c
new file mode 100644
index ..9340a4b61c5a
--- /dev/null
+++ b/drivers/gpu/drm/drm_buddy.c
@@ -0,0 +1,516 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+
+static struct drm_buddy_block *drm_block_alloc(struct drm_buddy_mm *mm,
+  struct drm_buddy_block *parent,
+  unsigned int order,
+  u64 offset)
+{
+   struct drm_buddy_block *block;
+
+   BUG_ON(order > DRM_BUDDY_MAX_ORDER);
+
+   block = kmem_cache_zalloc(mm->slab_blocks, GFP_KERNEL);
+   if (!block)
+   return NULL;
+
+   block->header = offset;
+   block->header |= order;
+   block->parent = parent;
+
+   BUG_ON(block->header & DRM_BUDDY_HEADER_UNUSED);
+   return block;
+}
+
+static void drm_block_free(struct drm_buddy_mm *mm,
+  struct drm_buddy_block *block)
+{
+   kmem_cache_free(mm->slab_blocks, block);
+}
+
+static void mark_allocated(struct drm_buddy_block *block)
+{
+   block->header &= ~DRM_BUDDY_HEADER_STATE;
+   block->header |= DRM_BUDDY_ALLOCATED;
+
+   list_del(&block->link);
+}
+
+static void mark_free(struct drm_buddy_mm *mm,
+ struct drm_buddy_block *block)
+{
+   block->header &= ~DRM_BUDDY_HEADER_STATE;
+   block->header |= DRM_BUDDY_FREE;
+
+   list_add(&block->link,
+&mm->free_list[drm_buddy_block_order(block)]);
+}
+
+static void mark_split(struct drm_buddy_block *block)
+{
+   block->header &= ~DRM_BUDDY_HEADER_STATE;
+   block->header |= DRM_BUDDY_SPLIT;
+
+   list_del(&block->link);
+}
+
+/**
+ * drm_buddy_init - init memory manager
+ *
+ * @mm: DRM buddy manager to initialize
+ * @size: size in bytes to manage
+ * @chunk_size: minimum page size in bytes for our allocations
+ *
+ * Initializes the memory manager and its resources.
+ *
+ * Returns:
+ * 0 on success, error code on failure.
+ */
+int drm_buddy_init(struct drm_buddy_mm *mm, u64 size, u64 chunk_size)
+{
+   unsigned int i;
+   u64 offset;
+
+   if (size < chunk_si

[PATCH v4 3/6] drm: implement top-down allocation method

2021-12-01 Thread Arunpravin
Implemented a function which walk through the order list,
compares the offset and returns the maximum offset block,
this method is unpredictable in obtaining the high range
address blocks which depends on allocation and deallocation.
for instance, if driver requests address at a low specific
range, allocator traverses from the root block and splits
the larger blocks until it reaches the specific block and
in the process of splitting, lower orders in the freelist
are occupied with low range address blocks and for the
subsequent TOPDOWN memory request we may return the low
range blocks.To overcome this issue, we may go with the
below approach.

The other approach, sorting each order list entries in
ascending order and compares the last entry of each
order list in the freelist and return the max block.
This creates sorting overhead on every drm_buddy_free()
request and split up of larger blocks for a single page
request.

v2:
  - Fix alignment issues(Matthew Auld)
  - Remove unnecessary list_empty check(Matthew Auld)
  - merged the below patch to see the feature in action
- add top-down alloc support to i915 driver

Signed-off-by: Arunpravin 
---
 drivers/gpu/drm/drm_buddy.c   | 36 ---
 drivers/gpu/drm/i915/i915_ttm_buddy_manager.c |  3 ++
 include/drm/drm_buddy.h   |  1 +
 3 files changed, 35 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c
index 7f47632821f4..eddc1eeda02e 100644
--- a/drivers/gpu/drm/drm_buddy.c
+++ b/drivers/gpu/drm/drm_buddy.c
@@ -367,6 +367,26 @@ alloc_range_bias(struct drm_buddy_mm *mm,
return ERR_PTR(err);
 }
 
+static struct drm_buddy_block *
+get_maxblock(struct list_head *head)
+{
+   struct drm_buddy_block *max_block = NULL, *node;
+
+   max_block = list_first_entry_or_null(head,
+struct drm_buddy_block,
+link);
+   if (!max_block)
+   return NULL;
+
+   list_for_each_entry(node, head, link) {
+   if (drm_buddy_block_offset(node) >
+   drm_buddy_block_offset(max_block))
+   max_block = node;
+   }
+
+   return max_block;
+}
+
 static struct drm_buddy_block *
 alloc_from_freelist(struct drm_buddy_mm *mm,
unsigned int order,
@@ -377,11 +397,17 @@ alloc_from_freelist(struct drm_buddy_mm *mm,
int err;
 
for (i = order; i <= mm->max_order; ++i) {
-   block = list_first_entry_or_null(&mm->free_list[i],
-struct drm_buddy_block,
-link);
-   if (block)
-   break;
+   if (flags & DRM_BUDDY_TOPDOWN_ALLOCATION) {
+   block = get_maxblock(&mm->free_list[i]);
+   if (block)
+   break;
+   } else {
+   block = list_first_entry_or_null(&mm->free_list[i],
+struct drm_buddy_block,
+link);
+   if (block)
+   break;
+   }
}
 
if (!block)
diff --git a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c 
b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
index 7621d42155e6..7c58efb60dba 100644
--- a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
+++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
@@ -53,6 +53,9 @@ static int i915_ttm_buddy_man_alloc(struct 
ttm_resource_manager *man,
INIT_LIST_HEAD(&bman_res->blocks);
bman_res->mm = mm;
 
+   if (place->flags & TTM_PL_FLAG_TOPDOWN)
+   bman_res->flags |= DRM_BUDDY_TOPDOWN_ALLOCATION;
+
if (place->fpfn || lpfn != man->size)
bman_res->flags |= DRM_BUDDY_RANGE_ALLOCATION;
 
diff --git a/include/drm/drm_buddy.h b/include/drm/drm_buddy.h
index 221de702e909..316ac0d25f08 100644
--- a/include/drm/drm_buddy.h
+++ b/include/drm/drm_buddy.h
@@ -28,6 +28,7 @@
 })
 
 #define DRM_BUDDY_RANGE_ALLOCATION (1 << 0)
+#define DRM_BUDDY_TOPDOWN_ALLOCATION (1 << 1)
 
 struct drm_buddy_block {
 #define DRM_BUDDY_HEADER_OFFSET GENMASK_ULL(63, 12)
-- 
2.25.1



[PATCH v4 2/6] drm: improve drm_buddy_alloc function

2021-12-01 Thread Arunpravin
- Make drm_buddy_alloc a single function to handle
  range allocation and non-range allocation demands

- Implemented a new function alloc_range() which allocates
  the requested power-of-two block comply with range limitations

- Moved order computation and memory alignment logic from
  i915 driver to drm buddy

v2:
  merged below changes to keep the build unbroken
   - drm_buddy_alloc_range() becomes obsolete and may be removed
   - enable ttm range allocation (fpfn / lpfn) support in i915 driver
   - apply enhanced drm_buddy_alloc() function to i915 driver

v3(Matthew Auld):
  - Fix alignment issues and remove unnecessary list_empty check
  - add more validation checks for input arguments
  - make alloc_range() block allocations as bottom-up
  - optimize order computation logic
  - replace uint64_t with u64, which is preferred in the kernel

v4(Matthew Auld):
  - keep drm_buddy_alloc_range() function implementation for generic
actual range allocations
  - keep alloc_range() implementation for end bias allocations

Signed-off-by: Arunpravin 
---
 drivers/gpu/drm/drm_buddy.c   | 316 +-
 drivers/gpu/drm/i915/i915_ttm_buddy_manager.c |  67 ++--
 drivers/gpu/drm/i915/i915_ttm_buddy_manager.h |   2 +
 include/drm/drm_buddy.h   |  22 +-
 4 files changed, 285 insertions(+), 122 deletions(-)

diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c
index 9340a4b61c5a..7f47632821f4 100644
--- a/drivers/gpu/drm/drm_buddy.c
+++ b/drivers/gpu/drm/drm_buddy.c
@@ -280,23 +280,97 @@ void drm_buddy_free_list(struct drm_buddy_mm *mm, struct 
list_head *objects)
 }
 EXPORT_SYMBOL(drm_buddy_free_list);
 
-/**
- * drm_buddy_alloc - allocate power-of-two blocks
- *
- * @mm: DRM buddy manager to allocate from
- * @order: size of the allocation
- *
- * The order value here translates to:
- *
- * 0 = 2^0 * mm->chunk_size
- * 1 = 2^1 * mm->chunk_size
- * 2 = 2^2 * mm->chunk_size
- *
- * Returns:
- * allocated ptr to the &drm_buddy_block on success
- */
-struct drm_buddy_block *
-drm_buddy_alloc(struct drm_buddy_mm *mm, unsigned int order)
+static inline bool overlaps(u64 s1, u64 e1, u64 s2, u64 e2)
+{
+   return s1 <= e2 && e1 >= s2;
+}
+
+static inline bool contains(u64 s1, u64 e1, u64 s2, u64 e2)
+{
+   return s1 <= s2 && e1 >= e2;
+}
+
+static struct drm_buddy_block *
+alloc_range_bias(struct drm_buddy_mm *mm,
+u64 start, u64 end,
+unsigned int order)
+{
+   struct drm_buddy_block *block;
+   struct drm_buddy_block *buddy;
+   LIST_HEAD(dfs);
+   int err;
+   int i;
+
+   end = end - 1;
+
+   for (i = 0; i < mm->n_roots; ++i)
+   list_add_tail(&mm->roots[i]->tmp_link, &dfs);
+
+   do {
+   u64 block_start;
+   u64 block_end;
+
+   block = list_first_entry_or_null(&dfs,
+struct drm_buddy_block,
+tmp_link);
+   if (!block)
+   break;
+
+   list_del(&block->tmp_link);
+
+   if (drm_buddy_block_order(block) < order)
+   continue;
+
+   block_start = drm_buddy_block_offset(block);
+   block_end = block_start + drm_buddy_block_size(mm, block) - 1;
+
+   if (!overlaps(start, end, block_start, block_end))
+   continue;
+
+   if (drm_buddy_block_is_allocated(block))
+   continue;
+
+   if (contains(start, end, block_start, block_end) &&
+   order == drm_buddy_block_order(block)) {
+   /*
+* Find the free block within the range.
+*/
+   if (drm_buddy_block_is_free(block))
+   return block;
+
+   continue;
+   }
+
+   if (!drm_buddy_block_is_split(block)) {
+   err = split_block(mm, block);
+   if (unlikely(err))
+   goto err_undo;
+   }
+
+   list_add(&block->right->tmp_link, &dfs);
+   list_add(&block->left->tmp_link, &dfs);
+   } while (1);
+
+   return ERR_PTR(-ENOSPC);
+
+err_undo:
+   /*
+* We really don't want to leave around a bunch of split blocks, since
+* bigger is better, so make sure we merge everything back before we
+* free the allocated blocks.
+*/
+   buddy = get_buddy(block);
+   if (buddy &&
+   (drm_buddy_block_is_free(block) &&
+drm_buddy_block_is_free(buddy)))
+   __drm_buddy_free(mm, block);
+   return ERR_PTR(err);
+}
+
+static struct drm_buddy_block *
+alloc_from_freelist(struct drm_buddy_mm *mm,
+   unsigned int order,
+   unsigned long flags)
 {
struct drm_

Re: [PATCH 09/12] arm64: dts: rockchip: rk356x: Add HDMI nodes

2021-12-01 Thread Sascha Hauer
On Wed, Nov 17, 2021 at 09:13:33AM -0600, Rob Herring wrote:
> On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer  wrote:
> >
> > Add support for the HDMI port found on RK3568.
> >
> > Signed-off-by: Sascha Hauer 
> > ---
> >  arch/arm64/boot/dts/rockchip/rk356x.dtsi | 65 
> >  1 file changed, 65 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi 
> > b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > index 6ebf7c14e096a..53be61a7ce595 100644
> > --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > @@ -472,18 +472,36 @@ vp0: port@0 {
> > #address-cells = <1>;
> > #size-cells = <0>;
> > reg = <0>;
> > +
> > +   vp0_out_hdmi: endpoint@0 {
> > +   reg = <0>;
> > +   remote-endpoint = <&hdmi_in_vp0>;
> > +   status = "disabled";
> > +   };
> > };
> >
> > vp1: port@1 {
> > #address-cells = <1>;
> > #size-cells = <0>;
> > reg = <1>;
> > +
> > +   vp1_out_hdmi: endpoint@0 {
> > +   reg = <0>;
> > +   remote-endpoint = <&hdmi_in_vp1>;
> > +   status = "disabled";
> > +   };
> > };
> >
> > vp2: port@2 {
> > #address-cells = <1>;
> > #size-cells = <0>;
> > reg = <2>;
> > +
> > +   vp2_out_hdmi: endpoint@0 {
> > +   reg = <0>;
> > +   remote-endpoint = <&hdmi_in_vp2>;
> > +   status = "disabled";
> > +   };
> > };
> > };
> > };
> > @@ -499,6 +517,53 @@ vop_mmu: iommu@fe043e00 {
> > status = "disabled";
> > };
> >
> > +   hdmi: hdmi@fe0a {
> > +   compatible = "rockchip,rk3568-dw-hdmi";
> > +   reg = <0x0 0xfe0a 0x0 0x2>;
> > +   interrupts = ;
> > +   clocks = <&cru PCLK_HDMI_HOST>,
> > +<&cru CLK_HDMI_SFR>,
> > +<&cru CLK_HDMI_CEC>,
> > +<&cru HCLK_VOP>;
> > +   clock-names = "iahb", "isfr", "cec", "hclk";
> > +   power-domains = <&power RK3568_PD_VO>;
> > +   reg-io-width = <4>;
> > +   rockchip,grf = <&grf>;
> > +   #sound-dai-cells = <0>;
> > +   pinctrl-names = "default";
> > +   pinctrl-0 = <&hdmitx_scl &hdmitx_sda &hdmitxm0_cec>;
> > +   status = "disabled";
> > +
> > +   ports {
> > +   #address-cells = <1>;
> > +   #size-cells = <0>;
> > +
> > +   hdmi_in: port@0 {
> 
> 
> The schema says there is only 1 'port' node. Please run schema
> validation when making DT changes.
> 
> However, an HDMI bridge should also define an output port to a
> connector node (or another bridge). So the fix is to allow 'port@0'
> and add an output port.

The rockchip bindings traditionally don't have a connector explicitly
specified in their device trees. I'll stick to that for the next round.
If necessary I'll look later what it takes to add a connector node.

Sascha


-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |


Re: [PATCH v2] drm/gma500/cdv: Fix a wild pointer dereference in cdv_intel_dp_get_modes()

2021-12-01 Thread Patrik Jakobsson
On Wed, Dec 1, 2021 at 4:29 PM Zhou Qingyang  wrote:
>
> In cdv_intel_dp_get_modes(), the third return value of
> drm_mode_duplicate() is assigned to mode and used in
> drm_mode_probed_add(). drm_mode_probed_add() passes mode->head to
> list_add_tail(). list_add_tail() will further call __list_add() and
> there is a dereference of mode->head in __list_add(), which could lead
> to a wild pointer dereference on failure of drm_mode_duplicate().
>
> Fix this bug by adding a check of mode.
>
> This bug was found by a static analyzer. The analysis employs
> differential checking to identify inconsistent security operations
> (e.g., checks or kfrees) between two code paths and confirms that the
> inconsistent operations are not recovered in the current function or
> the callers, so they constitute bugs.
>
> Note that, as a bug found by static analysis, it can be a false
> positive or hard to trigger. Multiple researchers have cross-reviewed
> the bug.
>

Is it really necessary to explain what the static analyzer does and
that it can be faulty in every single patch?
"This bug was found by a static analyzer" is enough for me.

> Builds with CONFIG_DRM_GMA500=m show no new warnings,
> and our static analyzer no longer warns about this code.

I assume all patches to be at least compile tested before submitted,
so if you didn't actually run this code on hardware it's better to
replace the above with:
"Only compile tested".

-Patrik

>
> Fixes: d112a8163f83 ("gma500/cdv: Add eDP support")
> Signed-off-by: Zhou Qingyang 
> ---
> Changes in V2:
>   -  Instead of returning -ENOMEM, this patch returns 0
>   -  Use DRM_DEBUG_KMS to report the failure of drm_mode_duplicate()
>
>  drivers/gpu/drm/gma500/cdv_intel_dp.c | 5 +
>  1 file changed, 5 insertions(+)
>
> diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c 
> b/drivers/gpu/drm/gma500/cdv_intel_dp.c
> index ba6ad1466374..bf47db488b7b 100644
> --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c
> +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c
> @@ -1773,6 +1773,11 @@ static int cdv_intel_dp_get_modes(struct drm_connector 
> *connector)
> if (intel_dp->panel_fixed_mode != NULL) {
> struct drm_display_mode *mode;
> mode = drm_mode_duplicate(dev, 
> intel_dp->panel_fixed_mode);
> +   if (!mode) {
> +   DRM_DEBUG_KMS("Failure in 
> drm_mode_duplicate()\n");
> +   return 0;
> +   }
> +
> drm_mode_probed_add(connector, mode);
> return 1;
> }
> --
> 2.25.1
>


Re: [PATCH] drm/komeda: Fix an undefined behavior bug in komeda_plane_add()

2021-12-01 Thread Steven Price
On 30/11/2021 14:25, Zhou Qingyang wrote:
> In komeda_plane_add(), komeda_get_layer_fourcc_list() is assigned to
> formats and used in drm_universal_plane_init().
> drm_universal_plane_init() passes formats to
> __drm_universal_plane_init(). __drm_universal_plane_init() further
> passes formats to memcpy() as src parameter, which could lead to an
> undefined behavior bug on failure of komeda_get_layer_fourcc_list().
> 
> Fix this bug by adding a check of formats.
> 
> This bug was found by a static analyzer. The analysis employs
> differential checking to identify inconsistent security operations
> (e.g., checks or kfrees) between two code paths and confirms that the
> inconsistent operations are not recovered in the current function or
> the callers, so they constitute bugs.
> 
> Note that, as a bug found by static analysis, it can be a false
> positive or hard to trigger. Multiple researchers have cross-reviewed
> the bug.
> 
> Builds with CONFIG_DRM_KOMEDA=m show no new warnings,
> and our static analyzer no longer warns about this code.
> 
> Fixes: 61f1c4a8ab75 ("drm/komeda: Attach komeda_dev to DRM-KMS")
> Signed-off-by: Zhou Qingyang 
> ---
>  drivers/gpu/drm/arm/display/komeda/komeda_plane.c | 4 
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c 
> b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
> index d63d83800a8a..dd3f17e970dd 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
> @@ -265,6 +265,10 @@ static int komeda_plane_add(struct komeda_kms_dev *kms,
>  
>   formats = komeda_get_layer_fourcc_list(&mdev->fmt_tbl,
>  layer->layer_type, &n_formats);
> + if (!formats) {
> + err = -ENOMEM;
> + goto cleanup;
> + }

If this executes it will cause undefined behaviour...

The cleanup code calls komeda_plane_destroy() which calls
drm_plane_cleanup() which does (amongst other things) a
list_del(&plane->head). But the plane hasn't been put on a list yet as
that's done in drm_universal_plane_init().

So in this case we simple want to do:

if (!formats) {
kfree(kplane);
return -ENOMEM;
}

Note that without this 'fix' a NULL return from
komeda_get_layer_fourcc_list() would leave n_formats==0, so while the
NULL pointer is passed into memcpy() it is also passed a length of 0.
Which I believe is safe.

However while looking at this function...

>  
>   err = drm_universal_plane_init(&kms->base, plane,
>   get_possible_crtcs(kms, c->pipeline),
> 

This call to drm_universal_plane_init() can fail early before
plane->head has been initialised. In which case the following:

>   komeda_put_fourcc_list(formats);
> 
>   if (err)
>   goto cleanup;

commits the exact same sin and would cause a similar NULL dereference in
drm_plane_cleanup().

Steve


Re: [PATCH v4 3/4] arm64: dts: qcom: sc7280: add edp display dt nodes

2021-12-01 Thread Bjorn Andersson
On Mon 22 Nov 05:26 CST 2021, Sankeerth Billakanti wrote:

> Add edp controller and phy DT nodes for sc7280.
> 
> Signed-off-by: Krishna Manikandan 

If Krishna authored the patch (he certified its origin first), then he
should be From: as well.

> Reviewed-by: Stephen Boyd 
> Signed-off-by: Sankeerth Billakanti 
> ---
> 
> Changes in v4:
> None
> 
> Changes in v3:
> - Add one clock cell per line (Stephen Boyd)
> - Unit address should match first reg property (Stephen Boyd)
> - Remove new line (Stephen Boyd)
> - Add the dsi_phy clocks in dispcc (Kuogee Hsieh)
> 
> Changes in v2:
> - Move regulator definitions to board file (Matthias Kaehlcke)
> - Move the gpio definitions to board file (Matthias Kaehlcke)
> - Move the pinconf to board file (Matthias Kaehlcke)
> - Move status property (Stephen Boyd)
> - Drop flags from interrupts (Stephen Boyd)
> - Add clock names one per line for readability (Stephen Boyd)
> - Rename edp-opp-table (Stephen Boyd)
> 
>  arch/arm64/boot/dts/qcom/sc7280.dtsi | 107 
> ++-
>  1 file changed, 105 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi 
> b/arch/arm64/boot/dts/qcom/sc7280.dtsi
> index 12c4d32..5ad500e 100644
> --- a/arch/arm64/boot/dts/qcom/sc7280.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi
> @@ -2695,8 +2695,8 @@
><&dsi_phy 1>,
><0>,
><0>,
> -  <0>,
> -  <0>;
> +  <&edp_phy 0>,
> +  <&edp_phy 1>;
>   clock-names = "bi_tcxo",
> "gcc_disp_gpll0_clk",
> "dsi0_phy_pll_out_byteclk",
> @@ -2784,6 +2784,13 @@
>   remote-endpoint = 
> <&dsi0_in>;
>   };
>   };
> +
> + port@1 {
> + reg = <1>;
> + dpu_intf5_out: endpoint {
> + remote-endpoint = 
> <&edp_in>;
> + };
> + };
>   };
>  
>   mdp_opp_table: opp-table {
> @@ -2899,6 +2906,102 @@
>  
>   status = "disabled";
>   };
> +
> + msm_edp: edp@aea {

mdss_edp:

> + compatible = "qcom,sc7280-edp";
> +
> + reg = <0 0xaea 0 0x200>,
> +   <0 0xaea0200 0 0x200>,
> +   <0 0xaea0400 0 0xc00>,
> +   <0 0xaea1000 0 0x400>;
> +
> + interrupt-parent = <&mdss>;
> + interrupts = <14>;
> +
> + clocks = <&rpmhcc RPMH_CXO_CLK>,
> +  <&gcc GCC_EDP_CLKREF_EN>,
> +  <&dispcc DISP_CC_MDSS_AHB_CLK>,
> +  <&dispcc DISP_CC_MDSS_EDP_AUX_CLK>,
> +  <&dispcc DISP_CC_MDSS_EDP_LINK_CLK>,
> +  <&dispcc 
> DISP_CC_MDSS_EDP_LINK_INTF_CLK>,
> +  <&dispcc DISP_CC_MDSS_EDP_PIXEL_CLK>;
> + clock-names = "core_xo",
> +   "core_ref",
> +   "core_iface",
> +   "core_aux",
> +   "ctrl_link",
> +   "ctrl_link_iface",
> +   "stream_pixel";
> + #clock-cells = <1>;
> + assigned-clocks = <&dispcc 
> DISP_CC_MDSS_EDP_LINK_CLK_SRC>,
> +   <&dispcc 
> DISP_CC_MDSS_EDP_PIXEL_CLK_SRC>;
> + assigned-clock-parents = <&edp_phy 0>, 
> <&edp_phy 1>;
> +
> + phys = <&edp_phy>;
> + phy-names = "dp";
> +
> + operating-points-v2 = <&edp_opp_table>;
> + power-domains = <&rpmhpd SC7280_CX>;
> +
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + status = "disabled";
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +

[PATCH 3/3] drm/ast: Fail if connector initialization fails

2021-12-01 Thread Thomas Zimmermann
Update the connector code to fail if the connector could not be
initialized. The current code just ignored the error and failed
later when the connector was supposed to be used.

Signed-off-by: Thomas Zimmermann 
---
 drivers/gpu/drm/ast/ast_mode.c | 13 -
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index a84dced95440..c988991cad33 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -1319,18 +1319,21 @@ static int ast_connector_init(struct drm_device *dev)
struct ast_connector *ast_connector = &ast->connector;
struct drm_connector *connector = &ast_connector->base;
struct drm_encoder *encoder = &ast->encoder;
+   int ret;
 
ast_connector->i2c = ast_i2c_create(dev);
if (!ast_connector->i2c)
drm_err(dev, "failed to add ddc bus for connector\n");
 
if (ast_connector->i2c)
-   drm_connector_init_with_ddc(dev, connector, 
&ast_connector_funcs,
-   DRM_MODE_CONNECTOR_VGA,
-   &ast_connector->i2c->adapter);
+   ret = drm_connector_init_with_ddc(dev, connector, 
&ast_connector_funcs,
+ DRM_MODE_CONNECTOR_VGA,
+ &ast_connector->i2c->adapter);
else
-   drm_connector_init(dev, connector, &ast_connector_funcs,
-  DRM_MODE_CONNECTOR_VGA);
+   ret = drm_connector_init(dev, connector, &ast_connector_funcs,
+DRM_MODE_CONNECTOR_VGA);
+   if (ret)
+   return ret;
 
drm_connector_helper_add(connector, &ast_connector_helper_funcs);
 
-- 
2.34.0



[PATCH 0/3] ast: Fix I2C corner cases wrt init/cleanup

2021-12-01 Thread Thomas Zimmermann
The VGA connector in ast is supposed to work without I2C. Currently,
this isn't correctly implemented in several places. Fix this. Also
add managed cleanup of the I2C code, and fail if the connector setup
fail.

Tested on AST2100 hardware.

Thomas Zimmermann (3):
  drm/ast: Handle failed I2C initialization gracefully
  drm/ast: Convert I2C code to managed cleanup
  drm/ast: Fail if connector initialization fails

 drivers/gpu/drm/ast/ast_mode.c | 52 ++
 1 file changed, 27 insertions(+), 25 deletions(-)


base-commit: 6a8f90ec433e2f5de5fc16d7a4839771b7027cc0
--
2.34.0



[PATCH 2/3] drm/ast: Convert I2C code to managed cleanup

2021-12-01 Thread Thomas Zimmermann
Release the I2C adapter as part of the DRM device cleanup.

Signed-off-by: Thomas Zimmermann 
---
 drivers/gpu/drm/ast/ast_mode.c | 36 +++---
 1 file changed, 16 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index 3f0c8c1f9777..a84dced95440 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -40,6 +40,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -48,7 +49,6 @@
 #include "ast_tables.h"
 
 static struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev);
-static void ast_i2c_destroy(struct ast_i2c_chan *i2c);
 
 static inline void ast_load_palette_index(struct ast_private *ast,
 u8 index, u8 red, u8 green,
@@ -1300,14 +1300,6 @@ static enum drm_mode_status ast_mode_valid(struct 
drm_connector *connector,
return flags;
 }
 
-static void ast_connector_destroy(struct drm_connector *connector)
-{
-   struct ast_connector *ast_connector = to_ast_connector(connector);
-
-   ast_i2c_destroy(ast_connector->i2c);
-   drm_connector_cleanup(connector);
-}
-
 static const struct drm_connector_helper_funcs ast_connector_helper_funcs = {
.get_modes = ast_get_modes,
.mode_valid = ast_mode_valid,
@@ -1316,7 +1308,7 @@ static const struct drm_connector_helper_funcs 
ast_connector_helper_funcs = {
 static const struct drm_connector_funcs ast_connector_funcs = {
.reset = drm_atomic_helper_connector_reset,
.fill_modes = drm_helper_probe_single_connector_modes,
-   .destroy = ast_connector_destroy,
+   .destroy = drm_connector_cleanup,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
@@ -1493,6 +1485,14 @@ static void set_data(void *i2c_priv, int data)
}
 }
 
+static void ast_i2c_release(struct drm_device *dev, void *res)
+{
+   struct ast_i2c_chan *i2c = res;
+
+   i2c_del_adapter(&i2c->adapter);
+   kfree(i2c);
+}
+
 static struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev)
 {
struct ast_i2c_chan *i2c;
@@ -1521,19 +1521,15 @@ static struct ast_i2c_chan *ast_i2c_create(struct 
drm_device *dev)
ret = i2c_bit_add_bus(&i2c->adapter);
if (ret) {
drm_err(dev, "Failed to register bit i2c\n");
-   goto out_free;
+   goto out_kfree;
}
 
+   ret = drmm_add_action_or_reset(dev, ast_i2c_release, i2c);
+   if (ret)
+   return NULL;
return i2c;
-out_free:
-   kfree(i2c);
-   return NULL;
-}
 
-static void ast_i2c_destroy(struct ast_i2c_chan *i2c)
-{
-   if (!i2c)
-   return;
-   i2c_del_adapter(&i2c->adapter);
+out_kfree:
kfree(i2c);
+   return NULL;
 }
-- 
2.34.0



[PATCH 1/3] drm/ast: Handle failed I2C initialization gracefully

2021-12-01 Thread Thomas Zimmermann
I2C initialization is allowed to fail. In this case, create a connector
without DDC adapter. The current code would dereference a NULL pointer.

Reading the modes from the connector is supposed to work without I2C
adapter. Add the respective test.

Signed-off-by: Thomas Zimmermann 
---
 drivers/gpu/drm/ast/ast_mode.c | 13 -
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index 1e30eaeb0e1b..3f0c8c1f9777 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -1226,7 +1226,7 @@ static int ast_get_modes(struct drm_connector *connector)
else
kfree(edid);
}
-   if (!flags)
+   if (!flags && ast_connector->i2c)
edid = drm_get_edid(connector, &ast_connector->i2c->adapter);
if (edid) {
drm_connector_update_edid_property(&ast_connector->base, edid);
@@ -1332,10 +1332,13 @@ static int ast_connector_init(struct drm_device *dev)
if (!ast_connector->i2c)
drm_err(dev, "failed to add ddc bus for connector\n");
 
-   drm_connector_init_with_ddc(dev, connector,
-   &ast_connector_funcs,
-   DRM_MODE_CONNECTOR_VGA,
-   &ast_connector->i2c->adapter);
+   if (ast_connector->i2c)
+   drm_connector_init_with_ddc(dev, connector, 
&ast_connector_funcs,
+   DRM_MODE_CONNECTOR_VGA,
+   &ast_connector->i2c->adapter);
+   else
+   drm_connector_init(dev, connector, &ast_connector_funcs,
+  DRM_MODE_CONNECTOR_VGA);
 
drm_connector_helper_add(connector, &ast_connector_helper_funcs);
 
-- 
2.34.0



Re: [PATCH v4 2/4] arm64: dts: qcom: sc7280: Add DSI display nodes

2021-12-01 Thread Bjorn Andersson
On Mon 22 Nov 05:26 CST 2021, Sankeerth Billakanti wrote:

> From: Krishna Manikandan 
> 
> Add DSI controller and PHY nodes for sc7280.
> 
> Signed-off-by: Rajeev Nandan 
> Signed-off-by: Krishna Manikandan 
> Reviewed-by: Matthias Kaehlcke 
> Reviewed-by: Stephen Boyd 
> Signed-off-by: Sankeerth Billakanti 
> ---
> 
> Changes in v4:
> None
> 
> Changes in v3:
> - Add the dsi_phy clocks (Kuogee Hsieh)
> - One clock cell per line (Stephen Boyd)
> 
> Changes in v2:
> - Drop flags from interrupts (Stephen Boyd)
> - Rename dsi-opp-table (Stephen Boyd)
> - Rename dsi phy  node (Stephen Boyd)
> 
> 
>  arch/arm64/boot/dts/qcom/sc7280.dtsi | 111 
> ++-
>  1 file changed, 109 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi 
> b/arch/arm64/boot/dts/qcom/sc7280.dtsi
> index a4536b6..12c4d32 100644
> --- a/arch/arm64/boot/dts/qcom/sc7280.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi
> @@ -2691,8 +2691,14 @@
>   reg = <0 0xaf0 0 0x2>;
>   clocks = <&rpmhcc RPMH_CXO_CLK>,
><&gcc GCC_DISP_GPLL0_CLK_SRC>,
> -  <0>, <0>, <0>, <0>, <0>, <0>;
> - clock-names = "bi_tcxo", "gcc_disp_gpll0_clk",
> +  <&dsi_phy 0>,
> +  <&dsi_phy 1>,
> +  <0>,
> +  <0>,
> +  <0>,
> +  <0>;
> + clock-names = "bi_tcxo",
> +   "gcc_disp_gpll0_clk",
> "dsi0_phy_pll_out_byteclk",
> "dsi0_phy_pll_out_dsiclk",
> "dp_phy_pll_link_clk",
> @@ -2768,6 +2774,18 @@
>  
>   status = "disabled";
>  
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> + dpu_intf1_out: endpoint {
> + remote-endpoint = 
> <&dsi0_in>;
> + };
> + };
> + };
> +
>   mdp_opp_table: opp-table {
>   compatible = "operating-points-v2";
>  
> @@ -2792,6 +2810,95 @@
>   };
>   };
>   };
> +
> + dsi0: dsi@ae94000 {

Please label this mdss_dsi0, to make it group nicely when sorted in the
dts.

> + compatible = "qcom,mdss-dsi-ctrl";
> + reg = <0 0x0ae94000 0 0x400>;
> + reg-names = "dsi_ctrl";
> +
> + interrupt-parent = <&mdss>;
> + interrupts = <4>;
> +
> + clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>,
> +  <&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>,
> +  <&dispcc DISP_CC_MDSS_PCLK0_CLK>,
> +  <&dispcc DISP_CC_MDSS_ESC0_CLK>,
> +  <&dispcc DISP_CC_MDSS_AHB_CLK>,
> +  <&gcc GCC_DISP_HF_AXI_CLK>;
> + clock-names = "byte",
> +   "byte_intf",
> +   "pixel",
> +   "core",
> +   "iface",
> +   "bus";
> +
> + operating-points-v2 = <&dsi_opp_table>;
> + power-domains = <&rpmhpd SC7280_CX>;
> +
> + phys = <&dsi_phy>;
> + phy-names = "dsi";
> +
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + status = "disabled";
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> + dsi0_in: endpoint {
> + remote-endpoint = 
> <&dpu_intf1_out>;
> + };
> + };
> +
> + port@1 {
>

Re: [PATCH v4 1/4] arm64: dts: qcom: sc7280: add display dt nodes

2021-12-01 Thread Bjorn Andersson
On Mon 22 Nov 05:26 CST 2021, Sankeerth Billakanti wrote:

> From: Krishna Manikandan 
> 
> Add mdss and mdp DT nodes for sc7280.
> 
> Signed-off-by: Krishna Manikandan 
> Reported-by: kernel test robot 

Sorry, missed this one before sending my reply.

"kernel test robot" did not report the lack of mdss nodes in your dts.
So please drop this as well.

> Reviewed-by: Stephen Boyd 
> Reported-by: kernel test robot 

And again.

Thanks,
Bjorn

> Signed-off-by: Sankeerth Billakanti 
> ---
> 
> Changes in v4:
> None
> 
> Changes in v3:
> None
> 
> Changes in v2:
> - Rename display dt nodes (Stephen Boyd)
> - Add clock names one per line for readability (Stephen Boyd)
> 
> 
>  arch/arm64/boot/dts/qcom/sc7280.dtsi | 90 
> 
>  1 file changed, 90 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi 
> b/arch/arm64/boot/dts/qcom/sc7280.dtsi
> index 365a2e0..a4536b6 100644
> --- a/arch/arm64/boot/dts/qcom/sc7280.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi
> @@ -2704,6 +2704,96 @@
>   #power-domain-cells = <1>;
>   };
>  
> + mdss: display-subsystem@ae0 {
> + compatible = "qcom,sc7280-mdss";
> + reg = <0 0x0ae0 0 0x1000>;
> + reg-names = "mdss";
> +
> + power-domains = <&dispcc DISP_CC_MDSS_CORE_GDSC>;
> +
> + clocks = <&gcc GCC_DISP_AHB_CLK>,
> +  <&dispcc DISP_CC_MDSS_AHB_CLK>,
> + <&dispcc DISP_CC_MDSS_MDP_CLK>;
> + clock-names = "iface",
> +   "ahb",
> +   "core";
> +
> + assigned-clocks = <&dispcc DISP_CC_MDSS_MDP_CLK>;
> + assigned-clock-rates = <3>;
> +
> + interrupts = ;
> + interrupt-controller;
> + #interrupt-cells = <1>;
> +
> + interconnects = <&mmss_noc MASTER_MDP0 0 &mc_virt 
> SLAVE_EBI1 0>;
> + interconnect-names = "mdp0-mem";
> +
> + iommus = <&apps_smmu 0x900 0x402>;
> +
> + #address-cells = <2>;
> + #size-cells = <2>;
> + ranges;
> +
> + status = "disabled";
> +
> + mdp: display-controller@ae01000 {
> + compatible = "qcom,sc7280-dpu";
> + reg = <0 0x0ae01000 0 0x8f030>,
> + <0 0x0aeb 0 0x2008>;
> + reg-names = "mdp", "vbif";
> +
> + clocks = <&gcc GCC_DISP_HF_AXI_CLK>,
> + <&gcc GCC_DISP_SF_AXI_CLK>,
> + <&dispcc DISP_CC_MDSS_AHB_CLK>,
> + <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>,
> + <&dispcc DISP_CC_MDSS_MDP_CLK>,
> + <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
> + clock-names = "bus",
> +   "nrt_bus",
> +   "iface",
> +   "lut",
> +   "core",
> +   "vsync";
> + assigned-clocks = <&dispcc 
> DISP_CC_MDSS_MDP_CLK>,
> + <&dispcc 
> DISP_CC_MDSS_VSYNC_CLK>,
> + <&dispcc DISP_CC_MDSS_AHB_CLK>;
> + assigned-clock-rates = <3>,
> + <1920>,
> + <1920>;
> + operating-points-v2 = <&mdp_opp_table>;
> + power-domains = <&rpmhpd SC7280_CX>;
> +
> + interrupt-parent = <&mdss>;
> + interrupts = <0>;
> +
> + status = "disabled";
> +
> + mdp_opp_table: opp-table {
> + compatible = "operating-points-v2";
> +
> + opp-2 {
> + opp-hz = /bits/ 64 <2>;
> + required-opps = 
> <&rpmhpd_opp_low_svs>;
> + };
> +
> + opp-3 {
> + opp-hz = /bits/ 64 <3>;
> + required-opps = 
> <&rpmhpd_opp_svs>;
> + };
> +
> + opp-38000 {
> +  

Re: [PATCH v4 1/4] arm64: dts: qcom: sc7280: add display dt nodes

2021-12-01 Thread Bjorn Andersson
On Mon 22 Nov 05:26 CST 2021, Sankeerth Billakanti wrote:

> From: Krishna Manikandan 
> 
> Add mdss and mdp DT nodes for sc7280.
> 
> Signed-off-by: Krishna Manikandan 
> Reported-by: kernel test robot 
> Reviewed-by: Stephen Boyd 
> Reported-by: kernel test robot 
> Signed-off-by: Sankeerth Billakanti 
> ---
> 
> Changes in v4:
> None
> 
> Changes in v3:
> None
> 
> Changes in v2:
> - Rename display dt nodes (Stephen Boyd)
> - Add clock names one per line for readability (Stephen Boyd)
> 
> 
>  arch/arm64/boot/dts/qcom/sc7280.dtsi | 90 
> 
>  1 file changed, 90 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi 
> b/arch/arm64/boot/dts/qcom/sc7280.dtsi
> index 365a2e0..a4536b6 100644
> --- a/arch/arm64/boot/dts/qcom/sc7280.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi
> @@ -2704,6 +2704,96 @@
>   #power-domain-cells = <1>;
>   };
>  
> + mdss: display-subsystem@ae0 {
> + compatible = "qcom,sc7280-mdss";
> + reg = <0 0x0ae0 0 0x1000>;
> + reg-names = "mdss";
> +
> + power-domains = <&dispcc DISP_CC_MDSS_CORE_GDSC>;
> +
> + clocks = <&gcc GCC_DISP_AHB_CLK>,
> +  <&dispcc DISP_CC_MDSS_AHB_CLK>,
> + <&dispcc DISP_CC_MDSS_MDP_CLK>;
> + clock-names = "iface",
> +   "ahb",
> +   "core";
> +
> + assigned-clocks = <&dispcc DISP_CC_MDSS_MDP_CLK>;
> + assigned-clock-rates = <3>;
> +
> + interrupts = ;
> + interrupt-controller;
> + #interrupt-cells = <1>;
> +
> + interconnects = <&mmss_noc MASTER_MDP0 0 &mc_virt 
> SLAVE_EBI1 0>;
> + interconnect-names = "mdp0-mem";
> +
> + iommus = <&apps_smmu 0x900 0x402>;
> +
> + #address-cells = <2>;
> + #size-cells = <2>;
> + ranges;
> +
> + status = "disabled";
> +
> + mdp: display-controller@ae01000 {

I believe the only reason to give this a label is so that you can enable
it in the dts. But I don't see the point of having it status disabled,
given that it should always follow the mdss node's status.

> + compatible = "qcom,sc7280-dpu";
> + reg = <0 0x0ae01000 0 0x8f030>,
> + <0 0x0aeb 0 0x2008>;
> + reg-names = "mdp", "vbif";
> +
> + clocks = <&gcc GCC_DISP_HF_AXI_CLK>,
> + <&gcc GCC_DISP_SF_AXI_CLK>,
> + <&dispcc DISP_CC_MDSS_AHB_CLK>,
> + <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>,
> + <&dispcc DISP_CC_MDSS_MDP_CLK>,
> + <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
> + clock-names = "bus",
> +   "nrt_bus",
> +   "iface",
> +   "lut",
> +   "core",
> +   "vsync";
> + assigned-clocks = <&dispcc 
> DISP_CC_MDSS_MDP_CLK>,
> + <&dispcc 
> DISP_CC_MDSS_VSYNC_CLK>,
> + <&dispcc DISP_CC_MDSS_AHB_CLK>;
> + assigned-clock-rates = <3>,
> + <1920>,
> + <1920>;
> + operating-points-v2 = <&mdp_opp_table>;
> + power-domains = <&rpmhpd SC7280_CX>;
> +
> + interrupt-parent = <&mdss>;
> + interrupts = <0>;
> +
> + status = "disabled";

So my suggestion is to drop this and drop the label.

If not, please change the label of this node to mdss_mdp, for sorting
purposes.

Thanks,
Bjorn

> +
> + mdp_opp_table: opp-table {
> + compatible = "operating-points-v2";
> +
> + opp-2 {
> + opp-hz = /bits/ 64 <2>;
> + required-opps = 
> <&rpmhpd_opp_low_svs>;
> + };
> +
> + opp-3 {
> + opp-hz = /bits/ 64 <3>;
> +  

Re: [PATCH v4 4/4] arm64: dts: qcom: sc7280: Add Display Port node

2021-12-01 Thread Bjorn Andersson
On Mon 22 Nov 05:29 CST 2021, Sankeerth Billakanti wrote:

> From: Kuogee Hsieh 
> 
> Signed-off-by: Kuogee Hsieh 
> Reviewed-by: Stephen Boyd 
> Signed-off-by: Sankeerth Billakanti 

Can you please update this to make From: and Signed-off-by: match.


Also I don't know how you prepared this patch series, because this says
patch 4/4, but it's not part of the same series as the other patches.

I did pick up the first  3 patches, but then noticed that you are back
at using the original labels, so please see below and send all 4 patches
in a proper series.

> ---
> 
> Changes in v4:
> - Add the patch to display DT change series (Bjorn Andersson)
> - Remove the trailing whitespaces
> 
>  arch/arm64/boot/dts/qcom/sc7280.dtsi | 90 
> +++-
>  1 file changed, 88 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi 
> b/arch/arm64/boot/dts/qcom/sc7280.dtsi
> index 5ad500e..0b2ffd5 100644
> --- a/arch/arm64/boot/dts/qcom/sc7280.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi
> @@ -2693,8 +2693,8 @@
><&gcc GCC_DISP_GPLL0_CLK_SRC>,
><&dsi_phy 0>,
><&dsi_phy 1>,
> -  <0>,
> -  <0>,
> +  <&dp_phy 0>,
> +  <&dp_phy 1>,
><&edp_phy 0>,
><&edp_phy 1>;
>   clock-names = "bi_tcxo",
> @@ -2791,6 +2791,13 @@
>   remote-endpoint = 
> <&edp_in>;
>   };
>   };
> +
> + port@2 {
> +reg = <2>;
> +dpu_intf0_out: endpoint {
> +remote-endpoint = 
> <&dp_in>;
> +};
> +};
>   };
>  
>   mdp_opp_table: opp-table {
> @@ -3002,6 +3009,79 @@
>  
>   status = "disabled";
>   };
> +
> + msm_dp: displayport-controller@ae9 {

As requested previously, can you please label this mdss_dp, to make it
sort nicely in the dts?

Thanks,
Bjorn

> + compatible = "qcom,sc7280-dp";
> +
> + reg = <0 0x0ae9 0 0x1400>;
> +
> + interrupt-parent = <&mdss>;
> + interrupts = <12>;
> +
> + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
> +  <&dispcc DISP_CC_MDSS_DP_AUX_CLK>,
> +  <&dispcc DISP_CC_MDSS_DP_LINK_CLK>,
> +  <&dispcc 
> DISP_CC_MDSS_DP_LINK_INTF_CLK>,
> +  <&dispcc DISP_CC_MDSS_DP_PIXEL_CLK>;
> + clock-names =   "core_iface",
> + "core_aux",
> + "ctrl_link",
> + "ctrl_link_iface",
> + "stream_pixel";
> + #clock-cells = <1>;
> + assigned-clocks = <&dispcc 
> DISP_CC_MDSS_DP_LINK_CLK_SRC>,
> +   <&dispcc 
> DISP_CC_MDSS_DP_PIXEL_CLK_SRC>;
> + assigned-clock-parents = <&dp_phy 0>, <&dp_phy 
> 1>;
> + phys = <&dp_phy>;
> + phy-names = "dp";
> +
> + operating-points-v2 = <&dp_opp_table>;
> + power-domains = <&rpmhpd SC7280_CX>;
> +
> + #sound-dai-cells = <0>;
> +
> + status = "disabled";
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + port@0 {
> + reg = <0>;
> + dp_in: endpoint {
> + remote-endpoint = 
> <&dpu_intf0_out>;
> + };
> + };
> +
> + port@1 {
> + reg = <1>;
> + dp_out: endpoint { };
> + };
> + };
> +
> + dp_opp_table:

Re: [PATCH] drm: Return error codes from struct drm_driver.gem_create_object

2021-12-01 Thread Steven Price
On 30/11/2021 09:52, Thomas Zimmermann wrote:
> GEM helper libraries use struct drm_driver.gem_create_object to let
> drivers override GEM object allocation. On failure, the call returns
> NULL.
> 
> Change the semantics to make the calls return a pointer-encoded error.
> This aligns the callback with its callers. Fixes the ingenic driver,
> which already returns an error pointer.
> 
> Also update the callers to handle the involved types more strictly.
> 
> Signed-off-by: Thomas Zimmermann 

Reviewed-by: Steven Price 

> ---
> There is an alternative patch at [1] that updates the value returned
> by ingenics' gem_create_object to NULL. Fixing the interface to return
> an errno code is more consistent with the rest of the GEM functions.
> 
> [1] https://lore.kernel.org/dri-devel/2028111522.GD1147@kili/
> ---
>  drivers/gpu/drm/drm_gem_cma_helper.c| 17 ++---
>  drivers/gpu/drm/drm_gem_shmem_helper.c  | 17 ++---
>  drivers/gpu/drm/drm_gem_vram_helper.c   |  4 ++--
>  drivers/gpu/drm/lima/lima_gem.c |  2 +-
>  drivers/gpu/drm/panfrost/panfrost_gem.c |  2 +-
>  drivers/gpu/drm/v3d/v3d_bo.c|  4 ++--
>  drivers/gpu/drm/vc4/vc4_bo.c|  2 +-
>  drivers/gpu/drm/vgem/vgem_drv.c |  2 +-
>  drivers/gpu/drm/virtio/virtgpu_object.c |  2 +-
>  include/drm/drm_drv.h   |  5 +++--
>  10 files changed, 32 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c 
> b/drivers/gpu/drm/drm_gem_cma_helper.c
> index 7d4895de9e0d..cefd0cbf9deb 100644
> --- a/drivers/gpu/drm/drm_gem_cma_helper.c
> +++ b/drivers/gpu/drm/drm_gem_cma_helper.c
> @@ -67,18 +67,21 @@ __drm_gem_cma_create(struct drm_device *drm, size_t size, 
> bool private)
>   struct drm_gem_object *gem_obj;
>   int ret = 0;
> 
> - if (drm->driver->gem_create_object)
> + if (drm->driver->gem_create_object) {
>   gem_obj = drm->driver->gem_create_object(drm, size);
> - else
> - gem_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL);
> - if (!gem_obj)
> - return ERR_PTR(-ENOMEM);
> + if (IS_ERR(gem_obj))
> + return ERR_CAST(gem_obj);
> + cma_obj = to_drm_gem_cma_obj(gem_obj);
> + } else {
> + cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL);
> + if (!cma_obj)
> + return ERR_PTR(-ENOMEM);
> + gem_obj = &cma_obj->base;
> + }
> 
>   if (!gem_obj->funcs)
>   gem_obj->funcs = &drm_gem_cma_default_funcs;
> 
> - cma_obj = container_of(gem_obj, struct drm_gem_cma_object, base);
> -
>   if (private) {
>   drm_gem_private_object_init(drm, gem_obj, size);
> 
> diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c 
> b/drivers/gpu/drm/drm_gem_shmem_helper.c
> index 0eeda1012364..7915047cb041 100644
> --- a/drivers/gpu/drm/drm_gem_shmem_helper.c
> +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
> @@ -56,14 +56,17 @@ __drm_gem_shmem_create(struct drm_device *dev, size_t 
> size, bool private)
> 
>   size = PAGE_ALIGN(size);
> 
> - if (dev->driver->gem_create_object)
> + if (dev->driver->gem_create_object) {
>   obj = dev->driver->gem_create_object(dev, size);
> - else
> - obj = kzalloc(sizeof(*shmem), GFP_KERNEL);
> - if (!obj)
> - return ERR_PTR(-ENOMEM);
> -
> - shmem = to_drm_gem_shmem_obj(obj);
> + if (IS_ERR(obj))
> + return ERR_CAST(obj);
> + shmem = to_drm_gem_shmem_obj(obj);
> + } else {
> + shmem = kzalloc(sizeof(*shmem), GFP_KERNEL);
> + if (!shmem)
> + return ERR_PTR(-ENOMEM);
> + obj = &shmem->base;
> + }
> 
>   if (!obj->funcs)
>   obj->funcs = &drm_gem_shmem_funcs;
> diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c 
> b/drivers/gpu/drm/drm_gem_vram_helper.c
> index bfa386b98134..3f00192215d1 100644
> --- a/drivers/gpu/drm/drm_gem_vram_helper.c
> +++ b/drivers/gpu/drm/drm_gem_vram_helper.c
> @@ -197,8 +197,8 @@ struct drm_gem_vram_object *drm_gem_vram_create(struct 
> drm_device *dev,
> 
>   if (dev->driver->gem_create_object) {
>   gem = dev->driver->gem_create_object(dev, size);
> - if (!gem)
> - return ERR_PTR(-ENOMEM);
> + if (IS_ERR(gem))
> + return ERR_CAST(gem);
>   gbo = drm_gem_vram_of_gem(gem);
>   } else {
>   gbo = kzalloc(sizeof(*gbo), GFP_KERNEL);
> diff --git a/drivers/gpu/drm/lima/lima_gem.c b/drivers/gpu/drm/lima/lima_gem.c
> index 2723d333c608..f9a9198ef198 100644
> --- a/drivers/gpu/drm/lima/lima_gem.c
> +++ b/drivers/gpu/drm/lima/lima_gem.c
> @@ -221,7 +221,7 @@ struct drm_gem_object *lima_gem_create_object(struct 
> drm_device *dev, size_t siz
> 
>   bo = kzalloc(sizeof(*bo), GFP_KERNEL);
>   if (!bo)
> - return NULL;
> + return ERR_

Re: [PATCH v5] drm/radeon/radeon_kms: Fix a NULL pointer dereference in radeon_driver_open_kms()

2021-12-01 Thread Christian König

Am 01.12.21 um 16:13 schrieb Zhou Qingyang:

In radeon_driver_open_kms(), radeon_vm_bo_add() is assigned to
vm->ib_bo_va and passes and used in radeon_vm_bo_set_addr(). In
radeon_vm_bo_set_addr(), there is a dereference of vm->ib_bo_va,
which could lead to a NULL pointer dereference on failure of
radeon_vm_bo_add().

Fix this bug by adding a check of vm->ib_bo_va.

This bug was found by a static analyzer. The analysis employs
differential checking to identify inconsistent security operations
(e.g., checks or kfrees) between two code paths and confirms that the
inconsistent operations are not recovered in the current function or
the callers, so they constitute bugs.

Note that, as a bug found by static analysis, it can be a false
positive or hard to trigger. Multiple researchers have cross-reviewed
the bug.

Builds with CONFIG_DRM_RADEON=m show no new warnings,
and our static analyzer no longer warns about this code.

Fixes: cc9e67e3d700 ("drm/radeon: fix VM IB handling")
Signed-off-by: Zhou Qingyang 
---
Changes in v5:
   -  Use conditions to avoid unnecessary initialization

Changes in v4:
   -  Initialize the variables to silence warning

Changes in v3:
   -  Fix the bug that good case will also be freed
   -  Improve code style

Changes in v2:
   -  Improve the error handling into goto style

  drivers/gpu/drm/radeon/radeon_kms.c | 36 -
  1 file changed, 20 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_kms.c 
b/drivers/gpu/drm/radeon/radeon_kms.c
index 482fb0ae6cb5..66aee48fd09d 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -648,6 +648,8 @@ void radeon_driver_lastclose_kms(struct drm_device *dev)
  int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
  {
struct radeon_device *rdev = dev->dev_private;
+   struct radeon_fpriv *fpriv;
+   struct radeon_vm *vm;
int r;
  
  	file_priv->driver_priv = NULL;

@@ -660,8 +662,6 @@ int radeon_driver_open_kms(struct drm_device *dev, struct 
drm_file *file_priv)
  
  	/* new gpu have virtual address space support */

if (rdev->family >= CHIP_CAYMAN) {
-   struct radeon_fpriv *fpriv;
-   struct radeon_vm *vm;
  
  		fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);

if (unlikely(!fpriv)) {
@@ -672,35 +672,39 @@ int radeon_driver_open_kms(struct drm_device *dev, struct 
drm_file *file_priv)
if (rdev->accel_working) {
vm = &fpriv->vm;
r = radeon_vm_init(rdev, vm);
-   if (r) {
-   kfree(fpriv);
-   goto out_suspend;
-   }
+   if (r)
+   goto out_fpriv;
  
  			r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);

-   if (r) {
-   radeon_vm_fini(rdev, vm);
-   kfree(fpriv);
-   goto out_suspend;
-   }
+   if (r)
+   goto out_vm_fini;
  
  			/* map the ib pool buffer read only into

 * virtual address space */
vm->ib_bo_va = radeon_vm_bo_add(rdev, vm,
rdev->ring_tmp_bo.bo);
+   if (!vm->ib_bo_va) {
+   r = -ENOMEM;
+   goto out_vm_fini;
+   }
+
r = radeon_vm_bo_set_addr(rdev, vm->ib_bo_va,
  RADEON_VA_IB_OFFSET,
  RADEON_VM_PAGE_READABLE |
  RADEON_VM_PAGE_SNOOPED);
-   if (r) {
-   radeon_vm_fini(rdev, vm);
-   kfree(fpriv);
-   goto out_suspend;
-   }
+   if (r)
+   goto out_vm_fini;
}
file_priv->driver_priv = fpriv;
}
  
+	if (!r)


I think that test is unecessary now, maybe double check.

Either way patch Reviewed-by: Christian König 
. Alex will probably pick it up now.


Thanks for the help,
Christian.


+   goto out_suspend;
+
+out_vm_fini:
+   radeon_vm_fini(rdev, vm);
+out_fpriv:
+   kfree(fpriv);
  out_suspend:
pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev);




Re: [PATCH v10 4/8] drm/ingenic: Add dw-hdmi driver for jz4780

2021-12-01 Thread Mark Brown
On Wed, Dec 01, 2021 at 03:33:24PM +0100, H. Nikolaus Schaller wrote:
> > Am 01.12.2021 um 15:03 schrieb Paul Cercueil :

> > Please make it mandatory in DTS then, and use devm_regulator_get() in the 
> > driver.

> Well, I just wonder why the elegant devm_regulator_get_optional() exists at 
> all
> and seems to be used in ca. 80 places.

Frankly because half of them are broken usages like this since people
seem determined to have the most fragile error handling they can :/
There are valid use cases for it, with things like SD cards where some
supplies are genuinely optional and simply constrain what features are
available if they're omitted from the design.  You also see some devices
with the ability to replace internal regulators with external ones.

> And if it is not allowed, why some DTS should be forced to add not physically 
> existing dummy-regulators.

Again, if the supply can be physically absent that is a sensible use
case but that means completely absent, not just not software
controllable.  We can represent fixed voltage regulators just fine.

> AFAIR drivers should implement functionality defined by DTS but not the other 
> way round: enforce DTS style.
> BTW: there is no +5 mains dummy regulator defined in ci20.dts.

It wouldn't be the first time a DTS were incomplete, and I'm sure it
won't be the last.

> What I fear is that if we always have to define the mains +5V (which is for 
> example not
> defined in ci20.dts), which rules stops us from asking to add a 
> dummy-regulator from 110/230V to +5V as well.

It is good practice to specify the full tree of supplies all the way to
the main supply rail of the board, this ensures that if we need the
information for something we've got it (even if that thing is just that
we've got to the root of the tree).  There's potential applications in
battery supplied devices for managing very low power situations.


signature.asc
Description: PGP signature


Re: [PATCH] drm/i915: Force ww lock for i915_gem_object_ggtt_pin_ww, v2.

2021-12-01 Thread Matthew Auld
On Tue, 30 Nov 2021 at 09:21, Maarten Lankhorst
 wrote:
>
> We will need the lock to unbind the vma, and wait for bind to complete.
> Remove the special casing for the !ww path, and force ww locking for all.
>
> Changes since v1:
> - Pass err to for_i915_gem_ww handling for -EDEADLK handling.
>
> Signed-off-by: Maarten Lankhorst 
> ---
>  drivers/gpu/drm/i915/i915_drv.h |  7 ++-
>  drivers/gpu/drm/i915/i915_gem.c | 30 ++
>  2 files changed, 28 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 1bfadd9127fc..8322abe194da 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1842,13 +1842,10 @@ i915_gem_object_ggtt_pin_ww(struct 
> drm_i915_gem_object *obj,
> const struct i915_ggtt_view *view,
> u64 size, u64 alignment, u64 flags);
>
> -static inline struct i915_vma * __must_check
> +struct i915_vma * __must_check
>  i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
>  const struct i915_ggtt_view *view,
> -u64 size, u64 alignment, u64 flags)
> -{
> -   return i915_gem_object_ggtt_pin_ww(obj, NULL, view, size, alignment, 
> flags);
> -}
> +u64 size, u64 alignment, u64 flags);
>
>  int i915_gem_object_unbind(struct drm_i915_gem_object *obj,
>unsigned long flags);
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 527228d4da7e..6002045bd194 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -877,6 +877,8 @@ i915_gem_object_ggtt_pin_ww(struct drm_i915_gem_object 
> *obj,
> struct i915_vma *vma;
> int ret;
>
> +   GEM_WARN_ON(!ww);

Return something here, or GEM_BUG_ON()? I assume it's going to crash
and burn anyway?

> +
> if (flags & PIN_MAPPABLE &&
> (!view || view->type == I915_GGTT_VIEW_NORMAL)) {
> /*
> @@ -936,10 +938,7 @@ i915_gem_object_ggtt_pin_ww(struct drm_i915_gem_object 
> *obj,
> return ERR_PTR(ret);
> }
>
> -   if (ww)
> -   ret = i915_vma_pin_ww(vma, ww, size, alignment, flags | 
> PIN_GLOBAL);
> -   else
> -   ret = i915_vma_pin(vma, size, alignment, flags | PIN_GLOBAL);
> +   ret = i915_vma_pin_ww(vma, ww, size, alignment, flags | PIN_GLOBAL);
>
> if (ret)
> return ERR_PTR(ret);
> @@ -959,6 +958,29 @@ i915_gem_object_ggtt_pin_ww(struct drm_i915_gem_object 
> *obj,
> return vma;
>  }
>
> +struct i915_vma * __must_check
> +i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
> +const struct i915_ggtt_view *view,
> +u64 size, u64 alignment, u64 flags)
> +{
> +   struct i915_gem_ww_ctx ww;
> +   struct i915_vma *ret;
> +   int err;
> +
> +   for_i915_gem_ww(&ww, err, true) {
> +   err = i915_gem_object_lock(obj, &ww);
> +   if (err)
> +   continue;
> +
> +   ret = i915_gem_object_ggtt_pin_ww(obj, &ww, view, size,
> + alignment, flags);
> +   if (IS_ERR(ret))
> +   err = PTR_ERR(ret);

Maybe s/ret/vma/ ? Seeing ret makes me think it's an integer.

Anyway,
Reviewed-by: Matthew Auld 

> +   }
> +
> +   return err ? ERR_PTR(err) : ret;
> +}
> +
>  int
>  i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
>struct drm_file *file_priv)
> --
> 2.34.1
>


Re: [PATCH] drm: Return error codes from struct drm_driver.gem_create_object

2021-12-01 Thread Maxime Ripard
On Tue, Nov 30, 2021 at 10:52:55AM +0100, Thomas Zimmermann wrote:
> GEM helper libraries use struct drm_driver.gem_create_object to let
> drivers override GEM object allocation. On failure, the call returns
> NULL.
> 
> Change the semantics to make the calls return a pointer-encoded error.
> This aligns the callback with its callers. Fixes the ingenic driver,
> which already returns an error pointer.
> 
> Also update the callers to handle the involved types more strictly.
> 
> Signed-off-by: Thomas Zimmermann 
> ---
> There is an alternative patch at [1] that updates the value returned
> by ingenics' gem_create_object to NULL. Fixing the interface to return
> an errno code is more consistent with the rest of the GEM functions.
> 
> [1] https://lore.kernel.org/dri-devel/2028111522.GD1147@kili/

Acked-by: Maxime Ripard 

Maxime


signature.asc
Description: PGP signature


Re: [PATCH 0/6] drm/tiny/st7735r: Match up with staging/fbtft driver

2021-12-01 Thread Maxime Ripard
Hi Noralf,

On Tue, Nov 30, 2021 at 03:30:11PM +0100, Noralf Trønnes wrote:
> Den 29.11.2021 10.39, skrev Maxime Ripard:
> > On Wed, Nov 24, 2021 at 04:03:07PM -0600, David Lechner wrote:
> >> On 11/24/21 9:07 AM, Noralf Trønnes wrote:
> > I agree that it doesn't really fit in the DT either though. Noralf, what
> > kind of data do we need to setup a display in fbtft? The init sequence,
> > and maybe some enable/reset GPIO, plus some timing duration maybe?
> > 
> > There's one similar situation I can think of: wifi chips. Those also
> > need a few infos from the DT (like what bus it's connected to, enable
> > GPIO, etc) and a different sequence (firmware), sometimes different from
> > one board to the other.
> > 
> > Could we have a binding that would be something like:
> > 
> > panel@42 {
> >  compatible = "panel-spi";
> >  model = "panel-from-random-place-42";
> >  enable-gpios = <&...>;
> > }
> > 
> > And then, the driver would request the init sequence through the
> > firmware mechanism using a name generated from the model property.
> > 
> > It allows to support multiple devices in a given system, since the
> > firmware name wouldn't conflict, it makes a decent binding, and users
> > can adjust the init sequence easily (maybe with a bit of tooling)
> > 
> > Would that work?
>
> I really like this idea. An added benefit is that one driver can handle
> all MIPI DBI compatible controllers avoiding the need to do a patchset
> like this for all the various MIPI DBI controllers. The firmware will
> just contain numeric commands with parameters, so no need for different
> controller drivers to handle the controller specific command names.
> 
> The following is a list of the MIPI DBI compatible controllers currently
> in staging/fbtft: ili9341, hx8357d, st7735r, ili9163, ili9163, ili9163,
> ili9163, ili9486, ili9481, tinylcd, s6d02a1, s6d02a1, hx8340bn, ili9340.
> 
> The compatible needs to be a bit more specific though since there are 2
> major SPI protocols for these display: MIPI DBI and the one used by
> ILI9325 and others.
> 
> The full binding would be something like this:
> 
> panel@42 {
>   compatible = "panel-mipi-dbi-spi";
>   model = "panel-from-random-place-42";
> 
>   /* The MIPI DBI spec lists these powers supply pins */
>   vdd-supply = <&...>;
>   vddi-supply = <&...>;
> 
>   /* Optional gpio to drive the RESX line */
>   reset-gpios = <&...>;
> 
>   /*
>* D/CX: Data/Command, Command is active low
>* Abcense: Interface option 1 (D/C embedded in 9-bit word)
>* Precense: Interface option 3
>*/
>   dc-gpios = <&...>;
> 
>   /*
>* If set the driver won't try to read from the controller to see
>* if it's already configured by the bootloader or previously by
>* the driver. A readable controller avoids flicker and/or delay
>* enabling the pipeline.
>*
>* This property might not be necessary if we are guaranteed to
>* always read back all 1's or 0's when MISO is not connected.
>* I don't know if all setups can guarantee that.
>*/
>   write-only;
> 
>   /* Optional ref to backlight node */
>   backlight = <&...>;
> }

It looks decent to me. We'll want Rob to give his opinion though, but it
looks in a much better shape compared to what we usually have :)

> Many of these controllers also have a RGB interface option for the
> pixels and only do configuration over SPI.
> Maybe the compatible should reflect these 2 options somehow?

I think we'll want a "real" panel for RGB, with its own compatible
though. We have a few of these drivers in tree already, so it's better
to remain consistent.

Maxime


signature.asc
Description: PGP signature


Re: [PATCH v10 4/8] drm/ingenic: Add dw-hdmi driver for jz4780

2021-12-01 Thread H. Nikolaus Schaller
Hi Paul,

> Am 01.12.2021 um 15:03 schrieb Paul Cercueil :
> 
> Hi Nikolaus, Mark,
> 
> Le mer., déc. 1 2021 at 14:51:51 +0100, H. Nikolaus Schaller 
>  a écrit :
>> Hi,
>>> Am 01.12.2021 um 14:39 schrieb Mark Brown :
>>> On Wed, Dec 01, 2021 at 01:02:45PM +, Paul Cercueil wrote:
 Le mar., nov. 30 2021 at 22:26:37 +0100, H. Nikolaus Schaller
> + regulator = devm_regulator_get_optional(&pdev->dev, "hdmi-5v");
> + if (IS_ERR(regulator)) {
> + ret = PTR_ERR(regulator);
>>> Why is this using _optional()?  This should only be done when the supply
>>> can be physically absent
>> There can be +5V for HDMI but without a regulator that is visible to or 
>> controllable
>> by the driver.
> 
> There is always a power supply though. Either a controllable one (through 
> e.g. a GPIO), or it's just connected to the mains +5V; the pin is never left 
> floating. In the second case, in DTS the "hdmi-5v" would be connected to some 
> 5v regulator, even if it's just a dummy VCC-5V regulator. So Mark has a point.
> 
>> So hdmi-5v can be simply missing in DTS in which case the driver does not 
>> need to
>> care about. The driver just can't turn it on or off.
> 
> Please make it mandatory in DTS then, and use devm_regulator_get() in the 
> driver.

Well, I just wonder why the elegant devm_regulator_get_optional() exists at all
and seems to be used in ca. 80 places.

And if it is not allowed, why some DTS should be forced to add not physically 
existing dummy-regulators.
AFAIR drivers should implement functionality defined by DTS but not the other 
way round: enforce DTS style.
BTW: there is no +5 mains dummy regulator defined in ci20.dts.

What I fear is that if we always have to define the mains +5V (which is for 
example not
defined in ci20.dts), which rules stops us from asking to add a dummy-regulator 
from 110/230V to +5V as well.
In last consequence, it seems as if we have to describe all dummy regulators 
from the power plant to our hdmi-5v :)

Since I always follow the KISS principle I tend to leave out what is not 
relevant...

Of course adding a dummy regulator to the DTS allows to avoid the NULL pointer 
test
in the driver code.

Anyways, you are maintainers :)

So should I spin a v11 for the series or just this patch or how should we do it?

BR and thanks,
Nikolaus

> 
> Cheers,
> -Paul
> 
>>> (in which case I'd expect to see special
>>> handling).
>> The special case is to not enable/disable the regulator if it does not exist
>> and assume that there is hardware providing it otherwise (the driver can't 
>> know
>> that except by using get_optional). This is done by the code below
> + if (IS_ERR(regulator)) {
>> ...
>>> +   if (!regulator)
>>> +   return 0;
>>> +   ret = regulator_enable(regulator);
>> ...
>> BR and thanks,
>> Nikolaus
> 
> 



Re: [PATCH v2 3/3] drm/etnaviv: use a 32 bit mask as coherent DMA mask

2021-12-01 Thread Robin Murphy

On 2021-12-01 13:41, Lucas Stach wrote:

Hi Robin,

Am Mittwoch, dem 01.12.2021 um 12:50 + schrieb Robin Murphy:

Sorry I missed this earlier...

On 2021-09-07 17:49, Michael Walle wrote:

The STLB and the first command buffer (which is used to set up the TLBs)
has a 32 bit size restriction in hardware. There seems to be no way to
specify addresses larger than 32 bit. Keep it simple and restict the
addresses to the lower 4 GiB range for all coherent DMA memory
allocations.

Please note, that platform_device_alloc() will initialize dev->dma_mask
to point to pdev->platform_dma_mask, thus dma_set_mask() will work as
expected.

While at it, move the dma_mask setup code to the of_dma_configure() to
keep all the DMA setup code next to each other.

Suggested-by: Lucas Stach 
Signed-off-by: Michael Walle 
---
   drivers/gpu/drm/etnaviv/etnaviv_drv.c | 20 ++--
   1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c 
b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
index 54eb653ca295..0b756ecb1bc2 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -613,6 +613,24 @@ static int etnaviv_pdev_probe(struct platform_device *pdev)
component_match_add(dev, &match, compare_str, names[i]);
}
   
+	/*

+* PTA and MTLB can have 40 bit base addresses, but
+* unfortunately, an entry in the MTLB can only point to a
+* 32 bit base address of a STLB. Moreover, to initialize the
+* MMU we need a command buffer with a 32 bit address because
+* without an MMU there is only an indentity mapping between
+* the internal 32 bit addresses and the bus addresses.
+*
+* To make things easy, we set the dma_coherent_mask to 32
+* bit to make sure we are allocating the command buffers and
+* TLBs in the lower 4 GiB address space.
+*/
+   if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(40)) ||
+   dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32))) {


Since AFAICS you're not changing the default dma_mask pointer to point
to some storage other than the coherent mask, the dma_set_mask() call
effectively does nothing and both masks will end up reading back as 32 bits.


 From what I can see the dma_mask has allocated storage in the platform
device and does not point to the coherent dma mask, see
setup_pdev_dma_masks().


Urgh, apologies for the confusion - seems I had one of those mental 
short-circuits and was utterly convinced that that's what the platform 
device setup did, but of course it's only the fallback case in 
of_dma_configure(). Sorry for the noise!


Cheers,
Robin.


Re: [PATCH v10 4/8] drm/ingenic: Add dw-hdmi driver for jz4780

2021-12-01 Thread Paul Cercueil

Hi Nikolaus, Mark,

Le mer., déc. 1 2021 at 14:51:51 +0100, H. Nikolaus Schaller 
 a écrit :

Hi,


 Am 01.12.2021 um 14:39 schrieb Mark Brown :

 On Wed, Dec 01, 2021 at 01:02:45PM +, Paul Cercueil wrote:

 Le mar., nov. 30 2021 at 22:26:37 +0100, H. Nikolaus Schaller



 +  regulator = devm_regulator_get_optional(&pdev->dev, "hdmi-5v");
 +  if (IS_ERR(regulator)) {
 +  ret = PTR_ERR(regulator);


 Why is this using _optional()?  This should only be done when the 
supply

 can be physically absent


There can be +5V for HDMI but without a regulator that is visible to 
or controllable

by the driver.


There is always a power supply though. Either a controllable one 
(through e.g. a GPIO), or it's just connected to the mains +5V; the pin 
is never left floating. In the second case, in DTS the "hdmi-5v" would 
be connected to some 5v regulator, even if it's just a dummy VCC-5V 
regulator. So Mark has a point.


So hdmi-5v can be simply missing in DTS in which case the driver does 
not need to

care about. The driver just can't turn it on or off.


Please make it mandatory in DTS then, and use devm_regulator_get() in 
the driver.


Cheers,
-Paul


 (in which case I'd expect to see special
 handling).


The special case is to not enable/disable the regulator if it does 
not exist
and assume that there is hardware providing it otherwise (the driver 
can't know

that except by using get_optional). This is done by the code below


 +  if (IS_ERR(regulator)) {


...


 +  if (!regulator)
 +  return 0;

 +  ret = regulator_enable(regulator);


...

BR and thanks,
Nikolaus









Re: [PATCH v10 4/8] drm/ingenic: Add dw-hdmi driver for jz4780

2021-12-01 Thread H. Nikolaus Schaller
Hi,

> Am 01.12.2021 um 14:39 schrieb Mark Brown :
> 
> On Wed, Dec 01, 2021 at 01:02:45PM +, Paul Cercueil wrote:
>> Le mar., nov. 30 2021 at 22:26:37 +0100, H. Nikolaus Schaller
> 
>>> +   regulator = devm_regulator_get_optional(&pdev->dev, "hdmi-5v");
>>> +   if (IS_ERR(regulator)) {
>>> +   ret = PTR_ERR(regulator);
> 
> Why is this using _optional()?  This should only be done when the supply
> can be physically absent

There can be +5V for HDMI but without a regulator that is visible to or 
controllable
by the driver.

So hdmi-5v can be simply missing in DTS in which case the driver does not need 
to
care about. The driver just can't turn it on or off.

> (in which case I'd expect to see special
> handling).

The special case is to not enable/disable the regulator if it does not exist
and assume that there is hardware providing it otherwise (the driver can't know
that except by using get_optional). This is done by the code below

>>> +   if (IS_ERR(regulator)) {

...

> + if (!regulator)
> + return 0;
> 
> + ret = regulator_enable(regulator);

...

BR and thanks,
Nikolaus






Re: [PATCH v10 4/8] drm/ingenic: Add dw-hdmi driver for jz4780

2021-12-01 Thread Mark Brown
On Wed, Dec 01, 2021 at 01:02:45PM +, Paul Cercueil wrote:
> Le mar., nov. 30 2021 at 22:26:37 +0100, H. Nikolaus Schaller

> > +   regulator = devm_regulator_get_optional(&pdev->dev, "hdmi-5v");
> > +   if (IS_ERR(regulator)) {
> > +   ret = PTR_ERR(regulator);

Why is this using _optional()?  This should only be done when the supply
can be physically absent (in which case I'd expect to see special
handling).


signature.asc
Description: PGP signature


  1   2   >