Re: [PATCH v14 4/4] RDMA/mlx5: Support dma-buf based userspace memory region

2020-12-08 Thread Leon Romanovsky
On Tue, Dec 08, 2020 at 02:39:15PM -0800, Jianxin Xiong wrote:
> Implement the new driver method 'reg_user_mr_dmabuf'.  Utilize the core
> functions to import dma-buf based memory region and update the mappings.
>
> Add code to handle dma-buf related page fault.
>
> Signed-off-by: Jianxin Xiong 
> Reviewed-by: Sean Hefty 
> Acked-by: Michael J. Ruhl 
> Acked-by: Christian Koenig 
> Acked-by: Daniel Vetter 
> ---
>  drivers/infiniband/hw/mlx5/main.c|   2 +
>  drivers/infiniband/hw/mlx5/mlx5_ib.h |  18 +
>  drivers/infiniband/hw/mlx5/mr.c  | 128 
> +--
>  drivers/infiniband/hw/mlx5/odp.c |  86 +--
>  4 files changed, 225 insertions(+), 9 deletions(-)

<...>

>
> +
> + umem = ib_umem_dmabuf_get(&dev->ib_dev, offset, length, fd, 
> access_flags,
> +   &mlx5_ib_dmabuf_attach_ops);
> + if (IS_ERR(umem)) {
> + mlx5_ib_dbg(dev, "umem get failed (%ld)\n", PTR_ERR(umem));
> + return ERR_PTR(PTR_ERR(umem));

return ERR_CAST(umem);

> + }

<...>

> + dma_resv_lock(umem_dmabuf->attach->dmabuf->resv, NULL);
> + err = ib_umem_dmabuf_map_pages(umem_dmabuf);
> + if (!err) {
> + page_size = mlx5_umem_find_best_pgsz(&umem_dmabuf->umem, mkc,
> +  log_page_size, 0,
> +  umem_dmabuf->umem.iova);
> + if (unlikely(page_size < PAGE_SIZE)) {
> + ib_umem_dmabuf_unmap_pages(umem_dmabuf);
> + err = -EINVAL;
> + } else {
> + err = mlx5_ib_update_mr_pas(mr, xlt_flags);
> + }
> + }
> + dma_resv_unlock(umem_dmabuf->attach->dmabuf->resv);

Let's write this section in kernel coding style, please

dma_resv_lock(umem_dmabuf->attach->dmabuf->resv, NULL);
err = ib_umem_dmabuf_map_pages(umem_dmabuf);
if (err) {
  dma_resv_unlock(umem_dmabuf->attach->dmabuf->resv);
  return err;
}
.

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


Re: [PATCH v14 1/4] RDMA/umem: Support importing dma-buf as user memory region

2020-12-08 Thread Leon Romanovsky
On Tue, Dec 08, 2020 at 02:39:12PM -0800, Jianxin Xiong wrote:
> Dma-buf is a standard cross-driver buffer sharing mechanism that can be
> used to support peer-to-peer access from RDMA devices.
>
> Device memory exported via dma-buf is associated with a file descriptor.
> This is passed to the user space as a property associated with the
> buffer allocation. When the buffer is registered as a memory region,
> the file descriptor is passed to the RDMA driver along with other
> parameters.
>
> Implement the common code for importing dma-buf object and mapping
> dma-buf pages.
>
> Signed-off-by: Jianxin Xiong 
> Reviewed-by: Sean Hefty 
> Acked-by: Michael J. Ruhl 
> Acked-by: Christian Koenig 
> Acked-by: Daniel Vetter 
> ---
>  drivers/infiniband/core/Makefile  |   2 +-
>  drivers/infiniband/core/umem.c|   3 +
>  drivers/infiniband/core/umem_dmabuf.c | 174 
> ++
>  include/rdma/ib_umem.h|  47 -
>  4 files changed, 222 insertions(+), 4 deletions(-)
>  create mode 100644 drivers/infiniband/core/umem_dmabuf.c

<...>

> +int ib_umem_dmabuf_map_pages(struct ib_umem_dmabuf *umem_dmabuf)
> +{
> + struct sg_table *sgt;
> + struct scatterlist *sg;
> + struct dma_fence *fence;
> + unsigned long start, end, cur = 0;
> + unsigned int nmap = 0;
> + int i;
> +
> + dma_resv_assert_held(umem_dmabuf->attach->dmabuf->resv);
> +
> + if (umem_dmabuf->sgt)
> + goto wait_fence;
> +
> + sgt = dma_buf_map_attachment(umem_dmabuf->attach, DMA_BIDIRECTIONAL);
> + if (IS_ERR(sgt))
> + return PTR_ERR(sgt);
> +
> + /* modify the sg list in-place to match umem address and length */
> +
> + start = ALIGN_DOWN(umem_dmabuf->umem.address, PAGE_SIZE);
> + end = ALIGN(umem_dmabuf->umem.address + umem_dmabuf->umem.length,
> + PAGE_SIZE);
> + for_each_sgtable_dma_sg(sgt, sg, i) {
> + if (start < cur + sg_dma_len(sg) && cur < end)
> + nmap++;
> + if (cur <= start && start < cur + sg_dma_len(sg)) {
> + unsigned long offset = start - cur;
> +
> + umem_dmabuf->first_sg = sg;
> + umem_dmabuf->first_sg_offset = offset;
> + sg_dma_address(sg) += offset;
> + sg_dma_len(sg) -= offset;
> + cur += offset;
> + }
> + if (cur < end && end <= cur + sg_dma_len(sg)) {
> + unsigned long trim = cur + sg_dma_len(sg) - end;
> +
> + umem_dmabuf->last_sg = sg;
> + umem_dmabuf->last_sg_trim = trim;
> + sg_dma_len(sg) -= trim;
> + break;
> + }
> + cur += sg_dma_len(sg);
> + }
> +
> + umem_dmabuf->umem.sg_head.sgl = umem_dmabuf->first_sg;
> + umem_dmabuf->umem.sg_head.nents = nmap;
> + umem_dmabuf->umem.nmap = nmap;
> + umem_dmabuf->sgt = sgt;
> +
> +wait_fence:
> + /*
> +  * Although the sg list is valid now, the content of the pages
> +  * may be not up-to-date. Wait for the exporter to finish
> +  * the migration.
> +  */
> + fence = dma_resv_get_excl(umem_dmabuf->attach->dmabuf->resv);
> + if (fence)
> + return dma_fence_wait(fence, false);

You called to dma_buf_map_attachment() earlier in this function, so if
you return an error here, the dma_buf won't be unmapped in pagefault_dmabuf_mr()

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


Re: [PATCH v2 2/2] drm: automatic legacy gamma support

2020-12-08 Thread kernel test robot
Hi Tomi,

I love your patch! Perhaps something to improve:

[auto build test WARNING on drm-intel/for-linux-next]
[also build test WARNING on linus/master v5.10-rc7]
[cannot apply to drm-tip/drm-tip anholt/for-next next-20201208]
[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/Tomi-Valkeinen/drm-fix-and-cleanup-legacy-gamma-support/20201208-215917
base:   git://anongit.freedesktop.org/drm-intel for-linux-next
config: x86_64-randconfig-s021-20201208 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-15) 9.3.0
reproduce:
# apt-get install sparse
# sparse version: v0.6.3-179-ga00755aa-dirty
# 
https://github.com/0day-ci/linux/commit/82a704a10c400f58d4b9b44e6def07cc7d6bab20
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review 
Tomi-Valkeinen/drm-fix-and-cleanup-legacy-gamma-support/20201208-215917
git checkout 82a704a10c400f58d4b9b44e6def07cc7d6bab20
# save the attached .config to linux build tree
make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=x86_64 

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

All warnings (new ones prefixed by >>):

   In file included from drivers/gpu/drm/drm_ioc32.c:38:
>> drivers/gpu/drm/drm_crtc_internal.h:121:17: warning: 'struct 
>> drm_modeset_acquire_ctx' declared inside parameter list will not be visible 
>> outside of this definition or declaration
 121 |  struct drm_modeset_acquire_ctx *ctx);
 | ^~~

vim +121 drivers/gpu/drm/drm_crtc_internal.h

   116  
   117  bool drm_crtc_supports_legacy_gamma(struct drm_crtc *crtc);
   118  int drm_crtc_legacy_gamma_set(struct drm_crtc *crtc,
   119u16 *red, u16 *green, u16 *blue,
   120uint32_t size,
 > 121struct drm_modeset_acquire_ctx *ctx);
   122  

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


.config.gz
Description: application/gzip
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v2] [PATCH] drm/amdgpu: Initialise drm_gem_object_funcs for imported BOs

2020-12-08 Thread kernel test robot
Hi Andrey,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on drm-exynos/exynos-drm-next]
[also build test WARNING on drm-intel/for-linux-next 
tegra-drm/drm/tegra/for-next drm-tip/drm-tip linus/master v5.10-rc7 
next-20201208]
[cannot apply to drm/drm-next]
[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/Andrey-Grodzovsky/drm-amdgpu-Initialise-drm_gem_object_funcs-for-imported-BOs/20201209-041733
base:   https://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos.git 
exynos-drm-next
config: xtensa-randconfig-r004-20201208 (attached as .config)
compiler: xtensa-linux-gcc (GCC) 9.3.0
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/a7b4d98b3660452b6787b39dc59980606b462ff3
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review 
Andrey-Grodzovsky/drm-amdgpu-Initialise-drm_gem_object_funcs-for-imported-BOs/20201209-041733
git checkout a7b4d98b3660452b6787b39dc59980606b462ff3
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross 
ARCH=xtensa 

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

All warnings (new ones prefixed by >>):

   In file included from include/drm/drm_mm.h:49,
from include/drm/drm_vma_manager.h:26,
from include/drm/drm_gem.h:40,
from include/drm/drm_gem_ttm_helper.h:8,
from drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c:36:
   drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c: In function 
'amdgpu_gem_create_ioctl':
>> drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c:288:14: warning: format '%ld' 
>> expects argument of type 'long int', but argument 3 has type 'uint64_t' {aka 
>> 'long long unsigned int'} [-Wformat=]
 288 |DRM_DEBUG("Failed to allocate GEM object (%ld, %d, %u, %d)\n",
 |  ^~~
 289 |   size, initial_domain, args->in.alignment, r);
 |   
 |   |
 |   uint64_t {aka long long unsigned int}
   include/drm/drm_print.h:504:25: note: in definition of macro 'DRM_DEBUG'
 504 |  __drm_dbg(DRM_UT_CORE, fmt, ##__VA_ARGS__)
 | ^~~
   drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c:288:48: note: format string is 
defined here
 288 |DRM_DEBUG("Failed to allocate GEM object (%ld, %d, %u, %d)\n",
 |  ~~^
 ||
 |long int
 |  %lld
   In file included from include/drm/drm_mm.h:49,
from include/drm/drm_vma_manager.h:26,
from include/drm/drm_gem.h:40,
from include/drm/drm_gem_ttm_helper.h:8,
from drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c:36:
>> drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c:288:14: warning: format '%u' expects 
>> argument of type 'unsigned int', but argument 5 has type '__u64' {aka 'long 
>> long unsigned int'} [-Wformat=]
 288 |DRM_DEBUG("Failed to allocate GEM object (%ld, %d, %u, %d)\n",
 |  ^~~
 289 |   size, initial_domain, args->in.alignment, r);
 | ~~
 | |
 | __u64 {aka long long unsigned 
int}
   include/drm/drm_print.h:504:25: note: in definition of macro 'DRM_DEBUG'
 504 |  __drm_dbg(DRM_UT_CORE, fmt, ##__VA_ARGS__)
 | ^~~
   drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c:288:56: note: format string is 
defined here
 288 |DRM_DEBUG("Failed to allocate GEM object (%ld, %d, %u, %d)\n",
 |   ~^
 ||
 |unsigned int
 |   %llu
   In file included from drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c:38:
   At top level:
   drivers/gpu/drm/amd/amdgpu/amdgpu.h:198:19: warning: 'no_system_mem_limit' 
d

Re: [PATCH v2] [PATCH] drm/amdgpu: Initialise drm_gem_object_funcs for imported BOs

2020-12-08 Thread Alex Deucher
On Tue, Dec 8, 2020 at 3:16 PM Andrey Grodzovsky
 wrote:
>
> For BOs imported from outside of amdgpu, setting of amdgpu_gem_object_funcs
> was missing in amdgpu_dma_buf_create_obj. Fix by refactoring BO creation
> and amdgpu_gem_object_funcs setting into single function called
> from both code paths.
>
> Fixes: d693def4fd1c ("drm: Remove obsolete GEM and PRIME callbacks
> from struct drm_driver")
>
> v2: Use use amdgpu_gem_object_create() directly
>
> Signed-off-by: Andrey Grodzovsky 
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c |  8 --
>  drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 41 
> -
>  2 files changed, 29 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
> index e5919ef..e42175e 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
> @@ -424,6 +424,7 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, struct 
> dma_buf *dma_buf)
> struct amdgpu_device *adev = drm_to_adev(dev);
> struct amdgpu_bo *bo;
> struct amdgpu_bo_param bp;
> +   struct drm_gem_object *gobj;
> int ret;
>
> memset(&bp, 0, sizeof(bp));
> @@ -434,17 +435,20 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, 
> struct dma_buf *dma_buf)
> bp.type = ttm_bo_type_sg;
> bp.resv = resv;
> dma_resv_lock(resv, NULL);
> -   ret = amdgpu_bo_create(adev, &bp, &bo);
> +   ret = amdgpu_gem_object_create(adev, dma_buf->size, PAGE_SIZE,
> +   AMDGPU_GEM_DOMAIN_CPU,
> +   0, ttm_bo_type_sg, resv, &gobj);
> if (ret)
> goto error;
>
> +   bo = gem_to_amdgpu_bo(gobj);
> bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
> bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
> if (dma_buf->ops != &amdgpu_dmabuf_ops)
> bo->prime_shared_count = 1;
>
> dma_resv_unlock(resv);
> -   return &bo->tbo.base;
> +   return gobj;
>
>  error:
> dma_resv_unlock(resv);
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> index c9f94fb..ccf4d80 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> @@ -70,26 +70,12 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, 
> unsigned long size,
> bp.type = type;
> bp.resv = resv;
> bp.preferred_domain = initial_domain;
> -retry:
> bp.flags = flags;
> bp.domain = initial_domain;
> r = amdgpu_bo_create(adev, &bp, &bo);
> -   if (r) {
> -   if (r != -ERESTARTSYS) {
> -   if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) {
> -   flags &= 
> ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
> -   goto retry;
> -   }
> -
> -   if (initial_domain == AMDGPU_GEM_DOMAIN_VRAM) {
> -   initial_domain |= AMDGPU_GEM_DOMAIN_GTT;
> -   goto retry;
> -   }
> -   DRM_DEBUG("Failed to allocate GEM object (%ld, %d, 
> %u, %d)\n",
> - size, initial_domain, alignment, r);
> -   }
> +   if (r)
> return r;
> -   }
> +
> *obj = &bo->tbo.base;
> (*obj)->funcs = &amdgpu_gem_object_funcs;
>
> @@ -239,7 +225,7 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void 
> *data,
> uint64_t size = args->in.bo_size;
> struct dma_resv *resv = NULL;
> struct drm_gem_object *gobj;
> -   uint32_t handle;
> +   uint32_t handle, initial_domain;
> int r;
>
> /* reject invalid gem flags */
> @@ -283,9 +269,28 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void 
> *data,
> resv = vm->root.base.bo->tbo.base.resv;
> }
>
> +retry:
> +   initial_domain = (u32)(0x & args->in.domains);
> r = amdgpu_gem_object_create(adev, size, args->in.alignment,
> -(u32)(0x & args->in.domains),
> +initial_domain,
>  flags, ttm_bo_type_device, resv, &gobj);
> +   if (r) {
> +   if (r != -ERESTARTSYS) {
> +   if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) {
> +   flags &= 
> ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
> +   goto retry;
> +   }
> +
> +   if (initial_domain == AMDGPU_GEM_DOMAIN_VRAM) {
> +   initial_domain |= AMDGPU_GEM_DOMAIN_GTT;
> +   goto retry;
> +   }
> +   DRM_DEBUG("Failed to allocate GEM object

linux-next: build failure after merge of the drm tree

2020-12-08 Thread Stephen Rothwell
Hi all,

After merging the drm tree, today's linux-next build (x86_64 allmodconfig)
failed like this:

drivers/gpu/drm/i915/gt/intel_mocs.c: In function 'get_mocs_settings':
drivers/gpu/drm/i915/gt/intel_mocs.c:363:22: error: 'GEN11_NUM_MOCS_ENTRIES' 
undeclared (first use in this function); did you mean 'GEN9_NUM_MOCS_ENTRIES'?
  363 |   table->n_entries = GEN11_NUM_MOCS_ENTRIES;
  |  ^~
  |  GEN9_NUM_MOCS_ENTRIES
drivers/gpu/drm/i915/gt/intel_mocs.c:363:22: note: each undeclared identifier 
is reported only once for each function it appears in

Caused by commit

  2606b269234b ("drm/i915/dg1: Define MOCS table for DG1")

interacting with commit

  7c5c15dffe1e ("drm/i915/gt: Declare gen9 has 64 mocs entries!")

from the drm-intel-fixes tree.

I have applied the following merge fix patch for today:

From: Stephen Rothwell 
Date: Wed, 9 Dec 2020 12:47:45 +1100
Subject: [PATCH] fixup for "drm/i915/gt: Declare gen9 has 64 mocs entries!"

Signed-off-by: Stephen Rothwell 
---
 drivers/gpu/drm/i915/gt/intel_mocs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_mocs.c 
b/drivers/gpu/drm/i915/gt/intel_mocs.c
index c60ca62b38df..ab6870242e18 100644
--- a/drivers/gpu/drm/i915/gt/intel_mocs.c
+++ b/drivers/gpu/drm/i915/gt/intel_mocs.c
@@ -360,7 +360,7 @@ static unsigned int get_mocs_settings(const struct 
drm_i915_private *i915,
if (IS_DG1(i915)) {
table->size = ARRAY_SIZE(dg1_mocs_table);
table->table = dg1_mocs_table;
-   table->n_entries = GEN11_NUM_MOCS_ENTRIES;
+   table->n_entries = GEN9_NUM_MOCS_ENTRIES;
} else if (INTEL_GEN(i915) >= 12) {
table->size  = ARRAY_SIZE(tgl_mocs_table);
table->table = tgl_mocs_table;
-- 
2.29.2

-- 
Cheers,
Stephen Rothwell


pgpakRx1Rfj4j.pgp
Description: OpenPGP digital signature
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH V2] drm/vkms: Add setup and testing information

2020-12-08 Thread Daniel Vetter
On Wed, Dec 09, 2020 at 02:07:35AM +0530, Sumera Priyadarsini wrote:
> Update the vkms documentation to contain steps to:
> 
>  - setup the vkms driver
>  - run tests using igt
> 
> Signed-off-by: Sumera Priyadarsini 
> ___
> Changes in v2:
>  - Change heading to title case (Daniel)
>  - Add examples to run tests directly (Daniel)
>  - Add examples to run subtests (Melissa)
> ---
>  Documentation/gpu/vkms.rst | 67 ++
>  1 file changed, 67 insertions(+)
> 
> diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst
> index 13bab1d93bb3..d6739fbbe503 100644
> --- a/Documentation/gpu/vkms.rst
> +++ b/Documentation/gpu/vkms.rst
> @@ -7,6 +7,73 @@
>  .. kernel-doc:: drivers/gpu/drm/vkms/vkms_drv.c
> :doc: vkms (Virtual Kernel Modesetting)
>  
> +Setup
> +=
> +
> +The VKMS driver can be setup with the following steps:
> +
> +To check if VKMS is loaded, run::
> +
> +  lsmod | grep vkms
> +
> +This should list the VKMS driver. If no output is obtained, then
> +you need to enable and/or load the VKMS driver.
> +Ensure that the VKMS driver has been set as a loadable module in your
> +kernel config file. Do::
> +
> +  make nconfig
> +
> +  Go to `Device Drivers> Graphics support`
> +
> +  Enable `Virtual KMS (EXPERIMENTAL)`
> +
> +Compile and build the kernel for the changes to get reflected.
> +Now, to load the driver, use::
> +
> +  sudo modprobe vkms
> +
> +On running the lsmod command now, the VKMS driver will appear listed.
> +You can also observe the driver being loaded in the dmesg logs.
> +
> +To disable the driver, use ::
> +
> +  sudo modprobe -r vkms
> +
> +Testing With IGT
> +
> +
> +The IGT GPU Tools is a test suite used specifically for debugging and
> +development of the DRM drivers.
> +The IGT Tools can be installed from
> +`here `_ .
> +
> +The tests need to be run without a compositor, so you need to switch to text
> +only mode. You can do this by::
> +
> +  sudo systemctl isolate multi-user.target
> +
> +To return to graphical mode, do::
> +
> +  sudo systemctl isolate graphical.target
> +
> +Once you are in text only mode, you can run tests using the --device switch
> +or IGT_DEVICE variable to specify the device filter for the driver we want
> +to test::
> +
> +  sudo ./build/tests/ --device "sys:/sys/devices/platform/vkms"
> +  sudo IGT_DEVICE="sys:/sys/devices/platform/vkms" ./build/tests/ test>
> +
> +For example, to test the functionality of the writeback library,
> +we can run the kms_writeback test::
> +
> +  sudo ./build/tests/kms_writeback --device "sys:/sys/devices/platform/vkms"
> +  sudo IGT_DEVICE="sys:/sys/devices/platform/vkms" 
> ./build/tests/kms_writeback
> +
> +You can also run subtests if you do not want to run the entire test::
> +
> +  sudo ./build/tests/kms_flip --run-subtest basic-plain-flip --device 
> "sys:/sys/devices/platform/vkms"
> +  sudo IGT_DEVICE="sys:/sys/devices/platform/vkms" ./build/tests/kms_flip 
> --run-subtest basic-plain-flip

Does IGT_DEVICE also work with run-tests.sh? Aside from my curious
question, patch looks good to me, thanks a lot.

Reviewed-by: Daniel Vetter 

> +
>  TODO
>  
>  
> -- 
> 2.25.1
> 

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


Re: [PATCH v2 1/2] drm: add legacy support for using degamma for gamma

2020-12-08 Thread Daniel Vetter
On Tue, Dec 08, 2020 at 05:55:11PM +0200, Laurent Pinchart wrote:
> Hi Tomi,
> 
> Thank you for the patch.
> 
> On Tue, Dec 08, 2020 at 03:57:58PM +0200, Tomi Valkeinen wrote:
> > We currently have drm_atomic_helper_legacy_gamma_set() helper which can
> > be used to handle legacy gamma-set ioctl.
> > drm_atomic_helper_legacy_gamma_set() sets GAMMA_LUT, and clears
> > CTM and DEGAMMA_LUT. This works fine on HW where we have either:
> > 
> > degamma -> ctm -> gamma -> out
> > 
> > or
> > 
> > ctm -> gamma -> out
> > 
> > However, if the HW has gamma table before ctm, the atomic property
> > should be DEGAMMA_LUT, and thus we have:
> > 
> > degamma -> ctm -> out
> > 
> > This is fine for userspace which sets gamma table using the properties,
> > as the userspace can check for the existence of gamma & degamma, but the
> > legacy gamma-set ioctl does not work.
> > 
> > This patch fixes the issue by changing
> > drm_atomic_helper_legacy_gamma_set() so that GAMMA_LUT will be used if
> > it exists, and DEGAMMA_LUT will be used as a fallback.
> > 
> > Signed-off-by: Tomi Valkeinen 
> 
> Reviewed-by: Laurent Pinchart 
> 
> > ---
> >  drivers/gpu/drm/drm_atomic_helper.c | 15 ---
> >  drivers/gpu/drm/drm_color_mgmt.c|  4 
> >  drivers/gpu/drm/drm_fb_helper.c |  8 ++--
> >  include/drm/drm_crtc.h  |  3 +++
> >  4 files changed, 25 insertions(+), 5 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
> > b/drivers/gpu/drm/drm_atomic_helper.c
> > index ba1507036f26..117b186fe646 100644
> > --- a/drivers/gpu/drm/drm_atomic_helper.c
> > +++ b/drivers/gpu/drm/drm_atomic_helper.c
> > @@ -3512,6 +3512,10 @@ EXPORT_SYMBOL(drm_atomic_helper_page_flip_target);
> >   * that support color management through the DEGAMMA_LUT/GAMMA_LUT
> >   * properties. See drm_crtc_enable_color_mgmt() and the containing chapter 
> > for
> >   * how the atomic color management and gamma tables work.
> > + *
> > + * This function uses the GAMMA_LUT or DEGAMMA_LUT property for the gamma 
> > table.
> > + * GAMMA_LUT property is used if it exists, and DEGAMMA_LUT property is 
> > used as
> > + * a fallback.
> >   */
> >  int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
> >u16 *red, u16 *green, u16 *blue,
> > @@ -3526,6 +3530,9 @@ int drm_atomic_helper_legacy_gamma_set(struct 
> > drm_crtc *crtc,
> > int i, ret = 0;
> > bool replaced;
> >  
> > +   if (!crtc->has_gamma_prop && !crtc->has_degamma_prop)
> > +   return -ENODEV;
> > +
> > state = drm_atomic_state_alloc(crtc->dev);
> > if (!state)
> > return -ENOMEM;
> > @@ -3554,10 +3561,12 @@ int drm_atomic_helper_legacy_gamma_set(struct 
> > drm_crtc *crtc,
> > goto fail;
> > }
> >  
> > -   /* Reset DEGAMMA_LUT and CTM properties. */
> > -   replaced  = drm_property_replace_blob(&crtc_state->degamma_lut, NULL);
> > +   /* Set GAMMA/DEGAMMA_LUT and reset DEGAMMA/GAMMA_LUT and CTM */
> > +   replaced  = drm_property_replace_blob(&crtc_state->degamma_lut,
> > + crtc->has_gamma_prop ? NULL : 
> > blob);
> > replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL);
> > -   replaced |= drm_property_replace_blob(&crtc_state->gamma_lut, blob);
> > +   replaced |= drm_property_replace_blob(&crtc_state->gamma_lut,
> > + crtc->has_gamma_prop ? blob : 
> > NULL);
> > crtc_state->color_mgmt_changed |= replaced;
> >  
> > ret = drm_atomic_commit(state);
> > diff --git a/drivers/gpu/drm/drm_color_mgmt.c 
> > b/drivers/gpu/drm/drm_color_mgmt.c
> > index 3bcabc2f6e0e..956e59d5f6a7 100644
> > --- a/drivers/gpu/drm/drm_color_mgmt.c
> > +++ b/drivers/gpu/drm/drm_color_mgmt.c
> > @@ -176,6 +176,8 @@ void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
> >degamma_lut_size);
> > }
> >  
> > +   crtc->has_degamma_prop = !!degamma_lut_size;
> > +
> > if (has_ctm)
> > drm_object_attach_property(&crtc->base,
> >config->ctm_property, 0);
> > @@ -187,6 +189,8 @@ void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
> >config->gamma_lut_size_property,
> >gamma_lut_size);
> > }
> > +
> > +   crtc->has_gamma_prop = !!gamma_lut_size;
> >  }
> >  EXPORT_SYMBOL(drm_crtc_enable_color_mgmt);
> >  
> > diff --git a/drivers/gpu/drm/drm_fb_helper.c 
> > b/drivers/gpu/drm/drm_fb_helper.c
> > index 25edf670867c..b0906ef97617 100644
> > --- a/drivers/gpu/drm/drm_fb_helper.c
> > +++ b/drivers/gpu/drm/drm_fb_helper.c
> > @@ -1001,6 +1001,9 @@ static int setcmap_atomic(struct fb_cmap *cmap, 
> > struct fb_info *info)
> > drm_client_for_each_modeset(modeset, &fb_helper->client) {
> > crtc = modeset->crtc;
> >  
> > +   if (!crtc->has_gamma_prop && !crtc->has_degamma_prop)
> > + 

Re: [PATCH] drm/tidss: Use the new api devm_drm_irq_install

2020-12-08 Thread Daniel Vetter
On Tue, Dec 08, 2020 at 03:50:59PM +0800, Tian Tao wrote:
> Use devm_drm_irq_install to register interrupts so that
> drm_irq_uninstall is not needed to be called.
> 
> Signed-off-by: Tian Tao 

There's another drm_irq_install in the error path. But I'm not sure this
is safe since you're chaning the order in which things get cleaned up now.
So leaving this up to Tomi.
-Daniel

> ---
>  drivers/gpu/drm/tidss/tidss_drv.c | 4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/tidss/tidss_drv.c 
> b/drivers/gpu/drm/tidss/tidss_drv.c
> index 66e3c86e..48e1f9d 100644
> --- a/drivers/gpu/drm/tidss/tidss_drv.c
> +++ b/drivers/gpu/drm/tidss/tidss_drv.c
> @@ -173,7 +173,7 @@ static int tidss_probe(struct platform_device *pdev)
>   goto err_runtime_suspend;
>   }
>  
> - ret = drm_irq_install(ddev, irq);
> + ret = devm_irq_install(ddev, irq);
>   if (ret) {
>   dev_err(dev, "drm_irq_install failed: %d\n", ret);
>   goto err_runtime_suspend;
> @@ -219,8 +219,6 @@ static int tidss_remove(struct platform_device *pdev)
>  
>   drm_atomic_helper_shutdown(ddev);
>  
> - drm_irq_uninstall(ddev);
> -
>  #ifndef CONFIG_PM
>   /* If we don't have PM, we need to call suspend manually */
>   dispc_runtime_suspend(tidss->dispc);
> -- 
> 2.7.4
> 

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


Re: [PATCH v3 4/6] drm/atomic: Avoid unused-but-set-variable warning on for_each_old_plane_in_state

2020-12-08 Thread Daniel Vetter
On Mon, Dec 07, 2020 at 11:20:58AM +0800, Liu Ying wrote:
> Artifically use 'plane' and 'old_plane_state' to avoid 'not used' warning.
> The precedent has already been set by other macros in the same file.
> 
> Signed-off-by: Liu Ying 

Acked-by: Daniel Vetter 

I'm assuming someone will push this to drm-misc or some other tree. Should
probably land sooner than later.
-Daniel

> ---
> v2->v3:
> * Add a missing blank line.
> 
> v1->v2:
> * No change.
> 
>  include/drm/drm_atomic.h | 5 -
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
> index 54e051a..2e087d7 100644
> --- a/include/drm/drm_atomic.h
> +++ b/include/drm/drm_atomic.h
> @@ -888,7 +888,10 @@ void drm_state_dump(struct drm_device *dev, struct 
> drm_printer *p);
>(__i)++)   \
>   for_each_if ((__state)->planes[__i].ptr &&  \
>((plane) = (__state)->planes[__i].ptr, \
> -   (old_plane_state) = 
> (__state)->planes[__i].old_state, 1))
> +   (void)(plane) /* Only to avoid 
> unused-but-set-variable warning */, \
> +   (old_plane_state) = 
> (__state)->planes[__i].old_state, \
> +   (void)(old_plane_state) /* Only to avoid 
> unused-but-set-variable warning */, 1))
> +
>  /**
>   * for_each_new_plane_in_state - iterate over all planes in an atomic update
>   * @__state: &struct drm_atomic_state pointer
> -- 
> 2.7.4
> 

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


Re: [PATCH] drm: rework description of primary and cursor planes

2020-12-08 Thread Daniel Vetter
On Sun, Dec 06, 2020 at 04:34:15PM +, Simon Ser wrote:
> The previous wording could be understood by user-space evelopers as "a
> primary/cursor plane is only compatible with a single CRTC" [1].
> 
> Reword the planes description to make it clear the DRM-internal
> drm_crtc.primary and drm_crtc.cursor planes are for legacy uAPI.
> 
> [1]: https://github.com/swaywm/wlroots/pull/2333#discussion_r456788057
> 
> Signed-off-by: Simon Ser 
> Cc: Daniel Vetter 
> Cc: Pekka Paalanen 
> ---
>  drivers/gpu/drm/drm_crtc.c  |  3 +++
>  drivers/gpu/drm/drm_plane.c | 16 +---
>  2 files changed, 12 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index 74090fc3aa55..c71b134d663a 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -256,6 +256,9 @@ struct dma_fence *drm_crtc_create_fence(struct drm_crtc 
> *crtc)
>   * planes). For really simple hardware which has only 1 plane look at
>   * drm_simple_display_pipe_init() instead.
>   *
> + * The @primary and @cursor planes are only relevant for legacy uAPI, see
> + * &drm_crtc.primary and &drm_crtc.cursor.
> + *
>   * Returns:
>   * Zero on success, error code on failure.
>   */
> diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
> index e6231947f987..7a5697bc9e04 100644
> --- a/drivers/gpu/drm/drm_plane.c
> +++ b/drivers/gpu/drm/drm_plane.c
> @@ -49,14 +49,16 @@
>   * &struct drm_plane (possibly as part of a larger structure) and registers 
> it
>   * with a call to drm_universal_plane_init().
>   *
> - * Cursor and overlay planes are optional. All drivers should provide one
> - * primary plane per CRTC to avoid surprising userspace too much. See enum
> - * drm_plane_type for a more in-depth discussion of these special 
> uapi-relevant
> - * plane types. Special planes are associated with their CRTC by calling
> - * drm_crtc_init_with_planes().
> - *
>   * The type of a plane is exposed in the immutable "type" enumeration 
> property,
> - * which has one of the following values: "Overlay", "Primary", "Cursor".
> + * which has one of the following values: "Overlay", "Primary", "Cursor" (see
> + * enum drm_plane_type). A plane can be compatible with multiple CRTCs, see
> + * &drm_plane.possible_crtcs.
> + *
> + * Legacy uAPI doesn't expose the primary and cursor planes directly. DRM 
> core
> + * relies on the driver to set the primary and optionally the cursor plane 
> used
> + * for legacy IOCTLs. This is done by calling drm_crtc_init_with_planes(). 
> All
> + * drivers should provide one primary plane per CRTC to avoid surprising 
> legacy
> + * userspace too much.
>   */

Reviewed-by: Daniel Vetter 

I think maybe a follow up patch should document how userspace should
figure out how to line up the primary planes with the right crtcs (if it
wishes to know that information, it's not super useful aside from probably
good choice for a fullscreen fallback plane). See my reply on the old
thread.

And that patch should also add the code to drm_mode_config_validate() to
validate the possible_crtc masks for these. Something like

num_primary = 0; num_cursor = 0;

for_each_plane(plane) {
if (plane->type == primary) {
WARN_ON(!(plane->possible_crtcs & BIT(num_primary)));
num_primary++;
}

/* same for cursor */
}

WARN_ON(num_primary != dev->mode_config.num_crtcs);
}

Cheers, Daniel

>  
>  static unsigned int drm_num_planes(struct drm_device *dev)
> -- 
> 2.29.2
> 
> 

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


Re: [PATCH] drm: drivers may provide multiple primary planes per CRTC

2020-12-08 Thread Daniel Vetter
On Mon, Dec 07, 2020 at 09:10:00AM +, Simon Ser wrote:
> On Monday, December 7th, 2020 at 9:45 AM, Pekka Paalanen 
>  wrote:
> 
> > > > > > > - * Cursor and overlay planes are optional. All drivers should 
> > > > > > > provide one
> > > > > > > - * primary plane per CRTC to avoid surprising userspace too 
> > > > > > > much. See enum
> > > > > > > + * Cursor and overlay planes are optional. All drivers should 
> > > > > > > provide at least
> > > > > > > + * one primary plane per CRTC to avoid surprising userspace too 
> > > > > > > much. See enum
> > > > > >
> > > > > > I think that's even more confusing, since this reads like there 
> > > > > > could be
> > > > > > multiple primary planes for a specific CRTC. That's not the case, 
> > > > > > there'
> > > > > > only one pointer going from drm_crtc->primary to a drm_plane in the
> > > > > > kernel.
> > > > >
> > > > > There could be multiple primary planes *usable* for a specific CRTC 
> > > > > but
> > > > > just one used at a time, right?
> > > >
> > > > I'm not sure what you mean here, the crtc->primary link is invariant 
> > > > over
> > > > the lifetime of a driver load. You can't pick a different one, that's 
> > > > set
> > > > at driver init before drm_dev_register (and hence before userspace ever
> > > > sees anything).
> > >
> > > OK. I'm personally not very interested in documenting legacy bits, so 
> > > I'll skip
> > > that. I'm mainly interested here in making it clear possible_crtcs for a
> > > primary plane can have more than one bit set. Because of the paragraph in 
> > > the
> > > current docs, some user-space developers have understood "more than one 
> > > bit set
> > > in possible_crtcs for a primary plane is a kernel bug".
> > >
> > > I'll send a v2 that makes it clear these pointers are for legacy uAPI.
> >
> > Right, so this and what danvet said seem to be in direct conflict in
> > atomic uAPI, repeating above:
> >
> > > > I'm not sure what you mean here, the crtc->primary link is invariant 
> > > > over
> > > > the lifetime of a driver load. You can't pick a different one, that's 
> > > > set
> > > > at driver init before drm_dev_register (and hence before userspace ever
> > > > sees anything).
> >
> > But still, it is considered not a kernel bug that a primary plane has
> > more than one bit set in its possible_crtcs.
> >
> > If a primary plane has more than one bit set in possible_crtcs, and it
> > is not a kernel bug, then userspace expects to be able to choose any
> > of the multiple indicated possible CRTCs for this primary plane.
> >
> > Which way is it?
> >
> > Or, is there a different limitation that for each CRTC, there must be
> > exactly one primary plane with that CRTCs bit set in its possible_crtcs?
> >
> > IOW, you can have more CRTCs than primary planes in total, and you can
> > activate each CRTC alone, but you cannot activate all CRTCs
> > simultaneously because there are not enough primary planes for them?
> >
> > Representing it mathematically, the possible assignments according to
> > possible_crtcs while ignoring all other limitations are:
> > N CRTCs <-> M primary planes
> >
> > - Is N one or greater than one?
> > - Is M one or greater than one?
> 
> I think the current situation is that:
> 
> - It's perfectly fine for a driver to expose multiple bits in possible_crtcs.
>   User-space can attach the primary plane to any of these CRTCs (of course, a
>   primary plane still can only be attached to a single CRTC at a time). 
> Drivers
>   should provide as many primary planes as there are CRTCs.
> - The legacy API doesn't expose primary planes. Some legacy IOCTLs like
>   drmModeSetCrtc allow user-space to attach a FB directly to a CRTC. The 
> driver
>   needs to implicitly select a primary plane for this operation. That's the
>   only case where the internal CRTC → primary plane link is used in the 
> kernel.
> 
> Is this correct, Daniel?

Yup. atomic doesn't use crtc->primary link at all.

Pekka, where did you see an indication that this crtc->primary link is
used for atomic? My statement was only about legacy ioctl impact of
->primary. Atomic userspace can pick any plane it wants and consider that
the "primary" one (the hw/driver might reject that, but that's a different
issue).

> So I believe M > 1 and N > 1 is possible and isn't a kernel bug. For instance
> some drivers hardcode possible_crtcs to 0xFF (although it might be nicer to
> user-space to set the bitmask depending on the number of CRTCs, to avoid
> setting bits for non-existing CRTCs).

possible_crtcs for a primary plane has exactly the same constraints as
possible_crtcs for any other plane. The only additional constraint there
is that:
- first primary plane you iterate must have the first bit set in
  possible_crtcs, and it is the primary plane for that crtc
- 2nd primary plane has the 2nd bit set in possible_crtcs, and it is the
  primary plane for that crtc

and so on. That's all. I'm not sure all drivers get this right, so I think
it'd b

Re: [PATCH] dma-buf: Fix kerneldoc formatting

2020-12-08 Thread Daniel Vetter
On Mon, Dec 07, 2020 at 09:54:13PM +, Ruhl, Michael J wrote:
> >-Original Message-
> >From: dri-devel  On Behalf Of
> >Daniel Vetter
> >Sent: Friday, December 4, 2020 3:03 PM
> >To: DRI Development 
> >Cc: Daniel Vetter ; Vetter, Daniel
> >
> >Subject: [PATCH] dma-buf: Fix kerneldoc formatting
> >
> >I wanted to look up something and noticed the hyperlink doesn't work.
> >While fixing that also noticed a trivial kerneldoc comment typo in the
> >same section, fix that too.
> >
> >Signed-off-by: Daniel Vetter 
> >---
> > Documentation/driver-api/dma-buf.rst | 2 +-
> > include/linux/dma-buf-map.h  | 2 +-
> > 2 files changed, 2 insertions(+), 2 deletions(-)
> >
> >diff --git a/Documentation/driver-api/dma-buf.rst b/Documentation/driver-
> >api/dma-buf.rst
> >index d6b2a195dbed..a2133d69872c 100644
> >--- a/Documentation/driver-api/dma-buf.rst
> >+++ b/Documentation/driver-api/dma-buf.rst
> >@@ -190,7 +190,7 @@ DMA Fence uABI/Sync File
> > Indefinite DMA Fences
> > ~
> >
> >-At various times &dma_fence with an indefinite time until dma_fence_wait()
> >+At various times struct dma_fence with an indefinite time until
> >dma_fence_wait()
> > finishes have been proposed. Examples include:
> >
> > * Future fences, used in HWC1 to signal when a buffer isn't used by the
> >display
> >diff --git a/include/linux/dma-buf-map.h b/include/linux/dma-buf-map.h
> 
> Ahh, something to do while compiling...
> 
> Both changes look good to me.
> 
> Reviewed-by: Michael J. Ruhl 

Thanks for taking a look, patch applied.
-Daniel

> 
> M
> 
> >index 583a3a1f9447..278d489e4bdd 100644
> >--- a/include/linux/dma-buf-map.h
> >+++ b/include/linux/dma-buf-map.h
> >@@ -122,7 +122,7 @@ struct dma_buf_map {
> >
> > /**
> >  * DMA_BUF_MAP_INIT_VADDR - Initializes struct dma_buf_map to an
> >address in system memory
> >- * @vaddr:  A system-memory address
> >+ * @vaddr_: A system-memory address
> >  */
> > #define DMA_BUF_MAP_INIT_VADDR(vaddr_) \
> > { \
> >--
> >2.29.2
> >
> >___
> >dri-devel mailing list
> >dri-devel@lists.freedesktop.org
> >https://lists.freedesktop.org/mailman/listinfo/dri-devel

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


Re: [PATCH v2 4/7] drm/vc4: kms: Wait on previous FIFO users before a commit

2020-12-08 Thread Daniel Vetter
On Fri, Dec 04, 2020 at 04:11:35PM +0100, Maxime Ripard wrote:
> If we're having two subsequent, non-blocking, commits on two different
> CRTCs that share no resources, there's no guarantee on the order of
> execution of both commits.
> 
> However, the second one will consider the first one as the old state,
> and will be in charge of freeing it once that second commit is done.
> 
> If the first commit happens after that second commit, it might access
> some resources related to its state that has been freed, resulting in a
> use-after-free bug.
> 
> The standard DRM objects are protected against this, but our HVS private
> state isn't so let's make sure we wait for all the previous FIFO users
> to finish their commit before going with our own.
> 
> Signed-off-by: Maxime Ripard 
> ---
>  drivers/gpu/drm/vc4/vc4_kms.c | 123 +-
>  1 file changed, 122 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
> index 8937eb0b751d..fdd698df5fbe 100644
> --- a/drivers/gpu/drm/vc4/vc4_kms.c
> +++ b/drivers/gpu/drm/vc4/vc4_kms.c
> @@ -40,6 +40,11 @@ static struct vc4_ctm_state *to_vc4_ctm_state(struct 
> drm_private_state *priv)
>  struct vc4_hvs_state {
>   struct drm_private_state base;
>   unsigned int unassigned_channels;
> +
> + struct {
> + unsigned in_use: 1;
> + struct drm_crtc_commit *pending_commit;
> + } fifo_state[HVS_NUM_CHANNELS];
>  };
>  
>  static struct vc4_hvs_state *
> @@ -182,6 +187,32 @@ vc4_ctm_commit(struct vc4_dev *vc4, struct 
> drm_atomic_state *state)
> VC4_SET_FIELD(ctm_state->fifo, SCALER_OLEDOFFS_DISPFIFO));
>  }
>  
> +static struct vc4_hvs_state *
> +vc4_hvs_get_new_global_state(struct drm_atomic_state *state)
> +{
> + struct vc4_dev *vc4 = to_vc4_dev(state->dev);
> + struct drm_private_state *priv_state;
> +
> + priv_state = drm_atomic_get_new_private_obj_state(state, 
> &vc4->hvs_channels);
> + if (IS_ERR(priv_state))
> + return ERR_CAST(priv_state);
> +
> + return to_vc4_hvs_state(priv_state);
> +}
> +
> +static struct vc4_hvs_state *
> +vc4_hvs_get_old_global_state(struct drm_atomic_state *state)
> +{
> + struct vc4_dev *vc4 = to_vc4_dev(state->dev);
> + struct drm_private_state *priv_state;
> +
> + priv_state = drm_atomic_get_old_private_obj_state(state, 
> &vc4->hvs_channels);
> + if (IS_ERR(priv_state))
> + return ERR_CAST(priv_state);
> +
> + return to_vc4_hvs_state(priv_state);
> +}
> +
>  static struct vc4_hvs_state *
>  vc4_hvs_get_global_state(struct drm_atomic_state *state)
>  {
> @@ -308,8 +339,10 @@ vc4_atomic_complete_commit(struct drm_atomic_state 
> *state)
>   struct drm_device *dev = state->dev;
>   struct vc4_dev *vc4 = to_vc4_dev(dev);
>   struct vc4_hvs *hvs = vc4->hvs;
> + struct drm_crtc_state *old_crtc_state;
>   struct drm_crtc_state *new_crtc_state;
>   struct drm_crtc *crtc;
> + struct vc4_hvs_state *old_hvs_state;
>   int i;
>  
>   for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
> @@ -329,6 +362,36 @@ vc4_atomic_complete_commit(struct drm_atomic_state 
> *state)
>  
>   drm_atomic_helper_wait_for_dependencies(state);
>  
> + old_hvs_state = vc4_hvs_get_old_global_state(state);
> + if (!old_hvs_state)
> + return;
> +
> + for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) {
> + struct vc4_crtc_state *vc4_crtc_state =
> + to_vc4_crtc_state(old_crtc_state);
> + struct drm_crtc_commit *commit;
> + unsigned int channel = vc4_crtc_state->assigned_channel;
> + unsigned long done;
> +
> + if (channel == VC4_HVS_CHANNEL_DISABLED)
> + continue;
> +
> + if (!old_hvs_state->fifo_state[channel].in_use)
> + continue;
> +
> + commit = old_hvs_state->fifo_state[i].pending_commit;
> + if (!commit)
> + continue;
> +
> + done = wait_for_completion_timeout(&commit->hw_done, 10 * HZ);
> + if (!done)
> + drm_err(dev, "Timed out waiting for hw_done\n");
> +
> + done = wait_for_completion_timeout(&commit->flip_done, 10 * HZ);
> + if (!done)
> + drm_err(dev, "Timed out waiting for flip_done\n");

Idea for a follow-up patch: Add something like drm_crtc_commit_wait which
skips on a NULL commit and does the two waits here. And use it here and in
drm_atomic_helper_wait_for_dependencies, we have four copies of the same
code by now :-)

> + }
> +
>   drm_atomic_helper_commit_modeset_disables(dev, state);
>  
>   vc4_ctm_commit(vc4, state);
> @@ -368,6 +431,36 @@ static void commit_work(struct work_struct *work)
>   vc4_atomic_complete_commit(state);
>  }
>  
> +static int vc4_atomic_commit_setup(struct drm_atomic_state *state

Re: [PATCH v3 1/7] drm: add drmm_encoder_alloc()

2020-12-08 Thread Daniel Vetter
On Sat, Dec 05, 2020 at 08:57:38PM +0200, Laurent Pinchart wrote:
> Hi Philipp,
> 
> On Fri, Dec 04, 2020 at 11:12:20AM +0100, Philipp Zabel wrote:
> > On Fri, 2020-12-04 at 11:17 +0200, Laurent Pinchart wrote:
> > > On Fri, Sep 11, 2020 at 03:57:18PM +0200, Philipp Zabel wrote:
> > > > Add an alternative to drm_encoder_init() that allocates and initializes
> > > > an encoder and registers drm_encoder_cleanup() with
> > > > drmm_add_action_or_reset().
> > > > 
> > > > Signed-off-by: Philipp Zabel 
> > > > ---
> > > > Changes since v2:
> > > >  - call va_start() / va_end() unconditionally
> > > > ---
> > > >  drivers/gpu/drm/drm_encoder.c | 101 ++
> > > >  include/drm/drm_encoder.h |  30 ++
> > > >  2 files changed, 108 insertions(+), 23 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/drm_encoder.c 
> > > > b/drivers/gpu/drm/drm_encoder.c
> > > > index e555281f43d4..f5414705f9ad 100644
> > > > --- a/drivers/gpu/drm/drm_encoder.c
> > > > +++ b/drivers/gpu/drm/drm_encoder.c
> > > > @@ -26,6 +26,7 @@
> > > >  #include 
> > > >  #include 
> > > >  #include 
> > > > +#include 
> > > >  
> > > >  #include "drm_crtc_internal.h"
> > > >  
> > > > @@ -91,25 +92,11 @@ void drm_encoder_unregister_all(struct drm_device 
> > > > *dev)
> > > > }
> > > >  }
> > > >  
> > > > -/**
> > > > - * drm_encoder_init - Init a preallocated encoder
> > > > - * @dev: drm device
> > > > - * @encoder: the encoder to init
> > > > - * @funcs: callbacks for this encoder
> > > > - * @encoder_type: user visible type of the encoder
> > > > - * @name: printf style format string for the encoder name, or NULL for 
> > > > default name
> > > > - *
> > > > - * Initialises a preallocated encoder. Encoder should be subclassed as 
> > > > part of
> > > > - * driver encoder objects. At driver unload time drm_encoder_cleanup() 
> > > > should be
> > > > - * called from the driver's &drm_encoder_funcs.destroy hook.
> > > > - *
> > > > - * Returns:
> > > > - * Zero on success, error code on failure.
> > > > - */
> > > > -int drm_encoder_init(struct drm_device *dev,
> > > > -struct drm_encoder *encoder,
> > > > -const struct drm_encoder_funcs *funcs,
> > > > -int encoder_type, const char *name, ...)
> > > > +__printf(5, 0)
> > > > +static int __drm_encoder_init(struct drm_device *dev,
> > > > + struct drm_encoder *encoder,
> > > > + const struct drm_encoder_funcs *funcs,
> > > > + int encoder_type, const char *name, 
> > > > va_list ap)
> > > >  {
> > > > int ret;
> > > >  
> > > > @@ -125,11 +112,7 @@ int drm_encoder_init(struct drm_device *dev,
> > > > encoder->encoder_type = encoder_type;
> > > > encoder->funcs = funcs;
> > > > if (name) {
> > > > -   va_list ap;
> > > > -
> > > > -   va_start(ap, name);
> > > > encoder->name = kvasprintf(GFP_KERNEL, name, ap);
> > > > -   va_end(ap);
> > > > } else {
> > > > encoder->name = kasprintf(GFP_KERNEL, "%s-%d",
> > > >   
> > > > drm_encoder_enum_list[encoder_type].name,
> > > > @@ -150,6 +133,36 @@ int drm_encoder_init(struct drm_device *dev,
> > > >  
> > > > return ret;
> > > >  }
> > > > +
> > > > +/**
> > > > + * drm_encoder_init - Init a preallocated encoder
> > > > + * @dev: drm device
> > > > + * @encoder: the encoder to init
> > > > + * @funcs: callbacks for this encoder
> > > > + * @encoder_type: user visible type of the encoder
> > > > + * @name: printf style format string for the encoder name, or NULL for 
> > > > default name
> > > > + *
> > > > + * Initializes a preallocated encoder. Encoder should be subclassed as 
> > > > part of
> > > > + * driver encoder objects. At driver unload time drm_encoder_cleanup() 
> > > > should be
> > > > + * called from the driver's &drm_encoder_funcs.destroy hook.
> > > > + *
> > > > + * Returns:
> > > > + * Zero on success, error code on failure.
> > > > + */
> > > > +int drm_encoder_init(struct drm_device *dev,
> > > > +struct drm_encoder *encoder,
> > > > +const struct drm_encoder_funcs *funcs,
> > > > +int encoder_type, const char *name, ...)
> > > > +{
> > > > +   va_list ap;
> > > > +   int ret;
> > > > +
> > > > +   va_start(ap, name);
> > > > +   ret = __drm_encoder_init(dev, encoder, funcs, encoder_type, 
> > > > name, ap);
> > > > +   va_end(ap);
> > > > +
> > > > +   return ret;
> > > > +}
> > > >  EXPORT_SYMBOL(drm_encoder_init);
> > > >  
> > > >  /**
> > > > @@ -181,6 +194,48 @@ void drm_encoder_cleanup(struct drm_encoder 
> > > > *encoder)
> > > >  }
> > > >  EXPORT_SYMBOL(drm_encoder_cleanup);
> > > >  
> > > > +static void drmm_encoder_alloc_release(struct drm_device *dev, void 
> > > > *ptr)
> > > > +{
>

Re: [PATCH drm/hisilicon 0/3] support reading resolutions from EDID

2020-12-08 Thread Daniel Vetter
On Fri, Dec 04, 2020 at 09:28:33AM +0800, Tian Tao wrote:
> patch #1 add a new file to implements i2c adapters, #2 read the
> resolution from the edid, if that fails, set the resolution to fixed.
> patch #3 update the destroy callback function to release the i2c adapters.
> 
> Tian Tao (3):
>   drm/hisilicon: Support i2c driver algorithms for bit-shift adapters
>   drm/hisilicon: Features to support reading resolutions from EDID
>   drm/hisilicon: Releasing Resources in the Destroy callback Function

Just fyi, something with your patch submission got mangled. This one
doesn't seem to have any follow-up patches, the previous one had a
selection of unrelated bugfixes.
-Daniel

> 
>  drivers/gpu/drm/hisilicon/hibmc/Makefile |  2 +-
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h  | 21 -
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c  | 98 
> 
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 45 +--
>  4 files changed, 157 insertions(+), 9 deletions(-)
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c
> 
> -- 
> 2.7.4
> 

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


Re: [PATCH v2 7/7] dma-buf: Write down some rules for vmap usage

2020-12-08 Thread Daniel Vetter
On Fri, Dec 04, 2020 at 09:47:08AM +0100, Christian König wrote:
> Am 04.12.20 um 09:32 schrieb Thomas Zimmermann:
> > Hi
> > 
> > Am 03.12.20 um 21:41 schrieb Daniel Vetter:
> > > On Thu, Dec 03, 2020 at 07:59:04PM +0100, Thomas Zimmermann wrote:
> > > > Hi
> > > > 
> > > > Am 03.12.20 um 16:26 schrieb Daniel Vetter:
> > > > > On Thu, Dec 03, 2020 at 03:02:59PM +0100, Thomas Zimmermann wrote:
> > > > > > Dma-buf's vmap and vunmap callbacks are undocumented and various
> > > > > > exporters currently have slightly different semantics for them. Add
> > > > > > documentation on how to implement and use these interfaces 
> > > > > > correctly.
> > > > > > 
> > > > > > v2:
> > > > > > * document vmap semantics in struct dma_buf_ops
> > > > > > * add TODO item for reviewing and maybe fixing dma-buf exporters
> > > > > > 
> > > > > > Signed-off-by: Thomas Zimmermann 
> > > > > 
> > > > > I still don't think this works, we're breaking dma_buf_vmap
> > > > > for everyone
> > > > > else here.
> > > > 
> > > > I removed the text on the importer. These notes for callers in
> > > > the docs are
> > > > more or less a consequence of the exporter semantics.
> > > 
> > > Callers are importers, so I'm not seeing how that fixes anything.
> > > 
> > > > I thought we at least agreed on the exporter semantics in the
> > > > other thread,
> > > > didn't we?
> > > > 
> > > > What I'm trying to do is to write dome some rules for exporters,
> > > > even if not
> > > > all exporters follow them.
> > > 
> > > This is a standard interface, everyone needs to follow the same
> > > rules. And
> > > if they change, we need to make sure nothing breaks and we're not
> > > creating
> > > issues.
> > > 
> > > In the past the rule was the dma_buf_vmap was allowed to take the
> > > dma_resv_lock, and that the buffer should be pinned. Now some ttm
> > > drivers
> > > didn't ever bother with the pinning, and mostly got away with that
> > > because
> > > drm_prime helpers do the pinning by default at attach time, and most
> > > users
> > > do call dma_buf_attach.
> > > 
> > > But if you look through dma-buf docs nothing ever said you have to do a
> > > dummy attachment before you call dma_buf_vmap, that's just slightly
> > > crappy
> > > implementations that didn't blow up yet.
> > 
> > I had a patch for adding pin to radeon's implementation of vmap. [1]
> > Christian told me to not do this; instead just get the lock in the fbdev
> > code. His advise almost seems the opposite of what you're telling me
> > here.
> 
> I think what Daniel suggests here is that we need to smoothly transition the
> code from making assumptions to having a straight interface where importers
> explicitly say when stuff is locked and when stuff is pinned.
> 
> I've started this with the attach interface by adding a new dynamic approach
> to that, but you probably need to carry on here with that for vmap as well.
> 
> When that is done we can migrate every exporter over to the new dynamic
> approach.
> 
> > 
> > For the GEM VRAM helpers, that implicit pin in vmap gave me headaches.
> > Because scanouts can only be done from VRAM, which is badly suited for
> > exporting. So I ended up with an implicit pin that pins the buffer to
> > whatever domain it currently is. I got away with it because GEM VRAM BOs
> > are not sharable among devices; fbdev is the only user of that
> > functionality and only pins for short periods of time.
> > 
> > I suspect that fixing TTM-based drivers by adding an implicit pin would
> > result in a similar situation. Whatever domain it ends up pinning, some
> > functionality might not be compatible with that.
> 
> Correct, exactly that's the problem.
> 
> > 
> > > 
> > > > Given the circumstances, we should leave out this patch from the
> > > > patchset.
> > > 
> > > So the defacto rules are already a big mess, but that's not a good
> > > excuse
> > > to make it worse.
> > > 
> > > What I had in mind is that we split dma_buf_vmap up into two variants:
> > > 
> > > - The current one, which should guarantee that the buffer is pinned.
> > >    Because that's what all current callers wanted, before the fbdev code
> > >    started allowing non-pinned buffers.
> > 
> > Can we add an explicit pin operation to dma_buf_vmap() to enforce the
> > semantics?
> 
> At least I would be fine with that. For now amdgpu is the only exporter who
> implements the explicit pin/unpin semantics anyway.

Yup, I think that makes sense (if it works). Maybe we could use something
like:

a) dma_buf pin exists, driver is dynamic. This means dma_buf_vmap needs to
first pin, then call ->vmap. dma_buf_vmap_local otoh can directly call
->vmap since the exporter relies on either a pin or dma_resv_lock.

b) dma_buf pin not implement, driver is a legacy pile. dma_buf_vmap will
pin (somewhere at least, or rely on some implicit pin), dma_buf_vmap_local
doesn't work and should fail.

I think for less transition work fbdev helpers could first try
dma_resv_lock + dma_buf_vmap_loca

Re: [PATCH 1/2] drm: add legacy support for using degamma for gamma

2020-12-08 Thread Daniel Vetter
On Mon, Dec 07, 2020 at 05:45:02PM +0200, Tomi Valkeinen wrote:
> On 07/12/2020 17:31, Ville Syrjälä wrote:
> > On Sat, Dec 05, 2020 at 12:35:25AM +0200, Laurent Pinchart wrote:
> >> Hi Tomi,
> >>
> >> Thank you for the patch.
> >>
> >> On Thu, Dec 03, 2020 at 01:48:44PM +0200, Tomi Valkeinen wrote:
> >>> We currently have drm_atomic_helper_legacy_gamma_set() helper which can
> >>> be used to handle legacy gamma-set ioctl.
> >>> drm_atomic_helper_legacy_gamma_set() sets GAMMA_LUT, and clears
> >>> CTM and DEGAMMA_LUT. This works fine on HW where we have either:
> >>>
> >>> degamma -> ctm -> gamma -> out
> >>>
> >>> or
> >>>
> >>> ctm -> gamma -> out
> >>>
> >>> However, if the HW has gamma table before ctm, the atomic property
> >>> should be DEGAMMA_LUT, and thus we have:
> >>>
> >>> degamma -> ctm -> out
> >>>
> >>> This is fine for userspace which sets gamma table using the properties,
> >>> as the userspace can check for the existence of gamma & degamma, but the
> >>> legacy gamma-set ioctl does not work.
> >>>
> >>> This patch fixes the issue by changing
> >>> drm_atomic_helper_legacy_gamma_set() so that GAMMA_LUT will be used if
> >>> it exists, and DEGAMMA_LUT will be used as a fallback.
> >>>
> >>> Signed-off-by: Tomi Valkeinen 
> >>> ---
> >>>  drivers/gpu/drm/drm_atomic_helper.c | 18 +++---
> >>>  drivers/gpu/drm/drm_color_mgmt.c|  4 
> >>>  include/drm/drm_crtc.h  |  3 +++
> >>>  3 files changed, 22 insertions(+), 3 deletions(-)
> >>>
> >>> diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
> >>> b/drivers/gpu/drm/drm_atomic_helper.c
> >>> index ba1507036f26..fe59c8ea42a9 100644
> >>> --- a/drivers/gpu/drm/drm_atomic_helper.c
> >>> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> >>> @@ -3512,6 +3512,10 @@ EXPORT_SYMBOL(drm_atomic_helper_page_flip_target);
> >>>   * that support color management through the DEGAMMA_LUT/GAMMA_LUT
> >>>   * properties. See drm_crtc_enable_color_mgmt() and the containing 
> >>> chapter for
> >>>   * how the atomic color management and gamma tables work.
> >>> + *
> >>> + * This function uses the GAMMA_LUT or DEGAMMA_LUT property for the 
> >>> gamma table.
> >>> + * GAMMA_LUT property is used if it exists, and DEGAMMA_LUT property is 
> >>> used as
> >>> + * a fallback.
> >>>   */
> >>>  int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
> >>>  u16 *red, u16 *green, u16 *blue,
> >>> @@ -3525,6 +3529,12 @@ int drm_atomic_helper_legacy_gamma_set(struct 
> >>> drm_crtc *crtc,
> >>>   struct drm_color_lut *blob_data;
> >>>   int i, ret = 0;
> >>>   bool replaced;
> >>> + bool use_degamma;
> >>> +
> >>> + if (!crtc->has_gamma_prop && !crtc->has_degamma_prop)
> >>> + return -ENODEV;
> >>> +
> >>> + use_degamma = !crtc->has_gamma_prop;
> >>>  
> >>>   state = drm_atomic_state_alloc(crtc->dev);
> >>>   if (!state)
> >>> @@ -3554,10 +3564,12 @@ int drm_atomic_helper_legacy_gamma_set(struct 
> >>> drm_crtc *crtc,
> >>>   goto fail;
> >>>   }
> >>>  
> >>> - /* Reset DEGAMMA_LUT and CTM properties. */
> >>> - replaced  = drm_property_replace_blob(&crtc_state->degamma_lut, NULL);
> >>> + /* Set GAMMA/DEGAMMA_LUT and reset DEGAMMA/GAMMA_LUT and CTM */
> >>> + replaced  = drm_property_replace_blob(&crtc_state->degamma_lut,
> >>> +   use_degamma ? blob : NULL);
> >>>   replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL);
> >>> - replaced |= drm_property_replace_blob(&crtc_state->gamma_lut, blob);
> >>> + replaced |= drm_property_replace_blob(&crtc_state->gamma_lut,
> >>> +   use_degamma ? NULL : blob);
> >>>   crtc_state->color_mgmt_changed |= replaced;
> >>>  
> >>>   ret = drm_atomic_commit(state);
> >>> diff --git a/drivers/gpu/drm/drm_color_mgmt.c 
> >>> b/drivers/gpu/drm/drm_color_mgmt.c
> >>> index 3bcabc2f6e0e..956e59d5f6a7 100644
> >>> --- a/drivers/gpu/drm/drm_color_mgmt.c
> >>> +++ b/drivers/gpu/drm/drm_color_mgmt.c
> >>> @@ -176,6 +176,8 @@ void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
> >>>  degamma_lut_size);
> >>>   }
> >>>  
> >>> + crtc->has_degamma_prop = !!degamma_lut_size;
> >>> +
> >>>   if (has_ctm)
> >>>   drm_object_attach_property(&crtc->base,
> >>>  config->ctm_property, 0);
> >>> @@ -187,6 +189,8 @@ void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
> >>>  config->gamma_lut_size_property,
> >>>  gamma_lut_size);
> >>>   }
> >>> +
> >>> + crtc->has_gamma_prop = !!gamma_lut_size;
> >>>  }
> >>>  EXPORT_SYMBOL(drm_crtc_enable_color_mgmt);
> >>>  
> >>> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> >>> index ba839e5e357d..9e1f06047e3d 100644
> >>> --- a/include/drm/drm_crtc.h
> >>> +++ b/include/drm/drm_crtc.h
> >>> @@ -1084,6 +1084,9 @@ struct drm_crtc {
> >>>*/
> >>>   uint16_t *gamma_store;
> >>>  
> >>> + bo

Re: [RFC PATCH] drm/panel: Make backlight attachment lazy

2020-12-08 Thread Daniel Vetter
On Tue, Dec 08, 2020 at 04:02:16PM -0600, Bjorn Andersson wrote:
> On Tue 08 Dec 06:47 CST 2020, Thierry Reding wrote:
> 
> > On Mon, Dec 07, 2020 at 10:44:46PM -0600, Bjorn Andersson wrote:
> > > Some bridge chips, such as the TI SN65DSI86 DSI/eDP bridge, provides
> > > means of generating a PWM signal for backlight control of the attached
> > > panel. The provided PWM chip is typically controlled by the
> > > pwm-backlight driver, which if tied to the panel will provide DPMS.
> > > 
> > > But with the current implementation the panel will refuse to probe
> > > because the bridge driver has yet to probe and register the PWM chip,
> > > and the bridge driver will refuse to probe because it's unable to find
> > > the panel.
> > 
> > What you're describing is basically a circular dependency. Can't we get
> > rid of that in some other way? Why exactly does the bridge driver refuse
> > to probe if the panel can't be found?
> > 
> > In other words, I see how the bridge would /use/ the panel in that it
> > forward a video stream to it. But how does the panel /use/ the bridge?
> > 
> 
> Yes, this is indeed a circular dependency between the components.
> 
> The involved parts are:
> * the bridge driver that implements the PWM chip probe defers on
>   drm_of_find_panel_or_bridge() failing to find the panel.
> * the pwm-backlight driver that consumes the PWM channel probe defer
>   because the pwm_chip was not registered by the bridge.
> * the panel that uses the backlight for DPMS purposes probe defer
>   because drm_panel_of_backlight() fails to find the pwm-backlight.
> 
> I looked at means of postponing drm_of_find_panel_or_bridge() to
> drm_bridge_funcs->attach(), but at that time "deferral" would be fatal.
> I looked at registering the pwm_chip earlier, but that would depend on a
> guarantee of the pwm-backlight and panel driver to probe concurrently.
> And the current solution of not tying the backlight to the panel means
> that when userspace decides to DPMS the display the backlight stays on.
> 
> 
> The proposed solution (hack?) means that DPMS operations happening
> before the pwm-backlight has probed will be missed, so it's not perfect.
> It does however allow the backlight on my laptop to turn off, which is a
> big improvement.
> 
> But I'm certainly welcome to suggestions.

Entirely hand-waving, why doesn't the following work:

1. driver for the platform device which is the bridge loads
2. that platform driver registers the pwm
3. it registers some magic for later on (more below)
4. panel driver has deferred loading until step 2 happened
5. panel driver registers drm_panel
6. the magic from step 3 picks up (after having been deferred for a few
times probably) grabs the panel, and sets up the actual drm_bridge driver

Everyone happy, or not? From the description it looks like the problem
that the pwm that we need for the backlight is tied to the same driver as
the drm_bridge, and always torn down too if the drm_bridge setup fails
somehow for a reason. And that reason is the circular dependency this
creates.

Now for the magic in step 3, there's options:
- change DT to split out that pwm as a separate platform_device, that way
  bridge and panel can load indepedently (hopefully)

- convert bridge to a multi-function device (mfd), essentially a way to
  instantiate more devices with their drivers at runtime. Then the actual
  pwm and drm_bridge parts of your bridge driver bind against those
  sub-functions, and can defer indepedently

- we could create a callback/wait function for "pls wait for any panel to
  show up". Then your bridge driver could launch a work_struct with that
  wait function, which will do the bridge setup once the panel has shown
  up. The pwm will be registered right away. It's essentially hand-rolling
  EPROBE_DEFERRED for work_struct in drm/panel. Maybe we might even have
  that exported from the driver core, e.g.

register_bridge_fn(struct work *)
{
do_wait_probe_defer();
panel = drm_of_find_panel_or_bridge();
if (!panel) {
schedule_work(); /* want to restart the work so it can be 
stopped on driver unload */
return;
}

/* we have the panel now, register drm_bridge */
}

- cobble something together with component.c, but that's more for
  collecting unrelated struct device into a logical one than splitting it
  up more.

tldr; I think you can split this loop here at the bridge by untangling the
pwm from the drm_bridge part sufficiently.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v3 1/9] dt-binding: soc: xilinx: ai-engine: Add AI engine binding

2020-12-08 Thread Rob Herring
On Sun, Nov 29, 2020 at 11:48:17PM -0800, Wendy Liang wrote:
> Xilinx AI engine array can be partitioned statically for different
> applications. In the device tree, there will be device node for the AI
> engine device, and device nodes for the statically configured AI engine
> partitions. Each of the statically configured partition has a partition
> ID in the system.
>
> Signed-off-by: Wendy Liang 
> ---
>  .../bindings/soc/xilinx/xlnx,ai-engine.yaml| 126 
> +
>  1 file changed, 126 insertions(+)
>  create mode 100644 
> Documentation/devicetree/bindings/soc/xilinx/xlnx,ai-engine.yaml
> 
> diff --git a/Documentation/devicetree/bindings/soc/xilinx/xlnx,ai-engine.yaml 
> b/Documentation/devicetree/bindings/soc/xilinx/xlnx,ai-engine.yaml
> new file mode 100644
> index 000..1de5623
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/soc/xilinx/xlnx,ai-engine.yaml
> @@ -0,0 +1,126 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/soc/xilinx/xlnx,ai-engine.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Xilinx AI Engine
> +
> +maintainers:
> +  - Wendy Liang 
> +
> +description: |+

You don't need '|' unless there's formatting to preserve.

> +  The Xilinx AI Engine is a tile processor with many cores (up to 400) that
> +  can run in parallel. The data routing between cores is configured through
> +  internal switches, and shim tiles interface with external interconnect, 
> such
> +  as memory or PL.
> +
> +properties:
> +  compatible:
> +const: xlnx,ai-engine-v1.0

This is soft logic? If not, don't use version numbers.

> +
> +  reg:
> +description: |
> +  Physical base address and length of the device registers.

That's every 'reg' property. Drop.

> +  The AI engine address space assigned to Linux is defined by Xilinx
> +  platform design tool.
> +
> +  '#address-cells':
> +enum: [2]

const: 2

> +description: |
> +  size of cell to describe AI engine range of tiles address.
> +  It is the location of the starting tile of the range.
> +  As the AI engine tiles are 2D array, the location of a tile
> +  is presented as (column, row), the address cell is 2.
> +
> +  '#size-cells':
> +enum: [2]
> +description: |
> +  size of cell to describe AI engine range of tiles size.
> +  As the AI engine tiles are 2D array, the size cell is 2.
> +
> +  power-domains:
> +maxItems: 1
> +description: phandle to the associated power domain
> +
> +  interrupts:
> +maxItems: 3
> +
> +  interrupt-names:
> +description: |
> +  Should be "interrupt1", "interrupt2" or "interrupt3".

Really, not useful names. If you do have names, they should be a schema, 
not freeform text.

> +
> +required:
> +  - compatible
> +  - reg
> +  - '#address-cells'
> +  - '#size-cells'
> +  - power-domains
> +  - interrupt-parent

Generally, never required because it could be in the parent node.

> +  - interrupts
> +  - interrupt-names
> +
> +patternProperties:
> +  "^aie_partition@[0-9]+$":

aie-partition@

The unit-address is just the 1st cell of reg (the row)? Or needs to be 
row and column, in which case you'd want something like '@0,0'. Also, 
unit-address values are typically hex, not decimal.

> +type: object
> +description: |
> +  AI engine partition which is a group of column based tiles of the AI
> +  engine device. Each AI engine partition is isolated from the other
> +  AI engine partitions. An AI engine partition is defined by Xilinx
> +  platform design tools. Each partition has a SHIM row and core tiles 
> rows.
> +  A SHIM row contains SHIM tiles which are the interface to external
> +  components. AXI master can access AI engine registers, push data to and
> +  fetch data from AI engine through the SHIM tiles. Core tiles are the
> +  compute tiles.
> +
> +properties:
> +  reg:
> +description: |
> +  It describes the group of tiles of the AI engine partition. It 
> needs
> +  to include the SHIM row. The format is defined by the parent AI 
> engine
> +  device node's '#address-cells' and '#size-cells' properties. e.g. 
> a v1
> +  AI engine device has 2D tiles array, the first row is SHIM row. A
> +  partition which has 50 columns and 8 rows of core tiles and 1 row 
> of
> +  SHIM tiles will be presented as <0 0 50 9>.

You should be able to write some constraints like max row and column 
values?

> +
> +  label:
> +maxItems: 1

'label' is not an array. Why do you need label?

> +
> +  xlnx,partition-id:
> +$ref: /schemas/types.yaml#/definitions/uint32
> +description: |
> +  AI engine partition ID, which is defined by Xilinx platform design
> +  tool to identify the AI engine partition in the system.

I find the use of 'reg' a bit odd here. Maybe using 'reg' for partition 
woul

[PATCH v14 3/4] RDMA/uverbs: Add uverbs command for dma-buf based MR registration

2020-12-08 Thread Jianxin Xiong
Implement a new uverbs ioctl method for memory registration with file
descriptor as an extra parameter.

Signed-off-by: Jianxin Xiong 
Reviewed-by: Sean Hefty 
Acked-by: Michael J. Ruhl 
Acked-by: Christian Koenig 
Acked-by: Daniel Vetter 
Reviewed-by: Leon Romanovsky 
---
 drivers/infiniband/core/uverbs_std_types_mr.c | 117 +-
 include/uapi/rdma/ib_user_ioctl_cmds.h|  14 +++
 2 files changed, 129 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/core/uverbs_std_types_mr.c 
b/drivers/infiniband/core/uverbs_std_types_mr.c
index dc58564..4660c76 100644
--- a/drivers/infiniband/core/uverbs_std_types_mr.c
+++ b/drivers/infiniband/core/uverbs_std_types_mr.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2018, Mellanox Technologies inc.  All rights reserved.
+ * Copyright (c) 2020, Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -182,6 +183,86 @@ static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_MR)(
return IS_UVERBS_COPY_ERR(ret) ? ret : 0;
 }
 
+static int UVERBS_HANDLER(UVERBS_METHOD_REG_DMABUF_MR)(
+   struct uverbs_attr_bundle *attrs)
+{
+   struct ib_uobject *uobj =
+   uverbs_attr_get_uobject(attrs, 
UVERBS_ATTR_REG_DMABUF_MR_HANDLE);
+   struct ib_pd *pd =
+   uverbs_attr_get_obj(attrs, UVERBS_ATTR_REG_DMABUF_MR_PD_HANDLE);
+   struct ib_device *ib_dev = pd->device;
+
+   u64 offset, length, virt_addr;
+   u32 fd, access_flags;
+   struct ib_mr *mr;
+   int ret;
+
+   if (!ib_dev->ops.reg_user_mr_dmabuf)
+   return -EOPNOTSUPP;
+
+   if (!(pd->device->attrs.device_cap_flags & IB_DEVICE_ON_DEMAND_PAGING))
+   return -EOPNOTSUPP;
+
+   ret = uverbs_copy_from(&offset, attrs,
+  UVERBS_ATTR_REG_DMABUF_MR_OFFSET);
+   if (ret)
+   return ret;
+
+   ret = uverbs_copy_from(&length, attrs,
+  UVERBS_ATTR_REG_DMABUF_MR_LENGTH);
+   if (ret)
+   return ret;
+
+   ret = uverbs_copy_from(&virt_addr, attrs,
+  UVERBS_ATTR_REG_DMABUF_MR_IOVA);
+   if (ret)
+   return ret;
+
+   ret = uverbs_copy_from(&fd, attrs,
+  UVERBS_ATTR_REG_DMABUF_MR_FD);
+   if (ret)
+   return ret;
+
+   ret = uverbs_get_flags32(&access_flags, attrs,
+UVERBS_ATTR_REG_DMABUF_MR_ACCESS_FLAGS,
+IB_ACCESS_LOCAL_WRITE |
+IB_ACCESS_REMOTE_READ |
+IB_ACCESS_REMOTE_WRITE |
+IB_ACCESS_REMOTE_ATOMIC |
+IB_ACCESS_RELAXED_ORDERING);
+   if (ret)
+   return ret;
+
+   ret = ib_check_mr_access(access_flags);
+   if (ret)
+   return ret;
+
+   mr = pd->device->ops.reg_user_mr_dmabuf(pd, offset, length, virt_addr,
+   fd, access_flags,
+   &attrs->driver_udata);
+   if (IS_ERR(mr))
+   return PTR_ERR(mr);
+
+   mr->device = pd->device;
+   mr->pd = pd;
+   mr->type = IB_MR_TYPE_USER;
+   mr->uobject = uobj;
+   atomic_inc(&pd->usecnt);
+
+   uobj->object = mr;
+
+   uverbs_finalize_uobj_create(attrs, UVERBS_ATTR_REG_DMABUF_MR_HANDLE);
+
+   ret = uverbs_copy_to(attrs, UVERBS_ATTR_REG_DMABUF_MR_RESP_LKEY,
+&mr->lkey, sizeof(mr->lkey));
+   if (ret)
+   return ret;
+
+   ret = uverbs_copy_to(attrs, UVERBS_ATTR_REG_DMABUF_MR_RESP_RKEY,
+&mr->rkey, sizeof(mr->rkey));
+   return ret;
+}
+
 DECLARE_UVERBS_NAMED_METHOD(
UVERBS_METHOD_ADVISE_MR,
UVERBS_ATTR_IDR(UVERBS_ATTR_ADVISE_MR_PD_HANDLE,
@@ -247,6 +328,37 @@ static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_MR)(
UVERBS_ATTR_TYPE(u32),
UA_MANDATORY));
 
+DECLARE_UVERBS_NAMED_METHOD(
+   UVERBS_METHOD_REG_DMABUF_MR,
+   UVERBS_ATTR_IDR(UVERBS_ATTR_REG_DMABUF_MR_HANDLE,
+   UVERBS_OBJECT_MR,
+   UVERBS_ACCESS_NEW,
+   UA_MANDATORY),
+   UVERBS_ATTR_IDR(UVERBS_ATTR_REG_DMABUF_MR_PD_HANDLE,
+   UVERBS_OBJECT_PD,
+   UVERBS_ACCESS_READ,
+   UA_MANDATORY),
+   UVERBS_ATTR_PTR_IN(UVERBS_ATTR_REG_DMABUF_MR_OFFSET,
+  UVERBS_ATTR_TYPE(u64),
+  UA_MANDATORY),
+   UVERBS_ATTR_PTR_IN(UVERBS_ATTR_REG_DMABUF_MR_LENGTH,
+  UVERBS_ATTR_TYPE(u64),
+  UA_MANDATORY),
+   UVERBS_ATTR_PTR_IN(UVERBS_ATTR_REG_DMABUF_MR_IOVA,
+

[PATCH v14 4/4] RDMA/mlx5: Support dma-buf based userspace memory region

2020-12-08 Thread Jianxin Xiong
Implement the new driver method 'reg_user_mr_dmabuf'.  Utilize the core
functions to import dma-buf based memory region and update the mappings.

Add code to handle dma-buf related page fault.

Signed-off-by: Jianxin Xiong 
Reviewed-by: Sean Hefty 
Acked-by: Michael J. Ruhl 
Acked-by: Christian Koenig 
Acked-by: Daniel Vetter 
---
 drivers/infiniband/hw/mlx5/main.c|   2 +
 drivers/infiniband/hw/mlx5/mlx5_ib.h |  18 +
 drivers/infiniband/hw/mlx5/mr.c  | 128 +--
 drivers/infiniband/hw/mlx5/odp.c |  86 +--
 4 files changed, 225 insertions(+), 9 deletions(-)

diff --git a/drivers/infiniband/hw/mlx5/main.c 
b/drivers/infiniband/hw/mlx5/main.c
index 4a054eb..c025746 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
 /*
  * Copyright (c) 2013-2020, Mellanox Technologies inc. All rights reserved.
+ * Copyright (c) 2020, Intel Corporation. All rights reserved.
  */
 
 #include 
@@ -4069,6 +4070,7 @@ static int mlx5_ib_enable_driver(struct ib_device *dev)
.query_srq = mlx5_ib_query_srq,
.query_ucontext = mlx5_ib_query_ucontext,
.reg_user_mr = mlx5_ib_reg_user_mr,
+   .reg_user_mr_dmabuf = mlx5_ib_reg_user_mr_dmabuf,
.req_notify_cq = mlx5_ib_arm_cq,
.rereg_user_mr = mlx5_ib_rereg_user_mr,
.resize_cq = mlx5_ib_resize_cq,
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h 
b/drivers/infiniband/hw/mlx5/mlx5_ib.h
index 718e59f..6f4d1b4 100644
--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
 /*
  * Copyright (c) 2013-2020, Mellanox Technologies inc. All rights reserved.
+ * Copyright (c) 2020, Intel Corporation. All rights reserved.
  */
 
 #ifndef MLX5_IB_H
@@ -704,6 +705,12 @@ static inline bool is_odp_mr(struct mlx5_ib_mr *mr)
   mr->umem->is_odp;
 }
 
+static inline bool is_dmabuf_mr(struct mlx5_ib_mr *mr)
+{
+   return IS_ENABLED(CONFIG_INFINIBAND_ON_DEMAND_PAGING) && mr->umem &&
+  mr->umem->is_dmabuf;
+}
+
 struct mlx5_ib_mw {
struct ib_mwibmw;
struct mlx5_core_mkey   mmkey;
@@ -1239,6 +1246,10 @@ int mlx5_ib_create_cq(struct ib_cq *ibcq, const struct 
ib_cq_init_attr *attr,
 struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
  u64 virt_addr, int access_flags,
  struct ib_udata *udata);
+struct ib_mr *mlx5_ib_reg_user_mr_dmabuf(struct ib_pd *pd, u64 start,
+u64 length, u64 virt_addr,
+int fd, int access_flags,
+struct ib_udata *udata);
 int mlx5_ib_advise_mr(struct ib_pd *pd,
  enum ib_uverbs_advise_mr_advice advice,
  u32 flags,
@@ -1249,11 +1260,13 @@ int mlx5_ib_advise_mr(struct ib_pd *pd,
 int mlx5_ib_dealloc_mw(struct ib_mw *mw);
 int mlx5_ib_update_xlt(struct mlx5_ib_mr *mr, u64 idx, int npages,
   int page_shift, int flags);
+int mlx5_ib_update_mr_pas(struct mlx5_ib_mr *mr, unsigned int flags);
 struct mlx5_ib_mr *mlx5_ib_alloc_implicit_mr(struct mlx5_ib_pd *pd,
 struct ib_udata *udata,
 int access_flags);
 void mlx5_ib_free_implicit_mr(struct mlx5_ib_mr *mr);
 void mlx5_ib_fence_odp_mr(struct mlx5_ib_mr *mr);
+void mlx5_ib_fence_dmabuf_mr(struct mlx5_ib_mr *mr);
 int mlx5_ib_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start,
  u64 length, u64 virt_addr, int access_flags,
  struct ib_pd *pd, struct ib_udata *udata);
@@ -1341,6 +1354,7 @@ int mlx5_ib_advise_mr_prefetch(struct ib_pd *pd,
   enum ib_uverbs_advise_mr_advice advice,
   u32 flags, struct ib_sge *sg_list, u32 num_sge);
 int mlx5_ib_init_odp_mr(struct mlx5_ib_mr *mr, bool enable);
+int mlx5_ib_init_dmabuf_mr(struct mlx5_ib_mr *mr);
 #else /* CONFIG_INFINIBAND_ON_DEMAND_PAGING */
 static inline void mlx5_ib_internal_fill_odp_caps(struct mlx5_ib_dev *dev)
 {
@@ -1366,6 +1380,10 @@ static inline int mlx5_ib_init_odp_mr(struct mlx5_ib_mr 
*mr, bool enable)
 {
return -EOPNOTSUPP;
 }
+static inline int mlx5_ib_init_dmabuf_mr(struct mlx5_ib_mr *mr)
+{
+   return -EOPNOTSUPP;
+}
 #endif /* CONFIG_INFINIBAND_ON_DEMAND_PAGING */
 
 extern const struct mmu_interval_notifier_ops mlx5_mn_ops;
diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c
index b6116f6..e3be1f5 100644
--- a/drivers/infiniband/hw/mlx5/mr.c
+++ b/drivers/infiniband/hw/mlx5/mr.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2013-2015, Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2020, Intel Corporation. Al

[PATCH v14 1/4] RDMA/umem: Support importing dma-buf as user memory region

2020-12-08 Thread Jianxin Xiong
Dma-buf is a standard cross-driver buffer sharing mechanism that can be
used to support peer-to-peer access from RDMA devices.

Device memory exported via dma-buf is associated with a file descriptor.
This is passed to the user space as a property associated with the
buffer allocation. When the buffer is registered as a memory region,
the file descriptor is passed to the RDMA driver along with other
parameters.

Implement the common code for importing dma-buf object and mapping
dma-buf pages.

Signed-off-by: Jianxin Xiong 
Reviewed-by: Sean Hefty 
Acked-by: Michael J. Ruhl 
Acked-by: Christian Koenig 
Acked-by: Daniel Vetter 
---
 drivers/infiniband/core/Makefile  |   2 +-
 drivers/infiniband/core/umem.c|   3 +
 drivers/infiniband/core/umem_dmabuf.c | 174 ++
 include/rdma/ib_umem.h|  47 -
 4 files changed, 222 insertions(+), 4 deletions(-)
 create mode 100644 drivers/infiniband/core/umem_dmabuf.c

diff --git a/drivers/infiniband/core/Makefile b/drivers/infiniband/core/Makefile
index ccf2670..8ab4eea 100644
--- a/drivers/infiniband/core/Makefile
+++ b/drivers/infiniband/core/Makefile
@@ -40,5 +40,5 @@ ib_uverbs-y :=uverbs_main.o 
uverbs_cmd.o uverbs_marshall.o \
uverbs_std_types_srq.o \
uverbs_std_types_wq.o \
uverbs_std_types_qp.o
-ib_uverbs-$(CONFIG_INFINIBAND_USER_MEM) += umem.o
+ib_uverbs-$(CONFIG_INFINIBAND_USER_MEM) += umem.o umem_dmabuf.o
 ib_uverbs-$(CONFIG_INFINIBAND_ON_DEMAND_PAGING) += umem_odp.o
diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index 7ca4112..cc131f8 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -2,6 +2,7 @@
  * Copyright (c) 2005 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Cisco Systems.  All rights reserved.
  * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2020 Intel Corporation. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -278,6 +279,8 @@ void ib_umem_release(struct ib_umem *umem)
 {
if (!umem)
return;
+   if (umem->is_dmabuf)
+   return ib_umem_dmabuf_release(to_ib_umem_dmabuf(umem));
if (umem->is_odp)
return ib_umem_odp_release(to_ib_umem_odp(umem));
 
diff --git a/drivers/infiniband/core/umem_dmabuf.c 
b/drivers/infiniband/core/umem_dmabuf.c
new file mode 100644
index 000..3fcbcad
--- /dev/null
+++ b/drivers/infiniband/core/umem_dmabuf.c
@@ -0,0 +1,174 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020 Intel Corporation. All rights reserved.
+ */
+
+#include 
+#include 
+#include 
+
+#include "uverbs.h"
+
+int ib_umem_dmabuf_map_pages(struct ib_umem_dmabuf *umem_dmabuf)
+{
+   struct sg_table *sgt;
+   struct scatterlist *sg;
+   struct dma_fence *fence;
+   unsigned long start, end, cur = 0;
+   unsigned int nmap = 0;
+   int i;
+
+   dma_resv_assert_held(umem_dmabuf->attach->dmabuf->resv);
+
+   if (umem_dmabuf->sgt)
+   goto wait_fence;
+
+   sgt = dma_buf_map_attachment(umem_dmabuf->attach, DMA_BIDIRECTIONAL);
+   if (IS_ERR(sgt))
+   return PTR_ERR(sgt);
+
+   /* modify the sg list in-place to match umem address and length */
+
+   start = ALIGN_DOWN(umem_dmabuf->umem.address, PAGE_SIZE);
+   end = ALIGN(umem_dmabuf->umem.address + umem_dmabuf->umem.length,
+   PAGE_SIZE);
+   for_each_sgtable_dma_sg(sgt, sg, i) {
+   if (start < cur + sg_dma_len(sg) && cur < end)
+   nmap++;
+   if (cur <= start && start < cur + sg_dma_len(sg)) {
+   unsigned long offset = start - cur;
+
+   umem_dmabuf->first_sg = sg;
+   umem_dmabuf->first_sg_offset = offset;
+   sg_dma_address(sg) += offset;
+   sg_dma_len(sg) -= offset;
+   cur += offset;
+   }
+   if (cur < end && end <= cur + sg_dma_len(sg)) {
+   unsigned long trim = cur + sg_dma_len(sg) - end;
+
+   umem_dmabuf->last_sg = sg;
+   umem_dmabuf->last_sg_trim = trim;
+   sg_dma_len(sg) -= trim;
+   break;
+   }
+   cur += sg_dma_len(sg);
+   }
+
+   umem_dmabuf->umem.sg_head.sgl = umem_dmabuf->first_sg;
+   umem_dmabuf->umem.sg_head.nents = nmap;
+   umem_dmabuf->umem.nmap = nmap;
+   umem_dmabuf->sgt = sgt;
+
+wait_fence:
+   /*
+* Although the sg list is valid now, the content of the pages
+* may be not up-to-date. Wait for the exporter to finish
+* th

[PATCH v14 0/4] RDMA: Add dma-buf support

2020-12-08 Thread Jianxin Xiong
This is the fourteenth version of the patch set. Changelog:

v14:
* Check return value of dma_fence_wait()
* Fix a dma-buf leak in ib_umem_dmabuf_get()
* Fix return value type cast for ib_umem_dmabuf_get()
* Return -EOPNOTSUPP instead of -EINVAL for unimplemented functions
* Remove an unnecessary use of unlikely()
* Remove left-over commit message resulted from rebase

v13: https://www.spinics.net/lists/linux-rdma/msg98227.html
* Rebase to the latest linux-rdma 'for-next' branch (5.10.0-rc6+)
* Check for device on-demand paging capability at the entry point of
  the new verbs command to avoid calling device's reg_user_mr_dmabuf()
  method when CONFIG_INFINIBAND_ON_DEMAND_PAGING is diabled.

v12: https://www.spinics.net/lists/linux-rdma/msg97943.html
* Move the prototype of function ib_umem_dmabuf_release() to ib_umem.h
  and remove umem_dmabuf.h
* Break a line that is too long

v11: https://www.spinics.net/lists/linux-rdma/msg97860.html
* Rework the parameter checking code inside ib_umem_dmabuf_get() 
* Fix incorrect error handling in the new verbs command handler
* Put a duplicated code sequence for checking iova and setting page size
  into a function
* In the invalidation callback, check for if the buffer has been mapped
  and thus the presence of a valid driver mr is ensured
* The patch that checks for dma_virt_ops is dropped because it is no
  longer needed
* The patch that documents that dma-buf size is fixed has landed at:
  https://cgit.freedesktop.org/drm/drm-misc/commit/?id=476b485be03c
  and thus is no longer included here
* The matching user space patch set is sent separately

v10: https://www.spinics.net/lists/linux-rdma/msg97483.html
* Don't map the pages in ib_umem_dmabuf_get(); use the size information
  of the dma-buf object to validate the umem size instead
* Use PAGE_SIZE directly instead of use ib_umem_find_best_pgsz() when
  the MR is created since the pages have not been mapped yet and dma-buf
  requires PAGE_SIZE anyway
* Always call mlx5_umem_find_best_pgsz() after mapping the pages to
  verify that the page size requirement is satisfied
* Add a patch to document that dma-buf size is fixed

v9: https://www.spinics.net/lists/linux-rdma/msg97432.html
* Clean up the code for sg list in-place modification
* Prevent dma-buf pages from being mapped multiple times
* Map the pages in ib_umem_dmabuf_get() so that inproper values of
  address/length/iova can be caught early
* Check for unsupported flags in the new uverbs command
* Add missing uverbs_finalize_uobj_create()
* Sort uverbs objects by name
* Fix formating issue -- unnecessary alignment of '='
* Unmap pages in mlx5_ib_fence_dmabuf_mr()
* Remove address range checking from pagefault_dmabuf_mr()

v8: https://www.spinics.net/lists/linux-rdma/msg97370.html
* Modify the dma-buf sg list in place to get a proper umem sg list and
  restore it before calling dma_buf_unmap_attachment()
* Validate the umem sg list with ib_umem_find_best_pgsz()
* Remove the logic for slicing the sg list at runtime

v7: https://www.spinics.net/lists/linux-rdma/msg97297.html
* Rebase on top of latest mlx5 MR patch series
* Slice dma-buf sg list at runtime instead of creating a new list
* Preload the buffer page mapping when the MR is created
* Move the 'dma_virt_ops' check into dma_buf_dynamic_attach()

v6: https://www.spinics.net/lists/linux-rdma/msg96923.html
* Move the dma-buf invalidation callback from the core to the device
  driver
* Move mapping update from work queue to pagefault handler
* Add dma-buf based MRs to the xarray of mmkeys so that the pagefault
  handler can be reached
* Update the new driver method and uverbs command signature by changing
  the paramter 'addr' to 'offset'
* Modify the sg list returned from dma_buf_map_attachment() based on
  the parameters 'offset' and 'length'
* Don't import dma-buf if 'dma_virt_ops' is used by the dma device
* The patch that clarifies dma-buf sg lists alignment has landed at
  https://cgit.freedesktop.org/drm/drm-misc/commit/?id=ac80cd17a615
  and thus is no longer included with this set

v5: https://www.spinics.net/lists/linux-rdma/msg96786.html
* Fix a few warnings reported by kernel test robot:
- no previous prototype for function 'ib_umem_dmabuf_release' 
- no previous prototype for function 'ib_umem_dmabuf_map_pages'
- comparison of distinct pointer types in 'check_add_overflow'
* Add comment for the wait between getting the dma-buf sg tagle and
  updating the NIC page table

v4: https://www.spinics.net/lists/linux-rdma/msg96767.html
* Add a new ib_device method reg_user_mr_dmabuf() instead of expanding
  the existing method reg_user_mr()
* Use a separate code flow for dma-buf instead of adding special cases
  to the ODP memory region code path
* In invalidation callback, new mapping is updated as whole using work
  queue instead of being updated in page granularity in the page fault
  handler
* Use dma_resv_get_excl() and dma_fence_wait() to ensure the content of
  the pages have been mov

[PATCH v14 2/4] RDMA/core: Add device method for registering dma-buf based memory region

2020-12-08 Thread Jianxin Xiong
Dma-buf based memory region requires one extra parameter and is processed
quite differently. Adding a separate method allows clean separation from
regular memory regions.

Signed-off-by: Jianxin Xiong 
Reviewed-by: Sean Hefty 
Acked-by: Michael J. Ruhl 
Acked-by: Christian Koenig 
Acked-by: Daniel Vetter 
Reviewed-by: Leon Romanovsky 
---
 drivers/infiniband/core/device.c | 1 +
 include/rdma/ib_verbs.h  | 6 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 3ab1ede..23f7440 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -2677,6 +2677,7 @@ void ib_set_device_ops(struct ib_device *dev, const 
struct ib_device_ops *ops)
SET_DEVICE_OP(dev_ops, read_counters);
SET_DEVICE_OP(dev_ops, reg_dm_mr);
SET_DEVICE_OP(dev_ops, reg_user_mr);
+   SET_DEVICE_OP(dev_ops, reg_user_mr_dmabuf);
SET_DEVICE_OP(dev_ops, req_ncomp_notif);
SET_DEVICE_OP(dev_ops, req_notify_cq);
SET_DEVICE_OP(dev_ops, rereg_user_mr);
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 7bee8ab..fa3882b 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -2,7 +2,7 @@
 /*
  * Copyright (c) 2004 Mellanox Technologies Ltd.  All rights reserved.
  * Copyright (c) 2004 Infinicon Corporation.  All rights reserved.
- * Copyright (c) 2004 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2004, 2020 Intel Corporation.  All rights reserved.
  * Copyright (c) 2004 Topspin Corporation.  All rights reserved.
  * Copyright (c) 2004 Voltaire Corporation.  All rights reserved.
  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
@@ -2433,6 +2433,10 @@ struct ib_device_ops {
struct ib_mr *(*reg_user_mr)(struct ib_pd *pd, u64 start, u64 length,
 u64 virt_addr, int mr_access_flags,
 struct ib_udata *udata);
+   struct ib_mr *(*reg_user_mr_dmabuf)(struct ib_pd *pd, u64 offset,
+u64 length, u64 virt_addr, int fd,
+int mr_access_flags,
+struct ib_udata *udata);
int (*rereg_user_mr)(struct ib_mr *mr, int flags, u64 start, u64 length,
 u64 virt_addr, int mr_access_flags,
 struct ib_pd *pd, struct ib_udata *udata);
-- 
1.8.3.1

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


Re: [PATCH] drm/amdgpu: make DRM_AMD_DC x86-only again

2020-12-08 Thread Arnd Bergmann
On Tue, Dec 8, 2020 at 7:21 PM 'Nick Desaulniers' via Clang Built
Linux  wrote:
>
> On Tue, Dec 8, 2020 at 6:26 AM Arnd Bergmann  wrote:
> >
> > On Mon, Dec 7, 2020 at 11:28 PM 'Nick Desaulniers' via Clang Built
> > Linux  wrote:
> Hmm...no warnings for me with that config on next-20201208:
> $ make LLVM=1 -j71 olddefconfig
> $ make LLVM=1 -j71
> ...
> $ clang --version
> clang version 12.0.0 (g...@github.com:llvm/llvm-project.git
> 1c98f984105e552daa83ed8e92c61fba0e401410)
> (ie. near ToT LLVM)
>
> I see CONFIG_KASAN=y in the .config, so that's a recurring theme with
> clang; excessive stack usage.  It does seem a shame to disable a
> driver for a bunch of archs just due to KASAN stack usage.
> $ grep KASAN=y 0x9077925C_defconfig
> CONFIG_HAVE_ARCH_KASAN=y
> CONFIG_KASAN=y
>
> Is there a different branch of a different tree that I should be
> testing on instead? Otherwise, can you send the object file?

I was on a slightly older linux-next, and the latest version contains
the patch "ubsan: enable for all*config builds" in linux-next,
which enables CONFIG_UBSAN_SANITIZE_ALL. It took me
an hour to figure out, but after turning that option off, the warning
is back.

I'll send you the object for reference in a private mail, it's kind
of large.

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


Re: [PATCH v2] [PATCH] drm/amdgpu: Initialise drm_gem_object_funcs for imported BOs

2020-12-08 Thread Alex Deucher
On Tue, Dec 8, 2020 at 3:16 PM Andrey Grodzovsky
 wrote:
>
> For BOs imported from outside of amdgpu, setting of amdgpu_gem_object_funcs
> was missing in amdgpu_dma_buf_create_obj. Fix by refactoring BO creation
> and amdgpu_gem_object_funcs setting into single function called
> from both code paths.
>
> Fixes: d693def4fd1c ("drm: Remove obsolete GEM and PRIME callbacks
> from struct drm_driver")
>
> v2: Use use amdgpu_gem_object_create() directly
>
> Signed-off-by: Andrey Grodzovsky 

Reviewed-by: Alex Deucher 

> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c |  8 --
>  drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 41 
> -
>  2 files changed, 29 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
> index e5919ef..e42175e 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
> @@ -424,6 +424,7 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, struct 
> dma_buf *dma_buf)
> struct amdgpu_device *adev = drm_to_adev(dev);
> struct amdgpu_bo *bo;
> struct amdgpu_bo_param bp;
> +   struct drm_gem_object *gobj;
> int ret;
>
> memset(&bp, 0, sizeof(bp));
> @@ -434,17 +435,20 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, 
> struct dma_buf *dma_buf)
> bp.type = ttm_bo_type_sg;
> bp.resv = resv;
> dma_resv_lock(resv, NULL);
> -   ret = amdgpu_bo_create(adev, &bp, &bo);
> +   ret = amdgpu_gem_object_create(adev, dma_buf->size, PAGE_SIZE,
> +   AMDGPU_GEM_DOMAIN_CPU,
> +   0, ttm_bo_type_sg, resv, &gobj);
> if (ret)
> goto error;
>
> +   bo = gem_to_amdgpu_bo(gobj);
> bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
> bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
> if (dma_buf->ops != &amdgpu_dmabuf_ops)
> bo->prime_shared_count = 1;
>
> dma_resv_unlock(resv);
> -   return &bo->tbo.base;
> +   return gobj;
>
>  error:
> dma_resv_unlock(resv);
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> index c9f94fb..ccf4d80 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> @@ -70,26 +70,12 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, 
> unsigned long size,
> bp.type = type;
> bp.resv = resv;
> bp.preferred_domain = initial_domain;
> -retry:
> bp.flags = flags;
> bp.domain = initial_domain;
> r = amdgpu_bo_create(adev, &bp, &bo);
> -   if (r) {
> -   if (r != -ERESTARTSYS) {
> -   if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) {
> -   flags &= 
> ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
> -   goto retry;
> -   }
> -
> -   if (initial_domain == AMDGPU_GEM_DOMAIN_VRAM) {
> -   initial_domain |= AMDGPU_GEM_DOMAIN_GTT;
> -   goto retry;
> -   }
> -   DRM_DEBUG("Failed to allocate GEM object (%ld, %d, 
> %u, %d)\n",
> - size, initial_domain, alignment, r);
> -   }
> +   if (r)
> return r;
> -   }
> +
> *obj = &bo->tbo.base;
> (*obj)->funcs = &amdgpu_gem_object_funcs;
>
> @@ -239,7 +225,7 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void 
> *data,
> uint64_t size = args->in.bo_size;
> struct dma_resv *resv = NULL;
> struct drm_gem_object *gobj;
> -   uint32_t handle;
> +   uint32_t handle, initial_domain;
> int r;
>
> /* reject invalid gem flags */
> @@ -283,9 +269,28 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void 
> *data,
> resv = vm->root.base.bo->tbo.base.resv;
> }
>
> +retry:
> +   initial_domain = (u32)(0x & args->in.domains);
> r = amdgpu_gem_object_create(adev, size, args->in.alignment,
> -(u32)(0x & args->in.domains),
> +initial_domain,
>  flags, ttm_bo_type_device, resv, &gobj);
> +   if (r) {
> +   if (r != -ERESTARTSYS) {
> +   if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) {
> +   flags &= 
> ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
> +   goto retry;
> +   }
> +
> +   if (initial_domain == AMDGPU_GEM_DOMAIN_VRAM) {
> +   initial_domain |= AMDGPU_GEM_DOMAIN_GTT;
> +   goto retry;
> +   }
> +   DRM_DEBUG("

[PATCH V2] drm/vkms: Add setup and testing information

2020-12-08 Thread Sumera Priyadarsini
Update the vkms documentation to contain steps to:

 - setup the vkms driver
 - run tests using igt

Signed-off-by: Sumera Priyadarsini 
___
Changes in v2:
 - Change heading to title case (Daniel)
 - Add examples to run tests directly (Daniel)
 - Add examples to run subtests (Melissa)
---
 Documentation/gpu/vkms.rst | 67 ++
 1 file changed, 67 insertions(+)

diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst
index 13bab1d93bb3..d6739fbbe503 100644
--- a/Documentation/gpu/vkms.rst
+++ b/Documentation/gpu/vkms.rst
@@ -7,6 +7,73 @@
 .. kernel-doc:: drivers/gpu/drm/vkms/vkms_drv.c
:doc: vkms (Virtual Kernel Modesetting)
 
+Setup
+=
+
+The VKMS driver can be setup with the following steps:
+
+To check if VKMS is loaded, run::
+
+  lsmod | grep vkms
+
+This should list the VKMS driver. If no output is obtained, then
+you need to enable and/or load the VKMS driver.
+Ensure that the VKMS driver has been set as a loadable module in your
+kernel config file. Do::
+
+  make nconfig
+
+  Go to `Device Drivers> Graphics support`
+
+  Enable `Virtual KMS (EXPERIMENTAL)`
+
+Compile and build the kernel for the changes to get reflected.
+Now, to load the driver, use::
+
+  sudo modprobe vkms
+
+On running the lsmod command now, the VKMS driver will appear listed.
+You can also observe the driver being loaded in the dmesg logs.
+
+To disable the driver, use ::
+
+  sudo modprobe -r vkms
+
+Testing With IGT
+
+
+The IGT GPU Tools is a test suite used specifically for debugging and
+development of the DRM drivers.
+The IGT Tools can be installed from
+`here `_ .
+
+The tests need to be run without a compositor, so you need to switch to text
+only mode. You can do this by::
+
+  sudo systemctl isolate multi-user.target
+
+To return to graphical mode, do::
+
+  sudo systemctl isolate graphical.target
+
+Once you are in text only mode, you can run tests using the --device switch
+or IGT_DEVICE variable to specify the device filter for the driver we want
+to test::
+
+  sudo ./build/tests/ --device "sys:/sys/devices/platform/vkms"
+  sudo IGT_DEVICE="sys:/sys/devices/platform/vkms" ./build/tests/
+
+For example, to test the functionality of the writeback library,
+we can run the kms_writeback test::
+
+  sudo ./build/tests/kms_writeback --device "sys:/sys/devices/platform/vkms"
+  sudo IGT_DEVICE="sys:/sys/devices/platform/vkms" ./build/tests/kms_writeback
+
+You can also run subtests if you do not want to run the entire test::
+
+  sudo ./build/tests/kms_flip --run-subtest basic-plain-flip --device 
"sys:/sys/devices/platform/vkms"
+  sudo IGT_DEVICE="sys:/sys/devices/platform/vkms" ./build/tests/kms_flip 
--run-subtest basic-plain-flip
+
 TODO
 
 
-- 
2.25.1

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


Re: [PATCH 5/6] drm/i915/bios: fill in DSC rc_model_size from VBT

2020-12-08 Thread Navare, Manasi
On Tue, Dec 08, 2020 at 02:33:54PM +0200, Jani Nikula wrote:
> The VBT fields match the DPCD data, so use the same helper.
> 
> Cc: Manasi Navare 
> Cc: Vandita Kulkarni 
> Signed-off-by: Jani Nikula 

Only for DSI so far right?

In that case looks good

Reviewed-by: Manasi Navare 

Manasi

> ---
>  drivers/gpu/drm/i915/display/intel_bios.c | 11 +++
>  1 file changed, 3 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c 
> b/drivers/gpu/drm/i915/display/intel_bios.c
> index 4cc949b228f2..06c3310446a2 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.c
> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> @@ -2555,16 +2555,11 @@ static void fill_dsc(struct intel_crtc_state 
> *crtc_state,
> crtc_state->dsc.slice_count);
>  
>   /*
> -  * FIXME: Use VBT rc_buffer_block_size and rc_buffer_size for the
> -  * implementation specific physical rate buffer size. Currently we use
> -  * the required rate buffer model size calculated in
> -  * drm_dsc_compute_rc_parameters() according to VESA DSC Annex E.
> -  *
>* The VBT rc_buffer_block_size and rc_buffer_size definitions
> -  * correspond to DP 1.4 DPCD offsets 0x62 and 0x63. The DP DSC
> -  * implementation should also use the DPCD (or perhaps VBT for eDP)
> -  * provided value for the buffer size.
> +  * correspond to DP 1.4 DPCD offsets 0x62 and 0x63.
>*/
> + vdsc_cfg->rc_model_size = 
> drm_dsc_dp_rc_buffer_size(dsc->rc_buffer_block_size,
> + 
> dsc->rc_buffer_size);
>  
>   /* FIXME: DSI spec says bpc + 1 for this one */
>   vdsc_cfg->line_buf_depth = 
> VBT_DSC_LINE_BUFFER_DEPTH(dsc->line_buffer_depth);
> -- 
> 2.20.1
> 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH 3/6] drm/i915/dsc: make rc_model_size an encoder defined value

2020-12-08 Thread Navare, Manasi
On Tue, Dec 08, 2020 at 02:33:52PM +0200, Jani Nikula wrote:
> Move the intialization of the rc_model_size from the common code into
> encoder code, allowing different encoders to specify the size according
> to their needs. Keep using the hard coded value in the encoders for now
> to make this a non-functional change.
> 
> Cc: Manasi Navare 
> Cc: Vandita Kulkarni 
> Signed-off-by: Jani Nikula 

So still using the hardcoded value since thats in the DSC C model, Looks good 
to me

Reviewed-by: Manasi Navare 

Manasi

> ---
>  drivers/gpu/drm/i915/display/icl_dsi.c| 3 +++
>  drivers/gpu/drm/i915/display/intel_dp.c   | 8 
>  drivers/gpu/drm/i915/display/intel_vdsc.c | 2 --
>  3 files changed, 11 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c 
> b/drivers/gpu/drm/i915/display/icl_dsi.c
> index a9439b415603..676e40172fe9 100644
> --- a/drivers/gpu/drm/i915/display/icl_dsi.c
> +++ b/drivers/gpu/drm/i915/display/icl_dsi.c
> @@ -1535,6 +1535,9 @@ static int gen11_dsi_dsc_compute_config(struct 
> intel_encoder *encoder,
>  
>   vdsc_cfg->convert_rgb = true;
>  
> + /* FIXME: initialize from VBT */
> + vdsc_cfg->rc_model_size = DSC_RC_MODEL_SIZE_CONST;
> +
>   ret = intel_dsc_compute_params(encoder, crtc_state);
>   if (ret)
>   return ret;
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
> b/drivers/gpu/drm/i915/display/intel_dp.c
> index cb5e42c3ecd5..b2bc0c8c39c7 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -2289,6 +2289,14 @@ static int intel_dp_dsc_compute_params(struct 
> intel_encoder *encoder,
>   u8 line_buf_depth;
>   int ret;
>  
> + /*
> +  * RC_MODEL_SIZE is currently a constant across all configurations.
> +  *
> +  * FIXME: Look into using sink defined DPCD DP_DSC_RC_BUF_BLK_SIZE and
> +  * DP_DSC_RC_BUF_SIZE for this.
> +  */
> + vdsc_cfg->rc_model_size = DSC_RC_MODEL_SIZE_CONST;
> +
>   ret = intel_dsc_compute_params(encoder, crtc_state);
>   if (ret)
>   return ret;
> diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c 
> b/drivers/gpu/drm/i915/display/intel_vdsc.c
> index 22d08679844f..f58cc5700784 100644
> --- a/drivers/gpu/drm/i915/display/intel_vdsc.c
> +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
> @@ -454,8 +454,6 @@ int intel_dsc_compute_params(struct intel_encoder 
> *encoder,
>   else if (vdsc_cfg->bits_per_component == 12)
>   vdsc_cfg->mux_word_size = DSC_MUX_WORD_SIZE_12_BPC;
>  
> - /* RC_MODEL_SIZE is a constant across all configurations */
> - vdsc_cfg->rc_model_size = DSC_RC_MODEL_SIZE_CONST;
>   /* InitialScaleValue is a 6 bit value with 3 fractional bits (U3.3) */
>   vdsc_cfg->initial_scale_value = (vdsc_cfg->rc_model_size << 3) /
>   (vdsc_cfg->rc_model_size - vdsc_cfg->initial_offset);
> -- 
> 2.20.1
> 
> ___
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2] [PATCH] drm/amdgpu: Initialise drm_gem_object_funcs for imported BOs

2020-12-08 Thread Andrey Grodzovsky
For BOs imported from outside of amdgpu, setting of amdgpu_gem_object_funcs
was missing in amdgpu_dma_buf_create_obj. Fix by refactoring BO creation
and amdgpu_gem_object_funcs setting into single function called
from both code paths.

Fixes: d693def4fd1c ("drm: Remove obsolete GEM and PRIME callbacks
from struct drm_driver")

v2: Use use amdgpu_gem_object_create() directly

Signed-off-by: Andrey Grodzovsky 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c |  8 --
 drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 41 -
 2 files changed, 29 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
index e5919ef..e42175e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -424,6 +424,7 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, struct 
dma_buf *dma_buf)
struct amdgpu_device *adev = drm_to_adev(dev);
struct amdgpu_bo *bo;
struct amdgpu_bo_param bp;
+   struct drm_gem_object *gobj;
int ret;
 
memset(&bp, 0, sizeof(bp));
@@ -434,17 +435,20 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, struct 
dma_buf *dma_buf)
bp.type = ttm_bo_type_sg;
bp.resv = resv;
dma_resv_lock(resv, NULL);
-   ret = amdgpu_bo_create(adev, &bp, &bo);
+   ret = amdgpu_gem_object_create(adev, dma_buf->size, PAGE_SIZE,
+   AMDGPU_GEM_DOMAIN_CPU,
+   0, ttm_bo_type_sg, resv, &gobj);
if (ret)
goto error;
 
+   bo = gem_to_amdgpu_bo(gobj);
bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
if (dma_buf->ops != &amdgpu_dmabuf_ops)
bo->prime_shared_count = 1;
 
dma_resv_unlock(resv);
-   return &bo->tbo.base;
+   return gobj;
 
 error:
dma_resv_unlock(resv);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index c9f94fb..ccf4d80 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -70,26 +70,12 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, 
unsigned long size,
bp.type = type;
bp.resv = resv;
bp.preferred_domain = initial_domain;
-retry:
bp.flags = flags;
bp.domain = initial_domain;
r = amdgpu_bo_create(adev, &bp, &bo);
-   if (r) {
-   if (r != -ERESTARTSYS) {
-   if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) {
-   flags &= ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
-   goto retry;
-   }
-
-   if (initial_domain == AMDGPU_GEM_DOMAIN_VRAM) {
-   initial_domain |= AMDGPU_GEM_DOMAIN_GTT;
-   goto retry;
-   }
-   DRM_DEBUG("Failed to allocate GEM object (%ld, %d, %u, 
%d)\n",
- size, initial_domain, alignment, r);
-   }
+   if (r)
return r;
-   }
+
*obj = &bo->tbo.base;
(*obj)->funcs = &amdgpu_gem_object_funcs;
 
@@ -239,7 +225,7 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void 
*data,
uint64_t size = args->in.bo_size;
struct dma_resv *resv = NULL;
struct drm_gem_object *gobj;
-   uint32_t handle;
+   uint32_t handle, initial_domain;
int r;
 
/* reject invalid gem flags */
@@ -283,9 +269,28 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void 
*data,
resv = vm->root.base.bo->tbo.base.resv;
}
 
+retry:
+   initial_domain = (u32)(0x & args->in.domains);
r = amdgpu_gem_object_create(adev, size, args->in.alignment,
-(u32)(0x & args->in.domains),
+initial_domain,
 flags, ttm_bo_type_device, resv, &gobj);
+   if (r) {
+   if (r != -ERESTARTSYS) {
+   if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) {
+   flags &= ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
+   goto retry;
+   }
+
+   if (initial_domain == AMDGPU_GEM_DOMAIN_VRAM) {
+   initial_domain |= AMDGPU_GEM_DOMAIN_GTT;
+   goto retry;
+   }
+   DRM_DEBUG("Failed to allocate GEM object (%ld, %d, %u, 
%d)\n",
+ size, initial_domain, args->in.alignment, r);
+   }
+   return r;
+   }
+
if (flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID) {
if (!r) {
struct amdgpu_bo *abo = gem_t

Re: [PATCH v5 11/29] drm/omap: dsi: pass vc to various functions

2020-12-08 Thread Tomi Valkeinen
On 08/12/2020 17:38, Laurent Pinchart wrote:
> Hi Tomi,
> 
> Thank you for the patch.
> 
> On Tue, Dec 08, 2020 at 02:28:37PM +0200, Tomi Valkeinen wrote:
>> To start fixing the issues related to channels and vcs described in the
>> previous commit, pass vc to various functions which will need it do
>> properly handle different DSI channels and VCs.
> 
> This is a bit hard to review as you add the OMAP DSI VC as a parameter
> (named vc) to some functions , and the MIPI DSI virtual channel as a
> parameter (named channel) to other functions. Only the former matches
> the commit message. Splitting this in two would make the changes

Ah, that's true. I'll update the title and desc to mention channel too.

 Tomi

-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


RE: [PATCH v13 1/4] RDMA/umem: Support importing dma-buf as user memory region

2020-12-08 Thread Xiong, Jianxin
> -Original Message-
> From: Jason Gunthorpe 
> Sent: Tuesday, December 08, 2020 10:59 AM
> To: Xiong, Jianxin 
> Cc: Leon Romanovsky ; linux-r...@vger.kernel.org; 
> dri-devel@lists.freedesktop.org; Doug Ledford
> ; Sumit Semwal ; Christian 
> Koenig ; Vetter, Daniel
> 
> Subject: Re: [PATCH v13 1/4] RDMA/umem: Support importing dma-buf as user 
> memory region
> 
> On Tue, Dec 08, 2020 at 06:13:20PM +, Xiong, Jianxin wrote:
> 
> > > > +static inline struct ib_umem *ib_umem_dmabuf_get(struct ib_device 
> > > > *device,
> > > > +unsigned long offset,
> > > > +size_t size, int fd,
> > > > +int access,
> > > > +struct 
> > > > dma_buf_attach_ops *ops) {
> > > > +   return ERR_PTR(-EINVAL);
> > >
> > > Probably, It should be EOPNOTSUPP and not EINVAL.
> >
> > EINVAL is used here to be consistent with existing definitions in the same 
> > file.
> 
> They may be wrong, EOPNOTSUPP is right for this situation

Ok, let me change all of them to EOPNOTSUPP.

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


Re: [PATCH] drm/amdgpu: Initialise drm_gem_object_funcs for imported BOs

2020-12-08 Thread Christian König

Am 08.12.20 um 20:11 schrieb Andrey Grodzovsky:


On 12/8/20 2:01 PM, Christian König wrote:

Am 08.12.20 um 19:52 schrieb Andrey Grodzovsky:


On 12/8/20 1:47 PM, Christian König wrote:

Am 08.12.20 um 19:44 schrieb Andrey Grodzovsky:


On 12/8/20 1:29 PM, Christian König wrote:

Am 08.12.20 um 19:26 schrieb Andrey Grodzovsky:


On 12/8/20 12:36 PM, Christian König wrote:

Am 08.12.20 um 18:10 schrieb Andrey Grodzovsky:
For BOs imported from outside of amdgpu, setting of 
amdgpu_gem_object_funcs
was missing in amdgpu_dma_buf_create_obj. Fix by refactoring 
BO creation

and amdgpu_gem_object_funcs setting into single function called
from both code paths.


Can you outline why we can't use amdgpu_gem_object_create() 
directly?


I mean we have a bit of extra error handling in there and we 
need to grab the resv lock and set the domains after creation, 
but that shouldn't matter and I don't see why that should not 
work.



On top of what you mentioned you also have 
bp.domain/bp.preferred_domain being set differently so you need 
to add another
argument to amdgpu_gem_object_create to reflect this difference 
which clutters even more the already cluttered argument list.


That should be outside of the call to amdgpu_gem_object_create(), 
similar to how it is outside of the amdgpu_bo_create currently.



So you agree we have to add another argument to 
amdgpu_gem_object_create (e.g. u32 preferred_domain) which will be 
0 for amdgpu_dma_buf_create_obj
and equal to initial_domain for all the code path currently 
calling amdgpu_gem_object_create ?


No, I just don't see the need for that. We need to overwrite the 
preferred domain after the function call anyway.


DMA-buf imports are created with the initial domain CPU and then 
get that overwritten to GTT after creation.







Regarding the extra error handling - you have the 'retry' dance 
in amdgpu_gem_object_create which jumps back to the middle of 
amdgpu_bo_param
initialization but you don't have it in 
amdgpu_dma_buf_create_obj which also complicates the reuse of 
amdgpu_gem_object_create as is.


Regarding the extra error handling, that kicks in only when 
AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED is specified as flags or 
AMDGPU_GEM_DOMAIN_VRAM as initial domain. Neither is the case here.



Yes, still, it makes me a bit uncomfortable relying on internal 
implementation details of an API function I call to do the thing I 
expect.


Yeah, ok that is a rather good argument.

Christian.



So should I just keep it as is or you think it's still would be more 
beneficial to unify them the way you propose ?


Maybe we should move the error handling into 
amdgpu_gem_create_ioctl() anyway.


We don't really want that handling in the userptr stuff and for the 
call from amdgpufb_create_pinned_object() that is actually a bug!


E.g. for the fb emulation we can't fall back from VRAM to GTT like in 
the create ioctl.



What about amdgpu_mode_dumb_create, seems like there GTT domain is 
also relevant and so the error handling would be needed there too.


Nope, same thing as with the fb emulation:


    domain = amdgpu_bo_get_preferred_pin_domain(adev,
amdgpu_display_supported_domains(adev, flags));


This BO is created for scanout, falling back to GTT because we don't 
have enough memory or clearing the CPU access flag is most likely a bug 
here.


Christian.



Andrey




Christian.



Andrey






Andrey




Christian.



Andrey




Thanks,
Christian.



This fixes null ptr regression casued by commit
d693def drm: Remove obsolete GEM and PRIME callbacks from 
struct drm_driver


Signed-off-by: Andrey Grodzovsky 
---
  drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 13 ++---
  drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 22 
+-

  drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h |  5 +
  3 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c

index e5919ef..da4d0ab 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -405,6 +405,7 @@ struct dma_buf 
*amdgpu_gem_prime_export(struct drm_gem_object *gobj,

  return buf;
  }
  +
  /**
   * amdgpu_dma_buf_create_obj - create BO for DMA-buf import
   *
@@ -424,7 +425,7 @@ amdgpu_dma_buf_create_obj(struct 
drm_device *dev, struct dma_buf *dma_buf)

  struct amdgpu_device *adev = drm_to_adev(dev);
  struct amdgpu_bo *bo;
  struct amdgpu_bo_param bp;
-    int ret;
+    struct drm_gem_object *obj;
    memset(&bp, 0, sizeof(bp));
  bp.size = dma_buf->size;
@@ -434,21 +435,19 @@ amdgpu_dma_buf_create_obj(struct 
drm_device *dev, struct dma_buf *dma_buf)

  bp.type = ttm_bo_type_sg;
  bp.resv = resv;
  dma_resv_lock(resv, NULL);
-    ret = amdgpu_bo_create(adev, &bp, &bo);
-    if (ret)
+    obj = amdgpu_gem_object_create_raw(adev, &bp);
+    if (IS_ERR(obj))
  goto error;
  +    bo = gem_to_amdgpu_bo

Re: [PATCH] drm/amdgpu: Initialise drm_gem_object_funcs for imported BOs

2020-12-08 Thread Andrey Grodzovsky


On 12/8/20 2:01 PM, Christian König wrote:

Am 08.12.20 um 19:52 schrieb Andrey Grodzovsky:


On 12/8/20 1:47 PM, Christian König wrote:

Am 08.12.20 um 19:44 schrieb Andrey Grodzovsky:


On 12/8/20 1:29 PM, Christian König wrote:

Am 08.12.20 um 19:26 schrieb Andrey Grodzovsky:


On 12/8/20 12:36 PM, Christian König wrote:

Am 08.12.20 um 18:10 schrieb Andrey Grodzovsky:
For BOs imported from outside of amdgpu, setting of 
amdgpu_gem_object_funcs

was missing in amdgpu_dma_buf_create_obj. Fix by refactoring BO creation
and amdgpu_gem_object_funcs setting into single function called
from both code paths.


Can you outline why we can't use amdgpu_gem_object_create() directly?

I mean we have a bit of extra error handling in there and we need to 
grab the resv lock and set the domains after creation, but that 
shouldn't matter and I don't see why that should not work.



On top of what you mentioned you also have bp.domain/bp.preferred_domain 
being set differently so you need to add another
argument to amdgpu_gem_object_create to reflect this difference which 
clutters even more the already cluttered argument list.


That should be outside of the call to amdgpu_gem_object_create(), similar 
to how it is outside of the amdgpu_bo_create currently.



So you agree we have to add another argument to amdgpu_gem_object_create 
(e.g. u32 preferred_domain) which will be 0 for amdgpu_dma_buf_create_obj
and equal to initial_domain for all the code path currently calling 
amdgpu_gem_object_create ?


No, I just don't see the need for that. We need to overwrite the preferred 
domain after the function call anyway.


DMA-buf imports are created with the initial domain CPU and then get that 
overwritten to GTT after creation.







Regarding the extra error handling - you have the 'retry' dance in 
amdgpu_gem_object_create which jumps back to the middle of amdgpu_bo_param
initialization but you don't have it in amdgpu_dma_buf_create_obj which 
also complicates the reuse of amdgpu_gem_object_create as is.


Regarding the extra error handling, that kicks in only when 
AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED is specified as flags or 
AMDGPU_GEM_DOMAIN_VRAM as initial domain. Neither is the case here.



Yes, still, it makes me a bit uncomfortable relying on internal 
implementation details of an API function I call to do the thing I expect.


Yeah, ok that is a rather good argument.

Christian.



So should I just keep it as is or you think it's still would be more 
beneficial to unify them the way you propose ?


Maybe we should move the error handling into amdgpu_gem_create_ioctl() anyway.

We don't really want that handling in the userptr stuff and for the call from 
amdgpufb_create_pinned_object() that is actually a bug!


E.g. for the fb emulation we can't fall back from VRAM to GTT like in the 
create ioctl.



What about amdgpu_mode_dumb_create, seems like there GTT domain is also relevant 
and so the error handling would be needed there too.


Andrey




Christian.



Andrey






Andrey




Christian.



Andrey




Thanks,
Christian.



This fixes null ptr regression casued by commit
d693def drm: Remove obsolete GEM and PRIME callbacks from struct 
drm_driver


Signed-off-by: Andrey Grodzovsky 
---
  drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 13 ++---
  drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 22 +-
  drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h |  5 +
  3 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c

index e5919ef..da4d0ab 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -405,6 +405,7 @@ struct dma_buf *amdgpu_gem_prime_export(struct 
drm_gem_object *gobj,

  return buf;
  }
  +
  /**
   * amdgpu_dma_buf_create_obj - create BO for DMA-buf import
   *
@@ -424,7 +425,7 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, 
struct dma_buf *dma_buf)

  struct amdgpu_device *adev = drm_to_adev(dev);
  struct amdgpu_bo *bo;
  struct amdgpu_bo_param bp;
-    int ret;
+    struct drm_gem_object *obj;
    memset(&bp, 0, sizeof(bp));
  bp.size = dma_buf->size;
@@ -434,21 +435,19 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, 
struct dma_buf *dma_buf)

  bp.type = ttm_bo_type_sg;
  bp.resv = resv;
  dma_resv_lock(resv, NULL);
-    ret = amdgpu_bo_create(adev, &bp, &bo);
-    if (ret)
+    obj = amdgpu_gem_object_create_raw(adev, &bp);
+    if (IS_ERR(obj))
  goto error;
  +    bo = gem_to_amdgpu_bo(obj);
  bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
  bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
  if (dma_buf->ops != &amdgpu_dmabuf_ops)
  bo->prime_shared_count = 1;
  -    dma_resv_unlock(resv);
-    return &bo->tbo.base;
-
  error:
  dma_resv_unlock(resv);
-    return ERR_PTR(ret);
+    return obj;
  }
    /**
diff --git a/drivers/gpu/drm/amd/

Re: [PATCH v13 1/4] RDMA/umem: Support importing dma-buf as user memory region

2020-12-08 Thread Leon Romanovsky
On Tue, Dec 08, 2020 at 06:13:20PM +, Xiong, Jianxin wrote:
> > -Original Message-
> > From: Leon Romanovsky 
> > Sent: Monday, December 07, 2020 11:06 PM
> > To: Xiong, Jianxin 
> > Cc: linux-r...@vger.kernel.org; dri-devel@lists.freedesktop.org; Doug 
> > Ledford ; Jason Gunthorpe ;
> > Sumit Semwal ; Christian Koenig 
> > ; Vetter, Daniel 
> > Subject: Re: [PATCH v13 1/4] RDMA/umem: Support importing dma-buf as user 
> > memory region
> >
> > On Mon, Dec 07, 2020 at 02:15:50PM -0800, Jianxin Xiong wrote:
> > > Dma-buf is a standard cross-driver buffer sharing mechanism that can
> > > be used to support peer-to-peer access from RDMA devices.
> > >
> > > Device memory exported via dma-buf is associated with a file descriptor.
> > > This is passed to the user space as a property associated with the
> > > buffer allocation. When the buffer is registered as a memory region,
> > > the file descriptor is passed to the RDMA driver along with other
> > > parameters.
> > >
> > > Implement the common code for importing dma-buf object and mapping
> > > dma-buf pages.
> > >
> > > Signed-off-by: Jianxin Xiong 
> > > Reviewed-by: Sean Hefty 
> > > Acked-by: Michael J. Ruhl 
> > > Acked-by: Christian Koenig 
> > > Acked-by: Daniel Vetter 
> > >
> > > Conflicts:
> > >   include/rdma/ib_umem.h
> >

<...>

> > > + /*
> > > +  * Although the sg list is valid now, the content of the pages
> > > +  * may be not up-to-date. Wait for the exporter to finish
> > > +  * the migration.
> > > +  */
> > > + fence = dma_resv_get_excl(umem_dmabuf->attach->dmabuf->resv);
> > > + if (fence)
> > > + dma_fence_wait(fence, false);
> >
> > Any reason do not check return result from dma_fence_wait()?
>
> This is called with interruptible flag set to false and normally should only 
> return 0.
> I do see similar usage cases that check the result and don't check the 
> result. Maybe
> we can add a WARN_ON here?

I have no idea :), just saw that other places check returned value.

<...>

> > > +
> > > +struct ib_umem *ib_umem_dmabuf_get(struct ib_device *device,
> > > +unsigned long offset, size_t size,
> > > +int fd, int access,
> > > +const struct dma_buf_attach_ops *ops) {
> > > + struct dma_buf *dmabuf;
> > > + struct ib_umem_dmabuf *umem_dmabuf;
> > > + struct ib_umem *umem;
> > > + unsigned long end;
> > > + long ret = -EINVAL;
> >
> > It is wrong type for the returned value. One of the possible options is to 
> > declare "struct ib_umem *ret;" and set ret = ERR_PTR(-EINVAL) or
> > ret = ERR_CAST(dmabuf);
>
> At the actual point the value is returned, ERR_PTR(ret) is used. I think we 
> can change the
> variable name to "err" instead to avoid confusion.

The point is that "ret" should be declared as "struct ib_umem *" and not
as "long" and ERR_CAST() should be used instead of (void *).

<...>

> > > +static inline struct ib_umem *ib_umem_dmabuf_get(struct ib_device 
> > > *device,
> > > +  unsigned long offset,
> > > +  size_t size, int fd,
> > > +  int access,
> > > +  struct dma_buf_attach_ops 
> > > *ops) {
> > > + return ERR_PTR(-EINVAL);
> >
> > Probably, It should be EOPNOTSUPP and not EINVAL.
>
> EINVAL is used here to be consistent with existing definitions in the same 
> file.

ok

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


Re: [PATCH] drm/amdgpu: Initialise drm_gem_object_funcs for imported BOs

2020-12-08 Thread Christian König

Am 08.12.20 um 19:52 schrieb Andrey Grodzovsky:


On 12/8/20 1:47 PM, Christian König wrote:

Am 08.12.20 um 19:44 schrieb Andrey Grodzovsky:


On 12/8/20 1:29 PM, Christian König wrote:

Am 08.12.20 um 19:26 schrieb Andrey Grodzovsky:


On 12/8/20 12:36 PM, Christian König wrote:

Am 08.12.20 um 18:10 schrieb Andrey Grodzovsky:
For BOs imported from outside of amdgpu, setting of 
amdgpu_gem_object_funcs
was missing in amdgpu_dma_buf_create_obj. Fix by refactoring BO 
creation

and amdgpu_gem_object_funcs setting into single function called
from both code paths.


Can you outline why we can't use amdgpu_gem_object_create() 
directly?


I mean we have a bit of extra error handling in there and we need 
to grab the resv lock and set the domains after creation, but 
that shouldn't matter and I don't see why that should not work.



On top of what you mentioned you also have 
bp.domain/bp.preferred_domain being set differently so you need to 
add another
argument to amdgpu_gem_object_create to reflect this difference 
which clutters even more the already cluttered argument list.


That should be outside of the call to amdgpu_gem_object_create(), 
similar to how it is outside of the amdgpu_bo_create currently.



So you agree we have to add another argument to 
amdgpu_gem_object_create (e.g. u32 preferred_domain) which will be 0 
for amdgpu_dma_buf_create_obj
and equal to initial_domain for all the code path currently calling 
amdgpu_gem_object_create ?


No, I just don't see the need for that. We need to overwrite the 
preferred domain after the function call anyway.


DMA-buf imports are created with the initial domain CPU and then get 
that overwritten to GTT after creation.







Regarding the extra error handling - you have the 'retry' dance in 
amdgpu_gem_object_create which jumps back to the middle of 
amdgpu_bo_param
initialization but you don't have it in amdgpu_dma_buf_create_obj 
which also complicates the reuse of amdgpu_gem_object_create as is.


Regarding the extra error handling, that kicks in only when 
AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED is specified as flags or 
AMDGPU_GEM_DOMAIN_VRAM as initial domain. Neither is the case here.



Yes, still, it makes me a bit uncomfortable relying on internal 
implementation details of an API function I call to do the thing I 
expect.


Yeah, ok that is a rather good argument.

Christian.



So should I just keep it as is or you think it's still would be more 
beneficial to unify them the way you propose ?


Maybe we should move the error handling into amdgpu_gem_create_ioctl() 
anyway.


We don't really want that handling in the userptr stuff and for the call 
from amdgpufb_create_pinned_object() that is actually a bug!


E.g. for the fb emulation we can't fall back from VRAM to GTT like in 
the create ioctl.


Christian.



Andrey






Andrey




Christian.



Andrey




Thanks,
Christian.



This fixes null ptr regression casued by commit
d693def drm: Remove obsolete GEM and PRIME callbacks from struct 
drm_driver


Signed-off-by: Andrey Grodzovsky 
---
  drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 13 ++---
  drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 22 
+-

  drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h |  5 +
  3 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c

index e5919ef..da4d0ab 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -405,6 +405,7 @@ struct dma_buf 
*amdgpu_gem_prime_export(struct drm_gem_object *gobj,

  return buf;
  }
  +
  /**
   * amdgpu_dma_buf_create_obj - create BO for DMA-buf import
   *
@@ -424,7 +425,7 @@ amdgpu_dma_buf_create_obj(struct drm_device 
*dev, struct dma_buf *dma_buf)

  struct amdgpu_device *adev = drm_to_adev(dev);
  struct amdgpu_bo *bo;
  struct amdgpu_bo_param bp;
-    int ret;
+    struct drm_gem_object *obj;
    memset(&bp, 0, sizeof(bp));
  bp.size = dma_buf->size;
@@ -434,21 +435,19 @@ amdgpu_dma_buf_create_obj(struct 
drm_device *dev, struct dma_buf *dma_buf)

  bp.type = ttm_bo_type_sg;
  bp.resv = resv;
  dma_resv_lock(resv, NULL);
-    ret = amdgpu_bo_create(adev, &bp, &bo);
-    if (ret)
+    obj = amdgpu_gem_object_create_raw(adev, &bp);
+    if (IS_ERR(obj))
  goto error;
  +    bo = gem_to_amdgpu_bo(obj);
  bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
  bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
  if (dma_buf->ops != &amdgpu_dmabuf_ops)
  bo->prime_shared_count = 1;
  -    dma_resv_unlock(resv);
-    return &bo->tbo.base;
-
  error:
  dma_resv_unlock(resv);
-    return ERR_PTR(ret);
+    return obj;
  }
    /**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c

index c9f94fb..5f22ce6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem

Re: [PATCH] drm/amdgpu: Initialise drm_gem_object_funcs for imported BOs

2020-12-08 Thread Andrey Grodzovsky


On 12/8/20 1:47 PM, Christian König wrote:

Am 08.12.20 um 19:44 schrieb Andrey Grodzovsky:


On 12/8/20 1:29 PM, Christian König wrote:

Am 08.12.20 um 19:26 schrieb Andrey Grodzovsky:


On 12/8/20 12:36 PM, Christian König wrote:

Am 08.12.20 um 18:10 schrieb Andrey Grodzovsky:

For BOs imported from outside of amdgpu, setting of amdgpu_gem_object_funcs
was missing in amdgpu_dma_buf_create_obj. Fix by refactoring BO creation
and amdgpu_gem_object_funcs setting into single function called
from both code paths.


Can you outline why we can't use amdgpu_gem_object_create() directly?

I mean we have a bit of extra error handling in there and we need to grab 
the resv lock and set the domains after creation, but that shouldn't 
matter and I don't see why that should not work.



On top of what you mentioned you also have bp.domain/bp.preferred_domain 
being set differently so you need to add another
argument to amdgpu_gem_object_create to reflect this difference which 
clutters even more the already cluttered argument list.


That should be outside of the call to amdgpu_gem_object_create(), similar to 
how it is outside of the amdgpu_bo_create currently.



So you agree we have to add another argument to amdgpu_gem_object_create 
(e.g. u32 preferred_domain) which will be 0 for amdgpu_dma_buf_create_obj
and equal to initial_domain for all the code path currently calling 
amdgpu_gem_object_create ?


No, I just don't see the need for that. We need to overwrite the preferred 
domain after the function call anyway.


DMA-buf imports are created with the initial domain CPU and then get that 
overwritten to GTT after creation.







Regarding the extra error handling - you have the 'retry' dance in 
amdgpu_gem_object_create which jumps back to the middle of amdgpu_bo_param
initialization but you don't have it in amdgpu_dma_buf_create_obj which 
also complicates the reuse of amdgpu_gem_object_create as is.


Regarding the extra error handling, that kicks in only when 
AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED is specified as flags or 
AMDGPU_GEM_DOMAIN_VRAM as initial domain. Neither is the case here.



Yes, still, it makes me a bit uncomfortable relying on internal 
implementation details of an API function I call to do the thing I expect.


Yeah, ok that is a rather good argument.

Christian.



So should I just keep it as is or you think it's still would be more beneficial 
to unify them the way you propose ?


Andrey






Andrey




Christian.



Andrey




Thanks,
Christian.



This fixes null ptr regression casued by commit
d693def drm: Remove obsolete GEM and PRIME callbacks from struct drm_driver

Signed-off-by: Andrey Grodzovsky 
---
  drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 13 ++---
  drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 22 +-
  drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h |  5 +
  3 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c

index e5919ef..da4d0ab 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -405,6 +405,7 @@ struct dma_buf *amdgpu_gem_prime_export(struct 
drm_gem_object *gobj,

  return buf;
  }
  +
  /**
   * amdgpu_dma_buf_create_obj - create BO for DMA-buf import
   *
@@ -424,7 +425,7 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, 
struct dma_buf *dma_buf)

  struct amdgpu_device *adev = drm_to_adev(dev);
  struct amdgpu_bo *bo;
  struct amdgpu_bo_param bp;
-    int ret;
+    struct drm_gem_object *obj;
    memset(&bp, 0, sizeof(bp));
  bp.size = dma_buf->size;
@@ -434,21 +435,19 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, 
struct dma_buf *dma_buf)

  bp.type = ttm_bo_type_sg;
  bp.resv = resv;
  dma_resv_lock(resv, NULL);
-    ret = amdgpu_bo_create(adev, &bp, &bo);
-    if (ret)
+    obj = amdgpu_gem_object_create_raw(adev, &bp);
+    if (IS_ERR(obj))
  goto error;
  +    bo = gem_to_amdgpu_bo(obj);
  bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
  bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
  if (dma_buf->ops != &amdgpu_dmabuf_ops)
  bo->prime_shared_count = 1;
  -    dma_resv_unlock(resv);
-    return &bo->tbo.base;
-
  error:
  dma_resv_unlock(resv);
-    return ERR_PTR(ret);
+    return obj;
  }
    /**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c

index c9f94fb..5f22ce6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -52,13 +52,26 @@ static void amdgpu_gem_object_free(struct 
drm_gem_object *gobj)

  }
  }
  +struct drm_gem_object *amdgpu_gem_object_create_raw(struct 
amdgpu_device *adev,

+    struct amdgpu_bo_param *bp)
+{
+    struct amdgpu_bo *bo;
+    int r;
+
+    r = amdgpu_bo_create(adev, bp, &bo);
+    if (r)
+    return ERR_PTR(r);
+
+    bo->tbo.b

Re: [PATCH v4 01/19] drm/encoder: make encoder control functions optional

2020-12-08 Thread Sam Ravnborg
Hi Philipp,
On Tue, Dec 08, 2020 at 04:54:33PM +0100, Philipp Zabel wrote:
> Simple managed encoders do not require the .destroy callback,
> make the whole funcs structure optional.
> 
> Signed-off-by: Philipp Zabel 
> Reviewed-by: Laurent Pinchart 
> ---
> New in v4.
> ---
>  drivers/gpu/drm/drm_encoder.c | 4 ++--
>  drivers/gpu/drm/drm_mode_config.c | 5 +++--
>  include/drm/drm_encoder.h | 2 +-
>  3 files changed, 6 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
> index e555281f43d4..b0b86a3c08f5 100644
> --- a/drivers/gpu/drm/drm_encoder.c
> +++ b/drivers/gpu/drm/drm_encoder.c
> @@ -72,7 +72,7 @@ int drm_encoder_register_all(struct drm_device *dev)
>   int ret = 0;
>  
>   drm_for_each_encoder(encoder, dev) {
> - if (encoder->funcs->late_register)
> + if (encoder->funcs && encoder->funcs->late_register)
>   ret = encoder->funcs->late_register(encoder);
>   if (ret)
>   return ret;
> @@ -86,7 +86,7 @@ void drm_encoder_unregister_all(struct drm_device *dev)
>   struct drm_encoder *encoder;
>  
>   drm_for_each_encoder(encoder, dev) {
> - if (encoder->funcs->early_unregister)
> + if (encoder->funcs && encoder->funcs->early_unregister)
>   encoder->funcs->early_unregister(encoder);
>   }
>  }
> diff --git a/drivers/gpu/drm/drm_mode_config.c 
> b/drivers/gpu/drm/drm_mode_config.c
> index f1affc1bb679..87e144155456 100644
> --- a/drivers/gpu/drm/drm_mode_config.c
> +++ b/drivers/gpu/drm/drm_mode_config.c
> @@ -195,7 +195,7 @@ void drm_mode_config_reset(struct drm_device *dev)
>   crtc->funcs->reset(crtc);
>  
>   drm_for_each_encoder(encoder, dev)
> - if (encoder->funcs->reset)
> + if (encoder->funcs && encoder->funcs->reset)
>   encoder->funcs->reset(encoder);
>  
>   drm_connector_list_iter_begin(dev, &conn_iter);
> @@ -487,7 +487,8 @@ void drm_mode_config_cleanup(struct drm_device *dev)
>  
>   list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list,
>head) {
> - encoder->funcs->destroy(encoder);
> + if (encoder->funcs)
> + encoder->funcs->destroy(encoder);

So late_register and early_unregister are both optional.
But if encoder->funcs is set then the destroy callback is mandatory.

I am just wondering if this is intended.
Reding the documnetation of drm_encoder_funcs thist matches the
documentation but anyway..

With this comment considered,
Reviewed-by: Sam Ravnborg 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH] drm/amdgpu: Initialise drm_gem_object_funcs for imported BOs

2020-12-08 Thread Christian König

Am 08.12.20 um 19:44 schrieb Andrey Grodzovsky:


On 12/8/20 1:29 PM, Christian König wrote:

Am 08.12.20 um 19:26 schrieb Andrey Grodzovsky:


On 12/8/20 12:36 PM, Christian König wrote:

Am 08.12.20 um 18:10 schrieb Andrey Grodzovsky:
For BOs imported from outside of amdgpu, setting of 
amdgpu_gem_object_funcs
was missing in amdgpu_dma_buf_create_obj. Fix by refactoring BO 
creation

and amdgpu_gem_object_funcs setting into single function called
from both code paths.


Can you outline why we can't use amdgpu_gem_object_create() directly?

I mean we have a bit of extra error handling in there and we need 
to grab the resv lock and set the domains after creation, but that 
shouldn't matter and I don't see why that should not work.



On top of what you mentioned you also have 
bp.domain/bp.preferred_domain being set differently so you need to 
add another
argument to amdgpu_gem_object_create to reflect this difference 
which clutters even more the already cluttered argument list.


That should be outside of the call to amdgpu_gem_object_create(), 
similar to how it is outside of the amdgpu_bo_create currently.



So you agree we have to add another argument to 
amdgpu_gem_object_create (e.g. u32 preferred_domain) which will be 0 
for amdgpu_dma_buf_create_obj
and equal to initial_domain for all the code path currently calling 
amdgpu_gem_object_create ?


No, I just don't see the need for that. We need to overwrite the 
preferred domain after the function call anyway.


DMA-buf imports are created with the initial domain CPU and then get 
that overwritten to GTT after creation.







Regarding the extra error handling - you have the 'retry' dance in 
amdgpu_gem_object_create which jumps back to the middle of 
amdgpu_bo_param
initialization but you don't have it in amdgpu_dma_buf_create_obj 
which also complicates the reuse of amdgpu_gem_object_create as is.


Regarding the extra error handling, that kicks in only when 
AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED is specified as flags or 
AMDGPU_GEM_DOMAIN_VRAM as initial domain. Neither is the case here.



Yes, still, it makes me a bit uncomfortable relying on internal 
implementation details of an API function I call to do the thing I 
expect.


Yeah, ok that is a rather good argument.

Christian.



Andrey




Christian.



Andrey




Thanks,
Christian.



This fixes null ptr regression casued by commit
d693def drm: Remove obsolete GEM and PRIME callbacks from struct 
drm_driver


Signed-off-by: Andrey Grodzovsky 
---
  drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 13 ++---
  drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 22 
+-

  drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h |  5 +
  3 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c

index e5919ef..da4d0ab 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -405,6 +405,7 @@ struct dma_buf *amdgpu_gem_prime_export(struct 
drm_gem_object *gobj,

  return buf;
  }
  +
  /**
   * amdgpu_dma_buf_create_obj - create BO for DMA-buf import
   *
@@ -424,7 +425,7 @@ amdgpu_dma_buf_create_obj(struct drm_device 
*dev, struct dma_buf *dma_buf)

  struct amdgpu_device *adev = drm_to_adev(dev);
  struct amdgpu_bo *bo;
  struct amdgpu_bo_param bp;
-    int ret;
+    struct drm_gem_object *obj;
    memset(&bp, 0, sizeof(bp));
  bp.size = dma_buf->size;
@@ -434,21 +435,19 @@ amdgpu_dma_buf_create_obj(struct drm_device 
*dev, struct dma_buf *dma_buf)

  bp.type = ttm_bo_type_sg;
  bp.resv = resv;
  dma_resv_lock(resv, NULL);
-    ret = amdgpu_bo_create(adev, &bp, &bo);
-    if (ret)
+    obj = amdgpu_gem_object_create_raw(adev, &bp);
+    if (IS_ERR(obj))
  goto error;
  +    bo = gem_to_amdgpu_bo(obj);
  bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
  bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
  if (dma_buf->ops != &amdgpu_dmabuf_ops)
  bo->prime_shared_count = 1;
  -    dma_resv_unlock(resv);
-    return &bo->tbo.base;
-
  error:
  dma_resv_unlock(resv);
-    return ERR_PTR(ret);
+    return obj;
  }
    /**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c

index c9f94fb..5f22ce6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -52,13 +52,26 @@ static void amdgpu_gem_object_free(struct 
drm_gem_object *gobj)

  }
  }
  +struct drm_gem_object *amdgpu_gem_object_create_raw(struct 
amdgpu_device *adev,

+    struct amdgpu_bo_param *bp)
+{
+    struct amdgpu_bo *bo;
+    int r;
+
+    r = amdgpu_bo_create(adev, bp, &bo);
+    if (r)
+    return ERR_PTR(r);
+
+    bo->tbo.base.funcs = &amdgpu_gem_object_funcs;
+    return &bo->tbo.base;
+}
+
  int amdgpu_gem_object_create(struct amdgpu_device *adev, 
unsigned long size,


Re: [PATCH] drm/amdgpu: Initialise drm_gem_object_funcs for imported BOs

2020-12-08 Thread Andrey Grodzovsky


On 12/8/20 1:29 PM, Christian König wrote:

Am 08.12.20 um 19:26 schrieb Andrey Grodzovsky:


On 12/8/20 12:36 PM, Christian König wrote:

Am 08.12.20 um 18:10 schrieb Andrey Grodzovsky:

For BOs imported from outside of amdgpu, setting of amdgpu_gem_object_funcs
was missing in amdgpu_dma_buf_create_obj. Fix by refactoring BO creation
and amdgpu_gem_object_funcs setting into single function called
from both code paths.


Can you outline why we can't use amdgpu_gem_object_create() directly?

I mean we have a bit of extra error handling in there and we need to grab 
the resv lock and set the domains after creation, but that shouldn't matter 
and I don't see why that should not work.



On top of what you mentioned you also have bp.domain/bp.preferred_domain 
being set differently so you need to add another
argument to amdgpu_gem_object_create to reflect this difference which 
clutters even more the already cluttered argument list.


That should be outside of the call to amdgpu_gem_object_create(), similar to 
how it is outside of the amdgpu_bo_create currently.



So you agree we have to add another argument to amdgpu_gem_object_create (e.g. 
u32 preferred_domain) which will be 0 for amdgpu_dma_buf_create_obj
and equal to initial_domain for all the code path currently calling 
amdgpu_gem_object_create ?





Regarding the extra error handling -  you have the 'retry' dance in 
amdgpu_gem_object_create which jumps back to the middle of amdgpu_bo_param
initialization but you don't have it in amdgpu_dma_buf_create_obj which also 
complicates the reuse of amdgpu_gem_object_create as is.


Regarding the extra error handling, that kicks in only when 
AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED is specified as flags or 
AMDGPU_GEM_DOMAIN_VRAM as initial domain. Neither is the case here.



Yes, still, it makes me a bit uncomfortable relying on internal implementation 
details of an API function I call to do the thing I expect.


Andrey




Christian.



Andrey




Thanks,
Christian.



This fixes null ptr regression casued by commit
d693def drm: Remove obsolete GEM and PRIME callbacks from struct drm_driver

Signed-off-by: Andrey Grodzovsky 
---
  drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 13 ++---
  drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 22 +-
  drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h |  5 +
  3 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c

index e5919ef..da4d0ab 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -405,6 +405,7 @@ struct dma_buf *amdgpu_gem_prime_export(struct 
drm_gem_object *gobj,

  return buf;
  }
  +
  /**
   * amdgpu_dma_buf_create_obj - create BO for DMA-buf import
   *
@@ -424,7 +425,7 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, 
struct dma_buf *dma_buf)

  struct amdgpu_device *adev = drm_to_adev(dev);
  struct amdgpu_bo *bo;
  struct amdgpu_bo_param bp;
-    int ret;
+    struct drm_gem_object *obj;
    memset(&bp, 0, sizeof(bp));
  bp.size = dma_buf->size;
@@ -434,21 +435,19 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, 
struct dma_buf *dma_buf)

  bp.type = ttm_bo_type_sg;
  bp.resv = resv;
  dma_resv_lock(resv, NULL);
-    ret = amdgpu_bo_create(adev, &bp, &bo);
-    if (ret)
+    obj = amdgpu_gem_object_create_raw(adev, &bp);
+    if (IS_ERR(obj))
  goto error;
  +    bo = gem_to_amdgpu_bo(obj);
  bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
  bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
  if (dma_buf->ops != &amdgpu_dmabuf_ops)
  bo->prime_shared_count = 1;
  -    dma_resv_unlock(resv);
-    return &bo->tbo.base;
-
  error:
  dma_resv_unlock(resv);
-    return ERR_PTR(ret);
+    return obj;
  }
    /**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c

index c9f94fb..5f22ce6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -52,13 +52,26 @@ static void amdgpu_gem_object_free(struct 
drm_gem_object *gobj)

  }
  }
  +struct drm_gem_object *amdgpu_gem_object_create_raw(struct amdgpu_device 
*adev,

+    struct amdgpu_bo_param *bp)
+{
+    struct amdgpu_bo *bo;
+    int r;
+
+    r = amdgpu_bo_create(adev, bp, &bo);
+    if (r)
+    return ERR_PTR(r);
+
+    bo->tbo.base.funcs = &amdgpu_gem_object_funcs;
+    return &bo->tbo.base;
+}
+
  int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size,
   int alignment, u32 initial_domain,
   u64 flags, enum ttm_bo_type type,
   struct dma_resv *resv,
   struct drm_gem_object **obj)
  {
-    struct amdgpu_bo *bo;
  struct amdgpu_bo_param bp;
  int r;
  @@ -73,8 +86,9 @@ int amdgpu_gem_object_create(struct amdgpu_device 
*adev, unsigned lo

Re: [PATCH] drm/amdgpu: Initialise drm_gem_object_funcs for imported BOs

2020-12-08 Thread Christian König

Am 08.12.20 um 19:26 schrieb Andrey Grodzovsky:


On 12/8/20 12:36 PM, Christian König wrote:

Am 08.12.20 um 18:10 schrieb Andrey Grodzovsky:
For BOs imported from outside of amdgpu, setting of 
amdgpu_gem_object_funcs
was missing in amdgpu_dma_buf_create_obj. Fix by refactoring BO 
creation

and amdgpu_gem_object_funcs setting into single function called
from both code paths.


Can you outline why we can't use amdgpu_gem_object_create() directly?

I mean we have a bit of extra error handling in there and we need to 
grab the resv lock and set the domains after creation, but that 
shouldn't matter and I don't see why that should not work.



On top of what you mentioned you also have 
bp.domain/bp.preferred_domain being set differently so you need to add 
another
argument to amdgpu_gem_object_create to reflect this difference which 
clutters even more the already cluttered argument list.


That should be outside of the call to amdgpu_gem_object_create(), 
similar to how it is outside of the amdgpu_bo_create currently.


Regarding the extra error handling -  you have the 'retry' dance in 
amdgpu_gem_object_create which jumps back to the middle of 
amdgpu_bo_param
initialization but you don't have it in amdgpu_dma_buf_create_obj 
which also complicates the reuse of amdgpu_gem_object_create as is.


Regarding the extra error handling, that kicks in only when 
AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED is specified as flags or 
AMDGPU_GEM_DOMAIN_VRAM as initial domain. Neither is the case here.


Christian.



Andrey




Thanks,
Christian.



This fixes null ptr regression casued by commit
d693def drm: Remove obsolete GEM and PRIME callbacks from struct 
drm_driver


Signed-off-by: Andrey Grodzovsky 
---
  drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 13 ++---
  drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 22 
+-

  drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h |  5 +
  3 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c

index e5919ef..da4d0ab 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -405,6 +405,7 @@ struct dma_buf *amdgpu_gem_prime_export(struct 
drm_gem_object *gobj,

  return buf;
  }
  +
  /**
   * amdgpu_dma_buf_create_obj - create BO for DMA-buf import
   *
@@ -424,7 +425,7 @@ amdgpu_dma_buf_create_obj(struct drm_device 
*dev, struct dma_buf *dma_buf)

  struct amdgpu_device *adev = drm_to_adev(dev);
  struct amdgpu_bo *bo;
  struct amdgpu_bo_param bp;
-    int ret;
+    struct drm_gem_object *obj;
    memset(&bp, 0, sizeof(bp));
  bp.size = dma_buf->size;
@@ -434,21 +435,19 @@ amdgpu_dma_buf_create_obj(struct drm_device 
*dev, struct dma_buf *dma_buf)

  bp.type = ttm_bo_type_sg;
  bp.resv = resv;
  dma_resv_lock(resv, NULL);
-    ret = amdgpu_bo_create(adev, &bp, &bo);
-    if (ret)
+    obj = amdgpu_gem_object_create_raw(adev, &bp);
+    if (IS_ERR(obj))
  goto error;
  +    bo = gem_to_amdgpu_bo(obj);
  bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
  bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
  if (dma_buf->ops != &amdgpu_dmabuf_ops)
  bo->prime_shared_count = 1;
  -    dma_resv_unlock(resv);
-    return &bo->tbo.base;
-
  error:
  dma_resv_unlock(resv);
-    return ERR_PTR(ret);
+    return obj;
  }
    /**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c

index c9f94fb..5f22ce6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -52,13 +52,26 @@ static void amdgpu_gem_object_free(struct 
drm_gem_object *gobj)

  }
  }
  +struct drm_gem_object *amdgpu_gem_object_create_raw(struct 
amdgpu_device *adev,

+    struct amdgpu_bo_param *bp)
+{
+    struct amdgpu_bo *bo;
+    int r;
+
+    r = amdgpu_bo_create(adev, bp, &bo);
+    if (r)
+    return ERR_PTR(r);
+
+    bo->tbo.base.funcs = &amdgpu_gem_object_funcs;
+    return &bo->tbo.base;
+}
+
  int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned 
long size,

   int alignment, u32 initial_domain,
   u64 flags, enum ttm_bo_type type,
   struct dma_resv *resv,
   struct drm_gem_object **obj)
  {
-    struct amdgpu_bo *bo;
  struct amdgpu_bo_param bp;
  int r;
  @@ -73,8 +86,9 @@ int amdgpu_gem_object_create(struct 
amdgpu_device *adev, unsigned long size,

  retry:
  bp.flags = flags;
  bp.domain = initial_domain;
-    r = amdgpu_bo_create(adev, &bp, &bo);
-    if (r) {
+    *obj = amdgpu_gem_object_create_raw(adev, &bp);
+    if (IS_ERR(*obj)) {
+    r = PTR_ERR(*obj);
  if (r != -ERESTARTSYS) {
  if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) {
  flags &= ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
@@ -90,8 +104,6 @@ int amdgpu_

Re: [PATCH] drm/amdgpu: Initialise drm_gem_object_funcs for imported BOs

2020-12-08 Thread Andrey Grodzovsky


On 12/8/20 12:36 PM, Christian König wrote:

Am 08.12.20 um 18:10 schrieb Andrey Grodzovsky:

For BOs imported from outside of amdgpu, setting of amdgpu_gem_object_funcs
was missing in amdgpu_dma_buf_create_obj. Fix by refactoring BO creation
and amdgpu_gem_object_funcs setting into single function called
from both code paths.


Can you outline why we can't use amdgpu_gem_object_create() directly?

I mean we have a bit of extra error handling in there and we need to grab the 
resv lock and set the domains after creation, but that shouldn't matter and I 
don't see why that should not work.



On top of what you mentioned you also have bp.domain/bp.preferred_domain being 
set differently so you need to add another
argument to amdgpu_gem_object_create to reflect this difference which clutters 
even more the already cluttered argument list.
Regarding the extra error handling -  you have the 'retry' dance in 
amdgpu_gem_object_create which jumps back to the middle of amdgpu_bo_param
initialization but you don't have it in amdgpu_dma_buf_create_obj which also 
complicates the reuse of amdgpu_gem_object_create as is.


Andrey




Thanks,
Christian.



This fixes null ptr regression casued by commit
d693def drm: Remove obsolete GEM and PRIME callbacks from struct drm_driver

Signed-off-by: Andrey Grodzovsky 
---
  drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 13 ++---
  drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 22 +-
  drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h |  5 +
  3 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c

index e5919ef..da4d0ab 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -405,6 +405,7 @@ struct dma_buf *amdgpu_gem_prime_export(struct 
drm_gem_object *gobj,

  return buf;
  }
  +
  /**
   * amdgpu_dma_buf_create_obj - create BO for DMA-buf import
   *
@@ -424,7 +425,7 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, struct 
dma_buf *dma_buf)

  struct amdgpu_device *adev = drm_to_adev(dev);
  struct amdgpu_bo *bo;
  struct amdgpu_bo_param bp;
-    int ret;
+    struct drm_gem_object *obj;
    memset(&bp, 0, sizeof(bp));
  bp.size = dma_buf->size;
@@ -434,21 +435,19 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, 
struct dma_buf *dma_buf)

  bp.type = ttm_bo_type_sg;
  bp.resv = resv;
  dma_resv_lock(resv, NULL);
-    ret = amdgpu_bo_create(adev, &bp, &bo);
-    if (ret)
+    obj = amdgpu_gem_object_create_raw(adev, &bp);
+    if (IS_ERR(obj))
  goto error;
  +    bo = gem_to_amdgpu_bo(obj);
  bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
  bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
  if (dma_buf->ops != &amdgpu_dmabuf_ops)
  bo->prime_shared_count = 1;
  -    dma_resv_unlock(resv);
-    return &bo->tbo.base;
-
  error:
  dma_resv_unlock(resv);
-    return ERR_PTR(ret);
+    return obj;
  }
    /**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c

index c9f94fb..5f22ce6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -52,13 +52,26 @@ static void amdgpu_gem_object_free(struct drm_gem_object 
*gobj)

  }
  }
  +struct drm_gem_object *amdgpu_gem_object_create_raw(struct amdgpu_device 
*adev,

+    struct amdgpu_bo_param *bp)
+{
+    struct amdgpu_bo *bo;
+    int r;
+
+    r = amdgpu_bo_create(adev, bp, &bo);
+    if (r)
+    return ERR_PTR(r);
+
+    bo->tbo.base.funcs = &amdgpu_gem_object_funcs;
+    return &bo->tbo.base;
+}
+
  int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size,
   int alignment, u32 initial_domain,
   u64 flags, enum ttm_bo_type type,
   struct dma_resv *resv,
   struct drm_gem_object **obj)
  {
-    struct amdgpu_bo *bo;
  struct amdgpu_bo_param bp;
  int r;
  @@ -73,8 +86,9 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, 
unsigned long size,

  retry:
  bp.flags = flags;
  bp.domain = initial_domain;
-    r = amdgpu_bo_create(adev, &bp, &bo);
-    if (r) {
+    *obj = amdgpu_gem_object_create_raw(adev, &bp);
+    if (IS_ERR(*obj)) {
+    r = PTR_ERR(*obj);
  if (r != -ERESTARTSYS) {
  if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) {
  flags &= ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
@@ -90,8 +104,6 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, 
unsigned long size,

  }
  return r;
  }
-    *obj = &bo->tbo.base;
-    (*obj)->funcs = &amdgpu_gem_object_funcs;
    return 0;
  }
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h

index 637bf51..a6b90d3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h
+++ b/drivers/gpu/drm/amd/

RE: [PATCH v13 1/4] RDMA/umem: Support importing dma-buf as user memory region

2020-12-08 Thread Xiong, Jianxin
> -Original Message-
> From: Leon Romanovsky 
> Sent: Monday, December 07, 2020 11:06 PM
> To: Xiong, Jianxin 
> Cc: linux-r...@vger.kernel.org; dri-devel@lists.freedesktop.org; Doug Ledford 
> ; Jason Gunthorpe ;
> Sumit Semwal ; Christian Koenig 
> ; Vetter, Daniel 
> Subject: Re: [PATCH v13 1/4] RDMA/umem: Support importing dma-buf as user 
> memory region
> 
> On Mon, Dec 07, 2020 at 02:15:50PM -0800, Jianxin Xiong wrote:
> > Dma-buf is a standard cross-driver buffer sharing mechanism that can
> > be used to support peer-to-peer access from RDMA devices.
> >
> > Device memory exported via dma-buf is associated with a file descriptor.
> > This is passed to the user space as a property associated with the
> > buffer allocation. When the buffer is registered as a memory region,
> > the file descriptor is passed to the RDMA driver along with other
> > parameters.
> >
> > Implement the common code for importing dma-buf object and mapping
> > dma-buf pages.
> >
> > Signed-off-by: Jianxin Xiong 
> > Reviewed-by: Sean Hefty 
> > Acked-by: Michael J. Ruhl 
> > Acked-by: Christian Koenig 
> > Acked-by: Daniel Vetter 
> >
> > Conflicts:
> > include/rdma/ib_umem.h
> 
> This probably leftover from rebase, am I right?
> 
> > ---
> >  drivers/infiniband/core/Makefile  |   2 +-
> >  drivers/infiniband/core/umem.c|   3 +
> >  drivers/infiniband/core/umem_dmabuf.c | 173 
> > ++
> >  include/rdma/ib_umem.h|  43 -
> >  4 files changed, 219 insertions(+), 2 deletions(-)  create mode
> > 100644 drivers/infiniband/core/umem_dmabuf.c
> >
> > diff --git a/drivers/infiniband/core/Makefile
> > b/drivers/infiniband/core/Makefile
> > index ccf2670..8ab4eea 100644
> > --- a/drivers/infiniband/core/Makefile
> > +++ b/drivers/infiniband/core/Makefile
> > @@ -40,5 +40,5 @@ ib_uverbs-y :=uverbs_main.o 
> > uverbs_cmd.o uverbs_marshall.o \
> > uverbs_std_types_srq.o \
> > uverbs_std_types_wq.o \
> > uverbs_std_types_qp.o
> > -ib_uverbs-$(CONFIG_INFINIBAND_USER_MEM) += umem.o
> > +ib_uverbs-$(CONFIG_INFINIBAND_USER_MEM) += umem.o umem_dmabuf.o
> >  ib_uverbs-$(CONFIG_INFINIBAND_ON_DEMAND_PAGING) += umem_odp.o diff
> > --git a/drivers/infiniband/core/umem.c
> > b/drivers/infiniband/core/umem.c index 7ca4112..cc131f8 100644
> > --- a/drivers/infiniband/core/umem.c
> > +++ b/drivers/infiniband/core/umem.c
> > @@ -2,6 +2,7 @@
> >   * Copyright (c) 2005 Topspin Communications.  All rights reserved.
> >   * Copyright (c) 2005 Cisco Systems.  All rights reserved.
> >   * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
> > + * Copyright (c) 2020 Intel Corporation. All rights reserved.
> >   *
> >   * This software is available to you under a choice of one of two
> >   * licenses.  You may choose to be licensed under the terms of the
> > GNU @@ -278,6 +279,8 @@ void ib_umem_release(struct ib_umem *umem)  {
> > if (!umem)
> > return;
> > +   if (umem->is_dmabuf)
> > +   return ib_umem_dmabuf_release(to_ib_umem_dmabuf(umem));
> > if (umem->is_odp)
> > return ib_umem_odp_release(to_ib_umem_odp(umem));
> >
> > diff --git a/drivers/infiniband/core/umem_dmabuf.c
> > b/drivers/infiniband/core/umem_dmabuf.c
> > new file mode 100644
> > index 000..e50b955
> > --- /dev/null
> > +++ b/drivers/infiniband/core/umem_dmabuf.c
> > @@ -0,0 +1,173 @@
> > +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
> > +/*
> > + * Copyright (c) 2020 Intel Corporation. All rights reserved.
> > + */
> > +
> > +#include 
> > +#include 
> > +#include 
> > +
> > +#include "uverbs.h"
> > +
> > +int ib_umem_dmabuf_map_pages(struct ib_umem_dmabuf *umem_dmabuf) {
> > +   struct sg_table *sgt;
> > +   struct scatterlist *sg;
> > +   struct dma_fence *fence;
> > +   unsigned long start, end, cur;
> > +   unsigned int nmap;
> > +   int i;
> > +
> > +   dma_resv_assert_held(umem_dmabuf->attach->dmabuf->resv);
> > +
> > +   if (umem_dmabuf->sgt)
> > +   return 0;
> > +
> > +   sgt = dma_buf_map_attachment(umem_dmabuf->attach, DMA_BIDIRECTIONAL);
> > +   if (IS_ERR(sgt))
> > +   return PTR_ERR(sgt);
> > +
> > +   /* modify the sg list in-place to match umem address and length */
> > +
> > +   start = ALIGN_DOWN(umem_dmabuf->umem.address, PAGE_SIZE);
> > +   end = ALIGN(umem_dmabuf->umem.address + umem_dmabuf->umem.length,
> > +   PAGE_SIZE);
> > +   cur = 0;
> > +   nmap = 0;
> 
> Better to put as part of variable initialization.

Sure, can change that way.

> 
> > +   for_each_sgtable_dma_sg(sgt, sg, i) {
> > +   if (start < cur + sg_dma_len(sg) && cur < end)
> > +   nmap++;
> > +   if (cur <= start && start < cur + sg_dma_len(sg)) {
> > +   unsigned long offset = start - cur;
> > +
> > +   umem_dmabuf->first_sg = sg;
> > +   umem_dmabuf->f

Re: [PATCH v3 0/13] drivers/video: W=1 warning fixes

2020-12-08 Thread Sam Ravnborg
On Sun, Dec 06, 2020 at 08:02:34PM +0100, Sam Ravnborg wrote:
> Following the great work of Lee Jones in other subsystems
> here is a set of patches that address all remaining W=1
> warnings in drivers/video/.
> Lee Jones already fixed all warnings in video/backlight/ so
> this is mostly fbdev related fixes.
> 
> The general approach used were:
> - Fix kernel-doc, this is often very trivial
> - Drop unused local variables
> 
> Build tested on a set of architectures with various configs.
> 
> The patches do not depend on each other and fixes for one driver
> are kept in a single patch.
> 
> v2:
>   - Updated subject of the patches to tell what was fixed (Lee)
>   - Fixed build error in one patch (kernel test robot)
>   - A few editorials updates to the changelog messages
> 
> v3:
>   - Applied patches that was acked - thanks Thomas!
>   - Updated patches after feedback from Randy and Thomas
>   - Added several new patches to cover warnings that triggers
> with other architectures than the one I used for v1 + v2
>   - Included one sh specific fix that handle a corner-case,
> let's see what the sh people say to that
>   - One fix to previous set of patches to fix an issue
> reported by Coverity (By Colin)
> 
>   Sam
> 
> Sam Ravnborg (13):
>   video: fbdev: hgafb: Fix kernel-doc warnings
>   video: fbdev: core: Fix kernel-doc warnings in fbmon + fb_notify
>   video: fbdev: omapfb: Fix set but not used warnings in hdmi*_core
>   video: fbdev: uvesafb: Fix set but not used warning
>   sh: Fix set but not used warnings with !CONFIG_MMU
>   video: fbdev: sparc drivers: fix kernel-doc warnings for blank_mode
>   video: fbdev: mmp: Fix kernel-doc warning for lcd_spi_write
>   video: fbdev: wmt_ge_rops: Fix function not declared warnings
>   video: fbdev: goldfishfb: Fix defined but not used warning
>   video: fbdev: gbefb: Fix set but not used warning
>   video: fbdev: efifb: Fix set but not used warning for screen_pitch
>   video: fbdev: controlfb: Fix set but not used warnings
>   video: fbdev: sis: Drop useless call to SiS_GetResInfo()

Thanks for the feedback!
All applied to drm-misc-next except the sh patch.

The sh patch will be resend to the sh people as it should go in via the
sh tree.

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


[PATCH v2 2/2] drm: automatic legacy gamma support

2020-12-08 Thread Tomi Valkeinen
To support legacy gamma ioctls the drivers need to set
drm_crtc_funcs.gamma_set either to a custom implementation or to
drm_atomic_helper_legacy_gamma_set. Most of the atomic drivers do the
latter.

We can simplify this by making the core handle it automatically.

Add two functions: drm_crtc_supports_legacy_gamma() which tells if the
legacy gamma table can be set, and drm_crtc_legacy_gamma_set() which
does the work by either calling the drm_crtc_funcs.gamma_set or using
GAMMA_LUT or DEGAMMA_LUT.

We can then drop drm_atomic_helper_legacy_gamma_set() and remove all its
uses.

Signed-off-by: Tomi Valkeinen 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |   1 -
 .../gpu/drm/arm/display/komeda/komeda_crtc.c  |   1 -
 drivers/gpu/drm/arm/malidp_crtc.c |   1 -
 drivers/gpu/drm/armada/armada_crtc.c  |   1 -
 drivers/gpu/drm/ast/ast_mode.c|   1 -
 .../gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c|   1 -
 drivers/gpu/drm/drm_atomic_helper.c   |  79 
 drivers/gpu/drm/drm_color_mgmt.c  | 118 --
 drivers/gpu/drm/drm_crtc_internal.h   |   6 +
 drivers/gpu/drm/drm_fb_helper.c   |  13 +-
 drivers/gpu/drm/i915/display/intel_display.c  |   1 -
 drivers/gpu/drm/ingenic/ingenic-drm-drv.c |   2 -
 drivers/gpu/drm/mediatek/mtk_drm_crtc.c   |   1 -
 drivers/gpu/drm/nouveau/dispnv50/head.c   |   2 -
 drivers/gpu/drm/omapdrm/omap_crtc.c   |   1 -
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c|   1 -
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c   |   1 -
 drivers/gpu/drm/stm/ltdc.c|   1 -
 drivers/gpu/drm/vc4/vc4_crtc.c|   1 -
 drivers/gpu/drm/vc4/vc4_txp.c |   1 -
 include/drm/drm_atomic_helper.h   |   4 -
 21 files changed, 122 insertions(+), 116 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 2855bb918535..848b06c51b0e 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -5396,7 +5396,6 @@ static void dm_disable_vblank(struct drm_crtc *crtc)
 static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = {
.reset = dm_crtc_reset_state,
.destroy = amdgpu_dm_crtc_destroy,
-   .gamma_set = drm_atomic_helper_legacy_gamma_set,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
.atomic_duplicate_state = dm_crtc_duplicate_state,
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c 
b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
index 4b485eb512e2..59172acb9738 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
@@ -550,7 +550,6 @@ static void komeda_crtc_vblank_disable(struct drm_crtc 
*crtc)
 }
 
 static const struct drm_crtc_funcs komeda_crtc_funcs = {
-   .gamma_set  = drm_atomic_helper_legacy_gamma_set,
.destroy= drm_crtc_cleanup,
.set_config = drm_atomic_helper_set_config,
.page_flip  = drm_atomic_helper_page_flip,
diff --git a/drivers/gpu/drm/arm/malidp_crtc.c 
b/drivers/gpu/drm/arm/malidp_crtc.c
index 108e7a31bd26..494075ddbef6 100644
--- a/drivers/gpu/drm/arm/malidp_crtc.c
+++ b/drivers/gpu/drm/arm/malidp_crtc.c
@@ -510,7 +510,6 @@ static void malidp_crtc_disable_vblank(struct drm_crtc 
*crtc)
 }
 
 static const struct drm_crtc_funcs malidp_crtc_funcs = {
-   .gamma_set = drm_atomic_helper_legacy_gamma_set,
.destroy = drm_crtc_cleanup,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
diff --git a/drivers/gpu/drm/armada/armada_crtc.c 
b/drivers/gpu/drm/armada/armada_crtc.c
index 3ebcf5a52c8b..b7bb90ae787f 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -820,7 +820,6 @@ static const struct drm_crtc_funcs armada_crtc_funcs = {
.cursor_set = armada_drm_crtc_cursor_set,
.cursor_move= armada_drm_crtc_cursor_move,
.destroy= armada_drm_crtc_destroy,
-   .gamma_set  = drm_atomic_helper_legacy_gamma_set,
.set_config = drm_atomic_helper_set_config,
.page_flip  = drm_atomic_helper_page_flip,
.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index 9db371f4054f..5b0ec785c516 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -903,7 +903,6 @@ static void ast_crtc_atomic_destroy_state(struct drm_crtc 
*crtc,
 
 static const struct drm_crtc_funcs ast_crtc_funcs = {
.reset = ast_crtc_reset,
-   .gamma_set = drm_atomic_helper_legacy_gamma_set,
.destroy = drm_crtc_cleanup,
.set_config = drm_atomic_helper_set_config,
.page_flip = 

[PATCH v2 1/2] drm: add legacy support for using degamma for gamma

2020-12-08 Thread Tomi Valkeinen
We currently have drm_atomic_helper_legacy_gamma_set() helper which can
be used to handle legacy gamma-set ioctl.
drm_atomic_helper_legacy_gamma_set() sets GAMMA_LUT, and clears
CTM and DEGAMMA_LUT. This works fine on HW where we have either:

degamma -> ctm -> gamma -> out

or

ctm -> gamma -> out

However, if the HW has gamma table before ctm, the atomic property
should be DEGAMMA_LUT, and thus we have:

degamma -> ctm -> out

This is fine for userspace which sets gamma table using the properties,
as the userspace can check for the existence of gamma & degamma, but the
legacy gamma-set ioctl does not work.

This patch fixes the issue by changing
drm_atomic_helper_legacy_gamma_set() so that GAMMA_LUT will be used if
it exists, and DEGAMMA_LUT will be used as a fallback.

Signed-off-by: Tomi Valkeinen 
---
 drivers/gpu/drm/drm_atomic_helper.c | 15 ---
 drivers/gpu/drm/drm_color_mgmt.c|  4 
 drivers/gpu/drm/drm_fb_helper.c |  8 ++--
 include/drm/drm_crtc.h  |  3 +++
 4 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index ba1507036f26..117b186fe646 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -3512,6 +3512,10 @@ EXPORT_SYMBOL(drm_atomic_helper_page_flip_target);
  * that support color management through the DEGAMMA_LUT/GAMMA_LUT
  * properties. See drm_crtc_enable_color_mgmt() and the containing chapter for
  * how the atomic color management and gamma tables work.
+ *
+ * This function uses the GAMMA_LUT or DEGAMMA_LUT property for the gamma 
table.
+ * GAMMA_LUT property is used if it exists, and DEGAMMA_LUT property is used as
+ * a fallback.
  */
 int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
   u16 *red, u16 *green, u16 *blue,
@@ -3526,6 +3530,9 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc 
*crtc,
int i, ret = 0;
bool replaced;
 
+   if (!crtc->has_gamma_prop && !crtc->has_degamma_prop)
+   return -ENODEV;
+
state = drm_atomic_state_alloc(crtc->dev);
if (!state)
return -ENOMEM;
@@ -3554,10 +3561,12 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc 
*crtc,
goto fail;
}
 
-   /* Reset DEGAMMA_LUT and CTM properties. */
-   replaced  = drm_property_replace_blob(&crtc_state->degamma_lut, NULL);
+   /* Set GAMMA/DEGAMMA_LUT and reset DEGAMMA/GAMMA_LUT and CTM */
+   replaced  = drm_property_replace_blob(&crtc_state->degamma_lut,
+ crtc->has_gamma_prop ? NULL : 
blob);
replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL);
-   replaced |= drm_property_replace_blob(&crtc_state->gamma_lut, blob);
+   replaced |= drm_property_replace_blob(&crtc_state->gamma_lut,
+ crtc->has_gamma_prop ? blob : 
NULL);
crtc_state->color_mgmt_changed |= replaced;
 
ret = drm_atomic_commit(state);
diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c
index 3bcabc2f6e0e..956e59d5f6a7 100644
--- a/drivers/gpu/drm/drm_color_mgmt.c
+++ b/drivers/gpu/drm/drm_color_mgmt.c
@@ -176,6 +176,8 @@ void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
   degamma_lut_size);
}
 
+   crtc->has_degamma_prop = !!degamma_lut_size;
+
if (has_ctm)
drm_object_attach_property(&crtc->base,
   config->ctm_property, 0);
@@ -187,6 +189,8 @@ void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
   config->gamma_lut_size_property,
   gamma_lut_size);
}
+
+   crtc->has_gamma_prop = !!gamma_lut_size;
 }
 EXPORT_SYMBOL(drm_crtc_enable_color_mgmt);
 
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 25edf670867c..b0906ef97617 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -1001,6 +1001,9 @@ static int setcmap_atomic(struct fb_cmap *cmap, struct 
fb_info *info)
drm_client_for_each_modeset(modeset, &fb_helper->client) {
crtc = modeset->crtc;
 
+   if (!crtc->has_gamma_prop && !crtc->has_degamma_prop)
+   continue;
+
if (!gamma_lut)
gamma_lut = setcmap_new_gamma_lut(crtc, cmap);
if (IS_ERR(gamma_lut)) {
@@ -1015,11 +1018,12 @@ static int setcmap_atomic(struct fb_cmap *cmap, struct 
fb_info *info)
goto out_state;
}
 
+   /* Set GAMMA/DEGAMMA_LUT and reset DEGAMMA/GAMMA_LUT and CTM */
replaced  = drm_property_replace_blob(&crtc_state->degamma_lut,
- NULL);
+

[PATCH v2 0/2] drm: fix and cleanup legacy gamma support

2020-12-08 Thread Tomi Valkeinen
Hi,

This is v2 of the series.

The first patch fixes legacy gamma table for HW which have a degamma lut
block before CTM block, but no gamma lut after the CTM. This will allow
us to add CTM support to omapdrm, which only has "pre-gamma" i.e.
de-gamma table.

The second one cleans up the legacy gamma support a bit by handling
legacy gamma for modern drivers in the drm core.

Changes in v2:
- Use bitfields for has_gamma_prop and has_degamma_prop
- Drop use_degamma variable
- Also fix gamma/degamma handling in setcmap_atomic, which I had missed
  earlier.
- Fix comments that were still referring to drm_atomic_helper_legacy_gamma_set
- Drop drm_atomic_helper_legacy_gamma_set use from intel_display.c which
  I had missed earlier.
- Move the declaration of the new functions to drm_crtc_internal.h

I didn't add Laurent's RBs as I felt the changes were too big to keep
the RB.

Ville has a WIP branch at

git://github.com/vsyrjala/linux.git fb_helper_c8_lut_4

which does more extensive cleanups to the gamma handling. That work is
slightly overlapping with this series, but afaics the concepts do not
conflict as such (but the code changes do conflict).

 Tomi

Tomi Valkeinen (2):
  drm: add legacy support for using degamma for gamma
  drm: automatic legacy gamma support

 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |   1 -
 .../gpu/drm/arm/display/komeda/komeda_crtc.c  |   1 -
 drivers/gpu/drm/arm/malidp_crtc.c |   1 -
 drivers/gpu/drm/armada/armada_crtc.c  |   1 -
 drivers/gpu/drm/ast/ast_mode.c|   1 -
 .../gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c|   1 -
 drivers/gpu/drm/drm_atomic_helper.c   |  70 --
 drivers/gpu/drm/drm_color_mgmt.c  | 122 --
 drivers/gpu/drm/drm_crtc_internal.h   |   6 +
 drivers/gpu/drm/drm_fb_helper.c   |  21 +--
 drivers/gpu/drm/i915/display/intel_display.c  |   1 -
 drivers/gpu/drm/ingenic/ingenic-drm-drv.c |   2 -
 drivers/gpu/drm/mediatek/mtk_drm_crtc.c   |   1 -
 drivers/gpu/drm/nouveau/dispnv50/head.c   |   2 -
 drivers/gpu/drm/omapdrm/omap_crtc.c   |   1 -
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c|   1 -
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c   |   1 -
 drivers/gpu/drm/stm/ltdc.c|   1 -
 drivers/gpu/drm/vc4/vc4_crtc.c|   1 -
 drivers/gpu/drm/vc4/vc4_txp.c |   1 -
 include/drm/drm_atomic_helper.h   |   4 -
 include/drm/drm_crtc.h|   3 +
 22 files changed, 135 insertions(+), 109 deletions(-)

-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

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


Re: [PATCH v3 3/4] tpm_tis: Disable interrupts if interrupt storm detected

2020-12-08 Thread Jarkko Sakkinen
On Mon, Dec 07, 2020 at 11:58:44AM -0800, James Bottomley wrote:
> On Mon, 2020-12-07 at 15:28 -0400, Jason Gunthorpe wrote:
> > On Sun, Dec 06, 2020 at 08:26:16PM +0100, Thomas Gleixner wrote:
> > > Just as a side note. I was looking at tpm_tis_probe_irq_single()
> > > and that function is leaking the interrupt request if any of the
> > > checks afterwards fails, except for the final interrupt probe check
> > > which does a cleanup. That means on fail before that the interrupt
> > > handler stays requested up to the point where the module is
> > > removed. If that's a shared interrupt and some other device is
> > > active on the same line, then each interrupt from that device will
> > > call into the TPM code. Something like the below is needed.
> > > 
> > > Also the X86 autoprobe mechanism is interesting:
> > > 
> > >   if (IS_ENABLED(CONFIG_X86))
> > >   for (i = 3; i <= 15; i++)
> > >   if (!tpm_tis_probe_irq_single(chip, intmask, 0,
> > > i))
> > >   return;
> > > 
> > > The third argument is 'flags' which is handed to request_irq(). So
> > > that won't ever be able to probe a shared interrupt. But if an
> > > interrupt number > 0 is handed to tpm_tis_core_init() the interrupt
> > > is requested with IRQF_SHARED. Same issue when the chip has an
> > > interrupt number in the register. It's also requested exclusive
> > > which is pretty likely to fail on ancient x86 machines.
> > 
> > It is very likely none of this works any more, it has been repeatedly
> > reworked over the years and just left behind out of fear someone
> > needs it. I've thought it should be deleted for a while now.
> > 
> > I suppose the original logic was to try and probe without SHARED
> > because a probe would need exclusive access to the interrupt to tell
> > if the TPM was actually the source, not some other device.
> > 
> > It is all very old and very out of step with current thinking, IMHO.
> > I skeptical that TPM interrupts were ever valuable enough to deserve
> > this in the first place.
> 
> For what it's worth, I agree.  Trying to probe all 15 ISA interrupts is
> last millennium thinking we should completely avoid.  If it's not
> described in ACPI then you don't get an interrupt full stop.
> 
> James

Maybe you could add this as part of your patches?

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


Re: [PATCH v3 3/4] tpm_tis: Disable interrupts if interrupt storm detected

2020-12-08 Thread Jarkko Sakkinen
On Mon, Dec 07, 2020 at 03:28:03PM -0400, Jason Gunthorpe wrote:
> On Sun, Dec 06, 2020 at 08:26:16PM +0100, Thomas Gleixner wrote:
> > Just as a side note. I was looking at tpm_tis_probe_irq_single() and
> > that function is leaking the interrupt request if any of the checks
> > afterwards fails, except for the final interrupt probe check which does
> > a cleanup. That means on fail before that the interrupt handler stays
> > requested up to the point where the module is removed. If that's a
> > shared interrupt and some other device is active on the same line, then
> > each interrupt from that device will call into the TPM code. Something
> > like the below is needed.
> > 
> > Also the X86 autoprobe mechanism is interesting:
> > 
> > if (IS_ENABLED(CONFIG_X86))
> > for (i = 3; i <= 15; i++)
> > if (!tpm_tis_probe_irq_single(chip, intmask, 0, i))
> > return;
> > 
> > The third argument is 'flags' which is handed to request_irq(). So that
> > won't ever be able to probe a shared interrupt. But if an interrupt
> > number > 0 is handed to tpm_tis_core_init() the interrupt is requested
> > with IRQF_SHARED. Same issue when the chip has an interrupt number in
> > the register. It's also requested exclusive which is pretty likely
> > to fail on ancient x86 machines.
> 
> It is very likely none of this works any more, it has been repeatedly
> reworked over the years and just left behind out of fear someone needs
> it. I've thought it should be deleted for a while now.
> 
> I suppose the original logic was to try and probe without SHARED
> because a probe would need exclusive access to the interrupt to tell
> if the TPM was actually the source, not some other device.
> 
> It is all very old and very out of step with current thinking, IMHO. I
> skeptical that TPM interrupts were ever valuable enough to deserve
> this in the first place.
> 
> Jason

+1 for removing it.

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


Re: [PATCH] drm/amdgpu: Initialise drm_gem_object_funcs for imported BOs

2020-12-08 Thread Christian König

Am 08.12.20 um 18:10 schrieb Andrey Grodzovsky:

For BOs imported from outside of amdgpu, setting of amdgpu_gem_object_funcs
was missing in amdgpu_dma_buf_create_obj. Fix by refactoring BO creation
and amdgpu_gem_object_funcs setting into single function called
from both code paths.


Can you outline why we can't use amdgpu_gem_object_create() directly?

I mean we have a bit of extra error handling in there and we need to 
grab the resv lock and set the domains after creation, but that 
shouldn't matter and I don't see why that should not work.


Thanks,
Christian.



This fixes null ptr regression casued by commit
d693def drm: Remove obsolete GEM and PRIME callbacks from struct drm_driver

Signed-off-by: Andrey Grodzovsky 
---
  drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 13 ++---
  drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 22 +-
  drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h |  5 +
  3 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
index e5919ef..da4d0ab 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -405,6 +405,7 @@ struct dma_buf *amdgpu_gem_prime_export(struct 
drm_gem_object *gobj,
return buf;
  }
  
+

  /**
   * amdgpu_dma_buf_create_obj - create BO for DMA-buf import
   *
@@ -424,7 +425,7 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, struct 
dma_buf *dma_buf)
struct amdgpu_device *adev = drm_to_adev(dev);
struct amdgpu_bo *bo;
struct amdgpu_bo_param bp;
-   int ret;
+   struct drm_gem_object *obj;
  
  	memset(&bp, 0, sizeof(bp));

bp.size = dma_buf->size;
@@ -434,21 +435,19 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, struct 
dma_buf *dma_buf)
bp.type = ttm_bo_type_sg;
bp.resv = resv;
dma_resv_lock(resv, NULL);
-   ret = amdgpu_bo_create(adev, &bp, &bo);
-   if (ret)
+   obj = amdgpu_gem_object_create_raw(adev, &bp);
+   if (IS_ERR(obj))
goto error;
  
+	bo = gem_to_amdgpu_bo(obj);

bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
if (dma_buf->ops != &amdgpu_dmabuf_ops)
bo->prime_shared_count = 1;
  
-	dma_resv_unlock(resv);

-   return &bo->tbo.base;
-
  error:
dma_resv_unlock(resv);
-   return ERR_PTR(ret);
+   return obj;
  }
  
  /**

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index c9f94fb..5f22ce6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -52,13 +52,26 @@ static void amdgpu_gem_object_free(struct drm_gem_object 
*gobj)
}
  }
  
+struct drm_gem_object *amdgpu_gem_object_create_raw(struct amdgpu_device *adev,

+   struct amdgpu_bo_param *bp)
+{
+   struct amdgpu_bo *bo;
+   int r;
+
+   r = amdgpu_bo_create(adev, bp, &bo);
+   if (r)
+   return ERR_PTR(r);
+
+   bo->tbo.base.funcs = &amdgpu_gem_object_funcs;
+   return &bo->tbo.base;
+}
+
  int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size,
 int alignment, u32 initial_domain,
 u64 flags, enum ttm_bo_type type,
 struct dma_resv *resv,
 struct drm_gem_object **obj)
  {
-   struct amdgpu_bo *bo;
struct amdgpu_bo_param bp;
int r;
  
@@ -73,8 +86,9 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size,

  retry:
bp.flags = flags;
bp.domain = initial_domain;
-   r = amdgpu_bo_create(adev, &bp, &bo);
-   if (r) {
+   *obj = amdgpu_gem_object_create_raw(adev, &bp);
+   if (IS_ERR(*obj)) {
+   r = PTR_ERR(*obj);
if (r != -ERESTARTSYS) {
if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) {
flags &= ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
@@ -90,8 +104,6 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, 
unsigned long size,
}
return r;
}
-   *obj = &bo->tbo.base;
-   (*obj)->funcs = &amdgpu_gem_object_funcs;
  
  	return 0;

  }
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h
index 637bf51..a6b90d3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h
@@ -38,12 +38,17 @@ unsigned long amdgpu_gem_timeout(uint64_t timeout_ns);
  /*
   * GEM objects.
   */
+
+struct amdgpu_bo_param;
+
  void amdgpu_gem_force_release(struct amdgpu_device *adev);
  int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size,
 int alignment, u32 initial_domain,
   

Re: [PATCH] drm/amdgpu: Initialise drm_gem_object_funcs for imported BOs

2020-12-08 Thread Alex Deucher
On Tue, Dec 8, 2020 at 12:10 PM Andrey Grodzovsky
 wrote:
>
> For BOs imported from outside of amdgpu, setting of amdgpu_gem_object_funcs
> was missing in amdgpu_dma_buf_create_obj. Fix by refactoring BO creation
> and amdgpu_gem_object_funcs setting into single function called
> from both code paths.
>
> This fixes null ptr regression casued by commit
> d693def drm: Remove obsolete GEM and PRIME callbacks from struct drm_driver
>

Fixes: d693def4fd1c ("drm: Remove obsolete GEM and PRIME callbacks
from struct drm_driver")

> Signed-off-by: Andrey Grodzovsky 
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 13 ++---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 22 +-
>  drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h |  5 +
>  3 files changed, 28 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
> index e5919ef..da4d0ab 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
> @@ -405,6 +405,7 @@ struct dma_buf *amdgpu_gem_prime_export(struct 
> drm_gem_object *gobj,
> return buf;
>  }
>
> +

Unrelated whitespace change.

>  /**
>   * amdgpu_dma_buf_create_obj - create BO for DMA-buf import
>   *
> @@ -424,7 +425,7 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, struct 
> dma_buf *dma_buf)
> struct amdgpu_device *adev = drm_to_adev(dev);
> struct amdgpu_bo *bo;
> struct amdgpu_bo_param bp;
> -   int ret;
> +   struct drm_gem_object *obj;
>
> memset(&bp, 0, sizeof(bp));
> bp.size = dma_buf->size;
> @@ -434,21 +435,19 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, 
> struct dma_buf *dma_buf)
> bp.type = ttm_bo_type_sg;
> bp.resv = resv;
> dma_resv_lock(resv, NULL);
> -   ret = amdgpu_bo_create(adev, &bp, &bo);
> -   if (ret)
> +   obj = amdgpu_gem_object_create_raw(adev, &bp);
> +   if (IS_ERR(obj))
> goto error;
>
> +   bo = gem_to_amdgpu_bo(obj);
> bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
> bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
> if (dma_buf->ops != &amdgpu_dmabuf_ops)
> bo->prime_shared_count = 1;
>
> -   dma_resv_unlock(resv);
> -   return &bo->tbo.base;
> -
>  error:
> dma_resv_unlock(resv);
> -   return ERR_PTR(ret);
> +   return obj;
>  }
>
>  /**
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> index c9f94fb..5f22ce6 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> @@ -52,13 +52,26 @@ static void amdgpu_gem_object_free(struct drm_gem_object 
> *gobj)
> }
>  }
>
> +struct drm_gem_object *amdgpu_gem_object_create_raw(struct amdgpu_device 
> *adev,
> +   struct amdgpu_bo_param 
> *bp)

Maybe call this amdgpu_gem_object_do_create() for consistency with
amdgpu_object.c and other areas of the code.

> +{
> +   struct amdgpu_bo *bo;
> +   int r;
> +
> +   r = amdgpu_bo_create(adev, bp, &bo);
> +   if (r)
> +   return ERR_PTR(r);
> +
> +   bo->tbo.base.funcs = &amdgpu_gem_object_funcs;
> +   return &bo->tbo.base;
> +}
> +
>  int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size,
>  int alignment, u32 initial_domain,
>  u64 flags, enum ttm_bo_type type,
>  struct dma_resv *resv,
>  struct drm_gem_object **obj)
>  {
> -   struct amdgpu_bo *bo;
> struct amdgpu_bo_param bp;
> int r;
>
> @@ -73,8 +86,9 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, 
> unsigned long size,
>  retry:
> bp.flags = flags;
> bp.domain = initial_domain;
> -   r = amdgpu_bo_create(adev, &bp, &bo);
> -   if (r) {
> +   *obj = amdgpu_gem_object_create_raw(adev, &bp);
> +   if (IS_ERR(*obj)) {
> +   r = PTR_ERR(*obj);
> if (r != -ERESTARTSYS) {
> if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) {
> flags &= 
> ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
> @@ -90,8 +104,6 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, 
> unsigned long size,
> }
> return r;
> }
> -   *obj = &bo->tbo.base;
> -   (*obj)->funcs = &amdgpu_gem_object_funcs;
>
> return 0;
>  }
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h
> index 637bf51..a6b90d3 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h
> @@ -38,12 +38,17 @@ unsigned long amdgpu_gem_timeout(uint64_t timeout_ns);
>  /*
>   * GEM objects.
>   */
> +
> +struct amdgpu_bo_param;
> +
>  v

[PATCH] drm/amdgpu: Initialise drm_gem_object_funcs for imported BOs

2020-12-08 Thread Andrey Grodzovsky
For BOs imported from outside of amdgpu, setting of amdgpu_gem_object_funcs
was missing in amdgpu_dma_buf_create_obj. Fix by refactoring BO creation
and amdgpu_gem_object_funcs setting into single function called
from both code paths.

This fixes null ptr regression casued by commit
d693def drm: Remove obsolete GEM and PRIME callbacks from struct drm_driver

Signed-off-by: Andrey Grodzovsky 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 13 ++---
 drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 22 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h |  5 +
 3 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
index e5919ef..da4d0ab 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -405,6 +405,7 @@ struct dma_buf *amdgpu_gem_prime_export(struct 
drm_gem_object *gobj,
return buf;
 }
 
+
 /**
  * amdgpu_dma_buf_create_obj - create BO for DMA-buf import
  *
@@ -424,7 +425,7 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, struct 
dma_buf *dma_buf)
struct amdgpu_device *adev = drm_to_adev(dev);
struct amdgpu_bo *bo;
struct amdgpu_bo_param bp;
-   int ret;
+   struct drm_gem_object *obj;
 
memset(&bp, 0, sizeof(bp));
bp.size = dma_buf->size;
@@ -434,21 +435,19 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, struct 
dma_buf *dma_buf)
bp.type = ttm_bo_type_sg;
bp.resv = resv;
dma_resv_lock(resv, NULL);
-   ret = amdgpu_bo_create(adev, &bp, &bo);
-   if (ret)
+   obj = amdgpu_gem_object_create_raw(adev, &bp);
+   if (IS_ERR(obj))
goto error;
 
+   bo = gem_to_amdgpu_bo(obj);
bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
if (dma_buf->ops != &amdgpu_dmabuf_ops)
bo->prime_shared_count = 1;
 
-   dma_resv_unlock(resv);
-   return &bo->tbo.base;
-
 error:
dma_resv_unlock(resv);
-   return ERR_PTR(ret);
+   return obj;
 }
 
 /**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index c9f94fb..5f22ce6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -52,13 +52,26 @@ static void amdgpu_gem_object_free(struct drm_gem_object 
*gobj)
}
 }
 
+struct drm_gem_object *amdgpu_gem_object_create_raw(struct amdgpu_device *adev,
+   struct amdgpu_bo_param *bp)
+{
+   struct amdgpu_bo *bo;
+   int r;
+
+   r = amdgpu_bo_create(adev, bp, &bo);
+   if (r)
+   return ERR_PTR(r);
+
+   bo->tbo.base.funcs = &amdgpu_gem_object_funcs;
+   return &bo->tbo.base;
+}
+
 int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size,
 int alignment, u32 initial_domain,
 u64 flags, enum ttm_bo_type type,
 struct dma_resv *resv,
 struct drm_gem_object **obj)
 {
-   struct amdgpu_bo *bo;
struct amdgpu_bo_param bp;
int r;
 
@@ -73,8 +86,9 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, 
unsigned long size,
 retry:
bp.flags = flags;
bp.domain = initial_domain;
-   r = amdgpu_bo_create(adev, &bp, &bo);
-   if (r) {
+   *obj = amdgpu_gem_object_create_raw(adev, &bp);
+   if (IS_ERR(*obj)) {
+   r = PTR_ERR(*obj);
if (r != -ERESTARTSYS) {
if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) {
flags &= ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
@@ -90,8 +104,6 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, 
unsigned long size,
}
return r;
}
-   *obj = &bo->tbo.base;
-   (*obj)->funcs = &amdgpu_gem_object_funcs;
 
return 0;
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h
index 637bf51..a6b90d3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h
@@ -38,12 +38,17 @@ unsigned long amdgpu_gem_timeout(uint64_t timeout_ns);
 /*
  * GEM objects.
  */
+
+struct amdgpu_bo_param;
+
 void amdgpu_gem_force_release(struct amdgpu_device *adev);
 int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size,
 int alignment, u32 initial_domain,
 u64 flags, enum ttm_bo_type type,
 struct dma_resv *resv,
 struct drm_gem_object **obj);
+struct drm_gem_object *amdgpu_gem_object_create_raw(struct amdgpu_device *adev,
+   struct amdgpu_bo_param *bp);
 
 int amdgpu_mode_dumb_c

[PATCH v5 29/29] drm/omap: dsi: allow DSI commands to be sent early

2020-12-08 Thread Tomi Valkeinen
Panel drivers can send DSI commands in panel's prepare(), which happens
before the bridge's enable() is called. The OMAP DSI driver currently
only sets up the DSI interface at bridge's enable(), so prepare() cannot
be used to send DSI commands.

This patch fixes the issue by making it possible to enable the DSI
interface any time a command is about to be sent. Disabling the
interface is be done via delayed work.

Signed-off-by: Tomi Valkeinen 
---
 drivers/gpu/drm/omapdrm/dss/dsi.c | 49 +++
 drivers/gpu/drm/omapdrm/dss/dsi.h |  3 ++
 2 files changed, 47 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c 
b/drivers/gpu/drm/omapdrm/dss/dsi.c
index 53a64bc91867..34f665aa9a59 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -3503,6 +3503,9 @@ static void dsi_enable(struct dsi_data *dsi)
 
WARN_ON(!dsi_bus_is_locked(dsi));
 
+   if (WARN_ON(dsi->iface_enabled))
+   return;
+
mutex_lock(&dsi->lock);
 
r = dsi_runtime_get(dsi);
@@ -3515,6 +3518,8 @@ static void dsi_enable(struct dsi_data *dsi)
if (r)
goto err_init_dsi;
 
+   dsi->iface_enabled = true;
+
mutex_unlock(&dsi->lock);
 
return;
@@ -3530,6 +3535,9 @@ static void dsi_disable(struct dsi_data *dsi)
 {
WARN_ON(!dsi_bus_is_locked(dsi));
 
+   if (WARN_ON(!dsi->iface_enabled))
+   return;
+
mutex_lock(&dsi->lock);
 
dsi_sync_vc(dsi, 0);
@@ -3541,6 +3549,8 @@ static void dsi_disable(struct dsi_data *dsi)
 
dsi_runtime_put(dsi);
 
+   dsi->iface_enabled = false;
+
mutex_unlock(&dsi->lock);
 }
 
@@ -4229,10 +4239,12 @@ static ssize_t omap_dsi_host_transfer(struct 
mipi_dsi_host *host,
 
dsi_bus_lock(dsi);
 
-   if (dsi->video_enabled)
-   r = _omap_dsi_host_transfer(dsi, vc, msg);
-   else
-   r = -EIO;
+   if (!dsi->iface_enabled) {
+   dsi_enable(dsi);
+   schedule_delayed_work(&dsi->dsi_disable_work, 
msecs_to_jiffies(2000));
+   }
+
+   r = _omap_dsi_host_transfer(dsi, vc, msg);
 
dsi_bus_unlock(dsi);
 
@@ -4397,6 +4409,14 @@ static int omap_dsi_host_detach(struct mipi_dsi_host 
*host,
if (WARN_ON(dsi->dsidev != client))
return -EINVAL;
 
+   cancel_delayed_work_sync(&dsi->dsi_disable_work);
+
+   if (dsi->iface_enabled) {
+   dsi_bus_lock(dsi);
+   dsi_disable(dsi);
+   dsi_bus_unlock(dsi);
+   }
+
omap_dsi_unregister_te_irq(dsi);
dsi->dsidev = NULL;
return 0;
@@ -4632,9 +4652,12 @@ static void dsi_bridge_enable(struct drm_bridge *bridge)
struct dsi_data *dsi = drm_bridge_to_dsi(bridge);
struct omap_dss_device *dssdev = &dsi->output;
 
+   cancel_delayed_work_sync(&dsi->dsi_disable_work);
+
dsi_bus_lock(dsi);
 
-   dsi_enable(dsi);
+   if (!dsi->iface_enabled)
+   dsi_enable(dsi);
 
dsi_enable_video_output(dssdev, VC_VIDEO);
 
@@ -4648,6 +4671,8 @@ static void dsi_bridge_disable(struct drm_bridge *bridge)
struct dsi_data *dsi = drm_bridge_to_dsi(bridge);
struct omap_dss_device *dssdev = &dsi->output;
 
+   cancel_delayed_work_sync(&dsi->dsi_disable_work);
+
dsi_bus_lock(dsi);
 
dsi->video_enabled = false;
@@ -4840,6 +4865,18 @@ static const struct soc_device_attribute 
dsi_soc_devices[] = {
{ /* sentinel */ }
 };
 
+static void omap_dsi_disable_work_callback(struct work_struct *work)
+{
+   struct dsi_data *dsi = container_of(work, struct dsi_data, 
dsi_disable_work.work);
+
+   dsi_bus_lock(dsi);
+
+   if (dsi->iface_enabled && !dsi->video_enabled)
+   dsi_disable(dsi);
+
+   dsi_bus_unlock(dsi);
+}
+
 static int dsi_probe(struct platform_device *pdev)
 {
const struct soc_device_attribute *soc;
@@ -4873,6 +4910,8 @@ static int dsi_probe(struct platform_device *pdev)
INIT_DEFERRABLE_WORK(&dsi->framedone_timeout_work,
 dsi_framedone_timeout_work_callback);
 
+   INIT_DEFERRABLE_WORK(&dsi->dsi_disable_work, 
omap_dsi_disable_work_callback);
+
 #ifdef DSI_CATCH_MISSING_TE
timer_setup(&dsi->te_timer, dsi_te_timeout, 0);
 #endif
diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.h 
b/drivers/gpu/drm/omapdrm/dss/dsi.h
index de9411067ba2..601707c0ecc4 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.h
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.h
@@ -394,6 +394,7 @@ struct dsi_data {
atomic_t do_ext_te_update;
 
bool te_enabled;
+   bool iface_enabled;
bool video_enabled;
 
struct delayed_work framedone_timeout_work;
@@ -443,6 +444,8 @@ struct dsi_data {
 
struct omap_dss_device output;
struct drm_bridge bridge;
+
+   struct delayed_work dsi_disable_work;
 };
 
 struct dsi_packet_sent_handler_data {
-- 
Texas Instruments Finland Oy,

[PATCH v5 27/29] drm/omap: dsi: remove ulps support

2020-12-08 Thread Tomi Valkeinen
ULPS doesn't work, and I have been unable to get it to work. As ULPS is
a minor power-saving feature which requires substantial amount of
non-trivial code, and we have trouble just getting and
keeping DSI working at all, remove ULPS support.

When the DSI driver works reliably for command and video mode displays,
someone interested can add it back.

Signed-off-by: Tomi Valkeinen 
Reviewed-by: Laurent Pinchart 
---
 drivers/gpu/drm/omapdrm/dss/dsi.c | 297 +-
 drivers/gpu/drm/omapdrm/dss/dsi.h |   4 -
 2 files changed, 8 insertions(+), 293 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c 
b/drivers/gpu/drm/omapdrm/dss/dsi.c
index cc8b169b2223..b2aa07a09dcd 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -53,8 +53,6 @@
 #define REG_FLD_MOD(dsi, idx, val, start, end) \
dsi_write_reg(dsi, idx, FLD_MOD(dsi_read_reg(dsi, idx), val, start, 
end))
 
-static void dsi_set_ulps_auto(struct dsi_data *dsi, bool enable);
-
 static int dsi_init_dispc(struct dsi_data *dsi);
 static void dsi_uninit_dispc(struct dsi_data *dsi);
 
@@ -688,44 +686,6 @@ static int dsi_unregister_isr_vc(struct dsi_data *dsi, int 
vc,
return r;
 }
 
-static int dsi_register_isr_cio(struct dsi_data *dsi, omap_dsi_isr_t isr,
-   void *arg, u32 mask)
-{
-   unsigned long flags;
-   int r;
-
-   spin_lock_irqsave(&dsi->irq_lock, flags);
-
-   r = _dsi_register_isr(isr, arg, mask, dsi->isr_tables.isr_table_cio,
-   ARRAY_SIZE(dsi->isr_tables.isr_table_cio));
-
-   if (r == 0)
-   _omap_dsi_set_irqs_cio(dsi);
-
-   spin_unlock_irqrestore(&dsi->irq_lock, flags);
-
-   return r;
-}
-
-static int dsi_unregister_isr_cio(struct dsi_data *dsi, omap_dsi_isr_t isr,
- void *arg, u32 mask)
-{
-   unsigned long flags;
-   int r;
-
-   spin_lock_irqsave(&dsi->irq_lock, flags);
-
-   r = _dsi_unregister_isr(isr, arg, mask, dsi->isr_tables.isr_table_cio,
-   ARRAY_SIZE(dsi->isr_tables.isr_table_cio));
-
-   if (r == 0)
-   _omap_dsi_set_irqs_cio(dsi);
-
-   spin_unlock_irqrestore(&dsi->irq_lock, flags);
-
-   return r;
-}
-
 static u32 dsi_get_errors(struct dsi_data *dsi)
 {
unsigned long flags;
@@ -1450,56 +1410,6 @@ static void dsi_cio_timings(struct dsi_data *dsi)
dsi_write_reg(dsi, DSI_DSIPHY_CFG2, r);
 }
 
-/* lane masks have lane 0 at lsb. mask_p for positive lines, n for negative */
-static void dsi_cio_enable_lane_override(struct dsi_data *dsi,
-unsigned int mask_p,
-unsigned int mask_n)
-{
-   int i;
-   u32 l;
-   u8 lptxscp_start = dsi->num_lanes_supported == 3 ? 22 : 26;
-
-   l = 0;
-
-   for (i = 0; i < dsi->num_lanes_supported; ++i) {
-   unsigned int p = dsi->lanes[i].polarity;
-
-   if (mask_p & (1 << i))
-   l |= 1 << (i * 2 + (p ? 0 : 1));
-
-   if (mask_n & (1 << i))
-   l |= 1 << (i * 2 + (p ? 1 : 0));
-   }
-
-   /*
-* Bits in REGLPTXSCPDAT4TO0DXDY:
-* 17: DY0 18: DX0
-* 19: DY1 20: DX1
-* 21: DY2 22: DX2
-* 23: DY3 24: DX3
-* 25: DY4 26: DX4
-*/
-
-   /* Set the lane override configuration */
-
-   /* REGLPTXSCPDAT4TO0DXDY */
-   REG_FLD_MOD(dsi, DSI_DSIPHY_CFG10, l, lptxscp_start, 17);
-
-   /* Enable lane override */
-
-   /* ENLPTXSCPDAT */
-   REG_FLD_MOD(dsi, DSI_DSIPHY_CFG10, 1, 27, 27);
-}
-
-static void dsi_cio_disable_lane_override(struct dsi_data *dsi)
-{
-   /* Disable lane override */
-   REG_FLD_MOD(dsi, DSI_DSIPHY_CFG10, 0, 27, 27); /* ENLPTXSCPDAT */
-   /* Reset the lane override configuration */
-   /* REGLPTXSCPDAT4TO0DXDY */
-   REG_FLD_MOD(dsi, DSI_DSIPHY_CFG10, 0, 22, 17);
-}
-
 static int dsi_cio_wait_tx_clk_esc_reset(struct dsi_data *dsi)
 {
int t, i;
@@ -1674,32 +1584,6 @@ static int dsi_cio_init(struct dsi_data *dsi)
l = FLD_MOD(l, 0x1fff, 12, 0);  /* STOP_STATE_COUNTER_IO */
dsi_write_reg(dsi, DSI_TIMING1, l);
 
-   if (dsi->ulps_enabled) {
-   unsigned int mask_p;
-   int i;
-
-   DSSDBG("manual ulps exit\n");
-
-   /* ULPS is exited by Mark-1 state for 1ms, followed by
-* stop state. DSS HW cannot do this via the normal
-* ULPS exit sequence, as after reset the DSS HW thinks
-* that we are not in ULPS mode, and refuses to send the
-* sequence. So we need to send the ULPS exit sequence
-* manually by setting positive lines high and negative lines
-* low for 1ms.
-*/
-
-   mask_p = 0;
-
-   for (i = 0; i < dsi->num_lanes_supported; ++i) {
-   

[PATCH v5 28/29] drm/omap: dsi: fix DCS_CMD_ENABLE

2020-12-08 Thread Tomi Valkeinen
We only need to set VC_CTRL:DCS_CMD_ENABLE for command mode panels when
the HW has DSI_QUIRK_DCS_CMD_CONFIG_VC quirk. The old code did this
right by accident, but now we set DCS_CMD_ENABLE for video mode panels
too.

Fix this by skipping the set for video mode.

Signed-off-by: Tomi Valkeinen 
Reviewed-by: Laurent Pinchart 
---
 drivers/gpu/drm/omapdrm/dss/dsi.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c 
b/drivers/gpu/drm/omapdrm/dss/dsi.c
index b2aa07a09dcd..53a64bc91867 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -3406,7 +3406,8 @@ static void dsi_setup_dsi_vcs(struct dsi_data *dsi)
REG_FLD_MOD(dsi, DSI_VC_CTRL(VC_VIDEO), 1, 1, 1); /* SOURCE_VP */
dsi->vc[VC_VIDEO].source = DSI_VC_SOURCE_VP;
 
-   if (dsi->data->quirks & DSI_QUIRK_DCS_CMD_CONFIG_VC)
+   if ((dsi->data->quirks & DSI_QUIRK_DCS_CMD_CONFIG_VC) &&
+   !(dsi->dsidev->mode_flags & MIPI_DSI_MODE_VIDEO))
REG_FLD_MOD(dsi, DSI_VC_CTRL(VC_VIDEO), 1, 30, 30); /* 
DCS_CMD_ENABLE */
 
dsi_vc_enable(dsi, VC_CMD, 1);
-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

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


[PATCH v5 22/29] drm/omap: dsi: display_disable cleanup

2020-12-08 Thread Tomi Valkeinen
We can drop dsi_display_disable() which just calls
_dsi_display_disable(), and rename _dsi_display_disable() to
dsi_display_disable().

The WARN_ON(!dsi_bus_is_locked(dsi)) in dsi_display_disable is extra and
can be dropped, as _dsi_display_disable() has the same WARN_ON().

Signed-off-by: Tomi Valkeinen 
Reviewed-by: Laurent Pinchart 
---
 drivers/gpu/drm/omapdrm/dss/dsi.c | 19 +++
 1 file changed, 3 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c 
b/drivers/gpu/drm/omapdrm/dss/dsi.c
index 961b991f6498..d83346812810 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -63,8 +63,6 @@ static int dsi_vc_send_null(struct dsi_data *dsi, int vc, int 
channel);
 static ssize_t _omap_dsi_host_transfer(struct dsi_data *dsi, int vc,
   const struct mipi_dsi_msg *msg);
 
-static void dsi_display_disable(struct omap_dss_device *dssdev);
-
 #ifdef DSI_PERF_MEASURE
 static bool dsi_perf;
 module_param(dsi_perf, bool, 0644);
@@ -3772,7 +3770,7 @@ static void dsi_display_enable(struct dsi_data *dsi)
DSSDBG("dsi_display_ulps_enable FAILED\n");
 }
 
-static void _dsi_display_disable(struct dsi_data *dsi,
+static void dsi_display_disable(struct dsi_data *dsi,
bool disconnect_lanes, bool enter_ulps)
 {
WARN_ON(!dsi_bus_is_locked(dsi));
@@ -3791,17 +3789,6 @@ static void _dsi_display_disable(struct dsi_data *dsi,
mutex_unlock(&dsi->lock);
 }
 
-static void dsi_display_disable(struct omap_dss_device *dssdev)
-{
-   struct dsi_data *dsi = to_dsi_data(dssdev);
-
-   WARN_ON(!dsi_bus_is_locked(dsi));
-
-   DSSDBG("dsi_display_disable\n");
-
-   _dsi_display_disable(dsi, true, false);
-}
-
 static int dsi_enable_te(struct dsi_data *dsi, bool enable)
 {
dsi->te_enabled = enable;
@@ -3825,7 +3812,7 @@ static void omap_dsi_ulps_work_callback(struct 
work_struct *work)
 
dsi_enable_te(dsi, false);
 
-   _dsi_display_disable(dsi, false, true);
+   dsi_display_disable(dsi, false, true);
 
dsi_bus_unlock(dsi);
 }
@@ -4959,7 +4946,7 @@ static void dsi_bridge_disable(struct drm_bridge *bridge)
 
dsi_disable_video_output(dssdev, VC_VIDEO);
 
-   dsi_display_disable(dssdev);
+   dsi_display_disable(dsi, true, false);
 
dsi_bus_unlock(dsi);
 }
-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

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


[PATCH v5 25/29] drm/omap: dsi: split video mode enable/disable into separate func

2020-12-08 Thread Tomi Valkeinen
Clean up the code by separating video-mode enable/disable code into
functions of their own.

Signed-off-by: Tomi Valkeinen 
Reviewed-by: Laurent Pinchart 
---
 drivers/gpu/drm/omapdrm/dss/dsi.c | 101 +-
 1 file changed, 57 insertions(+), 44 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c 
b/drivers/gpu/drm/omapdrm/dss/dsi.c
index c32884f167b8..71de6119d2de 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -3207,12 +3207,61 @@ static int dsi_configure_pins(struct dsi_data *dsi,
return 0;
 }
 
-static void dsi_enable_video_output(struct omap_dss_device *dssdev, int vc)
+static int dsi_enable_video_mode(struct dsi_data *dsi, int vc)
 {
-   struct dsi_data *dsi = to_dsi_data(dssdev);
int bpp = mipi_dsi_pixel_format_to_bpp(dsi->pix_fmt);
u8 data_type;
u16 word_count;
+
+   switch (dsi->pix_fmt) {
+   case MIPI_DSI_FMT_RGB888:
+   data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24;
+   break;
+   case MIPI_DSI_FMT_RGB666:
+   data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
+   break;
+   case MIPI_DSI_FMT_RGB666_PACKED:
+   data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18;
+   break;
+   case MIPI_DSI_FMT_RGB565:
+   data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16;
+   break;
+   default:
+   return -EINVAL;
+   }
+
+   dsi_if_enable(dsi, false);
+   dsi_vc_enable(dsi, vc, false);
+
+   /* MODE, 1 = video mode */
+   REG_FLD_MOD(dsi, DSI_VC_CTRL(vc), 1, 4, 4);
+
+   word_count = DIV_ROUND_UP(dsi->vm.hactive * bpp, 8);
+
+   dsi_vc_write_long_header(dsi, vc, dsi->dsidev->channel, data_type,
+   word_count, 0);
+
+   dsi_vc_enable(dsi, vc, true);
+   dsi_if_enable(dsi, true);
+
+   return 0;
+}
+
+static void dsi_disable_video_mode(struct dsi_data *dsi, int vc)
+{
+   dsi_if_enable(dsi, false);
+   dsi_vc_enable(dsi, vc, false);
+
+   /* MODE, 0 = command mode */
+   REG_FLD_MOD(dsi, DSI_VC_CTRL(vc), 0, 4, 4);
+
+   dsi_vc_enable(dsi, vc, true);
+   dsi_if_enable(dsi, true);
+}
+
+static void dsi_enable_video_output(struct omap_dss_device *dssdev, int vc)
+{
+   struct dsi_data *dsi = to_dsi_data(dssdev);
int r;
 
r = dsi_init_dispc(dsi);
@@ -3222,37 +3271,9 @@ static void dsi_enable_video_output(struct 
omap_dss_device *dssdev, int vc)
}
 
if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
-   switch (dsi->pix_fmt) {
-   case MIPI_DSI_FMT_RGB888:
-   data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24;
-   break;
-   case MIPI_DSI_FMT_RGB666:
-   data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
-   break;
-   case MIPI_DSI_FMT_RGB666_PACKED:
-   data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18;
-   break;
-   case MIPI_DSI_FMT_RGB565:
-   data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16;
-   break;
-   default:
-   r = -EINVAL;
-   goto err_pix_fmt;
-   }
-
-   dsi_if_enable(dsi, false);
-   dsi_vc_enable(dsi, vc, false);
-
-   /* MODE, 1 = video mode */
-   REG_FLD_MOD(dsi, DSI_VC_CTRL(vc), 1, 4, 4);
-
-   word_count = DIV_ROUND_UP(dsi->vm.hactive * bpp, 8);
-
-   dsi_vc_write_long_header(dsi, vc, dsi->dsidev->channel, 
data_type,
-   word_count, 0);
-
-   dsi_vc_enable(dsi, vc, true);
-   dsi_if_enable(dsi, true);
+   r = dsi_enable_video_mode(dsi, vc);
+   if (r)
+   goto err_video_mode;
}
 
r = dss_mgr_enable(&dsi->output);
@@ -3266,7 +3287,7 @@ static void dsi_enable_video_output(struct 
omap_dss_device *dssdev, int vc)
dsi_if_enable(dsi, false);
dsi_vc_enable(dsi, vc, false);
}
-err_pix_fmt:
+err_video_mode:
dsi_uninit_dispc(dsi);
dev_err(dsi->dev, "failed to enable DSI encoder!\n");
return;
@@ -3276,16 +3297,8 @@ static void dsi_disable_video_output(struct 
omap_dss_device *dssdev, int vc)
 {
struct dsi_data *dsi = to_dsi_data(dssdev);
 
-   if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
-   dsi_if_enable(dsi, false);
-   dsi_vc_enable(dsi, vc, false);
-
-   /* MODE, 0 = command mode */
-   REG_FLD_MOD(dsi, DSI_VC_CTRL(vc), 0, 4, 4);
-
-   dsi_vc_enable(dsi, vc, true);
-   dsi_if_enable(dsi, true);
-   }
+   if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE)
+   dsi_disable_video_mode(dsi, vc);
 
dss_mgr_disable(&dsi->output);
 
-- 
Texas Instruments Finland Oy, Porkkalanka

[PATCH v5 17/29] drm/panel: panel-dsi-cm: add panel database to driver

2020-12-08 Thread Tomi Valkeinen
Add a panel database to the driver instead of reading propertes from DT
data. This is similar to panel-simple, and I believe it's more future
safe way to handle the panels.

Signed-off-by: Tomi Valkeinen 
Reviewed-by: Sam Ravnborg 
---
 drivers/gpu/drm/panel/panel-dsi-cm.c | 107 +--
 1 file changed, 69 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-dsi-cm.c 
b/drivers/gpu/drm/panel/panel-dsi-cm.c
index fa564aad7f25..3fb5b2856283 100644
--- a/drivers/gpu/drm/panel/panel-dsi-cm.c
+++ b/drivers/gpu/drm/panel/panel-dsi-cm.c
@@ -21,10 +21,7 @@
 #include 
 #include 
 
-#include 
 #include 
-#include 
-#include 
 
 #define DCS_GET_ID10xda
 #define DCS_GET_ID20xdb
@@ -32,6 +29,18 @@
 
 #define DCS_REGULATOR_SUPPLY_NUM 2
 
+static const struct of_device_id dsicm_of_match[];
+
+struct dsic_panel_data {
+   u32 xres;
+   u32 yres;
+   u32 refresh;
+   u32 width_mm;
+   u32 height_mm;
+   u32 max_hs_rate;
+   u32 max_lp_rate;
+};
+
 struct panel_drv_data {
struct mipi_dsi_device *dsi;
struct drm_panel panel;
@@ -47,16 +56,14 @@ struct panel_drv_data {
 */
unsigned long   hw_guard_wait;  /* max guard time in jiffies */
 
-   /* panel HW configuration from DT or platform data */
+   const struct dsic_panel_data *panel_data;
+
struct gpio_desc *reset_gpio;
 
struct regulator_bulk_data supplies[DCS_REGULATOR_SUPPLY_NUM];
 
bool use_dsi_backlight;
 
-   int width_mm;
-   int height_mm;
-
/* runtime variables */
bool enabled;
 
@@ -450,11 +457,8 @@ static int dsicm_get_modes(struct drm_panel *panel,
return -ENOMEM;
}
 
-   drm_mode_set_name(mode);
-   mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
-
-   connector->display_info.width_mm = ddata->width_mm;
-   connector->display_info.height_mm = ddata->height_mm;
+   connector->display_info.width_mm = ddata->panel_data->width_mm;
+   connector->display_info.height_mm = ddata->panel_data->height_mm;
 
drm_mode_probed_add(connector, mode);
 
@@ -471,15 +475,10 @@ static const struct drm_panel_funcs dsicm_panel_funcs = {
 
 static int dsicm_probe_of(struct mipi_dsi_device *dsi)
 {
-   struct device_node *node = dsi->dev.of_node;
struct backlight_device *backlight;
struct panel_drv_data *ddata = mipi_dsi_get_drvdata(dsi);
-   struct display_timing timing;
-   struct videomode vm = {
-   .hactive = 864,
-   .vactive = 480,
-   };
int err;
+   struct drm_display_mode *mode = &ddata->mode;
 
ddata->reset_gpio = devm_gpiod_get(&dsi->dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(ddata->reset_gpio)) {
@@ -488,23 +487,16 @@ static int dsicm_probe_of(struct mipi_dsi_device *dsi)
return err;
}
 
-   err = of_get_display_timing(node, "panel-timing", &timing);
-   if (!err) {
-   videomode_from_timing(&timing, &vm);
-   } else {
-   dev_warn(&dsi->dev,
-"failed to get video timing, using defaults\n");
-   }
-
-   if (!vm.pixelclock)
-   vm.pixelclock = vm.hactive * vm.vactive * 60;
-   drm_display_mode_from_videomode(&vm, &ddata->mode);
-
-   ddata->width_mm = 0;
-   of_property_read_u32(node, "width-mm", &ddata->width_mm);
-
-   ddata->height_mm = 0;
-   of_property_read_u32(node, "height-mm", &ddata->height_mm);
+   mode->hdisplay = mode->hsync_start = mode->hsync_end = mode->htotal =
+   ddata->panel_data->xres;
+   mode->vdisplay = mode->vsync_start = mode->vsync_end = mode->vtotal =
+   ddata->panel_data->yres;
+   mode->clock = ddata->panel_data->xres * ddata->panel_data->yres *
+   ddata->panel_data->refresh / 1000;
+   mode->width_mm = ddata->panel_data->width_mm;
+   mode->height_mm = ddata->panel_data->height_mm;
+   mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+   drm_mode_set_name(mode);
 
ddata->supplies[0].supply = "vpnl";
ddata->supplies[1].supply = "vddi";
@@ -531,6 +523,7 @@ static int dsicm_probe(struct mipi_dsi_device *dsi)
struct panel_drv_data *ddata;
struct backlight_device *bldev = NULL;
struct device *dev = &dsi->dev;
+   const struct of_device_id *id;
int r;
 
dev_dbg(dev, "probe\n");
@@ -542,6 +535,12 @@ static int dsicm_probe(struct mipi_dsi_device *dsi)
mipi_dsi_set_drvdata(dsi, ddata);
ddata->dsi = dsi;
 
+   id = of_match_node(dsicm_of_match, dev->of_node);
+   if (!id)
+   return -ENODEV;
+
+   ddata->panel_data = id->data;
+
r = dsicm_probe_of(dsi);
if (r)
return r;
@@ -578,8 +577,8 @@ static int dsicm_probe(struct mipi_dsi_device *dsi)
dsi->format = MIPI_DS

[PATCH v5 18/29] drm/panel: panel-dsi-cm: drop unneeded includes

2020-12-08 Thread Tomi Valkeinen
Drop unneeded includes.

Signed-off-by: Tomi Valkeinen 
Reviewed-by: Sam Ravnborg 
Reviewed-by: Laurent Pinchart 
---
 drivers/gpu/drm/panel/panel-dsi-cm.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-dsi-cm.c 
b/drivers/gpu/drm/panel/panel-dsi-cm.c
index 3fb5b2856283..3fe73c4bef6e 100644
--- a/drivers/gpu/drm/panel/panel-dsi-cm.c
+++ b/drivers/gpu/drm/panel/panel-dsi-cm.c
@@ -11,9 +11,6 @@
 #include 
 #include 
 #include 
-#include 
-#include 
-#include 
 #include 
 
 #include 
-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

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


[PATCH v5 20/29] drm/omap: dsi: move enable/disable to bridge enable/disable

2020-12-08 Thread Tomi Valkeinen
Clean up the code by inlining dsi_enable_video_outputs and
dsi_disable_video_outputs functions.

Signed-off-by: Tomi Valkeinen 
Reviewed-by: Laurent Pinchart 
---
 drivers/gpu/drm/omapdrm/dss/dsi.c | 55 +--
 1 file changed, 22 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c 
b/drivers/gpu/drm/omapdrm/dss/dsi.c
index da3ff9e236bd..44b8e42b52ec 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -3336,20 +3336,6 @@ static void dsi_disable_video_output(struct 
omap_dss_device *dssdev, int vc)
dsi_display_uninit_dispc(dsi);
 }
 
-static void dsi_disable_video_outputs(struct omap_dss_device *dssdev)
-{
-   struct dsi_data *dsi = to_dsi_data(dssdev);
-
-   dsi_bus_lock(dsi);
-   dsi->video_enabled = false;
-
-   dsi_disable_video_output(dssdev, VC_VIDEO);
-
-   dsi_display_disable(dssdev);
-
-   dsi_bus_unlock(dsi);
-}
-
 static void dsi_update_screen_dispc(struct dsi_data *dsi)
 {
unsigned int bytespp;
@@ -3796,23 +3782,6 @@ static void dsi_display_enable(struct omap_dss_device 
*dssdev)
_dsi_display_enable(dsi);
 }
 
-static void dsi_enable_video_outputs(struct omap_dss_device *dssdev)
-{
-   struct dsi_data *dsi = to_dsi_data(dssdev);
-
-   dsi_bus_lock(dsi);
-
-   dsi_display_enable(dssdev);
-
-   dsi_enable_video_output(dssdev, VC_VIDEO);
-
-   dsi->video_enabled = true;
-
-   dsi_set_ulps_auto(dsi, true);
-
-   dsi_bus_unlock(dsi);
-}
-
 static void _dsi_display_disable(struct dsi_data *dsi,
bool disconnect_lanes, bool enter_ulps)
 {
@@ -4974,15 +4943,35 @@ static void dsi_bridge_mode_set(struct drm_bridge 
*bridge,
 static void dsi_bridge_enable(struct drm_bridge *bridge)
 {
struct dsi_data *dsi = drm_bridge_to_dsi(bridge);
+   struct omap_dss_device *dssdev = &dsi->output;
 
-   dsi_enable_video_outputs(&dsi->output);
+   dsi_bus_lock(dsi);
+
+   dsi_display_enable(dssdev);
+
+   dsi_enable_video_output(dssdev, VC_VIDEO);
+
+   dsi->video_enabled = true;
+
+   dsi_set_ulps_auto(dsi, true);
+
+   dsi_bus_unlock(dsi);
 }
 
 static void dsi_bridge_disable(struct drm_bridge *bridge)
 {
struct dsi_data *dsi = drm_bridge_to_dsi(bridge);
+   struct omap_dss_device *dssdev = &dsi->output;
+
+   dsi_bus_lock(dsi);
+
+   dsi->video_enabled = false;
+
+   dsi_disable_video_output(dssdev, VC_VIDEO);
 
-   dsi_disable_video_outputs(&dsi->output);
+   dsi_display_disable(dssdev);
+
+   dsi_bus_unlock(dsi);
 }
 
 static const struct drm_bridge_funcs dsi_bridge_funcs = {
-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

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


[PATCH v5 15/29] drm/omap: dsi: use separate VCs for cmd and video

2020-12-08 Thread Tomi Valkeinen
For command mode panels we can use a single VC for sending command and
video data, even if we have to change the data source for that VC when
going from command to video or vice versa.

However, with video mode panels we want to keep the pixel data VC
enabled, and use another VC for command data, and the commands will get
interleaved into the pixel data.

This patch makes the driver use VC0 for commands and VC1 for video.

Signed-off-by: Tomi Valkeinen 
Reviewed-by: Laurent Pinchart 
---
 drivers/gpu/drm/omapdrm/dss/dsi.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c 
b/drivers/gpu/drm/omapdrm/dss/dsi.c
index 9d210a020916..0795efdd8902 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -452,7 +452,9 @@ static bool dsi_perf;
 module_param(dsi_perf, bool, 0644);
 #endif
 
-#define VC_DEFAULT 0
+/* Note: for some reason video mode seems to work only if VC_VIDEO is 0 */
+#define VC_VIDEO   0
+#define VC_CMD 1
 
 #define drm_bridge_to_dsi(bridge) \
container_of(bridge, struct dsi_data, bridge)
@@ -3723,7 +3725,7 @@ static void dsi_disable_video_outputs(struct 
omap_dss_device *dssdev)
dsi_bus_lock(dsi);
dsi->video_enabled = false;
 
-   dsi_disable_video_output(dssdev, VC_DEFAULT);
+   dsi_disable_video_output(dssdev, VC_VIDEO);
 
dsi_display_disable(dssdev);
 
@@ -3951,7 +3953,7 @@ static int dsi_update_channel(struct omap_dss_device 
*dssdev, int vc)
 
 static int dsi_update_all(struct omap_dss_device *dssdev)
 {
-   return dsi_update_channel(dssdev, VC_DEFAULT);
+   return dsi_update_channel(dssdev, VC_VIDEO);
 }
 
 /* Display funcs */
@@ -4184,7 +4186,7 @@ static void dsi_enable_video_outputs(struct 
omap_dss_device *dssdev)
 
dsi_display_enable(dssdev);
 
-   dsi_enable_video_output(dssdev, VC_DEFAULT);
+   dsi_enable_video_output(dssdev, VC_VIDEO);
 
dsi->video_enabled = true;
 
@@ -4941,7 +4943,7 @@ static ssize_t omap_dsi_host_transfer(struct 
mipi_dsi_host *host,
 {
struct dsi_data *dsi = host_to_omap(host);
int r;
-   int vc = VC_DEFAULT;
+   int vc = VC_CMD;
 
dsi_bus_lock(dsi);
 
-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

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


[PATCH v5 26/29] drm/omap: dsi: fix and cleanup ddr_clk_always_on

2020-12-08 Thread Tomi Valkeinen
The driver ignores MIPI_DSI_CLOCK_NON_CONTINUOUS, and always uses
non-continuous clock.

Fix this by using MIPI_DSI_CLOCK_NON_CONTINUOUS and at the same time,
drop ddr_clk_always_on field which seems pretty useless.

Signed-off-by: Tomi Valkeinen 
Reviewed-by: Laurent Pinchart 
---
 drivers/gpu/drm/omapdrm/dss/dsi.c | 12 +---
 drivers/gpu/drm/omapdrm/dss/dsi.h |  2 --
 2 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c 
b/drivers/gpu/drm/omapdrm/dss/dsi.c
index 71de6119d2de..cc8b169b2223 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -1734,11 +1734,10 @@ static int dsi_cio_init(struct dsi_data *dsi)
 
dsi_cio_timings(dsi);
 
-   if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
-   /* DDR_CLK_ALWAYS_ON */
-   REG_FLD_MOD(dsi, DSI_CLK_CTRL,
-   dsi->vm_timings.ddr_clk_always_on, 13, 13);
-   }
+   /* DDR_CLK_ALWAYS_ON */
+   REG_FLD_MOD(dsi, DSI_CLK_CTRL,
+   !(dsi->dsidev->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS),
+   13, 13);
 
dsi->ulps_enabled = false;
 
@@ -3646,7 +3645,7 @@ static void dsi_setup_dsi_vcs(struct dsi_data *dsi)
dsi_force_tx_stop_mode_io(dsi);
 
/* start the DDR clock by sending a NULL packet */
-   if (dsi->vm_timings.ddr_clk_always_on)
+   if (!(dsi->dsidev->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS))
dsi_vc_send_null(dsi, VC_CMD, dsi->dsidev->channel);
 }
 
@@ -4155,7 +4154,6 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx 
*ctx)
dsi_vm->hfp_blanking_mode = 1;
dsi_vm->hbp_blanking_mode = 1;
 
-   dsi_vm->ddr_clk_always_on = cfg->ddr_clk_always_on;
dsi_vm->window_sync = 4;
 
/* setup DISPC videomode */
diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.h 
b/drivers/gpu/drm/omapdrm/dss/dsi.h
index 478fc10bd18d..476069fda082 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.h
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.h
@@ -212,7 +212,6 @@ struct omap_dss_dsi_videomode_timings {
 
enum omap_dss_dsi_trans_mode trans_mode;
 
-   bool ddr_clk_always_on;
int window_sync;
 };
 
@@ -224,7 +223,6 @@ struct omap_dss_dsi_config {
unsigned long hs_clk_min, hs_clk_max;
unsigned long lp_clk_min, lp_clk_max;
 
-   bool ddr_clk_always_on;
enum omap_dss_dsi_trans_mode trans_mode;
 };
 
-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

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


[PATCH v5 24/29] drm/omap: dsi: cleanup initial vc setup

2020-12-08 Thread Tomi Valkeinen
As we now have a fixed setup for VCs (VC0 for video stream, VC1 for
commands), we can simplify the VC setup.

Signed-off-by: Tomi Valkeinen 
---
 drivers/gpu/drm/omapdrm/dss/dsi.c | 85 +++
 1 file changed, 31 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c 
b/drivers/gpu/drm/omapdrm/dss/dsi.c
index d9c2cd849328..c32884f167b8 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -2017,40 +2017,6 @@ static void dsi_vc_initial_config(struct dsi_data *dsi, 
int vc)
dsi->vc[vc].source = DSI_VC_SOURCE_L4;
 }
 
-static int dsi_vc_config_source(struct dsi_data *dsi, int vc,
-   enum dsi_vc_source source)
-{
-   if (dsi->vc[vc].source == source)
-   return 0;
-
-   DSSDBG("Source config of VC %d", vc);
-
-   dsi_sync_vc(dsi, vc);
-
-   dsi_vc_enable(dsi, vc, 0);
-
-   /* VC_BUSY */
-   if (!wait_for_bit_change(dsi, DSI_VC_CTRL(vc), 15, 0)) {
-   DSSERR("vc(%d) busy when trying to config for VP\n", vc);
-   return -EIO;
-   }
-
-   /* SOURCE, 0 = L4, 1 = video port */
-   REG_FLD_MOD(dsi, DSI_VC_CTRL(vc), source, 1, 1);
-
-   /* DCS_CMD_ENABLE */
-   if (dsi->data->quirks & DSI_QUIRK_DCS_CMD_CONFIG_VC) {
-   bool enable = source == DSI_VC_SOURCE_VP;
-   REG_FLD_MOD(dsi, DSI_VC_CTRL(vc), enable, 30, 30);
-   }
-
-   dsi_vc_enable(dsi, vc, 1);
-
-   dsi->vc[vc].source = source;
-
-   return 0;
-}
-
 static void dsi_vc_enable_hs(struct omap_dss_device *dssdev, int vc,
bool enable)
 {
@@ -2072,10 +2038,6 @@ static void dsi_vc_enable_hs(struct omap_dss_device 
*dssdev, int vc,
dsi_if_enable(dsi, 1);
 
dsi_force_tx_stop_mode_io(dsi);
-
-   /* start the DDR clock by sending a NULL packet */
-   if (dsi->vm_timings.ddr_clk_always_on && enable)
-   dsi_vc_send_null(dsi, vc, dsi->dsidev->channel);
 }
 
 static void dsi_vc_flush_long_data(struct dsi_data *dsi, int vc)
@@ -2270,8 +2232,6 @@ static int dsi_vc_send_long(struct dsi_data *dsi, int vc,
return -EINVAL;
}
 
-   dsi_vc_config_source(dsi, vc, DSI_VC_SOURCE_L4);
-
dsi_vc_write_long_header(dsi, vc, msg->channel, msg->type, msg->tx_len, 
0);
 
p = msg->tx_buf;
@@ -2331,8 +2291,6 @@ static int dsi_vc_send_short(struct dsi_data *dsi, int vc,
DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n",
   vc, msg->type, pkt.header[1], pkt.header[2]);
 
-   dsi_vc_config_source(dsi, vc, DSI_VC_SOURCE_L4);
-
if (FLD_GET(dsi_read_reg(dsi, DSI_VC_CTRL(vc)), 16, 16)) {
DSSERR("ERROR FIFO FULL, aborting transfer\n");
return -EINVAL;
@@ -3351,8 +3309,6 @@ static void dsi_update_screen_dispc(struct dsi_data *dsi)
 
DSSDBG("dsi_update_screen_dispc(%dx%d)\n", w, h);
 
-   dsi_vc_config_source(dsi, vc, DSI_VC_SOURCE_VP);
-
bytespp = mipi_dsi_pixel_format_to_bpp(dsi->pix_fmt) / 8;
bytespl = w * bytespp;
bytespf = bytespl * h;
@@ -3522,14 +3478,12 @@ static int dsi_update_channel(struct omap_dss_device 
*dssdev, int vc)
 
dsi_set_ulps_auto(dsi, false);
 
-   dsi_vc_enable_hs(dssdev, vc, true);
-
/*
 * Send NOP between the frames. If we don't send something here, the
 * updates stop working. This is probably related to DSI spec stating
 * that the DSI host should transition to LP at least once per frame.
 */
-   r = _dsi_send_nop(dsi, vc, dsi->dsidev->channel);
+   r = _dsi_send_nop(dsi, VC_CMD, dsi->dsidev->channel);
if (r < 0) {
DSSWARN("failed to send nop between frames: %d\n", r);
goto err;
@@ -3654,6 +3608,35 @@ static int dsi_configure_dsi_clocks(struct dsi_data *dsi)
return 0;
 }
 
+static void dsi_setup_dsi_vcs(struct dsi_data *dsi)
+{
+   /* Setup VC_CMD for LP and cpu transfers */
+   REG_FLD_MOD(dsi, DSI_VC_CTRL(VC_CMD), 0, 9, 9); /* LP */
+
+   REG_FLD_MOD(dsi, DSI_VC_CTRL(VC_CMD), 0, 1, 1); /* SOURCE_L4 */
+   dsi->vc[VC_CMD].source = DSI_VC_SOURCE_L4;
+
+   /* Setup VC_VIDEO for HS and dispc transfers */
+   REG_FLD_MOD(dsi, DSI_VC_CTRL(VC_VIDEO), 1, 9, 9); /* HS */
+
+   REG_FLD_MOD(dsi, DSI_VC_CTRL(VC_VIDEO), 1, 1, 1); /* SOURCE_VP */
+   dsi->vc[VC_VIDEO].source = DSI_VC_SOURCE_VP;
+
+   if (dsi->data->quirks & DSI_QUIRK_DCS_CMD_CONFIG_VC)
+   REG_FLD_MOD(dsi, DSI_VC_CTRL(VC_VIDEO), 1, 30, 30); /* 
DCS_CMD_ENABLE */
+
+   dsi_vc_enable(dsi, VC_CMD, 1);
+   dsi_vc_enable(dsi, VC_VIDEO, 1);
+
+   dsi_if_enable(dsi, 1);
+
+   dsi_force_tx_stop_mode_io(dsi);
+
+   /* start the DDR clock by sending a NULL packet */
+   if (dsi->vm_timings.ddr_clk_always_on)
+   dsi_vc_send_null(dsi, VC_CMD, dsi->dsidev->channel);
+}
+
 static int dsi_in

[PATCH v5 21/29] drm/omap: dsi: display_enable cleanup

2020-12-08 Thread Tomi Valkeinen
We can drop dsi_display_enable(), which just calls
_dsi_display_enable(), and rename _dsi_display_enable() to
dsi_display_enable().

The WARN_ON(!dsi_bus_is_locked(dsi)) in dsi_display_enable is extra and
can be dropped, as _dsi_display_enable() has the same WARN_ON().

Signed-off-by: Tomi Valkeinen 
Reviewed-by: Laurent Pinchart 
---
 drivers/gpu/drm/omapdrm/dss/dsi.c | 16 +++-
 1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c 
b/drivers/gpu/drm/omapdrm/dss/dsi.c
index 44b8e42b52ec..961b991f6498 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -3743,7 +3743,7 @@ static void dsi_display_uninit_dsi(struct dsi_data *dsi, 
bool disconnect_lanes,
}
 }
 
-static void _dsi_display_enable(struct dsi_data *dsi)
+static void dsi_display_enable(struct dsi_data *dsi)
 {
int r;
 
@@ -3772,16 +3772,6 @@ static void _dsi_display_enable(struct dsi_data *dsi)
DSSDBG("dsi_display_ulps_enable FAILED\n");
 }
 
-static void dsi_display_enable(struct omap_dss_device *dssdev)
-{
-   struct dsi_data *dsi = to_dsi_data(dssdev);
-   DSSDBG("dsi_display_enable\n");
-
-   WARN_ON(!dsi_bus_is_locked(dsi));
-
-   _dsi_display_enable(dsi);
-}
-
 static void _dsi_display_disable(struct dsi_data *dsi,
bool disconnect_lanes, bool enter_ulps)
 {
@@ -3856,7 +3846,7 @@ static void dsi_set_ulps_auto(struct dsi_data *dsi, bool 
enable)
return;
 
dsi_bus_lock(dsi);
-   _dsi_display_enable(dsi);
+   dsi_display_enable(dsi);
dsi_enable_te(dsi, true);
dsi_bus_unlock(dsi);
}
@@ -4947,7 +4937,7 @@ static void dsi_bridge_enable(struct drm_bridge *bridge)
 
dsi_bus_lock(dsi);
 
-   dsi_display_enable(dssdev);
+   dsi_display_enable(dsi);
 
dsi_enable_video_output(dssdev, VC_VIDEO);
 
-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

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


[PATCH v5 23/29] drm/omap: dsi: rename dsi_display_* functions

2020-12-08 Thread Tomi Valkeinen
The function names have evolved to be very confusing, and bunch of them
have "display" in them even if the function doesn't deal with display as
such (e.g. dsi_display_enable which just enables the DSI interface).
Rename them by dropping the "display".

Signed-off-by: Tomi Valkeinen 
Reviewed-by: Laurent Pinchart 
---
 drivers/gpu/drm/omapdrm/dss/dsi.c | 36 +++
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c 
b/drivers/gpu/drm/omapdrm/dss/dsi.c
index d83346812810..d9c2cd849328 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -55,8 +55,8 @@
 
 static void dsi_set_ulps_auto(struct dsi_data *dsi, bool enable);
 
-static int dsi_display_init_dispc(struct dsi_data *dsi);
-static void dsi_display_uninit_dispc(struct dsi_data *dsi);
+static int dsi_init_dispc(struct dsi_data *dsi);
+static void dsi_uninit_dispc(struct dsi_data *dsi);
 
 static int dsi_vc_send_null(struct dsi_data *dsi, int vc, int channel);
 
@@ -3257,7 +3257,7 @@ static void dsi_enable_video_output(struct 
omap_dss_device *dssdev, int vc)
u16 word_count;
int r;
 
-   r = dsi_display_init_dispc(dsi);
+   r = dsi_init_dispc(dsi);
if (r) {
dev_err(dsi->dev, "failed to init dispc!\n");
return;
@@ -3309,7 +3309,7 @@ static void dsi_enable_video_output(struct 
omap_dss_device *dssdev, int vc)
dsi_vc_enable(dsi, vc, false);
}
 err_pix_fmt:
-   dsi_display_uninit_dispc(dsi);
+   dsi_uninit_dispc(dsi);
dev_err(dsi->dev, "failed to enable DSI encoder!\n");
return;
 }
@@ -3331,7 +3331,7 @@ static void dsi_disable_video_output(struct 
omap_dss_device *dssdev, int vc)
 
dss_mgr_disable(&dsi->output);
 
-   dsi_display_uninit_dispc(dsi);
+   dsi_uninit_dispc(dsi);
 }
 
 static void dsi_update_screen_dispc(struct dsi_data *dsi)
@@ -3582,7 +3582,7 @@ static int dsi_configure_dispc_clocks(struct dsi_data 
*dsi)
return 0;
 }
 
-static int dsi_display_init_dispc(struct dsi_data *dsi)
+static int dsi_init_dispc(struct dsi_data *dsi)
 {
enum omap_channel dispc_channel = dsi->output.dispc_channel;
int r;
@@ -3627,7 +3627,7 @@ static int dsi_display_init_dispc(struct dsi_data *dsi)
return r;
 }
 
-static void dsi_display_uninit_dispc(struct dsi_data *dsi)
+static void dsi_uninit_dispc(struct dsi_data *dsi)
 {
enum omap_channel dispc_channel = dsi->output.dispc_channel;
 
@@ -3654,7 +3654,7 @@ static int dsi_configure_dsi_clocks(struct dsi_data *dsi)
return 0;
 }
 
-static int dsi_display_init_dsi(struct dsi_data *dsi)
+static int dsi_init_dsi(struct dsi_data *dsi)
 {
int r;
 
@@ -3718,7 +3718,7 @@ static int dsi_display_init_dsi(struct dsi_data *dsi)
return r;
 }
 
-static void dsi_display_uninit_dsi(struct dsi_data *dsi, bool disconnect_lanes,
+static void dsi_uninit_dsi(struct dsi_data *dsi, bool disconnect_lanes,
   bool enter_ulps)
 {
if (enter_ulps && !dsi->ulps_enabled)
@@ -3741,7 +3741,7 @@ static void dsi_display_uninit_dsi(struct dsi_data *dsi, 
bool disconnect_lanes,
}
 }
 
-static void dsi_display_enable(struct dsi_data *dsi)
+static void dsi_enable(struct dsi_data *dsi)
 {
int r;
 
@@ -3755,7 +3755,7 @@ static void dsi_display_enable(struct dsi_data *dsi)
 
_dsi_initialize_irq(dsi);
 
-   r = dsi_display_init_dsi(dsi);
+   r = dsi_init_dsi(dsi);
if (r)
goto err_init_dsi;
 
@@ -3767,10 +3767,10 @@ static void dsi_display_enable(struct dsi_data *dsi)
dsi_runtime_put(dsi);
 err_get_dsi:
mutex_unlock(&dsi->lock);
-   DSSDBG("dsi_display_ulps_enable FAILED\n");
+   DSSDBG("dsi_enable FAILED\n");
 }
 
-static void dsi_display_disable(struct dsi_data *dsi,
+static void dsi_disable(struct dsi_data *dsi,
bool disconnect_lanes, bool enter_ulps)
 {
WARN_ON(!dsi_bus_is_locked(dsi));
@@ -3782,7 +3782,7 @@ static void dsi_display_disable(struct dsi_data *dsi,
dsi_sync_vc(dsi, 2);
dsi_sync_vc(dsi, 3);
 
-   dsi_display_uninit_dsi(dsi, disconnect_lanes, enter_ulps);
+   dsi_uninit_dsi(dsi, disconnect_lanes, enter_ulps);
 
dsi_runtime_put(dsi);
 
@@ -3812,7 +3812,7 @@ static void omap_dsi_ulps_work_callback(struct 
work_struct *work)
 
dsi_enable_te(dsi, false);
 
-   dsi_display_disable(dsi, false, true);
+   dsi_disable(dsi, false, true);
 
dsi_bus_unlock(dsi);
 }
@@ -3833,7 +3833,7 @@ static void dsi_set_ulps_auto(struct dsi_data *dsi, bool 
enable)
return;
 
dsi_bus_lock(dsi);
-   dsi_display_enable(dsi);
+   dsi_enable(dsi);
dsi_enable_te(dsi, true);
dsi_bus_unlock(dsi);
}
@@ -4924,7 +4924,7 @@ static void dsi_bridge_enable(struct drm_bridge *bridge)
 
dsi

[PATCH v5 16/29] drm/panel: panel-dsi-cm: remove extra 'if'

2020-12-08 Thread Tomi Valkeinen
We have a useless 'if' in the dsicm_bl_update_status(), a left over from
the conversion to DRM model. Drop the if.

Signed-off-by: Tomi Valkeinen 
Reviewed-by: Sam Ravnborg 
---
 drivers/gpu/drm/panel/panel-dsi-cm.c | 8 +++-
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-dsi-cm.c 
b/drivers/gpu/drm/panel/panel-dsi-cm.c
index 556f9a2c5c0c..fa564aad7f25 100644
--- a/drivers/gpu/drm/panel/panel-dsi-cm.c
+++ b/drivers/gpu/drm/panel/panel-dsi-cm.c
@@ -202,11 +202,9 @@ static int dsicm_bl_update_status(struct backlight_device 
*dev)
 
mutex_lock(&ddata->lock);
 
-   if (ddata->enabled) {
-   if (!r)
-   r = dsicm_dcs_write_1(
-   ddata, MIPI_DCS_SET_DISPLAY_BRIGHTNESS, level);
-   }
+   if (ddata->enabled)
+   r = dsicm_dcs_write_1(ddata, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
+ level);
 
mutex_unlock(&ddata->lock);
 
-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

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


[PATCH v5 19/29] drm/omap: dsi: move structs & defines to dsi.h

2020-12-08 Thread Tomi Valkeinen
Move structs and defines to a private dsi.h header file to make dsi.c a
bit easier to navigate. Also move the (now) private structs and defines
from omapdss.h to dsi.h.

Signed-off-by: Tomi Valkeinen 
Reviewed-by: Laurent Pinchart 
---
 drivers/gpu/drm/omapdrm/dss/dsi.c | 384 +
 drivers/gpu/drm/omapdrm/dss/dsi.h | 459 ++
 drivers/gpu/drm/omapdrm/dss/omapdss.h |  64 
 3 files changed, 460 insertions(+), 447 deletions(-)
 create mode 100644 drivers/gpu/drm/omapdrm/dss/dsi.h

diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c 
b/drivers/gpu/drm/omapdrm/dss/dsi.c
index 0795efdd8902..da3ff9e236bd 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -45,73 +45,7 @@
 
 #define DSI_CATCH_MISSING_TE
 
-struct dsi_reg { u16 module; u16 idx; };
-
-#define DSI_REG(mod, idx)  ((const struct dsi_reg) { mod, idx })
-
-/* DSI Protocol Engine */
-
-#define DSI_PROTO  0
-#define DSI_PROTO_SZ   0x200
-
-#define DSI_REVISION   DSI_REG(DSI_PROTO, 0x)
-#define DSI_SYSCONFIG  DSI_REG(DSI_PROTO, 0x0010)
-#define DSI_SYSSTATUS  DSI_REG(DSI_PROTO, 0x0014)
-#define DSI_IRQSTATUS  DSI_REG(DSI_PROTO, 0x0018)
-#define DSI_IRQENABLE  DSI_REG(DSI_PROTO, 0x001C)
-#define DSI_CTRL   DSI_REG(DSI_PROTO, 0x0040)
-#define DSI_GNQDSI_REG(DSI_PROTO, 0x0044)
-#define DSI_COMPLEXIO_CFG1 DSI_REG(DSI_PROTO, 0x0048)
-#define DSI_COMPLEXIO_IRQ_STATUS   DSI_REG(DSI_PROTO, 0x004C)
-#define DSI_COMPLEXIO_IRQ_ENABLE   DSI_REG(DSI_PROTO, 0x0050)
-#define DSI_CLK_CTRL   DSI_REG(DSI_PROTO, 0x0054)
-#define DSI_TIMING1DSI_REG(DSI_PROTO, 0x0058)
-#define DSI_TIMING2DSI_REG(DSI_PROTO, 0x005C)
-#define DSI_VM_TIMING1 DSI_REG(DSI_PROTO, 0x0060)
-#define DSI_VM_TIMING2 DSI_REG(DSI_PROTO, 0x0064)
-#define DSI_VM_TIMING3 DSI_REG(DSI_PROTO, 0x0068)
-#define DSI_CLK_TIMING DSI_REG(DSI_PROTO, 0x006C)
-#define DSI_TX_FIFO_VC_SIZEDSI_REG(DSI_PROTO, 0x0070)
-#define DSI_RX_FIFO_VC_SIZEDSI_REG(DSI_PROTO, 0x0074)
-#define DSI_COMPLEXIO_CFG2 DSI_REG(DSI_PROTO, 0x0078)
-#define DSI_RX_FIFO_VC_FULLNESSDSI_REG(DSI_PROTO, 0x007C)
-#define DSI_VM_TIMING4 DSI_REG(DSI_PROTO, 0x0080)
-#define DSI_TX_FIFO_VC_EMPTINESS   DSI_REG(DSI_PROTO, 0x0084)
-#define DSI_VM_TIMING5 DSI_REG(DSI_PROTO, 0x0088)
-#define DSI_VM_TIMING6 DSI_REG(DSI_PROTO, 0x008C)
-#define DSI_VM_TIMING7 DSI_REG(DSI_PROTO, 0x0090)
-#define DSI_STOPCLK_TIMING DSI_REG(DSI_PROTO, 0x0094)
-#define DSI_VC_CTRL(n) DSI_REG(DSI_PROTO, 0x0100 + (n * 0x20))
-#define DSI_VC_TE(n)   DSI_REG(DSI_PROTO, 0x0104 + (n * 0x20))
-#define DSI_VC_LONG_PACKET_HEADER(n)   DSI_REG(DSI_PROTO, 0x0108 + (n * 0x20))
-#define DSI_VC_LONG_PACKET_PAYLOAD(n)  DSI_REG(DSI_PROTO, 0x010C + (n * 0x20))
-#define DSI_VC_SHORT_PACKET_HEADER(n)  DSI_REG(DSI_PROTO, 0x0110 + (n * 0x20))
-#define DSI_VC_IRQSTATUS(n)DSI_REG(DSI_PROTO, 0x0118 + (n * 0x20))
-#define DSI_VC_IRQENABLE(n)DSI_REG(DSI_PROTO, 0x011C + (n * 0x20))
-
-/* DSIPHY_SCP */
-
-#define DSI_PHY1
-#define DSI_PHY_OFFSET 0x200
-#define DSI_PHY_SZ 0x40
-
-#define DSI_DSIPHY_CFG0DSI_REG(DSI_PHY, 0x)
-#define DSI_DSIPHY_CFG1DSI_REG(DSI_PHY, 0x0004)
-#define DSI_DSIPHY_CFG2DSI_REG(DSI_PHY, 0x0008)
-#define DSI_DSIPHY_CFG5DSI_REG(DSI_PHY, 0x0014)
-#define DSI_DSIPHY_CFG10   DSI_REG(DSI_PHY, 0x0028)
-
-/* DSI_PLL_CTRL_SCP */
-
-#define DSI_PLL2
-#define DSI_PLL_OFFSET 0x300
-#define DSI_PLL_SZ 0x20
-
-#define DSI_PLL_CONTROLDSI_REG(DSI_PLL, 0x)
-#define DSI_PLL_STATUS DSI_REG(DSI_PLL, 0x0004)
-#define DSI_PLL_GO DSI_REG(DSI_PLL, 0x0008)
-#define DSI_PLL_CONFIGURATION1 DSI_REG(DSI_PLL, 0x000C)
-#define DSI_PLL_CONFIGURATION2 DSI_REG(DSI_PLL, 0x0010)
+#include "dsi.h"
 
 #define REG_GET(dsi, idx, start, end) \
FLD_GET(dsi_read_reg(dsi, idx), start, end)
@@ -119,96 +53,6 @@ struct dsi_reg { u16 module; u16 idx; };
 #define REG_FLD_MOD(dsi, idx, val, start, end) \
dsi_write_reg(dsi, idx, FLD_MOD(dsi_read_reg(dsi, idx), val, start, 
end))
 
-/* Global interrupts */
-#define DSI_IRQ_VC0(1 << 0)
-#define DSI_IRQ_VC1(1 << 1)
-#define DSI_IRQ_VC2(1 << 2)
-#define DSI_IRQ_VC3(1 << 3)
-#define DSI_IRQ_WAKEUP (1 << 4)
-#define DSI_IR

[PATCH v5 14/29] drm/omap: dsi: enable HS before sending the frame

2020-12-08 Thread Tomi Valkeinen
We currently use a single VC for sending commands and pixel data. The
LP/HS mode for pixel data is correctly set to HS by accident, as we have
set the VC to HS already earlier.

However, if we use a different VC for video data, the VC is in LP mode.
Fix this by always enabling HS mode before starting a frame update.

Signed-off-by: Tomi Valkeinen 
---
 drivers/gpu/drm/omapdrm/dss/dsi.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c 
b/drivers/gpu/drm/omapdrm/dss/dsi.c
index 544f5f1eed91..9d210a020916 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -3918,6 +3918,8 @@ static int dsi_update_channel(struct omap_dss_device 
*dssdev, int vc)
 
dsi_set_ulps_auto(dsi, false);
 
+   dsi_vc_enable_hs(dssdev, vc, true);
+
/*
 * Send NOP between the frames. If we don't send something here, the
 * updates stop working. This is probably related to DSI spec stating
-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

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


[PATCH v5 12/29] drm/omap: dsi: untangle vc & channel

2020-12-08 Thread Tomi Valkeinen
DSI virtual channel and hardware VC blocks have gotten tangled as
described in the previous commits. This has not caused any issues, as
the value for both is 0, so it happens to work.

To fix the issue, change the code to use the correct one of the two.

Signed-off-by: Tomi Valkeinen 
---
 drivers/gpu/drm/omapdrm/dss/dsi.c | 43 +++
 1 file changed, 21 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c 
b/drivers/gpu/drm/omapdrm/dss/dsi.c
index 8d8412199693..a1f3623f45b1 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -2613,7 +2613,7 @@ static inline void dsi_vc_write_long_header(struct 
dsi_data *dsi, int vc,
 
WARN_ON(!dsi_bus_is_locked(dsi));
 
-   data_id = data_type | vc << 6;
+   data_id = data_type | channel << 6;
 
val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) |
FLD_VAL(ecc, 31, 24);
@@ -2647,12 +2647,12 @@ static int dsi_vc_send_long(struct dsi_data *dsi, int 
vc,
DSSDBG("dsi_vc_send_long, %d bytes\n", msg->tx_len);
 
/* len + header */
-   if (dsi->vc[msg->channel].tx_fifo_size * 32 * 4 < msg->tx_len + 4) {
+   if (dsi->vc[vc].tx_fifo_size * 32 * 4 < msg->tx_len + 4) {
DSSERR("unable to send long packet: packet too long.\n");
return -EINVAL;
}
 
-   dsi_vc_config_source(dsi, msg->channel, DSI_VC_SOURCE_L4);
+   dsi_vc_config_source(dsi, vc, DSI_VC_SOURCE_L4);
 
dsi_vc_write_long_header(dsi, vc, msg->channel, msg->type, msg->tx_len, 
0);
 
@@ -2666,7 +2666,7 @@ static int dsi_vc_send_long(struct dsi_data *dsi, int vc,
b3 = *p++;
b4 = *p++;
 
-   dsi_vc_write_long_payload(dsi, msg->channel, b1, b2, b3, b4);
+   dsi_vc_write_long_payload(dsi, vc, b1, b2, b3, b4);
}
 
i = msg->tx_len % 4;
@@ -2691,7 +2691,7 @@ static int dsi_vc_send_long(struct dsi_data *dsi, int vc,
break;
}
 
-   dsi_vc_write_long_payload(dsi, msg->channel, b1, b2, b3, 0);
+   dsi_vc_write_long_payload(dsi, vc, b1, b2, b3, 0);
}
 
return r;
@@ -2711,11 +2711,11 @@ static int dsi_vc_send_short(struct dsi_data *dsi, int 
vc,
 
if (dsi->debug_write)
DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n",
-  msg->channel, msg->type, pkt.header[1], pkt.header[2]);
+  vc, msg->type, pkt.header[1], pkt.header[2]);
 
-   dsi_vc_config_source(dsi, msg->channel, DSI_VC_SOURCE_L4);
+   dsi_vc_config_source(dsi, vc, DSI_VC_SOURCE_L4);
 
-   if (FLD_GET(dsi_read_reg(dsi, DSI_VC_CTRL(msg->channel)), 16, 16)) {
+   if (FLD_GET(dsi_read_reg(dsi, DSI_VC_CTRL(vc)), 16, 16)) {
DSSERR("ERROR FIFO FULL, aborting transfer\n");
return -EINVAL;
}
@@ -2723,7 +2723,7 @@ static int dsi_vc_send_short(struct dsi_data *dsi, int vc,
r = pkt.header[3] << 24 | pkt.header[2] << 16 | pkt.header[1] << 8 |
pkt.header[0];
 
-   dsi_write_reg(dsi, DSI_VC_SHORT_PACKET_HEADER(msg->channel), r);
+   dsi_write_reg(dsi, DSI_VC_SHORT_PACKET_HEADER(vc), r);
 
return 0;
 }
@@ -2731,7 +2731,7 @@ static int dsi_vc_send_short(struct dsi_data *dsi, int vc,
 static int dsi_vc_send_null(struct dsi_data *dsi, int vc, int channel)
 {
const struct mipi_dsi_msg msg = {
-   .channel = vc,
+   .channel = channel,
.type = MIPI_DSI_NULL_PACKET,
};
 
@@ -2759,16 +2759,16 @@ static int dsi_vc_write_common(struct omap_dss_device 
*dssdev, int vc,
 * In that case we can return early.
 */
 
-   r = dsi_vc_send_bta_sync(dssdev, msg->channel);
+   r = dsi_vc_send_bta_sync(dssdev, vc);
if (r) {
DSSERR("bta sync failed\n");
return r;
}
 
/* RX_FIFO_NOT_EMPTY */
-   if (REG_GET(dsi, DSI_VC_CTRL(msg->channel), 20, 20)) {
+   if (REG_GET(dsi, DSI_VC_CTRL(vc), 20, 20)) {
DSSERR("rx fifo not empty after write, dumping data:\n");
-   dsi_vc_flush_receive_data(dsi, msg->channel);
+   dsi_vc_flush_receive_data(dsi, vc);
return -EIO;
}
 
@@ -2888,21 +2888,20 @@ static int dsi_vc_dcs_read(struct omap_dss_device 
*dssdev, int vc,
 {
struct dsi_data *dsi = to_dsi_data(dssdev);
u8 cmd = ((u8 *)msg->tx_buf)[0];
-   u8 channel = msg->channel;
int r;
 
if (dsi->debug_read)
-   DSSDBG("%s(ch %d, cmd %x)\n", __func__, channel, cmd);
+   DSSDBG("%s(ch %d, cmd %x)\n", __func__, vc, cmd);
 
r = dsi_vc_send_short(dsi, vc, msg);
if (r)
goto err;
 
-   r = dsi_vc_send_bta_sync(dssdev, channel);
+   r = dsi_vc_send_bta_sync(dssdev, vc);
if (r)
goto err;
 
-   r = 

[PATCH v5 01/29] drm/panel: panel-dsi-cm: cleanup tear enable

2020-12-08 Thread Tomi Valkeinen
Simplify the code by moving code from _dsicm_enable_te() into
dsicm_power_on().

Signed-off-by: Tomi Valkeinen 
Reviewed-by: Sam Ravnborg 
Reviewed-by: Laurent Pinchart 
---
 drivers/gpu/drm/panel/panel-dsi-cm.c | 23 ---
 1 file changed, 4 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-dsi-cm.c 
b/drivers/gpu/drm/panel/panel-dsi-cm.c
index 729b42b4dabd..38f79dca1fd0 100644
--- a/drivers/gpu/drm/panel/panel-dsi-cm.c
+++ b/drivers/gpu/drm/panel/panel-dsi-cm.c
@@ -68,8 +68,6 @@ static inline struct panel_drv_data *panel_to_ddata(struct 
drm_panel *panel)
return container_of(panel, struct panel_drv_data, panel);
 }
 
-static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable);
-
 static void dsicm_bl_power(struct panel_drv_data *ddata, bool enable)
 {
struct backlight_device *backlight;
@@ -313,10 +311,13 @@ static int dsicm_power_on(struct panel_drv_data *ddata)
if (r)
goto err;
 
-   r = _dsicm_enable_te(ddata, true);
+   r = mipi_dsi_dcs_set_tear_on(ddata->dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
if (r)
goto err;
 
+   /* possible panel bug */
+   msleep(100);
+
ddata->enabled = true;
 
if (!ddata->intro_printed) {
@@ -417,22 +418,6 @@ static int dsicm_disable(struct drm_panel *panel)
return r;
 }
 
-static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable)
-{
-   struct mipi_dsi_device *dsi = ddata->dsi;
-   int r;
-
-   if (enable)
-   r = mipi_dsi_dcs_set_tear_on(dsi, 
MIPI_DSI_DCS_TEAR_MODE_VBLANK);
-   else
-   r = mipi_dsi_dcs_set_tear_off(dsi);
-
-   /* possible panel bug */
-   msleep(100);
-
-   return r;
-}
-
 static int dsicm_get_modes(struct drm_panel *panel,
   struct drm_connector *connector)
 {
-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

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


[PATCH v5 09/29] drm/omap: dsi: cleanup dispc channel usage

2020-12-08 Thread Tomi Valkeinen
The "channel" usage in omap dsi driver is confusing. As the first step,
change "channel" to "dispc_channel" when dealing with the dispc channel.

Signed-off-by: Tomi Valkeinen 
---
 drivers/gpu/drm/omapdrm/dss/dsi.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c 
b/drivers/gpu/drm/omapdrm/dss/dsi.c
index c78ae99c8742..cf0dc4872d14 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -3978,10 +3978,10 @@ static int dsi_configure_dispc_clocks(struct dsi_data 
*dsi)
 
 static int dsi_display_init_dispc(struct dsi_data *dsi)
 {
-   enum omap_channel channel = dsi->output.dispc_channel;
+   enum omap_channel dispc_channel = dsi->output.dispc_channel;
int r;
 
-   dss_select_lcd_clk_source(dsi->dss, channel, dsi->module_id == 0 ?
+   dss_select_lcd_clk_source(dsi->dss, dispc_channel, dsi->module_id == 0 ?
DSS_CLK_SRC_PLL1_1 :
DSS_CLK_SRC_PLL2_1);
 
@@ -4017,19 +4017,19 @@ static int dsi_display_init_dispc(struct dsi_data *dsi)
dss_mgr_unregister_framedone_handler(&dsi->output,
dsi_framedone_irq_callback, dsi);
 err:
-   dss_select_lcd_clk_source(dsi->dss, channel, DSS_CLK_SRC_FCK);
+   dss_select_lcd_clk_source(dsi->dss, dispc_channel, DSS_CLK_SRC_FCK);
return r;
 }
 
 static void dsi_display_uninit_dispc(struct dsi_data *dsi)
 {
-   enum omap_channel channel = dsi->output.dispc_channel;
+   enum omap_channel dispc_channel = dsi->output.dispc_channel;
 
if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
dss_mgr_unregister_framedone_handler(&dsi->output,
dsi_framedone_irq_callback, dsi);
 
-   dss_select_lcd_clk_source(dsi->dss, channel, DSS_CLK_SRC_FCK);
+   dss_select_lcd_clk_source(dsi->dss, dispc_channel, DSS_CLK_SRC_FCK);
 }
 
 static int dsi_configure_dsi_clocks(struct dsi_data *dsi)
@@ -4846,12 +4846,12 @@ static int dsi_set_config(struct omap_dss_device 
*dssdev,
 }
 
 /*
- * Return a hardcoded channel for the DSI output. This should work for
+ * Return a hardcoded dispc channel for the DSI output. This should work for
  * current use cases, but this can be later expanded to either resolve
  * the channel in some more dynamic manner, or get the channel as a user
  * parameter.
  */
-static enum omap_channel dsi_get_channel(struct dsi_data *dsi)
+static enum omap_channel dsi_get_dispc_channel(struct dsi_data *dsi)
 {
switch (dsi->data->model) {
case DSI_MODEL_OMAP3:
@@ -5403,7 +5403,7 @@ static int dsi_init_output(struct dsi_data *dsi)
 
out->type = OMAP_DISPLAY_TYPE_DSI;
out->name = dsi->module_id == 0 ? "dsi.0" : "dsi.1";
-   out->dispc_channel = dsi_get_channel(dsi);
+   out->dispc_channel = dsi_get_dispc_channel(dsi);
out->dsi_ops = &dsi_ops;
out->of_port = 0;
out->bus_flags = DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE
-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

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


[PATCH v5 08/29] drm/omap: dsi: drop useless channel checks

2020-12-08 Thread Tomi Valkeinen
A DSI peripheral can have virtual channel ID of 0-3. This should be
always the case, and there's no need in the driver to validate the
channel.

Signed-off-by: Tomi Valkeinen 
Reviewed-by: Laurent Pinchart 
---
 drivers/gpu/drm/omapdrm/dss/dsi.c | 11 ---
 1 file changed, 11 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c 
b/drivers/gpu/drm/omapdrm/dss/dsi.c
index 5e13478010db..c78ae99c8742 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -3902,9 +3902,6 @@ static int dsi_update_channel(struct omap_dss_device 
*dssdev, int channel)
struct dsi_data *dsi = to_dsi_data(dssdev);
int r;
 
-   if (channel > 3)
-   return -EINVAL;
-
dsi_bus_lock(dsi);
 
if (!dsi->video_enabled) {
@@ -5068,12 +5065,8 @@ static int omap_dsi_host_attach(struct mipi_dsi_host 
*host,
struct mipi_dsi_device *client)
 {
struct dsi_data *dsi = host_to_omap(host);
-   unsigned int channel = client->channel;
int r;
 
-   if (channel > 3)
-   return -EINVAL;
-
if (dsi->dsidev) {
DSSERR("dsi client already attached\n");
return -EBUSY;
@@ -5123,10 +5116,6 @@ static int omap_dsi_host_detach(struct mipi_dsi_host 
*host,
struct mipi_dsi_device *client)
 {
struct dsi_data *dsi = host_to_omap(host);
-   unsigned int channel = client->channel;
-
-   if (channel > 3)
-   return -EINVAL;
 
if (WARN_ON(dsi->dsidev != client))
return -EINVAL;
-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

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


[PATCH v5 13/29] drm/omap: dsi: skip dsi_vc_enable_hs when already in correct mode

2020-12-08 Thread Tomi Valkeinen
Simplify and optimize dsi_vc_enable_hs() so that it can be called
without checking the current HS/LP mode. Make dsi_vc_enable_hs() return
if the VC is already in the correct mode.

Signed-off-by: Tomi Valkeinen 
Reviewed-by: Laurent Pinchart 
---
 drivers/gpu/drm/omapdrm/dss/dsi.c | 10 --
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c 
b/drivers/gpu/drm/omapdrm/dss/dsi.c
index a1f3623f45b1..544f5f1eed91 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -341,7 +341,6 @@ struct dsi_data {
int irq;
 
bool is_enabled;
-   bool in_lp_mode;
 
struct clk *dss_clk;
struct regmap *syscon;
@@ -2441,6 +2440,9 @@ static void dsi_vc_enable_hs(struct omap_dss_device 
*dssdev, int vc,
 
DSSDBG("dsi_vc_enable_hs(%d, %d)\n", vc, enable);
 
+   if (REG_GET(dsi, DSI_VC_CTRL(vc), 9, 9) == enable)
+   return;
+
WARN_ON(!dsi_bus_is_locked(dsi));
 
dsi_vc_enable(dsi, vc, 0);
@@ -2456,8 +2458,6 @@ static void dsi_vc_enable_hs(struct omap_dss_device 
*dssdev, int vc,
/* start the DDR clock by sending a NULL packet */
if (dsi->vm_timings.ddr_clk_always_on && enable)
dsi_vc_send_null(dsi, vc, dsi->dsidev->channel);
-
-   dsi->in_lp_mode = !enable;
 }
 
 static void dsi_vc_flush_long_data(struct dsi_data *dsi, int vc)
@@ -4891,9 +4891,7 @@ static ssize_t _omap_dsi_host_transfer(struct dsi_data 
*dsi, int vc,
struct omap_dss_device *dssdev = &dsi->output;
int r;
 
-   if (!!(msg->flags & MIPI_DSI_MSG_USE_LPM) != dsi->in_lp_mode)
-   dsi_vc_enable_hs(dssdev, vc,
-!(msg->flags & MIPI_DSI_MSG_USE_LPM));
+   dsi_vc_enable_hs(dssdev, vc, !(msg->flags & MIPI_DSI_MSG_USE_LPM));
 
switch (msg->type) {
case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

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


[PATCH v5 11/29] drm/omap: dsi: pass vc to various functions

2020-12-08 Thread Tomi Valkeinen
To start fixing the issues related to channels and vcs described in the
previous commit, pass vc to various functions which will need it do
properly handle different DSI channels and VCs.

No functional changes.

Signed-off-by: Tomi Valkeinen 
---
 drivers/gpu/drm/omapdrm/dss/dsi.c | 54 ---
 1 file changed, 28 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c 
b/drivers/gpu/drm/omapdrm/dss/dsi.c
index 273159e8f992..8d8412199693 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -214,9 +214,9 @@ static void dsi_set_ulps_auto(struct dsi_data *dsi, bool 
enable);
 static int dsi_display_init_dispc(struct dsi_data *dsi);
 static void dsi_display_uninit_dispc(struct dsi_data *dsi);
 
-static int dsi_vc_send_null(struct dsi_data *dsi, int vc);
+static int dsi_vc_send_null(struct dsi_data *dsi, int vc, int channel);
 
-static ssize_t _omap_dsi_host_transfer(struct dsi_data *dsi,
+static ssize_t _omap_dsi_host_transfer(struct dsi_data *dsi, int vc,
   const struct mipi_dsi_msg *msg);
 
 static void dsi_display_disable(struct omap_dss_device *dssdev);
@@ -2455,7 +2455,7 @@ static void dsi_vc_enable_hs(struct omap_dss_device 
*dssdev, int vc,
 
/* start the DDR clock by sending a NULL packet */
if (dsi->vm_timings.ddr_clk_always_on && enable)
-   dsi_vc_send_null(dsi, vc);
+   dsi_vc_send_null(dsi, vc, dsi->dsidev->channel);
 
dsi->in_lp_mode = !enable;
 }
@@ -2605,7 +2605,8 @@ static int dsi_vc_send_bta_sync(struct omap_dss_device 
*dssdev, int vc)
 }
 
 static inline void dsi_vc_write_long_header(struct dsi_data *dsi, int vc,
-   u8 data_type, u16 len, u8 ecc)
+   int channel, u8 data_type, u16 len,
+   u8 ecc)
 {
u32 val;
u8 data_id;
@@ -2633,7 +2634,7 @@ static inline void dsi_vc_write_long_payload(struct 
dsi_data *dsi, int vc,
dsi_write_reg(dsi, DSI_VC_LONG_PACKET_PAYLOAD(vc), val);
 }
 
-static int dsi_vc_send_long(struct dsi_data *dsi,
+static int dsi_vc_send_long(struct dsi_data *dsi, int vc,
const struct mipi_dsi_msg *msg)
 {
/*u32 val; */
@@ -2653,7 +2654,7 @@ static int dsi_vc_send_long(struct dsi_data *dsi,
 
dsi_vc_config_source(dsi, msg->channel, DSI_VC_SOURCE_L4);
 
-   dsi_vc_write_long_header(dsi, msg->channel, msg->type, msg->tx_len, 0);
+   dsi_vc_write_long_header(dsi, vc, msg->channel, msg->type, msg->tx_len, 
0);
 
p = msg->tx_buf;
for (i = 0; i < msg->tx_len >> 2; i++) {
@@ -2696,7 +2697,7 @@ static int dsi_vc_send_long(struct dsi_data *dsi,
return r;
 }
 
-static int dsi_vc_send_short(struct dsi_data *dsi,
+static int dsi_vc_send_short(struct dsi_data *dsi, int vc,
 const struct mipi_dsi_msg *msg)
 {
struct mipi_dsi_packet pkt;
@@ -2727,26 +2728,26 @@ static int dsi_vc_send_short(struct dsi_data *dsi,
return 0;
 }
 
-static int dsi_vc_send_null(struct dsi_data *dsi, int vc)
+static int dsi_vc_send_null(struct dsi_data *dsi, int vc, int channel)
 {
const struct mipi_dsi_msg msg = {
.channel = vc,
.type = MIPI_DSI_NULL_PACKET,
};
 
-   return dsi_vc_send_long(dsi, &msg);
+   return dsi_vc_send_long(dsi, vc, &msg);
 }
 
-static int dsi_vc_write_common(struct omap_dss_device *dssdev,
+static int dsi_vc_write_common(struct omap_dss_device *dssdev, int vc,
   const struct mipi_dsi_msg *msg)
 {
struct dsi_data *dsi = to_dsi_data(dssdev);
int r;
 
if (mipi_dsi_packet_format_is_short(msg->type))
-   r = dsi_vc_send_short(dsi, msg);
+   r = dsi_vc_send_short(dsi, vc, msg);
else
-   r = dsi_vc_send_long(dsi, msg);
+   r = dsi_vc_send_long(dsi, vc, msg);
 
if (r < 0)
return r;
@@ -2882,7 +2883,7 @@ static int dsi_vc_read_rx_fifo(struct dsi_data *dsi, int 
vc, u8 *buf,
return r;
 }
 
-static int dsi_vc_dcs_read(struct omap_dss_device *dssdev,
+static int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int vc,
   const struct mipi_dsi_msg *msg)
 {
struct dsi_data *dsi = to_dsi_data(dssdev);
@@ -2893,7 +2894,7 @@ static int dsi_vc_dcs_read(struct omap_dss_device *dssdev,
if (dsi->debug_read)
DSSDBG("%s(ch %d, cmd %x)\n", __func__, channel, cmd);
 
-   r = dsi_vc_send_short(dsi, msg);
+   r = dsi_vc_send_short(dsi, vc, msg);
if (r)
goto err;
 
@@ -2917,13 +2918,13 @@ static int dsi_vc_dcs_read(struct omap_dss_device 
*dssdev,
return r;
 }
 
-static int dsi_vc_generic_read(struct omap_dss_device *dssdev,
+static int dsi_vc_generic_read(struct omap_dss_device *dssdev, int vc,
   

[PATCH v5 10/29] drm/omap: dsi: rename 'channel' to 'vc'

2020-12-08 Thread Tomi Valkeinen
The "channel" usage in omap dsi driver is confusing. We have three
different "channels":

1) DSI virtual channel ID. This is a number from 0 to 3, included in the
packet payload.

2) VC. This is a register block in the DSI IP. There are four of those
blocks. A VC is a DSI "pipeline", with defined fifo settings, data
source (cpu or dispc), and some other settings. It has no relation to
the 1).

3) dispc channel. It's the "pipeline" number dispc uses to send pixel
data.

The previous patch handled the third case.

 To start fixing 1) and 2), we first rename all uses of 'channel' to
'vc', as in most of the cases that is the correct thing to use.

However, in some places 1) and 2) have gotten mixed up (i.e. the code
uses msg->channel when it should use vc), which will be fixed in the
following patch.

Note that mixing 1) and 2) currently is "fine", as at the moment we only
support DSI peripherals with DSI virtual channel 0, and we always use
VC0 to send data. So both 1) and 2) are always 0.

Signed-off-by: Tomi Valkeinen 
---
 drivers/gpu/drm/omapdrm/dss/dsi.c | 220 +++---
 1 file changed, 110 insertions(+), 110 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c 
b/drivers/gpu/drm/omapdrm/dss/dsi.c
index cf0dc4872d14..273159e8f992 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -214,7 +214,7 @@ static void dsi_set_ulps_auto(struct dsi_data *dsi, bool 
enable);
 static int dsi_display_init_dispc(struct dsi_data *dsi);
 static void dsi_display_uninit_dispc(struct dsi_data *dsi);
 
-static int dsi_vc_send_null(struct dsi_data *dsi, int channel);
+static int dsi_vc_send_null(struct dsi_data *dsi, int vc);
 
 static ssize_t _omap_dsi_host_transfer(struct dsi_data *dsi,
   const struct mipi_dsi_msg *msg);
@@ -376,7 +376,7 @@ struct dsi_data {
/* space for a copy used by the interrupt handler */
struct dsi_isr_tables isr_tables_copy;
 
-   int update_channel;
+   int update_vc;
 #ifdef DSI_PERF_MEASURE
unsigned int update_bytes;
 #endif
@@ -639,7 +639,7 @@ static void print_irq_status(u32 status)
 #undef PIS
 }
 
-static void print_irq_status_vc(int channel, u32 status)
+static void print_irq_status_vc(int vc, u32 status)
 {
if (status == 0)
return;
@@ -650,7 +650,7 @@ static void print_irq_status_vc(int channel, u32 status)
 #define PIS(x) (status & DSI_VC_IRQ_##x) ? (#x " ") : ""
 
pr_debug("DSI VC(%d) IRQ 0x%x: %s%s%s%s%s%s%s%s%s\n",
-   channel,
+   vc,
status,
PIS(CS),
PIS(ECC_CORR),
@@ -1031,7 +1031,7 @@ static int dsi_unregister_isr(struct dsi_data *dsi, 
omap_dsi_isr_t isr,
return r;
 }
 
-static int dsi_register_isr_vc(struct dsi_data *dsi, int channel,
+static int dsi_register_isr_vc(struct dsi_data *dsi, int vc,
   omap_dsi_isr_t isr, void *arg, u32 mask)
 {
unsigned long flags;
@@ -1040,18 +1040,18 @@ static int dsi_register_isr_vc(struct dsi_data *dsi, 
int channel,
spin_lock_irqsave(&dsi->irq_lock, flags);
 
r = _dsi_register_isr(isr, arg, mask,
-   dsi->isr_tables.isr_table_vc[channel],
-   ARRAY_SIZE(dsi->isr_tables.isr_table_vc[channel]));
+   dsi->isr_tables.isr_table_vc[vc],
+   ARRAY_SIZE(dsi->isr_tables.isr_table_vc[vc]));
 
if (r == 0)
-   _omap_dsi_set_irqs_vc(dsi, channel);
+   _omap_dsi_set_irqs_vc(dsi, vc);
 
spin_unlock_irqrestore(&dsi->irq_lock, flags);
 
return r;
 }
 
-static int dsi_unregister_isr_vc(struct dsi_data *dsi, int channel,
+static int dsi_unregister_isr_vc(struct dsi_data *dsi, int vc,
 omap_dsi_isr_t isr, void *arg, u32 mask)
 {
unsigned long flags;
@@ -1060,11 +1060,11 @@ static int dsi_unregister_isr_vc(struct dsi_data *dsi, 
int channel,
spin_lock_irqsave(&dsi->irq_lock, flags);
 
r = _dsi_unregister_isr(isr, arg, mask,
-   dsi->isr_tables.isr_table_vc[channel],
-   ARRAY_SIZE(dsi->isr_tables.isr_table_vc[channel]));
+   dsi->isr_tables.isr_table_vc[vc],
+   ARRAY_SIZE(dsi->isr_tables.isr_table_vc[vc]));
 
if (r == 0)
-   _omap_dsi_set_irqs_vc(dsi, channel);
+   _omap_dsi_set_irqs_vc(dsi, vc);
 
spin_unlock_irqrestore(&dsi->irq_lock, flags);
 
@@ -2232,9 +2232,9 @@ static int dsi_force_tx_stop_mode_io(struct dsi_data *dsi)
return 0;
 }
 
-static bool dsi_vc_is_enabled(struct dsi_data *dsi, int channel)
+static bool dsi_vc_is_enabled(struct dsi_data *dsi, int vc)
 {
-   return REG_GET(dsi, DSI_VC_CTRL(channel), 0, 0);
+   return REG_GET(dsi, DSI_VC_CTRL(vc), 0, 0);
 }
 
 static void dsi_packet_sent_handler_vp(void *data, u32 mask)
@@ -2242,14 +2242,14 @@ s

[PATCH v5 07/29] drm/omap: dsi: simplify VC handling

2020-12-08 Thread Tomi Valkeinen
The VC handling has gotten quite tangled up. As the first step to clean
it up, lets define that we only support a single DSI peripheral (which
was really already the case), and we always use VC0 (define VC_DEFAULT
0) register block to send data to the peripheral.

We can thus have a single mipi_dsi_device pointer and remove the
for-loops which made passes over all the four VCs (just the first one
was ever used).

Signed-off-by: Tomi Valkeinen 
Reviewed-by: Laurent Pinchart 
---
 drivers/gpu/drm/omapdrm/dss/dsi.c | 49 ---
 1 file changed, 13 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c 
b/drivers/gpu/drm/omapdrm/dss/dsi.c
index c6e044f8bece..5e13478010db 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -360,9 +360,10 @@ struct dsi_data {
bool vdds_dsi_enabled;
struct regulator *vdds_dsi_reg;
 
+   struct mipi_dsi_device *dsidev;
+
struct {
enum dsi_vc_source source;
-   struct mipi_dsi_device *dest;
enum fifo_size tx_fifo_size;
enum fifo_size rx_fifo_size;
} vc[4];
@@ -452,6 +453,8 @@ static bool dsi_perf;
 module_param(dsi_perf, bool, 0644);
 #endif
 
+#define VC_DEFAULT 0
+
 #define drm_bridge_to_dsi(bridge) \
container_of(bridge, struct dsi_data, bridge)
 
@@ -3716,16 +3719,11 @@ static void dsi_disable_video_output(struct 
omap_dss_device *dssdev, int channel
 static void dsi_disable_video_outputs(struct omap_dss_device *dssdev)
 {
struct dsi_data *dsi = to_dsi_data(dssdev);
-   unsigned int i;
 
dsi_bus_lock(dsi);
dsi->video_enabled = false;
 
-   for (i = 0; i < 4; i++) {
-   if (!dsi->vc[i].dest)
-   continue;
-   dsi_disable_video_output(dssdev, i);
-   }
+   dsi_disable_video_output(dssdev, VC_DEFAULT);
 
dsi_display_disable(dssdev);
 
@@ -3914,11 +3912,6 @@ static int dsi_update_channel(struct omap_dss_device 
*dssdev, int channel)
goto err;
}
 
-   if (!dsi->vc[channel].dest) {
-   r = -ENODEV;
-   goto err;
-   }
-
if (dsi->vm.hactive == 0 || dsi->vm.vactive == 0) {
r = -EINVAL;
goto err;
@@ -3959,16 +3952,7 @@ static int dsi_update_channel(struct omap_dss_device 
*dssdev, int channel)
 
 static int dsi_update_all(struct omap_dss_device *dssdev)
 {
-   unsigned int i;
-   int r;
-
-   for (i = 0; i < 4; i++) {
-   r = dsi_update_channel(dssdev, i);
-   if (r && r != -ENODEV)
-   return r;
-   }
-
-   return r;
+   return dsi_update_channel(dssdev, VC_DEFAULT);
 }
 
 /* Display funcs */
@@ -4196,17 +4180,12 @@ static void dsi_display_enable(struct omap_dss_device 
*dssdev)
 static void dsi_enable_video_outputs(struct omap_dss_device *dssdev)
 {
struct dsi_data *dsi = to_dsi_data(dssdev);
-   unsigned int i;
 
dsi_bus_lock(dsi);
 
dsi_display_enable(dssdev);
 
-   for (i = 0; i < 4; i++) {
-   if (!dsi->vc[i].dest)
-   continue;
-   dsi_enable_video_output(dssdev, i);
-   }
+   dsi_enable_video_output(dssdev, VC_DEFAULT);
 
dsi->video_enabled = true;
 
@@ -5095,8 +5074,8 @@ static int omap_dsi_host_attach(struct mipi_dsi_host 
*host,
if (channel > 3)
return -EINVAL;
 
-   if (dsi->vc[channel].dest) {
-   DSSERR("cannot get VC for display %s", dev_name(&client->dev));
+   if (dsi->dsidev) {
+   DSSERR("dsi client already attached\n");
return -EBUSY;
}
 
@@ -5117,7 +5096,7 @@ static int omap_dsi_host_attach(struct mipi_dsi_host 
*host,
dsi->mode = OMAP_DSS_DSI_CMD_MODE;
}
 
-   dsi->vc[channel].dest = client;
+   dsi->dsidev = client;
dsi->pix_fmt = client->format;
 
INIT_DEFERRABLE_WORK(&dsi->ulps_work,
@@ -5149,11 +5128,11 @@ static int omap_dsi_host_detach(struct mipi_dsi_host 
*host,
if (channel > 3)
return -EINVAL;
 
-   if (dsi->vc[channel].dest != client)
+   if (WARN_ON(dsi->dsidev != client))
return -EINVAL;
 
omap_dsi_unregister_te_irq(dsi);
-   dsi->vc[channel].dest = NULL;
+   dsi->dsidev = NULL;
return 0;
 }
 
@@ -5685,10 +5664,8 @@ static int dsi_probe(struct platform_device *pdev)
}
 
/* DSI VCs initialization */
-   for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) {
+   for (i = 0; i < ARRAY_SIZE(dsi->vc); i++)
dsi->vc[i].source = DSI_VC_SOURCE_L4;
-   dsi->vc[i].dest = NULL;
-   }
 
r = dsi_get_clocks(dsi);
if (r)
-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

___

[PATCH v5 02/29] ARM: dts: omap5: add address-cells & size-cells to dsi

2020-12-08 Thread Tomi Valkeinen
Add address-cells & size-cells to DSI nodes so that board files do not
need to define them.

Signed-off-by: Tomi Valkeinen 
Cc: Tony Lindgren 
Acked-by: Tony Lindgren 
---
 arch/arm/boot/dts/omap5.dtsi | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index 2bf2e5839a7f..e6f6947965ef 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -517,6 +517,9 @@ dsi1: encoder@0 {
clocks = <&dss_clkctrl 
OMAP5_DSS_CORE_CLKCTRL 8>,
 <&dss_clkctrl 
OMAP5_DSS_CORE_CLKCTRL 10>;
clock-names = "fck", "sys_clk";
+
+   #address-cells = <1>;
+   #size-cells = <0>;
};
};
 
@@ -549,6 +552,9 @@ dsi2: encoder@0 {
clocks = <&dss_clkctrl 
OMAP5_DSS_CORE_CLKCTRL 8>,
 <&dss_clkctrl 
OMAP5_DSS_CORE_CLKCTRL 10>;
clock-names = "fck", "sys_clk";
+
+   #address-cells = <1>;
+   #size-cells = <0>;
};
};
 
-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

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


[PATCH v5 06/29] drm/omap: dsi: send nop instead of page & column

2020-12-08 Thread Tomi Valkeinen
The OMAP DSI command mode panel driver used to send page & column
address before each frame update, and this code was moved into the DSI
host driver when converting it to the DRM bridge model.

However, it's not really required to send the page & column address
before each frame. It's also something that doesn't really belong to the
DSI host driver, so we should drop the code.

That said, frame updates break if we don't send _something_ between the
frames. A NOP command does the trick.

It is not clear if this behavior is as expected from a DSI command mode
frame transfer, or is it a feature/issue with OMAP DSI driver, or a
feature/issue in the command mode panel used.

Most likely this is related to the following from the DSI spec:

"To enable PHY synchronization the host processor should periodically
end HS transmission and drive the Data Lanes to the LP state. This
transition should take place at least once per frame."

Signed-off-by: Tomi Valkeinen 
Reviewed-by: Laurent Pinchart 
---
 drivers/gpu/drm/omapdrm/dss/dsi.c | 46 ---
 1 file changed, 17 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c 
b/drivers/gpu/drm/omapdrm/dss/dsi.c
index 7fee9cf8782d..c6e044f8bece 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -3884,35 +3884,19 @@ static int _dsi_update(struct dsi_data *dsi)
return 0;
 }
 
-static int _dsi_update_window(struct dsi_data *dsi, int channel,
- int x, int y, int w, int h)
-{
-   int x1 = x, x2 = (x + w - 1);
-   int y1 = y, y2 = (y + h - 1);
-   u8 payloadX[5] = { MIPI_DCS_SET_COLUMN_ADDRESS,
-  x1 >> 8, x1 & 0xff, x2 >> 8, x2 & 0xff };
-   u8 payloadY[5] = { MIPI_DCS_SET_PAGE_ADDRESS,
-  y1 >> 8, y1 & 0xff, y2 >> 8, y2 & 0xff };
-   struct mipi_dsi_msg msgX = { 0 }, msgY = { 0 };
-   int ret;
+static int _dsi_send_nop(struct dsi_data *dsi, int channel)
+{
+   const u8 payload[] = { MIPI_DCS_NOP };
+   const struct mipi_dsi_msg msg = {
+   .channel = channel,
+   .type = MIPI_DSI_DCS_SHORT_WRITE,
+   .tx_len = 1,
+   .tx_buf = payload,
+   };
 
WARN_ON(!dsi_bus_is_locked(dsi));
 
-   msgX.type = MIPI_DSI_DCS_LONG_WRITE;
-   msgX.channel = channel;
-   msgX.tx_buf = payloadX;
-   msgX.tx_len = sizeof(payloadX);
-
-   msgY.type = MIPI_DSI_DCS_LONG_WRITE;
-   msgY.channel = channel;
-   msgY.tx_buf = payloadY;
-   msgY.tx_len = sizeof(payloadY);
-
-   ret = _omap_dsi_host_transfer(dsi, &msgX);
-   if (ret != 0)
-   return ret;
-
-   return _omap_dsi_host_transfer(dsi, &msgY);
+   return _omap_dsi_host_transfer(dsi, &msg);
 }
 
 static int dsi_update_channel(struct omap_dss_device *dssdev, int channel)
@@ -3944,10 +3928,14 @@ static int dsi_update_channel(struct omap_dss_device 
*dssdev, int channel)
 
dsi_set_ulps_auto(dsi, false);
 
-   r = _dsi_update_window(dsi, channel, 0, 0, dsi->vm.hactive,
-  dsi->vm.vactive);
+   /*
+* Send NOP between the frames. If we don't send something here, the
+* updates stop working. This is probably related to DSI spec stating
+* that the DSI host should transition to LP at least once per frame.
+*/
+   r = _dsi_send_nop(dsi, channel);
if (r < 0) {
-   DSSWARN("window update error: %d\n", r);
+   DSSWARN("failed to send nop between frames: %d\n", r);
goto err;
}
 
-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

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


[PATCH v5 04/29] drm/omap: dsi: set trans_mode according to client mode_flags

2020-12-08 Thread Tomi Valkeinen
The DSI host driver currently ignores the video mode flags in
client->mode_flags. Add the code to take the transfer mode from client's
mode_flags.

Signed-off-by: Tomi Valkeinen 
Reviewed-by: Laurent Pinchart 
---
 drivers/gpu/drm/omapdrm/dss/dsi.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c 
b/drivers/gpu/drm/omapdrm/dss/dsi.c
index c3592c6db977..7fee9cf8782d 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -5140,6 +5140,13 @@ static int omap_dsi_host_attach(struct mipi_dsi_host 
*host,
dsi->config.lp_clk_min = 700; // TODO: get from client?
dsi->config.lp_clk_max = client->lp_rate;
 
+   if (client->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
+   dsi->config.trans_mode = OMAP_DSS_DSI_BURST_MODE;
+   else if (client->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
+   dsi->config.trans_mode = OMAP_DSS_DSI_PULSE_MODE;
+   else
+   dsi->config.trans_mode = OMAP_DSS_DSI_EVENT_MODE;
+
dsi->ulps_auto_idle = false;
 
return 0;
-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

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


[PATCH v5 00/29] Convert DSI code to use drm_mipi_dsi and drm_panel (second half)

2020-12-08 Thread Tomi Valkeinen
Hi,

This is version 5 of the series OMAP DSI conversion series. Previous
version can be found from:

https://www.spinics.net/lists/linux-omap/msg157480.html

To lessen the patch spam, I'm sending only patches starting from patch
56/80. There has been no changes to the patches before 56/80.

Diff between v4 and v5 is not much. There are no functional changes at
the end of the series (diff between v4 and v5 shows only cosmetic
changes, except fixing one missing r = 0 initialization).

The biggest change is splitting "drm/omap: dsi: cleanup channel usages"
into three parts. Also, the last patch is new in this version, although
I did send it for v4 as 81/80.

Other changes include minor clarifications and cleanups in the
descriptions, and moving a few changes from one commit to another in
case the change logically belongs to the other commit.

 Tomi

Tomi Valkeinen (29):
  drm/panel: panel-dsi-cm: cleanup tear enable
  ARM: dts: omap5: add address-cells & size-cells to dsi
  drm/omap: pll: fix iteration loop check
  drm/omap: dsi: set trans_mode according to client mode_flags
  drm/panel: panel-dsi-cm: set column & page at setup
  drm/omap: dsi: send nop instead of page & column
  drm/omap: dsi: simplify VC handling
  drm/omap: dsi: drop useless channel checks
  drm/omap: dsi: cleanup dispc channel usage
  drm/omap: dsi: rename 'channel' to 'vc'
  drm/omap: dsi: pass vc to various functions
  drm/omap: dsi: untangle vc & channel
  drm/omap: dsi: skip dsi_vc_enable_hs when already in correct mode
  drm/omap: dsi: enable HS before sending the frame
  drm/omap: dsi: use separate VCs for cmd and video
  drm/panel: panel-dsi-cm: remove extra 'if'
  drm/panel: panel-dsi-cm: add panel database to driver
  drm/panel: panel-dsi-cm: drop unneeded includes
  drm/omap: dsi: move structs & defines to dsi.h
  drm/omap: dsi: move enable/disable to bridge enable/disable
  drm/omap: dsi: display_enable cleanup
  drm/omap: dsi: display_disable cleanup
  drm/omap: dsi: rename dsi_display_* functions
  drm/omap: dsi: cleanup initial vc setup
  drm/omap: dsi: split video mode enable/disable into separate func
  drm/omap: dsi: fix and cleanup ddr_clk_always_on
  drm/omap: dsi: remove ulps support
  drm/omap: dsi: fix DCS_CMD_ENABLE
  drm/omap: dsi: allow DSI commands to be sent early

 arch/arm/boot/dts/omap5.dtsi  |6 +
 drivers/gpu/drm/omapdrm/dss/dsi.c | 1375 ++---
 drivers/gpu/drm/omapdrm/dss/dsi.h |  456 
 drivers/gpu/drm/omapdrm/dss/omapdss.h |   64 --
 drivers/gpu/drm/omapdrm/dss/pll.c |6 +
 drivers/gpu/drm/panel/panel-dsi-cm.c  |  161 +--
 6 files changed, 899 insertions(+), 1169 deletions(-)
 create mode 100644 drivers/gpu/drm/omapdrm/dss/dsi.h

-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

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


[PATCH v5 05/29] drm/panel: panel-dsi-cm: set column & page at setup

2020-12-08 Thread Tomi Valkeinen
Set the column & page address once during setup, instead of relying the
DSI host driver to set those.

Signed-off-by: Tomi Valkeinen 
Reviewed-by: Sam Ravnborg 
Reviewed-by: Laurent Pinchart 
---
 drivers/gpu/drm/panel/panel-dsi-cm.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/drivers/gpu/drm/panel/panel-dsi-cm.c 
b/drivers/gpu/drm/panel/panel-dsi-cm.c
index 38f79dca1fd0..556f9a2c5c0c 100644
--- a/drivers/gpu/drm/panel/panel-dsi-cm.c
+++ b/drivers/gpu/drm/panel/panel-dsi-cm.c
@@ -170,6 +170,22 @@ static int dsicm_get_id(struct panel_drv_data *ddata, u8 
*id1, u8 *id2, u8 *id3)
return 0;
 }
 
+static int dsicm_set_update_window(struct panel_drv_data *ddata)
+{
+   struct mipi_dsi_device *dsi = ddata->dsi;
+   int r;
+
+   r = mipi_dsi_dcs_set_column_address(dsi, 0, ddata->mode.hdisplay - 1);
+   if (r < 0)
+   return r;
+
+   r = mipi_dsi_dcs_set_page_address(dsi, 0, ddata->mode.vdisplay - 1);
+   if (r < 0)
+   return r;
+
+   return 0;
+}
+
 static int dsicm_bl_update_status(struct backlight_device *dev)
 {
struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
@@ -307,6 +323,10 @@ static int dsicm_power_on(struct panel_drv_data *ddata)
if (r)
goto err;
 
+   r = dsicm_set_update_window(ddata);
+   if (r)
+   goto err;
+
r = mipi_dsi_dcs_set_display_on(ddata->dsi);
if (r)
goto err;
-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

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


[PATCH v5 03/29] drm/omap: pll: fix iteration loop check

2020-12-08 Thread Tomi Valkeinen
If the PLL calc function is given bad parameters, n_start/m_start may be
higher than n_stop/m_stop, which leads to the loops iterating through
the whole u32 number space.

Fix this by failing early on such cases.

Signed-off-by: Tomi Valkeinen 
Reviewed-by: Laurent Pinchart 
---
 drivers/gpu/drm/omapdrm/dss/pll.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/omapdrm/dss/pll.c 
b/drivers/gpu/drm/omapdrm/dss/pll.c
index 1212f3cc52d1..12926218c436 100644
--- a/drivers/gpu/drm/omapdrm/dss/pll.c
+++ b/drivers/gpu/drm/omapdrm/dss/pll.c
@@ -222,6 +222,9 @@ bool dss_pll_calc_a(const struct dss_pll *pll, unsigned 
long clkin,
n_stop = min((unsigned)(clkin / fint_hw_min), hw->n_max);
n_inc = 1;
 
+   if (n_start > n_stop)
+   return false;
+
if (hw->errata_i886) {
swap(n_start, n_stop);
n_inc = -1;
@@ -239,6 +242,9 @@ bool dss_pll_calc_a(const struct dss_pll *pll, unsigned 
long clkin,
hw->m_max);
m_inc = 1;
 
+   if (m_start > m_stop)
+   continue;
+
if (hw->errata_i886) {
swap(m_start, m_stop);
m_inc = -1;
-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

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


[Bug 210543] amdgpu Kernel panic:__ttm_dma_free_page.isra.0+0xac/0xe8 [ttm]

2020-12-08 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=210543

--- Comment #1 from Alex Deucher (alexdeuc...@gmail.com) ---
Please attach your full dmesg output.

-- 
You are receiving this mail because:
You are watching the assignee of the bug.
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v2 2/2] drm: automatic legacy gamma support

2020-12-08 Thread Laurent Pinchart
Hi Tomi,

Thank you for the patch.

On Tue, Dec 08, 2020 at 03:57:59PM +0200, Tomi Valkeinen wrote:
> To support legacy gamma ioctls the drivers need to set
> drm_crtc_funcs.gamma_set either to a custom implementation or to
> drm_atomic_helper_legacy_gamma_set. Most of the atomic drivers do the
> latter.
> 
> We can simplify this by making the core handle it automatically.
> 
> Add two functions: drm_crtc_supports_legacy_gamma() which tells if the
> legacy gamma table can be set, and drm_crtc_legacy_gamma_set() which
> does the work by either calling the drm_crtc_funcs.gamma_set or using
> GAMMA_LUT or DEGAMMA_LUT.
> 
> We can then drop drm_atomic_helper_legacy_gamma_set() and remove all its
> uses.
> 
> Signed-off-by: Tomi Valkeinen 
> ---
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |   1 -
>  .../gpu/drm/arm/display/komeda/komeda_crtc.c  |   1 -
>  drivers/gpu/drm/arm/malidp_crtc.c |   1 -
>  drivers/gpu/drm/armada/armada_crtc.c  |   1 -
>  drivers/gpu/drm/ast/ast_mode.c|   1 -
>  .../gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c|   1 -
>  drivers/gpu/drm/drm_atomic_helper.c   |  79 
>  drivers/gpu/drm/drm_color_mgmt.c  | 118 --
>  drivers/gpu/drm/drm_crtc_internal.h   |   6 +
>  drivers/gpu/drm/drm_fb_helper.c   |  13 +-
>  drivers/gpu/drm/i915/display/intel_display.c  |   1 -
>  drivers/gpu/drm/ingenic/ingenic-drm-drv.c |   2 -
>  drivers/gpu/drm/mediatek/mtk_drm_crtc.c   |   1 -
>  drivers/gpu/drm/nouveau/dispnv50/head.c   |   2 -
>  drivers/gpu/drm/omapdrm/omap_crtc.c   |   1 -
>  drivers/gpu/drm/rcar-du/rcar_du_crtc.c|   1 -
>  drivers/gpu/drm/rockchip/rockchip_drm_vop.c   |   1 -
>  drivers/gpu/drm/stm/ltdc.c|   1 -
>  drivers/gpu/drm/vc4/vc4_crtc.c|   1 -
>  drivers/gpu/drm/vc4/vc4_txp.c |   1 -
>  include/drm/drm_atomic_helper.h   |   4 -
>  21 files changed, 122 insertions(+), 116 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index 2855bb918535..848b06c51b0e 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -5396,7 +5396,6 @@ static void dm_disable_vblank(struct drm_crtc *crtc)
>  static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = {
>   .reset = dm_crtc_reset_state,
>   .destroy = amdgpu_dm_crtc_destroy,
> - .gamma_set = drm_atomic_helper_legacy_gamma_set,
>   .set_config = drm_atomic_helper_set_config,
>   .page_flip = drm_atomic_helper_page_flip,
>   .atomic_duplicate_state = dm_crtc_duplicate_state,
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c 
> b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
> index 4b485eb512e2..59172acb9738 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
> @@ -550,7 +550,6 @@ static void komeda_crtc_vblank_disable(struct drm_crtc 
> *crtc)
>  }
>  
>  static const struct drm_crtc_funcs komeda_crtc_funcs = {
> - .gamma_set  = drm_atomic_helper_legacy_gamma_set,
>   .destroy= drm_crtc_cleanup,
>   .set_config = drm_atomic_helper_set_config,
>   .page_flip  = drm_atomic_helper_page_flip,
> diff --git a/drivers/gpu/drm/arm/malidp_crtc.c 
> b/drivers/gpu/drm/arm/malidp_crtc.c
> index 108e7a31bd26..494075ddbef6 100644
> --- a/drivers/gpu/drm/arm/malidp_crtc.c
> +++ b/drivers/gpu/drm/arm/malidp_crtc.c
> @@ -510,7 +510,6 @@ static void malidp_crtc_disable_vblank(struct drm_crtc 
> *crtc)
>  }
>  
>  static const struct drm_crtc_funcs malidp_crtc_funcs = {
> - .gamma_set = drm_atomic_helper_legacy_gamma_set,
>   .destroy = drm_crtc_cleanup,
>   .set_config = drm_atomic_helper_set_config,
>   .page_flip = drm_atomic_helper_page_flip,
> diff --git a/drivers/gpu/drm/armada/armada_crtc.c 
> b/drivers/gpu/drm/armada/armada_crtc.c
> index 3ebcf5a52c8b..b7bb90ae787f 100644
> --- a/drivers/gpu/drm/armada/armada_crtc.c
> +++ b/drivers/gpu/drm/armada/armada_crtc.c
> @@ -820,7 +820,6 @@ static const struct drm_crtc_funcs armada_crtc_funcs = {
>   .cursor_set = armada_drm_crtc_cursor_set,
>   .cursor_move= armada_drm_crtc_cursor_move,
>   .destroy= armada_drm_crtc_destroy,
> - .gamma_set  = drm_atomic_helper_legacy_gamma_set,
>   .set_config = drm_atomic_helper_set_config,
>   .page_flip  = drm_atomic_helper_page_flip,
>   .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
> index 9db371f4054f..5b0ec785c516 100644
> --- a/drivers/gpu/drm/ast/ast_mode.c
> +++ b/drivers/gpu/drm/ast/ast_mode.c
> @@ -903,7 +903,6 @@ static void ast_crtc_atomic_destroy_state(struct drm_crtc 
> *crtc,

Re: [PATCH v4 00/19] drm: managed encoder/plane/crtc allocation

2020-12-08 Thread Philipp Zabel
On Tue, 2020-12-08 at 16:54 +0100, Philipp Zabel wrote:
> Hi,
> 
> this is an update of the drmm_(simple_)encoder_alloc(),
> drmm_universal_plane_alloc(), and drmm_crtc_alloc_with_plane()
> functions in v3 [1] together with the imx-drm managed allocation
> conversion from [2] as an example usage.
> a bit.
  ^^
this is a left-over of ", reordered an squashed a bit." before I decided
to move it into the list of changes below.

> 
> Changes since v3:
[...]
>  - Reorder and squash the imx-drm managed allocation conversion patches
>to use the new functions directly.

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


[PATCH v4 16/19] drm/imx: imx-tve: use drm managed resources

2020-12-08 Thread Philipp Zabel
Use drmm_simple_encoder_alloc() to align encoder memory lifetime with
the drm device. drm_encoder_cleanup() is called automatically before
the memory is freed.
Also fold imx_tve_register() into imx_tve_bind().

Signed-off-by: Philipp Zabel 
---
Changes since v3:
 - use drmm_simple_encoder_alloc()
 - fold imx_tve_register() into imx_tve_bind()
---
 drivers/gpu/drm/imx/imx-tve.c | 74 ++-
 1 file changed, 39 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c
index 3ef71f688f79..bc8c3f802a15 100644
--- a/drivers/gpu/drm/imx/imx-tve.c
+++ b/drivers/gpu/drm/imx/imx-tve.c
@@ -19,6 +19,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -99,9 +100,13 @@ enum {
TVE_MODE_VGA,
 };
 
-struct imx_tve {
+struct imx_tve_encoder {
struct drm_connector connector;
struct drm_encoder encoder;
+   struct imx_tve *tve;
+};
+
+struct imx_tve {
struct device *dev;
int mode;
int di_hsync_pin;
@@ -118,12 +123,12 @@ struct imx_tve {
 
 static inline struct imx_tve *con_to_tve(struct drm_connector *c)
 {
-   return container_of(c, struct imx_tve, connector);
+   return container_of(c, struct imx_tve_encoder, connector)->tve;
 }
 
 static inline struct imx_tve *enc_to_tve(struct drm_encoder *e)
 {
-   return container_of(e, struct imx_tve, encoder);
+   return container_of(e, struct imx_tve_encoder, encoder)->tve;
 }
 
 static void tve_enable(struct imx_tve *tve)
@@ -428,37 +433,6 @@ static int tve_clk_init(struct imx_tve *tve, void __iomem 
*base)
return 0;
 }
 
-static int imx_tve_register(struct drm_device *drm, struct imx_tve *tve)
-{
-   struct drm_encoder *encoder = &tve->encoder;
-   struct drm_connector *connector = &tve->connector;
-   int encoder_type;
-   int ret;
-
-   encoder_type = tve->mode == TVE_MODE_VGA ?
-   DRM_MODE_ENCODER_DAC : DRM_MODE_ENCODER_TVDAC;
-
-   memset(connector, 0, sizeof(*connector));
-   memset(encoder, 0, sizeof(*encoder));
-
-   ret = imx_drm_encoder_parse_of(drm, encoder, tve->dev->of_node);
-   if (ret)
-   return ret;
-
-   drm_encoder_helper_add(encoder, &imx_tve_encoder_helper_funcs);
-   drm_simple_encoder_init(drm, encoder, encoder_type);
-
-   drm_connector_helper_add(connector, &imx_tve_connector_helper_funcs);
-   drm_connector_init_with_ddc(drm, connector,
-   &imx_tve_connector_funcs,
-   DRM_MODE_CONNECTOR_VGA,
-   tve->ddc);
-
-   drm_connector_attach_encoder(connector, encoder);
-
-   return 0;
-}
-
 static void imx_tve_disable_regulator(void *data)
 {
struct imx_tve *tve = data;
@@ -508,8 +482,38 @@ static int imx_tve_bind(struct device *dev, struct device 
*master, void *data)
 {
struct drm_device *drm = data;
struct imx_tve *tve = dev_get_drvdata(dev);
+   struct imx_tve_encoder *tvee;
+   struct drm_encoder *encoder;
+   struct drm_connector *connector;
+   int encoder_type;
+   int ret;
+
+   encoder_type = tve->mode == TVE_MODE_VGA ?
+  DRM_MODE_ENCODER_DAC : DRM_MODE_ENCODER_TVDAC;
+
+   tvee = drmm_simple_encoder_alloc(drm, struct imx_tve_encoder, encoder,
+encoder_type);
+   if (IS_ERR(tvee))
+   return PTR_ERR(tvee);
+
+   tvee->tve = tve;
+   encoder = &tvee->encoder;
+   connector = &tvee->connector;
+
+   ret = imx_drm_encoder_parse_of(drm, encoder, tve->dev->of_node);
+   if (ret)
+   return ret;
+
+   drm_encoder_helper_add(encoder, &imx_tve_encoder_helper_funcs);
+
+   drm_connector_helper_add(connector, &imx_tve_connector_helper_funcs);
+   ret = drm_connector_init_with_ddc(drm, connector,
+ &imx_tve_connector_funcs,
+ DRM_MODE_CONNECTOR_VGA, tve->ddc);
+   if (ret)
+   return ret;
 
-   return imx_tve_register(drm, tve);
+   return drm_connector_attach_encoder(connector, encoder);
 }
 
 static const struct component_ops imx_tve_ops = {
-- 
2.20.1

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


[PATCH v4 03/19] drm/simple_kms_helper: add drmm_simple_encoder_alloc()

2020-12-08 Thread Philipp Zabel
Add an alternative to drm_simple_encoder_init() that allocates and
initializes a simple encoder and registers drm_encoder_cleanup() with
drmm_add_action_or_reset().

Signed-off-by: Philipp Zabel 
Reviewed-by: Laurent Pinchart 
---
Changes since v3:
 - drop drmm_simple_encoder_funcs_empty, now that encoder control
   functions are optional
---
 drivers/gpu/drm/drm_simple_kms_helper.c |  9 +
 include/drm/drm_simple_kms_helper.h | 24 
 2 files changed, 33 insertions(+)

diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c 
b/drivers/gpu/drm/drm_simple_kms_helper.c
index 743e57c1b44f..ccf0908eb82e 100644
--- a/drivers/gpu/drm/drm_simple_kms_helper.c
+++ b/drivers/gpu/drm/drm_simple_kms_helper.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -71,6 +72,14 @@ int drm_simple_encoder_init(struct drm_device *dev,
 }
 EXPORT_SYMBOL(drm_simple_encoder_init);
 
+void *__drmm_simple_encoder_alloc(struct drm_device *dev, size_t size,
+ size_t offset, int encoder_type)
+{
+   return __drmm_encoder_alloc(dev, size, offset, NULL, encoder_type,
+   NULL);
+}
+EXPORT_SYMBOL(__drmm_simple_encoder_alloc);
+
 static enum drm_mode_status
 drm_simple_kms_crtc_mode_valid(struct drm_crtc *crtc,
   const struct drm_display_mode *mode)
diff --git a/include/drm/drm_simple_kms_helper.h 
b/include/drm/drm_simple_kms_helper.h
index a026375464ff..e6dbf3161c2f 100644
--- a/include/drm/drm_simple_kms_helper.h
+++ b/include/drm/drm_simple_kms_helper.h
@@ -185,4 +185,28 @@ int drm_simple_encoder_init(struct drm_device *dev,
struct drm_encoder *encoder,
int encoder_type);
 
+void *__drmm_simple_encoder_alloc(struct drm_device *dev, size_t size,
+ size_t offset, int encoder_type);
+
+/**
+ * drmm_simple_encoder_alloc - Allocate and initialize an encoder with basic
+ * functionality.
+ * @dev: drm device
+ * @type: the type of the struct which contains struct &drm_encoder
+ * @member: the name of the &drm_encoder within @type.
+ * @encoder_type: user visible type of the encoder
+ *
+ * Allocates and initializes an encoder that has no further functionality.
+ * Settings for possible CRTC and clones are left to their initial values.
+ * Cleanup is automatically handled through registering drm_encoder_cleanup()
+ * with drmm_add_action().
+ *
+ * Returns:
+ * Pointer to new encoder, or ERR_PTR on failure.
+ */
+#define drmm_simple_encoder_alloc(dev, type, member, encoder_type) \
+   ((type *)__drmm_simple_encoder_alloc(dev, sizeof(type), \
+offsetof(type, member), \
+encoder_type))
+
 #endif /* __LINUX_DRM_SIMPLE_KMS_HELPER_H */
-- 
2.20.1

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


[PATCH v4 18/19] drm/imx: ipuv3-plane: use drm managed resources

2020-12-08 Thread Philipp Zabel
Use drmm_universal_plane_alloc() to align plane memory lifetime with
the drm device. drm_plane_cleanup() is called automatically before the
memory is freed.
Also move the call to ipu_plane_get_resources() into ipu_plane_init()
and use drm managed resources to put IPU resources automatically when
required. Handle error return values of the plane property creation
functions.

Signed-off-by: Philipp Zabel 
---
Changes since v3:
 - use drmm_universal_plane_alloc()
 - squash with patch "drm/imx: move call to ipu_plane_get_resources()
   into ipu_plane_init()"
---
 drivers/gpu/drm/imx/ipuv3-crtc.c  | 27 +---
 drivers/gpu/drm/imx/ipuv3-plane.c | 69 +++
 drivers/gpu/drm/imx/ipuv3-plane.h |  3 --
 3 files changed, 36 insertions(+), 63 deletions(-)

diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c
index 7ebd99ee3240..6ce8fa4348c9 100644
--- a/drivers/gpu/drm/imx/ipuv3-crtc.c
+++ b/drivers/gpu/drm/imx/ipuv3-crtc.c
@@ -384,29 +384,14 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
drm_crtc_init_with_planes(drm, crtc, &ipu_crtc->plane[0]->base, NULL,
  &ipu_crtc_funcs, NULL);
 
-   ret = ipu_plane_get_resources(ipu_crtc->plane[0]);
-   if (ret) {
-   dev_err(ipu_crtc->dev, "getting plane 0 resources failed with 
%d.\n",
-   ret);
-   goto err_put_resources;
-   }
-
/* If this crtc is using the DP, add an overlay plane */
if (pdata->dp >= 0 && pdata->dma[1] > 0) {
ipu_crtc->plane[1] = ipu_plane_init(drm, ipu, pdata->dma[1],
IPU_DP_FLOW_SYNC_FG,
drm_crtc_mask(&ipu_crtc->base),
DRM_PLANE_TYPE_OVERLAY);
-   if (IS_ERR(ipu_crtc->plane[1])) {
+   if (IS_ERR(ipu_crtc->plane[1]))
ipu_crtc->plane[1] = NULL;
-   } else {
-   ret = ipu_plane_get_resources(ipu_crtc->plane[1]);
-   if (ret) {
-   dev_err(ipu_crtc->dev, "getting plane 1 "
-   "resources failed with %d.\n", ret);
-   goto err_put_plane0_res;
-   }
-   }
}
 
ipu_crtc->irq = ipu_plane_irq(ipu_crtc->plane[0]);
@@ -414,18 +399,13 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
"imx_drm", ipu_crtc);
if (ret < 0) {
dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret);
-   goto err_put_plane1_res;
+   goto err_put_resources;
}
/* Only enable IRQ when we actually need it to trigger work. */
disable_irq(ipu_crtc->irq);
 
return 0;
 
-err_put_plane1_res:
-   if (ipu_crtc->plane[1])
-   ipu_plane_put_resources(ipu_crtc->plane[1]);
-err_put_plane0_res:
-   ipu_plane_put_resources(ipu_crtc->plane[0]);
 err_put_resources:
ipu_put_resources(ipu_crtc);
 
@@ -452,9 +432,6 @@ static void ipu_drm_unbind(struct device *dev, struct 
device *master,
struct ipu_crtc *ipu_crtc = dev_get_drvdata(dev);
 
ipu_put_resources(ipu_crtc);
-   if (ipu_crtc->plane[1])
-   ipu_plane_put_resources(ipu_crtc->plane[1]);
-   ipu_plane_put_resources(ipu_crtc->plane[0]);
 }
 
 static const struct component_ops ipu_crtc_ops = {
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c 
b/drivers/gpu/drm/imx/ipuv3-plane.c
index 8a4235d9d9f1..075508051b5f 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3-plane.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -142,8 +143,10 @@ drm_plane_state_to_vbo(struct drm_plane_state *state)
   fb->format->cpp[2] * x - eba;
 }
 
-void ipu_plane_put_resources(struct ipu_plane *ipu_plane)
+static void ipu_plane_put_resources(struct drm_device *dev, void *ptr)
 {
+   struct ipu_plane *ipu_plane = ptr;
+
if (!IS_ERR_OR_NULL(ipu_plane->dp))
ipu_dp_put(ipu_plane->dp);
if (!IS_ERR_OR_NULL(ipu_plane->dmfc))
@@ -154,7 +157,8 @@ void ipu_plane_put_resources(struct ipu_plane *ipu_plane)
ipu_idmac_put(ipu_plane->alpha_ch);
 }
 
-int ipu_plane_get_resources(struct ipu_plane *ipu_plane)
+static int ipu_plane_get_resources(struct drm_device *dev,
+  struct ipu_plane *ipu_plane)
 {
int ret;
int alpha_ch;
@@ -166,6 +170,10 @@ int ipu_plane_get_resources(struct ipu_plane *ipu_plane)
return ret;
}
 
+   ret = drmm_add_action_or_reset(dev, ipu_plane_put_resources, ipu_plane);
+   if (ret)
+   return ret;
+
alpha_ch = ipu_channel_alpha_channel(ipu_plane->dma);
if (alpha_ch >= 0) {
ipu_plane->alp

[PATCH v4 19/19] drm/imx: ipuv3-crtc: use drm managed resources

2020-12-08 Thread Philipp Zabel
Use use drmm_crtc_alloc_with_planes() to align crtc memory lifetime
with the drm device. drm_crtc_cleanup() is called automatically before
the memory is freed.
Also use drmm_add_action_or_reset() to make sure IPU resources are
released automatically.

Signed-off-by: Philipp Zabel 
---
Changes since v3:
 - use drmm_crtc_alloc_with_planes()
 - merge ipu_crtc_init into ipu_drm_bind
---
 drivers/gpu/drm/imx/ipuv3-crtc.c | 114 ---
 1 file changed, 43 insertions(+), 71 deletions(-)

diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c
index 6ce8fa4348c9..e6431a227feb 100644
--- a/drivers/gpu/drm/imx/ipuv3-crtc.c
+++ b/drivers/gpu/drm/imx/ipuv3-crtc.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -163,7 +164,6 @@ static void ipu_disable_vblank(struct drm_crtc *crtc)
 
 static const struct drm_crtc_funcs ipu_crtc_funcs = {
.set_config = drm_atomic_helper_set_config,
-   .destroy = drm_crtc_cleanup,
.page_flip = drm_atomic_helper_page_flip,
.reset = imx_drm_crtc_reset,
.atomic_duplicate_state = imx_drm_crtc_duplicate_state,
@@ -322,67 +322,74 @@ static const struct drm_crtc_helper_funcs 
ipu_helper_funcs = {
.atomic_enable = ipu_crtc_atomic_enable,
 };
 
-static void ipu_put_resources(struct ipu_crtc *ipu_crtc)
+static void ipu_put_resources(struct drm_device *dev, void *ptr)
 {
+   struct ipu_crtc *ipu_crtc = ptr;
+
if (!IS_ERR_OR_NULL(ipu_crtc->dc))
ipu_dc_put(ipu_crtc->dc);
if (!IS_ERR_OR_NULL(ipu_crtc->di))
ipu_di_put(ipu_crtc->di);
 }
 
-static int ipu_get_resources(struct ipu_crtc *ipu_crtc,
-   struct ipu_client_platformdata *pdata)
+static int ipu_get_resources(struct drm_device *dev, struct ipu_crtc *ipu_crtc,
+struct ipu_client_platformdata *pdata)
 {
struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
int ret;
 
ipu_crtc->dc = ipu_dc_get(ipu, pdata->dc);
-   if (IS_ERR(ipu_crtc->dc)) {
-   ret = PTR_ERR(ipu_crtc->dc);
-   goto err_out;
-   }
+   if (IS_ERR(ipu_crtc->dc))
+   return PTR_ERR(ipu_crtc->dc);
+
+   ret = drmm_add_action_or_reset(dev, ipu_put_resources, ipu_crtc);
+   if (ret)
+   return ret;
 
ipu_crtc->di = ipu_di_get(ipu, pdata->di);
-   if (IS_ERR(ipu_crtc->di)) {
-   ret = PTR_ERR(ipu_crtc->di);
-   goto err_out;
-   }
+   if (IS_ERR(ipu_crtc->di))
+   return PTR_ERR(ipu_crtc->di);
 
return 0;
-err_out:
-   ipu_put_resources(ipu_crtc);
-
-   return ret;
 }
 
-static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
-   struct ipu_client_platformdata *pdata, struct drm_device *drm)
+static int ipu_drm_bind(struct device *dev, struct device *master, void *data)
 {
-   struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
-   struct drm_crtc *crtc = &ipu_crtc->base;
+   struct ipu_client_platformdata *pdata = dev->platform_data;
+   struct ipu_soc *ipu = dev_get_drvdata(dev->parent);
+   struct drm_device *drm = data;
+   struct ipu_plane *primary_plane;
+   struct ipu_crtc *ipu_crtc;
+   struct drm_crtc *crtc;
int dp = -EINVAL;
int ret;
 
-   ret = ipu_get_resources(ipu_crtc, pdata);
-   if (ret) {
-   dev_err(ipu_crtc->dev, "getting resources failed with %d.\n",
-   ret);
-   return ret;
-   }
-
if (pdata->dp >= 0)
dp = IPU_DP_FLOW_SYNC_BG;
-   ipu_crtc->plane[0] = ipu_plane_init(drm, ipu, pdata->dma[0], dp, 0,
-   DRM_PLANE_TYPE_PRIMARY);
-   if (IS_ERR(ipu_crtc->plane[0])) {
-   ret = PTR_ERR(ipu_crtc->plane[0]);
-   goto err_put_resources;
-   }
+   primary_plane = ipu_plane_init(drm, ipu, pdata->dma[0], dp, 0,
+  DRM_PLANE_TYPE_PRIMARY);
+   if (IS_ERR(primary_plane))
+   return PTR_ERR(primary_plane);
+
+   ipu_crtc = drmm_crtc_alloc_with_planes(drm, struct ipu_crtc, base,
+  &primary_plane->base, NULL,
+  &ipu_crtc_funcs, NULL);
+   if (IS_ERR(ipu_crtc))
+   return PTR_ERR(ipu_crtc);
+
+   ipu_crtc->dev = dev;
+   ipu_crtc->plane[0] = primary_plane;
 
+   crtc = &ipu_crtc->base;
crtc->port = pdata->of_node;
drm_crtc_helper_add(crtc, &ipu_helper_funcs);
-   drm_crtc_init_with_planes(drm, crtc, &ipu_crtc->plane[0]->base, NULL,
- &ipu_crtc_funcs, NULL);
+
+   ret = ipu_get_resources(drm, ipu_crtc, pdata);
+   if (ret) {
+   dev_err(ipu_crtc->dev, "getting resources failed with %d.\n",
+   ret);
+

[PATCH v4 09/19] drm/imx: imx-tve: use local encoder and connector variables

2020-12-08 Thread Philipp Zabel
Introduce local variables for encoder and connector.
This simplifies the following commits.

Signed-off-by: Philipp Zabel 
---
 drivers/gpu/drm/imx/imx-tve.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c
index 2a8d2e32e7b4..37771073a525 100644
--- a/drivers/gpu/drm/imx/imx-tve.c
+++ b/drivers/gpu/drm/imx/imx-tve.c
@@ -430,27 +430,28 @@ static int tve_clk_init(struct imx_tve *tve, void __iomem 
*base)
 
 static int imx_tve_register(struct drm_device *drm, struct imx_tve *tve)
 {
+   struct drm_encoder *encoder = &tve->encoder;
+   struct drm_connector *connector = &tve->connector;
int encoder_type;
int ret;
 
encoder_type = tve->mode == TVE_MODE_VGA ?
DRM_MODE_ENCODER_DAC : DRM_MODE_ENCODER_TVDAC;
 
-   ret = imx_drm_encoder_parse_of(drm, &tve->encoder, tve->dev->of_node);
+   ret = imx_drm_encoder_parse_of(drm, encoder, tve->dev->of_node);
if (ret)
return ret;
 
-   drm_encoder_helper_add(&tve->encoder, &imx_tve_encoder_helper_funcs);
-   drm_simple_encoder_init(drm, &tve->encoder, encoder_type);
+   drm_encoder_helper_add(encoder, &imx_tve_encoder_helper_funcs);
+   drm_simple_encoder_init(drm, encoder, encoder_type);
 
-   drm_connector_helper_add(&tve->connector,
-   &imx_tve_connector_helper_funcs);
-   drm_connector_init_with_ddc(drm, &tve->connector,
+   drm_connector_helper_add(connector, &imx_tve_connector_helper_funcs);
+   drm_connector_init_with_ddc(drm, connector,
&imx_tve_connector_funcs,
DRM_MODE_CONNECTOR_VGA,
tve->ddc);
 
-   drm_connector_attach_encoder(&tve->connector, &tve->encoder);
+   drm_connector_attach_encoder(connector, encoder);
 
return 0;
 }
-- 
2.20.1

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


[PATCH v4 14/19] drm/imx: dw_hdmi-imx: use drm managed resources

2020-12-08 Thread Philipp Zabel
Use drmm_simple_encoder_alloc() to align encoder memory lifetime with
the drm device. drm_encoder_cleanup() is called automatically.

Signed-off-by: Philipp Zabel 
---
Changes since v3:
 - use drmm_simple_encoder_alloc()
---
 drivers/gpu/drm/imx/dw_hdmi-imx.c | 25 +
 1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c 
b/drivers/gpu/drm/imx/dw_hdmi-imx.c
index bbd0a0cd7c3d..87428fb23d9f 100644
--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c
+++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c
@@ -18,14 +18,21 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
 #include "imx-drm.h"
 
+struct imx_hdmi;
+
+struct imx_hdmi_encoder {
+   struct drm_encoder encoder;
+   struct imx_hdmi *hdmi;
+};
+
 struct imx_hdmi {
struct device *dev;
-   struct drm_encoder encoder;
struct drm_bridge *bridge;
struct dw_hdmi *hdmi;
struct regmap *regmap;
@@ -33,7 +40,7 @@ struct imx_hdmi {
 
 static inline struct imx_hdmi *enc_to_imx_hdmi(struct drm_encoder *e)
 {
-   return container_of(e, struct imx_hdmi, encoder);
+   return container_of(e, struct imx_hdmi_encoder, encoder)->hdmi;
 }
 
 static const struct dw_hdmi_mpll_config imx_mpll_cfg[] = {
@@ -185,23 +192,25 @@ static int dw_hdmi_imx_bind(struct device *dev, struct 
device *master,
void *data)
 {
struct drm_device *drm = data;
+   struct imx_hdmi_encoder *hdmi_encoder;
struct drm_encoder *encoder;
-   struct imx_hdmi *hdmi;
int ret;
 
-   hdmi = dev_get_drvdata(dev);
-   memset(&hdmi->encoder, 0, sizeof(hdmi->encoder));
+   hdmi_encoder = drmm_simple_encoder_alloc(drm, struct imx_hdmi_encoder,
+encoder, 
DRM_MODE_ENCODER_TMDS);
+   if (IS_ERR(hdmi_encoder))
+   return PTR_ERR(hdmi_encoder);
 
-   encoder = &hdmi->encoder;
+   hdmi_encoder->hdmi = dev_get_drvdata(dev);
+   encoder = &hdmi_encoder->encoder;
 
ret = imx_drm_encoder_parse_of(drm, encoder, dev->of_node);
if (ret)
return ret;
 
drm_encoder_helper_add(encoder, &dw_hdmi_imx_encoder_helper_funcs);
-   drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
 
-   return drm_bridge_attach(encoder, hdmi->bridge, NULL, 0);
+   return drm_bridge_attach(encoder, hdmi_encoder->hdmi->bridge, NULL, 0);
 }
 
 static const struct component_ops dw_hdmi_imx_ops = {
-- 
2.20.1

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


[PATCH v4 06/19] drm/imx: dw_hdmi-imx: move initialization into probe

2020-12-08 Thread Philipp Zabel
Parts of the initialization that do not require the drm device can be
done once during probe instead of possibly multiple times during bind.
The bind function only creates the encoder and attaches the bridge.

Signed-off-by: Philipp Zabel 
---
 drivers/gpu/drm/imx/dw_hdmi-imx.c | 74 +++
 1 file changed, 26 insertions(+), 48 deletions(-)

diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c 
b/drivers/gpu/drm/imx/dw_hdmi-imx.c
index d07b39b8afd2..bbd0a0cd7c3d 100644
--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c
+++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c
@@ -15,6 +15,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -25,6 +26,7 @@
 struct imx_hdmi {
struct device *dev;
struct drm_encoder encoder;
+   struct drm_bridge *bridge;
struct dw_hdmi *hdmi;
struct regmap *regmap;
 };
@@ -98,19 +100,6 @@ static const struct dw_hdmi_phy_config imx_phy_config[] = {
{ ~0UL,  0x, 0x, 0x}
 };
 
-static int dw_hdmi_imx_parse_dt(struct imx_hdmi *hdmi)
-{
-   struct device_node *np = hdmi->dev->of_node;
-
-   hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "gpr");
-   if (IS_ERR(hdmi->regmap)) {
-   dev_err(hdmi->dev, "Unable to get gpr\n");
-   return PTR_ERR(hdmi->regmap);
-   }
-
-   return 0;
-}
-
 static void dw_hdmi_imx_encoder_enable(struct drm_encoder *encoder)
 {
struct imx_hdmi *hdmi = enc_to_imx_hdmi(encoder);
@@ -195,65 +184,34 @@ MODULE_DEVICE_TABLE(of, dw_hdmi_imx_dt_ids);
 static int dw_hdmi_imx_bind(struct device *dev, struct device *master,
void *data)
 {
-   struct platform_device *pdev = to_platform_device(dev);
-   const struct dw_hdmi_plat_data *plat_data;
-   const struct of_device_id *match;
struct drm_device *drm = data;
struct drm_encoder *encoder;
struct imx_hdmi *hdmi;
int ret;
 
-   if (!pdev->dev.of_node)
-   return -ENODEV;
-
hdmi = dev_get_drvdata(dev);
-   memset(hdmi, 0, sizeof(*hdmi));
+   memset(&hdmi->encoder, 0, sizeof(hdmi->encoder));
 
-   match = of_match_node(dw_hdmi_imx_dt_ids, pdev->dev.of_node);
-   plat_data = match->data;
-   hdmi->dev = &pdev->dev;
encoder = &hdmi->encoder;
 
ret = imx_drm_encoder_parse_of(drm, encoder, dev->of_node);
if (ret)
return ret;
 
-   ret = dw_hdmi_imx_parse_dt(hdmi);
-   if (ret < 0)
-   return ret;
-
drm_encoder_helper_add(encoder, &dw_hdmi_imx_encoder_helper_funcs);
drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
 
-   hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data);
-
-   /*
-* If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
-* which would have called the encoder cleanup.  Do it manually.
-*/
-   if (IS_ERR(hdmi->hdmi)) {
-   ret = PTR_ERR(hdmi->hdmi);
-   drm_encoder_cleanup(encoder);
-   }
-
-   return ret;
-}
-
-static void dw_hdmi_imx_unbind(struct device *dev, struct device *master,
-  void *data)
-{
-   struct imx_hdmi *hdmi = dev_get_drvdata(dev);
-
-   dw_hdmi_unbind(hdmi->hdmi);
+   return drm_bridge_attach(encoder, hdmi->bridge, NULL, 0);
 }
 
 static const struct component_ops dw_hdmi_imx_ops = {
.bind   = dw_hdmi_imx_bind,
-   .unbind = dw_hdmi_imx_unbind,
 };
 
 static int dw_hdmi_imx_probe(struct platform_device *pdev)
 {
+   struct device_node *np = pdev->dev.of_node;
+   const struct of_device_id *match = of_match_node(dw_hdmi_imx_dt_ids, 
np);
struct imx_hdmi *hdmi;
 
hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
@@ -261,13 +219,33 @@ static int dw_hdmi_imx_probe(struct platform_device *pdev)
return -ENOMEM;
 
platform_set_drvdata(pdev, hdmi);
+   hdmi->dev = &pdev->dev;
+
+   hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "gpr");
+   if (IS_ERR(hdmi->regmap)) {
+   dev_err(hdmi->dev, "Unable to get gpr\n");
+   return PTR_ERR(hdmi->regmap);
+   }
+
+   hdmi->hdmi = dw_hdmi_probe(pdev, match->data);
+   if (IS_ERR(hdmi->hdmi))
+   return PTR_ERR(hdmi->hdmi);
+
+   hdmi->bridge = of_drm_find_bridge(np);
+   if (!hdmi->bridge) {
+   dev_err(hdmi->dev, "Unable to find bridge\n");
+   return -ENODEV;
+   }
 
return component_add(&pdev->dev, &dw_hdmi_imx_ops);
 }
 
 static int dw_hdmi_imx_remove(struct platform_device *pdev)
 {
+   struct imx_hdmi *hdmi = platform_get_drvdata(pdev);
+
component_del(&pdev->dev, &dw_hdmi_imx_ops);
+   dw_hdmi_remove(hdmi->hdmi);
 
return 0;
 }
-- 
2.20.1

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


[PATCH v4 10/19] drm/imx: imx-tve: move initialization into probe

2020-12-08 Thread Philipp Zabel
Parts of the initialization that do not require the drm device can be
done once during probe instead of possibly multiple times during bind.
The bind function only creates the encoder.

Signed-off-by: Philipp Zabel 
---
 drivers/gpu/drm/imx/imx-tve.c | 42 ---
 1 file changed, 19 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c
index 37771073a525..649e2f56a5da 100644
--- a/drivers/gpu/drm/imx/imx-tve.c
+++ b/drivers/gpu/drm/imx/imx-tve.c
@@ -438,6 +438,9 @@ static int imx_tve_register(struct drm_device *drm, struct 
imx_tve *tve)
encoder_type = tve->mode == TVE_MODE_VGA ?
DRM_MODE_ENCODER_DAC : DRM_MODE_ENCODER_TVDAC;
 
+   memset(connector, 0, sizeof(*connector));
+   memset(encoder, 0, sizeof(*encoder));
+
ret = imx_drm_encoder_parse_of(drm, encoder, tve->dev->of_node);
if (ret)
return ret;
@@ -503,8 +506,19 @@ static int of_get_tve_mode(struct device_node *np)
 
 static int imx_tve_bind(struct device *dev, struct device *master, void *data)
 {
-   struct platform_device *pdev = to_platform_device(dev);
struct drm_device *drm = data;
+   struct imx_tve *tve = dev_get_drvdata(dev);
+
+   return imx_tve_register(drm, tve);
+}
+
+static const struct component_ops imx_tve_ops = {
+   .bind   = imx_tve_bind,
+};
+
+static int imx_tve_probe(struct platform_device *pdev)
+{
+   struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct device_node *ddc_node;
struct imx_tve *tve;
@@ -514,8 +528,9 @@ static int imx_tve_bind(struct device *dev, struct device 
*master, void *data)
int irq;
int ret;
 
-   tve = dev_get_drvdata(dev);
-   memset(tve, 0, sizeof(*tve));
+   tve = devm_kzalloc(dev, sizeof(*tve), GFP_KERNEL);
+   if (!tve)
+   return -ENOMEM;
 
tve->dev = dev;
 
@@ -622,28 +637,9 @@ static int imx_tve_bind(struct device *dev, struct device 
*master, void *data)
if (ret)
return ret;
 
-   ret = imx_tve_register(drm, tve);
-   if (ret)
-   return ret;
-
-   return 0;
-}
-
-static const struct component_ops imx_tve_ops = {
-   .bind   = imx_tve_bind,
-};
-
-static int imx_tve_probe(struct platform_device *pdev)
-{
-   struct imx_tve *tve;
-
-   tve = devm_kzalloc(&pdev->dev, sizeof(*tve), GFP_KERNEL);
-   if (!tve)
-   return -ENOMEM;
-
platform_set_drvdata(pdev, tve);
 
-   return component_add(&pdev->dev, &imx_tve_ops);
+   return component_add(dev, &imx_tve_ops);
 }
 
 static int imx_tve_remove(struct platform_device *pdev)
-- 
2.20.1

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


[PATCH v4 02/19] drm: add drmm_encoder_alloc()

2020-12-08 Thread Philipp Zabel
Add an alternative to drm_encoder_init() that allocates and initializes
an encoder and registers drm_encoder_cleanup() with
drmm_add_action_or_reset().

Signed-off-by: Philipp Zabel 
Reviewed-by: Laurent Pinchart 
---
Changes since v3:
 - allow the funcs parameter to __drmm_encoder_alloc() to be NULL
---
 drivers/gpu/drm/drm_encoder.c | 101 ++
 include/drm/drm_encoder.h |  30 ++
 2 files changed, 108 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
index b0b86a3c08f5..cc0edb8361e8 100644
--- a/drivers/gpu/drm/drm_encoder.c
+++ b/drivers/gpu/drm/drm_encoder.c
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "drm_crtc_internal.h"
 
@@ -91,25 +92,11 @@ void drm_encoder_unregister_all(struct drm_device *dev)
}
 }
 
-/**
- * drm_encoder_init - Init a preallocated encoder
- * @dev: drm device
- * @encoder: the encoder to init
- * @funcs: callbacks for this encoder
- * @encoder_type: user visible type of the encoder
- * @name: printf style format string for the encoder name, or NULL for default 
name
- *
- * Initialises a preallocated encoder. Encoder should be subclassed as part of
- * driver encoder objects. At driver unload time drm_encoder_cleanup() should 
be
- * called from the driver's &drm_encoder_funcs.destroy hook.
- *
- * Returns:
- * Zero on success, error code on failure.
- */
-int drm_encoder_init(struct drm_device *dev,
-struct drm_encoder *encoder,
-const struct drm_encoder_funcs *funcs,
-int encoder_type, const char *name, ...)
+__printf(5, 0)
+static int __drm_encoder_init(struct drm_device *dev,
+ struct drm_encoder *encoder,
+ const struct drm_encoder_funcs *funcs,
+ int encoder_type, const char *name, va_list ap)
 {
int ret;
 
@@ -125,11 +112,7 @@ int drm_encoder_init(struct drm_device *dev,
encoder->encoder_type = encoder_type;
encoder->funcs = funcs;
if (name) {
-   va_list ap;
-
-   va_start(ap, name);
encoder->name = kvasprintf(GFP_KERNEL, name, ap);
-   va_end(ap);
} else {
encoder->name = kasprintf(GFP_KERNEL, "%s-%d",
  
drm_encoder_enum_list[encoder_type].name,
@@ -150,6 +133,36 @@ int drm_encoder_init(struct drm_device *dev,
 
return ret;
 }
+
+/**
+ * drm_encoder_init - Init a preallocated encoder
+ * @dev: drm device
+ * @encoder: the encoder to init
+ * @funcs: callbacks for this encoder
+ * @encoder_type: user visible type of the encoder
+ * @name: printf style format string for the encoder name, or NULL for default 
name
+ *
+ * Initializes a preallocated encoder. Encoder should be subclassed as part of
+ * driver encoder objects. At driver unload time drm_encoder_cleanup() should 
be
+ * called from the driver's &drm_encoder_funcs.destroy hook.
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drm_encoder_init(struct drm_device *dev,
+struct drm_encoder *encoder,
+const struct drm_encoder_funcs *funcs,
+int encoder_type, const char *name, ...)
+{
+   va_list ap;
+   int ret;
+
+   va_start(ap, name);
+   ret = __drm_encoder_init(dev, encoder, funcs, encoder_type, name, ap);
+   va_end(ap);
+
+   return ret;
+}
 EXPORT_SYMBOL(drm_encoder_init);
 
 /**
@@ -181,6 +194,48 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
 }
 EXPORT_SYMBOL(drm_encoder_cleanup);
 
+static void drmm_encoder_alloc_release(struct drm_device *dev, void *ptr)
+{
+   struct drm_encoder *encoder = ptr;
+
+   if (WARN_ON(!encoder->dev))
+   return;
+
+   drm_encoder_cleanup(encoder);
+}
+
+void *__drmm_encoder_alloc(struct drm_device *dev, size_t size, size_t offset,
+  const struct drm_encoder_funcs *funcs,
+  int encoder_type, const char *name, ...)
+{
+   void *container;
+   struct drm_encoder *encoder;
+   va_list ap;
+   int ret;
+
+   if (WARN_ON(funcs && funcs->destroy))
+   return ERR_PTR(-EINVAL);
+
+   container = drmm_kzalloc(dev, size, GFP_KERNEL);
+   if (!container)
+   return ERR_PTR(-EINVAL);
+
+   encoder = container + offset;
+
+   va_start(ap, name);
+   ret = __drm_encoder_init(dev, encoder, funcs, encoder_type, name, ap);
+   va_end(ap);
+   if (ret)
+   return ERR_PTR(ret);
+
+   ret = drmm_add_action_or_reset(dev, drmm_encoder_alloc_release, 
encoder);
+   if (ret)
+   return ERR_PTR(ret);
+
+   return container;
+}
+EXPORT_SYMBOL(__drmm_encoder_alloc);
+
 static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder)
 {
struct drm_connector *connector;

[PATCH v4 04/19] drm/plane: add drmm_universal_plane_alloc()

2020-12-08 Thread Philipp Zabel
Add an alternative to drm_universal_plane_init() that allocates
and initializes a plane and registers drm_plane_cleanup() with
drmm_add_action_or_reset().

Signed-off-by: Philipp Zabel 
Reviewed-by: Laurent Pinchart 
---
 drivers/gpu/drm/drm_plane.c | 126 +++-
 include/drm/drm_plane.h |  42 
 2 files changed, 139 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index e6231947f987..6b1261fe09fb 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -30,6 +30,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "drm_crtc_internal.h"
@@ -152,31 +153,16 @@ static int create_in_format_blob(struct drm_device *dev, 
struct drm_plane *plane
return 0;
 }
 
-/**
- * drm_universal_plane_init - Initialize a new universal plane object
- * @dev: DRM device
- * @plane: plane object to init
- * @possible_crtcs: bitmask of possible CRTCs
- * @funcs: callbacks for the new plane
- * @formats: array of supported formats (DRM_FORMAT\_\*)
- * @format_count: number of elements in @formats
- * @format_modifiers: array of struct drm_format modifiers terminated by
- *DRM_FORMAT_MOD_INVALID
- * @type: type of plane (overlay, primary, cursor)
- * @name: printf style format string for the plane name, or NULL for default 
name
- *
- * Initializes a plane object of type @type.
- *
- * Returns:
- * Zero on success, error code on failure.
- */
-int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
-uint32_t possible_crtcs,
-const struct drm_plane_funcs *funcs,
-const uint32_t *formats, unsigned int format_count,
-const uint64_t *format_modifiers,
-enum drm_plane_type type,
-const char *name, ...)
+__printf(9, 0)
+static int __drm_universal_plane_init(struct drm_device *dev,
+ struct drm_plane *plane,
+ uint32_t possible_crtcs,
+ const struct drm_plane_funcs *funcs,
+ const uint32_t *formats,
+ unsigned int format_count,
+ const uint64_t *format_modifiers,
+ enum drm_plane_type type,
+ const char *name, va_list ap)
 {
struct drm_mode_config *config = &dev->mode_config;
unsigned int format_modifier_count = 0;
@@ -237,11 +223,7 @@ int drm_universal_plane_init(struct drm_device *dev, 
struct drm_plane *plane,
}
 
if (name) {
-   va_list ap;
-
-   va_start(ap, name);
plane->name = kvasprintf(GFP_KERNEL, name, ap);
-   va_end(ap);
} else {
plane->name = kasprintf(GFP_KERNEL, "plane-%d",
drm_num_planes(dev));
@@ -286,8 +268,94 @@ int drm_universal_plane_init(struct drm_device *dev, 
struct drm_plane *plane,
 
return 0;
 }
+
+/**
+ * drm_universal_plane_init - Initialize a new universal plane object
+ * @dev: DRM device
+ * @plane: plane object to init
+ * @possible_crtcs: bitmask of possible CRTCs
+ * @funcs: callbacks for the new plane
+ * @formats: array of supported formats (DRM_FORMAT\_\*)
+ * @format_count: number of elements in @formats
+ * @format_modifiers: array of struct drm_format modifiers terminated by
+ *DRM_FORMAT_MOD_INVALID
+ * @type: type of plane (overlay, primary, cursor)
+ * @name: printf style format string for the plane name, or NULL for default 
name
+ *
+ * Initializes a plane object of type @type.
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
+uint32_t possible_crtcs,
+const struct drm_plane_funcs *funcs,
+const uint32_t *formats, unsigned int format_count,
+const uint64_t *format_modifiers,
+enum drm_plane_type type,
+const char *name, ...)
+{
+   va_list ap;
+   int ret;
+
+   va_start(ap, name);
+   ret = __drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
+formats, format_count, 
format_modifiers,
+type, name, ap);
+   va_end(ap);
+   return ret;
+}
 EXPORT_SYMBOL(drm_universal_plane_init);
 
+static void drmm_universal_plane_alloc_release(struct drm_device *dev, void 
*ptr)
+{
+   struct drm_plane *plane = ptr;
+
+   if (WARN_ON(!plane->dev))
+   return;
+
+   drm_plane_cleanup(plane);
+}
+
+void *__drmm_u

[PATCH v4 17/19] drm/imx: parallel-display: use drm managed resources

2020-12-08 Thread Philipp Zabel
Use drmm_simple_encoder_alloc() to align encoder memory lifetime with
the drm device. drm_encoder_cleanup() is called automatically before
the memory is freed.

Signed-off-by: Philipp Zabel 
---
Changes since v3:
 - use drmm_simple_encoder_alloc()
---
 drivers/gpu/drm/imx/parallel-display.c | 57 +-
 1 file changed, 29 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/imx/parallel-display.c 
b/drivers/gpu/drm/imx/parallel-display.c
index 42b44dbf45f5..9b1ec7e73c30 100644
--- a/drivers/gpu/drm/imx/parallel-display.c
+++ b/drivers/gpu/drm/imx/parallel-display.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -22,10 +23,14 @@
 
 #include "imx-drm.h"
 
-struct imx_parallel_display {
+struct imx_parallel_display_encoder {
struct drm_connector connector;
struct drm_encoder encoder;
struct drm_bridge bridge;
+   struct imx_parallel_display *pd;
+};
+
+struct imx_parallel_display {
struct device *dev;
void *edid;
u32 bus_format;
@@ -37,12 +42,12 @@ struct imx_parallel_display {
 
 static inline struct imx_parallel_display *con_to_imxpd(struct drm_connector 
*c)
 {
-   return container_of(c, struct imx_parallel_display, connector);
+   return container_of(c, struct imx_parallel_display_encoder, 
connector)->pd;
 }
 
 static inline struct imx_parallel_display *bridge_to_imxpd(struct drm_bridge 
*b)
 {
-   return container_of(b, struct imx_parallel_display, bridge);
+   return container_of(b, struct imx_parallel_display_encoder, bridge)->pd;
 }
 
 static int imx_pd_connector_get_modes(struct drm_connector *connector)
@@ -253,17 +258,25 @@ static const struct drm_bridge_funcs imx_pd_bridge_funcs 
= {
.atomic_get_output_bus_fmts = imx_pd_bridge_atomic_get_output_bus_fmts,
 };
 
-static int imx_pd_register(struct drm_device *drm,
-   struct imx_parallel_display *imxpd)
+static int imx_pd_bind(struct device *dev, struct device *master, void *data)
 {
-   struct drm_connector *connector = &imxpd->connector;
-   struct drm_encoder *encoder = &imxpd->encoder;
-   struct drm_bridge *bridge = &imxpd->bridge;
+   struct drm_device *drm = data;
+   struct imx_parallel_display *imxpd = dev_get_drvdata(dev);
+   struct imx_parallel_display_encoder *imxpd_encoder;
+   struct drm_connector *connector;
+   struct drm_encoder *encoder;
+   struct drm_bridge *bridge;
int ret;
 
-   memset(connector, 0, sizeof(*connector));
-   memset(encoder, 0, sizeof(*encoder));
-   memset(bridge, 0, sizeof(*bridge));
+   imxpd_encoder = drmm_simple_encoder_alloc(drm, struct 
imx_parallel_display_encoder,
+ encoder, 
DRM_MODE_ENCODER_NONE);
+   if (IS_ERR(imxpd_encoder))
+   return PTR_ERR(imxpd_encoder);
+
+   imxpd_encoder->pd = imxpd;
+   connector = &imxpd_encoder->connector;
+   encoder = &imxpd_encoder->encoder;
+   bridge = &imxpd_encoder->bridge;
 
ret = imx_drm_encoder_parse_of(drm, encoder, imxpd->dev->of_node);
if (ret)
@@ -276,18 +289,9 @@ static int imx_pd_register(struct drm_device *drm,
 */
connector->dpms = DRM_MODE_DPMS_OFF;
 
-   drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_NONE);
-
bridge->funcs = &imx_pd_bridge_funcs;
drm_bridge_attach(encoder, bridge, NULL, 0);
 
-   if (!imxpd->next_bridge) {
-   drm_connector_helper_add(connector,
-&imx_pd_connector_helper_funcs);
-   drm_connector_init(drm, connector, &imx_pd_connector_funcs,
-  DRM_MODE_CONNECTOR_DPI);
-   }
-
if (imxpd->next_bridge) {
ret = drm_bridge_attach(encoder, imxpd->next_bridge, bridge, 0);
if (ret < 0) {
@@ -296,20 +300,17 @@ static int imx_pd_register(struct drm_device *drm,
return ret;
}
} else {
+   drm_connector_helper_add(connector,
+&imx_pd_connector_helper_funcs);
+   drm_connector_init(drm, connector, &imx_pd_connector_funcs,
+  DRM_MODE_CONNECTOR_DPI);
+
drm_connector_attach_encoder(connector, encoder);
}
 
return 0;
 }
 
-static int imx_pd_bind(struct device *dev, struct device *master, void *data)
-{
-   struct drm_device *drm = data;
-   struct imx_parallel_display *imxpd = dev_get_drvdata(dev);
-
-   return imx_pd_register(drm, imxpd);
-}
-
 static const struct component_ops imx_pd_ops = {
.bind   = imx_pd_bind,
 };
-- 
2.20.1

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


[PATCH v4 15/19] drm/imx: imx-ldb: use drm managed resources

2020-12-08 Thread Philipp Zabel
Use drmm_simple_encoder_alloc() to align encoder memory lifetime with
the drm device. drm_encoder_cleanup() is called automatically before
the memory is freed.

Signed-off-by: Philipp Zabel 
---
Changes since v3:
 - use drmm_simple_encoder_alloc()
---
 drivers/gpu/drm/imx/imx-ldb.c | 31 ++-
 1 file changed, 22 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
index c3639cc32ddf..dbfe39e2f7f6 100644
--- a/drivers/gpu/drm/imx/imx-ldb.c
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -47,12 +48,18 @@
 #define LDB_DI1_VS_POL_ACT_LOW (1 << 10)
 #define LDB_BGREF_RMODE_INT(1 << 15)
 
+struct imx_ldb_channel;
+
+struct imx_ldb_encoder {
+   struct drm_connector connector;
+   struct drm_encoder encoder;
+   struct imx_ldb_channel *channel;
+};
+
 struct imx_ldb;
 
 struct imx_ldb_channel {
struct imx_ldb *ldb;
-   struct drm_connector connector;
-   struct drm_encoder encoder;
 
/* Defines what is connected to the ldb, only one at a time */
struct drm_panel *panel;
@@ -70,12 +77,12 @@ struct imx_ldb_channel {
 
 static inline struct imx_ldb_channel *con_to_imx_ldb_ch(struct drm_connector 
*c)
 {
-   return container_of(c, struct imx_ldb_channel, connector);
+   return container_of(c, struct imx_ldb_encoder, connector)->channel;
 }
 
 static inline struct imx_ldb_channel *enc_to_imx_ldb_ch(struct drm_encoder *e)
 {
-   return container_of(e, struct imx_ldb_channel, encoder);
+   return container_of(e, struct imx_ldb_encoder, encoder)->channel;
 }
 
 struct bus_mux {
@@ -411,12 +418,19 @@ static int imx_ldb_register(struct drm_device *drm,
struct imx_ldb_channel *imx_ldb_ch)
 {
struct imx_ldb *ldb = imx_ldb_ch->ldb;
-   struct drm_connector *connector = &imx_ldb_ch->connector;
-   struct drm_encoder *encoder = &imx_ldb_ch->encoder;
+   struct imx_ldb_encoder *ldb_encoder;
+   struct drm_connector *connector;
+   struct drm_encoder *encoder;
int ret;
 
-   memset(connector, 0, sizeof(*connector));
-   memset(encoder, 0, sizeof(*encoder));
+   ldb_encoder = drmm_simple_encoder_alloc(drm, struct imx_ldb_encoder,
+   encoder, DRM_MODE_ENCODER_LVDS);
+   if (IS_ERR(ldb_encoder))
+   return PTR_ERR(ldb_encoder);
+
+   ldb_encoder->channel = imx_ldb_ch;
+   connector = &ldb_encoder->connector;
+   encoder = &ldb_encoder->encoder;
 
ret = imx_drm_encoder_parse_of(drm, encoder, imx_ldb_ch->child);
if (ret)
@@ -433,7 +447,6 @@ static int imx_ldb_register(struct drm_device *drm,
}
 
drm_encoder_helper_add(encoder, &imx_ldb_encoder_helper_funcs);
-   drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_LVDS);
 
if (imx_ldb_ch->bridge) {
ret = drm_bridge_attach(encoder, imx_ldb_ch->bridge, NULL, 0);
-- 
2.20.1

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


[PATCH v4 12/19] drm/imx: parallel-display: use local bridge and connector variables

2020-12-08 Thread Philipp Zabel
Use local variables for bridge and connector.
This simplifies the following commits.

Signed-off-by: Philipp Zabel 
---
 drivers/gpu/drm/imx/parallel-display.c | 20 ++--
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/imx/parallel-display.c 
b/drivers/gpu/drm/imx/parallel-display.c
index 2eb8df4697df..16e576f8ee83 100644
--- a/drivers/gpu/drm/imx/parallel-display.c
+++ b/drivers/gpu/drm/imx/parallel-display.c
@@ -256,7 +256,9 @@ static const struct drm_bridge_funcs imx_pd_bridge_funcs = {
 static int imx_pd_register(struct drm_device *drm,
struct imx_parallel_display *imxpd)
 {
+   struct drm_connector *connector = &imxpd->connector;
struct drm_encoder *encoder = &imxpd->encoder;
+   struct drm_bridge *bridge = &imxpd->bridge;
int ret;
 
ret = imx_drm_encoder_parse_of(drm, encoder, imxpd->dev->of_node);
@@ -268,31 +270,29 @@ static int imx_pd_register(struct drm_device *drm,
 * immediately since the current state is ON
 * at this point.
 */
-   imxpd->connector.dpms = DRM_MODE_DPMS_OFF;
+   connector->dpms = DRM_MODE_DPMS_OFF;
 
drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_NONE);
 
-   imxpd->bridge.funcs = &imx_pd_bridge_funcs;
-   drm_bridge_attach(encoder, &imxpd->bridge, NULL, 0);
+   bridge->funcs = &imx_pd_bridge_funcs;
+   drm_bridge_attach(encoder, bridge, NULL, 0);
 
if (!imxpd->next_bridge) {
-   drm_connector_helper_add(&imxpd->connector,
-   &imx_pd_connector_helper_funcs);
-   drm_connector_init(drm, &imxpd->connector,
-  &imx_pd_connector_funcs,
+   drm_connector_helper_add(connector,
+&imx_pd_connector_helper_funcs);
+   drm_connector_init(drm, connector, &imx_pd_connector_funcs,
   DRM_MODE_CONNECTOR_DPI);
}
 
if (imxpd->next_bridge) {
-   ret = drm_bridge_attach(encoder, imxpd->next_bridge,
-   &imxpd->bridge, 0);
+   ret = drm_bridge_attach(encoder, imxpd->next_bridge, bridge, 0);
if (ret < 0) {
dev_err(imxpd->dev, "failed to attach bridge: %d\n",
ret);
return ret;
}
} else {
-   drm_connector_attach_encoder(&imxpd->connector, encoder);
+   drm_connector_attach_encoder(connector, encoder);
}
 
return 0;
-- 
2.20.1

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


[PATCH v4 01/19] drm/encoder: make encoder control functions optional

2020-12-08 Thread Philipp Zabel
Simple managed encoders do not require the .destroy callback,
make the whole funcs structure optional.

Signed-off-by: Philipp Zabel 
Reviewed-by: Laurent Pinchart 
---
New in v4.
---
 drivers/gpu/drm/drm_encoder.c | 4 ++--
 drivers/gpu/drm/drm_mode_config.c | 5 +++--
 include/drm/drm_encoder.h | 2 +-
 3 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
index e555281f43d4..b0b86a3c08f5 100644
--- a/drivers/gpu/drm/drm_encoder.c
+++ b/drivers/gpu/drm/drm_encoder.c
@@ -72,7 +72,7 @@ int drm_encoder_register_all(struct drm_device *dev)
int ret = 0;
 
drm_for_each_encoder(encoder, dev) {
-   if (encoder->funcs->late_register)
+   if (encoder->funcs && encoder->funcs->late_register)
ret = encoder->funcs->late_register(encoder);
if (ret)
return ret;
@@ -86,7 +86,7 @@ void drm_encoder_unregister_all(struct drm_device *dev)
struct drm_encoder *encoder;
 
drm_for_each_encoder(encoder, dev) {
-   if (encoder->funcs->early_unregister)
+   if (encoder->funcs && encoder->funcs->early_unregister)
encoder->funcs->early_unregister(encoder);
}
 }
diff --git a/drivers/gpu/drm/drm_mode_config.c 
b/drivers/gpu/drm/drm_mode_config.c
index f1affc1bb679..87e144155456 100644
--- a/drivers/gpu/drm/drm_mode_config.c
+++ b/drivers/gpu/drm/drm_mode_config.c
@@ -195,7 +195,7 @@ void drm_mode_config_reset(struct drm_device *dev)
crtc->funcs->reset(crtc);
 
drm_for_each_encoder(encoder, dev)
-   if (encoder->funcs->reset)
+   if (encoder->funcs && encoder->funcs->reset)
encoder->funcs->reset(encoder);
 
drm_connector_list_iter_begin(dev, &conn_iter);
@@ -487,7 +487,8 @@ void drm_mode_config_cleanup(struct drm_device *dev)
 
list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list,
 head) {
-   encoder->funcs->destroy(encoder);
+   if (encoder->funcs)
+   encoder->funcs->destroy(encoder);
}
 
drm_connector_list_iter_begin(dev, &conn_iter);
diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
index 5dfa5f7a80a7..833123637fbf 100644
--- a/include/drm/drm_encoder.h
+++ b/include/drm/drm_encoder.h
@@ -89,7 +89,7 @@ struct drm_encoder_funcs {
  * @head: list management
  * @base: base KMS object
  * @name: human readable name, can be overwritten by the driver
- * @funcs: control functions
+ * @funcs: control functions, can be NULL for simple managed encoders
  * @helper_private: mid-layer private data
  *
  * CRTCs drive pixels to encoders, which convert them into signals
-- 
2.20.1

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


  1   2   3   >