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

2021-11-30 Thread Christian König

Am 01.12.21 um 04:22 schrieb Zhou Qingyang:

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

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

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

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

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

Fixes: cc9e67e3d700 ("drm/radeon: fix VM IB handling")
Reported-by: kernel test robot 
Signed-off-by: Zhou Qingyang 
---
Changes in v2:
   -  Initialize the variables to silence warning


What warning do you get? Double checking the code that shouldn't be 
necessary and is usually rather frowned upon.


Thanks,
Christian.



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

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

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

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

file_priv->driver_priv = NULL;

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

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

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

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

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

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




Re: [RFC PATCH 1/2] dma-fence: Avoid establishing a locking order between fence classes

2021-11-30 Thread Christian König

Am 30.11.21 um 20:27 schrieb Thomas Hellström:


On 11/30/21 19:12, Thomas Hellström wrote:

On Tue, 2021-11-30 at 16:02 +0100, Christian König wrote:

Am 30.11.21 um 15:35 schrieb Thomas Hellström:

On Tue, 2021-11-30 at 14:26 +0100, Christian König wrote:

Am 30.11.21 um 13:56 schrieb Thomas Hellström:

On 11/30/21 13:42, Christian König wrote:

Am 30.11.21 um 13:31 schrieb Thomas Hellström:

[SNIP]

Other than that, I didn't investigate the nesting fails
enough to
say I can accurately review this. :)

Basically the problem is that within enable_signaling()
which
is
called with the dma_fence lock held, we take the dma_fence
lock
of
another fence. If that other fence is a dma_fence_array, or
a
dma_fence_chain which in turn tries to lock a
dma_fence_array
we hit
a splat.

Yeah, I already thought that you constructed something like
that.

You get the splat because what you do here is illegal, you
can't
mix
dma_fence_array and dma_fence_chain like this or you can end
up
in a
stack corruption.

Hmm. Ok, so what is the stack corruption, is it that the
enable_signaling() will end up with endless recursion? If so,
wouldn't
it be more usable we break that recursion chain and allow a
more
general use?

The problem is that this is not easily possible for
dma_fence_array
containers. Just imagine that you drop the last reference to the
containing fences during dma_fence_array destruction if any of
the
contained fences is another container you can easily run into
recursion
and with that stack corruption.

Indeed, that would require some deeper surgery.


That's one of the major reasons I came up with the
dma_fence_chain
container. This one you can chain any number of elements together
without running into any recursion.


Also what are the mixing rules between these? Never use a
dma-fence-chain as one of the array fences and never use a
dma-fence-array as a dma-fence-chain fence?

You can't add any other container to a dma_fence_array, neither
other
dma_fence_array instances nor dma_fence_chain instances.

IIRC at least technically a dma_fence_chain can contain a
dma_fence_array if you absolutely need that, but Daniel, Jason
and I
already had the same discussion a while back and came to the
conclusion
to avoid that as well if possible.

Yes, this is actually the use-case. But what I can't easily
guarantee
is that that dma_fence_chain isn't fed into a dma_fence_array
somewhere
else. How do you typically avoid that?

Meanwhile I guess I need to take a different approach in the driver
to
avoid this altogether.

Jason and I came up with a deep dive iterator for his use case, but I
think we don't want to use that any more after my dma_resv rework.

In other words when you need to create a new dma_fence_array you
flatten
out the existing construct which is at worst case
dma_fence_chain->dma_fence_array->dma_fence.

Ok, Are there any cross-driver contract here, Like every driver using a
dma_fence_array need to check for dma_fence_chain and flatten like
above?


So far we only discussed that on the mailing list but haven't made any 
documentation for that.




/Thomas


Oh, and a follow up question:

If there was a way to break the recursion on final put() (using the 
same basic approach as patch 2 in this series uses to break recursion 
in enable_signaling()), so that none of these containers did require 
any special treatment, would it be worth pursuing? I guess it might be 
possible by having the callbacks drop the references rather than the 
loop in the final put. + a couple of changes in code iterating over 
the fence pointers.


That won't really help, you just move the recursion from the final put 
into the callback.


What could be possible is to use an work item for any possible 
operation, e.g. enabling, signaling and destruction. But in the last 
discussion everybody agreed that it is better to just flatten out the array.


Christian.




/Thomas




Regards,
Christian.


/Thomas



Regards,
Christian.


/Thomas





Regards,
Christian.


But I'll update the commit message with a typical splat.

/Thomas




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

2021-11-30 Thread Christian König

Am 30.11.21 um 16:57 schrieb Zhou Qingyang:

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

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

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

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

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

Fixes: cc9e67e3d700 ("drm/radeon: fix VM IB handling")
Signed-off-by: Zhou Qingyang 


Reviewed-by: Christian König 


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

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

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

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

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

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

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

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

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

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




Re: [PATCH v2 1/2] drm/msm: Allocate msm_drm_private early and pass it as driver data

2021-11-30 Thread kernel test robot
Hi AngeloGioacchino,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on drm/drm-next]
[also build test WARNING on next-20211130]
[cannot apply to v5.16-rc3]
[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/AngeloGioacchino-Del-Regno/drm-msm-Fix-dsi-bridge-probe/20211130-221304
base:   git://anongit.freedesktop.org/drm/drm drm-next
config: csky-randconfig-c004-20211128 
(https://download.01.org/0day-ci/archive/20211201/202112011405.wn79h7q3-...@intel.com/config)
compiler: csky-linux-gcc (GCC) 11.2.0

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


cocci warnings: (new ones prefixed by >>)
>> drivers/gpu/drm/msm/msm_drv.c:412:1-6: WARNING: invalid free of devm_ 
>> allocated data

vim +412 drivers/gpu/drm/msm/msm_drv.c

2aa31767259722 Sean Paul   2019-05-24  384  
98659487b845c0 Abhinav Kumar   2021-04-16  385  
msm_disp_snapshot_destroy(ddev);
98659487b845c0 Abhinav Kumar   2021-04-16  386  
2b669875332fbd Archit Taneja   2016-05-02  387  
drm_mode_config_cleanup(ddev);
c8afe684c95cd1 Rob Clark   2013-06-26  388  
2b669875332fbd Archit Taneja   2016-05-02  389  
pm_runtime_get_sync(dev);
f026e431cf8611 Thomas Zimmermann   2021-08-03  390  msm_irq_uninstall(ddev);
2b669875332fbd Archit Taneja   2016-05-02  391  
pm_runtime_put_sync(dev);
c8afe684c95cd1 Rob Clark   2013-06-26  392  
16976085a114ae Archit Taneja   2016-11-03  393  if (kms && kms->funcs)
c8afe684c95cd1 Rob Clark   2013-06-26  394  
kms->funcs->destroy(kms);
c8afe684c95cd1 Rob Clark   2013-06-26  395  
871d812aa43e63 Rob Clark   2013-11-16  396  if (priv->vram.paddr) {
00085f1efa387a Krzysztof Kozlowski 2016-08-03  397  unsigned long 
attrs = DMA_ATTR_NO_KERNEL_MAPPING;
871d812aa43e63 Rob Clark   2013-11-16  398  
drm_mm_takedown(>vram.mm);
2b669875332fbd Archit Taneja   2016-05-02  399  
dma_free_attrs(dev, priv->vram.size, NULL,
00085f1efa387a Krzysztof Kozlowski 2016-08-03  400 
priv->vram.paddr, attrs);
871d812aa43e63 Rob Clark   2013-11-16  401  }
871d812aa43e63 Rob Clark   2013-11-16  402  
2b669875332fbd Archit Taneja   2016-05-02  403  
component_unbind_all(dev, ddev);
060530f1ea6740 Rob Clark   2014-03-03  404  
bc3220be22577e Rajesh Yadav2018-06-21  405  if (mdss && mdss->funcs)
bc3220be22577e Rajesh Yadav2018-06-21  406  
mdss->funcs->destroy(ddev);
0a6030d224d3a4 Archit Taneja   2016-05-08  407  
2b669875332fbd Archit Taneja   2016-05-02  408  ddev->dev_private = 
NULL;
4d8dc2dfae2c48 Thomas Zimmermann   2018-09-26  409  drm_dev_put(ddev);
c8afe684c95cd1 Rob Clark   2013-06-26  410  
2aa31767259722 Sean Paul   2019-05-24  411  
destroy_workqueue(priv->wq);
c8afe684c95cd1 Rob Clark   2013-06-26 @412  kfree(priv);
c8afe684c95cd1 Rob Clark   2013-06-26  413  
c8afe684c95cd1 Rob Clark   2013-06-26  414  return 0;
c8afe684c95cd1 Rob Clark   2013-06-26  415  }
c8afe684c95cd1 Rob Clark   2013-06-26  416  

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


Re: [PATCH] drm: rcar-du: add modifiers support

2021-11-30 Thread Esaki Tomohito

Hi Daniel-san,

On 2021/11/30 22:20, Daniel Stone wrote:

On Tue, 30 Nov 2021 at 08:44, Esaki Tomohito  wrote:

On 2021/11/18 23:05, Laurent Pinchart wrote:

On Thu, Nov 18, 2021 at 01:02:11PM +, Daniel Stone wrote:

Laurent's concern is that the DRM core should handle this rather than
open-coding in every driver, which I agree with. Some drivers (e.g.
radeon, maybe legacy NV?) do not support modifiers, and _also_ do
magic inference of the actual layout of the underlying buffer.
However, these drivers are legacy and we do not accept any new
addition of inferring layout without modifiers.

I think the best way forward here is:
- add a new mode_config.cannot_support_modifiers flag, and enable
this in radeon (plus any other drivers in the same boat)


Is there an easy way to identify the drivers that need this ?


Should I find a driver that has not use drm_plane_funcs?


I don't think there's a good way to systematically audit it. The only
two I know are radeon (i.e. pre-amdgpu) and nouveau (pre-nv50), both
of which pass no modifiers to drm_universal_plane_init(), but do have
magic back channels to communicate tiling information. If anyone knows
of any others, well, I guess we'll find out. :)

Thanks for the information.
I checked the driver code with the tiling keyword, and it seems that 
these are the only two drivers that require cannot_support_modifiers.

I will start creating patches for these two drivers first.

--
Best Regards
Tomohito Esaki


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

2021-11-30 Thread Laurent Pinchart
From: LUU HOAI 

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

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

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

Changes since v1:

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

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

[PATCH v3 1/2] dt-bindings: display: bridge: Add binding for R-Car MIPI DSI/CSI-2 TX

2021-11-30 Thread Laurent Pinchart
The R-Car MIPI DSI/CSI-2 TX is embedded in the Renesas R-Car V3U SoC. It
can operate in either DSI or CSI-2 mode, with up to four data lanes.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Kieran Bingham 
Acked-by: Sam Ravnborg 
Reviewed-by: Rob Herring 
Reviewed-by: Geert Uytterhoeven 
---
 .../display/bridge/renesas,dsi-csi2-tx.yaml   | 118 ++
 MAINTAINERS   |   1 +
 2 files changed, 119 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/bridge/renesas,dsi-csi2-tx.yaml

diff --git 
a/Documentation/devicetree/bindings/display/bridge/renesas,dsi-csi2-tx.yaml 
b/Documentation/devicetree/bindings/display/bridge/renesas,dsi-csi2-tx.yaml
new file mode 100644
index ..afeeb967393d
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/renesas,dsi-csi2-tx.yaml
@@ -0,0 +1,118 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/bridge/renesas,dsi-csi2-tx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas R-Car MIPI DSI/CSI-2 Encoder
+
+maintainers:
+  - Laurent Pinchart 
+
+description: |
+  This binding describes the MIPI DSI/CSI-2 encoder embedded in the Renesas
+  R-Car V3U SoC. The encoder can operate in either DSI or CSI-2 mode, with up
+  to four data lanes.
+
+properties:
+  compatible:
+enum:
+  - renesas,r8a779a0-dsi-csi2-tx# for V3U
+
+  reg:
+maxItems: 1
+
+  clocks:
+items:
+  - description: Functional clock
+  - description: DSI (and CSI-2) functional clock
+  - description: PLL reference clock
+
+  clock-names:
+items:
+  - const: fck
+  - const: dsi
+  - const: pll
+
+  power-domains:
+maxItems: 1
+
+  resets:
+maxItems: 1
+
+  ports:
+$ref: /schemas/graph.yaml#/properties/ports
+
+properties:
+  port@0:
+$ref: /schemas/graph.yaml#/properties/port
+description: Parallel input port
+
+  port@1:
+$ref: /schemas/graph.yaml#/$defs/port-base
+unevaluatedProperties: false
+description: DSI/CSI-2 output port
+
+properties:
+  endpoint:
+$ref: /schemas/media/video-interfaces.yaml#
+unevaluatedProperties: false
+
+properties:
+  data-lanes:
+minItems: 1
+maxItems: 4
+
+required:
+  - data-lanes
+
+required:
+  - port@0
+  - port@1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - power-domains
+  - resets
+  - ports
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+#include 
+
+dsi0: dsi-encoder@fed8 {
+compatible = "renesas,r8a779a0-dsi-csi2-tx";
+reg = <0xfed8 0x1>;
+power-domains = < R8A779A0_PD_ALWAYS_ON>;
+clocks = < CPG_MOD 415>,
+ < CPG_CORE R8A779A0_CLK_DSI>,
+ < CPG_CORE R8A779A0_CLK_CP>;
+clock-names = "fck", "dsi", "pll";
+resets = < 415>;
+
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+
+port@0 {
+reg = <0>;
+dsi0_in: endpoint {
+remote-endpoint = <_out_dsi0>;
+};
+};
+
+port@1 {
+reg = <1>;
+dsi0_out: endpoint {
+data-lanes = <1 2>;
+remote-endpoint = <_in>;
+};
+};
+};
+};
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index 53b859d10de6..caf359403a97 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6413,6 +6413,7 @@ L:dri-devel@lists.freedesktop.org
 L: linux-renesas-...@vger.kernel.org
 S: Supported
 T: git git://linuxtv.org/pinchartl/media drm/du/next
+F: 
Documentation/devicetree/bindings/display/bridge/renesas,dsi-csi2-tx.yaml
 F: Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.yaml
 F: Documentation/devicetree/bindings/display/bridge/renesas,lvds.yaml
 F: Documentation/devicetree/bindings/display/renesas,du.yaml
-- 
Regards,

Laurent Pinchart



[PATCH v3 0/2] R-Car DU: Add DSI encoder driver for V3U

2021-11-30 Thread Laurent Pinchart
Hello,

This patch series adds a driver for the DSI encoder found in the R-Car
V3U SoC, which is the first SoC in the family that supports DSI.

The driver is based on an implementation from the BSP written by Luu
Hoai, with lots of further rework. If anyone is interested in the
history, a broken down v1 is available from [1].

The driver has been successfully tested on the Falcon board, which
connects an SN65DSI86 to the output of the DSI encoder. Further patches
are needed for the ti-sn65dsi86 driver to enable usage in plain DP
(non-eDP) mode, as the Falcon board has a mini-DP connector wired to the
output of the SN65DSI86. This is work in progress (see [2]).

[1] 
https://lore.kernel.org/linux-renesas-soc/189c7a07-29cd-39f4-1dec-56aa94c11...@ideasonboard.com/T/#mafbe130386cbc8326f85cad46860813516ef4a80
[2] 
https://lore.kernel.org/linux-renesas-soc/20210322030128.2283-1-laurent.pinchart+rene...@ideasonboard.com/

LUU HOAI (1):
  drm: rcar-du: Add R-Car DSI driver

Laurent Pinchart (1):
  dt-bindings: display: bridge: Add binding for R-Car MIPI DSI/CSI-2 TX

 .../display/bridge/renesas,dsi-csi2-tx.yaml   | 118 +++
 MAINTAINERS   |   1 +
 drivers/gpu/drm/rcar-du/Kconfig   |   7 +
 drivers/gpu/drm/rcar-du/Makefile  |   1 +
 drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c   | 817 ++
 drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h  | 172 
 6 files changed, 1116 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/bridge/renesas,dsi-csi2-tx.yaml
 create mode 100644 drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c
 create mode 100644 drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h


base-commit: c18c889bb5e014e144716044991112f16833
-- 
Regards,

Laurent Pinchart



Re: [PATCH v2 2/2] drm: rcar-du: mipi-dsi: Use devm_drm_of_get_bridge helper

2021-11-30 Thread Laurent Pinchart
Hi Kieran,

On Tue, Nov 30, 2021 at 04:52:19PM +, Kieran Bingham wrote:
> Quoting Kieran Bingham (2021-11-30 16:25:13)
> > Instead of open coding the calls for
> >   drm_of_find_panel_or_bridge()
> >   devm_drm_panel_bridge_add()
> > 
> > use the devm_drm_of_get_bridge() helper directly.
> > 
> > Signed-off-by: Kieran Bingham 
> > ---
> > v2:
> >  - New patch
> > 
> >  drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c | 19 ---
> >  1 file changed, 4 insertions(+), 15 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c 
> > b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c
> > index 0a9f197ef62c..1dfe20d3d0f2 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c
> > @@ -637,7 +637,7 @@ static int rcar_mipi_dsi_host_attach(struct 
> > mipi_dsi_host *host,
> > struct mipi_dsi_device *device)
> >  {
> > struct rcar_mipi_dsi *dsi = host_to_rcar_mipi_dsi(host);
> > -   struct drm_panel *panel;
> > +   struct device *dev = dsi->dev;
> > int ret;
> >  
> > if (device->lanes > dsi->num_data_lanes)
> > @@ -646,20 +646,9 @@ static int rcar_mipi_dsi_host_attach(struct 
> > mipi_dsi_host *host,
> > dsi->lanes = device->lanes;
> > dsi->format = device->format;
> >  
> > -   ret = drm_of_find_panel_or_bridge(dsi->dev->of_node, 1, 0, ,
> > - >next_bridge);
> > -   if (ret) {
> > -   dev_err_probe(dsi->dev, ret, "could not find next 
> > bridge\n");
> > -   return ret;
> > -   }
> > -
> > -   if (!dsi->next_bridge) {
> > -   dsi->next_bridge = devm_drm_panel_bridge_add(dsi->dev, 
> > panel);
> > -   if (IS_ERR(dsi->next_bridge)) {
> > -   dev_err(dsi->dev, "failed to create panel 
> > bridge\n");
> > -   return PTR_ERR(dsi->next_bridge);
> > -   }
> > -   }
> > +   dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0);
> > +   if (IS_ERR(dsi->next_bridge))
> > +   return PTR_ERR(dsi->next_bridge);
> 
> I did make a change here to make this:
> 
>   dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0);
>   if (IS_ERR(dsi->next_bridge)) {
>   dev_err(dev, "failed to get next bridge\n");
>   return PTR_ERR(dsi->next_bridge);
>   }
> 
> But it seems I got out of sequence and saved out the wrong patch ;-(
> 
> If you think it's better with the error print, please add it while
> squashing, or if you really need, I can send an updated patch and
> retest.

I think an error message is useful, yes. I'll add it manually.

> >  
> > /* Initialize the DRM bridge. */
> > dsi->bridge.funcs = _mipi_dsi_bridge_ops;

-- 
Regards,

Laurent Pinchart


Re: [PATCH v2 1/2] drm: rcar-du: mipi-dsi: Support bridge probe ordering

2021-11-30 Thread Laurent Pinchart
Hi Kieran,

Thank you for the patch.

On Tue, Nov 30, 2021 at 04:25:12PM +, Kieran Bingham wrote:
> The bridge probe ordering for DSI devices has been clarified and further
> documented in

I've read the document and


:-)

> To support connecting with the SN65DSI86 device after commit c3b75d4734cb
> ("drm/bridge: sn65dsi86: Register and attach our DSI device at probe"),
> update to the new probe ordering to remove a perpetual -EPROBE_DEFER
> loop between the two devices.
> 
> Signed-off-by: Kieran Bingham 
> 
> ---
> v2
> - Remove now unused panel variable from rcar_mipi_dsi_probe()
> 
>  drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c | 49 +
>  1 file changed, 26 insertions(+), 23 deletions(-)
> 
> diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c 
> b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c
> index 50e922328fed..0a9f197ef62c 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c
> @@ -637,6 +637,8 @@ static int rcar_mipi_dsi_host_attach(struct mipi_dsi_host 
> *host,
>   struct mipi_dsi_device *device)
>  {
>   struct rcar_mipi_dsi *dsi = host_to_rcar_mipi_dsi(host);
> + struct drm_panel *panel;
> + int ret;
>  
>   if (device->lanes > dsi->num_data_lanes)
>   return -EINVAL;
> @@ -644,12 +646,36 @@ static int rcar_mipi_dsi_host_attach(struct 
> mipi_dsi_host *host,
>   dsi->lanes = device->lanes;
>   dsi->format = device->format;
>  
> + ret = drm_of_find_panel_or_bridge(dsi->dev->of_node, 1, 0, ,
> +   >next_bridge);
> + if (ret) {
> + dev_err_probe(dsi->dev, ret, "could not find next bridge\n");

dev_err_probe() should only be used in probe(), and this function isn't
guaranteed to be called at probe time only.

This isn't a big deal as the next patch fixes this, and both will be
squashed. Furthermore, rcar_mipi_dsi_host_attach() should only be called
when the DSI device gets registered, which should happen after it
registers its bridge, so I don't think we can see a probe deferral here.

Other than that the patch looks fine, I'll squash it with the DSI
driver.

> + return ret;
> + }
> +
> + if (!dsi->next_bridge) {
> + dsi->next_bridge = devm_drm_panel_bridge_add(dsi->dev, panel);
> + if (IS_ERR(dsi->next_bridge)) {
> + dev_err(dsi->dev, "failed to create panel bridge\n");
> + return PTR_ERR(dsi->next_bridge);
> + }
> + }
> +
> + /* Initialize the DRM bridge. */
> + dsi->bridge.funcs = _mipi_dsi_bridge_ops;
> + dsi->bridge.of_node = dsi->dev->of_node;
> + drm_bridge_add(>bridge);
> +
>   return 0;
>  }
>  
>  static int rcar_mipi_dsi_host_detach(struct mipi_dsi_host *host,
>   struct mipi_dsi_device *device)
>  {
> + struct rcar_mipi_dsi *dsi = host_to_rcar_mipi_dsi(host);
> +
> + drm_bridge_remove(>bridge);
> +
>   return 0;
>  }
>  
> @@ -731,7 +757,6 @@ static int rcar_mipi_dsi_get_clocks(struct rcar_mipi_dsi 
> *dsi)
>  static int rcar_mipi_dsi_probe(struct platform_device *pdev)
>  {
>   struct rcar_mipi_dsi *dsi;
> - struct drm_panel *panel;
>   struct resource *mem;
>   int ret;
>  
> @@ -764,21 +789,6 @@ static int rcar_mipi_dsi_probe(struct platform_device 
> *pdev)
>   return PTR_ERR(dsi->rstc);
>   }
>  
> - ret = drm_of_find_panel_or_bridge(dsi->dev->of_node, 1, 0, ,
> -   >next_bridge);
> - if (ret) {
> - dev_err_probe(dsi->dev, ret, "could not find next bridge\n");
> - return ret;
> - }
> -
> - if (!dsi->next_bridge) {
> - dsi->next_bridge = devm_drm_panel_bridge_add(dsi->dev, panel);
> - if (IS_ERR(dsi->next_bridge)) {
> - dev_err(dsi->dev, "failed to create panel bridge\n");
> - return PTR_ERR(dsi->next_bridge);
> - }
> - }
> -
>   /* Initialize the DSI host. */
>   dsi->host.dev = dsi->dev;
>   dsi->host.ops = _mipi_dsi_host_ops;
> @@ -786,11 +796,6 @@ static int rcar_mipi_dsi_probe(struct platform_device 
> *pdev)
>   if (ret < 0)
>   return ret;
>  
> - /* Initialize the DRM bridge. */
> - dsi->bridge.funcs = _mipi_dsi_bridge_ops;
> - dsi->bridge.of_node = dsi->dev->of_node;
> - drm_bridge_add(>bridge);
> -
>   return 0;
>  }
>  
> @@ -798,8 +803,6 @@ static int rcar_mipi_dsi_remove(struct platform_device 
> *pdev)
>  {
>   struct rcar_mipi_dsi *dsi = platform_get_drvdata(pdev);
>  
> - drm_bridge_remove(>bridge);
> -
>   mipi_dsi_host_unregister(>host);
>  
>   return 0;

-- 
Regards,

Laurent Pinchart


Re: [PATCH] drm/msm/dpu: fix exception in error path

2021-11-30 Thread Bjorn Andersson
On Thu 25 Nov 12:01 CST 2021, Dmitry Baryshkov wrote:

> In case of DPU probe failure, prevent the following NULL pointer
> exception:
> 
> [3.976112] Unable to handle kernel NULL pointer dereference at virtual 
> address 0030
> [3.984983] Mem abort info:
> [3.987800]   ESR = 0x9604
> [3.990891]   EC = 0x25: DABT (current EL), IL = 32 bits
> [3.996251]   SET = 0, FnV = 0
> [3.996254]   EA = 0, S1PTW = 0
> [3.996257]   FSC = 0x04: level 0 translation fault
> [3.996260] Data abort info:
> [3.996262]   ISV = 0, ISS = 0x0004
> [4.005229]   CM = 0, WnR = 0
> [4.028893] [0030] user address but active_mm is swapper
> [4.035305] Internal error: Oops: 9604 [#1] SMP
> [4.040223] Modules linked in:
> [4.043317] CPU: 1 PID: 50 Comm: kworker/u16:2 Not tainted 
> 5.16.0-rc1-00036-g6d4bafcbb015-dirty #166
> [4.052518] Hardware name: Thundercomm Dragonboard 845c (DT)
> [4.058224] Workqueue: events_unbound deferred_probe_work_func
> [4.064105] pstate: 6045 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> [4.071124] pc : dpu_core_irq_uninstall+0x28/0x100
> [4.075960] lr : dpu_core_irq_uninstall+0x24/0x100
> [4.080793] sp : 80001057b990
> [4.084138] x29: 80001057b990 x28: 7653c0a41c00 x27: 
> 7653c0926480
> [4.091330] x26: b90d5d262ad0 x25: 7653c4b2e980 x24: 
> 7653c0046080
> [4.098520] x23: 7653c099a810 x22: 7653c5a65800 x21: 
> 7653c5a65080
> [4.105711] x20: 7653c5a65800 x19: 7653c0046080 x18: 
> 0034
> [4.112902] x17: 0038 x16: 0005 x15: 
> 000c
> [4.120095] x14: 024c x13: 7653c2f90358 x12: 
> 
> [4.127287] x11: 7653c2f903b0 x10: 09c0 x9 : 
> 80001057b180
> [4.134477] x8 : 80001057b404 x7 :  x6 : 
> 7653c5a5f190
> [4.141669] x5 : 80001057b890 x4 :  x3 : 
> 7653c5a5f0f4
> [4.148859] x2 : 7653c2f5 x1 :  x0 : 
> 
> [4.156052] Call trace:
> [4.158525]  dpu_core_irq_uninstall+0x28/0x100
> [4.163004]  dpu_irq_uninstall+0x10/0x20
> [4.166963]  msm_drm_uninit.isra.0+0xe0/0x1b0
> [4.171353]  msm_drm_bind+0x278/0x5f0
> [4.175043]  try_to_bring_up_master+0x164/0x1d0
> [4.179610]  __component_add+0xa0/0x170
> [4.183482]  component_add+0x14/0x20
> [4.187086]  dsi_dev_probe+0x1c/0x30
> [4.190691]  platform_probe+0x68/0xe0
> [4.194382]  really_probe.part.0+0x9c/0x30c
> [4.198601]  __driver_probe_device+0x98/0x144
> [4.202990]  driver_probe_device+0x44/0x15c
> [4.207208]  __device_attach_driver+0xb4/0x120
> [4.211685]  bus_for_each_drv+0x78/0xd0
> [4.215549]  __device_attach+0xdc/0x184
> [4.219412]  device_initial_probe+0x14/0x20
> [4.223630]  bus_probe_device+0x9c/0xa4
> [4.227503]  deferred_probe_work_func+0x88/0xc0
> [4.232075]  process_one_work+0x1e8/0x380
> [4.236126]  worker_thread+0x280/0x520
> [4.239902]  kthread+0x168/0x174
> [4.243166]  ret_from_fork+0x10/0x20
> [4.246778] Code: f9442400 91004000 940188b9 f9430660 (b9403001)
> [4.252925] ---[ end trace b470a50cd7b5e606 ]---
> 
> Signed-off-by: Dmitry Baryshkov 
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c 
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
> index d2b6dca487e3..fc1b6c47c93d 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
> @@ -575,6 +575,9 @@ void dpu_core_irq_uninstall(struct dpu_kms *dpu_kms)
>  {
>   int i;
>  
> + if (!dpu_kms->hw_intr)
> + return;

I would rather see that we fix msm_drm_init() to nicely unroll things in
a more granular fashion instead of handle all types of errors with the
big hammer that msm_drm_uninit() provides.

Regards,
Bjorn

> +
>   pm_runtime_get_sync(_kms->pdev->dev);
>   for (i = 0; i < dpu_kms->hw_intr->total_irqs; i++)
>   if (!list_empty(_kms->hw_intr->irq_cb_tbl[i]))
> -- 
> 2.33.0
> 


[PATCH] drm/exynos: drop the use of label from exynos_dsi_register_te_irq

2021-11-30 Thread Inki Dae
Dropped the use of 'out' label from exynos_dsi_register_te_irq function
because the label isn't needed. This patch returns an error in each
error case directly not going to 'out' label.

With this patch build warning[1] is also fixed, which was reported by
kernel test robot 

[1] https://www.spinics.net/lists/dri-devel/msg323803.html

Reported-by: kernel test robot 
Signed-off-by: Inki Dae 
---
 drivers/gpu/drm/exynos/exynos_drm_dsi.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index b0b1acb7e712..32a36572b894 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -1338,7 +1338,7 @@ static int exynos_dsi_register_te_irq(struct exynos_dsi 
*dsi,
if (IS_ERR(dsi->te_gpio)) {
dev_err(dsi->dev, "gpio request failed with %ld\n",
PTR_ERR(dsi->te_gpio));
-   goto out;
+   return PTR_ERR(dsi->te_gpio);
}
 
te_gpio_irq = gpiod_to_irq(dsi->te_gpio);
@@ -1348,11 +1348,10 @@ static int exynos_dsi_register_te_irq(struct exynos_dsi 
*dsi,
if (ret) {
dev_err(dsi->dev, "request interrupt failed with %d\n", ret);
gpiod_put(dsi->te_gpio);
-   goto out;
+   return ret;
}
 
-out:
-   return ret;
+   return 0;
 }
 
 static void exynos_dsi_unregister_te_irq(struct exynos_dsi *dsi)
-- 
2.25.1



Re: [Intel-gfx] [PATCH v5] drm/i915: Re-use i915 macros for checking PTEs

2021-11-30 Thread Lucas De Marchi

On Thu, Nov 18, 2021 at 12:54:32PM -0800, Michael Cheng wrote:

Certain gen8 ppgtt/gtt functions are using _PAGE_RW and _PAGE_PRESENT to check
bits 0 and 1 for PTEs. These macros are defined per architectures, and some
architectures do not have these defined (like arm64). This patch replaces these
two macros with their i915 equivalent implementation.

Signed-off-by: Michael Cheng 



Reviewed-by: Lucas De Marchi 

thanks
Lucas De Marchi


Re: [PATCH v4 2/2] drm/i915: Use to_root_gt() to refer to the root tile

2021-11-30 Thread Lucas De Marchi

On Wed, Dec 01, 2021 at 12:41:08AM +0200, Andi Shyti wrote:

Hi Lucas,

fist of all thanks for taking a look at this, I was eagerly
waiting for reviewers.

On Tue, Nov 30, 2021 at 01:07:30PM -0800, Lucas De Marchi wrote:

On Sun, Nov 28, 2021 at 01:09:26PM +0200, Andi Shyti wrote:
> Starting from a patch from Matt to_root_gt() returns the
> reference to the root tile in order to abstract the root tile
> from th callers.
>
> Being the root tile identified as tile '0', embed the id in the
> name so that i915->gt becomes i915->gt0.
>
> The renaming has been mostly done with the following command and
> some manual fixes.
>
> sed -i -e sed -i 's/\\->gt\./\_root_gt(i915)\->/g' \
>-e sed -i 's/\_priv\->gt\./\_root_gt(dev_priv)\->/g' \
>-e 's/\_priv\->gt/to_root_gt(dev_priv)/g' \
>-e 's/\\->gt/to_root_gt(i915)/g' \
>-e 's/dev_priv\->gt\./to_root_gt(dev_priv)\->/g' \
>-e 's/i915\->gt\./to_root_gt(i915)\->/g' \
>`find drivers/gpu/drm/i915/ -name *.[ch]`
>
> Two small changes have been added to this commit:
>
> 1. intel_reset_gpu() in intel_display.c retreives the gt from
>to_scanout_gt()
> 2. in set_scheduler_caps() the gt is taken from the engine and
>not from i915.

Ideally the non-automatic changes should be in separate patches, before
the ones that can be done by automation. Because then it becomes easier
to apply the final result without conflicts.


OK


This is quite a big diff to merge in one go. Looking at the pending
patches from Michal however I see he had similar changes, split in
sensible chunks..  Could you split your version like that? at least
gt/gem and display would be good to have separate. Or sync with Michal
on how to proceed with these versions Here are his patches:

drm/i915: Remove i915->ggtt
drm/i915: Use to_gt() helper for GGTT accesses
drm/i915: Use to_gt() helper
drm/i915/gvt: Use to_gt() helper
drm/i915/gem: Use to_gt() helper
drm/i915/gt: Use to_gt() helper
drm/i915/display: Use to_gt() helper
drm/i915: Introduce to_gt() helper


I understand... will follow this approach.


This first patch also removed the `struct intel_gt *gt = to_gt(pool)`,
that would otherwise be a leftover in 
drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c


One difference from Michal patch is that I am not using the
wrapper

 to_gt(...)

but

 to_root_gt(...)

which was introduced by Matt. To me sounds more meaningful as it
specifies that we are really looking for the root tile and not
any tile.


yes, I think it makes sense, too.  Michal, any comment?  I think you
also had other plans to get the root gt by another helper... ?

Lucas De Marchi


Re: [PATCH v4 1/2] drm/i915: Store backpointer to GT in uncore

2021-11-30 Thread Andi Shyti
Hi,

ping! (Lucas?)

> We now support a per-gt uncore, yet we're not able to infer which GT
> we're operating upon.  Let's store a backpointer for now.
> 
> Signed-off-by: Michał Winiarski 
> Signed-off-by: Matt Roper 
> Reviewed-by: Andi Shyti 
> Signed-off-by: Andi Shyti 

can we merge this, meanwhile?

Andi


[PATCH v16 39/40] ARM: tegra: Add Memory Client resets to Tegra30 GR2D, GR3D and Host1x

2021-11-30 Thread Dmitry Osipenko
Memory access must be blocked before hardware reset is asserted and before
power is gated, otherwise a serious hardware fault is inevitable. Add
reset for memory clients to the GR2D, GR3D and Host1x nodes.

Tested-by: Peter Geis  # Ouya T30
Tested-by: Matt Merhar  # Ouya T30
Signed-off-by: Dmitry Osipenko 
---
 arch/arm/boot/dts/tegra30.dtsi | 14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index 0ac6cb315e8d..96d1c5688248 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -123,8 +123,8 @@ host1x@5000 {
interrupt-names = "syncpt", "host1x";
clocks = <_car TEGRA30_CLK_HOST1X>;
clock-names = "host1x";
-   resets = <_car 28>;
-   reset-names = "host1x";
+   resets = <_car 28>, < TEGRA30_MC_RESET_HC>;
+   reset-names = "host1x", "mc";
iommus = < TEGRA_SWGROUP_HC>;
power-domains = <_heg>;
operating-points-v2 = <_dvfs_opp_table>;
@@ -190,8 +190,8 @@ gr2d@5414 {
reg = <0x5414 0x0004>;
interrupts = ;
clocks = <_car TEGRA30_CLK_GR2D>;
-   resets = <_car 21>;
-   reset-names = "2d";
+   resets = <_car 21>, < TEGRA30_MC_RESET_2D>;
+   reset-names = "2d", "mc";
power-domains = <_heg>;
operating-points-v2 = <_dvfs_opp_table>;
 
@@ -205,8 +205,10 @@ gr3d@5418 {
 <_car TEGRA30_CLK_GR3D2>;
clock-names = "3d", "3d2";
resets = <_car 24>,
-<_car 98>;
-   reset-names = "3d", "3d2";
+<_car 98>,
+< TEGRA30_MC_RESET_3D>,
+< TEGRA30_MC_RESET_3D2>;
+   reset-names = "3d", "3d2", "mc", "mc2";
power-domains = <_3d0>, <_3d1>;
power-domain-names = "3d0", "3d1";
operating-points-v2 = <_dvfs_opp_table>;
-- 
2.33.1



[PATCH v16 20/40] bus: tegra-gmi: Add runtime PM and OPP support

2021-11-30 Thread Dmitry Osipenko
The GMI bus on Tegra belongs to the core power domain and we're going to
enable GENPD support for the core domain. Now GMI must be resumed using
runtime PM API in order to initialize the GMI power state. Add runtime PM
and OPP support to the GMI driver.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/bus/tegra-gmi.c | 50 -
 1 file changed, 44 insertions(+), 6 deletions(-)

diff --git a/drivers/bus/tegra-gmi.c b/drivers/bus/tegra-gmi.c
index a6570789f7af..35b59f92fa66 100644
--- a/drivers/bus/tegra-gmi.c
+++ b/drivers/bus/tegra-gmi.c
@@ -13,8 +13,11 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
+#include 
+
 #define TEGRA_GMI_CONFIG   0x00
 #define TEGRA_GMI_CONFIG_GOBIT(31)
 #define TEGRA_GMI_BUS_WIDTH_32BIT  BIT(30)
@@ -54,9 +57,10 @@ static int tegra_gmi_enable(struct tegra_gmi *gmi)
 {
int err;
 
-   err = clk_prepare_enable(gmi->clk);
-   if (err < 0) {
-   dev_err(gmi->dev, "failed to enable clock: %d\n", err);
+   pm_runtime_enable(gmi->dev);
+   err = pm_runtime_resume_and_get(gmi->dev);
+   if (err) {
+   pm_runtime_disable(gmi->dev);
return err;
}
 
@@ -83,7 +87,9 @@ static void tegra_gmi_disable(struct tegra_gmi *gmi)
writel(config, gmi->base + TEGRA_GMI_CONFIG);
 
reset_control_assert(gmi->rst);
-   clk_disable_unprepare(gmi->clk);
+
+   pm_runtime_put_sync_suspend(gmi->dev);
+   pm_runtime_force_suspend(gmi->dev);
 }
 
 static int tegra_gmi_parse_dt(struct tegra_gmi *gmi)
@@ -213,6 +219,7 @@ static int tegra_gmi_probe(struct platform_device *pdev)
if (!gmi)
return -ENOMEM;
 
+   platform_set_drvdata(pdev, gmi);
gmi->dev = dev;
 
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -232,6 +239,10 @@ static int tegra_gmi_probe(struct platform_device *pdev)
return PTR_ERR(gmi->rst);
}
 
+   err = devm_tegra_core_dev_init_opp_table_common(>dev);
+   if (err)
+   return err;
+
err = tegra_gmi_parse_dt(gmi);
if (err)
return err;
@@ -247,8 +258,6 @@ static int tegra_gmi_probe(struct platform_device *pdev)
return err;
}
 
-   platform_set_drvdata(pdev, gmi);
-
return 0;
 }
 
@@ -262,6 +271,34 @@ static int tegra_gmi_remove(struct platform_device *pdev)
return 0;
 }
 
+static int __maybe_unused tegra_gmi_runtime_resume(struct device *dev)
+{
+   struct tegra_gmi *gmi = dev_get_drvdata(dev);
+   int err;
+
+   err = clk_prepare_enable(gmi->clk);
+   if (err < 0) {
+   dev_err(gmi->dev, "failed to enable clock: %d\n", err);
+   return err;
+   }
+
+   return 0;
+}
+
+static int __maybe_unused tegra_gmi_runtime_suspend(struct device *dev)
+{
+   struct tegra_gmi *gmi = dev_get_drvdata(dev);
+
+   clk_disable_unprepare(gmi->clk);
+
+   return 0;
+}
+
+static const struct dev_pm_ops tegra_gmi_pm = {
+   SET_RUNTIME_PM_OPS(tegra_gmi_runtime_suspend, tegra_gmi_runtime_resume,
+  NULL)
+};
+
 static const struct of_device_id tegra_gmi_id_table[] = {
{ .compatible = "nvidia,tegra20-gmi", },
{ .compatible = "nvidia,tegra30-gmi", },
@@ -275,6 +312,7 @@ static struct platform_driver tegra_gmi_driver = {
.driver = {
.name   = "tegra-gmi",
.of_match_table = tegra_gmi_id_table,
+   .pm = _gmi_pm,
},
 };
 module_platform_driver(tegra_gmi_driver);
-- 
2.33.1



[PATCH v16 18/40] drm/tegra: Consolidate runtime PM management of older UAPI codepath

2021-11-30 Thread Dmitry Osipenko
Move runtime PM management of older UAPI code paths into the common place.
This removes boilerplate code from client drivers.

Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/tegra/drm.c   | 11 ++-
 drivers/gpu/drm/tegra/gr2d.c  | 10 +-
 drivers/gpu/drm/tegra/gr3d.c  | 10 +-
 drivers/gpu/drm/tegra/nvdec.c | 14 +-
 drivers/gpu/drm/tegra/vic.c   | 12 +---
 5 files changed, 14 insertions(+), 43 deletions(-)

diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index 2e7da2a7505d..dc04ce329be3 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -116,6 +117,7 @@ static int tegra_drm_open(struct drm_device *drm, struct 
drm_file *filp)
 static void tegra_drm_context_free(struct tegra_drm_context *context)
 {
context->client->ops->close_channel(context);
+   pm_runtime_put(context->client->base.dev);
kfree(context);
 }
 
@@ -427,13 +429,20 @@ static int tegra_client_open(struct tegra_drm_file *fpriv,
 {
int err;
 
+   err = pm_runtime_resume_and_get(client->base.dev);
+   if (err)
+   return err;
+
err = client->ops->open_channel(client, context);
-   if (err < 0)
+   if (err < 0) {
+   pm_runtime_put(client->base.dev);
return err;
+   }
 
err = idr_alloc(>legacy_contexts, context, 1, 0, GFP_KERNEL);
if (err < 0) {
client->ops->close_channel(context);
+   pm_runtime_put(client->base.dev);
return err;
}
 
diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
index 2382def93923..e3bb4c99ed39 100644
--- a/drivers/gpu/drm/tegra/gr2d.c
+++ b/drivers/gpu/drm/tegra/gr2d.c
@@ -127,17 +127,10 @@ static int gr2d_open_channel(struct tegra_drm_client 
*client,
 struct tegra_drm_context *context)
 {
struct gr2d *gr2d = to_gr2d(client);
-   int err;
-
-   err = pm_runtime_resume_and_get(client->base.dev);
-   if (err)
-   return err;
 
context->channel = host1x_channel_get(gr2d->channel);
-   if (!context->channel) {
-   pm_runtime_put(client->base.dev);
+   if (!context->channel)
return -ENOMEM;
-   }
 
return 0;
 }
@@ -145,7 +138,6 @@ static int gr2d_open_channel(struct tegra_drm_client 
*client,
 static void gr2d_close_channel(struct tegra_drm_context *context)
 {
host1x_channel_put(context->channel);
-   pm_runtime_put(context->client->base.dev);
 }
 
 static int gr2d_is_addr_reg(struct device *dev, u32 class, u32 offset)
diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c
index 032d71365494..a1fd3113ea96 100644
--- a/drivers/gpu/drm/tegra/gr3d.c
+++ b/drivers/gpu/drm/tegra/gr3d.c
@@ -136,17 +136,10 @@ static int gr3d_open_channel(struct tegra_drm_client 
*client,
 struct tegra_drm_context *context)
 {
struct gr3d *gr3d = to_gr3d(client);
-   int err;
-
-   err = pm_runtime_resume_and_get(client->base.dev);
-   if (err)
-   return err;
 
context->channel = host1x_channel_get(gr3d->channel);
-   if (!context->channel) {
-   pm_runtime_put(client->base.dev);
+   if (!context->channel)
return -ENOMEM;
-   }
 
return 0;
 }
@@ -154,7 +147,6 @@ static int gr3d_open_channel(struct tegra_drm_client 
*client,
 static void gr3d_close_channel(struct tegra_drm_context *context)
 {
host1x_channel_put(context->channel);
-   pm_runtime_put(context->client->base.dev);
 }
 
 static int gr3d_is_addr_reg(struct device *dev, u32 class, u32 offset)
diff --git a/drivers/gpu/drm/tegra/nvdec.c b/drivers/gpu/drm/tegra/nvdec.c
index 15f036e09e5c..79e1e88203cf 100644
--- a/drivers/gpu/drm/tegra/nvdec.c
+++ b/drivers/gpu/drm/tegra/nvdec.c
@@ -291,29 +291,17 @@ static int nvdec_open_channel(struct tegra_drm_client 
*client,
struct tegra_drm_context *context)
 {
struct nvdec *nvdec = to_nvdec(client);
-   int err;
-
-   err = pm_runtime_get_sync(nvdec->dev);
-   if (err < 0) {
-   pm_runtime_put(nvdec->dev);
-   return err;
-   }
 
context->channel = host1x_channel_get(nvdec->channel);
-   if (!context->channel) {
-   pm_runtime_put(nvdec->dev);
+   if (!context->channel)
return -ENOMEM;
-   }
 
return 0;
 }
 
 static void nvdec_close_channel(struct tegra_drm_context *context)
 {
-   struct nvdec *nvdec = to_nvdec(context->client);
-
host1x_channel_put(context->channel);
-   pm_runtime_put(nvdec->dev);
 }
 
 static const struct tegra_drm_client_ops nvdec_ops = {
diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c
index 9622ca96c539..7886740bcbf2 100644
--- 

[PATCH v16 14/40] drm/tegra: gr3d: Support generic power domain and runtime PM

2021-11-30 Thread Dmitry Osipenko
Add runtime power management and support generic power domains.

Reviewed-by: Ulf Hansson 
Tested-by: Peter Geis  # Ouya T30
Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20 and TK1 T124
Tested-by: Matt Merhar  # Ouya T30
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/tegra/gr3d.c | 363 +--
 1 file changed, 305 insertions(+), 58 deletions(-)

diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c
index 24442ade0da3..032d71365494 100644
--- a/drivers/gpu/drm/tegra/gr3d.c
+++ b/drivers/gpu/drm/tegra/gr3d.c
@@ -5,32 +5,47 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 #include 
 
+#include 
 #include 
 
 #include "drm.h"
 #include "gem.h"
 #include "gr3d.h"
 
+enum {
+   RST_MC,
+   RST_GR3D,
+   RST_MC2,
+   RST_GR3D2,
+   RST_GR3D_MAX,
+};
+
 struct gr3d_soc {
unsigned int version;
+   unsigned int num_clocks;
+   unsigned int num_resets;
 };
 
 struct gr3d {
struct tegra_drm_client client;
struct host1x_channel *channel;
-   struct clk *clk_secondary;
-   struct clk *clk;
-   struct reset_control *rst_secondary;
-   struct reset_control *rst;
 
const struct gr3d_soc *soc;
+   struct clk_bulk_data *clocks;
+   unsigned int nclocks;
+   struct reset_control_bulk_data resets[RST_GR3D_MAX];
+   unsigned int nresets;
 
DECLARE_BITMAP(addr_regs, GR3D_NUM_REGS);
 };
@@ -65,15 +80,22 @@ static int gr3d_init(struct host1x_client *client)
goto free;
}
 
+   pm_runtime_enable(client->dev);
+   pm_runtime_use_autosuspend(client->dev);
+   pm_runtime_set_autosuspend_delay(client->dev, 200);
+
err = tegra_drm_register_client(dev->dev_private, drm);
if (err < 0) {
dev_err(client->dev, "failed to register client: %d\n", err);
-   goto detach;
+   goto disable_rpm;
}
 
return 0;
 
-detach:
+disable_rpm:
+   pm_runtime_dont_use_autosuspend(client->dev);
+   pm_runtime_force_suspend(client->dev);
+
host1x_client_iommu_detach(client);
 free:
host1x_syncpt_put(client->syncpts[0]);
@@ -93,10 +115,15 @@ static int gr3d_exit(struct host1x_client *client)
if (err < 0)
return err;
 
+   pm_runtime_dont_use_autosuspend(client->dev);
+   pm_runtime_force_suspend(client->dev);
+
host1x_client_iommu_detach(client);
host1x_syncpt_put(client->syncpts[0]);
host1x_channel_put(gr3d->channel);
 
+   gr3d->channel = NULL;
+
return 0;
 }
 
@@ -109,10 +136,17 @@ static int gr3d_open_channel(struct tegra_drm_client 
*client,
 struct tegra_drm_context *context)
 {
struct gr3d *gr3d = to_gr3d(client);
+   int err;
+
+   err = pm_runtime_resume_and_get(client->base.dev);
+   if (err)
+   return err;
 
context->channel = host1x_channel_get(gr3d->channel);
-   if (!context->channel)
+   if (!context->channel) {
+   pm_runtime_put(client->base.dev);
return -ENOMEM;
+   }
 
return 0;
 }
@@ -120,6 +154,7 @@ static int gr3d_open_channel(struct tegra_drm_client 
*client,
 static void gr3d_close_channel(struct tegra_drm_context *context)
 {
host1x_channel_put(context->channel);
+   pm_runtime_put(context->client->base.dev);
 }
 
 static int gr3d_is_addr_reg(struct device *dev, u32 class, u32 offset)
@@ -155,14 +190,20 @@ static const struct tegra_drm_client_ops gr3d_ops = {
 
 static const struct gr3d_soc tegra20_gr3d_soc = {
.version = 0x20,
+   .num_clocks = 1,
+   .num_resets = 2,
 };
 
 static const struct gr3d_soc tegra30_gr3d_soc = {
.version = 0x30,
+   .num_clocks = 2,
+   .num_resets = 4,
 };
 
 static const struct gr3d_soc tegra114_gr3d_soc = {
.version = 0x35,
+   .num_clocks = 1,
+   .num_resets = 2,
 };
 
 static const struct of_device_id tegra_gr3d_match[] = {
@@ -278,69 +319,216 @@ static const u32 gr3d_addr_regs[] = {
GR3D_GLOBAL_SAMP23SURFADDR(15),
 };
 
-static int gr3d_probe(struct platform_device *pdev)
+static int gr3d_power_up_legacy_domain(struct device *dev, const char *name,
+  unsigned int id)
 {
-   struct device_node *np = pdev->dev.of_node;
-   struct host1x_syncpt **syncpts;
-   struct gr3d *gr3d;
+   struct gr3d *gr3d = dev_get_drvdata(dev);
+   struct reset_control *reset;
+   struct clk *clk;
unsigned int i;
int err;
 
-   gr3d = devm_kzalloc(>dev, sizeof(*gr3d), GFP_KERNEL);
-   if (!gr3d)
-   return -ENOMEM;
-
-   gr3d->soc = of_device_get_match_data(>dev);
+   /*
+* Tegra20 device-tree doesn't specify 3d clock name and there is only
+* one clock for Tegra20. Tegra30+ 

[PATCH v16 32/40] soc/tegra: pmc: Rename core power domain

2021-11-30 Thread Dmitry Osipenko
CORE power domain uses name of device-tree node, which is inconsistent with
the names of PMC domains. Set the name to "core" to make it consistent.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/soc/tegra/pmc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index e1fae1a5e36a..de6234ec4f9b 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -1369,7 +1369,7 @@ static int tegra_pmc_core_pd_add(struct tegra_pmc *pmc, 
struct device_node *np)
if (!genpd)
return -ENOMEM;
 
-   genpd->name = np->name;
+   genpd->name = "core";
genpd->set_performance_state = tegra_pmc_core_pd_set_performance_state;
genpd->opp_to_performance_state = 
tegra_pmc_core_pd_opp_to_performance_state;
 
-- 
2.33.1



[PATCH v16 22/40] mmc: sdhci-tegra: Add runtime PM and OPP support

2021-11-30 Thread Dmitry Osipenko
The SDHCI on Tegra belongs to the core power domain and we're going to
enable GENPD support for the core domain. Now SDHCI must be resumed using
runtime PM API in order to initialize the SDHCI power state. The SDHCI
clock rate must be changed using OPP API that will reconfigure the power
domain performance state in accordance to the rate. Add runtime PM and OPP
support to the SDHCI driver.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/mmc/host/sdhci-tegra.c | 81 +++---
 1 file changed, 65 insertions(+), 16 deletions(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index a5001875876b..6435a75142a6 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -15,6 +15,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -24,6 +26,8 @@
 #include 
 #include 
 
+#include 
+
 #include "sdhci-pltfm.h"
 #include "cqhci.h"
 
@@ -760,7 +764,9 @@ static void tegra_sdhci_set_clock(struct sdhci_host *host, 
unsigned int clock)
 {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
+   struct device *dev = mmc_dev(host->mmc);
unsigned long host_clk;
+   int err;
 
if (!clock)
return sdhci_set_clock(host, clock);
@@ -778,7 +784,12 @@ static void tegra_sdhci_set_clock(struct sdhci_host *host, 
unsigned int clock)
 * from clk_get_rate() is used.
 */
host_clk = tegra_host->ddr_signaling ? clock * 2 : clock;
-   clk_set_rate(pltfm_host->clk, host_clk);
+
+   err = dev_pm_opp_set_rate(dev, host_clk);
+   if (err)
+   dev_err(dev, "failed to set clk rate to %luHz: %d\n",
+   host_clk, err);
+
tegra_host->curr_clk_rate = host_clk;
if (tegra_host->ddr_signaling)
host->max_clk = host_clk;
@@ -1705,7 +1716,6 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
   "failed to get clock\n");
goto err_clk_get;
}
-   clk_prepare_enable(clk);
pltfm_host->clk = clk;
 
tegra_host->rst = devm_reset_control_get_exclusive(>dev,
@@ -1716,15 +1726,24 @@ static int sdhci_tegra_probe(struct platform_device 
*pdev)
goto err_rst_get;
}
 
-   rc = reset_control_assert(tegra_host->rst);
+   rc = devm_tegra_core_dev_init_opp_table_common(>dev);
if (rc)
goto err_rst_get;
 
+   pm_runtime_enable(>dev);
+   rc = pm_runtime_resume_and_get(>dev);
+   if (rc)
+   goto err_pm_get;
+
+   rc = reset_control_assert(tegra_host->rst);
+   if (rc)
+   goto err_rst_assert;
+
usleep_range(2000, 4000);
 
rc = reset_control_deassert(tegra_host->rst);
if (rc)
-   goto err_rst_get;
+   goto err_rst_assert;
 
usleep_range(2000, 4000);
 
@@ -1736,8 +1755,11 @@ static int sdhci_tegra_probe(struct platform_device 
*pdev)
 
 err_add_host:
reset_control_assert(tegra_host->rst);
+err_rst_assert:
+   pm_runtime_put_sync_suspend(>dev);
+err_pm_get:
+   pm_runtime_disable(>dev);
 err_rst_get:
-   clk_disable_unprepare(pltfm_host->clk);
 err_clk_get:
clk_disable_unprepare(tegra_host->tmclk);
 err_power_req:
@@ -1756,19 +1778,38 @@ static int sdhci_tegra_remove(struct platform_device 
*pdev)
 
reset_control_assert(tegra_host->rst);
usleep_range(2000, 4000);
-   clk_disable_unprepare(pltfm_host->clk);
-   clk_disable_unprepare(tegra_host->tmclk);
 
+   pm_runtime_put_sync_suspend(>dev);
+   pm_runtime_force_suspend(>dev);
+
+   clk_disable_unprepare(tegra_host->tmclk);
sdhci_pltfm_free(pdev);
 
return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int __maybe_unused sdhci_tegra_suspend(struct device *dev)
+static int __maybe_unused sdhci_tegra_runtime_suspend(struct device *dev)
 {
struct sdhci_host *host = dev_get_drvdata(dev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+   clk_disable_unprepare(pltfm_host->clk);
+
+   return 0;
+}
+
+static int __maybe_unused sdhci_tegra_runtime_resume(struct device *dev)
+{
+   struct sdhci_host *host = dev_get_drvdata(dev);
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+   return clk_prepare_enable(pltfm_host->clk);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int sdhci_tegra_suspend(struct device *dev)
+{
+   struct sdhci_host *host = dev_get_drvdata(dev);
int ret;
 
if (host->mmc->caps2 & MMC_CAP2_CQE) {
@@ -1783,17 +1824,22 @@ static int __maybe_unused sdhci_tegra_suspend(struct 
device *dev)
return ret;
}
 
-   clk_disable_unprepare(pltfm_host->clk);
+   ret = pm_runtime_force_suspend(dev);
+   if (ret) {
+   sdhci_resume_host(host);
+ 

[PATCH v16 17/40] drm/tegra: submit: Remove pm_runtime_enabled() checks

2021-11-30 Thread Dmitry Osipenko
Runtime PM is now universally available, make it mandatory by removing
the pm_runtime_enabled() checks.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/tegra/submit.c | 16 ++--
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/tegra/submit.c b/drivers/gpu/drm/tegra/submit.c
index 1ba4d539da06..6d6dd8c35475 100644
--- a/drivers/gpu/drm/tegra/submit.c
+++ b/drivers/gpu/drm/tegra/submit.c
@@ -504,10 +504,8 @@ static void release_job(struct host1x_job *job)
kfree(job_data->used_mappings);
kfree(job_data);
 
-   if (pm_runtime_enabled(client->base.dev)) {
-   pm_runtime_mark_last_busy(client->base.dev);
-   pm_runtime_put_autosuspend(client->base.dev);
-   }
+   pm_runtime_mark_last_busy(client->base.dev);
+   pm_runtime_put_autosuspend(client->base.dev);
 }
 
 int tegra_drm_ioctl_channel_submit(struct drm_device *drm, void *data,
@@ -591,12 +589,10 @@ int tegra_drm_ioctl_channel_submit(struct drm_device 
*drm, void *data,
}
 
/* Boot engine. */
-   if (pm_runtime_enabled(context->client->base.dev)) {
-   err = pm_runtime_resume_and_get(context->client->base.dev);
-   if (err < 0) {
-   SUBMIT_ERR(context, "could not power up engine: %d", 
err);
-   goto unpin_job;
-   }
+   err = pm_runtime_resume_and_get(context->client->base.dev);
+   if (err < 0) {
+   SUBMIT_ERR(context, "could not power up engine: %d", err);
+   goto unpin_job;
}
 
job->user_data = job_data;
-- 
2.33.1



[PATCH v16 37/40] ARM: tegra: Add OPP tables and power domains to Tegra30 device-trees

2021-11-30 Thread Dmitry Osipenko
Add OPP tables and power domains to all peripheral devices which
support power management on Tegra30 SoC.

Tested-by: Peter Geis  # Ouya T30
Tested-by: Matt Merhar  # Ouya T30
Signed-off-by: Dmitry Osipenko 
---
 arch/arm/boot/dts/tegra20-trimslice.dts   |2 +-
 .../tegra30-asus-nexus7-grouper-common.dtsi   |1 +
 arch/arm/boot/dts/tegra30-beaver.dts  |1 +
 arch/arm/boot/dts/tegra30-cardhu.dtsi |1 +
 arch/arm/boot/dts/tegra30-colibri.dtsi|   17 +-
 arch/arm/boot/dts/tegra30-ouya.dts|1 +
 .../arm/boot/dts/tegra30-peripherals-opp.dtsi | 1227 -
 arch/arm/boot/dts/tegra30.dtsi|  153 ++
 8 files changed, 1398 insertions(+), 5 deletions(-)

diff --git a/arch/arm/boot/dts/tegra20-trimslice.dts 
b/arch/arm/boot/dts/tegra20-trimslice.dts
index 306e5f33e7f8..7646a4a1f2be 100644
--- a/arch/arm/boot/dts/tegra20-trimslice.dts
+++ b/arch/arm/boot/dts/tegra20-trimslice.dts
@@ -445,7 +445,7 @@ pci_vdd_reg: regulator-pcivdd {
regulator-always-on;
};
 
-   vdd_core: regulator@5 {
+   vdd_core: regulator-core {
compatible = "regulator-fixed";
regulator-name = "vdd_core";
regulator-min-microvolt = <130>;
diff --git a/arch/arm/boot/dts/tegra30-asus-nexus7-grouper-common.dtsi 
b/arch/arm/boot/dts/tegra30-asus-nexus7-grouper-common.dtsi
index 861ac96bd806..f9d64360222b 100644
--- a/arch/arm/boot/dts/tegra30-asus-nexus7-grouper-common.dtsi
+++ b/arch/arm/boot/dts/tegra30-asus-nexus7-grouper-common.dtsi
@@ -966,6 +966,7 @@ pmc@7000e400 {
nvidia,core-pwr-off-time = <0>;
nvidia,core-power-req-active-high;
nvidia,sys-clock-req-active-high;
+   core-supply = <_core>;
};
 
ahub@7008 {
diff --git a/arch/arm/boot/dts/tegra30-beaver.dts 
b/arch/arm/boot/dts/tegra30-beaver.dts
index 2ec5e47d9623..24de27a8594e 100644
--- a/arch/arm/boot/dts/tegra30-beaver.dts
+++ b/arch/arm/boot/dts/tegra30-beaver.dts
@@ -1915,6 +1915,7 @@ pmc@7000e400 {
nvidia,core-pwr-off-time = <0>;
nvidia,core-power-req-active-high;
nvidia,sys-clock-req-active-high;
+   core-supply = <_vdd_reg>;
};
 
ahub@7008 {
diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi 
b/arch/arm/boot/dts/tegra30-cardhu.dtsi
index d2f6121049a4..506cb747b2db 100644
--- a/arch/arm/boot/dts/tegra30-cardhu.dtsi
+++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi
@@ -391,6 +391,7 @@ pmc@7000e400 {
nvidia,core-pwr-off-time = <0>;
nvidia,core-power-req-active-high;
nvidia,sys-clock-req-active-high;
+   core-supply = <_core>;
};
 
ahub@7008 {
diff --git a/arch/arm/boot/dts/tegra30-colibri.dtsi 
b/arch/arm/boot/dts/tegra30-colibri.dtsi
index 413e35215804..0627b64f044d 100644
--- a/arch/arm/boot/dts/tegra30-colibri.dtsi
+++ b/arch/arm/boot/dts/tegra30-colibri.dtsi
@@ -765,9 +765,14 @@ vdd1_reg: vdd1 {
 
vddctrl_reg: vddctrl {
regulator-name = "+V1.0_VDD_CPU";
-   regulator-min-microvolt = <115>;
-   regulator-max-microvolt = <115>;
+   regulator-min-microvolt = <80>;
+   regulator-max-microvolt = <125>;
+   regulator-coupled-with = <_core>;
+   regulator-coupled-max-spread = <30>;
+   regulator-max-step-microvolt = <10>;
regulator-always-on;
+
+   nvidia,tegra-cpu-regulator;
};
 
reg_1v8_vio: vio {
@@ -890,18 +895,23 @@ temp-sensor@4c {
};
 
/* SW: +V1.2_VDD_CORE */
-   regulator@60 {
+   vdd_core: regulator@60 {
compatible = "ti,tps62362";
reg = <0x60>;
 
regulator-name = "tps62362-vout";
regulator-min-microvolt = <90>;
regulator-max-microvolt = <140>;
+   regulator-coupled-with = <_reg>;
+   regulator-coupled-max-spread = <30>;
+   regulator-max-step-microvolt = <10>;
regulator-boot-on;
regulator-always-on;
ti,vsel0-state-low;
/* VSEL1: EN_CORE_DVFS_N low for DVFS */
ti,vsel1-state-low;
+
+   nvidia,tegra-core-regulator;
};
};
 
@@ -914,6 +924,7 @@ pmc@7000e400 {
nvidia,core-pwr-off-time = <0>;
 

[PATCH v16 25/40] media: dt: bindings: tegra-vde: Convert to schema

2021-11-30 Thread Dmitry Osipenko
Convert NVIDIA Tegra video decoder binding to schema.

Reviewed-by: Rob Herring 
Acked-by: Hans Verkuil 
Signed-off-by: Dmitry Osipenko 
---
 .../bindings/media/nvidia,tegra-vde.txt   |  64 ---
 .../bindings/media/nvidia,tegra-vde.yaml  | 107 ++
 2 files changed, 107 insertions(+), 64 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/media/nvidia,tegra-vde.txt
 create mode 100644 
Documentation/devicetree/bindings/media/nvidia,tegra-vde.yaml

diff --git a/Documentation/devicetree/bindings/media/nvidia,tegra-vde.txt 
b/Documentation/devicetree/bindings/media/nvidia,tegra-vde.txt
deleted file mode 100644
index 602169b8aa19..
--- a/Documentation/devicetree/bindings/media/nvidia,tegra-vde.txt
+++ /dev/null
@@ -1,64 +0,0 @@
-NVIDIA Tegra Video Decoder Engine
-
-Required properties:
-- compatible : Must contain one of the following values:
-   - "nvidia,tegra20-vde"
-   - "nvidia,tegra30-vde"
-   - "nvidia,tegra114-vde"
-   - "nvidia,tegra124-vde"
-   - "nvidia,tegra132-vde"
-- reg : Must contain an entry for each entry in reg-names.
-- reg-names : Must include the following entries:
-  - sxe
-  - bsev
-  - mbe
-  - ppe
-  - mce
-  - tfe
-  - ppb
-  - vdma
-  - frameid
-- iram : Must contain phandle to the mmio-sram device node that represents
- IRAM region used by VDE.
-- interrupts : Must contain an entry for each entry in interrupt-names.
-- interrupt-names : Must include the following entries:
-  - sync-token
-  - bsev
-  - sxe
-- clocks : Must include the following entries:
-  - vde
-- resets : Must contain an entry for each entry in reset-names.
-- reset-names : Should include the following entries:
-  - vde
-
-Optional properties:
-- resets : Must contain an entry for each entry in reset-names.
-- reset-names : Must include the following entries:
-  - mc
-- iommus: Must contain phandle to the IOMMU device node.
-
-Example:
-
-video-codec@6001a000 {
-   compatible = "nvidia,tegra20-vde";
-   reg = <0x6001a000 0x1000 /* Syntax Engine */
-  0x6001b000 0x1000 /* Video Bitstream Engine */
-  0x6001c000  0x100 /* Macroblock Engine */
-  0x6001c200  0x100 /* Post-processing Engine */
-  0x6001c400  0x100 /* Motion Compensation Engine */
-  0x6001c600  0x100 /* Transform Engine */
-  0x6001c800  0x100 /* Pixel prediction block */
-  0x6001ca00  0x100 /* Video DMA */
-  0x6001d800  0x300 /* Video frame controls */>;
-   reg-names = "sxe", "bsev", "mbe", "ppe", "mce",
-   "tfe", "ppb", "vdma", "frameid";
-   iram = <_pool>; /* IRAM region */
-   interrupts = , /* Sync token interrupt 
*/
-, /* BSE-V interrupt */
-; /* SXE interrupt */
-   interrupt-names = "sync-token", "bsev", "sxe";
-   clocks = <_car TEGRA20_CLK_VDE>;
-   reset-names = "vde", "mc";
-   resets = <_car 61>, < TEGRA20_MC_RESET_VDE>;
-   iommus = < TEGRA_SWGROUP_VDE>;
-};
diff --git a/Documentation/devicetree/bindings/media/nvidia,tegra-vde.yaml 
b/Documentation/devicetree/bindings/media/nvidia,tegra-vde.yaml
new file mode 100644
index ..c143aaa06346
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/nvidia,tegra-vde.yaml
@@ -0,0 +1,107 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/nvidia,tegra-vde.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NVIDIA Tegra Video Decoder Engine
+
+maintainers:
+  - Dmitry Osipenko 
+  - Jon Hunter 
+  - Thierry Reding 
+
+properties:
+  compatible:
+oneOf:
+  - items:
+  - enum:
+  - nvidia,tegra132-vde
+  - nvidia,tegra124-vde
+  - nvidia,tegra114-vde
+  - items:
+  - const: nvidia,tegra30-vde
+  - const: nvidia,tegra20-vde
+  - items:
+  - const: nvidia,tegra20-vde
+
+  reg:
+maxItems: 9
+
+  reg-names:
+items:
+  - const: sxe
+  - const: bsev
+  - const: mbe
+  - const: ppe
+  - const: mce
+  - const: tfe
+  - const: ppb
+  - const: vdma
+  - const: frameid
+
+  clocks:
+maxItems: 1
+
+  resets:
+maxItems: 2
+
+  reset-names:
+items:
+  - const: vde
+  - const: mc
+
+  interrupts:
+maxItems: 3
+
+  interrupt-names:
+items:
+  - const: sync-token
+  - const: bsev
+  - const: sxe
+
+  iommus:
+maxItems: 1
+
+  iram:
+$ref: /schemas/types.yaml#/definitions/phandle
+description:
+  Phandle of the SRAM MMIO node.
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - clocks
+  - resets
+  - reset-names
+  - interrupts
+  - interrupt-names
+
+additionalProperties: false
+
+examples:
+  - |
+video-codec@6001a000 {
+  compatible = "nvidia,tegra20-vde";
+  reg = <0x6001a000 0x1000>, /* Syntax Engine */
+<0x6001b000 0x1000>, /* Video 

[PATCH v16 16/40] drm/tegra: nvdec: Stop channel on suspend

2021-11-30 Thread Dmitry Osipenko
CDMA must be stopped before hardware is suspended. Add channel stopping
to RPM suspend callback. Add system level suspend-resume callbacks.

Runtime PM initialization is moved to host1x client init phase because
RPM callback now uses host1x channel that is available only when host1x
client is registered.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/tegra/nvdec.c | 29 ++---
 1 file changed, 18 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/tegra/nvdec.c b/drivers/gpu/drm/tegra/nvdec.c
index 791bf1acf5f0..15f036e09e5c 100644
--- a/drivers/gpu/drm/tegra/nvdec.c
+++ b/drivers/gpu/drm/tegra/nvdec.c
@@ -113,9 +113,13 @@ static int nvdec_init(struct host1x_client *client)
goto free_channel;
}
 
+   pm_runtime_enable(client->dev);
+   pm_runtime_use_autosuspend(client->dev);
+   pm_runtime_set_autosuspend_delay(client->dev, 500);
+
err = tegra_drm_register_client(tegra, drm);
if (err < 0)
-   goto free_syncpt;
+   goto disable_rpm;
 
/*
 * Inherit the DMA parameters (such as maximum segment size) from the
@@ -125,7 +129,10 @@ static int nvdec_init(struct host1x_client *client)
 
return 0;
 
-free_syncpt:
+disable_rpm:
+   pm_runtime_dont_use_autosuspend(client->dev);
+   pm_runtime_force_suspend(client->dev);
+
host1x_syncpt_put(client->syncpts[0]);
 free_channel:
host1x_channel_put(nvdec->channel);
@@ -150,10 +157,15 @@ static int nvdec_exit(struct host1x_client *client)
if (err < 0)
return err;
 
+   pm_runtime_dont_use_autosuspend(client->dev);
+   pm_runtime_force_suspend(client->dev);
+
host1x_syncpt_put(client->syncpts[0]);
host1x_channel_put(nvdec->channel);
host1x_client_iommu_detach(client);
 
+   nvdec->channel = NULL;
+
if (client->group) {
dma_unmap_single(nvdec->dev, nvdec->falcon.firmware.phys,
 nvdec->falcon.firmware.size, DMA_TO_DEVICE);
@@ -268,6 +280,8 @@ static __maybe_unused int nvdec_runtime_suspend(struct 
device *dev)
 {
struct nvdec *nvdec = dev_get_drvdata(dev);
 
+   host1x_channel_stop(nvdec->channel);
+
clk_disable_unprepare(nvdec->clk);
 
return 0;
@@ -412,10 +426,6 @@ static int nvdec_probe(struct platform_device *pdev)
goto exit_falcon;
}
 
-   pm_runtime_enable(>dev);
-   pm_runtime_set_autosuspend_delay(>dev, 500);
-   pm_runtime_use_autosuspend(>dev);
-
return 0;
 
 exit_falcon:
@@ -436,11 +446,6 @@ static int nvdec_remove(struct platform_device *pdev)
return err;
}
 
-   if (pm_runtime_enabled(>dev))
-   pm_runtime_disable(>dev);
-   else
-   nvdec_runtime_suspend(>dev);
-
falcon_exit(>falcon);
 
return 0;
@@ -448,6 +453,8 @@ static int nvdec_remove(struct platform_device *pdev)
 
 static const struct dev_pm_ops nvdec_pm_ops = {
SET_RUNTIME_PM_OPS(nvdec_runtime_suspend, nvdec_runtime_resume, NULL)
+   SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+   pm_runtime_force_resume)
 };
 
 struct platform_driver tegra_nvdec_driver = {
-- 
2.33.1



[PATCH v16 19/40] usb: chipidea: tegra: Add runtime PM and OPP support

2021-11-30 Thread Dmitry Osipenko
The Tegra USB controller belongs to the core power domain and we're going
to enable GENPD support for the core domain. Now USB controller must be
resumed using runtime PM API in order to initialize the USB power state.
We already support runtime PM for the CI device, but CI's PM is separated
from the RPM managed by tegra-usb driver. Add runtime PM and OPP support
to the driver.

Acked-by: Peter Chen 
Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/usb/chipidea/ci_hdrc_tegra.c | 53 
 1 file changed, 46 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/chipidea/ci_hdrc_tegra.c 
b/drivers/usb/chipidea/ci_hdrc_tegra.c
index 60361141ac04..a72a9474afea 100644
--- a/drivers/usb/chipidea/ci_hdrc_tegra.c
+++ b/drivers/usb/chipidea/ci_hdrc_tegra.c
@@ -7,6 +7,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -15,6 +16,8 @@
 #include 
 #include 
 
+#include 
+
 #include "../host/ehci.h"
 
 #include "ci.h"
@@ -278,6 +281,8 @@ static int tegra_usb_probe(struct platform_device *pdev)
if (!usb)
return -ENOMEM;
 
+   platform_set_drvdata(pdev, usb);
+
soc = of_device_get_match_data(>dev);
if (!soc) {
dev_err(>dev, "failed to match OF data\n");
@@ -296,11 +301,14 @@ static int tegra_usb_probe(struct platform_device *pdev)
return err;
}
 
-   err = clk_prepare_enable(usb->clk);
-   if (err < 0) {
-   dev_err(>dev, "failed to enable clock: %d\n", err);
+   err = devm_tegra_core_dev_init_opp_table_common(>dev);
+   if (err)
+   return err;
+
+   pm_runtime_enable(>dev);
+   err = pm_runtime_resume_and_get(>dev);
+   if (err)
return err;
-   }
 
if (device_property_present(>dev, "nvidia,needs-double-reset"))
usb->needs_double_reset = true;
@@ -320,8 +328,6 @@ static int tegra_usb_probe(struct platform_device *pdev)
if (err)
goto fail_power_off;
 
-   platform_set_drvdata(pdev, usb);
-
/* setup and register ChipIdea HDRC device */
usb->soc = soc;
usb->data.name = "tegra-usb";
@@ -350,7 +356,9 @@ static int tegra_usb_probe(struct platform_device *pdev)
 phy_shutdown:
usb_phy_shutdown(usb->phy);
 fail_power_off:
-   clk_disable_unprepare(usb->clk);
+   pm_runtime_put_sync_suspend(>dev);
+   pm_runtime_force_suspend(>dev);
+
return err;
 }
 
@@ -360,15 +368,46 @@ static int tegra_usb_remove(struct platform_device *pdev)
 
ci_hdrc_remove_device(usb->dev);
usb_phy_shutdown(usb->phy);
+
+   pm_runtime_put_sync_suspend(>dev);
+   pm_runtime_force_suspend(>dev);
+
+   return 0;
+}
+
+static int __maybe_unused tegra_usb_runtime_resume(struct device *dev)
+{
+   struct tegra_usb *usb = dev_get_drvdata(dev);
+   int err;
+
+   err = clk_prepare_enable(usb->clk);
+   if (err < 0) {
+   dev_err(dev, "failed to enable clock: %d\n", err);
+   return err;
+   }
+
+   return 0;
+}
+
+static int __maybe_unused tegra_usb_runtime_suspend(struct device *dev)
+{
+   struct tegra_usb *usb = dev_get_drvdata(dev);
+
clk_disable_unprepare(usb->clk);
 
return 0;
 }
 
+static const struct dev_pm_ops tegra_usb_pm = {
+   SET_RUNTIME_PM_OPS(tegra_usb_runtime_suspend, tegra_usb_runtime_resume,
+  NULL)
+};
+
 static struct platform_driver tegra_usb_driver = {
.driver = {
.name = "tegra-usb",
.of_match_table = tegra_usb_of_match,
+   .pm = _usb_pm,
},
.probe = tegra_usb_probe,
.remove = tegra_usb_remove,
-- 
2.33.1



[PATCH v16 36/40] ARM: tegra: Add OPP tables and power domains to Tegra20 device-trees

2021-11-30 Thread Dmitry Osipenko
Add OPP tables and power domains to all peripheral devices which
support power management on Tegra20 SoC.

Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20
Signed-off-by: Dmitry Osipenko 
---
 .../boot/dts/tegra20-acer-a500-picasso.dts|   1 +
 arch/arm/boot/dts/tegra20-colibri.dtsi|   3 +-
 arch/arm/boot/dts/tegra20-harmony.dts |   3 +-
 arch/arm/boot/dts/tegra20-paz00.dts   |   1 +
 .../arm/boot/dts/tegra20-peripherals-opp.dtsi | 913 ++
 arch/arm/boot/dts/tegra20-seaboard.dts|   3 +-
 arch/arm/boot/dts/tegra20-tamonten.dtsi   |   3 +-
 arch/arm/boot/dts/tegra20-trimslice.dts   |   9 +
 arch/arm/boot/dts/tegra20-ventana.dts |   1 +
 arch/arm/boot/dts/tegra20.dtsi| 102 +-
 10 files changed, 1034 insertions(+), 5 deletions(-)

diff --git a/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts 
b/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts
index e1b33d25b6e0..db388ddd062f 100644
--- a/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts
+++ b/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts
@@ -716,6 +716,7 @@ pmc@7000e400 {
nvidia,core-pwr-good-time = <3845 3845>;
nvidia,core-pwr-off-time = <458>;
nvidia,sys-clock-req-active-high;
+   core-supply = <_core>;
};
 
usb@c500 {
diff --git a/arch/arm/boot/dts/tegra20-colibri.dtsi 
b/arch/arm/boot/dts/tegra20-colibri.dtsi
index 3f9cb5cd6bd8..eb5b3feb5907 100644
--- a/arch/arm/boot/dts/tegra20-colibri.dtsi
+++ b/arch/arm/boot/dts/tegra20-colibri.dtsi
@@ -495,7 +495,7 @@ reg_3v3_vsys: sys {
regulator-always-on;
};
 
-   sm0 {
+   vdd_core: sm0 {
regulator-name = "VDD_CORE_1.2V";
regulator-min-microvolt = <120>;
regulator-max-microvolt = <120>;
@@ -601,6 +601,7 @@ pmc@7000e400 {
nvidia,core-pwr-good-time = <3845 3845>;
nvidia,core-pwr-off-time = <3875>;
nvidia,sys-clock-req-active-high;
+   core-supply = <_core>;
 
/* Set SLEEP MODE bit in SUPPLYENE register of TPS658643 PMIC */
i2c-thermtrip {
diff --git a/arch/arm/boot/dts/tegra20-harmony.dts 
b/arch/arm/boot/dts/tegra20-harmony.dts
index a8494378c382..b4cc88b0f130 100644
--- a/arch/arm/boot/dts/tegra20-harmony.dts
+++ b/arch/arm/boot/dts/tegra20-harmony.dts
@@ -339,7 +339,7 @@ sys_reg: sys {
regulator-always-on;
};
 
-   sm0 {
+   vdd_core: sm0 {
regulator-name = "vdd_sm0,vdd_core";
regulator-min-microvolt = <120>;
regulator-max-microvolt = <120>;
@@ -565,6 +565,7 @@ pmc@7000e400 {
nvidia,core-pwr-good-time = <3845 3845>;
nvidia,core-pwr-off-time = <3875>;
nvidia,sys-clock-req-active-high;
+   core-supply = <_core>;
};
 
pcie@80003000 {
diff --git a/arch/arm/boot/dts/tegra20-paz00.dts 
b/arch/arm/boot/dts/tegra20-paz00.dts
index 1fd5a7458c7a..f68d37ae6c64 100644
--- a/arch/arm/boot/dts/tegra20-paz00.dts
+++ b/arch/arm/boot/dts/tegra20-paz00.dts
@@ -519,6 +519,7 @@ pmc@7000e400 {
nvidia,core-pwr-good-time = <3845 3845>;
nvidia,core-pwr-off-time = <0>;
nvidia,sys-clock-req-active-high;
+   core-supply = <_vdd_reg>;
};
 
usb@c500 {
diff --git a/arch/arm/boot/dts/tegra20-peripherals-opp.dtsi 
b/arch/arm/boot/dts/tegra20-peripherals-opp.dtsi
index d4d0a5fa7015..e7477b129e34 100644
--- a/arch/arm/boot/dts/tegra20-peripherals-opp.dtsi
+++ b/arch/arm/boot/dts/tegra20-peripherals-opp.dtsi
@@ -1,6 +1,46 @@
 // SPDX-License-Identifier: GPL-2.0
 
 / {
+   core_opp_table: opp-table-core {
+   compatible = "operating-points-v2";
+   opp-shared;
+
+   core_opp_950: opp-95 {
+   opp-microvolt = <95 95 130>;
+   opp-level = <95>;
+   };
+
+   core_opp_1000: opp-100 {
+   opp-microvolt = <100 100 130>;
+   opp-level = <100>;
+   };
+
+   core_opp_1100: opp-110 {
+   opp-microvolt = <110 110 130>;
+   opp-level = <110>;
+   };
+
+   core_opp_1200: opp-120 {
+   opp-microvolt = <120 120 130>;
+   opp-level = <120>;
+   };
+
+   

[PATCH v16 38/40] ARM: tegra: Add Memory Client resets to Tegra20 GR2D, GR3D and Host1x

2021-11-30 Thread Dmitry Osipenko
Memory access must be blocked before hardware reset is asserted and before
power is gated, otherwise a serious hardware fault is inevitable. Add
reset for memory clients to the GR2D, GR3D and Host1x nodes.

Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20
Signed-off-by: Dmitry Osipenko 
---
 arch/arm/boot/dts/tegra20.dtsi | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 1898351a099f..7b69ffc57abe 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -40,8 +40,8 @@ host1x@5000 {
interrupt-names = "syncpt", "host1x";
clocks = <_car TEGRA20_CLK_HOST1X>;
clock-names = "host1x";
-   resets = <_car 28>;
-   reset-names = "host1x";
+   resets = <_car 28>, < TEGRA20_MC_RESET_HC>;
+   reset-names = "host1x", "mc";
power-domains = <_core>;
operating-points-v2 = <_dvfs_opp_table>;
 
@@ -98,8 +98,8 @@ gr2d@5414 {
reg = <0x5414 0x0004>;
interrupts = ;
clocks = <_car TEGRA20_CLK_GR2D>;
-   resets = <_car 21>;
-   reset-names = "2d";
+   resets = <_car 21>, < TEGRA20_MC_RESET_2D>;
+   reset-names = "2d", "mc";
power-domains = <_core>;
operating-points-v2 = <_dvfs_opp_table>;
};
@@ -108,8 +108,8 @@ gr3d@5418 {
compatible = "nvidia,tegra20-gr3d";
reg = <0x5418 0x0004>;
clocks = <_car TEGRA20_CLK_GR3D>;
-   resets = <_car 24>;
-   reset-names = "3d";
+   resets = <_car 24>, < TEGRA20_MC_RESET_3D>;
+   reset-names = "3d", "mc";
power-domains = <_3d>;
operating-points-v2 = <_dvfs_opp_table>;
};
-- 
2.33.1



[PATCH v16 21/40] pwm: tegra: Add runtime PM and OPP support

2021-11-30 Thread Dmitry Osipenko
The PWM on Tegra belongs to the core power domain and we're going to
enable GENPD support for the core domain. Now PWM must be resumed using
runtime PM API in order to initialize the PWM power state. The PWM clock
rate must be changed using OPP API that will reconfigure the power domain
performance state in accordance to the rate. Add runtime PM and OPP
support to the PWM driver.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/pwm/pwm-tegra.c | 82 -
 1 file changed, 64 insertions(+), 18 deletions(-)

diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
index 11a10b575ace..18cf974ac776 100644
--- a/drivers/pwm/pwm-tegra.c
+++ b/drivers/pwm/pwm-tegra.c
@@ -42,12 +42,16 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
+#include 
+
 #define PWM_ENABLE (1 << 31)
 #define PWM_DUTY_WIDTH 8
 #define PWM_DUTY_SHIFT 16
@@ -145,7 +149,7 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct 
pwm_device *pwm,
required_clk_rate =
(NSEC_PER_SEC / period_ns) << PWM_DUTY_WIDTH;
 
-   err = clk_set_rate(pc->clk, required_clk_rate);
+   err = dev_pm_opp_set_rate(pc->dev, required_clk_rate);
if (err < 0)
return -EINVAL;
 
@@ -181,8 +185,8 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct 
pwm_device *pwm,
 * before writing the register. Otherwise, keep it enabled.
 */
if (!pwm_is_enabled(pwm)) {
-   err = clk_prepare_enable(pc->clk);
-   if (err < 0)
+   err = pm_runtime_resume_and_get(pc->dev);
+   if (err)
return err;
} else
val |= PWM_ENABLE;
@@ -193,7 +197,7 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct 
pwm_device *pwm,
 * If the PWM is not enabled, turn the clock off again to save power.
 */
if (!pwm_is_enabled(pwm))
-   clk_disable_unprepare(pc->clk);
+   pm_runtime_put(pc->dev);
 
return 0;
 }
@@ -204,8 +208,8 @@ static int tegra_pwm_enable(struct pwm_chip *chip, struct 
pwm_device *pwm)
int rc = 0;
u32 val;
 
-   rc = clk_prepare_enable(pc->clk);
-   if (rc < 0)
+   rc = pm_runtime_resume_and_get(pc->dev);
+   if (rc)
return rc;
 
val = pwm_readl(pc, pwm->hwpwm);
@@ -224,7 +228,7 @@ static void tegra_pwm_disable(struct pwm_chip *chip, struct 
pwm_device *pwm)
val &= ~PWM_ENABLE;
pwm_writel(pc, pwm->hwpwm, val);
 
-   clk_disable_unprepare(pc->clk);
+   pm_runtime_put_sync(pc->dev);
 }
 
 static const struct pwm_ops tegra_pwm_ops = {
@@ -256,11 +260,20 @@ static int tegra_pwm_probe(struct platform_device *pdev)
if (IS_ERR(pwm->clk))
return PTR_ERR(pwm->clk);
 
+   ret = devm_tegra_core_dev_init_opp_table_common(>dev);
+   if (ret)
+   return ret;
+
+   pm_runtime_enable(>dev);
+   ret = pm_runtime_resume_and_get(>dev);
+   if (ret)
+   return ret;
+
/* Set maximum frequency of the IP */
-   ret = clk_set_rate(pwm->clk, pwm->soc->max_frequency);
+   ret = dev_pm_opp_set_rate(pwm->dev, pwm->soc->max_frequency);
if (ret < 0) {
dev_err(>dev, "Failed to set max frequency: %d\n", ret);
-   return ret;
+   goto put_pm;
}
 
/*
@@ -278,7 +291,7 @@ static int tegra_pwm_probe(struct platform_device *pdev)
if (IS_ERR(pwm->rst)) {
ret = PTR_ERR(pwm->rst);
dev_err(>dev, "Reset control is not found: %d\n", ret);
-   return ret;
+   goto put_pm;
}
 
reset_control_deassert(pwm->rst);
@@ -291,10 +304,16 @@ static int tegra_pwm_probe(struct platform_device *pdev)
if (ret < 0) {
dev_err(>dev, "pwmchip_add() failed: %d\n", ret);
reset_control_assert(pwm->rst);
-   return ret;
+   goto put_pm;
}
 
+   pm_runtime_put(>dev);
+
return 0;
+put_pm:
+   pm_runtime_put_sync_suspend(>dev);
+   pm_runtime_force_suspend(>dev);
+   return ret;
 }
 
 static int tegra_pwm_remove(struct platform_device *pdev)
@@ -305,20 +324,44 @@ static int tegra_pwm_remove(struct platform_device *pdev)
 
reset_control_assert(pc->rst);
 
+   pm_runtime_force_suspend(>dev);
+
return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int tegra_pwm_suspend(struct device *dev)
+static int __maybe_unused tegra_pwm_runtime_suspend(struct device *dev)
 {
-   return pinctrl_pm_select_sleep_state(dev);
+   struct tegra_pwm_chip *pc = dev_get_drvdata(dev);
+   int err;
+
+   clk_disable_unprepare(pc->clk);
+
+   err = pinctrl_pm_select_sleep_state(dev);
+   if (err) {
+   

[PATCH v16 13/40] drm/tegra: gr2d: Support generic power domain and runtime PM

2021-11-30 Thread Dmitry Osipenko
Add runtime power management and support generic power domains.

Reviewed-by: Ulf Hansson 
Tested-by: Peter Geis  # Ouya T30
Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20 and TK1 T124
Tested-by: Matt Merhar  # Ouya T30
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/tegra/gr2d.c | 184 ---
 1 file changed, 148 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
index ba3722f1b865..2382def93923 100644
--- a/drivers/gpu/drm/tegra/gr2d.c
+++ b/drivers/gpu/drm/tegra/gr2d.c
@@ -8,12 +8,21 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
+#include 
+
 #include "drm.h"
 #include "gem.h"
 #include "gr2d.h"
 
+enum {
+   RST_MC,
+   RST_GR2D,
+   RST_GR2D_MAX,
+};
+
 struct gr2d_soc {
unsigned int version;
 };
@@ -21,9 +30,11 @@ struct gr2d_soc {
 struct gr2d {
struct tegra_drm_client client;
struct host1x_channel *channel;
-   struct reset_control *rst;
struct clk *clk;
 
+   struct reset_control_bulk_data resets[RST_GR2D_MAX];
+   unsigned int nresets;
+
const struct gr2d_soc *soc;
 
DECLARE_BITMAP(addr_regs, GR2D_NUM_REGS);
@@ -59,15 +70,22 @@ static int gr2d_init(struct host1x_client *client)
goto free;
}
 
+   pm_runtime_enable(client->dev);
+   pm_runtime_use_autosuspend(client->dev);
+   pm_runtime_set_autosuspend_delay(client->dev, 200);
+
err = tegra_drm_register_client(dev->dev_private, drm);
if (err < 0) {
dev_err(client->dev, "failed to register client: %d\n", err);
-   goto detach;
+   goto disable_rpm;
}
 
return 0;
 
-detach:
+disable_rpm:
+   pm_runtime_dont_use_autosuspend(client->dev);
+   pm_runtime_force_suspend(client->dev);
+
host1x_client_iommu_detach(client);
 free:
host1x_syncpt_put(client->syncpts[0]);
@@ -88,10 +106,15 @@ static int gr2d_exit(struct host1x_client *client)
if (err < 0)
return err;
 
+   pm_runtime_dont_use_autosuspend(client->dev);
+   pm_runtime_force_suspend(client->dev);
+
host1x_client_iommu_detach(client);
host1x_syncpt_put(client->syncpts[0]);
host1x_channel_put(gr2d->channel);
 
+   gr2d->channel = NULL;
+
return 0;
 }
 
@@ -104,10 +127,17 @@ static int gr2d_open_channel(struct tegra_drm_client 
*client,
 struct tegra_drm_context *context)
 {
struct gr2d *gr2d = to_gr2d(client);
+   int err;
+
+   err = pm_runtime_resume_and_get(client->base.dev);
+   if (err)
+   return err;
 
context->channel = host1x_channel_get(gr2d->channel);
-   if (!context->channel)
+   if (!context->channel) {
+   pm_runtime_put(client->base.dev);
return -ENOMEM;
+   }
 
return 0;
 }
@@ -115,6 +145,7 @@ static int gr2d_open_channel(struct tegra_drm_client 
*client,
 static void gr2d_close_channel(struct tegra_drm_context *context)
 {
host1x_channel_put(context->channel);
+   pm_runtime_put(context->client->base.dev);
 }
 
 static int gr2d_is_addr_reg(struct device *dev, u32 class, u32 offset)
@@ -193,6 +224,27 @@ static const u32 gr2d_addr_regs[] = {
GR2D_VA_BASE_ADDR_SB,
 };
 
+static int gr2d_get_resets(struct device *dev, struct gr2d *gr2d)
+{
+   int err;
+
+   gr2d->resets[RST_MC].id = "mc";
+   gr2d->resets[RST_GR2D].id = "2d";
+   gr2d->nresets = RST_GR2D_MAX;
+
+   err = devm_reset_control_bulk_get_optional_exclusive_released(
+   dev, gr2d->nresets, gr2d->resets);
+   if (err) {
+   dev_err(dev, "failed to get reset: %d\n", err);
+   return err;
+   }
+
+   if (WARN_ON(!gr2d->resets[RST_GR2D].rstc))
+   return -ENOENT;
+
+   return 0;
+}
+
 static int gr2d_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
@@ -205,37 +257,23 @@ static int gr2d_probe(struct platform_device *pdev)
if (!gr2d)
return -ENOMEM;
 
+   platform_set_drvdata(pdev, gr2d);
+
gr2d->soc = of_device_get_match_data(dev);
 
syncpts = devm_kzalloc(dev, sizeof(*syncpts), GFP_KERNEL);
if (!syncpts)
return -ENOMEM;
 
-   gr2d->rst = devm_reset_control_get(dev, NULL);
-   if (IS_ERR(gr2d->rst)) {
-   dev_err(dev, "cannot get reset\n");
-   return PTR_ERR(gr2d->rst);
-   }
-
gr2d->clk = devm_clk_get(dev, NULL);
if (IS_ERR(gr2d->clk)) {
dev_err(dev, "cannot get clock\n");
return PTR_ERR(gr2d->clk);
}
 
-   err = clk_prepare_enable(gr2d->clk);
-   if (err) {
-   dev_err(dev, "cannot turn on clock\n");
+   err = gr2d_get_resets(dev, gr2d);
+   if (err)
return err;
-   }

[PATCH v16 34/40] ARM: tegra: Rename CPU and EMC OPP table device-tree nodes

2021-11-30 Thread Dmitry Osipenko
OPP table name now should start with "opp-table" and OPP entries
shouldn't contain commas and @ signs in accordance to the new schema
requirement. Reorganize CPU and EMC OPP table device-tree nodes.

Signed-off-by: Dmitry Osipenko 
---
 arch/arm/boot/dts/tegra124-apalis-emc.dtsi|   4 +-
 .../arm/boot/dts/tegra124-jetson-tk1-emc.dtsi |   4 +-
 arch/arm/boot/dts/tegra124-nyan-big-emc.dtsi  |   8 +-
 .../arm/boot/dts/tegra124-nyan-blaze-emc.dtsi |   8 +-
 .../boot/dts/tegra124-peripherals-opp.dtsi| 140 -
 .../boot/dts/tegra20-acer-a500-picasso.dts|   4 +-
 arch/arm/boot/dts/tegra20-colibri.dtsi|   2 +-
 .../boot/dts/tegra20-cpu-opp-microvolt.dtsi   |  82 +-
 arch/arm/boot/dts/tegra20-cpu-opp.dtsi|  82 +-
 arch/arm/boot/dts/tegra20-paz00.dts   |   2 +-
 .../arm/boot/dts/tegra20-peripherals-opp.dtsi |  36 ++---
 ...30-asus-nexus7-grouper-memory-timings.dtsi |  12 +-
 .../boot/dts/tegra30-cpu-opp-microvolt.dtsi   | 144 +-
 arch/arm/boot/dts/tegra30-cpu-opp.dtsi| 144 +-
 arch/arm/boot/dts/tegra30-ouya.dts|   4 +-
 .../arm/boot/dts/tegra30-peripherals-opp.dtsi | 128 
 16 files changed, 402 insertions(+), 402 deletions(-)

diff --git a/arch/arm/boot/dts/tegra124-apalis-emc.dtsi 
b/arch/arm/boot/dts/tegra124-apalis-emc.dtsi
index a7ac805eeed5..3d9cf16f233c 100644
--- a/arch/arm/boot/dts/tegra124-apalis-emc.dtsi
+++ b/arch/arm/boot/dts/tegra124-apalis-emc.dtsi
@@ -1467,9 +1467,9 @@ timing-92400 {
 };
 
 _icc_dvfs_opp_table {
-   /delete-node/ opp@12,1100;
+   /delete-node/ opp-12-1100;
 };
 
 _bw_dfs_opp_table {
-   /delete-node/ opp@12;
+   /delete-node/ opp-12;
 };
diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1-emc.dtsi 
b/arch/arm/boot/dts/tegra124-jetson-tk1-emc.dtsi
index df4e463afbd1..bb10cf9fc0f9 100644
--- a/arch/arm/boot/dts/tegra124-jetson-tk1-emc.dtsi
+++ b/arch/arm/boot/dts/tegra124-jetson-tk1-emc.dtsi
@@ -2422,9 +2422,9 @@ timing-92400 {
 };
 
 _icc_dvfs_opp_table {
-   /delete-node/ opp@12,1100;
+   /delete-node/ opp-12-1100;
 };
 
 _bw_dfs_opp_table {
-   /delete-node/ opp@12;
+   /delete-node/ opp-12;
 };
diff --git a/arch/arm/boot/dts/tegra124-nyan-big-emc.dtsi 
b/arch/arm/boot/dts/tegra124-nyan-big-emc.dtsi
index a0f56cc9da5c..6f2ea9469d49 100644
--- a/arch/arm/boot/dts/tegra124-nyan-big-emc.dtsi
+++ b/arch/arm/boot/dts/tegra124-nyan-big-emc.dtsi
@@ -6651,11 +6651,11 @@ timing-79200 {
 };
 
 _icc_dvfs_opp_table {
-   /delete-node/ opp@92400,1100;
-   /delete-node/ opp@12,1100;
+   /delete-node/ opp-92400-1100;
+   /delete-node/ opp-12-1100;
 };
 
 _bw_dfs_opp_table {
-   /delete-node/ opp@92400;
-   /delete-node/ opp@12;
+   /delete-node/ opp-92400;
+   /delete-node/ opp-12;
 };
diff --git a/arch/arm/boot/dts/tegra124-nyan-blaze-emc.dtsi 
b/arch/arm/boot/dts/tegra124-nyan-blaze-emc.dtsi
index 35c98734d35f..d47cdb863f88 100644
--- a/arch/arm/boot/dts/tegra124-nyan-blaze-emc.dtsi
+++ b/arch/arm/boot/dts/tegra124-nyan-blaze-emc.dtsi
@@ -2050,11 +2050,11 @@ timing-79200 {
 };
 
 _icc_dvfs_opp_table {
-   /delete-node/ opp@92400,1100;
-   /delete-node/ opp@12,1100;
+   /delete-node/ opp-92400-1100;
+   /delete-node/ opp-12-1100;
 };
 
 _bw_dfs_opp_table {
-   /delete-node/ opp@92400;
-   /delete-node/ opp@12;
+   /delete-node/ opp-92400;
+   /delete-node/ opp-12;
 };
diff --git a/arch/arm/boot/dts/tegra124-peripherals-opp.dtsi 
b/arch/arm/boot/dts/tegra124-peripherals-opp.dtsi
index 781ac8601030..b262c1289da5 100644
--- a/arch/arm/boot/dts/tegra124-peripherals-opp.dtsi
+++ b/arch/arm/boot/dts/tegra124-peripherals-opp.dtsi
@@ -1,421 +1,421 @@
 // SPDX-License-Identifier: GPL-2.0
 
 / {
-   emc_icc_dvfs_opp_table: emc-dvfs-opp-table {
+   emc_icc_dvfs_opp_table: opp-table-emc {
compatible = "operating-points-v2";
 
-   opp@1275,800 {
+   opp-1275-800 {
opp-microvolt = <80 80 115>;
opp-hz = /bits/ 64 <1275>;
opp-supported-hw = <0x0003>;
};
 
-   opp@1275,950 {
+   opp-1275-950 {
opp-microvolt = <95 95 115>;
opp-hz = /bits/ 64 <1275>;
opp-supported-hw = <0x0008>;
};
 
-   opp@1275,1050 {
+   opp-1275-1050 {
opp-microvolt = <105 105 115>;
opp-hz = /bits/ 64 <1275>;
opp-supported-hw = <0x0010>;
};
 
-   opp@1275,1110 {
+   opp-1275-1110 {

[PATCH v16 35/40] ARM: tegra: Add 500MHz entry to Tegra30 memory OPP table

2021-11-30 Thread Dmitry Osipenko
Extend memory OPPs with 500MHz entry. This clock rate is used by ASUS
Transformer tablets.

Signed-off-by: Dmitry Osipenko 
---
 arch/arm/boot/dts/tegra30-peripherals-opp.dtsi | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/arch/arm/boot/dts/tegra30-peripherals-opp.dtsi 
b/arch/arm/boot/dts/tegra30-peripherals-opp.dtsi
index ff25350869b3..af9640401402 100644
--- a/arch/arm/boot/dts/tegra30-peripherals-opp.dtsi
+++ b/arch/arm/boot/dts/tegra30-peripherals-opp.dtsi
@@ -216,6 +216,18 @@ opp-45000-1250 {
opp-supported-hw = <0x0008>;
};
 
+   opp-5-1200 {
+   opp-microvolt = <120 120 135>;
+   opp-hz = /bits/ 64 <5>;
+   opp-supported-hw = <0x0007>;
+   };
+
+   opp-5-1250 {
+   opp-microvolt = <125 125 135>;
+   opp-hz = /bits/ 64 <5>;
+   opp-supported-hw = <0x0008>;
+   };
+
opp-53300-1200 {
opp-microvolt = <120 120 135>;
opp-hz = /bits/ 64 <53300>;
@@ -347,6 +359,12 @@ opp-45000 {
opp-peak-kBps = <360>;
};
 
+   opp-5 {
+   opp-hz = /bits/ 64 <5>;
+   opp-supported-hw = <0x000F>;
+   opp-peak-kBps = <400>;
+   };
+
opp-53300 {
opp-hz = /bits/ 64 <53300>;
opp-supported-hw = <0x000F>;
-- 
2.33.1



[PATCH v16 27/40] media: staging: tegra-vde: Support generic power domain

2021-11-30 Thread Dmitry Osipenko
Currently driver supports legacy power domain API, this patch adds generic
power domain support. This allows us to utilize a modern GENPD API for
newer device-trees.

Reviewed-by: Ulf Hansson 
Tested-by: Peter Geis  # Ouya T30
Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20 and TK1 T124
Tested-by: Matt Merhar  # Ouya T30
Acked-by: Hans Verkuil 
Signed-off-by: Dmitry Osipenko 
---
 drivers/staging/media/tegra-vde/vde.c | 63 ++-
 1 file changed, 52 insertions(+), 11 deletions(-)

diff --git a/drivers/staging/media/tegra-vde/vde.c 
b/drivers/staging/media/tegra-vde/vde.c
index ed4c1250b303..859f60a70904 100644
--- a/drivers/staging/media/tegra-vde/vde.c
+++ b/drivers/staging/media/tegra-vde/vde.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 
+#include 
 #include 
 
 #include "uapi.h"
@@ -920,13 +921,17 @@ static __maybe_unused int 
tegra_vde_runtime_suspend(struct device *dev)
struct tegra_vde *vde = dev_get_drvdata(dev);
int err;
 
-   err = tegra_powergate_power_off(TEGRA_POWERGATE_VDEC);
-   if (err) {
-   dev_err(dev, "Failed to power down HW: %d\n", err);
-   return err;
+   if (!dev->pm_domain) {
+   err = tegra_powergate_power_off(TEGRA_POWERGATE_VDEC);
+   if (err) {
+   dev_err(dev, "Failed to power down HW: %d\n", err);
+   return err;
+   }
}
 
clk_disable_unprepare(vde->clk);
+   reset_control_release(vde->rst);
+   reset_control_release(vde->rst_mc);
 
return 0;
 }
@@ -936,14 +941,45 @@ static __maybe_unused int tegra_vde_runtime_resume(struct 
device *dev)
struct tegra_vde *vde = dev_get_drvdata(dev);
int err;
 
-   err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_VDEC,
-   vde->clk, vde->rst);
+   err = reset_control_acquire(vde->rst_mc);
if (err) {
-   dev_err(dev, "Failed to power up HW : %d\n", err);
+   dev_err(dev, "Failed to acquire mc reset: %d\n", err);
return err;
}
 
+   err = reset_control_acquire(vde->rst);
+   if (err) {
+   dev_err(dev, "Failed to acquire reset: %d\n", err);
+   goto release_mc_reset;
+   }
+
+   if (!dev->pm_domain) {
+   err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_VDEC,
+   vde->clk, vde->rst);
+   if (err) {
+   dev_err(dev, "Failed to power up HW : %d\n", err);
+   goto release_reset;
+   }
+   } else {
+   /*
+* tegra_powergate_sequence_power_up() leaves clocks enabled,
+* while GENPD not.
+*/
+   err = clk_prepare_enable(vde->clk);
+   if (err) {
+   dev_err(dev, "Failed to enable clock: %d\n", err);
+   goto release_reset;
+   }
+   }
+
return 0;
+
+release_reset:
+   reset_control_release(vde->rst);
+release_mc_reset:
+   reset_control_release(vde->rst_mc);
+
+   return err;
 }
 
 static int tegra_vde_probe(struct platform_device *pdev)
@@ -1001,14 +1037,14 @@ static int tegra_vde_probe(struct platform_device *pdev)
return err;
}
 
-   vde->rst = devm_reset_control_get(dev, NULL);
+   vde->rst = devm_reset_control_get_exclusive_released(dev, NULL);
if (IS_ERR(vde->rst)) {
err = PTR_ERR(vde->rst);
dev_err(dev, "Could not get VDE reset %d\n", err);
return err;
}
 
-   vde->rst_mc = devm_reset_control_get_optional(dev, "mc");
+   vde->rst_mc = devm_reset_control_get_optional_exclusive_released(dev, 
"mc");
if (IS_ERR(vde->rst_mc)) {
err = PTR_ERR(vde->rst_mc);
dev_err(dev, "Could not get MC reset %d\n", err);
@@ -1026,6 +1062,12 @@ static int tegra_vde_probe(struct platform_device *pdev)
return err;
}
 
+   err = devm_tegra_core_dev_init_opp_table_common(dev);
+   if (err) {
+   dev_err(dev, "Could initialize OPP table %d\n", err);
+   return err;
+   }
+
vde->iram_pool = of_gen_pool_get(dev->of_node, "iram", 0);
if (!vde->iram_pool) {
dev_err(dev, "Could not get IRAM pool\n");
@@ -1133,8 +1175,7 @@ static void tegra_vde_shutdown(struct platform_device 
*pdev)
 * On some devices bootloader isn't ready to a power-gated VDE on
 * a warm-reboot, machine will hang in that case.
 */
-   if (pm_runtime_status_suspended(>dev))
-   tegra_vde_runtime_resume(>dev);
+   pm_runtime_get_sync(>dev);
 }
 
 static __maybe_unused int tegra_vde_pm_suspend(struct device *dev)
-- 
2.33.1



[PATCH v16 33/40] soc/tegra: pmc: Enable core domain support for Tegra20 and Tegra30

2021-11-30 Thread Dmitry Osipenko
All device drivers got runtime PM and OPP support. Flip the core domain
support status for Tegra20 and Tegra30 SoCs.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/soc/tegra/pmc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index de6234ec4f9b..585a05968ea9 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -3070,7 +3070,7 @@ static void tegra20_pmc_setup_irq_polarity(struct 
tegra_pmc *pmc,
 }
 
 static const struct tegra_pmc_soc tegra20_pmc_soc = {
-   .supports_core_domain = false,
+   .supports_core_domain = true,
.num_powergates = ARRAY_SIZE(tegra20_powergates),
.powergates = tegra20_powergates,
.num_cpu_powergates = 0,
@@ -3131,7 +3131,7 @@ static const char * const tegra30_reset_sources[] = {
 };
 
 static const struct tegra_pmc_soc tegra30_pmc_soc = {
-   .supports_core_domain = false,
+   .supports_core_domain = true,
.num_powergates = ARRAY_SIZE(tegra30_powergates),
.powergates = tegra30_powergates,
.num_cpu_powergates = ARRAY_SIZE(tegra30_cpu_powergates),
-- 
2.33.1



[PATCH v16 31/40] soc/tegra: pmc: Rename 3d power domains

2021-11-30 Thread Dmitry Osipenko
Device-tree schema doesn't allow domain name to start with a number.
We don't use 3d domain yet in device-trees, so rename it to the name
used by Tegra TRMs: TD, TD2.

Reported-by: David Heidelberg 
Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/soc/tegra/pmc.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 1a55b8319d63..e1fae1a5e36a 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -2992,7 +2992,7 @@ static SIMPLE_DEV_PM_OPS(tegra_pmc_pm_ops, 
tegra_pmc_suspend, tegra_pmc_resume);
 
 static const char * const tegra20_powergates[] = {
[TEGRA_POWERGATE_CPU] = "cpu",
-   [TEGRA_POWERGATE_3D] = "3d",
+   [TEGRA_POWERGATE_3D] = "td",
[TEGRA_POWERGATE_VENC] = "venc",
[TEGRA_POWERGATE_VDEC] = "vdec",
[TEGRA_POWERGATE_PCIE] = "pcie",
@@ -3100,7 +3100,7 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = {
 
 static const char * const tegra30_powergates[] = {
[TEGRA_POWERGATE_CPU] = "cpu0",
-   [TEGRA_POWERGATE_3D] = "3d0",
+   [TEGRA_POWERGATE_3D] = "td",
[TEGRA_POWERGATE_VENC] = "venc",
[TEGRA_POWERGATE_VDEC] = "vdec",
[TEGRA_POWERGATE_PCIE] = "pcie",
@@ -3112,7 +3112,7 @@ static const char * const tegra30_powergates[] = {
[TEGRA_POWERGATE_CPU2] = "cpu2",
[TEGRA_POWERGATE_CPU3] = "cpu3",
[TEGRA_POWERGATE_CELP] = "celp",
-   [TEGRA_POWERGATE_3D1] = "3d1",
+   [TEGRA_POWERGATE_3D1] = "td2",
 };
 
 static const u8 tegra30_cpu_powergates[] = {
@@ -3161,7 +3161,7 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = {
 
 static const char * const tegra114_powergates[] = {
[TEGRA_POWERGATE_CPU] = "crail",
-   [TEGRA_POWERGATE_3D] = "3d",
+   [TEGRA_POWERGATE_3D] = "td",
[TEGRA_POWERGATE_VENC] = "venc",
[TEGRA_POWERGATE_VDEC] = "vdec",
[TEGRA_POWERGATE_MPE] = "mpe",
-- 
2.33.1



[PATCH v16 28/40] soc/tegra: fuse: Reset hardware

2021-11-30 Thread Dmitry Osipenko
The FUSE controller is enabled at a boot time. Reset it in order to put
hardware and clock into clean and disabled state.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/soc/tegra/fuse/fuse-tegra.c | 25 +
 drivers/soc/tegra/fuse/fuse.h   |  1 +
 2 files changed, 26 insertions(+)

diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c 
b/drivers/soc/tegra/fuse/fuse-tegra.c
index f2151815db58..cc032729a143 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra.c
@@ -14,6 +14,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -243,6 +244,30 @@ static int tegra_fuse_probe(struct platform_device *pdev)
goto restore;
}
 
+   fuse->rst = devm_reset_control_get_optional(>dev, "fuse");
+   if (IS_ERR(fuse->rst)) {
+   err = PTR_ERR(fuse->rst);
+   dev_err(>dev, "failed to get FUSE reset: %pe\n",
+   fuse->rst);
+   goto restore;
+   }
+
+   /*
+* FUSE clock is enabled at a boot time, hence this resume/suspend
+* disables the clock besides the h/w resetting.
+*/
+   err = pm_runtime_resume_and_get(>dev);
+   if (err)
+   goto restore;
+
+   err = reset_control_reset(fuse->rst);
+   pm_runtime_put(>dev);
+
+   if (err < 0) {
+   dev_err(>dev, "failed to reset FUSE: %d\n", err);
+   goto restore;
+   }
+
/* release the early I/O memory mapping */
iounmap(base);
 
diff --git a/drivers/soc/tegra/fuse/fuse.h b/drivers/soc/tegra/fuse/fuse.h
index de58feba0435..1b719d85bd04 100644
--- a/drivers/soc/tegra/fuse/fuse.h
+++ b/drivers/soc/tegra/fuse/fuse.h
@@ -43,6 +43,7 @@ struct tegra_fuse {
void __iomem *base;
phys_addr_t phys;
struct clk *clk;
+   struct reset_control *rst;
 
u32 (*read_early)(struct tegra_fuse *fuse, unsigned int offset);
u32 (*read)(struct tegra_fuse *fuse, unsigned int offset);
-- 
2.33.1



[PATCH v16 29/40] soc/tegra: fuse: Use resource-managed helpers

2021-11-30 Thread Dmitry Osipenko
Use resource-managed helpers to make code cleaner and more correct,
properly releasing all resources in case of driver probe error.

Signed-off-by: Dmitry Osipenko 
---
 drivers/soc/tegra/fuse/fuse-tegra.c   | 32 ++
 drivers/soc/tegra/fuse/fuse-tegra20.c | 33 ---
 2 files changed, 48 insertions(+), 17 deletions(-)

diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c 
b/drivers/soc/tegra/fuse/fuse-tegra.c
index cc032729a143..fe4f935ce73a 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra.c
@@ -182,6 +182,12 @@ static const struct nvmem_cell_info tegra_fuse_cells[] = {
},
 };
 
+static void tegra_fuse_restore(void *base)
+{
+   fuse->clk = NULL;
+   fuse->base = base;
+}
+
 static int tegra_fuse_probe(struct platform_device *pdev)
 {
void __iomem *base = fuse->base;
@@ -189,13 +195,16 @@ static int tegra_fuse_probe(struct platform_device *pdev)
struct resource *res;
int err;
 
+   err = devm_add_action(>dev, tegra_fuse_restore, base);
+   if (err)
+   return err;
+
/* take over the memory region from the early initialization */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
fuse->phys = res->start;
fuse->base = devm_ioremap_resource(>dev, res);
if (IS_ERR(fuse->base)) {
err = PTR_ERR(fuse->base);
-   fuse->base = base;
return err;
}
 
@@ -205,19 +214,20 @@ static int tegra_fuse_probe(struct platform_device *pdev)
dev_err(>dev, "failed to get FUSE clock: %ld",
PTR_ERR(fuse->clk));
 
-   fuse->base = base;
return PTR_ERR(fuse->clk);
}
 
platform_set_drvdata(pdev, fuse);
fuse->dev = >dev;
 
-   pm_runtime_enable(>dev);
+   err = devm_pm_runtime_enable(>dev);
+   if (err)
+   return err;
 
if (fuse->soc->probe) {
err = fuse->soc->probe(fuse);
if (err < 0)
-   goto restore;
+   return err;
}
 
memset(, 0, sizeof(nvmem));
@@ -241,7 +251,7 @@ static int tegra_fuse_probe(struct platform_device *pdev)
err = PTR_ERR(fuse->nvmem);
dev_err(>dev, "failed to register NVMEM device: %d\n",
err);
-   goto restore;
+   return err;
}
 
fuse->rst = devm_reset_control_get_optional(>dev, "fuse");
@@ -249,7 +259,7 @@ static int tegra_fuse_probe(struct platform_device *pdev)
err = PTR_ERR(fuse->rst);
dev_err(>dev, "failed to get FUSE reset: %pe\n",
fuse->rst);
-   goto restore;
+   return err;
}
 
/*
@@ -258,26 +268,20 @@ static int tegra_fuse_probe(struct platform_device *pdev)
 */
err = pm_runtime_resume_and_get(>dev);
if (err)
-   goto restore;
+   return err;
 
err = reset_control_reset(fuse->rst);
pm_runtime_put(>dev);
 
if (err < 0) {
dev_err(>dev, "failed to reset FUSE: %d\n", err);
-   goto restore;
+   return err;
}
 
/* release the early I/O memory mapping */
iounmap(base);
 
return 0;
-
-restore:
-   fuse->clk = NULL;
-   fuse->base = base;
-   pm_runtime_disable(>dev);
-   return err;
 }
 
 static int __maybe_unused tegra_fuse_runtime_resume(struct device *dev)
diff --git a/drivers/soc/tegra/fuse/fuse-tegra20.c 
b/drivers/soc/tegra/fuse/fuse-tegra20.c
index 8ec9fc5e5e4b..12503f563e36 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra20.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra20.c
@@ -94,9 +94,28 @@ static bool dma_filter(struct dma_chan *chan, void 
*filter_param)
return of_device_is_compatible(np, "nvidia,tegra20-apbdma");
 }
 
+static void tegra20_fuse_release_channel(void *data)
+{
+   struct tegra_fuse *fuse = data;
+
+   dma_release_channel(fuse->apbdma.chan);
+   fuse->apbdma.chan = NULL;
+}
+
+static void tegra20_fuse_free_coherent(void *data)
+{
+   struct tegra_fuse *fuse = data;
+
+   dma_free_coherent(fuse->dev, sizeof(u32), fuse->apbdma.virt,
+ fuse->apbdma.phys);
+   fuse->apbdma.virt = NULL;
+   fuse->apbdma.phys = 0x0;
+}
+
 static int tegra20_fuse_probe(struct tegra_fuse *fuse)
 {
dma_cap_mask_t mask;
+   int err;
 
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
@@ -105,13 +124,21 @@ static int tegra20_fuse_probe(struct tegra_fuse *fuse)
if (!fuse->apbdma.chan)
return -EPROBE_DEFER;
 
+   err = devm_add_action_or_reset(fuse->dev, tegra20_fuse_release_channel,
+  fuse);
+   if (err)
+   return err;
+
fuse->apbdma.virt = 

[PATCH v16 23/40] mtd: rawnand: tegra: Add runtime PM and OPP support

2021-11-30 Thread Dmitry Osipenko
The NAND on Tegra belongs to the core power domain and we're going to
enable GENPD support for the core domain. Now NAND must be resumed using
runtime PM API in order to initialize the NAND power state. Add runtime PM
and OPP support to the NAND driver.

Reviewed-by: Ulf Hansson 
Acked-by: Miquel Raynal 
Signed-off-by: Dmitry Osipenko 
---
 drivers/mtd/nand/raw/tegra_nand.c | 58 ++-
 1 file changed, 50 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/nand/raw/tegra_nand.c 
b/drivers/mtd/nand/raw/tegra_nand.c
index 32431bbe69b8..b36e5260ae27 100644
--- a/drivers/mtd/nand/raw/tegra_nand.c
+++ b/drivers/mtd/nand/raw/tegra_nand.c
@@ -17,8 +17,11 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
+#include 
+
 #define COMMAND0x00
 #define   COMMAND_GO   BIT(31)
 #define   COMMAND_CLE  BIT(30)
@@ -1151,6 +1154,7 @@ static int tegra_nand_probe(struct platform_device *pdev)
return -ENOMEM;
 
ctrl->dev = >dev;
+   platform_set_drvdata(pdev, ctrl);
nand_controller_init(>controller);
ctrl->controller.ops = _nand_controller_ops;
 
@@ -1166,14 +1170,23 @@ static int tegra_nand_probe(struct platform_device 
*pdev)
if (IS_ERR(ctrl->clk))
return PTR_ERR(ctrl->clk);
 
-   err = clk_prepare_enable(ctrl->clk);
+   err = devm_tegra_core_dev_init_opp_table_common(>dev);
+   if (err)
+   return err;
+
+   /*
+* This driver doesn't support active power management yet,
+* so we will simply keep device resumed.
+*/
+   pm_runtime_enable(>dev);
+   err = pm_runtime_resume_and_get(>dev);
if (err)
return err;
 
err = reset_control_reset(rst);
if (err) {
dev_err(ctrl->dev, "Failed to reset HW: %d\n", err);
-   goto err_disable_clk;
+   goto err_put_pm;
}
 
writel_relaxed(HWSTATUS_CMD_DEFAULT, ctrl->regs + HWSTATUS_CMD);
@@ -1188,21 +1201,20 @@ static int tegra_nand_probe(struct platform_device 
*pdev)
   dev_name(>dev), ctrl);
if (err) {
dev_err(ctrl->dev, "Failed to get IRQ: %d\n", err);
-   goto err_disable_clk;
+   goto err_put_pm;
}
 
writel_relaxed(DMA_MST_CTRL_IS_DONE, ctrl->regs + DMA_MST_CTRL);
 
err = tegra_nand_chips_init(ctrl->dev, ctrl);
if (err)
-   goto err_disable_clk;
-
-   platform_set_drvdata(pdev, ctrl);
+   goto err_put_pm;
 
return 0;
 
-err_disable_clk:
-   clk_disable_unprepare(ctrl->clk);
+err_put_pm:
+   pm_runtime_put_sync_suspend(ctrl->dev);
+   pm_runtime_force_suspend(ctrl->dev);
return err;
 }
 
@@ -1219,11 +1231,40 @@ static int tegra_nand_remove(struct platform_device 
*pdev)
 
nand_cleanup(chip);
 
+   pm_runtime_put_sync_suspend(ctrl->dev);
+   pm_runtime_force_suspend(ctrl->dev);
+
+   return 0;
+}
+
+static int __maybe_unused tegra_nand_runtime_resume(struct device *dev)
+{
+   struct tegra_nand_controller *ctrl = dev_get_drvdata(dev);
+   int err;
+
+   err = clk_prepare_enable(ctrl->clk);
+   if (err) {
+   dev_err(dev, "Failed to enable clock: %d\n", err);
+   return err;
+   }
+
+   return 0;
+}
+
+static int __maybe_unused tegra_nand_runtime_suspend(struct device *dev)
+{
+   struct tegra_nand_controller *ctrl = dev_get_drvdata(dev);
+
clk_disable_unprepare(ctrl->clk);
 
return 0;
 }
 
+static const struct dev_pm_ops tegra_nand_pm = {
+   SET_RUNTIME_PM_OPS(tegra_nand_runtime_suspend, 
tegra_nand_runtime_resume,
+  NULL)
+};
+
 static const struct of_device_id tegra_nand_of_match[] = {
{ .compatible = "nvidia,tegra20-nand" },
{ /* sentinel */ }
@@ -1234,6 +1275,7 @@ static struct platform_driver tegra_nand_driver = {
.driver = {
.name = "tegra-nand",
.of_match_table = tegra_nand_of_match,
+   .pm = _nand_pm,
},
.probe = tegra_nand_probe,
.remove = tegra_nand_remove,
-- 
2.33.1



[PATCH v16 40/40] ARM: tegra20/30: Disable unused host1x hardware

2021-11-30 Thread Dmitry Osipenko
MPE, VI, EPP and ISP were never used and we don't have drivers for them.
Since these modules are enabled by default in a device-tree, a device is
created for them, blocking voltage scaling because there is no driver to
bind, and thus, state of PMC driver is never synced. Disable them.

Signed-off-by: Dmitry Osipenko 
---
 arch/arm/boot/dts/tegra20.dtsi | 4 
 arch/arm/boot/dts/tegra30.dtsi | 8 
 2 files changed, 12 insertions(+)

diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 7b69ffc57abe..8010b40d7377 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -59,6 +59,7 @@ mpe@5404 {
reset-names = "mpe";
power-domains = <_mpe>;
operating-points-v2 = <_dvfs_opp_table>;
+   status = "disabled";
};
 
vi@5408 {
@@ -70,6 +71,7 @@ vi@5408 {
reset-names = "vi";
power-domains = <_venc>;
operating-points-v2 = <_dvfs_opp_table>;
+   status = "disabled";
};
 
epp@540c {
@@ -81,6 +83,7 @@ epp@540c {
reset-names = "epp";
power-domains = <_core>;
operating-points-v2 = <_dvfs_opp_table>;
+   status = "disabled";
};
 
isp@5410 {
@@ -91,6 +94,7 @@ isp@5410 {
resets = <_car 23>;
reset-names = "isp";
power-domains = <_venc>;
+   status = "disabled";
};
 
gr2d@5414 {
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index 96d1c5688248..c8b22ec30ef0 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -145,6 +145,8 @@ mpe@5404 {
operating-points-v2 = <_dvfs_opp_table>;
 
iommus = < TEGRA_SWGROUP_MPE>;
+
+   status = "disabled";
};
 
vi@5408 {
@@ -158,6 +160,8 @@ vi@5408 {
operating-points-v2 = <_dvfs_opp_table>;
 
iommus = < TEGRA_SWGROUP_VI>;
+
+   status = "disabled";
};
 
epp@540c {
@@ -171,6 +175,8 @@ epp@540c {
operating-points-v2 = <_dvfs_opp_table>;
 
iommus = < TEGRA_SWGROUP_EPP>;
+
+   status = "disabled";
};
 
isp@5410 {
@@ -183,6 +189,8 @@ isp@5410 {
power-domains = <_venc>;
 
iommus = < TEGRA_SWGROUP_ISP>;
+
+   status = "disabled";
};
 
gr2d@5414 {
-- 
2.33.1



[PATCH v16 30/40] soc/tegra: regulators: Prepare for suspend

2021-11-30 Thread Dmitry Osipenko
Depending on hardware version, Tegra SoC may require a higher voltages
during resume from system suspend, otherwise hardware will crash. Set
SoC voltages to a nominal levels during suspend.

Link: 
https://lore.kernel.org/all/a8280b5b-7347-8995-c97b-10b798cdf...@gmail.com/
Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/soc/tegra/regulators-tegra20.c |  99 
 drivers/soc/tegra/regulators-tegra30.c | 122 +
 2 files changed, 221 insertions(+)

diff --git a/drivers/soc/tegra/regulators-tegra20.c 
b/drivers/soc/tegra/regulators-tegra20.c
index b8ce9fd0650d..6a2f90ab9d3e 100644
--- a/drivers/soc/tegra/regulators-tegra20.c
+++ b/drivers/soc/tegra/regulators-tegra20.c
@@ -16,7 +16,9 @@
 #include 
 #include 
 #include 
+#include 
 
+#include 
 #include 
 
 struct tegra_regulator_coupler {
@@ -25,9 +27,12 @@ struct tegra_regulator_coupler {
struct regulator_dev *cpu_rdev;
struct regulator_dev *rtc_rdev;
struct notifier_block reboot_notifier;
+   struct notifier_block suspend_notifier;
int core_min_uV, cpu_min_uV;
bool sys_reboot_mode_req;
bool sys_reboot_mode;
+   bool sys_suspend_mode_req;
+   bool sys_suspend_mode;
 };
 
 static inline struct tegra_regulator_coupler *
@@ -105,6 +110,28 @@ static int tegra20_core_rtc_max_spread(struct 
regulator_dev *core_rdev,
return 15;
 }
 
+static int tegra20_cpu_nominal_uV(void)
+{
+   switch (tegra_sku_info.soc_speedo_id) {
+   case 0:
+   return 110;
+   case 1:
+   return 1025000;
+   default:
+   return 1125000;
+   }
+}
+
+static int tegra20_core_nominal_uV(void)
+{
+   switch (tegra_sku_info.soc_speedo_id) {
+   default:
+   return 1225000;
+   case 2:
+   return 130;
+   }
+}
+
 static int tegra20_core_rtc_update(struct tegra_regulator_coupler *tegra,
   struct regulator_dev *core_rdev,
   struct regulator_dev *rtc_rdev,
@@ -144,6 +171,11 @@ static int tegra20_core_rtc_update(struct 
tegra_regulator_coupler *tegra,
if (err)
return err;
 
+   /* prepare voltage level for suspend */
+   if (tegra->sys_suspend_mode)
+   core_min_uV = clamp(tegra20_core_nominal_uV(),
+   core_min_uV, core_max_uV);
+
core_uV = regulator_get_voltage_rdev(core_rdev);
if (core_uV < 0)
return core_uV;
@@ -279,6 +311,11 @@ static int tegra20_cpu_voltage_update(struct 
tegra_regulator_coupler *tegra,
if (tegra->sys_reboot_mode)
cpu_min_uV = max(cpu_min_uV, tegra->cpu_min_uV);
 
+   /* prepare voltage level for suspend */
+   if (tegra->sys_suspend_mode)
+   cpu_min_uV = clamp(tegra20_cpu_nominal_uV(),
+  cpu_min_uV, cpu_max_uV);
+
if (cpu_min_uV > cpu_uV) {
err = tegra20_core_rtc_update(tegra, core_rdev, rtc_rdev,
  cpu_uV, cpu_min_uV);
@@ -320,6 +357,7 @@ static int tegra20_regulator_balance_voltage(struct 
regulator_coupler *coupler,
}
 
tegra->sys_reboot_mode = READ_ONCE(tegra->sys_reboot_mode_req);
+   tegra->sys_suspend_mode = READ_ONCE(tegra->sys_suspend_mode_req);
 
if (rdev == cpu_rdev)
return tegra20_cpu_voltage_update(tegra, cpu_rdev,
@@ -334,6 +372,63 @@ static int tegra20_regulator_balance_voltage(struct 
regulator_coupler *coupler,
return -EPERM;
 }
 
+static int tegra20_regulator_prepare_suspend(struct tegra_regulator_coupler 
*tegra,
+bool sys_suspend_mode)
+{
+   int err;
+
+   if (!tegra->core_rdev || !tegra->rtc_rdev || !tegra->cpu_rdev)
+   return 0;
+
+   /*
+* All power domains are enabled early during resume from suspend
+* by GENPD core.  Domains like VENC may require a higher voltage
+* when enabled during resume from suspend.  This also prepares
+* hardware for resuming from LP0.
+*/
+
+   WRITE_ONCE(tegra->sys_suspend_mode_req, sys_suspend_mode);
+
+   err = regulator_sync_voltage_rdev(tegra->cpu_rdev);
+   if (err)
+   return err;
+
+   err = regulator_sync_voltage_rdev(tegra->core_rdev);
+   if (err)
+   return err;
+
+   return 0;
+}
+
+static int tegra20_regulator_suspend(struct notifier_block *notifier,
+unsigned long mode, void *arg)
+{
+   struct tegra_regulator_coupler *tegra;
+   int ret = 0;
+
+   tegra = container_of(notifier, struct tegra_regulator_coupler,
+suspend_notifier);
+
+   switch (mode) {
+   case PM_HIBERNATION_PREPARE:
+   case PM_RESTORE_PREPARE:
+   case PM_SUSPEND_PREPARE:
+   ret = 

[PATCH v16 26/40] media: dt: bindings: tegra-vde: Document OPP and power domain

2021-11-30 Thread Dmitry Osipenko
Document new OPP table and power domain properties of the video decoder
hardware.

Reviewed-by: Rob Herring 
Acked-by: Hans Verkuil 
Signed-off-by: Dmitry Osipenko 
---
 .../devicetree/bindings/media/nvidia,tegra-vde.yaml  | 12 
 1 file changed, 12 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/nvidia,tegra-vde.yaml 
b/Documentation/devicetree/bindings/media/nvidia,tegra-vde.yaml
index c143aaa06346..4ecdee1be37e 100644
--- a/Documentation/devicetree/bindings/media/nvidia,tegra-vde.yaml
+++ b/Documentation/devicetree/bindings/media/nvidia,tegra-vde.yaml
@@ -68,6 +68,16 @@ properties:
 description:
   Phandle of the SRAM MMIO node.
 
+  operating-points-v2:
+description:
+  Should contain freqs and voltages and opp-supported-hw property,
+  which is a bitfield indicating SoC speedo or process ID mask.
+
+  power-domains:
+maxItems: 1
+description:
+  Phandle to the SoC core power domain.
+
 required:
   - compatible
   - reg
@@ -104,4 +114,6 @@ examples:
   reset-names = "vde", "mc";
   resets = < 61>, < 13>;
   iommus = < 15>;
+  operating-points-v2 = <_opp_table>;
+  power-domains = <>;
 };
-- 
2.33.1



[PATCH v16 15/40] drm/tegra: vic: Stop channel on suspend

2021-11-30 Thread Dmitry Osipenko
CDMA must be stopped before hardware is suspended. Add channel stopping
to RPM suspend callback. Add system level suspend-resume callbacks.

Runtime PM initialization is moved to host1x client init phase because
RPM callback now uses host1x channel that is available only when host1x
client is registered.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/tegra/vic.c | 36 ++--
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c
index b58e2b99f81a..9622ca96c539 100644
--- a/drivers/gpu/drm/tegra/vic.c
+++ b/drivers/gpu/drm/tegra/vic.c
@@ -151,9 +151,13 @@ static int vic_init(struct host1x_client *client)
goto free_channel;
}
 
+   pm_runtime_enable(client->dev);
+   pm_runtime_use_autosuspend(client->dev);
+   pm_runtime_set_autosuspend_delay(client->dev, 500);
+
err = tegra_drm_register_client(tegra, drm);
if (err < 0)
-   goto free_syncpt;
+   goto disable_rpm;
 
/*
 * Inherit the DMA parameters (such as maximum segment size) from the
@@ -163,7 +167,10 @@ static int vic_init(struct host1x_client *client)
 
return 0;
 
-free_syncpt:
+disable_rpm:
+   pm_runtime_dont_use_autosuspend(client->dev);
+   pm_runtime_force_suspend(client->dev);
+
host1x_syncpt_put(client->syncpts[0]);
 free_channel:
host1x_channel_put(vic->channel);
@@ -188,10 +195,15 @@ static int vic_exit(struct host1x_client *client)
if (err < 0)
return err;
 
+   pm_runtime_dont_use_autosuspend(client->dev);
+   pm_runtime_force_suspend(client->dev);
+
host1x_syncpt_put(client->syncpts[0]);
host1x_channel_put(vic->channel);
host1x_client_iommu_detach(client);
 
+   vic->channel = NULL;
+
if (client->group) {
dma_unmap_single(vic->dev, vic->falcon.firmware.phys,
 vic->falcon.firmware.size, DMA_TO_DEVICE);
@@ -315,6 +327,8 @@ static int vic_runtime_suspend(struct device *dev)
struct vic *vic = dev_get_drvdata(dev);
int err;
 
+   host1x_channel_stop(vic->channel);
+
err = reset_control_assert(vic->rst);
if (err < 0)
return err;
@@ -482,19 +496,8 @@ static int vic_probe(struct platform_device *pdev)
goto exit_falcon;
}
 
-   pm_runtime_enable(>dev);
-   if (!pm_runtime_enabled(>dev)) {
-   err = vic_runtime_resume(>dev);
-   if (err < 0)
-   goto unregister_client;
-   }
-   pm_runtime_set_autosuspend_delay(>dev, 500);
-   pm_runtime_use_autosuspend(>dev);
-
return 0;
 
-unregister_client:
-   host1x_client_unregister(>client.base);
 exit_falcon:
falcon_exit(>falcon);
 
@@ -513,11 +516,6 @@ static int vic_remove(struct platform_device *pdev)
return err;
}
 
-   if (pm_runtime_enabled(>dev))
-   pm_runtime_disable(>dev);
-   else
-   vic_runtime_suspend(>dev);
-
falcon_exit(>falcon);
 
return 0;
@@ -525,6 +523,8 @@ static int vic_remove(struct platform_device *pdev)
 
 static const struct dev_pm_ops vic_pm_ops = {
SET_RUNTIME_PM_OPS(vic_runtime_suspend, vic_runtime_resume, NULL)
+   SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+   pm_runtime_force_resume)
 };
 
 struct platform_driver tegra_vic_driver = {
-- 
2.33.1



[PATCH v16 24/40] spi: tegra20-slink: Add OPP support

2021-11-30 Thread Dmitry Osipenko
The SPI on Tegra belongs to the core power domain and we're going to
enable GENPD support for the core domain. Now SPI driver must use OPP
API for driving the controller's clock rate because OPP API takes care
of reconfiguring the domain's performance state in accordance to the
rate. Add OPP support to the driver.

Acked-by: Mark Brown 
Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/spi/spi-tegra20-slink.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c
index e8204e155484..2a03739a0c60 100644
--- a/drivers/spi/spi-tegra20-slink.c
+++ b/drivers/spi/spi-tegra20-slink.c
@@ -18,12 +18,15 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 
+#include 
+
 #define SLINK_COMMAND  0x000
 #define SLINK_BIT_LENGTH(x)(((x) & 0x1f) << 0)
 #define SLINK_WORD_SIZE(x) (((x) & 0x1f) << 5)
@@ -680,7 +683,7 @@ static int tegra_slink_start_transfer_one(struct spi_device 
*spi,
bits_per_word = t->bits_per_word;
speed = t->speed_hz;
if (speed != tspi->cur_speed) {
-   clk_set_rate(tspi->clk, speed * 4);
+   dev_pm_opp_set_rate(tspi->dev, speed * 4);
tspi->cur_speed = speed;
}
 
@@ -1066,6 +1069,10 @@ static int tegra_slink_probe(struct platform_device 
*pdev)
goto exit_free_master;
}
 
+   ret = devm_tegra_core_dev_init_opp_table_common(>dev);
+   if (ret)
+   goto exit_free_master;
+
tspi->max_buf_size = SLINK_FIFO_DEPTH << 2;
tspi->dma_buf_size = DEFAULT_SPI_DMA_BUF_LEN;
 
-- 
2.33.1



[PATCH v16 12/40] drm/tegra: hdmi: Add OPP support

2021-11-30 Thread Dmitry Osipenko
The HDMI on Tegra belongs to the core power domain and we're going to
enable GENPD support for the core domain. Now HDMI driver must use
OPP API for driving the controller's clock rate because OPP API takes
care of reconfiguring the domain's performance state based on HDMI clock
rate. Add OPP support to the HDMI driver.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/tegra/hdmi.c | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
index e5d2a4026028..9a87d351a828 100644
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -11,10 +11,13 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 
+#include 
+
 #include 
 #include 
 #include 
@@ -1195,7 +1198,7 @@ static void tegra_hdmi_encoder_enable(struct drm_encoder 
*encoder)
h_back_porch = mode->htotal - mode->hsync_end;
h_front_porch = mode->hsync_start - mode->hdisplay;
 
-   err = clk_set_rate(hdmi->clk, hdmi->pixel_clock);
+   err = dev_pm_opp_set_rate(hdmi->dev, hdmi->pixel_clock);
if (err < 0) {
dev_err(hdmi->dev, "failed to set HDMI clock frequency: %d\n",
err);
@@ -1732,7 +1735,14 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
}
 
platform_set_drvdata(pdev, hdmi);
-   pm_runtime_enable(>dev);
+
+   err = devm_pm_runtime_enable(>dev);
+   if (err)
+   return err;
+
+   err = devm_tegra_core_dev_init_opp_table_common(>dev);
+   if (err)
+   return err;
 
INIT_LIST_HEAD(>client.list);
hdmi->client.ops = _client_ops;
@@ -1753,8 +1763,6 @@ static int tegra_hdmi_remove(struct platform_device *pdev)
struct tegra_hdmi *hdmi = platform_get_drvdata(pdev);
int err;
 
-   pm_runtime_disable(>dev);
-
err = host1x_client_unregister(>client);
if (err < 0) {
dev_err(>dev, "failed to unregister host1x client: %d\n",
-- 
2.33.1



[PATCH v16 10/40] drm/tegra: submit: Add missing pm_runtime_mark_last_busy()

2021-11-30 Thread Dmitry Osipenko
Runtime PM auto-suspension doesn't work without pm_runtime_mark_last_busy(),
add it.

Cc: 
Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/tegra/submit.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/tegra/submit.c b/drivers/gpu/drm/tegra/submit.c
index c32698404e36..1ba4d539da06 100644
--- a/drivers/gpu/drm/tegra/submit.c
+++ b/drivers/gpu/drm/tegra/submit.c
@@ -504,8 +504,10 @@ static void release_job(struct host1x_job *job)
kfree(job_data->used_mappings);
kfree(job_data);
 
-   if (pm_runtime_enabled(client->base.dev))
+   if (pm_runtime_enabled(client->base.dev)) {
+   pm_runtime_mark_last_busy(client->base.dev);
pm_runtime_put_autosuspend(client->base.dev);
+   }
 }
 
 int tegra_drm_ioctl_channel_submit(struct drm_device *drm, void *data,
-- 
2.33.1



[PATCH v16 07/40] dt-bindings: host1x: Document Memory Client resets of Host1x, GR2D and GR3D

2021-11-30 Thread Dmitry Osipenko
Memory Client should be blocked before hardware reset is asserted in order
to prevent memory corruption and hanging of memory controller.

Document Memory Client resets of Host1x, GR2D and GR3D hardware units.

Reviewed-by: Rob Herring 
Signed-off-by: Dmitry Osipenko 
---
 .../bindings/display/tegra/nvidia,tegra20-host1x.txt  | 4 
 1 file changed, 4 insertions(+)

diff --git 
a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt 
b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
index 62861a8fb5c6..e61999ce54e9 100644
--- a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
+++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
@@ -19,6 +19,7 @@ Required properties:
   See ../reset/reset.txt for details.
 - reset-names: Must include the following entries:
   - host1x
+  - mc
 
 Optional properties:
 - operating-points-v2: See ../bindings/opp/opp.txt for details.
@@ -198,6 +199,7 @@ of the following host1x client modules:
 See ../reset/reset.txt for details.
   - reset-names: Must include the following entries:
 - 2d
+- mc
 
   Optional properties:
   - interconnects: Must contain entry for the GR2D memory clients.
@@ -224,6 +226,8 @@ of the following host1x client modules:
   - reset-names: Must include the following entries:
 - 3d
 - 3d2 (Only required on SoCs with two 3D clocks)
+- mc
+- mc2 (Only required on SoCs with two 3D clocks)
 
   Optional properties:
   - interconnects: Must contain entry for the GR3D memory clients.
-- 
2.33.1



[PATCH v16 03/40] soc/tegra: Don't print error message when OPPs not available

2021-11-30 Thread Dmitry Osipenko
Previously we assumed that devm_tegra_core_dev_init_opp_table() will
be used only by drivers that will always have device with OPP table,
but this is not true anymore. For example now Tegra30 will have OPP table
for PWM, but Tegra20 not and both use the same driver. Hence let's not
print the error message about missing OPP table in the common helper,
we can print it elsewhere.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/soc/tegra/common.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/soc/tegra/common.c b/drivers/soc/tegra/common.c
index 35c882da55fc..32c346b72635 100644
--- a/drivers/soc/tegra/common.c
+++ b/drivers/soc/tegra/common.c
@@ -136,9 +136,7 @@ int devm_tegra_core_dev_init_opp_table(struct device *dev,
 */
err = devm_pm_opp_of_add_table(dev);
if (err) {
-   if (err == -ENODEV)
-   dev_err_once(dev, "OPP table not found, please update 
device-tree\n");
-   else
+   if (err != -ENODEV)
dev_err(dev, "failed to add OPP table: %d\n", err);
 
return err;
-- 
2.33.1



[PATCH v16 11/40] drm/tegra: dc: Support OPP and SoC core voltage scaling

2021-11-30 Thread Dmitry Osipenko
Add OPP and SoC core voltage scaling support to the display controller
driver. This is required for enabling system-wide DVFS on pre-Tegra186
SoCs.

Reviewed-by: Ulf Hansson 
Tested-by: Peter Geis  # Ouya T30
Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20 and TK1 T124
Tested-by: Matt Merhar  # Ouya T30
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/tegra/dc.c | 79 ++
 drivers/gpu/drm/tegra/dc.h |  2 +
 2 files changed, 81 insertions(+)

diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index a457ee954a49..eb70eee8992a 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -11,9 +11,12 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 
+#include 
 #include 
 
 #include 
@@ -1834,6 +1837,52 @@ int tegra_dc_state_setup_clock(struct tegra_dc *dc,
return 0;
 }
 
+static void tegra_dc_update_voltage_state(struct tegra_dc *dc,
+ struct tegra_dc_state *state)
+{
+   unsigned long rate, pstate;
+   struct dev_pm_opp *opp;
+   int err;
+
+   if (!dc->has_opp_table)
+   return;
+
+   /* calculate actual pixel clock rate which depends on internal divider 
*/
+   rate = DIV_ROUND_UP(clk_get_rate(dc->clk) * 2, state->div + 2);
+
+   /* find suitable OPP for the rate */
+   opp = dev_pm_opp_find_freq_ceil(dc->dev, );
+
+   /*
+* Very high resolution modes may results in a clock rate that is
+* above the characterized maximum. In this case it's okay to fall
+* back to the characterized maximum.
+*/
+   if (opp == ERR_PTR(-ERANGE))
+   opp = dev_pm_opp_find_freq_floor(dc->dev, );
+
+   if (IS_ERR(opp)) {
+   dev_err(dc->dev, "failed to find OPP for %luHz: %pe\n",
+   rate, opp);
+   return;
+   }
+
+   pstate = dev_pm_opp_get_required_pstate(opp, 0);
+   dev_pm_opp_put(opp);
+
+   /*
+* The minimum core voltage depends on the pixel clock rate (which
+* depends on internal clock divider of the CRTC) and not on the
+* rate of the display controller clock. This is why we're not using
+* dev_pm_opp_set_rate() API and instead controlling the power domain
+* directly.
+*/
+   err = dev_pm_genpd_set_performance_state(dc->dev, pstate);
+   if (err)
+   dev_err(dc->dev, "failed to set power domain state to %lu: 
%d\n",
+   pstate, err);
+}
+
 static void tegra_dc_set_clock_rate(struct tegra_dc *dc,
struct tegra_dc_state *state)
 {
@@ -1867,6 +1916,8 @@ static void tegra_dc_set_clock_rate(struct tegra_dc *dc,
DRM_DEBUG_KMS("rate: %lu, div: %u\n", clk_get_rate(dc->clk),
  state->div);
DRM_DEBUG_KMS("pclk: %lu\n", state->pclk);
+
+   tegra_dc_update_voltage_state(dc, state);
 }
 
 static void tegra_dc_stop(struct tegra_dc *dc)
@@ -2057,6 +2108,13 @@ static void tegra_crtc_atomic_disable(struct drm_crtc 
*crtc,
err = host1x_client_suspend(>client);
if (err < 0)
dev_err(dc->dev, "failed to suspend: %d\n", err);
+
+   if (dc->has_opp_table) {
+   err = dev_pm_genpd_set_performance_state(dc->dev, 0);
+   if (err)
+   dev_err(dc->dev,
+   "failed to clear power domain state: %d\n", 
err);
+   }
 }
 
 static void tegra_crtc_atomic_enable(struct drm_crtc *crtc,
@@ -3058,6 +3116,23 @@ static int tegra_dc_couple(struct tegra_dc *dc)
return 0;
 }
 
+static int tegra_dc_init_opp_table(struct tegra_dc *dc)
+{
+   struct tegra_core_opp_params opp_params = {};
+   int err;
+
+   err = devm_tegra_core_dev_init_opp_table(dc->dev, _params);
+   if (err && err != -ENODEV)
+   return err;
+
+   if (err)
+   dc->has_opp_table = false;
+   else
+   dc->has_opp_table = true;
+
+   return 0;
+}
+
 static int tegra_dc_probe(struct platform_device *pdev)
 {
u64 dma_mask = dma_get_mask(pdev->dev.parent);
@@ -3123,6 +3198,10 @@ static int tegra_dc_probe(struct platform_device *pdev)
tegra_powergate_power_off(dc->powergate);
}
 
+   err = tegra_dc_init_opp_table(dc);
+   if (err < 0)
+   return err;
+
dc->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(dc->regs))
return PTR_ERR(dc->regs);
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
index c9c4c45c0518..3f91a10ea6c7 100644
--- a/drivers/gpu/drm/tegra/dc.h
+++ b/drivers/gpu/drm/tegra/dc.h
@@ -101,6 +101,8 @@ struct tegra_dc {
struct drm_info_list *debugfs_files;
 
const struct tegra_dc_soc_info *soc;
+
+   bool has_opp_table;
 };
 
 static inline struct tegra_dc *
-- 
2.33.1



[PATCH v16 09/40] gpu: host1x: Add host1x_channel_stop()

2021-11-30 Thread Dmitry Osipenko
Add host1x_channel_stop() which waits till channel becomes idle and then
stops the channel hardware. This is needed for supporting suspend/resume
by host1x drivers since the hardware state is lost after power-gating,
thus the channel needs to be stopped before client enters into suspend.

Tested-by: Peter Geis  # Ouya T30
Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20 and TK1 T124
Tested-by: Matt Merhar  # Ouya T30
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/host1x/channel.c | 8 
 include/linux/host1x.h   | 1 +
 2 files changed, 9 insertions(+)

diff --git a/drivers/gpu/host1x/channel.c b/drivers/gpu/host1x/channel.c
index 4cd212bb570d..2a9a3a8d5931 100644
--- a/drivers/gpu/host1x/channel.c
+++ b/drivers/gpu/host1x/channel.c
@@ -75,6 +75,14 @@ struct host1x_channel *host1x_channel_get_index(struct 
host1x *host,
return ch;
 }
 
+void host1x_channel_stop(struct host1x_channel *channel)
+{
+   struct host1x *host = dev_get_drvdata(channel->dev->parent);
+
+   host1x_hw_cdma_stop(host, >cdma);
+}
+EXPORT_SYMBOL(host1x_channel_stop);
+
 static void release_channel(struct kref *kref)
 {
struct host1x_channel *channel =
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index 2ca53d7ed7ca..e8dc5bc41f79 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -226,6 +226,7 @@ struct host1x_job;
 
 struct host1x_channel *host1x_channel_request(struct host1x_client *client);
 struct host1x_channel *host1x_channel_get(struct host1x_channel *channel);
+void host1x_channel_stop(struct host1x_channel *channel);
 void host1x_channel_put(struct host1x_channel *channel);
 int host1x_job_submit(struct host1x_job *job);
 
-- 
2.33.1



[PATCH v16 02/40] soc/tegra: Add devm_tegra_core_dev_init_opp_table_common()

2021-11-30 Thread Dmitry Osipenko
Only couple drivers need to get the -ENODEV error code and majority of
drivers need to explicitly initialize the performance state. Add new
common helper which sets up OPP table for these drivers.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 include/soc/tegra/common.h | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/include/soc/tegra/common.h b/include/soc/tegra/common.h
index af41ad80ec21..8ec1ac07fc85 100644
--- a/include/soc/tegra/common.h
+++ b/include/soc/tegra/common.h
@@ -39,4 +39,19 @@ devm_tegra_core_dev_init_opp_table(struct device *dev,
 }
 #endif
 
+static inline int
+devm_tegra_core_dev_init_opp_table_common(struct device *dev)
+{
+   struct tegra_core_opp_params opp_params = {};
+   int err;
+
+   opp_params.init_state = true;
+
+   err = devm_tegra_core_dev_init_opp_table(dev, _params);
+   if (err != -ENODEV)
+   return err;
+
+   return 0;
+}
+
 #endif /* __SOC_TEGRA_COMMON_H__ */
-- 
2.33.1



[PATCH v16 08/40] gpu: host1x: Add initial runtime PM and OPP support

2021-11-30 Thread Dmitry Osipenko
Add runtime PM and OPP support to the Host1x driver. For the starter we
will keep host1x always-on because dynamic power management require a major
refactoring of the driver code since lot's of code paths are missing the
RPM handling and we're going to remove some of these paths in the future.

Reviewed-by: Ulf Hansson 
Tested-by: Peter Geis  # Ouya T30
Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20 and TK1 T124
Tested-by: Matt Merhar  # Ouya T30
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/host1x/debug.c |  15 +++
 drivers/gpu/host1x/dev.c   | 150 +++--
 drivers/gpu/host1x/dev.h   |   3 +-
 drivers/gpu/host1x/hw/channel_hw.c |  44 -
 drivers/gpu/host1x/intr.c  |   3 -
 drivers/gpu/host1x/syncpt.c|   5 +-
 6 files changed, 164 insertions(+), 56 deletions(-)

diff --git a/drivers/gpu/host1x/debug.c b/drivers/gpu/host1x/debug.c
index 8a14880c61bb..18d9c8d206e3 100644
--- a/drivers/gpu/host1x/debug.c
+++ b/drivers/gpu/host1x/debug.c
@@ -7,6 +7,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 
@@ -52,6 +53,11 @@ static int show_channel(struct host1x_channel *ch, void 
*data, bool show_fifo)
 {
struct host1x *m = dev_get_drvdata(ch->dev->parent);
struct output *o = data;
+   int err;
+
+   err = pm_runtime_resume_and_get(m->dev);
+   if (err < 0)
+   return err;
 
mutex_lock(>cdma.lock);
mutex_lock(_lock);
@@ -64,6 +70,8 @@ static int show_channel(struct host1x_channel *ch, void 
*data, bool show_fifo)
mutex_unlock(_lock);
mutex_unlock(>cdma.lock);
 
+   pm_runtime_put(m->dev);
+
return 0;
 }
 
@@ -71,9 +79,14 @@ static void show_syncpts(struct host1x *m, struct output *o)
 {
struct list_head *pos;
unsigned int i;
+   int err;
 
host1x_debug_output(o, " syncpts \n");
 
+   err = pm_runtime_resume_and_get(m->dev);
+   if (err < 0)
+   return;
+
for (i = 0; i < host1x_syncpt_nb_pts(m); i++) {
u32 max = host1x_syncpt_read_max(m->syncpt + i);
u32 min = host1x_syncpt_load(m->syncpt + i);
@@ -101,6 +114,8 @@ static void show_syncpts(struct host1x *m, struct output *o)
base_val);
}
 
+   pm_runtime_put(m->dev);
+
host1x_debug_output(o, "\n");
 }
 
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index 3d4cabdbc78d..c42ab78327e7 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -6,14 +6,18 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 
+#include 
+
 #define CREATE_TRACE_POINTS
 #include 
 #undef CREATE_TRACE_POINTS
@@ -208,6 +212,9 @@ static void host1x_setup_sid_table(struct host1x *host)
const struct host1x_info *info = host->info;
unsigned int i;
 
+   if (!info->has_hypervisor)
+   return;
+
for (i = 0; i < info->num_sid_entries; i++) {
const struct host1x_sid_entry *entry = >sid_table[i];
 
@@ -365,6 +372,27 @@ static void host1x_iommu_exit(struct host1x *host)
}
 }
 
+static int host1x_get_resets(struct host1x *host)
+{
+   int err;
+
+   host->resets[0].id = "mc";
+   host->resets[1].id = "host1x";
+   host->nresets = ARRAY_SIZE(host->resets);
+
+   err = devm_reset_control_bulk_get_optional_exclusive_released(
+   host->dev, host->nresets, host->resets);
+   if (err) {
+   dev_err(host->dev, "failed to get reset: %d\n", err);
+   return err;
+   }
+
+   if (WARN_ON(!host->resets[1].rstc))
+   return -ENOENT;
+
+   return 0;
+}
+
 static int host1x_probe(struct platform_device *pdev)
 {
struct host1x *host;
@@ -442,12 +470,9 @@ static int host1x_probe(struct platform_device *pdev)
return err;
}
 
-   host->rst = devm_reset_control_get(>dev, "host1x");
-   if (IS_ERR(host->rst)) {
-   err = PTR_ERR(host->rst);
-   dev_err(>dev, "failed to get reset: %d\n", err);
+   err = host1x_get_resets(host);
+   if (err)
return err;
-   }
 
err = host1x_iommu_init(host);
if (err < 0) {
@@ -462,22 +487,10 @@ static int host1x_probe(struct platform_device *pdev)
goto iommu_exit;
}
 
-   err = clk_prepare_enable(host->clk);
-   if (err < 0) {
-   dev_err(>dev, "failed to enable clock\n");
-   goto free_channels;
-   }
-
-   err = reset_control_deassert(host->rst);
-   if (err < 0) {
-   dev_err(>dev, "failed to deassert reset: %d\n", err);
-   goto unprepare_disable;
-   }
-
err = host1x_syncpt_init(host);
if (err) {
dev_err(>dev, "failed to initialize syncpts\n");
-   

[PATCH v16 04/40] dt-bindings: clock: tegra-car: Document new clock sub-nodes

2021-11-30 Thread Dmitry Osipenko
Document sub-nodes which describe Tegra SoC clocks that require a higher
voltage of the core power domain in order to operate properly on a higher
clock rates.  Each node contains a phandle to OPP table and power domain.

The root PLLs and system clocks don't have any specific device dedicated
to them, clock controller is in charge of managing power for them.

Reviewed-by: Rob Herring 
Signed-off-by: Dmitry Osipenko 
---
 .../bindings/clock/nvidia,tegra20-car.yaml| 37 +++
 1 file changed, 37 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra20-car.yaml 
b/Documentation/devicetree/bindings/clock/nvidia,tegra20-car.yaml
index 459d2a525393..f832abb7f11a 100644
--- a/Documentation/devicetree/bindings/clock/nvidia,tegra20-car.yaml
+++ b/Documentation/devicetree/bindings/clock/nvidia,tegra20-car.yaml
@@ -42,6 +42,36 @@ properties:
   "#reset-cells":
 const: 1
 
+patternProperties:
+  "^(sclk)|(pll-[cem])$":
+type: object
+properties:
+  compatible:
+enum:
+  - nvidia,tegra20-sclk
+  - nvidia,tegra30-sclk
+  - nvidia,tegra30-pllc
+  - nvidia,tegra30-plle
+  - nvidia,tegra30-pllm
+
+  operating-points-v2: true
+
+  clocks:
+items:
+  - description: node's clock
+
+  power-domains:
+maxItems: 1
+description: phandle to the core SoC power domain
+
+required:
+  - compatible
+  - operating-points-v2
+  - clocks
+  - power-domains
+
+additionalProperties: false
+
 required:
   - compatible
   - reg
@@ -59,6 +89,13 @@ examples:
 reg = <0x60006000 0x1000>;
 #clock-cells = <1>;
 #reset-cells = <1>;
+
+sclk {
+compatible = "nvidia,tegra20-sclk";
+operating-points-v2 = <_table>;
+clocks = <_car TEGRA20_CLK_SCLK>;
+power-domains = <>;
+};
 };
 
 usb-controller@c5004000 {
-- 
2.33.1



[PATCH v16 06/40] dt-bindings: host1x: Document OPP and power domain properties

2021-11-30 Thread Dmitry Osipenko
Document new DVFS OPP table and power domain properties of the Host1x bus
and devices sitting on the bus.

Reviewed-by: Rob Herring 
Signed-off-by: Dmitry Osipenko 
---
 .../display/tegra/nvidia,tegra20-host1x.txt   | 49 +++
 1 file changed, 49 insertions(+)

diff --git 
a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt 
b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
index 8a6d3e1ee306..62861a8fb5c6 100644
--- a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
+++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
@@ -20,6 +20,18 @@ Required properties:
 - reset-names: Must include the following entries:
   - host1x
 
+Optional properties:
+- operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - power-domains: Phandle to HEG or core power domain.
+
+For each opp entry in 'operating-points-v2' table of host1x and its modules:
+- opp-supported-hw: One bitfield indicating:
+   On Tegra20: SoC process ID mask
+   On Tegra30+: SoC speedo ID mask
+
+   A bitwise AND is performed against the value and if any bit
+   matches, the OPP gets enabled.
+
 Each host1x client module having to perform DMA through the Memory Controller
 should have the interconnect endpoints set to the Memory Client and External
 Memory respectively.
@@ -45,6 +57,8 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
 interconnect entry. Consult TRM documentation for information about
 available memory clients, see MEMORY CONTROLLER section.
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - power-domains: Phandle to MPE power domain.
 
 - vi: video input
 
@@ -128,6 +142,8 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
 interconnect entry. Consult TRM documentation for information about
 available memory clients, see MEMORY CONTROLLER section.
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - power-domains: Phandle to VENC power domain.
 
 - epp: encoder pre-processor
 
@@ -147,6 +163,8 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
 interconnect entry. Consult TRM documentation for information about
 available memory clients, see MEMORY CONTROLLER section.
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - power-domains: Phandle to HEG or core power domain.
 
 - isp: image signal processor
 
@@ -166,6 +184,7 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
 interconnect entry. Consult TRM documentation for information about
 available memory clients, see MEMORY CONTROLLER section.
+  - power-domains: Phandle to VENC or core power domain.
 
 - gr2d: 2D graphics engine
 
@@ -185,6 +204,8 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
 interconnect entry. Consult TRM documentation for information about
 available memory clients, see MEMORY CONTROLLER section.
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - power-domains: Phandle to HEG or core power domain.
 
 - gr3d: 3D graphics engine
 
@@ -209,6 +230,8 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
 interconnect entry. Consult TRM documentation for information about
 available memory clients, see MEMORY CONTROLLER section.
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - power-domains: Phandles to 3D or core power domain.
 
 - dc: display controller
 
@@ -241,6 +264,8 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
 interconnect entry. Consult TRM documentation for information about
 available memory clients, see MEMORY CONTROLLER section.
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - power-domains: Phandle to core power domain.
 
 - hdmi: High Definition Multimedia Interface
 
@@ -267,6 +292,7 @@ of the following host1x client modules:
   - nvidia,hpd-gpio: specifies a GPIO used for hotplug detection
   - nvidia,edid: supplies a binary EDID blob
   - nvidia,panel: phandle of a display panel
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
 
 - tvo: TV encoder output
 
@@ -277,6 +303,10 @@ of the following host1x client modules:
   - clocks: Must contain one entry, for the module clock.
 See ../clocks/clock-bindings.txt for details.
 
+  Optional properties:
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - power-domains: Phandle to core power domain.
+
 - dsi: display serial interface
 
   Required properties:
@@ 

[PATCH v16 05/40] clk: tegra: Support runtime PM and power domain

2021-11-30 Thread Dmitry Osipenko
The Clock-and-Reset controller resides in a core power domain on NVIDIA
Tegra SoCs.  In order to support voltage scaling of the core power domain,
we hook up DVFS-capable clocks to the core GENPD for managing of the
GENPD's performance state based on the clock changes.

Some clocks don't have any specific physical hardware unit that backs
them, like root PLLs and system clock and they have theirs own voltage
requirements.  This patch adds new clk-device driver that backs the clocks
and provides runtime PM functionality for them.  A virtual clk-device is
created for each such DVFS-capable clock at the clock's registration time
by the new tegra_clk_register() helper.  Driver changes clock's device
GENPD performance state based on clk-rate notifications.

In result we have this sequence of events:

  1. Clock driver creates virtual device for selective clocks, enables
 runtime PM for the created device and registers the clock.
  2. Clk-device driver starts to listen to clock rate changes.
  3. Something changes clk rate or enables/disables clk.
  4. CCF core propagates the change through the clk tree.
  5. Clk-device driver gets clock rate-change notification or GENPD core
 handles prepare/unprepare of the clock.
  6. Clk-device driver changes GENPD performance state on clock rate
 change.
  7. GENPD driver changes voltage regulator state change.
  8. The regulator state is committed to hardware via I2C.

We rely on fact that DVFS is not needed for Tegra I2C and that Tegra I2C
driver already keeps clock always-prepared.  Hence I2C subsystem stays
independent from the clk power management and there are no deadlock spots
in the sequence.

Currently all clocks are registered very early during kernel boot when the
device driver core isn't available yet.  The clk-device can't be created
at that time.  This patch splits the registration of the clocks in two
phases:

  1. Register all essential clocks which don't use RPM and are needed
 during early boot.

  2. Register at a later boot time the rest of clocks.

This patch adds power management support for Tegra20 and Tegra30 clocks.

Reviewed-by: Ulf Hansson 
Tested-by: Peter Geis  # Ouya T30
Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20 and TK1 T124
Tested-by: Matt Merhar  # Ouya T30
Signed-off-by: Dmitry Osipenko 
---
 drivers/clk/tegra/Makefile  |   1 +
 drivers/clk/tegra/clk-device.c  | 199 
 drivers/clk/tegra/clk-pll.c |   2 +-
 drivers/clk/tegra/clk-super.c   |   2 +-
 drivers/clk/tegra/clk-tegra20.c |  77 +---
 drivers/clk/tegra/clk-tegra30.c | 116 ++-
 drivers/clk/tegra/clk.c |  75 +++-
 drivers/clk/tegra/clk.h |   2 +
 8 files changed, 420 insertions(+), 54 deletions(-)
 create mode 100644 drivers/clk/tegra/clk-device.c

diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile
index 7b1816856eb5..a0715cdfc1a4 100644
--- a/drivers/clk/tegra/Makefile
+++ b/drivers/clk/tegra/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-y  += clk.o
 obj-y  += clk-audio-sync.o
+obj-y  += clk-device.o
 obj-y  += clk-dfll.o
 obj-y  += clk-divider.o
 obj-y  += clk-periph.o
diff --git a/drivers/clk/tegra/clk-device.c b/drivers/clk/tegra/clk-device.c
new file mode 100644
index ..c58beaf8afbc
--- /dev/null
+++ b/drivers/clk/tegra/clk-device.c
@@ -0,0 +1,199 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include "clk.h"
+
+/*
+ * This driver manages performance state of the core power domain for the
+ * independent PLLs and system clocks.  We created a virtual clock device
+ * for such clocks, see tegra_clk_dev_register().
+ */
+
+struct tegra_clk_device {
+   struct notifier_block clk_nb;
+   struct device *dev;
+   struct clk_hw *hw;
+   struct mutex lock;
+};
+
+static int tegra_clock_set_pd_state(struct tegra_clk_device *clk_dev,
+   unsigned long rate)
+{
+   struct device *dev = clk_dev->dev;
+   struct dev_pm_opp *opp;
+   unsigned int pstate;
+
+   opp = dev_pm_opp_find_freq_ceil(dev, );
+   if (opp == ERR_PTR(-ERANGE)) {
+   /*
+* Some clocks may be unused by a particular board and they
+* may have uninitiated clock rate that is overly high.  In
+* this case clock is expected to be disabled, but still we
+* need to set up performance state of the power domain and
+* not error out clk initialization.  A typical example is
+* a PCIe clock on Android tablets.
+*/
+   dev_dbg(dev, "failed to find ceil 

[PATCH v16 01/40] soc/tegra: Enable runtime PM during OPP state-syncing

2021-11-30 Thread Dmitry Osipenko
GENPD core now can set up domain's performance state properly while device
is RPM-suspended. Runtime PM of a device must be enabled during setup
because GENPD checks whether device is suspended and check doesn't work
while RPM is disabled. Instead of replicating the boilerplate RPM-enable
code around OPP helper for each driver, let's make OPP helper to take care
of enabling it.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/soc/tegra/common.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/drivers/soc/tegra/common.c b/drivers/soc/tegra/common.c
index cd33e99249c3..35c882da55fc 100644
--- a/drivers/soc/tegra/common.c
+++ b/drivers/soc/tegra/common.c
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -43,6 +44,7 @@ static int tegra_core_dev_init_opp_state(struct device *dev)
 {
unsigned long rate;
struct clk *clk;
+   bool rpm_enabled;
int err;
 
clk = devm_clk_get(dev, NULL);
@@ -57,8 +59,31 @@ static int tegra_core_dev_init_opp_state(struct device *dev)
return -EINVAL;
}
 
+   /*
+* Runtime PM of the device must be enabled in order to set up
+* GENPD's performance properly because GENPD core checks whether
+* device is suspended and this check doesn't work while RPM is
+* disabled. This makes sure the OPP vote below gets cached in
+* GENPD for the device. Instead, the vote is done the next time
+* the device gets runtime resumed.
+*/
+   rpm_enabled = pm_runtime_enabled(dev);
+   if (!rpm_enabled)
+   pm_runtime_enable(dev);
+
+   /* should never happen in practice */
+   if (!pm_runtime_enabled(dev)) {
+   dev_WARN(dev, "failed to enable runtime PM\n");
+   pm_runtime_disable(dev);
+   return -EINVAL;
+   }
+
/* first dummy rate-setting initializes voltage vote */
err = dev_pm_opp_set_rate(dev, rate);
+
+   if (!rpm_enabled)
+   pm_runtime_disable(dev);
+
if (err) {
dev_err(dev, "failed to initialize OPP clock: %d\n", err);
return err;
-- 
2.33.1



[PATCH v16 00/40] NVIDIA Tegra power management patches for 5.17

2021-11-30 Thread Dmitry Osipenko
This series adds runtime PM support to Tegra drivers and enables core
voltage scaling for Tegra20/30 SoCs, resolving overheating troubles.

All patches in this series are interdependent and should go via Tegra tree
for simplicity.

Changelog:

v16: - Replaced redundant "context->client" with "client" in gr2d/3d
   RPM patches, which was spotted by Michał Mirosław in v15.

 - Added new patch that consolidates the RPM management of older
   UAPI code path.

 - Added stable tag to "submit: Add missing pm_runtime_mark_last_busy()"
   patch and reordered it such that it could be backported without merge
   conflicts.

v15: - Added r-b from Ulf Hansson to "soc/tegra: Enable runtime PM during
   OPP state-syncing" patch and added extra sanity-check to this patch
   which ensures that RPM is indeed enabled.

 - Fixed double RPM-disable on unbind for drivers that used
   devm_pm_runtime_enable() + pm_runtime_force_suspend().

 - Added link with additional info to commit message of "regulators:
   Prepare for suspend" patch.

v14: - Fixed missing runtime PM syncing on removal of drivers, which was
   spotted by Ulf Hansson in v13.

 - clk-device driver now resumes RPM on system suspend instead of
   preparing clock which it backs. This was suggested by Ulf Hansson.

 - clk-device driver now syncs power domain performance unconditionally
   during driver's probe time since GENPD API allows to do this now.
   It was spotted by Ulf Hansson.

 - Added new "Enable runtime PM during OPP state-syncing" patch, which
   allows drivers to sync state at any time. Previously drivers were
   obligated to take care of enabling RPM at the "right" time.

 - Moved runtime PM initialization/uninitialization of DRM drivers that
   use host1x channel to host1x client init/deinit phase. I noticed that
   there is UAF problem because RPM-suspend callback waits until channel
   is idling and channel is already released/freed during driver's removal
   phase.

 - Added system suspend support to the new NVDEC DRM driver.

 - Added missing pm_runtime_mark_last_busy() to DRM driver.

 - Corrected VDE GENPD patch which previously made video decoder clock
   always-enabled by mistake if legacy PD code path was used. It was
   spotted while we were testing VDE on Tegra114 that doesn't support
   GENPD yet.

 - Added ack from Peter Chen to the USB patch that he gave to v13.

 - Changed OPP table names in accordance to the new naming scheme
   required by the recent core OPP binding.

 - Added 500MHz memory OPP entry used by ASUS Transformer tablets.

v13: - Fixed compile-test error reported by build bot by reverting the
   mmc/ patch to v11. The sdhci_suspend/resume_host() functions aren't
   available with the disabled CONFIG_PM_SLEEP, some code needs the
   ifdef.

 - Added last r-b from Rob Herring for the DT patches.

 - Corrected clk/ PM domain-support patch by not using the
   devm_tegra_core_dev_init_opp_table_common() helper, which I
   utilized in v12. The clk driver implements its own power domain
   state syncing and common helper shouldn't be used. This fixes driver
   probing for some clocks on some devices. It was reported by
   Svyatoslav Ryhel for PLLE OPP error on T30 Asus Transformer tablet.

v12: - Added r-b from Rob Herring to the host1x binding patch.

 - Added acks from Hans Verkuil to the video decoder patches.

 - In the v11 changelog I forgot to mention that the clk-binding
   patch was also changed with a corrected regex pattern and removed
   'clocks' sub-node. This patch needs r-b or ack too.

 - Added new "Rename 3d power domains" patch to match the DT schema
   naming requirement. Thanks to David Heidelberg for spotting this
   problem.

 - Replaced #ifdef CONFIG_PM_SLEEP with maybe_unused in the MMC patch
   to make code cleaner.

v11: - Added acks and r-b from Rob Herring, Mark Brown and Miquel Raynal
   that were given to v8.

 - Corrected order of the new memory controller reset entry in
   device-trees and host1x DT binding patch, which was requested by
   Rob Herring.

 - Switched consumer drivers to use power domain state syncing done
   by new Tegra's common OPP-initialization helper.

 - Made use of new devm_pm_runtime_enable() helper that was added to
   v5.15 kernel, where appropriate.

 - Added "fuse: Use resource-managed helpers" patch.

 - Converted Tegra20/30 clk drivers to a proper platform drivers,
   which was requested by Thierry Reding.

 - Removed clk-bulk API usage from the MMC patch, which was requested
   by Thierry Reding.

 - Changed CORE power domain name to "core" in a new patch
   "Change name of core power domain".

 - Misc small fixes for problems that I found since v8, like couple
   typos in error 

[PATCH v2 4/4] drm/tegra: Use dev_err_probe()

2021-11-30 Thread Dmitry Osipenko
Replace dev_printk() with a generic dev_err_probe() helper which silences
noisy error messages about deferred probe and makes easy to debug failing
deferred probe by printing notification about the failure to KMSG in the
end of kernel booting process and by adding failing device and the reason
of deferred probe to devices_deferred of debugfs. This was proven to be
useful in the case of eDP driver regression by immediately showing why
display driver was failing when user asked for help, otherwise it would've
been much more difficult to debug such problems on a third party device
that doesn't have developer setup.

Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/tegra/dc.c   | 13 +++--
 drivers/gpu/drm/tegra/hdmi.c | 34 +-
 2 files changed, 12 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 7ea3c045a6f7..f7370d28816f 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -3236,16 +3236,9 @@ static int tegra_dc_probe(struct platform_device *pdev)
return -ENXIO;
 
err = tegra_dc_rgb_probe(dc);
-   if (err < 0 && err != -ENODEV) {
-   const char *level = KERN_ERR;
-
-   if (err == -EPROBE_DEFER)
-   level = KERN_DEBUG;
-
-   dev_printk(level, dc->dev, "failed to probe RGB output: %d\n",
-  err);
-   return err;
-   }
+   if (err < 0 && err != -ENODEV)
+   return dev_err_probe(>dev, err,
+"failed to probe RGB output\n");
 
platform_set_drvdata(pdev, dc);
pm_runtime_enable(>dev);
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
index 9a87d351a828..3242baddc5e7 100644
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -1638,7 +1638,6 @@ static irqreturn_t tegra_hdmi_irq(int irq, void *data)
 
 static int tegra_hdmi_probe(struct platform_device *pdev)
 {
-   const char *level = KERN_ERR;
struct tegra_hdmi *hdmi;
struct resource *regs;
int err;
@@ -1678,36 +1677,21 @@ static int tegra_hdmi_probe(struct platform_device 
*pdev)
 
hdmi->hdmi = devm_regulator_get(>dev, "hdmi");
err = PTR_ERR_OR_ZERO(hdmi->hdmi);
-   if (err) {
-   if (err == -EPROBE_DEFER)
-   level = KERN_DEBUG;
-
-   dev_printk(level, >dev,
-  "failed to get HDMI regulator: %d\n", err);
-   return err;
-   }
+   if (err)
+   return dev_err_probe(>dev, err,
+"failed to get HDMI regulator\n");
 
hdmi->pll = devm_regulator_get(>dev, "pll");
err = PTR_ERR_OR_ZERO(hdmi->pll);
-   if (err) {
-   if (err == -EPROBE_DEFER)
-   level = KERN_DEBUG;
-
-   dev_printk(level, >dev,
-  "failed to get PLL regulator: %d\n", err);
-   return err;
-   }
+   if (err)
+   return dev_err_probe(>dev, err,
+"failed to get PLL regulator\n");
 
hdmi->vdd = devm_regulator_get(>dev, "vdd");
err = PTR_ERR_OR_ZERO(hdmi->vdd);
-   if (err) {
-   if (err == -EPROBE_DEFER)
-   level = KERN_DEBUG;
-
-   dev_printk(level, >dev,
-  "failed to get VDD regulator: %d\n", err);
-   return err;
-   }
+   if (err)
+   return dev_err_probe(>dev, err,
+"failed to get VDD regulator\n");
 
hdmi->output.dev = >dev;
 
-- 
2.33.1



[PATCH v2 1/4] gpu/host1x: Add init/deinit callbacks to host1x driver framework

2021-11-30 Thread Dmitry Osipenko
Add init/deinit callbacks to host1x driver framework which allow to
perform early pre-initialization required by Tegra DRM driver.

Cc:  # 5.13+
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/host1x/bus.c | 15 +++
 include/linux/host1x.h   |  4 
 2 files changed, 19 insertions(+)

diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c
index 0d81eede1217..25d688e5c742 100644
--- a/drivers/gpu/host1x/bus.c
+++ b/drivers/gpu/host1x/bus.c
@@ -479,8 +479,18 @@ static int host1x_device_add(struct host1x *host1x,
device->dev.dma_parms = >dma_parms;
dma_set_max_seg_size(>dev, UINT_MAX);
 
+   if (driver->init) {
+   err = driver->init(device);
+   if (err < 0) {
+   kfree(device);
+   return err;
+   }
+   }
+
err = host1x_device_parse_dt(device, driver);
if (err < 0) {
+   if (driver->deinit)
+   driver->deinit(device);
kfree(device);
return err;
}
@@ -512,11 +522,16 @@ static int host1x_device_add(struct host1x *host1x,
 static void host1x_device_del(struct host1x *host1x,
  struct host1x_device *device)
 {
+   struct host1x_driver *driver = device->driver;
+
if (device->registered) {
device->registered = false;
device_del(>dev);
}
 
+   if (driver->deinit)
+   driver->deinit(device);
+
put_device(>dev);
 }
 
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index e8dc5bc41f79..5e5ba33af4ae 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -346,6 +346,8 @@ struct host1x_device;
  * @driver: core driver
  * @subdevs: table of OF device IDs matching subdevices for this driver
  * @list: list node for the driver
+ * @init: called when the host1x logical driver is registered
+ * @deinit: called when the host1x logical driver is unregistered
  * @probe: called when the host1x logical device is probed
  * @remove: called when the host1x logical device is removed
  * @shutdown: called when the host1x logical device is shut down
@@ -356,6 +358,8 @@ struct host1x_driver {
const struct of_device_id *subdevs;
struct list_head list;
 
+   int (*init)(struct host1x_device *device);
+   void (*deinit)(struct host1x_device *device);
int (*probe)(struct host1x_device *device);
int (*remove)(struct host1x_device *device);
void (*shutdown)(struct host1x_device *device);
-- 
2.33.1



[PATCH v2 3/4] drm/tegra: dpaux: Restore DP AUX DDC registration order

2021-11-30 Thread Dmitry Osipenko
Restore DP AUX I2C DDC registration order by moving registration to
DP AUX driver probe phase. This fixes broken display panel driver of
Acer Chromebook CB5-311 that fails to probe starting with v5.13 kernel
when DP AUX registration order was changed to prevent accessing
uninitialized aux->drm_dev. Tegra SOR driver is never probed now using
the new registration order because tegra-output always fails with
-EPROBE_DEFER due to missing display panel that requires DP AUX DDC to
be registered first. The offending commit made DDC to be registered after
SOR's output, which can't ever happen. Use new tegra_drm_device() helper
that allows to set aux->drm_dev during DP AUX probe, restoring the DCC
registration order and reviving display panel.

Cc:  # 5.13+
Fixes: 39c17ae60ea9 ("drm/tegra: Don't register DP AUX channels before 
connectors")
Reported-by: Thomas Graichen  # T124 Nyan Big
Tested-by: Thomas Graichen  # T124 Nyan Big
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/tegra/dpaux.c | 26 +-
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c
index 1f96e416fa08..148d3c00dd8e 100644
--- a/drivers/gpu/drm/tegra/dpaux.c
+++ b/drivers/gpu/drm/tegra/dpaux.c
@@ -530,9 +530,12 @@ static int tegra_dpaux_probe(struct platform_device *pdev)
disable_irq(dpaux->irq);
 
dpaux->aux.transfer = tegra_dpaux_transfer;
+   dpaux->aux.drm_dev = tegra_drm_device();
dpaux->aux.dev = >dev;
 
-   drm_dp_aux_init(>aux);
+   err = drm_dp_aux_register(>aux);
+   if (err < 0)
+   goto put_pm;
 
/*
 * Assume that by default the DPAUX/I2C pads will be used for HDMI,
@@ -544,7 +547,7 @@ static int tegra_dpaux_probe(struct platform_device *pdev)
 */
err = tegra_dpaux_pad_config(dpaux, DPAUX_PADCTL_FUNC_I2C);
if (err < 0)
-   return err;
+   goto dp_aux_unreg;
 
 #ifdef CONFIG_GENERIC_PINCONF
dpaux->desc.name = dev_name(>dev);
@@ -557,7 +560,8 @@ static int tegra_dpaux_probe(struct platform_device *pdev)
dpaux->pinctrl = devm_pinctrl_register(>dev, >desc, dpaux);
if (IS_ERR(dpaux->pinctrl)) {
dev_err(>dev, "failed to register pincontrol\n");
-   return PTR_ERR(dpaux->pinctrl);
+   err = PTR_ERR(dpaux->pinctrl);
+   goto dp_aux_unreg;
}
 #endif
/* enable and clear all interrupts */
@@ -571,6 +575,14 @@ static int tegra_dpaux_probe(struct platform_device *pdev)
mutex_unlock(_lock);
 
return 0;
+
+dp_aux_unreg:
+   drm_dp_aux_unregister(>aux);
+put_pm:
+   pm_runtime_put_sync(>dev);
+   pm_runtime_disable(>dev);
+
+   return err;
 }
 
 static int tegra_dpaux_remove(struct platform_device *pdev)
@@ -579,6 +591,8 @@ static int tegra_dpaux_remove(struct platform_device *pdev)
 
cancel_work_sync(>work);
 
+   drm_dp_aux_unregister(>aux);
+
/* make sure pads are powered down when not in use */
tegra_dpaux_pad_power_down(dpaux);
 
@@ -717,11 +731,6 @@ int drm_dp_aux_attach(struct drm_dp_aux *aux, struct 
tegra_output *output)
unsigned long timeout;
int err;
 
-   aux->drm_dev = output->connector.dev;
-   err = drm_dp_aux_register(aux);
-   if (err < 0)
-   return err;
-
output->connector.polled = DRM_CONNECTOR_POLL_HPD;
dpaux->output = output;
 
@@ -759,7 +768,6 @@ int drm_dp_aux_detach(struct drm_dp_aux *aux)
unsigned long timeout;
int err;
 
-   drm_dp_aux_unregister(aux);
disable_irq(dpaux->irq);
 
if (dpaux->output->panel) {
-- 
2.33.1



[PATCH v2 2/4] drm/tegra: Create DRM device early

2021-11-30 Thread Dmitry Osipenko
DRM sub-drivers need to access DRM device early during first stage of
drivers' probing. Use new host1x init/deinit callbacks to create DRM
device early and destroy late.

Cc:  # 5.13+
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/tegra/drm.c | 46 ++---
 drivers/gpu/drm/tegra/drm.h |  2 ++
 2 files changed, 35 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index e9de91a4e7e8..e9cbcaf6e017 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -1133,21 +1133,42 @@ static bool host1x_drm_wants_iommu(struct host1x_device 
*dev)
return domain != NULL;
 }
 
-static int host1x_drm_probe(struct host1x_device *dev)
+static struct drm_device *terga_drm_dev;
+
+struct drm_device *tegra_drm_device(void)
 {
-   struct tegra_drm *tegra;
-   struct drm_device *drm;
-   int err;
+   return terga_drm_dev;
+}
 
-   drm = drm_dev_alloc(_drm_driver, >dev);
+static int host1x_drm_dev_init(struct host1x_device *dev)
+{
+   struct drm_device *drm = drm_dev_alloc(_drm_driver, >dev);
if (IS_ERR(drm))
return PTR_ERR(drm);
 
+   dev_set_drvdata(>dev, drm);
+   terga_drm_dev = drm;
+
+   return 0;
+}
+
+static void host1x_drm_dev_deinit(struct host1x_device *dev)
+{
+   struct drm_device *drm = dev_get_drvdata(>dev);
+
+   terga_drm_dev = NULL;
+   drm_dev_put(drm);
+}
+
+static int host1x_drm_probe(struct host1x_device *dev)
+{
+   struct drm_device *drm = dev_get_drvdata(>dev);
+   struct tegra_drm *tegra;
+   int err;
+
tegra = kzalloc(sizeof(*tegra), GFP_KERNEL);
-   if (!tegra) {
-   err = -ENOMEM;
-   goto put;
-   }
+   if (!tegra)
+   return -ENOMEM;
 
if (host1x_drm_wants_iommu(dev) && iommu_present(_bus_type)) {
tegra->domain = iommu_domain_alloc(_bus_type);
@@ -1164,7 +1185,6 @@ static int host1x_drm_probe(struct host1x_device *dev)
mutex_init(>clients_lock);
INIT_LIST_HEAD(>clients);
 
-   dev_set_drvdata(>dev, drm);
drm->dev_private = tegra;
tegra->drm = drm;
 
@@ -1285,8 +1305,7 @@ static int host1x_drm_probe(struct host1x_device *dev)
iommu_domain_free(tegra->domain);
 free:
kfree(tegra);
-put:
-   drm_dev_put(drm);
+
return err;
 }
 
@@ -1319,7 +1338,6 @@ static int host1x_drm_remove(struct host1x_device *dev)
}
 
kfree(tegra);
-   drm_dev_put(drm);
 
return 0;
 }
@@ -1391,6 +1409,8 @@ static struct host1x_driver host1x_drm_driver = {
.probe = host1x_drm_probe,
.remove = host1x_drm_remove,
.subdevs = host1x_drm_subdevs,
+   .init = host1x_drm_dev_init,
+   .deinit = host1x_drm_dev_deinit,
 };
 
 static struct platform_driver * const drivers[] = {
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index fc0a19554eac..8b7c9508070f 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -121,6 +121,8 @@ int tegra_drm_unregister_client(struct tegra_drm *tegra,
 int host1x_client_iommu_attach(struct host1x_client *client);
 void host1x_client_iommu_detach(struct host1x_client *client);
 
+struct drm_device *tegra_drm_device(void);
+
 int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm);
 int tegra_drm_exit(struct tegra_drm *tegra);
 
-- 
2.33.1



[PATCH v2 0/4] Restore Tegra DRM on Nyan Big Chromebook

2021-11-30 Thread Dmitry Osipenko
This patchset restores regressed SOR driver probing on Nyan Chromebook.

Changelog:

v2: - Changed host1x and Tegra DRM drivers such that DRM device is
  registered early now. This removes the need to change DRM core.

- Introduced dev_err_probe() patch again. Previously Thierry rejected
  it, saying that he likes his variant more, but I kept that patch in
  grate kernel and it happened to be very handy to have because I
  instantly identified the problem in the DP AUX driver with it,
  which would've been much more difficult to do otherwise.
  Please apply it this time.

Dmitry Osipenko (4):
  gpu/host1x: Add init/deinit callbacks to host1x driver framework
  drm/tegra: Create DRM device early
  drm/tegra: dpaux: Restore DP AUX DDC registration order
  drm/tegra: Use dev_err_probe()

 drivers/gpu/drm/tegra/dc.c| 13 +++---
 drivers/gpu/drm/tegra/dpaux.c | 26 +---
 drivers/gpu/drm/tegra/drm.c   | 46 +--
 drivers/gpu/drm/tegra/drm.h   |  2 ++
 drivers/gpu/drm/tegra/hdmi.c  | 34 +++---
 drivers/gpu/host1x/bus.c  | 15 
 include/linux/host1x.h|  4 +++
 7 files changed, 83 insertions(+), 57 deletions(-)

-- 
2.33.1



Re: [PATCH v4 2/2] drm/i915: Use to_root_gt() to refer to the root tile

2021-11-30 Thread Andi Shyti
Hi Lucas,

fist of all thanks for taking a look at this, I was eagerly
waiting for reviewers.

On Tue, Nov 30, 2021 at 01:07:30PM -0800, Lucas De Marchi wrote:
> On Sun, Nov 28, 2021 at 01:09:26PM +0200, Andi Shyti wrote:
> > Starting from a patch from Matt to_root_gt() returns the
> > reference to the root tile in order to abstract the root tile
> > from th callers.
> > 
> > Being the root tile identified as tile '0', embed the id in the
> > name so that i915->gt becomes i915->gt0.
> > 
> > The renaming has been mostly done with the following command and
> > some manual fixes.
> > 
> > sed -i -e sed -i 's/\\->gt\./\_root_gt(i915)\->/g' \
> > -e sed -i 's/\_priv\->gt\./\_root_gt(dev_priv)\->/g' \
> > -e 's/\_priv\->gt/to_root_gt(dev_priv)/g' \
> > -e 's/\\->gt/to_root_gt(i915)/g' \
> > -e 's/dev_priv\->gt\./to_root_gt(dev_priv)\->/g' \
> > -e 's/i915\->gt\./to_root_gt(i915)\->/g' \
> > `find drivers/gpu/drm/i915/ -name *.[ch]`
> > 
> > Two small changes have been added to this commit:
> > 
> > 1. intel_reset_gpu() in intel_display.c retreives the gt from
> >to_scanout_gt()
> > 2. in set_scheduler_caps() the gt is taken from the engine and
> >not from i915.
> 
> Ideally the non-automatic changes should be in separate patches, before
> the ones that can be done by automation. Because then it becomes easier
> to apply the final result without conflicts.

OK

> This is quite a big diff to merge in one go. Looking at the pending
> patches from Michal however I see he had similar changes, split in
> sensible chunks..  Could you split your version like that? at least
> gt/gem and display would be good to have separate. Or sync with Michal
> on how to proceed with these versions Here are his patches:
> 
>   drm/i915: Remove i915->ggtt
>   drm/i915: Use to_gt() helper for GGTT accesses
>   drm/i915: Use to_gt() helper
>   drm/i915/gvt: Use to_gt() helper
>   drm/i915/gem: Use to_gt() helper
>   drm/i915/gt: Use to_gt() helper
>   drm/i915/display: Use to_gt() helper
>   drm/i915: Introduce to_gt() helper

I understand... will follow this approach.

> This first patch also removed the `struct intel_gt *gt = to_gt(pool)`,
> that would otherwise be a leftover in 
> drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c

One difference from Michal patch is that I am not using the
wrapper

  to_gt(...)

but

  to_root_gt(...)

which was introduced by Matt. To me sounds more meaningful as it
specifies that we are really looking for the root tile and not
any tile.

Thanks again,
Andi


[PATCH v3] drm/i915/dp: Perform 30ms delay after source OUI write

2021-11-30 Thread Lyude Paul
While working on supporting the Intel HDR backlight interface, I noticed
that there's a couple of laptops that will very rarely manage to boot up
without detecting Intel HDR backlight support - even though it's supported
on the system. One example of such a laptop is the Lenovo P17 1st
generation.

Following some investigation Ville Syrjälä did through the docs they have
available to them, they discovered that there's actually supposed to be a
30ms wait after writing the source OUI before we begin setting up the rest
of the backlight interface.

This seems to be correct, as adding this 30ms delay seems to have
completely fixed the probing issues I was previously seeing. So - let's
start performing a 30ms wait after writing the OUI, which we do in a manner
similar to how we keep track of PPS delays (e.g. record the timestamp of
the OUI write, and then wait for however many ms are left since that
timestamp right before we interact with the backlight) in order to avoid
waiting any longer then we need to. As well, this also avoids us performing
this delay on systems where we don't end up using the HDR backlight
interface.

V3:
* Move last_oui_write into intel_dp
V2:
* Move panel delays into intel_pps

Signed-off-by: Lyude Paul 
Reviewed-by: Jani Nikula 
Fixes: 4a8d79901d5b ("drm/i915/dp: Enable Intel's HDR backlight interface (only 
SDR for now)")
Cc: Ville Syrjälä 
Cc:  # v5.12+
---
 drivers/gpu/drm/i915/display/intel_display_types.h|  3 +++
 drivers/gpu/drm/i915/display/intel_dp.c   | 11 +++
 drivers/gpu/drm/i915/display/intel_dp.h   |  2 ++
 drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c |  5 +
 4 files changed, 21 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index ea1e8a6e10b0..b9c967837872 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1653,6 +1653,9 @@ struct intel_dp {
struct intel_dp_pcon_frl frl;
 
struct intel_psr psr;
+
+   /* When we last wrote the OUI for eDP */
+   unsigned long last_oui_write;
 };
 
 enum lspcon_vendor {
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 0a424bf69396..5a8206298691 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -29,6 +29,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -2010,6 +2011,16 @@ intel_edp_init_source_oui(struct intel_dp *intel_dp, 
bool careful)
 
if (drm_dp_dpcd_write(_dp->aux, DP_SOURCE_OUI, oui, sizeof(oui)) 
< 0)
drm_err(>drm, "Failed to write source OUI\n");
+
+   intel_dp->last_oui_write = jiffies;
+}
+
+void intel_dp_wait_source_oui(struct intel_dp *intel_dp)
+{
+   struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+
+   drm_dbg_kms(>drm, "Performing OUI wait\n");
+   wait_remaining_ms_from_jiffies(intel_dp->last_oui_write, 30);
 }
 
 /* If the device supports it, try to set the power state appropriately */
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h 
b/drivers/gpu/drm/i915/display/intel_dp.h
index ce229026dc91..b64145a3869a 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -119,4 +119,6 @@ void intel_dp_pcon_dsc_configure(struct intel_dp *intel_dp,
 const struct intel_crtc_state *crtc_state);
 void intel_dp_phy_test(struct intel_encoder *encoder);
 
+void intel_dp_wait_source_oui(struct intel_dp *intel_dp);
+
 #endif /* __INTEL_DP_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c 
b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
index 8b9c925c4c16..62c112daacf2 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
@@ -36,6 +36,7 @@
 
 #include "intel_backlight.h"
 #include "intel_display_types.h"
+#include "intel_dp.h"
 #include "intel_dp_aux_backlight.h"
 
 /* TODO:
@@ -106,6 +107,8 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector 
*connector)
int ret;
u8 tcon_cap[4];
 
+   intel_dp_wait_source_oui(intel_dp);
+
ret = drm_dp_dpcd_read(aux, INTEL_EDP_HDR_TCON_CAP0, tcon_cap, 
sizeof(tcon_cap));
if (ret != sizeof(tcon_cap))
return false;
@@ -204,6 +207,8 @@ intel_dp_aux_hdr_enable_backlight(const struct 
intel_crtc_state *crtc_state,
int ret;
u8 old_ctrl, ctrl;
 
+   intel_dp_wait_source_oui(intel_dp);
+
ret = drm_dp_dpcd_readb(_dp->aux, 
INTEL_EDP_HDR_GETSET_CTRL_PARAMS, _ctrl);
if (ret != 1) {
drm_err(>drm, "Failed to read current backlight control 
mode: %d\n", ret);
-- 
2.33.1



[PATCH v10 5/8] MIPS: DTS: jz4780: Account for Synopsys HDMI driver and LCD controllers

2021-11-30 Thread H. Nikolaus Schaller
From: Paul Boddie 

A specialisation of the generic Synopsys HDMI driver is employed for
JZ4780 HDMI support. This requires a new driver, plus device tree and
configuration modifications.

Here we add jz4780 device tree setup.

Signed-off-by: Paul Boddie 
Signed-off-by: H. Nikolaus Schaller 
---
 arch/mips/boot/dts/ingenic/jz4780.dtsi | 40 ++
 1 file changed, 40 insertions(+)

diff --git a/arch/mips/boot/dts/ingenic/jz4780.dtsi 
b/arch/mips/boot/dts/ingenic/jz4780.dtsi
index b0a4e2e019c36..3f9ea47a10cd2 100644
--- a/arch/mips/boot/dts/ingenic/jz4780.dtsi
+++ b/arch/mips/boot/dts/ingenic/jz4780.dtsi
@@ -444,6 +444,46 @@ i2c4: i2c@10054000 {
status = "disabled";
};
 
+   hdmi: hdmi@1018 {
+   compatible = "ingenic,jz4780-dw-hdmi";
+   reg = <0x1018 0x8000>;
+   reg-io-width = <4>;
+
+   clocks = < JZ4780_CLK_AHB0>, < JZ4780_CLK_HDMI>;
+   clock-names = "iahb", "isfr";
+
+   interrupt-parent = <>;
+   interrupts = <3>;
+
+   status = "disabled";
+   };
+
+   lcdc0: lcdc0@1305 {
+   compatible = "ingenic,jz4780-lcd";
+   reg = <0x1305 0x1800>;
+
+   clocks = < JZ4780_CLK_TVE>, < JZ4780_CLK_LCD0PIXCLK>;
+   clock-names = "lcd", "lcd_pclk";
+
+   interrupt-parent = <>;
+   interrupts = <31>;
+
+   status = "disabled";
+   };
+
+   lcdc1: lcdc1@130a {
+   compatible = "ingenic,jz4780-lcd";
+   reg = <0x130a 0x1800>;
+
+   clocks = < JZ4780_CLK_TVE>, < JZ4780_CLK_LCD1PIXCLK>;
+   clock-names = "lcd", "lcd_pclk";
+
+   interrupt-parent = <>;
+   interrupts = <23>;
+
+   status = "disabled";
+   };
+
nemc: nemc@1341 {
compatible = "ingenic,jz4780-nemc", "simple-mfd";
reg = <0x1341 0x1>;
-- 
2.33.0



[PATCH v10 8/8] [RFC] MIPS: DTS: Ingenic: adjust register size to available registers

2021-11-30 Thread H. Nikolaus Schaller
After getting the regmap size from the device tree we should
reduce the ranges to the really available registers. This
allows to read only existing registers from the debug fs
and makes the regmap check out-of-bounds access.

For the jz4780 we have done this already.

Suggested-for: Paul Cercueil 
Signed-off-by: H. Nikolaus Schaller 
---
 arch/mips/boot/dts/ingenic/jz4725b.dtsi | 2 +-
 arch/mips/boot/dts/ingenic/jz4740.dtsi  | 2 +-
 arch/mips/boot/dts/ingenic/jz4770.dtsi  | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/mips/boot/dts/ingenic/jz4725b.dtsi 
b/arch/mips/boot/dts/ingenic/jz4725b.dtsi
index 0c6a5a4266f43..e9e48022f6316 100644
--- a/arch/mips/boot/dts/ingenic/jz4725b.dtsi
+++ b/arch/mips/boot/dts/ingenic/jz4725b.dtsi
@@ -321,7 +321,7 @@ udc: usb@1304 {
 
lcd: lcd-controller@1305 {
compatible = "ingenic,jz4725b-lcd";
-   reg = <0x1305 0x1000>;
+   reg = <0x1305 0x130>; /* tbc */
 
interrupt-parent = <>;
interrupts = <31>;
diff --git a/arch/mips/boot/dts/ingenic/jz4740.dtsi 
b/arch/mips/boot/dts/ingenic/jz4740.dtsi
index 772542e1f266a..7f76cba03a089 100644
--- a/arch/mips/boot/dts/ingenic/jz4740.dtsi
+++ b/arch/mips/boot/dts/ingenic/jz4740.dtsi
@@ -323,7 +323,7 @@ udc: usb@1304 {
 
lcd: lcd-controller@1305 {
compatible = "ingenic,jz4740-lcd";
-   reg = <0x1305 0x1000>;
+   reg = <0x1305 0x60>; /* LCDCMD1+4 */
 
interrupt-parent = <>;
interrupts = <30>;
diff --git a/arch/mips/boot/dts/ingenic/jz4770.dtsi 
b/arch/mips/boot/dts/ingenic/jz4770.dtsi
index dfe74328ae5dc..bda0a3a86ed5f 100644
--- a/arch/mips/boot/dts/ingenic/jz4770.dtsi
+++ b/arch/mips/boot/dts/ingenic/jz4770.dtsi
@@ -399,7 +399,7 @@ gpu: gpu@1304 {
 
lcd: lcd-controller@1305 {
compatible = "ingenic,jz4770-lcd";
-   reg = <0x1305 0x300>;
+   reg = <0x1305 0x130>; /* tbc */
 
interrupt-parent = <>;
interrupts = <31>;
-- 
2.33.0



[PATCH v10 3/8] dt-bindings: display: Add ingenic, jz4780-dw-hdmi DT Schema

2021-11-30 Thread H. Nikolaus Schaller
From: Sam Ravnborg 

Add DT bindings for the hdmi driver for the Ingenic JZ4780 SoC.
Based on .txt binding from Zubair Lutfullah Kakakhel

We also add generic ddc-i2c-bus to synopsys,dw-hdmi.yaml

Signed-off-by: Sam Ravnborg 
Signed-off-by: H. Nikolaus Schaller 
Cc: Rob Herring 
Cc: devicet...@vger.kernel.org
---
 .../display/bridge/ingenic,jz4780-hdmi.yaml   | 76 +++
 .../display/bridge/synopsys,dw-hdmi.yaml  |  3 +
 2 files changed, 79 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/bridge/ingenic,jz4780-hdmi.yaml

diff --git 
a/Documentation/devicetree/bindings/display/bridge/ingenic,jz4780-hdmi.yaml 
b/Documentation/devicetree/bindings/display/bridge/ingenic,jz4780-hdmi.yaml
new file mode 100644
index 0..5f372bdea0f0d
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/ingenic,jz4780-hdmi.yaml
@@ -0,0 +1,76 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/bridge/ingenic,jz4780-hdmi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Bindings for Ingenic JZ4780 HDMI Transmitter
+
+maintainers:
+  - H. Nikolaus Schaller 
+
+description: |
+  The HDMI Transmitter in the Ingenic JZ4780 is a Synopsys DesignWare HDMI 1.4
+  TX controller IP with accompanying PHY IP.
+
+allOf:
+  - $ref: synopsys,dw-hdmi.yaml#
+
+properties:
+  compatible:
+const: ingenic,jz4780-dw-hdmi
+
+  reg-io-width:
+const: 4
+
+  clocks:
+maxItems: 2
+
+  hdmi-5v-supply:
+description: Optional regulator to provide +5V at the connector
+
+  ports:
+$ref: /schemas/graph.yaml#/properties/ports
+
+required:
+  - compatible
+  - clocks
+  - clock-names
+  - ports
+  - reg-io-width
+
+unevaluatedProperties: false
+
+examples:
+  - |
+#include 
+
+hdmi: hdmi@1018 {
+compatible = "ingenic,jz4780-dw-hdmi";
+reg = <0x1018 0x8000>;
+reg-io-width = <4>;
+ddc-i2c-bus = <>;
+interrupt-parent = <>;
+interrupts = <3>;
+clocks = < JZ4780_CLK_AHB0>, < JZ4780_CLK_HDMI>;
+clock-names = "iahb", "isfr";
+
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+hdmi_in: port@0 {
+reg = <0>;
+dw_hdmi_in: endpoint {
+remote-endpoint = <_lcd_out>;
+};
+};
+hdmi_out: port@1 {
+reg = <1>;
+dw_hdmi_out: endpoint {
+remote-endpoint = <_con>;
+};
+};
+};
+};
+
+...
diff --git 
a/Documentation/devicetree/bindings/display/bridge/synopsys,dw-hdmi.yaml 
b/Documentation/devicetree/bindings/display/bridge/synopsys,dw-hdmi.yaml
index 9be44a682e67a..9cbeabaee0968 100644
--- a/Documentation/devicetree/bindings/display/bridge/synopsys,dw-hdmi.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/synopsys,dw-hdmi.yaml
@@ -50,6 +50,9 @@ properties:
   interrupts:
 maxItems: 1
 
+  ddc-i2c-bus:
+description: An I2C interface if the internal DDC I2C driver is not to be 
used
+
 additionalProperties: true
 
 ...
-- 
2.33.0



[PATCH v10 2/8] drm/ingenic: Add support for JZ4780 and HDMI output

2021-11-30 Thread H. Nikolaus Schaller
From: Paul Boddie 

Add support for the LCD controller present on JZ4780 SoCs.
This SoC uses 8-byte descriptors which extend the current
4-byte descriptors used for other Ingenic SoCs.

Tested on MIPS Creator CI20 board.

Signed-off-by: Paul Boddie 
Signed-off-by: Ezequiel Garcia 
Signed-off-by: H. Nikolaus Schaller 
---
 drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 53 +++
 drivers/gpu/drm/ingenic/ingenic-drm.h | 38 
 2 files changed, 91 insertions(+)

diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c 
b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
index 0bb590c3910d9..34089bc6e0fcd 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
@@ -6,6 +6,7 @@
 
 #include "ingenic-drm.h"
 
+#include 
 #include 
 #include 
 #include 
@@ -49,6 +50,11 @@ struct ingenic_dma_hwdesc {
u32 addr;
u32 id;
u32 cmd;
+   /* extended hw descriptor for jz4780 */
+   u32 offsize;
+   u32 pagewidth;
+   u32 cpos;
+   u32 dessize;
 } __aligned(16);
 
 struct ingenic_dma_hwdescs {
@@ -60,6 +66,7 @@ struct jz_soc_info {
bool needs_dev_clk;
bool has_osd;
bool map_noncoherent;
+   bool use_extended_hwdesc;
unsigned int max_width, max_height;
const u32 *formats_f0, *formats_f1;
unsigned int num_formats_f0, num_formats_f1;
@@ -446,6 +453,9 @@ static int ingenic_drm_plane_atomic_check(struct drm_plane 
*plane,
if (!crtc)
return 0;
 
+   if (plane == >f0)
+   return -EINVAL;
+
crtc_state = drm_atomic_get_existing_crtc_state(state,
crtc);
if (WARN_ON(!crtc_state))
@@ -662,6 +672,33 @@ static void ingenic_drm_plane_atomic_update(struct 
drm_plane *plane,
hwdesc->cmd = JZ_LCD_CMD_EOF_IRQ | (width * height * cpp / 4);
hwdesc->next = dma_hwdesc_addr(priv, next_id);
 
+   if (priv->soc_info->use_extended_hwdesc) {
+   hwdesc->cmd |= JZ_LCD_CMD_FRM_ENABLE;
+
+   /* Extended 8-byte descriptor */
+   hwdesc->cpos = 0;
+   hwdesc->offsize = 0;
+   hwdesc->pagewidth = 0;
+
+   switch (newstate->fb->format->format) {
+   case DRM_FORMAT_XRGB1555:
+   hwdesc->cpos |= JZ_LCD_CPOS_RGB555;
+   fallthrough;
+   case DRM_FORMAT_RGB565:
+   hwdesc->cpos |= JZ_LCD_CPOS_BPP_15_16;
+   break;
+   case DRM_FORMAT_XRGB:
+   hwdesc->cpos |= JZ_LCD_CPOS_BPP_18_24;
+   break;
+   }
+   hwdesc->cpos |= (JZ_LCD_CPOS_COEFFICIENT_1 <<
+JZ_LCD_CPOS_COEFFICIENT_OFFSET);
+   hwdesc->dessize =
+   (0xff << JZ_LCD_DESSIZE_ALPHA_OFFSET) |
+   FIELD_PREP(JZ_LCD_DESSIZE_HEIGHT_MASK, height - 
1) |
+   FIELD_PREP(JZ_LCD_DESSIZE_WIDTH_MASK, width - 
1);
+   }
+
if (drm_atomic_crtc_needs_modeset(crtc_state)) {
fourcc = newstate->fb->format->format;
 
@@ -693,6 +730,9 @@ static void ingenic_drm_encoder_atomic_mode_set(struct 
drm_encoder *encoder,
| JZ_LCD_CFG_SPL_DISABLE | JZ_LCD_CFG_REV_DISABLE;
}
 
+   if (priv->soc_info->use_extended_hwdesc)
+   cfg |= JZ_LCD_CFG_DESCRIPTOR_8;
+
if (mode->flags & DRM_MODE_FLAG_NHSYNC)
cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW;
if (mode->flags & DRM_MODE_FLAG_NVSYNC)
@@ -1468,10 +1508,23 @@ static const struct jz_soc_info jz4770_soc_info = {
.num_formats_f0 = ARRAY_SIZE(jz4770_formats_f0),
 };
 
+static const struct jz_soc_info jz4780_soc_info = {
+   .needs_dev_clk = true,
+   .has_osd = true,
+   .use_extended_hwdesc = true,
+   .max_width = 4096,
+   .max_height = 2048,
+   .formats_f1 = jz4770_formats_f1,
+   .num_formats_f1 = ARRAY_SIZE(jz4770_formats_f1),
+   .formats_f0 = jz4770_formats_f0,
+   .num_formats_f0 = ARRAY_SIZE(jz4770_formats_f0),
+};
+
 static const struct of_device_id ingenic_drm_of_match[] = {
{ .compatible = "ingenic,jz4740-lcd", .data = _soc_info },
{ .compatible = "ingenic,jz4725b-lcd", .data = _soc_info },
{ .compatible = "ingenic,jz4770-lcd", .data = _soc_info },
+   { .compatible = "ingenic,jz4780-lcd", .data = _soc_info },
{ /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, ingenic_drm_of_match);
diff --git a/drivers/gpu/drm/ingenic/ingenic-drm.h 
b/drivers/gpu/drm/ingenic/ingenic-drm.h
index 22654ac1dde1c..cb1d09b625881 100644
--- 

[PATCH v10 7/8] MIPS: defconfig: CI20: configure for DRM_DW_HDMI_JZ4780

2021-11-30 Thread H. Nikolaus Schaller
Enable CONFIG options as modules.

Signed-off-by: Ezequiel Garcia 
Signed-off-by: H. Nikolaus Schaller 
---
 arch/mips/configs/ci20_defconfig | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/arch/mips/configs/ci20_defconfig b/arch/mips/configs/ci20_defconfig
index ab7ebb0668340..cc69b215854ea 100644
--- a/arch/mips/configs/ci20_defconfig
+++ b/arch/mips/configs/ci20_defconfig
@@ -98,7 +98,13 @@ CONFIG_RC_DEVICES=y
 CONFIG_IR_GPIO_CIR=m
 CONFIG_IR_GPIO_TX=m
 CONFIG_MEDIA_SUPPORT=m
+CONFIG_DRM=m
+CONFIG_DRM_INGENIC=m
+CONFIG_DRM_INGENIC_DW_HDMI=m
+CONFIG_DRM_DISPLAY_CONNECTOR=m
 # CONFIG_VGA_CONSOLE is not set
+CONFIG_FB=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
 # CONFIG_HID is not set
 CONFIG_USB=y
 CONFIG_USB_STORAGE=y
-- 
2.33.0



[PATCH v10 6/8] MIPS: DTS: CI20: Add DT nodes for HDMI setup

2021-11-30 Thread H. Nikolaus Schaller
From: Paul Boddie 

We need to hook up
* HDMI connector
* HDMI power regulator
* JZ4780_CLK_HDMI @ 27 MHz
* DDC pinmux
* HDMI and LCDC endpoint connections

Signed-off-by: Paul Boddie 
Signed-off-by: H. Nikolaus Schaller 
---
 arch/mips/boot/dts/ingenic/ci20.dts | 72 -
 1 file changed, 70 insertions(+), 2 deletions(-)

diff --git a/arch/mips/boot/dts/ingenic/ci20.dts 
b/arch/mips/boot/dts/ingenic/ci20.dts
index b249a4f0f6b62..3e336b3dbb109 100644
--- a/arch/mips/boot/dts/ingenic/ci20.dts
+++ b/arch/mips/boot/dts/ingenic/ci20.dts
@@ -78,6 +78,18 @@ eth0_power: fixedregulator@0 {
enable-active-high;
};
 
+   hdmi_out: connector {
+   compatible = "hdmi-connector";
+   label = "HDMI OUT";
+   type = "a";
+
+   port {
+   hdmi_con: endpoint {
+   remote-endpoint = <_hdmi_out>;
+   };
+   };
+   };
+
ir: ir {
compatible = "gpio-ir-receiver";
gpios = < 3 GPIO_ACTIVE_LOW>;
@@ -102,6 +114,17 @@ otg_power: fixedregulator@2 {
gpio = < 14 GPIO_ACTIVE_LOW>;
enable-active-high;
};
+
+   hdmi_power: fixedregulator@3 {
+   compatible = "regulator-fixed";
+
+   regulator-name = "hdmi_power";
+   regulator-min-microvolt = <500>;
+   regulator-max-microvolt = <500>;
+
+   gpio = < 25 0>;
+   enable-active-high;
+   };
 };
 
  {
@@ -114,11 +137,12 @@  {
 * precision.
 */
assigned-clocks = < JZ4780_CLK_OTGPHY>, < JZ4780_CLK_RTC>,
- < JZ4780_CLK_SSIPLL>, < JZ4780_CLK_SSI>;
+ < JZ4780_CLK_SSIPLL>, < JZ4780_CLK_SSI>,
+ < JZ4780_CLK_HDMI>;
assigned-clock-parents = <0>, < JZ4780_CLK_RTCLK>,
 < JZ4780_CLK_MPLL>,
 < JZ4780_CLK_SSIPLL>;
-   assigned-clock-rates = <4800>, <0>, <5400>;
+   assigned-clock-rates = <4800>, <0>, <5400>, <0>, <2700>;
 };
 
  {
@@ -509,6 +533,12 @@ pins_i2c4: i2c4 {
bias-disable;
};
 
+   pins_hdmi_ddc: hdmi_ddc {
+   function = "hdmi-ddc";
+   groups = "hdmi-ddc";
+   bias-disable;
+   };
+
pins_nemc: nemc {
function = "nemc";
groups = "nemc-data", "nemc-cle-ale", "nemc-rd-we", 
"nemc-frd-fwe";
@@ -539,3 +569,41 @@ pins_mmc1: mmc1 {
bias-disable;
};
 };
+
+ {
+   status = "okay";
+
+   pinctrl-names = "default";
+   pinctrl-0 = <_hdmi_ddc>;
+
+   hdmi-5v-supply = <_power>;
+
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   port@0 {
+   reg = <0>;
+   dw_hdmi_in: endpoint {
+   remote-endpoint = <_out>;
+   };
+   };
+
+   port@1 {
+   reg = <1>;
+   dw_hdmi_out: endpoint {
+   remote-endpoint = <_con>;
+   };
+   };
+   };
+};
+
+ {
+   status = "okay";
+
+   port {
+   lcd_out: endpoint {
+   remote-endpoint = <_hdmi_in>;
+   };
+   };
+};
-- 
2.33.0



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

2021-11-30 Thread H. Nikolaus Schaller
From: Paul Boddie 

A specialisation of the generic Synopsys HDMI driver is employed for
JZ4780 HDMI support. This requires a new driver, plus device tree and
configuration modifications.

Here we add Kconfig DRM_INGENIC_DW_HDMI, Makefile and driver code.

Signed-off-by: Paul Boddie 
Signed-off-by: Ezequiel Garcia 
Signed-off-by: H. Nikolaus Schaller 
---
 drivers/gpu/drm/ingenic/Kconfig   |   9 ++
 drivers/gpu/drm/ingenic/Makefile  |   1 +
 drivers/gpu/drm/ingenic/ingenic-dw-hdmi.c | 138 ++
 3 files changed, 148 insertions(+)
 create mode 100644 drivers/gpu/drm/ingenic/ingenic-dw-hdmi.c

diff --git a/drivers/gpu/drm/ingenic/Kconfig b/drivers/gpu/drm/ingenic/Kconfig
index 3b57f8be007c4..4efc709d77b0a 100644
--- a/drivers/gpu/drm/ingenic/Kconfig
+++ b/drivers/gpu/drm/ingenic/Kconfig
@@ -25,4 +25,13 @@ config DRM_INGENIC_IPU
 
  The Image Processing Unit (IPU) will appear as a second primary plane.
 
+config DRM_INGENIC_DW_HDMI
+   tristate "Ingenic specific support for Synopsys DW HDMI"
+   depends on MACH_JZ4780
+   select DRM_DW_HDMI
+   help
+ Choose this option to enable Synopsys DesignWare HDMI based driver.
+ If you want to enable HDMI on Ingenic JZ4780 based SoC, you should
+ select this option..
+
 endif
diff --git a/drivers/gpu/drm/ingenic/Makefile b/drivers/gpu/drm/ingenic/Makefile
index d313326bdddbb..f10cc1c5a5f22 100644
--- a/drivers/gpu/drm/ingenic/Makefile
+++ b/drivers/gpu/drm/ingenic/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_DRM_INGENIC) += ingenic-drm.o
 ingenic-drm-y = ingenic-drm-drv.o
 ingenic-drm-$(CONFIG_DRM_INGENIC_IPU) += ingenic-ipu.o
+obj-$(CONFIG_DRM_INGENIC_DW_HDMI) += ingenic-dw-hdmi.o
diff --git a/drivers/gpu/drm/ingenic/ingenic-dw-hdmi.c 
b/drivers/gpu/drm/ingenic/ingenic-dw-hdmi.c
new file mode 100644
index 0..199e39c227d29
--- /dev/null
+++ b/drivers/gpu/drm/ingenic/ingenic-dw-hdmi.c
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
+ * Copyright (C) 2019, 2020 Paul Boddie 
+ *
+ * Derived from dw_hdmi-imx.c with i.MX portions removed.
+ * Probe and remove operations derived from rcar_dw_hdmi.c.
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+static const struct dw_hdmi_mpll_config ingenic_mpll_cfg[] = {
+   { 4525,  { { 0x01e0, 0x }, { 0x21e1, 0x }, { 0x41e2, 0x 
} } },
+   { 9250,  { { 0x0140, 0x0005 }, { 0x2141, 0x0005 }, { 0x4142, 0x0005 
} } },
+   { 14850, { { 0x00a0, 0x000a }, { 0x20a1, 0x000a }, { 0x40a2, 0x000a 
} } },
+   { 21600, { { 0x00a0, 0x000a }, { 0x2001, 0x000f }, { 0x4002, 0x000f 
} } },
+   { ~0UL,  { { 0x, 0x }, { 0x, 0x }, { 0x, 0x 
} } }
+};
+
+static const struct dw_hdmi_curr_ctrl ingenic_cur_ctr[] = {
+   /*pixelclk bpp8bpp10   bpp12 */
+   { 5400,  { 0x091c, 0x091c, 0x06dc } },
+   { 5840,  { 0x091c, 0x06dc, 0x06dc } },
+   { 7200,  { 0x06dc, 0x06dc, 0x091c } },
+   { 7425,  { 0x06dc, 0x0b5c, 0x091c } },
+   { 11880, { 0x091c, 0x091c, 0x06dc } },
+   { 21600, { 0x06dc, 0x0b5c, 0x091c } },
+   { ~0UL,  { 0x, 0x, 0x } },
+};
+
+/*
+ * Resistance term 133Ohm Cfg
+ * PREEMP config 0.00
+ * TX/CK level 10
+ */
+static const struct dw_hdmi_phy_config ingenic_phy_config[] = {
+   /*pixelclk   symbol   term   vlev */
+   { 21600, 0x800d, 0x0005, 0x01ad},
+   { ~0UL,  0x, 0x, 0x}
+};
+
+static enum drm_mode_status
+ingenic_dw_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data,
+  const struct drm_display_info *info,
+  const struct drm_display_mode *mode)
+{
+   if (mode->clock < 13500)
+   return MODE_CLOCK_LOW;
+   /* FIXME: Hardware is capable of 270MHz, but setup data is missing. */
+   if (mode->clock > 216000)
+   return MODE_CLOCK_HIGH;
+
+   return MODE_OK;
+}
+
+static struct dw_hdmi_plat_data ingenic_dw_hdmi_plat_data = {
+   .mpll_cfg   = ingenic_mpll_cfg,
+   .cur_ctr= ingenic_cur_ctr,
+   .phy_config = ingenic_phy_config,
+   .mode_valid = ingenic_dw_hdmi_mode_valid,
+   .output_port= 1,
+};
+
+static const struct of_device_id ingenic_dw_hdmi_dt_ids[] = {
+   { .compatible = "ingenic,jz4780-dw-hdmi" },
+   { /* Sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, ingenic_dw_hdmi_dt_ids);
+
+static void ingenic_dw_hdmi_cleanup(void *data)
+{
+   struct dw_hdmi *hdmi = (struct dw_hdmi *)data;
+
+   dw_hdmi_remove(hdmi);
+}
+
+static void ingenic_dw_hdmi_disable_regulator(void *data)
+{
+   struct regulator *regulator = (struct regulator *)data;
+
+   regulator_disable(regulator);
+}
+
+static int ingenic_dw_hdmi_probe(struct platform_device *pdev)
+{
+   struct dw_hdmi *hdmi;
+   struct regulator *regulator;
+   int ret;
+
+   hdmi = 

[PATCH v10 0/8] MIPS: JZ4780 and CI20 HDMI

2021-11-30 Thread H. Nikolaus Schaller
PATCH V10 2021-11-30 22:26:41:
- patch 3/8: fix $id and $ref paths (found by r...@kernel.org)

PATCH V9 2021-11-24 22:29:14:
- patch 6/8: remove optional <0> for assigned-clocks and unintentionally 
included "unwedge" setup (found by p...@crapouillou.net)
- patch 4/8: some cosmetics
 make regulator enable/disable only if not NULL (found by 
p...@crapouillou.net)
 simplify/fix error handling and driver cleanup on remove (proposed 
by p...@crapouillou.net)
- patch 3/8: fix #include path in example (found by p...@crapouillou.net)
 fix missing "i" in unevaluatedProperties (found by r...@kernel.org)
 fix 4 spaces indentation for required: property (found by 
r...@kernel.org)

PATCH V8 2021-11-23 19:14:00:
- fix a bad editing result from patch 2/8 (found by p...@crapouillou.net)

PATCH V7 2021-11-23 18:46:23:
- changed gpio polarity of hdmi_power to 0 (suggested by p...@crapouillou.net)
- fixed LCD1 irq number (bug found by p...@crapouillou.net)
- removed "- 4" for calculating max_register (suggested by p...@crapouillou.net)
- use unevaluatedPropertes instead of additionalProperties (suggested by 
r...@kernel.org)
- moved and renamed ingenic,jz4780-hdmi.yaml (suggested by r...@kernel.org)
- adjusted assigned-clocks changes to upstream which added some for SSI (by 
h...@goldelico.com)
- rebased and tested with v5.16-rc2 + patch set drm/ingenic by 
p...@crapouillou.net (by h...@goldelico.com)

PATCH V6 2021-11-10 20:43:33:
- changed CONFIG_DRM_INGENIC_DW_HDMI to "m" (by h...@goldelico.com)
- made ingenic-dw-hdmi an independent platform driver which can be compiled as 
module
  and removed error patch fixes for IPU (suggested by p...@crapouillou.net)
- moved assigned-clocks from jz4780.dtsi to ci20.dts (suggested by 
p...@crapouillou.net)
- fixed reg property in jz4780.dtsi to cover all registers incl. gamma and vee 
(by h...@goldelico.com)
- added a base patch to calculate regmap size from DTS reg property (requested 
by p...@crapouillou.net)
- restored resetting all bits except one in LCDOSDC (requested by 
p...@crapouillou.net)
- clarified setting of cpos (suggested by p...@crapouillou.net)
- moved bindings definition for ddc-i2c-bus (suggested by p...@crapouillou.net)
- simplified mask definitions for JZ_LCD_DESSIZE (requested by 
p...@crapouillou.net)
- removed setting alpha premultiplication (suggested by p...@crapouillou.net)
- removed some comments (suggested by p...@crapouillou.net)

PATCH V5 2021-10-05 14:28:44:
- dropped mode_fixup and timings support in dw-hdmi as it is no longer needed 
in this V5 (by h...@goldelico.com)
- dropped "drm/ingenic: add some jz4780 specific features" (stimulated by 
p...@crapouillou.net)
- fixed typo in commit subject: "synopsis" -> "synopsys" (by h...@goldelico.com)
- swapped clocks in jz4780.dtsi to match synopsys,dw-hdmi.yaml (by 
h...@goldelico.com)
- improved, simplified, fixed, dtbschecked ingenic-jz4780-hdmi.yaml and made 
dependent of bridge/synopsys,dw-hdmi.yaml (based on suggestions by 
max...@cerno.tech)
- fixed binding vs. driver use of hdmi-5v regulator (suggested by 
max...@cerno.tech)
- dropped "drm/bridge: synopsis: Fix to properly handle HPD" - was a no longer 
needed workaround for a previous version
  (suggested by max...@cerno.tech)

PATCH V4 2021-09-27 18:44:38:
- fix setting output_port = 1 (issue found by p...@crapouillou.net)
- ci20.dts: convert to use hdmi-connector (by h...@goldelico.com)
- add a hdmi-regulator to control +5V power (by h...@goldelico.com)
- added a fix to dw-hdmi to call drm_kms_helper_hotplug_event on plugin event 
detection (by h...@goldelico.com)
- always allocate extended descriptor but initialize only for jz4780 (by 
h...@goldelico.com)
- updated to work on top of "[PATCH v3 0/6] drm/ingenic: Various improvements 
v3" (by p...@crapouillou.net)
- rebased to v5.13-rc3

PATCH V3 2021-08-08 07:10:50:
This series adds HDMI support for JZ4780 and CI20 board (and fixes one IPU 
related issue in registration error path)
- [patch 1/8] switched from mode_fixup to atomic_check (suggested by 
robert.f...@linaro.org)
  - the call to the dw-hdmi specialization is still called mode_fixup
- [patch 3/8] diverse fixes for ingenic-drm-drv (suggested by 
p...@crapouillou.net)
  - factor out some non-HDMI features of the jz4780 into a separate patch
  - multiple fixes around max height
  - do not change regmap config but a copy on stack
  - define some constants
  - factor out fixing of drm_init error path for IPU into separate patch
  - use FIELD_PREP()
- [patch 8/8] conversion to component framework dropped (suggested by 
laurent.pinch...@ideasonboard.com and p...@crapouillou.net)

PATCH V2 2021-08-05 16:08:05:
- code and commit messages revisited for checkpatch warnings
- rebased on v5.14-rc4
- include (failed, hence RFC 8/8) attempt to convert to component framework
  (was suggested by Paul Cercueil  a while ago)

This series adds HDMI support for JZ4780 and CI20 board



H. Nikolaus Schaller 

[PATCH v10 1/8] drm/ingenic: prepare ingenic drm for later addition of JZ4780

2021-11-30 Thread H. Nikolaus Schaller
This changes the way the regmap is allocated to prepare for the
later addition of the JZ4780 which has more registers and bits
than the others.

Therefore we make the regmap as big as the reg property in
the device tree tells.

Suggested-by: Paul Cercueil 
Signed-off-by: H. Nikolaus Schaller 
---
 drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c 
b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
index 462bc0f35f1bf..0bb590c3910d9 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
@@ -173,7 +173,6 @@ static const struct regmap_config ingenic_drm_regmap_config 
= {
.val_bits = 32,
.reg_stride = 4,
 
-   .max_register = JZ_REG_LCD_SIZE1,
.writeable_reg = ingenic_drm_writeable_reg,
 };
 
@@ -1011,6 +1010,8 @@ static int ingenic_drm_bind(struct device *dev, bool 
has_components)
struct ingenic_drm_bridge *ib;
struct drm_device *drm;
void __iomem *base;
+   struct resource *res;
+   struct regmap_config regmap_config;
long parent_rate;
unsigned int i, clone_mask = 0;
int ret, irq;
@@ -1056,14 +1057,16 @@ static int ingenic_drm_bind(struct device *dev, bool 
has_components)
drm->mode_config.funcs = _drm_mode_config_funcs;
drm->mode_config.helper_private = _drm_mode_config_helpers;
 
-   base = devm_platform_ioremap_resource(pdev, 0);
+   base = devm_platform_get_and_ioremap_resource(pdev, 0, );
if (IS_ERR(base)) {
dev_err(dev, "Failed to get memory resource\n");
return PTR_ERR(base);
}
 
+   regmap_config = ingenic_drm_regmap_config;
+   regmap_config.max_register = res->end - res->start;
priv->map = devm_regmap_init_mmio(dev, base,
- _drm_regmap_config);
+ _config);
if (IS_ERR(priv->map)) {
dev_err(dev, "Failed to create regmap\n");
return PTR_ERR(priv->map);
-- 
2.33.0



Re: [PATCH v4 2/2] drm/i915: Use to_root_gt() to refer to the root tile

2021-11-30 Thread Lucas De Marchi

On Sun, Nov 28, 2021 at 01:09:26PM +0200, Andi Shyti wrote:

Starting from a patch from Matt to_root_gt() returns the
reference to the root tile in order to abstract the root tile
from th callers.

Being the root tile identified as tile '0', embed the id in the
name so that i915->gt becomes i915->gt0.

The renaming has been mostly done with the following command and
some manual fixes.

sed -i -e sed -i 's/\\->gt\./\_root_gt(i915)\->/g' \
-e sed -i 's/\_priv\->gt\./\_root_gt(dev_priv)\->/g' \
-e 's/\_priv\->gt/to_root_gt(dev_priv)/g' \
-e 's/\\->gt/to_root_gt(i915)/g' \
-e 's/dev_priv\->gt\./to_root_gt(dev_priv)\->/g' \
-e 's/i915\->gt\./to_root_gt(i915)\->/g' \
`find drivers/gpu/drm/i915/ -name *.[ch]`

Two small changes have been added to this commit:

1. intel_reset_gpu() in intel_display.c retreives the gt from
   to_scanout_gt()
2. in set_scheduler_caps() the gt is taken from the engine and
   not from i915.


Ideally the non-automatic changes should be in separate patches, before
the ones that can be done by automation. Because then it becomes easier
to apply the final result without conflicts.

This is quite a big diff to merge in one go. Looking at the pending
patches from Michal however I see he had similar changes, split in
sensible chunks..  Could you split your version like that? at least
gt/gem and display would be good to have separate. Or sync with Michal
on how to proceed with these versions Here are his patches:

drm/i915: Remove i915->ggtt
drm/i915: Use to_gt() helper for GGTT accesses
drm/i915: Use to_gt() helper
drm/i915/gvt: Use to_gt() helper
drm/i915/gem: Use to_gt() helper
drm/i915/gt: Use to_gt() helper
drm/i915/display: Use to_gt() helper
drm/i915: Introduce to_gt() helper

This first patch also removed the `struct intel_gt *gt = to_gt(pool)`,
that would otherwise be a leftover in 
drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c

thanks
Lucas De Marchi


Re: [PATCH 1/6] Documentation/gpu: Reorganize DC documentation

2021-11-30 Thread Yann Dirson
> On 2021-11-30 10:48 a.m., Harry Wentland wrote:
> > On 2021-11-30 10:46, Rodrigo Siqueira Jordao wrote:
> >>
> >>
> >> On 2021-11-29 7:06 a.m., Jani Nikula wrote:
> >>> On Fri, 26 Nov 2021, Daniel Vetter  wrote:
>  On Thu, Nov 25, 2021 at 10:38:25AM -0500, Rodrigo Siqueira
>  wrote:
> > Display core documentation is not well organized, and it is
> > hard to find
> > information due to the lack of sections. This commit
> > reorganizes the
> > documentation layout, and it is preparation work for future
> > changes.
> >
> > Signed-off-by: Rodrigo Siqueira 
> > ---
> >    Documentation/gpu/amdgpu-dc.rst   | 74
> >    ---
> >    .../gpu/amdgpu-dc/amdgpu-dc-debug.rst |  4 +
> >    Documentation/gpu/amdgpu-dc/amdgpu-dc.rst | 29 
> >    Documentation/gpu/amdgpu-dc/amdgpu-dm.rst | 42
> >    +++
> >    Documentation/gpu/drivers.rst |  2 +-
> >    5 files changed, 76 insertions(+), 75 deletions(-)
> >    delete mode 100644 Documentation/gpu/amdgpu-dc.rst
> >    create mode 100644
> >    Documentation/gpu/amdgpu-dc/amdgpu-dc-debug.rst
> >    create mode 100644 Documentation/gpu/amdgpu-dc/amdgpu-dc.rst
> >    create mode 100644 Documentation/gpu/amdgpu-dc/amdgpu-dm.rst
> >
> > diff --git a/Documentation/gpu/amdgpu-dc.rst
> > b/Documentation/gpu/amdgpu-dc.rst
> > deleted file mode 100644
> > index f7ff7e1309de..
> > --- a/Documentation/gpu/amdgpu-dc.rst
> > +++ /dev/null
> > @@ -1,74 +0,0 @@
> > -===
> > -drm/amd/display - Display Core (DC)
> > -===
> > -
> > -*placeholder - general description of supported platforms,
> > what dc is, etc.*
> > -
> > -Because it is partially shared with other operating systems,
> > the Display Core
> > -Driver is divided in two pieces.
> > -
> > -1. **Display Core (DC)** contains the OS-agnostic components.
> > Things like
> > -   hardware programming and resource management are handled
> > here.
> > -2. **Display Manager (DM)** contains the OS-dependent
> > components. Hooks to the
> > -   amdgpu base driver and DRM are implemented here.
> > -
> > -It doesn't help that the entire package is frequently referred
> > to as DC. But
> > -with the context in mind, it should be clear.
> > -
> > -When CONFIG_DRM_AMD_DC is enabled, DC will be initialized by
> > default for
> > -supported ASICs. To force disable, set `amdgpu.dc=0` on kernel
> > command line.
> > -Likewise, to force enable on unsupported ASICs, set
> > `amdgpu.dc=1`.
> > -
> > -To determine if DC is loaded, search dmesg for the following
> > entry:
> > -
> > -``Display Core initialized with ``
> > -
> > -AMDgpu Display Manager
> > -==
> > -
> > -.. kernel-doc::
> > drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > -   :doc: overview
> > -
> > -.. kernel-doc::
> > drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> > -   :internal:
> > -
> > -Lifecycle
> > --
> > -
> > -.. kernel-doc::
> > drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > -   :doc: DM Lifecycle
> > -
> > -.. kernel-doc::
> > drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > -   :functions: dm_hw_init dm_hw_fini
> > -
> > -Interrupts
> > ---
> > -
> > -.. kernel-doc::
> > drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
> > -   :doc: overview
> > -
> > -.. kernel-doc::
> > drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
> > -   :internal:
> > -
> > -.. kernel-doc::
> > drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > -   :functions: register_hpd_handlers dm_crtc_high_irq
> > dm_pflip_high_irq
> > -
> > -Atomic Implementation
> > --
> > -
> > -.. kernel-doc::
> > drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > -   :doc: atomic
> > -
> > -.. kernel-doc::
> > drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > -   :functions: amdgpu_dm_atomic_check
> > amdgpu_dm_atomic_commit_tail
> > -
> > -Display Core
> > -
> > -
> > -**WIP**
> > -
> > -FreeSync Video
> > ---
> > -
> > -.. kernel-doc::
> > drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > -   :doc: FreeSync Video
> > diff --git a/Documentation/gpu/amdgpu-dc/amdgpu-dc-debug.rst
> > b/Documentation/gpu/amdgpu-dc/amdgpu-dc-debug.rst
> > new file mode 100644
> > index ..bbb8c3fc8eee
> > --- /dev/null
> > +++ b/Documentation/gpu/amdgpu-dc/amdgpu-dc-debug.rst
> > @@ -0,0 +1,4 @@
> > +Display Core Debug 

Re: [PATCH v2 1/2] drm/input_helper: Add new input-handling helper

2021-11-30 Thread Brian Norris
Hi Pekka,

On Fri, Nov 19, 2021 at 12:38:41PM +0200, Pekka Paalanen wrote:
> On Thu, 18 Nov 2021 17:46:10 -0800
> Brian Norris  wrote:
> > On Thu, Nov 18, 2021 at 12:39:28PM +0200, Pekka Paalanen wrote:
> > > On Wed, 17 Nov 2021 14:48:40 -0800
> > > Brian Norris  wrote:
> > > If KMS gets a pageflip or modeset in no time after an input event, then
> > > what's the gain. OTOH, if the display server is locking on to vblank,
> > > there might be a delay worth avoiding. But then, is it worth
> > > short-circuiting the wake-up in kernel vs. adding a new ioctl that
> > > userspace could hit to start the warming up process?  
> > 
> > Rob responded to the first part to some extent (there is definitely gain
> > to be had).
> > 
> > To the last part: I wrote a simple debugfs hook to allow user space to
> > force a PSR exit, and then a simple user space program to read input
> > events and smash that debugfs file whenever it sees one. Testing in the
> > same scenarios, this appears to lose less than 100 microseconds versus
> > the in-kernel approach, which is negligible for this use case. (I'm not
> > sure about the other use cases.)
> > 
> > So, this is technically doable in user space.
> 
> This is crucial information I would like you to include in some commit
> message. I think it is very interesting for the reviewers. Maybe also
> copy that in the cover letter.
> 
> In my opinion there is a clear and obvious decision due that
> measurement: Add the new ioctl for userspace to hit, do not try to
> hardcode or upload the wake-up policy into the kernel.

Perhaps.

I'll admit, I'm not eager to go write the fd-passing solutions that
others are designing on the fly. I'm currently torn on whether I'll just
live with this current patch set out-of-tree (or, y'all can decide that
a simple, 99% working solution is better than no solution), because it's
simple; or possibly figuring out how to utilize such an ioctl cleanly
within our display manager. I'm not super hopeful on the latter.

IOW, I'm approximately in line with Doug's thoughts:
https://lore.kernel.org/all/CAD=FV=XARhZoj+0p-doxcbC=4K+NuMc=ur6wqg6kwk-mkpk...@mail.gmail.com/
But then, we're obviously biased.

> > I can't speak to the ease of _actually_ integrating this into even our
> > own Chrome display manager, but I highly doubt it will get integrated
> > into others. I'd posit this should weigh into the relative worth, but
> > otherwise can't really give you an answer there.
> 
> I think such a thing would be very simple to add to any display server.
> They already have hooks for things like resetting idle timeout timers on
> any relevant input event.
> 
> > I'd also note, software-directed PSR is so far designed to be completely
> > opaque to user space. There's no way to disable it; no way to know it's
> > active; and no way to know anything about the parameters it's computing
> > (like average entry/exit delay). Would you suggest a whole set of new
> > IOCTLs for this?
> 
> Just one ioctl on the DRM device: "Hey, wake up!". Because that's what
> your patch does in-kernel, right?

Well, we'd at least want something to advertise that the feature does
something ("is supported") I think, otherwise we're just asking user
space to do useless work.

> If there are use case specific parameters, then how did you intend to
> allow adjusting those in your proposal?

Another commenter mentioned the latency tradeoff -- it's possible that
there are panels/eDP-links that resume fast enough that one doesn't care
to use this ioctl. For an in-kernel solution, one has all the data
available and could use hardware information to make decisions, if
needed. For a user space solution, we won't have any of that, and we'd
have to work to expose that information.

I suppose we could ignore that problem and only expose a minimal UAPI
until we need something more, but it feels like exposing a UAPI for
something is a critical point where one should make sure it's reasonably
descriptive and useful.

> > > How do you know userspace is using this input device at all? If
> > > userspace is not using the input device, then DRM should not be opening
> > > it either, as it must have no effect on anything.
> > > 
> > > If you open an input device that userspace does not use, you also cause
> > > a power consumption regression, because now the input device itself is
> > > active and possibly flooding the kernel with events (e.g. an
> > > accelerometer).  
> > 
> > Well, I don't think accelerometers show up as input devices, but I
> > suppose your point could apply to actual input devices.
> 
> My understanding is that accelerometers are evdev (input) devices,
> especially when used as input e.g. for controlling games. I'm not aware
> of any other interface for it.

I'm not familiar with game-controlling accelerometers, but many types of
accelerometers are serviced by drivers/iio/.

And even if they register as input devices, do they match the ID list in
this patch?

> Even audio sockets are input 

Re: linux-next: manual merge of the drm tree with the drm-misc-fixes tree

2021-11-30 Thread Stephen Rothwell
Hi Maxime,

On Tue, 30 Nov 2021 09:58:31 +0100 Maxime Ripard  wrote:
>
> Unfortunately the merge resolution isn't entirely correct :/
> 
> There's multiple conflicts between those two branches on that file, but
> things went wrong between 16e101051f32 and 0c980a006d3f
> 
> The first one changes the logic a bit for the clk_set_min_rate argument,
> and the second moves the clk_set_min_rate around.
> 
> However, the merge resolution reintroduced the initial clk_set_min_rate
> call line (line 373), without changing the logic of the proper call site
> (line 396).
> 
> This is the patch to fix the resolution:
> 
> -- >8 --  
> --- a/drivers/gpu/drm/vc4/vc4_kms.c   2021-11-30 08:56:28.748524275 +0100
> +++ b/drivers/gpu/drm/vc4/vc4_kms.c   2021-11-29 15:46:11.692151678 +0100
> @@ -365,14 +365,6 @@
>   vc4_hvs_mask_underrun(dev, vc4_crtc_state->assigned_channel);
>   }
> 
> - if (vc4->hvs->hvs5) {
> - unsigned long core_rate = max_t(unsigned long,
> - 5,
> - new_hvs_state->core_clock_rate);
> -
> - clk_set_min_rate(hvs->core_clk, core_rate);
> - }
> -
>   for (channel = 0; channel < HVS_NUM_CHANNELS; channel++) {
>   struct drm_crtc_commit *commit;
>   int ret;
> @@ -392,8 +384,13 @@
>   old_hvs_state->fifo_state[channel].pending_commit = NULL;
>   }
> 
> - if (vc4->hvs->hvs5)
> - clk_set_min_rate(hvs->core_clk, 5);
> + if (vc4->hvs->hvs5) {
> + unsigned long core_rate = max_t(unsigned long,
> + 5,
> + new_hvs_state->core_clock_rate);
> +
> + clk_set_min_rate(hvs->core_clk, core_rate);
> + }
> 
>   drm_atomic_helper_commit_modeset_disables(dev, state);
> -- >8 --  

Thanks, I have fixed that up in my resolution.

-- 
Cheers,
Stephen Rothwell


pgpCdjHVzzrwX.pgp
Description: OpenPGP digital signature


Re: [PATCH v2] drm/i915/dp: Perform 30ms delay after source OUI write

2021-11-30 Thread Lyude Paul
On Tue, 2021-11-30 at 12:36 +0200, Jani Nikula wrote:
> On Mon, 29 Nov 2021, Lyude Paul  wrote:
> > While working on supporting the Intel HDR backlight interface, I noticed
> > that there's a couple of laptops that will very rarely manage to boot up
> > without detecting Intel HDR backlight support - even though it's supported
> > on the system. One example of such a laptop is the Lenovo P17 1st
> > generation.
> > 
> > Following some investigation Ville Syrjälä did through the docs they have
> > available to them, they discovered that there's actually supposed to be a
> > 30ms wait after writing the source OUI before we begin setting up the rest
> > of the backlight interface.
> > 
> > This seems to be correct, as adding this 30ms delay seems to have
> > completely fixed the probing issues I was previously seeing. So - let's
> > start performing a 30ms wait after writing the OUI, which we do in a
> > manner
> > similar to how we keep track of PPS delays (e.g. record the timestamp of
> > the OUI write, and then wait for however many ms are left since that
> > timestamp right before we interact with the backlight) in order to avoid
> > waiting any longer then we need to. As well, this also avoids us
> > performing
> > this delay on systems where we don't end up using the HDR backlight
> > interface.
> > 
> > V2:
> > * Move panel delays into intel_pps
> > 
> > Signed-off-by: Lyude Paul 
> > Fixes: 4a8d79901d5b ("drm/i915/dp: Enable Intel's HDR backlight interface
> > (only SDR for now)")
> > Cc: Ville Syrjälä 
> > Cc:  # v5.12+
> > ---
> >  drivers/gpu/drm/i915/display/intel_display_types.h    |  4 
> >  drivers/gpu/drm/i915/display/intel_dp.c   | 11 +++
> >  drivers/gpu/drm/i915/display/intel_dp.h   |  2 ++
> >  drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c |  5 +
> >  4 files changed, 22 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h
> > b/drivers/gpu/drm/i915/display/intel_display_types.h
> > index ea1e8a6e10b0..ad64f9caa7ff 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> > +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> > @@ -1485,6 +1485,7 @@ struct intel_pps {
> > bool want_panel_vdd;
> > unsigned long last_power_on;
> > unsigned long last_backlight_off;
> > +   unsigned long last_oui_write;
> > ktime_t panel_power_off_time;
> > intel_wakeref_t vdd_wakeref;
> >  
> > @@ -1653,6 +1654,9 @@ struct intel_dp {
> > struct intel_dp_pcon_frl frl;
> >  
> > struct intel_psr psr;
> > +
> > +   /* When we last wrote the OUI for eDP */
> > +   unsigned long last_oui_write;
> 
> Now you're adding last_oui_write to both intel_pps and intel_dp, forgot
> to git add? ;)

Yep :P, will send out a different version in a bit
> 
> I guess I'd add this to intel_dp only, because it's not strictly about
> PPS. I just wanted the mechanism to be similar to that.
> 
> >  };
> >  
> >  enum lspcon_vendor {
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c
> > b/drivers/gpu/drm/i915/display/intel_dp.c
> > index 0a424bf69396..45318891ba07 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> > @@ -29,6 +29,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  
> >  #include 
> > @@ -2010,6 +2011,16 @@ intel_edp_init_source_oui(struct intel_dp
> > *intel_dp, bool careful)
> >  
> > if (drm_dp_dpcd_write(_dp->aux, DP_SOURCE_OUI, oui,
> > sizeof(oui)) < 0)
> > drm_err(>drm, "Failed to write source OUI\n");
> > +
> > +   intel_dp->pps.last_oui_write = jiffies;
> 
> Set to intel_dp->last_oui_write.
> 
> With those fixes,
> 
> Reviewed-by: Jani Nikula 
> 
> 
> > +}
> > +
> > +void intel_dp_wait_source_oui(struct intel_dp *intel_dp)
> > +{
> > +   struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> > +
> > +   drm_dbg_kms(>drm, "Performing OUI wait\n");
> > +   wait_remaining_ms_from_jiffies(intel_dp->last_oui_write, 30);
> >  }
> >  
> >  /* If the device supports it, try to set the power state appropriately */
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp.h
> > b/drivers/gpu/drm/i915/display/intel_dp.h
> > index ce229026dc91..b64145a3869a 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp.h
> > +++ b/drivers/gpu/drm/i915/display/intel_dp.h
> > @@ -119,4 +119,6 @@ void intel_dp_pcon_dsc_configure(struct intel_dp
> > *intel_dp,
> >  const struct intel_crtc_state
> > *crtc_state);
> >  void intel_dp_phy_test(struct intel_encoder *encoder);
> >  
> > +void intel_dp_wait_source_oui(struct intel_dp *intel_dp);
> > +
> >  #endif /* __INTEL_DP_H__ */
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
> > b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
> > index 8b9c925c4c16..62c112daacf2 100644
> > --- 

Re: [PATCH] staging: fbtft: add spi_device_id table

2021-11-30 Thread Heiner Kallweit
On 30.11.2021 09:16, Geert Uytterhoeven wrote:
> Hi Heiner,
> 
> On Mon, Nov 29, 2021 at 10:12 PM Heiner Kallweit  wrote:
>> After 5fa6863ba692 ("spi: Check we have a spi_device_id for each DT
>> compatible") we need the following to make the SPI core happy.
>>
>> Works for me with a SH1106-based OLED display.
>>
>> Signed-off-by: Heiner Kallweit 
> 
> Thanks for your patch!
> 
>> --- a/drivers/staging/fbtft/fbtft.h
>> +++ b/drivers/staging/fbtft/fbtft.h
>> @@ -307,12 +307,19 @@ static const struct of_device_id dt_ids[] = {  
>> \
>>\
>>  MODULE_DEVICE_TABLE(of, dt_ids);   \
>>\
>> +static const struct spi_device_id spi_ids[] = {\
>> +   { .name = _compatible },   \
> 
> Shouldn't this be the part of _compatible after the "," prefix?
> 

You're right. I was fooled by a new bug in SPI core that made the warning
suddenly disappear:
https://patchwork.kernel.org/project/spi-devel-general/patch/44b2ad71-dc4b-801c-237f-9c233f675...@gmail.com/

>> +   {},\
>> +}; \
>> +  \
>> +MODULE_DEVICE_TABLE(spi, spi_ids);\
>>\
>>  static struct spi_driver fbtft_driver_spi_driver = {   \
>> .driver = {\
>> .name   = _name,   \
>> .of_match_table = dt_ids,  \
>> }, \
>> +   .id_table = spi_ids,   \
>> .probe  = fbtft_driver_probe_spi,  \
>> .remove = fbtft_driver_remove_spi, \
>>  }; \
> 
> Gr{oetje,eeting}s,
> 
> Geert
> 
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- 
> ge...@linux-m68k.org
> 
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like 
> that.
> -- Linus Torvalds
> 



Re: [PATCH 6/6] Documentation/gpu: Add DC glossary

2021-11-30 Thread Yann Dirson



- Mail original -
> De: "Rodrigo Siqueira Jordao" 
> À: ydir...@free.fr, "Rodrigo Siqueira" , "Christian 
> König" ,
> "Alex Deucher" 
> Cc: "Harry Wentland" , "Linux Doc Mailing List" 
> , "Mark Yacoub"
> , "Michel Dänzer" , "Bas 
> Nieuwenhuizen" ,
> "Roman Li" , "amd-gfx list" 
> , "Roman Gilg" ,
> "Marek Olšák" , "Pekka Paalanen" , 
> "Aurabindo Pillai"
> , "nicholas choi" , "Maling 
> list - DRI developers"
> , "Simon Ser" , "Alex 
> Deucher" , "Sean
> Paul" , "Qingqing Zhuo" , 
> "Bhawanpreet Lakha"
> , "Nicholas Kazlauskas" 
> 
> Envoyé: Mardi 30 Novembre 2021 16:53:55
> Objet: Re: [PATCH 6/6] Documentation/gpu: Add DC glossary
> 
> 
> 
> On 2021-11-29 3:48 p.m., ydir...@free.fr wrote:
> > Hi Rodrigo,
> > 
> > That will really be helpful!
> > 
> > I know drawing the line is a difficult problem (and can even make
> > things
> > harder when searching), but maybe it would make sense to keep
> > generic
> > acronyms not specific to amdgpu in a separate list.  I bet a number
> > of
> > them would be useful in the scope of other drm drivers (e.g. CRTC,
> > DCC,
> > MST), and some are not restricted to the drm subsystem at all (e.g.
> > FEC,
> > LUT), but still have value as not necessarily easy to look up.
> > 
> > Maybe "DC glossary" should just be "Glossary", since quite some
> > entries
> > help to read adm/amdgpu/ too.  Which brings me to the result of my
> > recent
> > searches as suggested entries:
> > 
> >   KIQ (Kernel Interface Queue), MQD (memory queue descriptor), HQD
> >   (hardware
> >   queue descriptor), EOP (still no clue :)
> > 
> > Maybe some more specific ones just to be spelled out in clear where
> > they
> > are used ?  KCQ (compute queue?), KGQ (gfx queue?)
> > 
> > More suggestions inlined.
> > 
> > Best regards,
> > 
> 
> Hi all,
> 
> I'll address all the highlighted problems in the V2. Thanks a lot for
> all the feedback.
> 
> Yann,
> For the generic acronyms, how about keeping it in this patch for now?
> After it gets merged, I can prepare a new documentation patch that
> creates a glossary for DRM where I move the generic acronyms to the
> DRM
> documentation. I prefer this approach to keep the improvement small
> and
> manageable.

Sure, especially as the Right Solution(tm) is not necessarily obvious :)

One thing I thought about is that a context could be specified together
with terms.  Like "BPP (graphics)", "FEC (CS)", "DMCUB (amdgpu)".  Well,
"CS" may not be a good choice but you get the idea: that would keep all
terms together and keep it easy for the reader.

That way it could be easily be generalized at some point by just moving
it to a generic kernel level - provided the solution suits the doc
community at large.

Best regards,
-- 
Yann




Re: [PATCH v1 1/2] dt-bindings: sharp, lq101r1sx01: Add compatible for LQ101R1SX03

2021-11-30 Thread Dmitry Osipenko
30.11.2021 18:54, Dmitry Osipenko пишет:
> 30.11.2021 00:32, Rob Herring пишет:
>> On Sun, Nov 14, 2021 at 11:07:16PM +0300, Dmitry Osipenko wrote:
>>> From: Anton Bambura 
>>>
>>> LQ101R1SX03 is compatible with LQ101R1SX01, document it.
>>
>> Then sounds like '"sharp,lq101r1sx03", "sharp,lq101r1sx01"' would be the 
>> appropriate compatible value. Do that, and you don't need a driver 
>> change.
> 
> Apparently you're right. The "sharp,lq101r1sx03" should be a slightly
> improved revision of "sharp,lq101r1sx01". I see now that LQ101R1SX03 is
> sold as a spare part panel for ASUS TF701T, hence these panels should be
> entirely compatible with each other.
> 

I mixed up the panel model which TF701T uses.

I compared datasheets of both panel variants. These panel have
differences in the pins configuration. Hence panels seems aren't
compatible in terms of hardware integration, although the difference is
small. They should be compatible from software perspective.


Re: [PATCH v4] drm/i915: Use per device iommu check

2021-11-30 Thread Lucas De Marchi

On Fri, Nov 26, 2021 at 02:14:24PM +, Tvrtko Ursulin wrote:

From: Tvrtko Ursulin 

With both integrated and discrete Intel GPUs in a system, the current
global check of intel_iommu_gfx_mapped, as done from intel_vtd_active()
may not be completely accurate.

In this patch we add i915 parameter to intel_vtd_active() in order to
prepare it for multiple GPUs and we also change the check away from Intel
specific intel_iommu_gfx_mapped (global exported by the Intel IOMMU
driver) to probing the presence of IOMMU on a specific device using
device_iommu_mapped().

This will return true both for IOMMU pass-through and address translation
modes which matches the current behaviour. If in the future we wanted to
distinguish between these two modes we could either use
iommu_get_domain_for_dev() and check for __IOMMU_DOMAIN_PAGING bit
indicating address translation, or ask for a new API to be exported from
the IOMMU core code.

v2:
 * Check for dmar translation specifically, not just iommu domain. (Baolu)

v3:
* Go back to plain "any domain" check for now, rewrite commit message.

v4:
* Use device_iommu_mapped. (Robin, Baolu)

Signed-off-by: Tvrtko Ursulin 
Cc: Lu Baolu 
Cc: Lucas De Marchi 
Cc: Robin Murphy 
Acked-by: Robin Murphy 
Reviewed-by: Lu Baolu 


this last version looks pretty clean.

Also, for patches touching gem / gt we should Cc dri-devel. I'm leaving
the patch below for reference and Cc'ing it. Small nit below,
but can be ignored.


---
drivers/gpu/drm/i915/display/intel_bw.c  |  2 +-
drivers/gpu/drm/i915/display/intel_display.c |  2 +-
drivers/gpu/drm/i915/display/intel_fbc.c |  2 +-
drivers/gpu/drm/i915/gem/i915_gem_stolen.c   |  2 +-
drivers/gpu/drm/i915/gem/i915_gemfs.c|  2 +-
drivers/gpu/drm/i915/gt/intel_ggtt.c |  4 ++--
drivers/gpu/drm/i915/i915_debugfs.c  |  1 +
drivers/gpu/drm/i915/i915_driver.c   |  7 +++
drivers/gpu/drm/i915/i915_drv.h  | 13 +++--
drivers/gpu/drm/i915/i915_gpu_error.c|  5 +
drivers/gpu/drm/i915/intel_device_info.c | 14 +-
drivers/gpu/drm/i915/intel_pm.c  |  2 +-
12 files changed, 25 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bw.c 
b/drivers/gpu/drm/i915/display/intel_bw.c
index abec394f6869..2da4aacc956b 100644
--- a/drivers/gpu/drm/i915/display/intel_bw.c
+++ b/drivers/gpu/drm/i915/display/intel_bw.c
@@ -634,7 +634,7 @@ static unsigned int intel_bw_data_rate(struct 
drm_i915_private *dev_priv,
for_each_pipe(dev_priv, pipe)
data_rate += bw_state->data_rate[pipe];

-   if (DISPLAY_VER(dev_priv) >= 13 && intel_vtd_active())
+   if (DISPLAY_VER(dev_priv) >= 13 && intel_vtd_active(dev_priv))
data_rate = data_rate * 105 / 100;

return data_rate;
diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index b2d51cd79d6c..1ef77ba7f645 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1293,7 +1293,7 @@ static bool needs_async_flip_vtd_wa(const struct 
intel_crtc_state *crtc_state)
{
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);

-   return crtc_state->uapi.async_flip && intel_vtd_active() &&
+   return crtc_state->uapi.async_flip && intel_vtd_active(i915) &&
(DISPLAY_VER(i915) == 9 || IS_BROADWELL(i915) || 
IS_HASWELL(i915));
}

diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c 
b/drivers/gpu/drm/i915/display/intel_fbc.c
index d0c34bc3af6c..614e8697c068 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -1677,7 +1677,7 @@ static int intel_sanitize_fbc_option(struct 
drm_i915_private *i915)
static bool need_fbc_vtd_wa(struct drm_i915_private *i915)
{
/* WaFbcTurnOffFbcWhenHyperVisorIsUsed:skl,bxt */
-   if (intel_vtd_active() &&
+   if (intel_vtd_active(i915) &&
(IS_SKYLAKE(i915) || IS_BROXTON(i915))) {
drm_info(>drm,
 "Disabling framebuffer compression (FBC) to prevent screen 
flicker with VT-d enabled\n");
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c 
b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
index 80680395bb3b..bce03d74a0b4 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
@@ -399,7 +399,7 @@ static int i915_gem_init_stolen(struct intel_memory_region 
*mem)
return 0;
}

-   if (intel_vtd_active() && GRAPHICS_VER(i915) < 8) {
+   if (intel_vtd_active(i915) && GRAPHICS_VER(i915) < 8) {
drm_notice(>drm,
   "%s, disabling use of stolen memory\n",
   "DMAR active");
diff --git a/drivers/gpu/drm/i915/gem/i915_gemfs.c 
b/drivers/gpu/drm/i915/gem/i915_gemfs.c
index dbdbdc344d87..11cd66d183e6 100644
--- a/drivers/gpu/drm/i915/gem/i915_gemfs.c

Re: [RFC PATCH 1/2] dma-fence: Avoid establishing a locking order between fence classes

2021-11-30 Thread Thomas Hellström



On 11/30/21 19:12, Thomas Hellström wrote:

On Tue, 2021-11-30 at 16:02 +0100, Christian König wrote:

Am 30.11.21 um 15:35 schrieb Thomas Hellström:

On Tue, 2021-11-30 at 14:26 +0100, Christian König wrote:

Am 30.11.21 um 13:56 schrieb Thomas Hellström:

On 11/30/21 13:42, Christian König wrote:

Am 30.11.21 um 13:31 schrieb Thomas Hellström:

[SNIP]

Other than that, I didn't investigate the nesting fails
enough to
say I can accurately review this. :)

Basically the problem is that within enable_signaling()
which
is
called with the dma_fence lock held, we take the dma_fence
lock
of
another fence. If that other fence is a dma_fence_array, or
a
dma_fence_chain which in turn tries to lock a
dma_fence_array
we hit
a splat.

Yeah, I already thought that you constructed something like
that.

You get the splat because what you do here is illegal, you
can't
mix
dma_fence_array and dma_fence_chain like this or you can end
up
in a
stack corruption.

Hmm. Ok, so what is the stack corruption, is it that the
enable_signaling() will end up with endless recursion? If so,
wouldn't
it be more usable we break that recursion chain and allow a
more
general use?

The problem is that this is not easily possible for
dma_fence_array
containers. Just imagine that you drop the last reference to the
containing fences during dma_fence_array destruction if any of
the
contained fences is another container you can easily run into
recursion
and with that stack corruption.

Indeed, that would require some deeper surgery.


That's one of the major reasons I came up with the
dma_fence_chain
container. This one you can chain any number of elements together
without running into any recursion.


Also what are the mixing rules between these? Never use a
dma-fence-chain as one of the array fences and never use a
dma-fence-array as a dma-fence-chain fence?

You can't add any other container to a dma_fence_array, neither
other
dma_fence_array instances nor dma_fence_chain instances.

IIRC at least technically a dma_fence_chain can contain a
dma_fence_array if you absolutely need that, but Daniel, Jason
and I
already had the same discussion a while back and came to the
conclusion
to avoid that as well if possible.

Yes, this is actually the use-case. But what I can't easily
guarantee
is that that dma_fence_chain isn't fed into a dma_fence_array
somewhere
else. How do you typically avoid that?

Meanwhile I guess I need to take a different approach in the driver
to
avoid this altogether.

Jason and I came up with a deep dive iterator for his use case, but I
think we don't want to use that any more after my dma_resv rework.

In other words when you need to create a new dma_fence_array you
flatten
out the existing construct which is at worst case
dma_fence_chain->dma_fence_array->dma_fence.

Ok, Are there any cross-driver contract here, Like every driver using a
dma_fence_array need to check for dma_fence_chain and flatten like
above?

/Thomas


Oh, and a follow up question:

If there was a way to break the recursion on final put() (using the same 
basic approach as patch 2 in this series uses to break recursion in 
enable_signaling()), so that none of these containers did require any 
special treatment, would it be worth pursuing? I guess it might be 
possible by having the callbacks drop the references rather than the 
loop in the final put. + a couple of changes in code iterating over the 
fence pointers.


/Thomas




Regards,
Christian.


/Thomas



Regards,
Christian.


/Thomas





Regards,
Christian.


But I'll update the commit message with a typical splat.

/Thomas


Re: [Intel-gfx] [PATCH v2 00/16] drm/i915: Remove short term pins from execbuf.

2021-11-30 Thread Tvrtko Ursulin



On 30/11/2021 11:17, Maarten Lankhorst wrote:

On 30-11-2021 09:54, Tvrtko Ursulin wrote:


Hi,

On 29/11/2021 13:47, Maarten Lankhorst wrote:

New version of the series, with feedback from previous series added.


If there was a cover letter sent for this work in the past could you please 
keep attaching it? Or if there wasn't, could you please write one?

I am worried about two things. First is that we need to have a high level 
overview of the rules/design changes documented so third party people have any 
hope of getting code right after this lands. (Where we are, where we are going, 
how we will get there, how far did we get and when we will get to the end.)

Second is that when parts of the series land piecemeal (Which they have in this 
right, right?), it gets very hard to write up a maintainer level changelog.


The preparation part is to ensure we always hold vma->obj->resv when unbinding.

The first preparation series ensured vma->obj always existed. This was not the 
case for mock gtt and gen6 aliasing gtt. This allowed us to remove all the special 
handling for those uncommon cases, and actually enforce we can always take that 
lock. This part is merged.


Sounds good. But also mention the high level motivation for why we 
always want to hold vma->obj->resv when unbinding in the introduction as 
well.




Patch 2-11 in this series adds the vma->obj->resv to eviction and shrinker. 
Those are the only parts where we don't take the lock yet.

After that, we always hold the lock when required, and we can start requiring the 
obj-> resv lock when unbinding. This is completed in patch 15.

With that fixed, removing short term pins can be done, because for unbind we now 
always take obj->resv, so holding obj->resv during execbuf submission is 
sufficient, and all short term pinning can be removed.


I'd also like the cover letter to contain a high level description on 
_why_ is removing short term pins needed or beneficial.


What was the flow and object lifetimes so far, and what it will be going 
forward etc.




We only pin temporarily when calling i915_gem_evict_vm in execbuf, which could 
also be handled in theory by just marking all objects as unpinned.

As a bonus, using TTM for delayed eviction on all objects becomes easy, just 
need to get rid of i915_active in i915_vma, as it keeps the object refcount 
alive.

Remainder is removing refcount to i915_vma, to make it a real


Sounds on the right track with maybe a bit more text so the readers can 
easily understand it on the higher level.





But in any case, even on the mundane process level, we need to have cover 
letters for any non trivial work was the conclusion since some time ago.


Here you go! I hope it explains the reasoning.


It is on the right track. I think just needs to be expanded a bit with 
high level direction and plan, pointing out where in the grand scheme 
this series is. And then don't forget to add the improved text as cover 
letter when sending next time please.


Regards,

Tvrtko


Re: [RFC PATCH 1/2] dma-fence: Avoid establishing a locking order between fence classes

2021-11-30 Thread Thomas Hellström
On Tue, 2021-11-30 at 16:02 +0100, Christian König wrote:
> Am 30.11.21 um 15:35 schrieb Thomas Hellström:
> > On Tue, 2021-11-30 at 14:26 +0100, Christian König wrote:
> > > Am 30.11.21 um 13:56 schrieb Thomas Hellström:
> > > > On 11/30/21 13:42, Christian König wrote:
> > > > > Am 30.11.21 um 13:31 schrieb Thomas Hellström:
> > > > > > [SNIP]
> > > > > > > Other than that, I didn't investigate the nesting fails
> > > > > > > enough to
> > > > > > > say I can accurately review this. :)
> > > > > > Basically the problem is that within enable_signaling()
> > > > > > which
> > > > > > is
> > > > > > called with the dma_fence lock held, we take the dma_fence
> > > > > > lock
> > > > > > of
> > > > > > another fence. If that other fence is a dma_fence_array, or
> > > > > > a
> > > > > > dma_fence_chain which in turn tries to lock a
> > > > > > dma_fence_array
> > > > > > we hit
> > > > > > a splat.
> > > > > Yeah, I already thought that you constructed something like
> > > > > that.
> > > > > 
> > > > > You get the splat because what you do here is illegal, you
> > > > > can't
> > > > > mix
> > > > > dma_fence_array and dma_fence_chain like this or you can end
> > > > > up
> > > > > in a
> > > > > stack corruption.
> > > > Hmm. Ok, so what is the stack corruption, is it that the
> > > > enable_signaling() will end up with endless recursion? If so,
> > > > wouldn't
> > > > it be more usable we break that recursion chain and allow a
> > > > more
> > > > general use?
> > > The problem is that this is not easily possible for
> > > dma_fence_array
> > > containers. Just imagine that you drop the last reference to the
> > > containing fences during dma_fence_array destruction if any of
> > > the
> > > contained fences is another container you can easily run into
> > > recursion
> > > and with that stack corruption.
> > Indeed, that would require some deeper surgery.
> > 
> > > That's one of the major reasons I came up with the
> > > dma_fence_chain
> > > container. This one you can chain any number of elements together
> > > without running into any recursion.
> > > 
> > > > Also what are the mixing rules between these? Never use a
> > > > dma-fence-chain as one of the array fences and never use a
> > > > dma-fence-array as a dma-fence-chain fence?
> > > You can't add any other container to a dma_fence_array, neither
> > > other
> > > dma_fence_array instances nor dma_fence_chain instances.
> > > 
> > > IIRC at least technically a dma_fence_chain can contain a
> > > dma_fence_array if you absolutely need that, but Daniel, Jason
> > > and I
> > > already had the same discussion a while back and came to the
> > > conclusion
> > > to avoid that as well if possible.
> > Yes, this is actually the use-case. But what I can't easily
> > guarantee
> > is that that dma_fence_chain isn't fed into a dma_fence_array
> > somewhere
> > else. How do you typically avoid that?
> > 
> > Meanwhile I guess I need to take a different approach in the driver
> > to
> > avoid this altogether.
> 
> Jason and I came up with a deep dive iterator for his use case, but I
> think we don't want to use that any more after my dma_resv rework.
> 
> In other words when you need to create a new dma_fence_array you
> flatten 
> out the existing construct which is at worst case 
> dma_fence_chain->dma_fence_array->dma_fence.

Ok, Are there any cross-driver contract here, Like every driver using a
dma_fence_array need to check for dma_fence_chain and flatten like
above?

/Thomas


> 
> Regards,
> Christian.
> 
> > 
> > /Thomas
> > 
> > 
> > > Regards,
> > > Christian.
> > > 
> > > > /Thomas
> > > > 
> > > > 
> > > > 
> > > > 
> > > > > Regards,
> > > > > Christian.
> > > > > 
> > > > > > But I'll update the commit message with a typical splat.
> > > > > > 
> > > > > > /Thomas
> > 
> 




Re: [PATCH 1/3] drm/simpledrm: Bind to OF framebuffers in /chosen

2021-11-30 Thread Rob Herring
On Tue, Nov 30, 2021 at 12:45 AM Javier Martinez Canillas
 wrote:
>
> > > >
> > > > Simpledrm is just a driver, but this is platform setup code. Why is this
> > > > code located here and not under arch/ or drivers/firmware/?
> > > >
>
> Agreed. Creating platform devices is something for platform code and
> not really a DRM driver.
>
> > > > I know that other drivers do similar things, it doesn't seem to belong 
> > > > here.
> > >
>
> Yeah, the simplefb driver does this but that seems like something that
> should be changed.
>
> > > This definitely doesn't belong in either of those, since it is not arch-
> > > or firmware-specific. It is implementing support for the standard
> > > simple-framebuffer OF binding, which specifies that it must be located
> > > within the /chosen node (and thus the default OF setup code won't do the
> > > matching for you); this applies to all OF platforms [1]
> > >
> > > Adding Rob; do you think this should move from simplefb/simpledrm to
> > > common OF code? (where?)
> >
> > of_platform_default_populate_init() should work.
>
> That should work but I still wonder if it is the correct place to add
> this logic.

It is because that is where most of the other devices are created
unless the bus handles it.

> I think that instead it could be done in the sysfb_create_simplefb()
> function [0], which already creates the "simple-framebuffer" device
> for x86 legacy BIOS and x86/arm64/riscv EFI so it makes sense to do
> the same for OF. That way the simplefb platform device registration
> code could also be dropped from the driver and users would just need
> to enable CONFIG_SYSFB and CONFIG_SYSFB_SIMPLEFB to have the same.

Doesn't look like that would share anything with anything else (BIOS/EFI/ACPI).

Rob


Re: [PATCH v9 3/8] dt-bindings: display: Add ingenic,jz4780-dw-hdmi DT Schema

2021-11-30 Thread Rob Herring
On Tue, Nov 30, 2021 at 11:03 AM H. Nikolaus Schaller  
wrote:
>
> Hi Rob,
>
> > Am 25.11.2021 um 22:26 schrieb Rob Herring :
> >
> > On Wed, 24 Nov 2021 22:29:09 +0100, H. Nikolaus Schaller wrote:
> >> From: Sam Ravnborg 
> >>
> >> Add DT bindings for the hdmi driver for the Ingenic JZ4780 SoC.
> >> Based on .txt binding from Zubair Lutfullah Kakakhel
> >>
> >> We also add generic ddc-i2c-bus to synopsys,dw-hdmi.yaml
> >>
> >> Signed-off-by: Sam Ravnborg 
> >> Signed-off-by: H. Nikolaus Schaller 
> >> Cc: Rob Herring 
> >> Cc: devicet...@vger.kernel.org
> >> ---
> >> .../display/bridge/ingenic,jz4780-hdmi.yaml   | 76 +++
> >> .../display/bridge/synopsys,dw-hdmi.yaml  |  3 +
> >> 2 files changed, 79 insertions(+)
> >> create mode 100644 
> >> Documentation/devicetree/bindings/display/bridge/ingenic,jz4780-hdmi.yaml
> >>
> >
> > My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
> > on your patch (DT_CHECKER_FLAGS is new in v5.13):
> >
> > yamllint warnings/errors:
> >
> > dtschema/dtc warnings/errors:
> > Unknown file referenced: [Errno 2] No such file or directory: 
> > '/usr/local/lib/python3.8/dist-packages/dtschema/schemas/bridge/bridge/synopsys,dw-hdmi.yaml'
>
> I wasn't able to fix that.
>
> If I change
>
>  allOf:
> -  - $ref: bridge/synopsys,dw-hdmi.yaml#
> +  - $ref: synopsys,dw-hdmi.yaml#

That is correct.

>
> then make dt_binding_check still reports:
>
> Unknown file referenced: [Errno 2] No such file or directory: 
> '/Users/hns/Library/Python/3.7/lib/python/site-packages/dtschema/schemas/bridge/synopsys,dw-hdmi.yaml'

The $id is wrong:

$id: http://devicetree.org/schemas/bridge/ingenic,jz4780-hdmi.yaml#

The path should be:
http://devicetree.org/schemas/display/bridge/ingenic,jz4780-hdmi.yaml#

Rob


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

2021-11-30 Thread Liviu Dudau
Hi Zhou,

On Tue, Nov 30, 2021 at 10:23:01PM +0800, Zhou Qingyang wrote:
> In komeda_plane_add(), komeda_get_layer_fourcc_list() is assigned to
> formats and used in drm_universal_plane_init().
> drm_universal_plane_init() passes formats to
> __drm_universal_plane_init(). __drm_universal_plane_init() further
> passes formats to memcpy() as src parameter, which could lead to an
> undefined behavior bug on failure of komeda_get_layer_fourcc_list().
> 
> Fix this bug by adding a check of formats.
> 
> This bug was found by a static analyzer. The analysis employs
> differential checking to identify inconsistent security operations
> (e.g., checks or kfrees) between two code paths and confirms that the
> inconsistent operations are not recovered in the current function or
> the callers, so they constitute bugs.
> 
> Note that, as a bug found by static analysis, it can be a false
> positive or hard to trigger. Multiple researchers have cross-reviewed
> the bug.

If multiple researchers have cross-reviewed the bug how many have reviewed the 
fix?
I'm asking because there is a problem with the fix 


> 
> Builds with CONFIG_DRM_KOMEDA=m show no new warnings,
> and our static analyzer no longer warns about this code.
> 
> Fixes: 61f1c4a8ab75 ("drm/komeda: Attach komeda_dev to DRM-KMS")
> Signed-off-by: Zhou Qingyang 
> ---
>  drivers/gpu/drm/arm/display/komeda/komeda_plane.c | 4 
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c 
> b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
> index d63d83800a8a..dd3f17e970dd 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
> @@ -265,6 +265,10 @@ static int komeda_plane_add(struct komeda_kms_dev *kms,
>  
>   formats = komeda_get_layer_fourcc_list(>fmt_tbl,
>  layer->layer_type, _formats);
> + if (!formats) {
> + err = -ENOMEM;
> + goto cleanup;

If you go to cleanup here it is too early, as the plane variable has not been
initialised by the drm_universal_plane_init(), so komeda_plane_destroy() will 
crash.
The correct fix here is to free the kplane allocation and then return -ENOMEM.

> + }
>  
>   err = drm_universal_plane_init(>base, plane,
>   get_possible_crtcs(kms, c->pipeline),
> -- 
> 2.25.1
> 

Best regards,
Liviu

-- 

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


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

2021-11-30 Thread jason-jh . lin
Change in v3:
- fix return typo: modify -NOEDV to -ENODEV.
- add missing complete function in ddp_cmdq_cb.

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

jason-jh.lin (2):
  drm/mediatek: add blocking config mode for crtc disable flow
  drm/mediatek: add devlink to cmdq dev

 drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 31 -
 1 file changed, 30 insertions(+), 1 deletion(-)

-- 
2.18.0



[PATCH v3 1/2] drm/mediatek: add blocking config mode for crtc disable flow

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

Change async cmd to blocking cmd for mtk_drm_crtc_atomic_disable
to make sure the lastest cmd is done before cmdq_suspend.

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

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c 
b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index 62529a954b62..6ca96802fd77 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -56,6 +56,8 @@ struct mtk_drm_crtc {
struct cmdq_pkt cmdq_handle;
u32 cmdq_event;
u32 cmdq_vblank_cnt;
+   boolblocking_config;
+   struct completion   cmplt;
 #endif
 
struct device   *mmsys_dev;
@@ -314,6 +316,9 @@ static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg)
}
 
mtk_crtc->cmdq_vblank_cnt = 0;
+
+   if (mtk_crtc->blocking_config)
+   complete(_crtc->cmplt);
 }
 #endif
 
@@ -584,8 +589,16 @@ static void mtk_drm_crtc_update_config(struct mtk_drm_crtc 
*mtk_crtc,
 */
mtk_crtc->cmdq_vblank_cnt = 3;
 
+   if (mtk_crtc->blocking_config)
+   init_completion(_crtc->cmplt);
+
mbox_send_message(mtk_crtc->cmdq_client.chan, cmdq_handle);
mbox_client_txdone(mtk_crtc->cmdq_client.chan, 0);
+
+   if (mtk_crtc->blocking_config) {
+   wait_for_completion(_crtc->cmplt);
+   mtk_crtc->blocking_config = false;
+   }
}
 #endif
mtk_crtc->config_updating = false;
@@ -698,7 +711,9 @@ static void mtk_drm_crtc_atomic_disable(struct drm_crtc 
*crtc,
plane_state->pending.config = true;
}
mtk_crtc->pending_planes = true;
-
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+   mtk_crtc->blocking_config = true;
+#endif
mtk_drm_crtc_update_config(mtk_crtc, false);
/* Wait for planes to be disabled */
drm_crtc_wait_one_vblank(crtc);
-- 
2.18.0



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

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

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

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c 
b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index 6ca96802fd77..88b57a20f26d 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -61,6 +61,7 @@ struct mtk_drm_crtc {
 #endif
 
struct device   *mmsys_dev;
+   struct device   *drm_dev;
struct mtk_mutex*mutex;
unsigned intddp_comp_nr;
struct mtk_ddp_comp **ddp_comp;
@@ -160,6 +161,7 @@ static void mtk_drm_crtc_destroy(struct drm_crtc *crtc)
mtk_drm_cmdq_pkt_destroy(_crtc->cmdq_handle);
 
if (mtk_crtc->cmdq_client.chan) {
+   device_link_remove(mtk_crtc->drm_dev, 
mtk_crtc->cmdq_client.chan->mbox->dev);
mbox_free_channel(mtk_crtc->cmdq_client.chan);
mtk_crtc->cmdq_client.chan = NULL;
}
@@ -908,6 +910,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
return -ENOMEM;
 
mtk_crtc->mmsys_dev = priv->mmsys_dev;
+   mtk_crtc->drm_dev = priv->dev;
mtk_crtc->ddp_comp_nr = path_len;
mtk_crtc->ddp_comp = devm_kmalloc_array(dev, mtk_crtc->ddp_comp_nr,
sizeof(*mtk_crtc->ddp_comp),
@@ -975,6 +978,17 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
}
 
if (mtk_crtc->cmdq_client.chan) {
+   struct device_link *link;
+
+   /* add devlink to cmdq dev to make sure suspend/resume order is 
correct */
+   link = device_link_add(priv->dev, 
mtk_crtc->cmdq_client.chan->mbox->dev,
+  DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS);
+   if (!link) {
+   dev_err(priv->dev, "Unable to link dev=%s\n",
+   
dev_name(mtk_crtc->cmdq_client.chan->mbox->dev));
+   return -ENODEV;
+   }
+
ret = of_property_read_u32_index(priv->mutex_node,
 "mediatek,gce-events",
 i,
-- 
2.18.0



Re: [PATCH] drm/amdkfd: Fix a wild pointer dereference in svm_range_add()

2021-11-30 Thread Felix Kuehling
Am 2021-11-30 um 11:51 a.m. schrieb philip yang:
>
>
> On 2021-11-30 6:26 a.m., Zhou Qingyang wrote:
>> In svm_range_add(), the return value of svm_range_new() is assigned
>> to prange and >insert_list is used in list_add(). There is a
>> a dereference of >insert_list in list_add(), which could lead
>> to a wild pointer dereference on failure of vm_range_new() if
>> CONFIG_DEBUG_LIST is unset in .config file.
>>
>> Fix this bug by adding a check of prange.
>>
>> This bug was found by a static analyzer. The analysis employs
>> differential checking to identify inconsistent security operations
>> (e.g., checks or kfrees) between two code paths and confirms that the
>> inconsistent operations are not recovered in the current function or
>> the callers, so they constitute bugs.
>>
>> Note that, as a bug found by static analysis, it can be a false
>> positive or hard to trigger. Multiple researchers have cross-reviewed
>> the bug.
>>
>> Builds with CONFIG_DRM_AMDGPU=m, CONFIG_HSA_AMD=y, and
>> CONFIG_HSA_AMD_SVM=y show no new warnings, and our static analyzer no
>> longer warns about this code.
>>
>> Fixes: 42de677f7999 ("drm/amdkfd: register svm range")
>> Signed-off-by: Zhou Qingyang 
> Reviewed-by: Philip Yang 

The patch looks good to me. It's an obvious bug and definitely not a
false positive. The patch description is a bit verbose. Is this
auto-generated output from the static checker? It could be replaced with
something more concise. Especially the comment about this possibly being
a false positive should not be in the final submission.

Regards,
  Felix


>> ---
>>  drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 3 +++
>>  1 file changed, 3 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
>> b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
>> index 58b89b53ebe6..e40c2211901d 100644
>> --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
>> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
>> @@ -2940,6 +2940,9 @@ svm_range_add(struct kfd_process *p, uint64_t start, 
>> uint64_t size,
>>  
>>  if (left) {
>>  prange = svm_range_new(svms, last - left + 1, last);
>> +if (!prange)
>> +return -ENOMEM;
>> +
>>  list_add(>insert_list, insert_list);
>>  list_add(>update_list, update_list);
>>  }


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

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

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

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c 
b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index e886d299813c..98486f99043e 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -61,6 +61,7 @@ struct mtk_drm_crtc {
 #endif
 
struct device   *mmsys_dev;
+   struct device   *drm_dev;
struct mtk_mutex*mutex;
unsigned intddp_comp_nr;
struct mtk_ddp_comp **ddp_comp;
@@ -160,6 +161,7 @@ static void mtk_drm_crtc_destroy(struct drm_crtc *crtc)
mtk_drm_cmdq_pkt_destroy(_crtc->cmdq_handle);
 
if (mtk_crtc->cmdq_client.chan) {
+   device_link_remove(mtk_crtc->drm_dev, 
mtk_crtc->cmdq_client.chan->mbox->dev);
mbox_free_channel(mtk_crtc->cmdq_client.chan);
mtk_crtc->cmdq_client.chan = NULL;
}
@@ -905,6 +907,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
return -ENOMEM;
 
mtk_crtc->mmsys_dev = priv->mmsys_dev;
+   mtk_crtc->drm_dev = priv->dev;
mtk_crtc->ddp_comp_nr = path_len;
mtk_crtc->ddp_comp = devm_kmalloc_array(dev, mtk_crtc->ddp_comp_nr,
sizeof(*mtk_crtc->ddp_comp),
@@ -972,6 +975,17 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
}
 
if (mtk_crtc->cmdq_client.chan) {
+   struct device_link *link;
+
+   /* add devlink to cmdq dev to make sure suspend/resume order is 
correct */
+   link = device_link_add(priv->dev, 
mtk_crtc->cmdq_client.chan->mbox->dev,
+  DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS);
+   if (!link) {
+   dev_err(priv->dev, "Unable to link dev=%s\n",
+   
dev_name(mtk_crtc->cmdq_client.chan->mbox->dev));
+   return -NODEV;
+   }
+
ret = of_property_read_u32_index(priv->mutex_node,
 "mediatek,gce-events",
 i,
-- 
2.18.0



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

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

jason-jh.lin (2):
  drm/mediatek: add blocking config mode for crtc disable flow
  drm/mediatek: add devlink to cmdq dev

 drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 28 -
 1 file changed, 27 insertions(+), 1 deletion(-)

-- 
2.18.0



[PATCH v2 1/2] drm/mediatek: add blocking config mode for crtc disable flow

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

Change async cmd to blocking cmd for mtk_drm_crtc_atomic_disable
to make sure the lastest cmd is done before cmdq_suspend.

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

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c 
b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index 62529a954b62..e886d299813c 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -56,6 +56,8 @@ struct mtk_drm_crtc {
struct cmdq_pkt cmdq_handle;
u32 cmdq_event;
u32 cmdq_vblank_cnt;
+   boolblocking_config;
+   struct completion   cmplt;
 #endif
 
struct device   *mmsys_dev;
@@ -584,8 +586,16 @@ static void mtk_drm_crtc_update_config(struct mtk_drm_crtc 
*mtk_crtc,
 */
mtk_crtc->cmdq_vblank_cnt = 3;
 
+   if (mtk_crtc->blocking_config)
+   init_completion(_crtc->cmplt);
+
mbox_send_message(mtk_crtc->cmdq_client.chan, cmdq_handle);
mbox_client_txdone(mtk_crtc->cmdq_client.chan, 0);
+
+   if (mtk_crtc->blocking_config) {
+   wait_for_completion(_crtc->cmplt);
+   mtk_crtc->blocking_config = false;
+   }
}
 #endif
mtk_crtc->config_updating = false;
@@ -698,7 +708,9 @@ static void mtk_drm_crtc_atomic_disable(struct drm_crtc 
*crtc,
plane_state->pending.config = true;
}
mtk_crtc->pending_planes = true;
-
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+   mtk_crtc->blocking_config = true;
+#endif
mtk_drm_crtc_update_config(mtk_crtc, false);
/* Wait for planes to be disabled */
drm_crtc_wait_one_vblank(crtc);
-- 
2.18.0



Re: [PATCH v9 3/8] dt-bindings: display: Add ingenic,jz4780-dw-hdmi DT Schema

2021-11-30 Thread H. Nikolaus Schaller
Hi Rob,

> Am 25.11.2021 um 22:26 schrieb Rob Herring :
> 
> On Wed, 24 Nov 2021 22:29:09 +0100, H. Nikolaus Schaller wrote:
>> From: Sam Ravnborg 
>> 
>> Add DT bindings for the hdmi driver for the Ingenic JZ4780 SoC.
>> Based on .txt binding from Zubair Lutfullah Kakakhel
>> 
>> We also add generic ddc-i2c-bus to synopsys,dw-hdmi.yaml
>> 
>> Signed-off-by: Sam Ravnborg 
>> Signed-off-by: H. Nikolaus Schaller 
>> Cc: Rob Herring 
>> Cc: devicet...@vger.kernel.org
>> ---
>> .../display/bridge/ingenic,jz4780-hdmi.yaml   | 76 +++
>> .../display/bridge/synopsys,dw-hdmi.yaml  |  3 +
>> 2 files changed, 79 insertions(+)
>> create mode 100644 
>> Documentation/devicetree/bindings/display/bridge/ingenic,jz4780-hdmi.yaml
>> 
> 
> My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
> on your patch (DT_CHECKER_FLAGS is new in v5.13):
> 
> yamllint warnings/errors:
> 
> dtschema/dtc warnings/errors:
> Unknown file referenced: [Errno 2] No such file or directory: 
> '/usr/local/lib/python3.8/dist-packages/dtschema/schemas/bridge/bridge/synopsys,dw-hdmi.yaml'

I wasn't able to fix that.

If I change

 allOf:
-  - $ref: bridge/synopsys,dw-hdmi.yaml#
+  - $ref: synopsys,dw-hdmi.yaml#

then make dt_binding_check still reports:

Unknown file referenced: [Errno 2] No such file or directory: 
'/Users/hns/Library/Python/3.7/lib/python/site-packages/dtschema/schemas/bridge/synopsys,dw-hdmi.yaml'

BR and thanks,
Nikolaus Schaller

> xargs: dt-doc-validate: exited with status 255; aborting
> make[1]: *** Deleting file 
> 'Documentation/devicetree/bindings/display/bridge/ingenic,jz4780-hdmi.example.dt.yaml'
> Unknown file referenced: [Errno 2] No such file or directory: 
> '/usr/local/lib/python3.8/dist-packages/dtschema/schemas/bridge/bridge/synopsys,dw-hdmi.yaml'
> make[1]: *** [scripts/Makefile.lib:373: 
> Documentation/devicetree/bindings/display/bridge/ingenic,jz4780-hdmi.example.dt.yaml]
>  Error 255
> make[1]: *** Waiting for unfinished jobs
> make: *** [Makefile:1413: dt_binding_check] Error 2
> 
> doc reference errors (make refcheckdocs):
> 
> See https://patchwork.ozlabs.org/patch/1559375
> 
> This check can fail if there are any dependencies. The base for a patch
> series is generally the most recent rc1.
> 
> If you already ran 'make dt_binding_check' and didn't see the above
> error(s), then make sure 'yamllint' is installed and dt-schema is up to
> date:
> 
> pip3 install dtschema --upgrade
> 
> Please check and re-submit.
> 



Re: [PATCH v2 2/2] drm: rcar-du: mipi-dsi: Use devm_drm_of_get_bridge helper

2021-11-30 Thread Kieran Bingham
Hi Laurent,

Quoting Kieran Bingham (2021-11-30 16:25:13)
> Instead of open coding the calls for
>   drm_of_find_panel_or_bridge()
>   devm_drm_panel_bridge_add()
> 
> use the devm_drm_of_get_bridge() helper directly.
> 
> Signed-off-by: Kieran Bingham 
> ---
> v2:
>  - New patch
> 
>  drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c | 19 ---
>  1 file changed, 4 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c 
> b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c
> index 0a9f197ef62c..1dfe20d3d0f2 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c
> @@ -637,7 +637,7 @@ static int rcar_mipi_dsi_host_attach(struct mipi_dsi_host 
> *host,
> struct mipi_dsi_device *device)
>  {
> struct rcar_mipi_dsi *dsi = host_to_rcar_mipi_dsi(host);
> -   struct drm_panel *panel;
> +   struct device *dev = dsi->dev;
> int ret;
>  
> if (device->lanes > dsi->num_data_lanes)
> @@ -646,20 +646,9 @@ static int rcar_mipi_dsi_host_attach(struct 
> mipi_dsi_host *host,
> dsi->lanes = device->lanes;
> dsi->format = device->format;
>  
> -   ret = drm_of_find_panel_or_bridge(dsi->dev->of_node, 1, 0, ,
> - >next_bridge);
> -   if (ret) {
> -   dev_err_probe(dsi->dev, ret, "could not find next bridge\n");
> -   return ret;
> -   }
> -
> -   if (!dsi->next_bridge) {
> -   dsi->next_bridge = devm_drm_panel_bridge_add(dsi->dev, panel);
> -   if (IS_ERR(dsi->next_bridge)) {
> -   dev_err(dsi->dev, "failed to create panel bridge\n");
> -   return PTR_ERR(dsi->next_bridge);
> -   }
> -   }
> +   dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0);
> +   if (IS_ERR(dsi->next_bridge))
> +   return PTR_ERR(dsi->next_bridge);

I did make a change here to make this:

dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0);
if (IS_ERR(dsi->next_bridge)) {
dev_err(dev, "failed to get next bridge\n");
return PTR_ERR(dsi->next_bridge);
}

But it seems I got out of sequence and saved out the wrong patch ;-(

If you think it's better with the error print, please add it while
squashing, or if you really need, I can send an updated patch and
retest.

--
Kieran


>  
> /* Initialize the DRM bridge. */
> dsi->bridge.funcs = _mipi_dsi_bridge_ops;
> -- 
> 2.30.2
>


Re: [PATCH] drm/amdkfd: Fix a wild pointer dereference in svm_range_add()

2021-11-30 Thread philip yang

  


On 2021-11-30 6:26 a.m., Zhou Qingyang
  wrote:


  In svm_range_add(), the return value of svm_range_new() is assigned
to prange and >insert_list is used in list_add(). There is a
a dereference of >insert_list in list_add(), which could lead
to a wild pointer dereference on failure of vm_range_new() if
CONFIG_DEBUG_LIST is unset in .config file.

Fix this bug by adding a check of prange.

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

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

Builds with CONFIG_DRM_AMDGPU=m, CONFIG_HSA_AMD=y, and
CONFIG_HSA_AMD_SVM=y show no new warnings, and our static analyzer no
longer warns about this code.

Fixes: 42de677f7999 ("drm/amdkfd: register svm range")
Signed-off-by: Zhou Qingyang 

Reviewed-by: Philip Yang 

  
---
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 58b89b53ebe6..e40c2211901d 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -2940,6 +2940,9 @@ svm_range_add(struct kfd_process *p, uint64_t start, uint64_t size,
 
 	if (left) {
 		prange = svm_range_new(svms, last - left + 1, last);
+		if (!prange)
+			return -ENOMEM;
+
 		list_add(>insert_list, insert_list);
 		list_add(>update_list, update_list);
 	}


  



Re: [PATCH v7 0/9] drm/omap: Add virtual-planes support

2021-11-30 Thread Neil Armstrong
Hi Tomi,

On 17/11/2021 15:19, Neil Armstrong wrote:
> This patchset is the follow-up the v4 patchset from Benoit Parrot at [1].
> 
> This patch series adds virtual-plane support to omapdrm driver to allow the 
> use
> of display wider than 2048 pixels.
> 
> In order to do so we introduce the concept of hw_overlay which can then be
> dynamically allocated to a plane. When the requested output width exceed what
> be supported by one overlay a second is then allocated if possible to handle
> display wider then 2048.
> 
> This series replaces an earlier series which was DT based and using statically
> allocated resources.
> 
> This implementation is inspired from the work done in msm/disp/mdp5
> driver.
> 
> Changes since v6 at [3]:
> - Patch 1: Added comment for drm_atomic_helper_check_plane_state, added 
> Reviewed-by
> - Patch 2: added Reviewed-by
> - Patch 3: added Reviewed-by
> - Patch 4: added Reviewed-by
> - Patch 5: added Reviewed-by
> - Patch 6: No changes
> - Patch 7: No changes
> - Patch 8: Reformatted omap_plane_atomic_print_state() output for overlays
> - Patch 9: Added a comment of the utility of the local 
> omap_atomic_update_normalize_zpos() + atomic_print_state() reformat
> 
> Changes since v5 at [2]:
> - Patch 1: renamed width/height_fp to max_width/height
> - Patch 2: no changes
> - Patch 3: removed possible_crtcs stuff,
>   added cleanup on failure to allocate,
>   removed name in omap_plane struct & plane_id_to_name in omap_plane.c,
>   switched all omap_plane->name to plane->name or omap_plane->id
> - Patch 4: aligned omap_plane_atomic_duplicate_state the the crtc style
> - Patch 5: removed glob_obj_lock & reformated global state declaration in 
> omap_drv.h
> - Patch 6: moved drm_atomic_helper_check_plane_state() from atomic_check() in 
> separate commit,
>   removed zpos change, updated debug messages to be useful,
>   renamed omap_overlay_disable() to omap_overlay_update_state(),
>   added useful comments for omap_overlay_assign() & 
> omap_overlay_update_state(),
>   simplified omap_overlay_assign() & omap_overlay_update_state() for 
> actual use-cases,
>   refactored omap_plane_atomic_check() changes to be cleaner & simpler
> - Patch 7: no changes (except possible_crtcs print removal)
> - Patch 8: Reformated omap_plane_atomic_check() & omap_overlay_assign() 
> changes to match previous patches layout 
> 
> Changes since v4 at [1]:
> - rebased on v5.15-rc2
> - adapted to drm_atomic_get_new/old_plane_state()
> - tested on Beagle-x15
> - checked for non-regression on Beagle-x15
> - removed unused "state" variable in omap_global_state
> 
> [1] https://lore.kernel.org/all/20181012201703.29065-1-bpar...@ti.com/
> [2] 
> https://lore.kernel.org/all/20210923070701.145377-1-narmstr...@baylibre.com/
> [3] 
> https://lore.kernel.org/all/20211018142842.2511200-1-narmstr...@baylibre.com
> 
> Benoit Parrot (8):
>   drm/omap: Add ability to check if requested plane modes can be
> supported
>   drm/omap: Add ovl checking funcs to dispc_ops
>   drm/omap: introduce omap_hw_overlay
>   drm/omap: omap_plane: subclass drm_plane_state
>   drm/omap: Add global state as a private atomic object
>   drm/omap: dynamically assign hw overlays to planes
>   drm/omap: add plane_atomic_print_state support
>   drm/omap: Add a 'right overlay' to plane state
> 
> Neil Armstrong (1):
>   drm/omap: add sanity plane state check
> 
>  drivers/gpu/drm/omapdrm/Makefile   |   1 +
>  drivers/gpu/drm/omapdrm/dss/dispc.c|  31 ++-
>  drivers/gpu/drm/omapdrm/dss/dss.h  |   5 +
>  drivers/gpu/drm/omapdrm/omap_drv.c | 196 +-
>  drivers/gpu/drm/omapdrm/omap_drv.h |  24 ++
>  drivers/gpu/drm/omapdrm/omap_fb.c  |  33 ++-
>  drivers/gpu/drm/omapdrm/omap_fb.h  |   4 +-
>  drivers/gpu/drm/omapdrm/omap_overlay.c | 212 +++
>  drivers/gpu/drm/omapdrm/omap_overlay.h |  35 +++
>  drivers/gpu/drm/omapdrm/omap_plane.c   | 349 +
>  drivers/gpu/drm/omapdrm/omap_plane.h   |   1 +
>  11 files changed, 832 insertions(+), 59 deletions(-)
>  create mode 100644 drivers/gpu/drm/omapdrm/omap_overlay.c
>  create mode 100644 drivers/gpu/drm/omapdrm/omap_overlay.h
> 
> 
> base-commit: 49c39ec4670a8f045729e3717af2e1a74caf89a5
> 


Gentle ping,

Neil


Re: [PATCH] drm/i915: Don't disable interrupts and pretend a lock as been acquired in __timeline_mark_lock().

2021-11-30 Thread Sebastian Andrzej Siewior
On 2021-11-19 17:04:00 [+0100], Daniel Vetter wrote:
> Yeah if we can simplify this with reverts then I'm all for this.
> 
> Acked-by: Daniel Vetter 
> 
> I've asked drm/i915 maintainers to check

Thanks. Should I repost my queue (excluding this one) or should wait
until this one has been taken care?

> -Daniel

Sebastian


[PATCH v2 2/2] drm: rcar-du: mipi-dsi: Use devm_drm_of_get_bridge helper

2021-11-30 Thread Kieran Bingham
Instead of open coding the calls for
  drm_of_find_panel_or_bridge()
  devm_drm_panel_bridge_add()

use the devm_drm_of_get_bridge() helper directly.

Signed-off-by: Kieran Bingham 
---
v2:
 - New patch

 drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c | 19 ---
 1 file changed, 4 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c 
b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c
index 0a9f197ef62c..1dfe20d3d0f2 100644
--- a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c
+++ b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c
@@ -637,7 +637,7 @@ static int rcar_mipi_dsi_host_attach(struct mipi_dsi_host 
*host,
struct mipi_dsi_device *device)
 {
struct rcar_mipi_dsi *dsi = host_to_rcar_mipi_dsi(host);
-   struct drm_panel *panel;
+   struct device *dev = dsi->dev;
int ret;
 
if (device->lanes > dsi->num_data_lanes)
@@ -646,20 +646,9 @@ static int rcar_mipi_dsi_host_attach(struct mipi_dsi_host 
*host,
dsi->lanes = device->lanes;
dsi->format = device->format;
 
-   ret = drm_of_find_panel_or_bridge(dsi->dev->of_node, 1, 0, ,
- >next_bridge);
-   if (ret) {
-   dev_err_probe(dsi->dev, ret, "could not find next bridge\n");
-   return ret;
-   }
-
-   if (!dsi->next_bridge) {
-   dsi->next_bridge = devm_drm_panel_bridge_add(dsi->dev, panel);
-   if (IS_ERR(dsi->next_bridge)) {
-   dev_err(dsi->dev, "failed to create panel bridge\n");
-   return PTR_ERR(dsi->next_bridge);
-   }
-   }
+   dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0);
+   if (IS_ERR(dsi->next_bridge))
+   return PTR_ERR(dsi->next_bridge);
 
/* Initialize the DRM bridge. */
dsi->bridge.funcs = _mipi_dsi_bridge_ops;
-- 
2.30.2



  1   2   >