Re: [RFC PATCH 02/16] dt-bindings: display: rockchip: Add EBC binding

2022-04-14 Thread Samuel Holland
Hi Andreas,

Thanks for the comments.

On 4/14/22 3:15 AM, Andreas Kemnade wrote:
> Hi Samuel,
> 
> for comparison, here is my submission for the IMX EPDC bindings:
> 
> https://lore.kernel.org/linux-devicetree/20220206080016.796556-2-andr...@kemnade.info/
> 
> On Wed, 13 Apr 2022 17:19:02 -0500
> Samuel Holland  wrote:
> 
> [...]
> we have sy7636a driver in kernel which should be suitable for powering a EPD
> and temperature measurement. So I would expect that to be 
>> +  io-channels:
>> +maxItems: 1
>> +description: I/O channel for panel temperature measurement
>> +
> so how would I reference the hwmon/thermal(-zone) of the sy7636a here?

It seems the consensus is to use a thermal zone for panel temperature, so I will
need to change this.

I think it's best to reference the thermal zone by phandle, not by name, even if
it requires extending the thermal zone API to support this.

>> +  panel-supply:
>> +description: Regulator supplying the panel's logic voltage
>> +
>> +  power-domains:
>> +maxItems: 1
>> +
>> +  vcom-supply:
>> +description: Regulator supplying the panel's compensation voltage
>> +
>> +  vdrive-supply:
>> +description: Regulator supplying the panel's gate and source drivers
>> +
> SY7636a has only one logical regulator in kernel for for the latter two.

Both properties could point to the same regulator node if there are more
consumers than regulators. I don't know of a clean way to handle the opposite
situation.

The other benefit of separating out VCOM is that the controller or panel driver
can set a calibrated voltage from e.g. NVMEM or the panel's DT node.

> If we have a separate panel node, than maybe these regulators should go
> there as they belong to the panel as they are powering the panel and
> not the EBC.

I agree on this. It doesn't work with panel-simple, but as Maxime points out, we
have more flexibility with a custom panel driver.

>> +  port:
>> +$ref: /schemas/graph.yaml#/properties/port
>> +description: OF graph port for the attached display panel
>> +
> In my approach for the IMX EPDC, (I will send a better commented one
> soon) I have no separate subnode to avoid messing with additional
> display parameters. Not sure what is really better here.

I tried to match the existing abstractions as much as possible, and I saw there
was already an "eink,vb3300-kca" display in panel-simple. I believe that one was
added for the reMarkable 2, where the existing LCD controller driver already
depends on the DRM panel code (although I have concerns about hooking that up to
a driver that doesn't understand EPDs).

My thought here is that the timings for a given panel should be the same across
controllers, both dedicated EPD controllers and LCD controllers. Or at least it
should be possible to derive the timings from some common set of parameters.

The panel node also usually hooks up to the backlight, although I am not sure
that is the right thing to do for EPDs. (And the PineNote has a separate issue
of having two backlights [warm/cool] for one display.)

Regards,
Samuel


RE: [PATCH 9/9] vfio: Remove calls to vfio_group_add_container_user()

2022-04-14 Thread Tian, Kevin
> From: Jason Gunthorpe 
> Sent: Thursday, April 14, 2022 10:22 PM
> 
> On Thu, Apr 14, 2022 at 09:51:49AM -0400, Matthew Rosato wrote:
> > On 4/12/22 11:53 AM, Jason Gunthorpe wrote:
> > > When the open_device() op is called the container_users is incremented
> and
> > > held incremented until close_device(). Thus, so long as drivers call
> > > functions within their open_device()/close_device() region they do not
> > > need to worry about the container_users.
> > >
> > > These functions can all only be called between
> > > open_device()/close_device():
> > >
> > >vfio_pin_pages()
> > >vfio_unpin_pages()
> > >vfio_dma_rw()
> > >vfio_register_notifier()
> > >vfio_unregister_notifier()
> > >
> > > So eliminate the calls to vfio_group_add_container_user() and add a
> simple
> > > WARN_ON to detect mis-use by drivers.
> > >
> >
> > vfio_device_fops_release decrements dev->open_count immediately
> before
> > calling dev->ops->close_device, which means we could enter close_device
> with
> > a dev_count of 0.
> >
> > Maybe vfio_device_fops_release should handle the same way as
> > vfio_group_get_device_fd?
> >
> > if (device->open_count == 1 && device->ops->close_device)
> > device->ops->close_device(device);
> > device->open_count--;
> 
> Yes, thanks alot! I have nothing to test these flows on...
> 
> It matches the ordering in the only other place to call close_device.
> 
> I folded this into the patch:

While it's a welcomed fix is it actually related to this series? The point
of this patch is that those functions are called when container_users
is non-zero. This is true even without this fix given container_users
is decremented after calling device->ops->close_device().

iiuc this might be better sent out as a separate fix out of this series?
Or at least add a comment in the commit msg about taking chance
to fix an unrelated issue to not cause confusion...

Thanks
Kevin


[linux-next:master] BUILD REGRESSION 40354149f4d738dc3492d9998e45b3f02950369a

2022-04-14 Thread kernel test robot
tree/branch: 
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master
branch HEAD: 40354149f4d738dc3492d9998e45b3f02950369a  Add linux-next specific 
files for 20220414

Error/Warning reports:

https://lore.kernel.org/linux-mm/202203160358.yulpl6b4-...@intel.com
https://lore.kernel.org/linux-mm/202204081656.6x4pfen4-...@intel.com
https://lore.kernel.org/linux-mm/202204140108.derahwen-...@intel.com
https://lore.kernel.org/lkml/202204140043.tx7bibvi-...@intel.com
https://lore.kernel.org/llvm/202203241958.uw9bwfmd-...@intel.com

Error/Warning: (recently discovered and may have been fixed)

ERROR: dtschema minimum version is v2022.3
aarch64-linux-ld: (.text+0x8): undefined reference to `crypto_sm4_sbox'
aarch64-linux-ld: sm4-neon-glue.c:(.text+0x880): undefined reference to 
`sm4_crypt_block'
drivers/bus/mhi/host/main.c:792:13: warning: parameter 'event_quota' set but 
not used
drivers/bus/mhi/host/main.c:792:13: warning: parameter 'event_quota' set but 
not used [-Wunused-but-set-parameter]
drivers/dma-buf/st-dma-fence-unwrap.c:25:4: warning: unused function 
'to_mock_fence'
drivers/gpu/drm/amd/amdgpu/../display/dc/virtual/virtual_link_hwss.c:32:6: 
warning: no previous prototype for 'virtual_setup_stream_attribute' 
[-Wmissing-prototypes]
sm4-neon-glue.c:(.text+0x190): undefined reference to `sm4_expandkey'
sm4-neon-glue.c:(.text+0x268): undefined reference to `sm4_crypt_block'

Unverified Error/Warning (likely false positive, please contact us if 
interested):

Makefile:684: arch/h8300/Makefile: No such file or directory
arch/Kconfig:10: can't open file "arch/h8300/Kconfig"
arch/s390/include/asm/spinlock.h:81:3: error: unexpected token in '.rept' 
directive
arch/s390/include/asm/spinlock.h:81:3: error: unknown directive
arch/s390/include/asm/spinlock.h:81:3: error: unmatched '.endr' directive
arch/s390/lib/spinlock.c:78:3: error: unexpected token in '.rept' directive
arch/s390/lib/spinlock.c:78:3: error: unknown directive
arch/s390/lib/spinlock.c:78:3: error: unmatched '.endr' directive
drivers/dma-buf/st-dma-fence-unwrap.c:125:13: warning: variable 'err' set but 
not used [-Wunused-but-set-variable]
drivers/edac/edac_device.c:73 edac_device_alloc_ctl_info() warn: Please 
consider using kcalloc instead
drivers/edac/edac_mc.c:369 edac_mc_alloc() warn: Please consider using kcalloc 
instead
drivers/gpu/drm/amd/amdgpu/../display/dc/dcn31/dcn31_hubp.c:57:6: warning: no 
previous prototype for 'hubp31_program_extended_blank' [-Wmissing-prototypes]
drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c:403:5: warning: Value stored to 'ret' 
is never read [clang-analyzer-deadcode.DeadStores]
drivers/hwmon/da9055-hwmon.c:201:9: warning: Call to function 'sprintf' is 
insecure as it does not provide bounding of the memory buffer or security 
checks introduced in the C11 standard. Replace with analogous functions that 
support length arguments or provides boundary checks such as 'sprintf_s' in 
case of C11 
[clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling]
drivers/hwmon/vt8231.c:634:9: warning: Call to function 'sprintf' is insecure 
as it does not provide bounding of the memory buffer or security checks 
introduced in the C11 standard. Replace with analogous functions that support 
length arguments or provides boundary checks such as 'sprintf_s' in case of C11 
[clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling]
drivers/misc/cb710/debug.c:96:1: warning: Call to function 'sprintf' is 
insecure as it does not provide bounding of the memory buffer or security 
checks introduced in the C11 standard. Replace with analogous functions that 
support length arguments or provides boundary checks such as 'sprintf_s' in 
case of C11 
[clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling]
drivers/usb/chipidea/core.c:956:10: warning: Call to function 'sprintf' is 
insecure as it does not provide bounding of the memory buffer or security 
checks introduced in the C11 standard. Replace with analogous functions that 
support length arguments or provides boundary checks such as 'sprintf_s' in 
case of C11 
[clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling]
drivers/usb/gadget/configfs.c:237:8: warning: Call to function 'sprintf' is 
insecure as it does not provide bounding of the memory buffer or security 
checks introduced in the C11 standard. Replace with analogous functions that 
support length arguments or provides boundary checks such as 'sprintf_s' in 
case of C11 
[clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling]
drivers/usb/gadget/udc/core.c:1664:9: warning: Call to function 'sprintf' is 
insecure as it does not provide bounding of the memory buffer or security 
checks introduced in the C11 standard. Replace with analogous functions that 
support length arguments or provides boundary checks such as 'sprintf_s' in 
case of C11 
[clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling]
drivers/video/fb

Re: [PATCH 11/12] drm/msm/dpu: gracefully handle null fb commits for writeback

2022-04-14 Thread Abhinav Kumar




On 4/14/2022 5:36 PM, Dmitry Baryshkov wrote:

On 15/04/2022 02:17, Abhinav Kumar wrote:



On 2/4/2022 2:43 PM, Dmitry Baryshkov wrote:

On 05/02/2022 00:17, Abhinav Kumar wrote:

kms_writeback test cases also verify with a null fb for the
writeback connector job. In addition there are also other
commit paths which can result in kickoffs without a valid
framebuffer like while closing the fb which results in the
callback to drm_atomic_helper_dirtyfb() which internally
triggers a commit.

Add protection in the dpu driver to ensure that commits for
writeback encoders without a valid fb are gracefully skipped.

Signed-off-by: Abhinav Kumar 
---
  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c    |  9 +
  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 21 
+

  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h |  6 ++
  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h    |  1 +
  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 12 
  5 files changed, 49 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c

index e7c9fe1..f7963b0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -869,6 +869,13 @@ void dpu_crtc_commit_kickoff(struct drm_crtc 
*crtc)

  DPU_ATRACE_BEGIN("crtc_commit");
+    drm_for_each_encoder_mask(encoder, crtc->dev,
+    crtc->state->encoder_mask) {
+    if (!dpu_encoder_has_valid_fb(encoder)) {


Two small comments here. First, let's probably rename the function to 
dpu_encoder_is_valid() or dpu_encoder_is_valid_for_commit() (ugh, too 
long). There might be other cases (in theory), why encoder is invalid 
at this moment.


dpu_encoder_is_valid_for_commit() seems fine to me even if long.


Good!





Also (a minor nit): I think that we should commit if at least one of 
encoders is valid. So we might want to create an encoder_valid_mask 
basing on the calls to dpu_encoder. And then use it later for calling 
dpu_encoder_prepare_for_kickoff() and dpu_encoder_kickoff().


Its not just these two calls. These can be easily skipped within the 
encoder itself. I had to bring this to the dpu_crtc level because of 
the frame_pending.


I see. Let's settle down on a question which should have been aksed 
initially. If we have a set of encoders, some of which are valid and 
others are not (for whatever reason), should we proceed with kickoff of 
the valid ones or should we skip it completely? Which encoder would call 
the frame_done callbacks, in the end decrementing the frame_pending?


Well, to answer this question, lets consider two cases:

1) If we are talking about only the encoder having a valid fb as the 
criteria for validity, and lets say there are two encoders one having 
valid fb and the other not having one. This is not possible.
We map the same fb which is passed from the prepare_wb_job to both the 
physical encoders today so such a case wont happen.


2) In future, if we extend this valid check for other cases like you are 
suggesting here, even in that case, lets say we have two physical 
encoders, one master and the other slave. Even if one of them is 
invalid, the frame is invalid in my opinion as it will end up displaying 
corruption on the screen.


I dont think we are missing any other case here.

IF we just consider these two, then perhaps current approach is good 
enough with just the renaming ofcourse from dpu_encoder_has_valid_fb 
---> dpu_encoder_is_valid_for_commit()






The issue is atomic_inc_return(_crtc->frame_pending)

We have to skip this call otherwise it leads to incorrect "frame done 
timeouts" because CRTC thinks frame was kicked off but it was actually 
skipped.


Maybe, what we can do is first prepare the mask.

if (hweight(crtc_encoder_mask)) {
 if (atomic_inc_return(_crtc->frame_pending) == 1) {
 /* acquire bandwidth and other resources */
 DRM_DEBUG_ATOMIC("crtc%d first commit\n", crtc->base.id);
 } else
 DRM_DEBUG_ATOMIC("crtc%d commit\n", crtc->base.id);

   dpu_crtc->play_count++;

 dpu_vbif_clear_errors(dpu_kms);
}

do the encoder_kickoff

if (hweight(crtc_encoder_mask))
 reinit_completion(_crtc->frame_done_comp);

calls to dpu_encoder_prepare_for_kickoff() and dpu_encoder_kickoff() 
can be protected by dpu_encoder_is_valid_for_commit() checks.


This is probably the best we can do here.

Let me know what you think.




+    DRM_DEBUG_ATOMIC("invalid FB not kicking off crtc\n");
+    goto end;
+    }
+    }
  /*
   * Encoder will flush/start now, unless it has a tx pending. 
If so, it

   * may delay and flush at an irq event (e.g. ppdone)
@@ -891,6 +898,8 @@ void dpu_crtc_commit_kickoff(struct drm_crtc *crtc)
  dpu_encoder_kickoff(encoder);
  reinit_completion(_crtc->frame_done_comp);
+
+end:
  DPU_ATRACE_END("crtc_commit");
  }
diff --git 

Re: [RFC PATCH 4/6] drm/panel-edp: Take advantage of is_hpd_asserted() in struct drm_dp_aux

2022-04-14 Thread Dmitry Baryshkov

On 09/04/2022 05:36, Douglas Anderson wrote:

Let's add support for being able to read the HPD pin even if it's
hooked directly to the controller. This will allow us to get more
accurate delays also lets us take away the waiting in the AUX transfer
functions of the eDP controller drivers.

Signed-off-by: Douglas Anderson 
---

  drivers/gpu/drm/panel/panel-edp.c | 37 ++-
  1 file changed, 31 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-edp.c 
b/drivers/gpu/drm/panel/panel-edp.c
index 1732b4f56e38..4a143eb9544b 100644
--- a/drivers/gpu/drm/panel/panel-edp.c
+++ b/drivers/gpu/drm/panel/panel-edp.c
@@ -417,6 +417,19 @@ static int panel_edp_get_hpd_gpio(struct device *dev, 
struct panel_edp *p)
return 0;
  }
  
+static bool panel_edp_can_read_hpd(struct panel_edp *p)

+{
+   return !p->no_hpd && (p->hpd_gpio || (p->aux && 
p->aux->is_hpd_asserted));
+}
+
+static bool panel_edp_read_hpd(struct panel_edp *p)
+{
+   if (p->hpd_gpio)
+   return gpiod_get_value_cansleep(p->hpd_gpio);
+
+   return p->aux->is_hpd_asserted(p->aux);
+}
+
  static int panel_edp_prepare_once(struct panel_edp *p)
  {
struct device *dev = p->base.dev;
@@ -441,13 +454,21 @@ static int panel_edp_prepare_once(struct panel_edp *p)
if (delay)
msleep(delay);
  
-	if (p->hpd_gpio) {

+   if (panel_edp_can_read_hpd(p)) {
if (p->desc->delay.hpd_absent)
hpd_wait_us = p->desc->delay.hpd_absent * 1000UL;
else
hpd_wait_us = 200;
  
-		err = readx_poll_timeout(gpiod_get_value_cansleep, p->hpd_gpio,

+   /*
+* Extra max delay, mostly to account for ps8640. ps8640
+* is crazy and the bridge chip driver itself has over 200 ms
+* of delay if it needs to do the pm_runtime resume of the
+* bridge chip to read the HPD.
+*/
+   hpd_wait_us += 300;


I think this should come in a separate commit and ideally this should be 
configurable somehow. Other hosts wouldn't need such 'additional' delay.


With this change removed:

Reviewed-by: Dmitry Baryshkov 



+
+   err = readx_poll_timeout(panel_edp_read_hpd, p,
 hpd_asserted, hpd_asserted,
 1000, hpd_wait_us);
if (hpd_asserted < 0)
@@ -532,18 +553,22 @@ static int panel_edp_enable(struct drm_panel *panel)
/*
 * If there is a "prepare_to_enable" delay then that's supposed to be
 * the delay from HPD going high until we can turn the backlight on.
-* However, we can only count this if HPD is handled by the panel
-* driver, not if it goes to a dedicated pin on the controller.
+* However, we can only count this if HPD is readable by the panel
+* driver.
+*
 * If we aren't handling the HPD pin ourselves then the best we
 * can do is assume that HPD went high immediately before we were
-* called (and link training took zero time).
+* called (and link training took zero time). Note that "no-hpd"
+* actually counts as handling HPD ourselves since we're doing the
+* worst case delay (in prepare) ourselves.
 *
 * NOTE: if we ever end up in this "if" statement then we're
 * guaranteed that the panel_edp_wait() call below will do no delay.
 * It already handles that case, though, so we don't need any special
 * code for it.
 */
-   if (p->desc->delay.prepare_to_enable && !p->hpd_gpio && !p->no_hpd)
+   if (p->desc->delay.prepare_to_enable &&
+   !panel_edp_can_read_hpd(p) && !p->no_hpd)
delay = max(delay, p->desc->delay.prepare_to_enable);
  
  	if (delay)



--
With best wishes
Dmitry


Re: [RFC PATCH 3/6] drm/dp: Add is_hpd_asserted() callback to struct drm_dp_aux

2022-04-14 Thread Dmitry Baryshkov

On 09/04/2022 05:36, Douglas Anderson wrote:

Sometimes it's useful for users of the DP AUX bus (like panels) to be
able to poll HPD. Let's add a callback that allows DP AUX busses
drivers to provide this.

Suggested-by: Dmitry Baryshkov 
Signed-off-by: Douglas Anderson 


Reviewed-by: Dmitry Baryshkov 


---

  include/drm/dp/drm_dp_helper.h | 14 ++
  1 file changed, 14 insertions(+)

diff --git a/include/drm/dp/drm_dp_helper.h b/include/drm/dp/drm_dp_helper.h
index dad1442c91df..a12951319573 100644
--- a/include/drm/dp/drm_dp_helper.h
+++ b/include/drm/dp/drm_dp_helper.h
@@ -2021,6 +2021,20 @@ struct drm_dp_aux {
ssize_t (*transfer)(struct drm_dp_aux *aux,
struct drm_dp_aux_msg *msg);
  
+	/**

+* @is_hpd_asserted: returns true if HPD is asserted
+*
+* This is mainly useful for eDP panels drivers to query whether
+* an eDP panel has finished powering on. This is an optional function.
+*
+* NOTE: this function specifically reports the state of the HPD pin
+* that's associated with the DP AUX channel. This is different from
+* the HPD concept in much of the rest of DRM which is more about
+* physical presence of a display. For eDP, for instance, a display is
+* assumed always present even if the HPD pin is deasserted.
+*/
+   bool (*is_hpd_asserted)(struct drm_dp_aux *aux);
+
/**
 * @i2c_nack_count: Counts I2C NACKs, used for DP validation.
 */



--
With best wishes
Dmitry


Re: [RFC PATCH 1/6] drm/dp: Helpers to make it easier for drivers to use DP AUX bus properly

2022-04-14 Thread Dmitry Baryshkov

On 09/04/2022 05:36, Douglas Anderson wrote:

As talked about in the kerneldoc for "struct dp_aux_ep_client" in this
patch and also in the past in commit a1e3667a9835 ("drm/bridge:
ti-sn65dsi86: Promote the AUX channel to its own sub-dev"), to use the
DP AUX bus properly we really need two "struct device"s. One "struct
device" is in charge of providing the DP AUX bus and the other is
where we'll try to get a reference to the newly probed endpoint
devices.

In ti-sn65dsi86 this wasn't too difficult to accomplish. That driver
is already broken up into several "struct devices" anyway because it
also provides a PWM and some GPIOs. Adding one more wasn't that
difficult / ugly.

When I tried to do the same solution in parade-ps8640, it felt like I
was copying too much boilerplate code. I made the realization that I
didn't _really_ need a separate "driver" for each person that wanted
to do the same thing. By putting all the "driver" related code in a
common place then we could save a bit of hassle. This change
effectively adds a new "ep_client" driver that can be used by
anyone. The devices instantiated by this driver will just call through
to the probe/remove/shutdown calls provided.

At the moment, the "ep_client" driver is backed by the Linux auxiliary
bus (unfortunate naming--this has nothing to do with DP AUX). I didn't
want to expose this to clients, though, so as far as clients are
concerned they get a vanilla "struct device".


I have been thinking about your approach for quite some time. I think 
that enforcing a use of auxilliary device is an overkill. What do we 
really need is the the set callbacks in the bus struct or a notifier. We 
have to notify the aux_bus controller side that the client has been 
probed successfully or that the client is going to be removed. And this 
approach would make driver's life easier, since e.g. the bus code can 
pm_get the EP device before calling callbacks/notifiers and 
pm_put_autosuspend it afterwards.




Signed-off-by: Douglas Anderson 
---

  drivers/gpu/drm/dp/drm_dp_aux_bus.c | 165 +++-
  include/drm/dp/drm_dp_aux_bus.h |  58 ++
  2 files changed, 222 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/dp/drm_dp_aux_bus.c 
b/drivers/gpu/drm/dp/drm_dp_aux_bus.c
index 415afce3cf96..5386ceacf133 100644
--- a/drivers/gpu/drm/dp/drm_dp_aux_bus.c
+++ b/drivers/gpu/drm/dp/drm_dp_aux_bus.c
@@ -12,6 +12,7 @@
   * to perform transactions on that bus.
   */
  
+#include 

  #include 
  #include 
  #include 
@@ -299,6 +300,163 @@ void dp_aux_dp_driver_unregister(struct dp_aux_ep_driver 
*drv)
  }
  EXPORT_SYMBOL_GPL(dp_aux_dp_driver_unregister);
  
+/* -

+ * DP AUX EP Client
+ */
+
+struct dp_aux_ep_client_data {
+   struct dp_aux_ep_client *client;
+   struct auxiliary_device adev;
+};
+
+static int dp_aux_ep_client_probe(struct auxiliary_device *adev,
+ const struct auxiliary_device_id *id)
+{
+   struct dp_aux_ep_client_data *data =
+   container_of(adev, struct dp_aux_ep_client_data, adev);
+
+   if (!data->client->probe)
+   return 0;
+
+   return data->client->probe(>dev, data->client);
+}
+
+static void dp_aux_ep_client_remove(struct auxiliary_device *adev)
+{
+   struct dp_aux_ep_client_data *data =
+   container_of(adev, struct dp_aux_ep_client_data, adev);
+
+   if (data->client->remove)
+   data->client->remove(>dev, data->client);
+}
+
+static void dp_aux_ep_client_shutdown(struct auxiliary_device *adev)
+{
+   struct dp_aux_ep_client_data *data =
+   container_of(adev, struct dp_aux_ep_client_data, adev);
+
+   if (data->client->shutdown)
+   data->client->shutdown(>dev, data->client);
+}
+
+static void dp_aux_ep_client_dev_release(struct device *dev)
+{
+   struct auxiliary_device *adev = to_auxiliary_dev(dev);
+   struct dp_aux_ep_client_data *data =
+   container_of(adev, struct dp_aux_ep_client_data, adev);
+
+   kfree(data);
+}
+
+/**
+ * dp_aux_register_ep_client() - Register an DP AUX EP client
+ * @client: The structure describing the client. It's the client's
+ *  responsibility to keep this memory around until
+ *  dp_aux_unregister_ep_client() is called, either explicitly or
+ *  implicitly via devm.
+ *
+ * See the description of "struct dp_aux_ep_client" for a full explanation
+ * of when you should use this and why.
+ *
+ * Return: 0 if no error or negative error code.
+ */
+int dp_aux_register_ep_client(struct dp_aux_ep_client *client)
+{
+   struct dp_aux_ep_client_data *data;
+   int ret;
+
+   data = kzalloc(sizeof(*data), GFP_KERNEL);
+   if (!data)
+   return -ENOMEM;
+
+   data->client = client;
+   data->adev.name = "ep_client";
+   data->adev.dev.parent = client->aux->dev;
+   

Re: [PATCH 11/12] drm/msm/dpu: gracefully handle null fb commits for writeback

2022-04-14 Thread Dmitry Baryshkov

On 15/04/2022 02:17, Abhinav Kumar wrote:



On 2/4/2022 2:43 PM, Dmitry Baryshkov wrote:

On 05/02/2022 00:17, Abhinav Kumar wrote:

kms_writeback test cases also verify with a null fb for the
writeback connector job. In addition there are also other
commit paths which can result in kickoffs without a valid
framebuffer like while closing the fb which results in the
callback to drm_atomic_helper_dirtyfb() which internally
triggers a commit.

Add protection in the dpu driver to ensure that commits for
writeback encoders without a valid fb are gracefully skipped.

Signed-off-by: Abhinav Kumar 
---
  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c    |  9 +
  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 21 
+

  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h |  6 ++
  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h    |  1 +
  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 12 
  5 files changed, 49 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c

index e7c9fe1..f7963b0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -869,6 +869,13 @@ void dpu_crtc_commit_kickoff(struct drm_crtc *crtc)
  DPU_ATRACE_BEGIN("crtc_commit");
+    drm_for_each_encoder_mask(encoder, crtc->dev,
+    crtc->state->encoder_mask) {
+    if (!dpu_encoder_has_valid_fb(encoder)) {


Two small comments here. First, let's probably rename the function to 
dpu_encoder_is_valid() or dpu_encoder_is_valid_for_commit() (ugh, too 
long). There might be other cases (in theory), why encoder is invalid 
at this moment.


dpu_encoder_is_valid_for_commit() seems fine to me even if long.


Good!





Also (a minor nit): I think that we should commit if at least one of 
encoders is valid. So we might want to create an encoder_valid_mask 
basing on the calls to dpu_encoder. And then use it later for calling 
dpu_encoder_prepare_for_kickoff() and dpu_encoder_kickoff().


Its not just these two calls. These can be easily skipped within the 
encoder itself. I had to bring this to the dpu_crtc level because of the 
frame_pending.


I see. Let's settle down on a question which should have been aksed 
initially. If we have a set of encoders, some of which are valid and 
others are not (for whatever reason), should we proceed with kickoff of 
the valid ones or should we skip it completely? Which encoder would call 
the frame_done callbacks, in the end decrementing the frame_pending?




The issue is atomic_inc_return(_crtc->frame_pending)

We have to skip this call otherwise it leads to incorrect "frame done 
timeouts" because CRTC thinks frame was kicked off but it was actually 
skipped.


Maybe, what we can do is first prepare the mask.

if (hweight(crtc_encoder_mask)) {
 if (atomic_inc_return(_crtc->frame_pending) == 1) {
     /* acquire bandwidth and other resources */
     DRM_DEBUG_ATOMIC("crtc%d first commit\n", crtc->base.id);
     } else
     DRM_DEBUG_ATOMIC("crtc%d commit\n", crtc->base.id);

   dpu_crtc->play_count++;

     dpu_vbif_clear_errors(dpu_kms);
}

do the encoder_kickoff

if (hweight(crtc_encoder_mask))
 reinit_completion(_crtc->frame_done_comp);

calls to dpu_encoder_prepare_for_kickoff() and dpu_encoder_kickoff() can 
be protected by dpu_encoder_is_valid_for_commit() checks.


This is probably the best we can do here.

Let me know what you think.




+    DRM_DEBUG_ATOMIC("invalid FB not kicking off crtc\n");
+    goto end;
+    }
+    }
  /*
   * Encoder will flush/start now, unless it has a tx pending. If 
so, it

   * may delay and flush at an irq event (e.g. ppdone)
@@ -891,6 +898,8 @@ void dpu_crtc_commit_kickoff(struct drm_crtc *crtc)
  dpu_encoder_kickoff(encoder);
  reinit_completion(_crtc->frame_done_comp);
+
+end:
  DPU_ATRACE_END("crtc_commit");
  }
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c

index 3746432..e990dbc 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1832,6 +1832,27 @@ void dpu_encoder_prepare_for_kickoff(struct 
drm_encoder *drm_enc)

  }
  }
+bool dpu_encoder_has_valid_fb(struct drm_encoder *drm_enc)
+{
+    struct dpu_encoder_virt *dpu_enc;
+    unsigned int i;
+    struct dpu_encoder_phys *phys;
+
+    dpu_enc = to_dpu_encoder_virt(drm_enc);
+
+    if (drm_enc->encoder_type == DRM_MODE_ENCODER_VIRTUAL) {
+    for (i = 0; i < dpu_enc->num_phys_encs; i++) {
+    phys = dpu_enc->phys_encs[i];
+    if (phys->ops.has_valid_output_fb && 
!phys->ops.has_valid_output_fb(phys)) {

+    DPU_DEBUG("invalid FB not kicking off\n");
+    return false;
+    }
+    }
+    }
+
+    return true;
+}
+
  void dpu_encoder_kickoff(struct drm_encoder *drm_enc)
  {
  

Re: [Freedreno] [PATCH 04/12] drm/msm/dpu: add changes to support writeback in hw_ctl

2022-04-14 Thread Abhinav Kumar

Sorry for multiple replies on this, I missed responding to one question.

On 4/14/2022 5:27 PM, Abhinav Kumar wrote:



On 4/14/2022 5:19 PM, Dmitry Baryshkov wrote:

On 15/04/2022 03:01, Abhinav Kumar wrote:



On 4/14/2022 4:25 PM, Dmitry Baryshkov wrote:

On 15/04/2022 00:50, Abhinav Kumar wrote:



On 2/4/2022 2:19 PM, Dmitry Baryshkov wrote:

On 05/02/2022 00:17, Abhinav Kumar wrote:

Add changes to support writeback module in the dpu_hw_ctl
interface. In addition inroduce a reset_intf_cfg op to reset
the interface bits for the currently active interfaces in
the ctl path.

Signed-off-by: Abhinav Kumar 
---
  .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c   |  3 +-
  .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c   |  6 +-
  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 65 
--

  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 27 -
  4 files changed, 91 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c

index 34a6940..4cb72fa 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
@@ -1,5 +1,6 @@
  // SPDX-License-Identifier: GPL-2.0-only
  /*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All 
rights reserved.
   * Copyright (c) 2015-2018, 2020-2021 The Linux Foundation. All 
rights reserved.

   */
@@ -70,7 +71,7 @@ static void _dpu_encoder_phys_cmd_update_intf_cfg(
  intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_CMD;
  intf_cfg.stream_sel = cmd_enc->stream_sel;
  intf_cfg.mode_3d = 
dpu_encoder_helper_get_3d_blend_mode(phys_enc);

-    ctl->ops.setup_intf_cfg(ctl, _cfg);
+    ctl->ops.setup_intf_cfg(ctl, _cfg, false);
  }
  static void dpu_encoder_phys_cmd_pp_tx_done_irq(void *arg, int 
irq_idx)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c

index ddd9d89..950fcd6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -1,5 +1,7 @@
  // SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2015-2018, 2020-2021 The Linux Foundation. All 
rights reserved.

+/*
+ *  Copyright (c) 2022 Qualcomm Innovation Center, Inc. All 
rights reserved.
+ *  Copyright (c) 2015-2018, 2020-2021 The Linux Foundation. All 
rights reserved.

   */
  #define pr_fmt(fmt)    "[drm:%s:%d] " fmt, __func__, __LINE__
@@ -290,7 +292,7 @@ static void 
dpu_encoder_phys_vid_setup_timing_engine(

  spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
  phys_enc->hw_intf->ops.setup_timing_gen(phys_enc->hw_intf,
  _params, fmt);
-    phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, 
_cfg);
+    phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, 
_cfg, false);

  /* setup which pp blk will connect to this intf */
  if (phys_enc->hw_intf->ops.bind_pingpong_blk)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c

index 02da9ec..a2069af 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -1,5 +1,6 @@
  // SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights 
reserved.
+/* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All 
rights reserved.
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights 
reserved.

   */
  #include 
@@ -23,8 +24,10 @@
  #define   CTL_SW_RESET  0x030
  #define   CTL_LAYER_EXTN_OFFSET 0x40
  #define   CTL_MERGE_3D_ACTIVE   0x0E4
+#define   CTL_WB_ACTIVE 0x0EC
  #define   CTL_INTF_ACTIVE   0x0F4
  #define   CTL_MERGE_3D_FLUSH    0x100
+#define   CTL_WB_FLUSH  0x108
  #define   CTL_INTF_FLUSH    0x110
  #define   CTL_INTF_MASTER   0x134
  #define   CTL_FETCH_PIPE_ACTIVE 0x0FC
@@ -35,6 +38,7 @@
  #define DPU_REG_RESET_TIMEOUT_US    2000
  #define  MERGE_3D_IDX   23
  #define  INTF_IDX   31
+#define WB_IDX  16
  #define CTL_INVALID_BIT 0x
  #define CTL_DEFAULT_GROUP_ID    0xf
@@ -128,6 +132,9 @@ static inline void 
dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)

  if (ctx->pending_flush_mask & BIT(INTF_IDX))
  DPU_REG_WRITE(>hw, CTL_INTF_FLUSH,
  ctx->pending_intf_flush_mask);
+    if (ctx->pending_flush_mask & BIT(WB_IDX))
+    DPU_REG_WRITE(>hw, CTL_WB_FLUSH,
+    ctx->pending_wb_flush_mask);
  DPU_REG_WRITE(>hw, CTL_FLUSH, ctx->pending_flush_mask);
  }
@@ -248,6 +255,13 @@ static void 
dpu_hw_ctl_update_pending_flush_intf(struct dpu_hw_ctl *ctx,

  }
  }
+static void dpu_hw_ctl_update_pending_flush_wb_v1(struct 
dpu_hw_ctl *ctx,

+    enum dpu_wb wb)
+{
+    ctx->pending_wb_flush_mask |= BIT(wb - WB_0);
+    

Re: [Freedreno] [PATCH 04/12] drm/msm/dpu: add changes to support writeback in hw_ctl

2022-04-14 Thread Abhinav Kumar




On 4/14/2022 5:19 PM, Dmitry Baryshkov wrote:

On 15/04/2022 03:01, Abhinav Kumar wrote:



On 4/14/2022 4:25 PM, Dmitry Baryshkov wrote:

On 15/04/2022 00:50, Abhinav Kumar wrote:



On 2/4/2022 2:19 PM, Dmitry Baryshkov wrote:

On 05/02/2022 00:17, Abhinav Kumar wrote:

Add changes to support writeback module in the dpu_hw_ctl
interface. In addition inroduce a reset_intf_cfg op to reset
the interface bits for the currently active interfaces in
the ctl path.

Signed-off-by: Abhinav Kumar 
---
  .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c   |  3 +-
  .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c   |  6 +-
  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 65 
--

  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 27 -
  4 files changed, 91 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c

index 34a6940..4cb72fa 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
@@ -1,5 +1,6 @@
  // SPDX-License-Identifier: GPL-2.0-only
  /*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights 
reserved.
   * Copyright (c) 2015-2018, 2020-2021 The Linux Foundation. All 
rights reserved.

   */
@@ -70,7 +71,7 @@ static void _dpu_encoder_phys_cmd_update_intf_cfg(
  intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_CMD;
  intf_cfg.stream_sel = cmd_enc->stream_sel;
  intf_cfg.mode_3d = 
dpu_encoder_helper_get_3d_blend_mode(phys_enc);

-    ctl->ops.setup_intf_cfg(ctl, _cfg);
+    ctl->ops.setup_intf_cfg(ctl, _cfg, false);
  }
  static void dpu_encoder_phys_cmd_pp_tx_done_irq(void *arg, int 
irq_idx)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c

index ddd9d89..950fcd6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -1,5 +1,7 @@
  // SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2015-2018, 2020-2021 The Linux Foundation. All 
rights reserved.

+/*
+ *  Copyright (c) 2022 Qualcomm Innovation Center, Inc. All 
rights reserved.
+ *  Copyright (c) 2015-2018, 2020-2021 The Linux Foundation. All 
rights reserved.

   */
  #define pr_fmt(fmt)    "[drm:%s:%d] " fmt, __func__, __LINE__
@@ -290,7 +292,7 @@ static void 
dpu_encoder_phys_vid_setup_timing_engine(

  spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
  phys_enc->hw_intf->ops.setup_timing_gen(phys_enc->hw_intf,
  _params, fmt);
-    phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, 
_cfg);
+    phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, 
_cfg, false);

  /* setup which pp blk will connect to this intf */
  if (phys_enc->hw_intf->ops.bind_pingpong_blk)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c

index 02da9ec..a2069af 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -1,5 +1,6 @@
  // SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights 
reserved.
+/* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights 
reserved.
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights 
reserved.

   */
  #include 
@@ -23,8 +24,10 @@
  #define   CTL_SW_RESET  0x030
  #define   CTL_LAYER_EXTN_OFFSET 0x40
  #define   CTL_MERGE_3D_ACTIVE   0x0E4
+#define   CTL_WB_ACTIVE 0x0EC
  #define   CTL_INTF_ACTIVE   0x0F4
  #define   CTL_MERGE_3D_FLUSH    0x100
+#define   CTL_WB_FLUSH  0x108
  #define   CTL_INTF_FLUSH    0x110
  #define   CTL_INTF_MASTER   0x134
  #define   CTL_FETCH_PIPE_ACTIVE 0x0FC
@@ -35,6 +38,7 @@
  #define DPU_REG_RESET_TIMEOUT_US    2000
  #define  MERGE_3D_IDX   23
  #define  INTF_IDX   31
+#define WB_IDX  16
  #define CTL_INVALID_BIT 0x
  #define CTL_DEFAULT_GROUP_ID    0xf
@@ -128,6 +132,9 @@ static inline void 
dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)

  if (ctx->pending_flush_mask & BIT(INTF_IDX))
  DPU_REG_WRITE(>hw, CTL_INTF_FLUSH,
  ctx->pending_intf_flush_mask);
+    if (ctx->pending_flush_mask & BIT(WB_IDX))
+    DPU_REG_WRITE(>hw, CTL_WB_FLUSH,
+    ctx->pending_wb_flush_mask);
  DPU_REG_WRITE(>hw, CTL_FLUSH, ctx->pending_flush_mask);
  }
@@ -248,6 +255,13 @@ static void 
dpu_hw_ctl_update_pending_flush_intf(struct dpu_hw_ctl *ctx,

  }
  }
+static void dpu_hw_ctl_update_pending_flush_wb_v1(struct 
dpu_hw_ctl *ctx,

+    enum dpu_wb wb)
+{
+    ctx->pending_wb_flush_mask |= BIT(wb - WB_0);
+    ctx->pending_flush_mask |= BIT(WB_IDX);
+}
+
  static void dpu_hw_ctl_update_pending_flush_intf_v1(struct 
dpu_hw_ctl *ctx,

  

Re: [Freedreno] [PATCH 08/12] drm/msm/dpu: introduce the dpu_encoder_phys_* for writeback

2022-04-14 Thread Dmitry Baryshkov

On 15/04/2022 01:16, Abhinav Kumar wrote:



On 2/4/2022 3:19 PM, Dmitry Baryshkov wrote:

On 05/02/2022 00:17, Abhinav Kumar wrote:

Introduce the dpu_encoder_phys_* for the writeback interface
to handle writeback specific hardware programming.

Signed-off-by: Abhinav Kumar 


Mostly looks ok, see minor comments bellow.


---
  drivers/gpu/drm/msm/Makefile   |   1 +
  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h   |  36 +-
  .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c    | 813 
+

  3 files changed, 849 insertions(+), 1 deletion(-)
  create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index c43ef35..3abaf84 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -53,6 +53,7 @@ msm-y := \
  disp/dpu1/dpu_encoder.o \
  disp/dpu1/dpu_encoder_phys_cmd.o \
  disp/dpu1/dpu_encoder_phys_vid.o \
+    disp/dpu1/dpu_encoder_phys_wb.o \
  disp/dpu1/dpu_formats.o \
  disp/dpu1/dpu_hw_catalog.o \
  disp/dpu1/dpu_hw_ctl.o \
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h

index 7b3354d..80da0a9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -159,6 +159,7 @@ struct dpu_encoder_phys_ops {
   * @INTR_IDX_PINGPONG: Pingpong done unterrupt for cmd mode panel
   * @INTR_IDX_UNDERRUN: Underrun unterrupt for video and cmd mode panel
   * @INTR_IDX_RDPTR:    Readpointer done unterrupt for cmd mode panel
+ * @INTR_IDX_WB_DONE:  Writeback fone interrupt for virtual connector
   */
  enum dpu_intr_idx {
  INTR_IDX_VSYNC,
@@ -166,6 +167,7 @@ enum dpu_intr_idx {
  INTR_IDX_UNDERRUN,
  INTR_IDX_CTL_START,
  INTR_IDX_RDPTR,
+    INTR_IDX_WB_DONE,
  INTR_IDX_MAX,
  };
@@ -196,7 +198,7 @@ struct dpu_encoder_irq {
   * @hw_ctl:    Hardware interface to the ctl registers
   * @hw_pp:    Hardware interface to the ping pong registers
   * @hw_intf:    Hardware interface to the intf registers
- * @hw_wb: Hardware interface to the wb registers
+ * @hw_wb:    Hardware interface to the wb registers
   * @dpu_kms:    Pointer to the dpu_kms top level
   * @cached_mode:    DRM mode cached at mode_set time, acted on in 
enable

   * @enabled:    Whether the encoder has enabled and running a mode
@@ -250,6 +252,31 @@ static inline int 
dpu_encoder_phys_inc_pending(struct dpu_encoder_phys *phys)

  }
  /**
+ * struct dpu_encoder_phys_wb - sub-class of dpu_encoder_phys to 
handle command

+ *    mode specific operations
+ * @base:    Baseclass physical encoder structure
+ * @wbirq_refcount: Reference count of writeback interrupt
+ * @wb_done_timeout_cnt: number of wb done irq timeout errors
+ * @wb_cfg:  writeback block config to store fb related details
+ * @cdp_cfg: chroma down prefetch block config for wb
+ * @aspace: address space to be used for wb framebuffer
+ * @wb_conn: backpointer to writeback connector
+ * @wb_job: backpointer to current writeback job
+ * @dest:   dpu buffer layout for current writeback output buffer
+ */
+struct dpu_encoder_phys_wb {
+    struct dpu_encoder_phys base;
+    atomic_t wbirq_refcount;
+    int wb_done_timeout_cnt;
+    struct dpu_hw_wb_cfg wb_cfg;
+    struct dpu_hw_wb_cdp_cfg cdp_cfg;


What about moving them to the stack rather storing them in the structure?


Yes cdp_cfg can be moved to the stack. Will do it in the next version.

wb_cfg cannot because for drm_wb, prepare_wb_job has the job's fb 
attributes which are used to setup the wb.


But we commit it only in the encoder_kickoff in 
dpu_encoder_phys_wb_setup_fb().


So its shared across two methods.




+    struct msm_gem_address_space *aspace;
+    struct drm_writeback_connector *wb_conn;
+    struct drm_writeback_job *wb_job;
+    struct dpu_hw_fmt_layout dest;
+};
+
+/**
   * struct dpu_encoder_phys_cmd - sub-class of dpu_encoder_phys to 
handle command

   *    mode specific operations
   * @base:    Baseclass physical encoder structure
@@ -317,6 +344,13 @@ struct dpu_encoder_phys *dpu_encoder_phys_cmd_init(
  struct dpu_enc_phys_init_params *p);
  /**
+ * dpu_encoder_phys_wb_init - initialize writeback encoder
+ * @init:    Pointer to init info structure with initialization params
+ */
+struct dpu_encoder_phys *dpu_encoder_phys_wb_init(
+    struct dpu_enc_phys_init_params *p);
+
+/**
   * dpu_encoder_helper_trigger_start - control start helper function
   *    This helper function may be optionally specified by physical
   *    encoders if they require ctl_start triggering.
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c

new file mode 100644
index 000..783f83e
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
@@ -0,0 +1,813 @@
+// SPDX-License-Identifier: 

Re: [PATCH 04/12] drm/msm/dpu: add changes to support writeback in hw_ctl

2022-04-14 Thread Dmitry Baryshkov

On 15/04/2022 03:01, Abhinav Kumar wrote:



On 4/14/2022 4:25 PM, Dmitry Baryshkov wrote:

On 15/04/2022 00:50, Abhinav Kumar wrote:



On 2/4/2022 2:19 PM, Dmitry Baryshkov wrote:

On 05/02/2022 00:17, Abhinav Kumar wrote:

Add changes to support writeback module in the dpu_hw_ctl
interface. In addition inroduce a reset_intf_cfg op to reset
the interface bits for the currently active interfaces in
the ctl path.

Signed-off-by: Abhinav Kumar 
---
  .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c   |  3 +-
  .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c   |  6 +-
  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 65 
--

  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 27 -
  4 files changed, 91 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c

index 34a6940..4cb72fa 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
@@ -1,5 +1,6 @@
  // SPDX-License-Identifier: GPL-2.0-only
  /*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights 
reserved.
   * Copyright (c) 2015-2018, 2020-2021 The Linux Foundation. All 
rights reserved.

   */
@@ -70,7 +71,7 @@ static void _dpu_encoder_phys_cmd_update_intf_cfg(
  intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_CMD;
  intf_cfg.stream_sel = cmd_enc->stream_sel;
  intf_cfg.mode_3d = 
dpu_encoder_helper_get_3d_blend_mode(phys_enc);

-    ctl->ops.setup_intf_cfg(ctl, _cfg);
+    ctl->ops.setup_intf_cfg(ctl, _cfg, false);
  }
  static void dpu_encoder_phys_cmd_pp_tx_done_irq(void *arg, int 
irq_idx)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c

index ddd9d89..950fcd6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -1,5 +1,7 @@
  // SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2015-2018, 2020-2021 The Linux Foundation. All 
rights reserved.

+/*
+ *  Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights 
reserved.
+ *  Copyright (c) 2015-2018, 2020-2021 The Linux Foundation. All 
rights reserved.

   */
  #define pr_fmt(fmt)    "[drm:%s:%d] " fmt, __func__, __LINE__
@@ -290,7 +292,7 @@ static void 
dpu_encoder_phys_vid_setup_timing_engine(

  spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
  phys_enc->hw_intf->ops.setup_timing_gen(phys_enc->hw_intf,
  _params, fmt);
-    phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, 
_cfg);
+    phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, 
_cfg, false);

  /* setup which pp blk will connect to this intf */
  if (phys_enc->hw_intf->ops.bind_pingpong_blk)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c

index 02da9ec..a2069af 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -1,5 +1,6 @@
  // SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights 
reserved.
+/* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights 
reserved.
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights 
reserved.

   */
  #include 
@@ -23,8 +24,10 @@
  #define   CTL_SW_RESET  0x030
  #define   CTL_LAYER_EXTN_OFFSET 0x40
  #define   CTL_MERGE_3D_ACTIVE   0x0E4
+#define   CTL_WB_ACTIVE 0x0EC
  #define   CTL_INTF_ACTIVE   0x0F4
  #define   CTL_MERGE_3D_FLUSH    0x100
+#define   CTL_WB_FLUSH  0x108
  #define   CTL_INTF_FLUSH    0x110
  #define   CTL_INTF_MASTER   0x134
  #define   CTL_FETCH_PIPE_ACTIVE 0x0FC
@@ -35,6 +38,7 @@
  #define DPU_REG_RESET_TIMEOUT_US    2000
  #define  MERGE_3D_IDX   23
  #define  INTF_IDX   31
+#define WB_IDX  16
  #define CTL_INVALID_BIT 0x
  #define CTL_DEFAULT_GROUP_ID    0xf
@@ -128,6 +132,9 @@ static inline void 
dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)

  if (ctx->pending_flush_mask & BIT(INTF_IDX))
  DPU_REG_WRITE(>hw, CTL_INTF_FLUSH,
  ctx->pending_intf_flush_mask);
+    if (ctx->pending_flush_mask & BIT(WB_IDX))
+    DPU_REG_WRITE(>hw, CTL_WB_FLUSH,
+    ctx->pending_wb_flush_mask);
  DPU_REG_WRITE(>hw, CTL_FLUSH, ctx->pending_flush_mask);
  }
@@ -248,6 +255,13 @@ static void 
dpu_hw_ctl_update_pending_flush_intf(struct dpu_hw_ctl *ctx,

  }
  }
+static void dpu_hw_ctl_update_pending_flush_wb_v1(struct 
dpu_hw_ctl *ctx,

+    enum dpu_wb wb)
+{
+    ctx->pending_wb_flush_mask |= BIT(wb - WB_0);
+    ctx->pending_flush_mask |= BIT(WB_IDX);
+}
+
  static void dpu_hw_ctl_update_pending_flush_intf_v1(struct 
dpu_hw_ctl *ctx,

  enum dpu_intf intf)
  {
@@ -493,10 +507,11 @@ 

Re: [Intel-gfx] [PATCH 1/1] drm/i915/guc: Update to GuC version 70.1.1

2022-04-14 Thread Matt Roper
On Tue, Apr 12, 2022 at 03:59:55PM -0700, john.c.harri...@intel.com wrote:
> From: John Harrison 
> 
> The latest GuC firmware drops the context descriptor pool in favour of
> passing all creation data in the create H2G. It also greatly simplifies
> the work queue and removes the process descriptor used for multi-LRC
> submission. So, remove all mention of LRC and process descriptors and
> update the registration code accordingly.
> 
> Unfortunately, the new API also removes the ability to set default
> values for the scheduling policies at context registration time.
> Instead, a follow up H2G must be sent. The individual scheduling
> policy update H2G commands are also dropped in favour of a single KLV
> based H2G. So, change the update wrappers accordingly and call this
> during context registration..
> 
> Of course, this second H2G per registration might fail due to being
> backed up. The registration code has a complicated state machine to
> cope with the actual registration call failing. However, if that works
> then there is no support for unwinding if a further call should fail.
> Unwinding would require sending a H2G to de-register - but that can't
> be done because the CTB is already backed up.
> 
> So instead, add a new flag to say whether the context has a pending
> policy update. This is set if the policy H2G fails at registration
> time. The submission code checks for this flag and retries the policy
> update if set. If that call fails, the submission path early exists
> with a retry error. This is something that is already supported for
> other reasons.
> 
> Signed-off-by: John Harrison 
> Reviewed-by: Daniele Ceraolo Spurio 

Applied to drm-intel-gt-next.  Thanks for the patch and review.


Matt

> ---
>  .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h  |   4 +-
>  drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h |  15 +
>  drivers/gpu/drm/i915/gt/uc/intel_guc.h|   5 -
>  drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h   |  67 ++--
>  .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 375 +++---
>  drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c  |  32 +-
>  6 files changed, 294 insertions(+), 204 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h 
> b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
> index 9ad6df1b6fbc..be9ac47fa9d0 100644
> --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
> +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
> @@ -122,11 +122,9 @@ enum intel_guc_action {
>   INTEL_GUC_ACTION_SCHED_CONTEXT_MODE_DONE = 0x1002,
>   INTEL_GUC_ACTION_SCHED_ENGINE_MODE_SET = 0x1003,
>   INTEL_GUC_ACTION_SCHED_ENGINE_MODE_DONE = 0x1004,
> - INTEL_GUC_ACTION_SET_CONTEXT_PRIORITY = 0x1005,
> - INTEL_GUC_ACTION_SET_CONTEXT_EXECUTION_QUANTUM = 0x1006,
> - INTEL_GUC_ACTION_SET_CONTEXT_PREEMPTION_TIMEOUT = 0x1007,
>   INTEL_GUC_ACTION_CONTEXT_RESET_NOTIFICATION = 0x1008,
>   INTEL_GUC_ACTION_ENGINE_FAILURE_NOTIFICATION = 0x1009,
> + INTEL_GUC_ACTION_HOST2GUC_UPDATE_CONTEXT_POLICIES = 0x100B,
>   INTEL_GUC_ACTION_SETUP_PC_GUCRC = 0x3004,
>   INTEL_GUC_ACTION_AUTHENTICATE_HUC = 0x4000,
>   INTEL_GUC_ACTION_GET_HWCONFIG = 0x4100,
> diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h 
> b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h
> index f0814a57c191..4a59478c3b5c 100644
> --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h
> +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h
> @@ -6,6 +6,8 @@
>  #ifndef _ABI_GUC_KLVS_ABI_H
>  #define _ABI_GUC_KLVS_ABI_H
>  
> +#include 
> +
>  /**
>   * DOC: GuC KLV
>   *
> @@ -79,4 +81,17 @@
>  #define GUC_KLV_SELF_CFG_G2H_CTB_SIZE_KEY0x0907
>  #define GUC_KLV_SELF_CFG_G2H_CTB_SIZE_LEN1u
>  
> +/*
> + * Per context scheduling policy update keys.
> + */
> +enum  {
> + GUC_CONTEXT_POLICIES_KLV_ID_EXECUTION_QUANTUM   = 
> 0x2001,
> + GUC_CONTEXT_POLICIES_KLV_ID_PREEMPTION_TIMEOUT  = 
> 0x2002,
> + GUC_CONTEXT_POLICIES_KLV_ID_SCHEDULING_PRIORITY = 
> 0x2003,
> + GUC_CONTEXT_POLICIES_KLV_ID_PREEMPT_TO_IDLE_ON_QUANTUM_EXPIRY   = 
> 0x2004,
> + GUC_CONTEXT_POLICIES_KLV_ID_SLPM_GT_FREQUENCY   = 
> 0x2005,
> +
> + GUC_CONTEXT_POLICIES_KLV_NUM_IDS = 5,
> +};
> +
>  #endif /* _ABI_GUC_KLVS_ABI_H */
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h 
> b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
> index 4e431c14b118..3f3373f68123 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
> @@ -170,11 +170,6 @@ struct intel_guc {
>   /** @ads_engine_usage_size: size of engine usage in the ADS */
>   u32 ads_engine_usage_size;
>  
> - /** @lrc_desc_pool: object allocated to hold the GuC LRC descriptor 
> pool */
> - struct i915_vma *lrc_desc_pool;
> - /** @lrc_desc_pool_vaddr: contents of the GuC LRC descriptor pool */
> - void *lrc_desc_pool_vaddr;
> -
>   /**
>* 

Re: [PATCH v5] drm/msm/dp: stop event kernel thread when DP unbind

2022-04-14 Thread Stephen Boyd
Quoting Kuogee Hsieh (2022-04-14 14:51:19)
> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
> b/drivers/gpu/drm/msm/dp/dp_display.c
> index 01453db..baba95d 100644
> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> @@ -230,6 +231,18 @@ void dp_display_signal_audio_complete(struct msm_dp 
> *dp_display)
> complete_all(>audio_comp);
>  }
>
> +

One too many newlines

> +static void dp_hpd_event_thread_stop(struct dp_display_private *dp_priv)
> +{
> +   kthread_stop(dp_priv->ev_tsk);
> +
> +   /* reset event q to empty */
> +   dp_priv->event_gndx = 0;
> +   dp_priv->event_pndx = 0;
> +}

This can move after the start function?

> +
> +static int dp_hpd_event_thread_start(struct dp_display_private *dp_priv);
> +
>  static int dp_display_bind(struct device *dev, struct device *master,
>void *data)
>  {

Otherwise

Reviewed-by: Stephen Boyd 


Re: [PATCH 04/12] drm/msm/dpu: add changes to support writeback in hw_ctl

2022-04-14 Thread Abhinav Kumar




On 4/14/2022 4:25 PM, Dmitry Baryshkov wrote:

On 15/04/2022 00:50, Abhinav Kumar wrote:



On 2/4/2022 2:19 PM, Dmitry Baryshkov wrote:

On 05/02/2022 00:17, Abhinav Kumar wrote:

Add changes to support writeback module in the dpu_hw_ctl
interface. In addition inroduce a reset_intf_cfg op to reset
the interface bits for the currently active interfaces in
the ctl path.

Signed-off-by: Abhinav Kumar 
---
  .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c   |  3 +-
  .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c   |  6 +-
  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 65 
--

  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 27 -
  4 files changed, 91 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c

index 34a6940..4cb72fa 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
@@ -1,5 +1,6 @@
  // SPDX-License-Identifier: GPL-2.0-only
  /*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights 
reserved.
   * Copyright (c) 2015-2018, 2020-2021 The Linux Foundation. All 
rights reserved.

   */
@@ -70,7 +71,7 @@ static void _dpu_encoder_phys_cmd_update_intf_cfg(
  intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_CMD;
  intf_cfg.stream_sel = cmd_enc->stream_sel;
  intf_cfg.mode_3d = 
dpu_encoder_helper_get_3d_blend_mode(phys_enc);

-    ctl->ops.setup_intf_cfg(ctl, _cfg);
+    ctl->ops.setup_intf_cfg(ctl, _cfg, false);
  }
  static void dpu_encoder_phys_cmd_pp_tx_done_irq(void *arg, int 
irq_idx)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c

index ddd9d89..950fcd6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -1,5 +1,7 @@
  // SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2015-2018, 2020-2021 The Linux Foundation. All 
rights reserved.

+/*
+ *  Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights 
reserved.
+ *  Copyright (c) 2015-2018, 2020-2021 The Linux Foundation. All 
rights reserved.

   */
  #define pr_fmt(fmt)    "[drm:%s:%d] " fmt, __func__, __LINE__
@@ -290,7 +292,7 @@ static void 
dpu_encoder_phys_vid_setup_timing_engine(

  spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
  phys_enc->hw_intf->ops.setup_timing_gen(phys_enc->hw_intf,
  _params, fmt);
-    phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, _cfg);
+    phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, 
_cfg, false);

  /* setup which pp blk will connect to this intf */
  if (phys_enc->hw_intf->ops.bind_pingpong_blk)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c

index 02da9ec..a2069af 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -1,5 +1,6 @@
  // SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights 
reserved.

+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
   */
  #include 
@@ -23,8 +24,10 @@
  #define   CTL_SW_RESET  0x030
  #define   CTL_LAYER_EXTN_OFFSET 0x40
  #define   CTL_MERGE_3D_ACTIVE   0x0E4
+#define   CTL_WB_ACTIVE 0x0EC
  #define   CTL_INTF_ACTIVE   0x0F4
  #define   CTL_MERGE_3D_FLUSH    0x100
+#define   CTL_WB_FLUSH  0x108
  #define   CTL_INTF_FLUSH    0x110
  #define   CTL_INTF_MASTER   0x134
  #define   CTL_FETCH_PIPE_ACTIVE 0x0FC
@@ -35,6 +38,7 @@
  #define DPU_REG_RESET_TIMEOUT_US    2000
  #define  MERGE_3D_IDX   23
  #define  INTF_IDX   31
+#define WB_IDX  16
  #define CTL_INVALID_BIT 0x
  #define CTL_DEFAULT_GROUP_ID    0xf
@@ -128,6 +132,9 @@ static inline void 
dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)

  if (ctx->pending_flush_mask & BIT(INTF_IDX))
  DPU_REG_WRITE(>hw, CTL_INTF_FLUSH,
  ctx->pending_intf_flush_mask);
+    if (ctx->pending_flush_mask & BIT(WB_IDX))
+    DPU_REG_WRITE(>hw, CTL_WB_FLUSH,
+    ctx->pending_wb_flush_mask);
  DPU_REG_WRITE(>hw, CTL_FLUSH, ctx->pending_flush_mask);
  }
@@ -248,6 +255,13 @@ static void 
dpu_hw_ctl_update_pending_flush_intf(struct dpu_hw_ctl *ctx,

  }
  }
+static void dpu_hw_ctl_update_pending_flush_wb_v1(struct dpu_hw_ctl 
*ctx,

+    enum dpu_wb wb)
+{
+    ctx->pending_wb_flush_mask |= BIT(wb - WB_0);
+    ctx->pending_flush_mask |= BIT(WB_IDX);
+}
+
  static void dpu_hw_ctl_update_pending_flush_intf_v1(struct 
dpu_hw_ctl *ctx,

  enum dpu_intf intf)
  {
@@ -493,10 +507,11 @@ static void dpu_hw_ctl_setup_blendstage(struct 

Re: [RFC PATCH 1/6] drm/dp: Helpers to make it easier for drivers to use DP AUX bus properly

2022-04-14 Thread Stephen Boyd
Quoting Douglas Anderson (2022-04-08 19:36:23)
> As talked about in the kerneldoc for "struct dp_aux_ep_client" in this
> patch and also in the past in commit a1e3667a9835 ("drm/bridge:
> ti-sn65dsi86: Promote the AUX channel to its own sub-dev"), to use the
> DP AUX bus properly we really need two "struct device"s. One "struct
> device" is in charge of providing the DP AUX bus and the other is
> where we'll try to get a reference to the newly probed endpoint
> devices.
>
> In ti-sn65dsi86 this wasn't too difficult to accomplish. That driver
> is already broken up into several "struct devices" anyway because it
> also provides a PWM and some GPIOs. Adding one more wasn't that
> difficult / ugly.
>
> When I tried to do the same solution in parade-ps8640, it felt like I
> was copying too much boilerplate code. I made the realization that I
> didn't _really_ need a separate "driver" for each person that wanted
> to do the same thing. By putting all the "driver" related code in a
> common place then we could save a bit of hassle. This change
> effectively adds a new "ep_client" driver that can be used by
> anyone. The devices instantiated by this driver will just call through
> to the probe/remove/shutdown calls provided.
>
> At the moment, the "ep_client" driver is backed by the Linux auxiliary
> bus (unfortunate naming--this has nothing to do with DP AUX). I didn't
> want to expose this to clients, though, so as far as clients are
> concerned they get a vanilla "struct device".
>
> Signed-off-by: Douglas Anderson 
> ---

Is it correct that the struct dp_aux_ep_client is largely equivalent to
a struct dp_aux_ep_device? What's the difference? I think it is a fully
probed dp_aux_ep_device? Or a way to tell the driver that calls
of_dp_aux_populate_ep_devices() that the endpoint has probed now?

I read the commit text but it didn't click until I read the next patch
that this is solving a probe ordering/loop problem. The driver that
creates the 'struct drm_dp_aux' and populates devices on the DP aux bus
with of_dp_aux_populate_ep_devices() wants to be sure that the
drm_bridge made by the 'struct dp_aux_ep_driver' probe routine in
edp-panel is going to be there before calling drm_of_get_bridge().

of_dp_aux_populate_ep_devices();
[No idea if the bridge is registered yet]
drm_of_get_bridge();

The solution is to retry the drm_of_get_bridge() until 'struct
dp_aux_ep_driver' probes and registers the next bridge. It looks like a
wait_for_completion() on top of drm_of_get_bridge() implemented through
driver probe and -EPROBE_DEFER; no disrespect!

Is there another problem here that the driver that creates the 'struct
drm_dp_aux' and populates devices on the DP aux bus with
of_dp_aux_populate_ep_devices() wants to use that same 'struct
drm_dp_aux' directly to poke at some 'struct dp_aux_ep_device' that was
populated? And the 'struct dp_aux_ep_device' may either not be probed
and bound to a 'struct dp_aux_ep_driver' or it may not be powered on
because it went to runtime PM suspend?

Put another way, I worry that the owner of 'struct drm_dp_aux' wants to
use some function in include/drm/dp/drm_dp_helper.h that takes the
'struct drm_dp_aux' directly without considering the device model state
of the endpoint device (the 'struct dp_aux_ep_device'). That would be a
similar problem as waiting for the endpoint to be powered on and probed.
Solving that through a sub-driver feels awkward.

What if we had some function like drm_dp_get_aux_ep() that took a
'struct drm_dp_aux' and looked for the endpoint device (there can only
be one?), waited for it to be probed, and then powered it up via some
pm_runtime_get_sync()? My understanding is that with edp-panel we have
two power "domains" of importance, the panel power domain and the DP/eDP
power domain. Access to the AUX bus via 'struct drm_dp_aux' needs both
power domains to be powered on. If the 'struct dp_aux_ep_device' is in
hand, then both power domains can be powered on by making sure the power
state of the 'struct dp_aux_ep_device::dev' is enabled. If only the
'struct drm_dp_aux' is in hand then we'll need to do something more like
find the child device and power it on.

Could the 'struct drm_dp_aux' functions in drm_dp_helper.h do this
automatically somehow? Maybe we can drop a variable in 'struct
drm_dp_aux' when of_dp_aux_populate_ep_devices() is called that the
other side may not be powered up. Then if something tries to transfer on
that aux channel it powers on all children of 'struct drm_dp_aux::dev'
that are on the 'dp_aux_bus_type' or bails out if those devices haven't
probed yet or can't be powered on.

> diff --git a/include/drm/dp/drm_dp_aux_bus.h b/include/drm/dp/drm_dp_aux_bus.h
> index 4f19b20b1dd6..ecf68b6873bd 100644
> --- a/include/drm/dp/drm_dp_aux_bus.h
> +++ b/include/drm/dp/drm_dp_aux_bus.h
> @@ -54,4 +54,62 @@ int __dp_aux_dp_driver_register(struct dp_aux_ep_driver 
> *aux_ep_drv,
> struct module 

Re: [PATCH v2] drm/msm/dp: enhance both connect and disconnect pending_timeout handle

2022-04-14 Thread Dmitry Baryshkov

On 15/04/2022 01:06, Kuogee Hsieh wrote:


On 4/8/2022 4:59 PM, Dmitry Baryshkov wrote:
On Fri, 8 Apr 2022 at 23:30, Kuogee Hsieh  
wrote:


On 4/8/2022 5:27 AM, Dmitry Baryshkov wrote:

On 07/04/2022 00:28, Kuogee Hsieh wrote:

dp_hpd_plug_handle() is responsible for setting up main link and send
uevent to notify user space framework to start video stream. 
Similarly,
dp_hdp_unplug_handle is responsible to send uevent to notify user 
space

framework to stop video stream and then tear down main link.
However there are rare cases, such as in the middle of system
suspending,
that uevent could not be delivered to user space framework. Therefore
some kind of recover mechanism armed by timer need to be in place 
in the

case of user space framework does not respond to uevent.

Hmm, how does userpsace 'respond' to the uevent? The driver should
send hotplug notifications to userspace, but it must not expect any
particular reaction. The userspace might be as simple, as fbdev
emulation, but the driver still should function correctly.

yes, driver is function correctly by setting up main link. but it does
not know which resolution to display.

It send hotplug notification through uevent to framework after main link
is ready.

Framework  is responsible to set up MDP timing engine to start video 
stream.



However it does not know which

It's of no concern to the driver. It is completely the userspace
problem. After resuming, it should reread available video output
properties. The display could have been changed while the system is
suspended.
 From your description I still do not understand why you need the
'recovery' mechanism.


I mean "recovery" means  dp driver may leave stay at link ready 
mistakenly after dongle unplugged due to missing framework action to 
tear down main link so that next dongle plug in will not work.


Currently it was armed with timeout function and it will fired if 
framework did not call msm_dp_display_disable() after 5 second.


framework = userspace?

Is my understanding correct? Currently DP driver sends a notification to 
userspace that DP is unplugged, waits for userspace to disable DP 
output, and only after that it will shutdown the link. Is this a correct 
description?


If so, then yes, your change is correct. I mean that the kernel 
shouldn't wait for clients to stop using video pipeline if the sink gets 
unplugged. Instead it should tear the video stream down and let the DRM 
client cope with that.


I'm not sure how should the driver react if the client doesn't disable 
the output, but then the sink gets reattached?
And a bit more interesting question: how should the driver behave if the 
new sink is not compatible with the existing video stream.




Anyway, we think this approach is not good. therefore it is replaced 
with  below patch.


drm/msm/dp: tear down main link at unplug handle immediately



--
With best wishes
Dmitry


Re: [git pull] drm fixes for 5.18-rc3

2022-04-14 Thread Linus Torvalds
On Thu, Apr 14, 2022 at 2:33 PM Dave Airlie  wrote:
>
>   git://anongit.freedesktop.org/drm/drm tags/drm-fixes-2022-04-15

.. and since I'm  now back home, I can confirm that my boot-time splat
I saw before is all gone.

It presumably went away with the previous pull request already, but I
hadn't remembered to check the issue until this pull reminded me about
the issue.

Thanks,
Linus


Re: [git pull] drm fixes for 5.18-rc3

2022-04-14 Thread pr-tracker-bot
The pull request you sent on Fri, 15 Apr 2022 07:33:01 +1000:

> git://anongit.freedesktop.org/drm/drm tags/drm-fixes-2022-04-15

has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/028192fea1de083f4f12bfb1eb7c4d7beb5c8ecd

Thank you!

-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/prtracker.html


Re: [PATCH 04/12] drm/msm/dpu: add changes to support writeback in hw_ctl

2022-04-14 Thread Dmitry Baryshkov

On 15/04/2022 00:50, Abhinav Kumar wrote:



On 2/4/2022 2:19 PM, Dmitry Baryshkov wrote:

On 05/02/2022 00:17, Abhinav Kumar wrote:

Add changes to support writeback module in the dpu_hw_ctl
interface. In addition inroduce a reset_intf_cfg op to reset
the interface bits for the currently active interfaces in
the ctl path.

Signed-off-by: Abhinav Kumar 
---
  .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c   |  3 +-
  .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c   |  6 +-
  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 65 
--

  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 27 -
  4 files changed, 91 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c

index 34a6940..4cb72fa 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
@@ -1,5 +1,6 @@
  // SPDX-License-Identifier: GPL-2.0-only
  /*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights 
reserved.
   * Copyright (c) 2015-2018, 2020-2021 The Linux Foundation. All 
rights reserved.

   */
@@ -70,7 +71,7 @@ static void _dpu_encoder_phys_cmd_update_intf_cfg(
  intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_CMD;
  intf_cfg.stream_sel = cmd_enc->stream_sel;
  intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc);
-    ctl->ops.setup_intf_cfg(ctl, _cfg);
+    ctl->ops.setup_intf_cfg(ctl, _cfg, false);
  }
  static void dpu_encoder_phys_cmd_pp_tx_done_irq(void *arg, int 
irq_idx)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c

index ddd9d89..950fcd6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -1,5 +1,7 @@
  // SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2015-2018, 2020-2021 The Linux Foundation. All 
rights reserved.

+/*
+ *  Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights 
reserved.
+ *  Copyright (c) 2015-2018, 2020-2021 The Linux Foundation. All 
rights reserved.

   */
  #define pr_fmt(fmt)    "[drm:%s:%d] " fmt, __func__, __LINE__
@@ -290,7 +292,7 @@ static void 
dpu_encoder_phys_vid_setup_timing_engine(

  spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
  phys_enc->hw_intf->ops.setup_timing_gen(phys_enc->hw_intf,
  _params, fmt);
-    phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, _cfg);
+    phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, 
_cfg, false);

  /* setup which pp blk will connect to this intf */
  if (phys_enc->hw_intf->ops.bind_pingpong_blk)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c

index 02da9ec..a2069af 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -1,5 +1,6 @@
  // SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights 
reserved.

+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
   */
  #include 
@@ -23,8 +24,10 @@
  #define   CTL_SW_RESET  0x030
  #define   CTL_LAYER_EXTN_OFFSET 0x40
  #define   CTL_MERGE_3D_ACTIVE   0x0E4
+#define   CTL_WB_ACTIVE 0x0EC
  #define   CTL_INTF_ACTIVE   0x0F4
  #define   CTL_MERGE_3D_FLUSH    0x100
+#define   CTL_WB_FLUSH  0x108
  #define   CTL_INTF_FLUSH    0x110
  #define   CTL_INTF_MASTER   0x134
  #define   CTL_FETCH_PIPE_ACTIVE 0x0FC
@@ -35,6 +38,7 @@
  #define DPU_REG_RESET_TIMEOUT_US    2000
  #define  MERGE_3D_IDX   23
  #define  INTF_IDX   31
+#define WB_IDX  16
  #define CTL_INVALID_BIT 0x
  #define CTL_DEFAULT_GROUP_ID    0xf
@@ -128,6 +132,9 @@ static inline void 
dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)

  if (ctx->pending_flush_mask & BIT(INTF_IDX))
  DPU_REG_WRITE(>hw, CTL_INTF_FLUSH,
  ctx->pending_intf_flush_mask);
+    if (ctx->pending_flush_mask & BIT(WB_IDX))
+    DPU_REG_WRITE(>hw, CTL_WB_FLUSH,
+    ctx->pending_wb_flush_mask);
  DPU_REG_WRITE(>hw, CTL_FLUSH, ctx->pending_flush_mask);
  }
@@ -248,6 +255,13 @@ static void 
dpu_hw_ctl_update_pending_flush_intf(struct dpu_hw_ctl *ctx,

  }
  }
+static void dpu_hw_ctl_update_pending_flush_wb_v1(struct dpu_hw_ctl 
*ctx,

+    enum dpu_wb wb)
+{
+    ctx->pending_wb_flush_mask |= BIT(wb - WB_0);
+    ctx->pending_flush_mask |= BIT(WB_IDX);
+}
+
  static void dpu_hw_ctl_update_pending_flush_intf_v1(struct 
dpu_hw_ctl *ctx,

  enum dpu_intf intf)
  {
@@ -493,10 +507,11 @@ static void dpu_hw_ctl_setup_blendstage(struct 
dpu_hw_ctl *ctx,

  static void 

Re: [PATCH 11/12] drm/msm/dpu: gracefully handle null fb commits for writeback

2022-04-14 Thread Abhinav Kumar




On 2/4/2022 2:43 PM, Dmitry Baryshkov wrote:

On 05/02/2022 00:17, Abhinav Kumar wrote:

kms_writeback test cases also verify with a null fb for the
writeback connector job. In addition there are also other
commit paths which can result in kickoffs without a valid
framebuffer like while closing the fb which results in the
callback to drm_atomic_helper_dirtyfb() which internally
triggers a commit.

Add protection in the dpu driver to ensure that commits for
writeback encoders without a valid fb are gracefully skipped.

Signed-off-by: Abhinav Kumar 
---
  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c    |  9 +
  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 21 
+

  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h |  6 ++
  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h    |  1 +
  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 12 
  5 files changed, 49 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c

index e7c9fe1..f7963b0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -869,6 +869,13 @@ void dpu_crtc_commit_kickoff(struct drm_crtc *crtc)
  DPU_ATRACE_BEGIN("crtc_commit");
+    drm_for_each_encoder_mask(encoder, crtc->dev,
+    crtc->state->encoder_mask) {
+    if (!dpu_encoder_has_valid_fb(encoder)) {


Two small comments here. First, let's probably rename the function to 
dpu_encoder_is_valid() or dpu_encoder_is_valid_for_commit() (ugh, too 
long). There might be other cases (in theory), why encoder is invalid at 
this moment.


dpu_encoder_is_valid_for_commit() seems fine to me even if long.



Also (a minor nit): I think that we should commit if at least one of 
encoders is valid. So we might want to create an encoder_valid_mask 
basing on the calls to dpu_encoder. And then use it later for calling 
dpu_encoder_prepare_for_kickoff() and dpu_encoder_kickoff().


Its not just these two calls. These can be easily skipped within the 
encoder itself. I had to bring this to the dpu_crtc level because of the 
frame_pending.


The issue is atomic_inc_return(_crtc->frame_pending)

We have to skip this call otherwise it leads to incorrect "frame done 
timeouts" because CRTC thinks frame was kicked off but it was actually 
skipped.


Maybe, what we can do is first prepare the mask.

if (hweight(crtc_encoder_mask)) {
if (atomic_inc_return(_crtc->frame_pending) == 1) {
/* acquire bandwidth and other resources */
DRM_DEBUG_ATOMIC("crtc%d first commit\n", crtc->base.id);
} else
DRM_DEBUG_ATOMIC("crtc%d commit\n", crtc->base.id);

dpu_crtc->play_count++;

dpu_vbif_clear_errors(dpu_kms);
}   

do the encoder_kickoff

if (hweight(crtc_encoder_mask))
reinit_completion(_crtc->frame_done_comp);

calls to dpu_encoder_prepare_for_kickoff() and dpu_encoder_kickoff() can 
be protected by dpu_encoder_is_valid_for_commit() checks.


This is probably the best we can do here.

Let me know what you think.




+    DRM_DEBUG_ATOMIC("invalid FB not kicking off crtc\n");
+    goto end;
+    }
+    }
  /*
   * Encoder will flush/start now, unless it has a tx pending. If 
so, it

   * may delay and flush at an irq event (e.g. ppdone)
@@ -891,6 +898,8 @@ void dpu_crtc_commit_kickoff(struct drm_crtc *crtc)
  dpu_encoder_kickoff(encoder);
  reinit_completion(_crtc->frame_done_comp);
+
+end:
  DPU_ATRACE_END("crtc_commit");
  }
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c

index 3746432..e990dbc 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1832,6 +1832,27 @@ void dpu_encoder_prepare_for_kickoff(struct 
drm_encoder *drm_enc)

  }
  }
+bool dpu_encoder_has_valid_fb(struct drm_encoder *drm_enc)
+{
+    struct dpu_encoder_virt *dpu_enc;
+    unsigned int i;
+    struct dpu_encoder_phys *phys;
+
+    dpu_enc = to_dpu_encoder_virt(drm_enc);
+
+    if (drm_enc->encoder_type == DRM_MODE_ENCODER_VIRTUAL) {
+    for (i = 0; i < dpu_enc->num_phys_encs; i++) {
+    phys = dpu_enc->phys_encs[i];
+    if (phys->ops.has_valid_output_fb && 
!phys->ops.has_valid_output_fb(phys)) {

+    DPU_DEBUG("invalid FB not kicking off\n");
+    return false;
+    }
+    }
+    }
+
+    return true;
+}
+
  void dpu_encoder_kickoff(struct drm_encoder *drm_enc)
  {
  struct dpu_encoder_virt *dpu_enc;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h

index da5b6d6..63d90b8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -187,4 +187,10 @@ void dpu_encoder_prepare_wb_job(struct 
drm_encoder *drm_enc,

  void 

Re: [Freedreno] [PATCH 06/12] drm/msm/dpu: make changes to dpu_encoder to support virtual encoder

2022-04-14 Thread Abhinav Kumar

Hi Marijn

Thank you for your suggestion.
I will address it and add your "Reported by".

Thanks

Abhinav

On 4/14/2022 3:26 PM, Marijn Suijten wrote:

On 2022-02-04 13:17:19, Abhinav Kumar wrote:

Make changes to dpu_encoder to support virtual encoder needed
to support writeback for dpu.

Signed-off-by: Abhinav Kumar 
---
  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 57 +
  1 file changed, 42 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index e977c05..947069b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -974,6 +974,7 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder 
*drm_enc,
struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC];
struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_ENC] = { NULL };
+   enum dpu_hw_blk_type blk_type;
int num_lm, num_ctl, num_pp;
int i, j;
  
@@ -1061,20 +1062,36 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,

phys->hw_pp = dpu_enc->hw_pp[i];
phys->hw_ctl = to_dpu_hw_ctl(hw_ctl[i]);
  
+		if (phys->intf_mode == INTF_MODE_WB_LINE)

+   blk_type = DPU_HW_BLK_WB;
+   else
+   blk_type = DPU_HW_BLK_INTF;
+
num_blk = dpu_rm_get_assigned_resources(_kms->rm,
-   global_state, drm_enc->base.id, DPU_HW_BLK_INTF,
+   global_state, drm_enc->base.id, blk_type,
hw_blk, ARRAY_SIZE(hw_blk));
-   for (j = 0; j < num_blk; j++) {
-   struct dpu_hw_intf *hw_intf;
  
-			hw_intf = to_dpu_hw_intf(hw_blk[i]);

-   if (hw_intf->idx == phys->intf_idx)
-   phys->hw_intf = hw_intf;
+   if (blk_type == DPU_HW_BLK_WB) {
+   for (j = 0; j < num_blk; j++) {
+   struct dpu_hw_wb *hw_wb;
+
+   hw_wb = to_dpu_hw_wb(hw_blk[i]);
+   if (hw_wb->idx == phys->intf_idx)
+   phys->hw_wb = hw_wb;
+   }
+   } else {
+   for (j = 0; j < num_blk; j++) {
+   struct dpu_hw_intf *hw_intf;
+
+   hw_intf = to_dpu_hw_intf(hw_blk[i]);
+   if (hw_intf->idx == phys->intf_idx)
+   phys->hw_intf = hw_intf;
+   }


It appears the original bit of code iterates j from 0 to num_blks yet
only uses i as iteration value.  All of this code seems reentrant
meaning that executing it more than one times is redundant.  You've
adopted this mistake, though I'd argue it should use j in hw_blk[i] as
that follows the number of elements in hw_blk returned by
dpu_rm_get_assigned_resources.

I suggest to address this in a separate patch (I can send that too, feel
free to add my Reported-by otherwise) and rebase this patch on top of
that, substituting i with j here as well.  It seems to have been
introduced by b954fa6baaca ("drm/msm/dpu: Refactor rm iterator").

- Marijn


}
  
-		if (!phys->hw_intf) {

+   if (!phys->hw_intf && !phys->hw_wb) {
DPU_ERROR_ENC(dpu_enc,
- "no intf block assigned at idx: %d\n", i);
+ "no intf or WB block assigned at idx: 
%d\n", i);
return;
}
  
@@ -1224,15 +1241,22 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc)

mutex_unlock(_enc->enc_lock);
  }
  
-static enum dpu_intf dpu_encoder_get_intf(struct dpu_mdss_cfg *catalog,

+static enum dpu_intf dpu_encoder_get_intf_or_wb(struct dpu_mdss_cfg *catalog,
enum dpu_intf_type type, u32 controller_id)
  {
int i = 0;
  
-	for (i = 0; i < catalog->intf_count; i++) {

-   if (catalog->intf[i].type == type
-   && catalog->intf[i].controller_id == controller_id) {
-   return catalog->intf[i].id;
+   if (type != INTF_WB) {
+   for (i = 0; i < catalog->intf_count; i++) {
+   if (catalog->intf[i].type == type
+   && catalog->intf[i].controller_id == 
controller_id) {
+   return catalog->intf[i].id;
+   }
+   }
+   } else {
+   for (i = 0; i < catalog->wb_count; i++) {
+   if (catalog->wb[i].id == controller_id)
+   return catalog->wb[i].id;
}
}
  
@@ -2096,6 +2120,9 @@ static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc,


Re: [PATCH 06/12] drm/msm/dpu: make changes to dpu_encoder to support virtual encoder

2022-04-14 Thread Marijn Suijten
On 2022-02-04 13:17:19, Abhinav Kumar wrote:
> Make changes to dpu_encoder to support virtual encoder needed
> to support writeback for dpu.
> 
> Signed-off-by: Abhinav Kumar 
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 57 
> +
>  1 file changed, 42 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index e977c05..947069b 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -974,6 +974,7 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder 
> *drm_enc,
>   struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
>   struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC];
>   struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_ENC] = { NULL };
> + enum dpu_hw_blk_type blk_type;
>   int num_lm, num_ctl, num_pp;
>   int i, j;
>  
> @@ -1061,20 +1062,36 @@ static void dpu_encoder_virt_mode_set(struct 
> drm_encoder *drm_enc,
>   phys->hw_pp = dpu_enc->hw_pp[i];
>   phys->hw_ctl = to_dpu_hw_ctl(hw_ctl[i]);
>  
> + if (phys->intf_mode == INTF_MODE_WB_LINE)
> + blk_type = DPU_HW_BLK_WB;
> + else
> + blk_type = DPU_HW_BLK_INTF;
> +
>   num_blk = dpu_rm_get_assigned_resources(_kms->rm,
> - global_state, drm_enc->base.id, DPU_HW_BLK_INTF,
> + global_state, drm_enc->base.id, blk_type,
>   hw_blk, ARRAY_SIZE(hw_blk));
> - for (j = 0; j < num_blk; j++) {
> - struct dpu_hw_intf *hw_intf;
>  
> - hw_intf = to_dpu_hw_intf(hw_blk[i]);
> - if (hw_intf->idx == phys->intf_idx)
> - phys->hw_intf = hw_intf;
> + if (blk_type == DPU_HW_BLK_WB) {
> + for (j = 0; j < num_blk; j++) {
> + struct dpu_hw_wb *hw_wb;
> +
> + hw_wb = to_dpu_hw_wb(hw_blk[i]);
> + if (hw_wb->idx == phys->intf_idx)
> + phys->hw_wb = hw_wb;
> + }
> + } else {
> + for (j = 0; j < num_blk; j++) {
> + struct dpu_hw_intf *hw_intf;
> +
> + hw_intf = to_dpu_hw_intf(hw_blk[i]);
> + if (hw_intf->idx == phys->intf_idx)
> + phys->hw_intf = hw_intf;
> + }

It appears the original bit of code iterates j from 0 to num_blks yet
only uses i as iteration value.  All of this code seems reentrant
meaning that executing it more than one times is redundant.  You've
adopted this mistake, though I'd argue it should use j in hw_blk[i] as
that follows the number of elements in hw_blk returned by
dpu_rm_get_assigned_resources.

I suggest to address this in a separate patch (I can send that too, feel
free to add my Reported-by otherwise) and rebase this patch on top of
that, substituting i with j here as well.  It seems to have been
introduced by b954fa6baaca ("drm/msm/dpu: Refactor rm iterator").

- Marijn

>   }
>  
> - if (!phys->hw_intf) {
> + if (!phys->hw_intf && !phys->hw_wb) {
>   DPU_ERROR_ENC(dpu_enc,
> -   "no intf block assigned at idx: %d\n", i);
> +   "no intf or WB block assigned at idx: 
> %d\n", i);
>   return;
>   }
>  
> @@ -1224,15 +1241,22 @@ static void dpu_encoder_virt_disable(struct 
> drm_encoder *drm_enc)
>   mutex_unlock(_enc->enc_lock);
>  }
>  
> -static enum dpu_intf dpu_encoder_get_intf(struct dpu_mdss_cfg *catalog,
> +static enum dpu_intf dpu_encoder_get_intf_or_wb(struct dpu_mdss_cfg *catalog,
>   enum dpu_intf_type type, u32 controller_id)
>  {
>   int i = 0;
>  
> - for (i = 0; i < catalog->intf_count; i++) {
> - if (catalog->intf[i].type == type
> - && catalog->intf[i].controller_id == controller_id) {
> - return catalog->intf[i].id;
> + if (type != INTF_WB) {
> + for (i = 0; i < catalog->intf_count; i++) {
> + if (catalog->intf[i].type == type
> + && catalog->intf[i].controller_id == 
> controller_id) {
> + return catalog->intf[i].id;
> + }
> + }
> + } else {
> + for (i = 0; i < catalog->wb_count; i++) {
> + if (catalog->wb[i].id == controller_id)
> + return catalog->wb[i].id;
>   }
>   }
>  
> @@ -2096,6 +2120,9 @@ static int dpu_encoder_setup_display(struct 
> dpu_encoder_virt *dpu_enc,
>   case DRM_MODE_ENCODER_TMDS:
> 

Re: [Freedreno] [PATCH 10/12] drm/msm/dpu: initialize dpu encoder and connector for writeback

2022-04-14 Thread Abhinav Kumar




On 2/4/2022 2:34 PM, Dmitry Baryshkov wrote:

On 05/02/2022 00:17, Abhinav Kumar wrote:

Initialize dpu encoder and connector for writeback if the
target supports it in the catalog.

Signed-off-by: Abhinav Kumar 
---
  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 37 -
  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 62 
+

  2 files changed, 88 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c

index b51a677..3746432 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2066,7 +2066,7 @@ static void dpu_encoder_early_unregister(struct 
drm_encoder *encoder)

  }
  static int dpu_encoder_virt_add_phys_encs(
-    u32 display_caps,
+    struct msm_display_info *disp_info,
  struct dpu_encoder_virt *dpu_enc,
  struct dpu_enc_phys_init_params *params)
  {
@@ -2085,7 +2085,7 @@ static int dpu_encoder_virt_add_phys_encs(
  return -EINVAL;
  }
-    if (display_caps & MSM_DISPLAY_CAP_VID_MODE) {
+    if (disp_info->capabilities & MSM_DISPLAY_CAP_VID_MODE) {
  enc = dpu_encoder_phys_vid_init(params);
  if (IS_ERR_OR_NULL(enc)) {
@@ -2098,7 +2098,7 @@ static int dpu_encoder_virt_add_phys_encs(
  ++dpu_enc->num_phys_encs;
  }
-    if (display_caps & MSM_DISPLAY_CAP_CMD_MODE) {
+    if (disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) {
  enc = dpu_encoder_phys_cmd_init(params);
  if (IS_ERR_OR_NULL(enc)) {
@@ -2111,6 +2111,19 @@ static int dpu_encoder_virt_add_phys_encs(
  ++dpu_enc->num_phys_encs;
  }
+    if (disp_info->intf_type == DRM_MODE_ENCODER_VIRTUAL) {
+    enc = dpu_encoder_phys_wb_init(params);
+
+    if (IS_ERR_OR_NULL(enc)) {
+    DPU_ERROR_ENC(dpu_enc, "failed to init wb enc: %ld\n",
+    PTR_ERR(enc));
+    return enc == NULL ? -EINVAL : PTR_ERR(enc);
+    }
+
+    dpu_enc->phys_encs[dpu_enc->num_phys_encs] = enc;
+    ++dpu_enc->num_phys_encs;
+    }
+
  if (params->split_role == ENC_ROLE_SLAVE)
  dpu_enc->cur_slave = enc;
  else
@@ -2199,9 +2212,8 @@ static int dpu_encoder_setup_display(struct 
dpu_encoder_virt *dpu_enc,

  }
  if (!ret) {
-    ret = 
dpu_encoder_virt_add_phys_encs(disp_info->capabilities,

- dpu_enc,
- _params);
+    ret = dpu_encoder_virt_add_phys_encs(disp_info,
+    dpu_enc, _params);
  if (ret)
  DPU_ERROR_ENC(dpu_enc, "failed to add phys encs\n");
  }
@@ -2317,11 +2329,14 @@ struct drm_encoder *dpu_encoder_init(struct 
drm_device *dev,

  if (!dpu_enc)
  return ERR_PTR(-ENOMEM);
-    rc = drm_encoder_init(dev, _enc->base, _encoder_funcs,
-    drm_enc_mode, NULL);
-    if (rc) {
-    devm_kfree(dev->dev, dpu_enc);
-    return ERR_PTR(rc);
+    /* this is handled by drm_writeback_connector_init for virtual 
encoder */

+    if (drm_enc_mode != DRM_MODE_ENCODER_VIRTUAL) {
+    rc = drm_encoder_init(dev, _enc->base, _encoder_funcs,
+  drm_enc_mode, NULL);
+    if (rc) {
+    devm_kfree(dev->dev, dpu_enc);
+    return ERR_PTR(rc);
+    }
  }
  drm_encoder_helper_add(_enc->base, _encoder_helper_funcs);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c

index 47fe11a..6327ba9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -1,5 +1,6 @@
  // SPDX-License-Identifier: GPL-2.0-only
  /*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights 
reserved.

   * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
   * Copyright (C) 2013 Red Hat
   * Author: Rob Clark 
@@ -15,6 +16,7 @@
  #include 
  #include 
  #include 
+#include 
  #include "msm_drv.h"
  #include "msm_mmu.h"
@@ -29,6 +31,7 @@
  #include "dpu_kms.h"
  #include "dpu_plane.h"
  #include "dpu_vbif.h"
+#include "dpu_writeback.h"
  #define CREATE_TRACE_POINTS
  #include "dpu_trace.h"
@@ -642,6 +645,56 @@ static int _dpu_kms_initialize_displayport(struct 
drm_device *dev,

  return 0;
  }
+static int _dpu_kms_initialize_writeback(struct drm_device *dev,
+    struct msm_drm_private *priv, struct dpu_kms *dpu_kms)
+{
+    struct drm_encoder *encoder = NULL;
+    struct msm_display_info info;
+    int rc, i;
+    const u32 *wb_formats;
+    int n_formats;
+
+    encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_VIRTUAL);
+    if (IS_ERR(encoder)) {
+    DPU_ERROR("encoder init failed for dsi display\n");
+    return PTR_ERR(encoder);
+    }
+
+    memset(, 0, sizeof(info));
+
+    for (i = 0; i < dpu_kms->catalog->wb_count; i++) {
+    if (dpu_kms->catalog->wb[i].id == WB_2) 

Re: [Freedreno] [PATCH 08/12] drm/msm/dpu: introduce the dpu_encoder_phys_* for writeback

2022-04-14 Thread Abhinav Kumar




On 2/4/2022 3:19 PM, Dmitry Baryshkov wrote:

On 05/02/2022 00:17, Abhinav Kumar wrote:

Introduce the dpu_encoder_phys_* for the writeback interface
to handle writeback specific hardware programming.

Signed-off-by: Abhinav Kumar 


Mostly looks ok, see minor comments bellow.


---
  drivers/gpu/drm/msm/Makefile   |   1 +
  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h   |  36 +-
  .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c    | 813 
+

  3 files changed, 849 insertions(+), 1 deletion(-)
  create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index c43ef35..3abaf84 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -53,6 +53,7 @@ msm-y := \
  disp/dpu1/dpu_encoder.o \
  disp/dpu1/dpu_encoder_phys_cmd.o \
  disp/dpu1/dpu_encoder_phys_vid.o \
+    disp/dpu1/dpu_encoder_phys_wb.o \
  disp/dpu1/dpu_formats.o \
  disp/dpu1/dpu_hw_catalog.o \
  disp/dpu1/dpu_hw_ctl.o \
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h

index 7b3354d..80da0a9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -159,6 +159,7 @@ struct dpu_encoder_phys_ops {
   * @INTR_IDX_PINGPONG: Pingpong done unterrupt for cmd mode panel
   * @INTR_IDX_UNDERRUN: Underrun unterrupt for video and cmd mode panel
   * @INTR_IDX_RDPTR:    Readpointer done unterrupt for cmd mode panel
+ * @INTR_IDX_WB_DONE:  Writeback fone interrupt for virtual connector
   */
  enum dpu_intr_idx {
  INTR_IDX_VSYNC,
@@ -166,6 +167,7 @@ enum dpu_intr_idx {
  INTR_IDX_UNDERRUN,
  INTR_IDX_CTL_START,
  INTR_IDX_RDPTR,
+    INTR_IDX_WB_DONE,
  INTR_IDX_MAX,
  };
@@ -196,7 +198,7 @@ struct dpu_encoder_irq {
   * @hw_ctl:    Hardware interface to the ctl registers
   * @hw_pp:    Hardware interface to the ping pong registers
   * @hw_intf:    Hardware interface to the intf registers
- * @hw_wb: Hardware interface to the wb registers
+ * @hw_wb:    Hardware interface to the wb registers
   * @dpu_kms:    Pointer to the dpu_kms top level
   * @cached_mode:    DRM mode cached at mode_set time, acted on in 
enable

   * @enabled:    Whether the encoder has enabled and running a mode
@@ -250,6 +252,31 @@ static inline int 
dpu_encoder_phys_inc_pending(struct dpu_encoder_phys *phys)

  }
  /**
+ * struct dpu_encoder_phys_wb - sub-class of dpu_encoder_phys to 
handle command

+ *    mode specific operations
+ * @base:    Baseclass physical encoder structure
+ * @wbirq_refcount: Reference count of writeback interrupt
+ * @wb_done_timeout_cnt: number of wb done irq timeout errors
+ * @wb_cfg:  writeback block config to store fb related details
+ * @cdp_cfg: chroma down prefetch block config for wb
+ * @aspace: address space to be used for wb framebuffer
+ * @wb_conn: backpointer to writeback connector
+ * @wb_job: backpointer to current writeback job
+ * @dest:   dpu buffer layout for current writeback output buffer
+ */
+struct dpu_encoder_phys_wb {
+    struct dpu_encoder_phys base;
+    atomic_t wbirq_refcount;
+    int wb_done_timeout_cnt;
+    struct dpu_hw_wb_cfg wb_cfg;
+    struct dpu_hw_wb_cdp_cfg cdp_cfg;


What about moving them to the stack rather storing them in the structure?


Yes cdp_cfg can be moved to the stack. Will do it in the next version.

wb_cfg cannot because for drm_wb, prepare_wb_job has the job's fb 
attributes which are used to setup the wb.


But we commit it only in the encoder_kickoff in 
dpu_encoder_phys_wb_setup_fb().


So its shared across two methods.




+    struct msm_gem_address_space *aspace;
+    struct drm_writeback_connector *wb_conn;
+    struct drm_writeback_job *wb_job;
+    struct dpu_hw_fmt_layout dest;
+};
+
+/**
   * struct dpu_encoder_phys_cmd - sub-class of dpu_encoder_phys to 
handle command

   *    mode specific operations
   * @base:    Baseclass physical encoder structure
@@ -317,6 +344,13 @@ struct dpu_encoder_phys *dpu_encoder_phys_cmd_init(
  struct dpu_enc_phys_init_params *p);
  /**
+ * dpu_encoder_phys_wb_init - initialize writeback encoder
+ * @init:    Pointer to init info structure with initialization params
+ */
+struct dpu_encoder_phys *dpu_encoder_phys_wb_init(
+    struct dpu_enc_phys_init_params *p);
+
+/**
   * dpu_encoder_helper_trigger_start - control start helper function
   *    This helper function may be optionally specified by physical
   *    encoders if they require ctl_start triggering.
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c

new file mode 100644
index 000..783f83e
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
@@ -0,0 +1,813 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022 

Re: [PATCH v2] drm/msm/dp: enhance both connect and disconnect pending_timeout handle

2022-04-14 Thread Kuogee Hsieh



On 4/8/2022 4:59 PM, Dmitry Baryshkov wrote:

On Fri, 8 Apr 2022 at 23:30, Kuogee Hsieh  wrote:


On 4/8/2022 5:27 AM, Dmitry Baryshkov wrote:

On 07/04/2022 00:28, Kuogee Hsieh wrote:

dp_hpd_plug_handle() is responsible for setting up main link and send
uevent to notify user space framework to start video stream. Similarly,
dp_hdp_unplug_handle is responsible to send uevent to notify user space
framework to stop video stream and then tear down main link.
However there are rare cases, such as in the middle of system
suspending,
that uevent could not be delivered to user space framework. Therefore
some kind of recover mechanism armed by timer need to be in place in the
case of user space framework does not respond to uevent.

Hmm, how does userpsace 'respond' to the uevent? The driver should
send hotplug notifications to userspace, but it must not expect any
particular reaction. The userspace might be as simple, as fbdev
emulation, but the driver still should function correctly.

yes, driver is function correctly by setting up main link. but it does
not know which resolution to display.

It send hotplug notification through uevent to framework after main link
is ready.

Framework  is responsible to set up MDP timing engine to start video stream.


However it does not know which

It's of no concern to the driver. It is completely the userspace
problem. After resuming, it should reread available video output
properties. The display could have been changed while the system is
suspended.
 From your description I still do not understand why you need the
'recovery' mechanism.


I mean "recovery" means  dp driver may leave stay at link ready 
mistakenly after dongle unplugged due to missing framework action to 
tear down main link so that next dongle plug in will not work.


Currently it was armed with timeout function and it will fired if 
framework did not call msm_dp_display_disable() after 5 second.


Anyway, we think this approach is not good. therefore it is replaced 
with  below patch.


drm/msm/dp: tear down main link at unplug handle immediately




Re: [PATCH 06/12] drm/msm/dpu: make changes to dpu_encoder to support virtual encoder

2022-04-14 Thread Abhinav Kumar




On 2/4/2022 3:36 PM, Dmitry Baryshkov wrote:

On 05/02/2022 00:17, Abhinav Kumar wrote:

Make changes to dpu_encoder to support virtual encoder needed
to support writeback for dpu.


This patch will change significantly if



Signed-off-by: Abhinav Kumar 
---
  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 57 
+

  1 file changed, 42 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c

index e977c05..947069b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -974,6 +974,7 @@ static void dpu_encoder_virt_mode_set(struct 
drm_encoder *drm_enc,

  struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
  struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC];
  struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_ENC] = { NULL };
+    enum dpu_hw_blk_type blk_type;
  int num_lm, num_ctl, num_pp;
  int i, j;
@@ -1061,20 +1062,36 @@ static void dpu_encoder_virt_mode_set(struct 
drm_encoder *drm_enc,

  phys->hw_pp = dpu_enc->hw_pp[i];
  phys->hw_ctl = to_dpu_hw_ctl(hw_ctl[i]);
+    if (phys->intf_mode == INTF_MODE_WB_LINE)
+    blk_type = DPU_HW_BLK_WB;
+    else
+    blk_type = DPU_HW_BLK_INTF;
+
  num_blk = dpu_rm_get_assigned_resources(_kms->rm,
-    global_state, drm_enc->base.id, DPU_HW_BLK_INTF,
+    global_state, drm_enc->base.id, blk_type,
  hw_blk, ARRAY_SIZE(hw_blk));
-    for (j = 0; j < num_blk; j++) {
-    struct dpu_hw_intf *hw_intf;
-    hw_intf = to_dpu_hw_intf(hw_blk[i]);
-    if (hw_intf->idx == phys->intf_idx)
-    phys->hw_intf = hw_intf;
+    if (blk_type == DPU_HW_BLK_WB) {
+    for (j = 0; j < num_blk; j++) {
+    struct dpu_hw_wb *hw_wb;
+
+    hw_wb = to_dpu_hw_wb(hw_blk[i]);
+    if (hw_wb->idx == phys->intf_idx)
+    phys->hw_wb = hw_wb;
+    }
+    } else {
+    for (j = 0; j < num_blk; j++) {
+    struct dpu_hw_intf *hw_intf;
+
+    hw_intf = to_dpu_hw_intf(hw_blk[i]);
+    if (hw_intf->idx == phys->intf_idx)
+    phys->hw_intf = hw_intf;
+    }
  }


I think that if we sequentially call dpu_rm_get_assigned_resources(.., 
DPU_HW_BLK_INTF, ...) and then dpu_rm_get_assigned_resources(.., 
DPU_HW_BLK_WB, ...), the code would be cleaner.


Or even better get the WB direclty using the provided ID.


Yeah i think you have done something like this for INTF on msm-next.
Will follow that and post in the next version :)




-    if (!phys->hw_intf) {
+    if (!phys->hw_intf && !phys->hw_wb) {
  DPU_ERROR_ENC(dpu_enc,
-  "no intf block assigned at idx: %d\n", i);
+  "no intf or WB block assigned at idx: %d\n", i);
  return;
  }
@@ -1224,15 +1241,22 @@ static void dpu_encoder_virt_disable(struct 
drm_encoder *drm_enc)

  mutex_unlock(_enc->enc_lock);
  }
-static enum dpu_intf dpu_encoder_get_intf(struct dpu_mdss_cfg *catalog,
+static enum dpu_intf dpu_encoder_get_intf_or_wb(struct dpu_mdss_cfg 
*catalog,

  enum dpu_intf_type type, u32 controller_id)
  {
  int i = 0;
-    for (i = 0; i < catalog->intf_count; i++) {
-    if (catalog->intf[i].type == type
-    && catalog->intf[i].controller_id == controller_id) {
-    return catalog->intf[i].id;
+    if (type != INTF_WB) {
+    for (i = 0; i < catalog->intf_count; i++) {
+    if (catalog->intf[i].type == type
+    && catalog->intf[i].controller_id == controller_id) {
+    return catalog->intf[i].id;
+    }
+    }
+    } else {
+    for (i = 0; i < catalog->wb_count; i++) {
+    if (catalog->wb[i].id == controller_id)
+    return catalog->wb[i].id;
  }
  }
@@ -2096,6 +2120,9 @@ static int dpu_encoder_setup_display(struct 
dpu_encoder_virt *dpu_enc,

  case DRM_MODE_ENCODER_TMDS:
  intf_type = INTF_DP;
  break;
+    case DRM_MODE_ENCODER_VIRTUAL:
+    intf_type = INTF_WB;
+    break;
  }
  WARN_ON(disp_info->num_of_h_tiles < 1);
@@ -2128,11 +2155,11 @@ static int dpu_encoder_setup_display(struct 
dpu_encoder_virt *dpu_enc,

  DPU_DEBUG("h_tile_instance %d = %d, split_role %d\n",
  i, controller_id, phys_params.split_role);
-    phys_params.intf_idx = dpu_encoder_get_intf(dpu_kms->catalog,
+    phys_params.intf_idx = 
dpu_encoder_get_intf_or_wb(dpu_kms->catalog,

  intf_type,
  controller_id);
  if (phys_params.intf_idx == INTF_MAX) {
-    DPU_ERROR_ENC(dpu_enc, "could not get intf: type %d, id 
%d\n",
+    DPU_ERROR_ENC(dpu_enc, 

Re: [PATCH 05/12] drm/msm/dpu: add an API to reset the encoder related hw blocks

2022-04-14 Thread Abhinav Kumar




On 2/4/2022 3:46 PM, Dmitry Baryshkov wrote:

On 05/02/2022 00:17, Abhinav Kumar wrote:

Add an API to reset the encoder related hw blocks to ensure
a proper teardown of the pipeline. At the moment this is being
used only for the writeback encoder but eventually we can start
using this for all interfaces.

Signed-off-by: Abhinav Kumar 
---
  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c  | 92 


  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 10 +++
  2 files changed, 102 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c

index 1e648db..e977c05 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1,5 +1,6 @@
  // SPDX-License-Identifier: GPL-2.0-only
  /*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights 
reserved.
   * Copyright (c) 2014-2018, 2020-2021 The Linux Foundation. All 
rights reserved.

   * Copyright (C) 2013 Red Hat
   * Author: Rob Clark 
@@ -21,6 +22,7 @@
  #include "dpu_hw_intf.h"
  #include "dpu_hw_ctl.h"
  #include "dpu_hw_dspp.h"
+#include "dpu_hw_merge3d.h"
  #include "dpu_formats.h"
  #include "dpu_encoder_phys.h"
  #include "dpu_crtc.h"
@@ -1813,6 +1815,96 @@ void dpu_encoder_kickoff(struct drm_encoder 
*drm_enc)

  DPU_ATRACE_END("encoder_kickoff");
  }
+static void dpu_encoder_helper_reset_mixers(struct dpu_encoder_phys 
*phys_enc)

+{
+    struct dpu_hw_mixer_cfg mixer;
+    int i, num_lm;
+    u32 flush_mask = 0;
+    struct dpu_global_state *global_state;
+    struct dpu_hw_blk *hw_lm[2];
+    struct dpu_hw_mixer *hw_mixer[2];
+    struct dpu_hw_ctl *ctl = phys_enc->hw_ctl;
+
+    memset(, 0, sizeof(mixer));
+
+    /* reset all mixers for this encoder */
+    if (phys_enc->hw_ctl->ops.clear_all_blendstages)
+    phys_enc->hw_ctl->ops.clear_all_blendstages(phys_enc->hw_ctl);
+
+    global_state = dpu_kms_get_existing_global_state(phys_enc->dpu_kms);
+
+    num_lm = dpu_rm_get_assigned_resources(_enc->dpu_kms->rm, 
global_state,
+    phys_enc->parent->base.id, DPU_HW_BLK_LM, hw_lm, 
ARRAY_SIZE(hw_lm));

+
+    for (i = 0; i < num_lm; i++) {
+    hw_mixer[i] = to_dpu_hw_mixer(hw_lm[i]);
+    flush_mask = phys_enc->hw_ctl->ops.get_bitmask_mixer(ctl, 
hw_mixer[i]->idx);

+    if (phys_enc->hw_ctl->ops.update_pending_flush)
+    phys_enc->hw_ctl->ops.update_pending_flush(ctl, flush_mask);
+
+    /* clear all blendstages */
+    if (phys_enc->hw_ctl->ops.setup_blendstage)
+    phys_enc->hw_ctl->ops.setup_blendstage(ctl, 
hw_mixer[i]->idx, NULL);

+    }
+}
+
+void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
+{
+    struct dpu_hw_ctl *ctl = phys_enc->hw_ctl;
+    struct dpu_hw_intf_cfg intf_cfg = { 0 };
+    int i;
+    struct dpu_encoder_virt *dpu_enc;
+
+    dpu_enc = to_dpu_encoder_virt(phys_enc->parent);
+
+    phys_enc->hw_ctl->ops.reset(ctl);
+
+    dpu_encoder_helper_reset_mixers(phys_enc);
+
+    if (phys_enc->hw_wb) {
+    /* disable the PP block */
+    if (phys_enc->hw_wb->ops.bind_pingpong_blk)
+    phys_enc->hw_wb->ops.bind_pingpong_blk(phys_enc->hw_wb, 
false,

+    phys_enc->hw_pp->idx);
+
+    /* mark WB flush as pending */
+    if (phys_enc->hw_ctl->ops.update_pending_flush_wb)
+    phys_enc->hw_ctl->ops.update_pending_flush_wb(ctl, 
phys_enc->hw_wb->idx);

+    } else {
+    for (i = 0; i < dpu_enc->num_phys_encs; i++) {
+    if (dpu_enc->phys_encs[i] && 
phys_enc->hw_intf->ops.bind_pingpong_blk)

+    phys_enc->hw_intf->ops.bind_pingpong_blk(
+    dpu_enc->phys_encs[i]->hw_intf, false,
+    dpu_enc->phys_encs[i]->hw_pp->idx);
+    /* mark INTF flush as pending */
+    if (phys_enc->hw_ctl->ops.update_pending_flush_intf)
+
phys_enc->hw_ctl->ops.update_pending_flush_intf(phys_enc->hw_ctl,

+    dpu_enc->phys_encs[i]->hw_intf->idx);
+    }
+    }
+
+    /* reset the merge 3D HW block */
+    if (phys_enc->hw_pp->merge_3d) {
+
phys_enc->hw_pp->merge_3d->ops.setup_3d_mode(phys_enc->hw_pp->merge_3d,

+    BLEND_3D_NONE);
+    if (phys_enc->hw_ctl->ops.update_pending_flush_merge_3d)
+    phys_enc->hw_ctl->ops.update_pending_flush_merge_3d(ctl,
+    phys_enc->hw_pp->merge_3d->idx);
+    }
+
+    intf_cfg.stream_sel = 0; /* Don't care value for video mode */
+    intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc);
+    if (phys_enc->hw_pp->merge_3d)
+    intf_cfg.merge_3d = phys_enc->hw_pp->merge_3d->idx;
+
+    if (ctl->ops.reset_intf_cfg)
+    ctl->ops.reset_intf_cfg(ctl, _cfg, true);
+
+    ctl->ops.trigger_flush(ctl);
+    ctl->ops.trigger_start(ctl);
+    ctl->ops.clear_pending_flush(ctl);
+}
+
  void dpu_encoder_prepare_commit(struct drm_encoder *drm_enc)
  {
  struct dpu_encoder_virt 

[PATCH v5] drm/msm/dp: stop event kernel thread when DP unbind

2022-04-14 Thread Kuogee Hsieh
Current DP driver implementation, event thread is kept running
after DP display is unbind. This patch fix this problem by disabling
DP irq and stop event thread to exit gracefully at dp_display_unbind().

Changes in v2:
-- start event thread at dp_display_bind()

Changes in v3:
-- disable all HDP interrupts at unbind
-- replace dp_hpd_event_setup() with dp_hpd_event_thread_start()
-- replace dp_hpd_event_stop() with dp_hpd_event_thread_stop()
-- move init_waitqueue_head(>event_q) to probe()
-- move spin_lock_init(>event_lock) to probe()

Changes in v4:
-- relocate both dp_display_bind() and dp_display_unbind() to bottom of file

Changes in v5:
-- cancel relocation of both dp_display_bind() and dp_display_unbind()

Fixes: e91e3065a806 ("drm/msm/dp: Add DP compliance tests on Snapdragon 
Chipsets")
Signed-off-by: Kuogee Hsieh 
Reported-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/dp/dp_display.c | 35 ---
 1 file changed, 28 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 01453db..baba95d 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -113,6 +113,7 @@ struct dp_display_private {
u32 hpd_state;
u32 event_pndx;
u32 event_gndx;
+   struct task_struct *ev_tsk;
struct dp_event event_list[DP_EVENT_Q_MAX];
spinlock_t event_lock;
 
@@ -230,6 +231,18 @@ void dp_display_signal_audio_complete(struct msm_dp 
*dp_display)
complete_all(>audio_comp);
 }
 
+
+static void dp_hpd_event_thread_stop(struct dp_display_private *dp_priv)
+{
+   kthread_stop(dp_priv->ev_tsk);
+
+   /* reset event q to empty */
+   dp_priv->event_gndx = 0;
+   dp_priv->event_pndx = 0;
+}
+
+static int dp_hpd_event_thread_start(struct dp_display_private *dp_priv);
+
 static int dp_display_bind(struct device *dev, struct device *master,
   void *data)
 {
@@ -269,6 +282,7 @@ static int dp_display_bind(struct device *dev, struct 
device *master,
if (rc)
DRM_ERROR("Audio registration Dp failed\n");
 
+   rc = dp_hpd_event_thread_start(dp);
 end:
return rc;
 }
@@ -280,6 +294,9 @@ static void dp_display_unbind(struct device *dev, struct 
device *master,
struct drm_device *drm = dev_get_drvdata(master);
struct msm_drm_private *priv = drm->dev_private;
 
+   /* disable all HPD interrupts */
+   dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_INT_MASK, false);
+   dp_hpd_event_thread_stop(dp);
dp_power_client_deinit(dp->power);
dp_aux_unregister(dp->aux);
priv->dp[dp->id] = NULL;
@@ -1054,7 +1071,7 @@ static int hpd_event_thread(void *data)
 
dp_priv = (struct dp_display_private *)data;
 
-   while (1) {
+   while (!kthread_should_stop()) {
if (timeout_mode) {
wait_event_timeout(dp_priv->event_q,
(dp_priv->event_pndx == dp_priv->event_gndx),
@@ -1132,12 +1149,15 @@ static int hpd_event_thread(void *data)
return 0;
 }
 
-static void dp_hpd_event_setup(struct dp_display_private *dp_priv)
+static int dp_hpd_event_thread_start(struct dp_display_private *dp_priv)
 {
-   init_waitqueue_head(_priv->event_q);
-   spin_lock_init(_priv->event_lock);
+   dp_priv->ev_tsk = kthread_run(hpd_event_thread, dp_priv, 
"dp_hpd_handler");
+   if (IS_ERR(dp_priv->ev_tsk)) {
+   DRM_ERROR("failed to create DP event thread\n");
+   return PTR_ERR(dp_priv->ev_tsk);
+   }
 
-   kthread_run(hpd_event_thread, dp_priv, "dp_hpd_handler");
+   return 0;
 }
 
 static irqreturn_t dp_display_irq_handler(int irq, void *dev_id)
@@ -1266,7 +1286,10 @@ static int dp_display_probe(struct platform_device *pdev)
return -EPROBE_DEFER;
}
 
+   /* setup event q */
mutex_init(>event_mutex);
+   init_waitqueue_head(>event_q);
+   spin_lock_init(>event_lock);
 
/* Store DP audio handle inside DP display */
dp->dp_display.dp_audio = dp->audio;
@@ -1441,8 +1464,6 @@ void msm_dp_irq_postinstall(struct msm_dp *dp_display)
 
dp = container_of(dp_display, struct dp_display_private, dp_display);
 
-   dp_hpd_event_setup(dp);
-
dp_add_event(dp, EV_HPD_INIT_SETUP, 0, 100);
 }
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



Re: [PATCH v7 1/4] drm/msm/dp: Add eDP support via aux_bus

2022-04-14 Thread Doug Anderson
Hi,

On Thu, Apr 14, 2022 at 2:16 PM Dmitry Baryshkov
 wrote:
>
> > Hmm, interesting. Probably for DRM_BRIDGE_OP_MODES that will work?
> > It's definitely worth confirming but from my reading of the code it
> > _probably_ wouldn't hurt.
> >
> > One thing someone would want to confirm would be what would happen if
> > we move this code and the panel code to implement DRM_BRIDGE_OP_EDID
> > properly. It looks as if both actually ought to be implementing that
> > instead of DRM_BRIDGE_OP_MODES, at least in some cases. A fix for a
> > future day. Could we get into trouble if one moved before the other?
> > Then the panel would no longer override the eDP controller and the eDP
> > controller would try to read from a possibly unpowered panel?
>
> That would depend on the way the get_edid would be implemented in DP
> driver. Currently the edid is cached via the
> dp_display_process_hpd_high() -> dp_panel_read_sink_caps() call chain.
>
> With this patchset, the dp_hpd_plug_handle() ->
> dp_display_usbpd_configure_cb() -> dp_display_process_hpd_high() will be
> called too late for the get_modes/get_edid (from dp_bridge's enable() op).
>
> There is another issue. drm_panel has only get_modes() callback, so
> panel_bridge can not implement get_edid() unless we extend the panel
> interface (which might be a good idea).

Ah, that makes sense and explains why the current panel code does the
EDID reading in its get_modes() function even though get_modes() is
_documented_ that it doesn't read the EDID. ;-) I guess it's another
of the "let's move some people over to the new way but we'll keep the
old code working". Definitely makes it hard to understand at times.


> > For hotplug/detect I'm even less confident that setting the bits would
> > be harmless. I haven't sat down and traced everything, but from what I
> > can see the panel _doesn't_ set these bits, does it? I believe that
> > the rule is that when every bridge in the chain _doesn't_ implement
> > detect/hotplug that the panel is always present. The moment someone
> > says "hey, I can detect" then it suddenly becomes _not_ always
> > present. Yes, I guess we could have the panel implement "detect" and
> > return true, but I'm not convinced that's actually better...
>
> I think it makes sense to implement OP_DETECT in panel bridge (that
> always returns connector_status_connected) at least to override the
> possible detect ops in previous bridges.

So I truly don't know the right answer, but are you sure that's the
best design? I _think_ that panel_bridge is used for all kinds of
panels, right? So what if there's some type of display that uses a
panel but there's still a mechanism that supports physical detection
of the panel? By implementing "detect" in the generic panel_bridge
then you're _preventing_ anyone higher up in the chain from
implementing it and you're forcing it to be "always connected".

For instance, we could come up with a new display standard called
"pluggable eDP" that is just like eDP except that you can physically
detect it. This imaginary new display standard is different from DP
because it has eDP power sequencing (fully powers the display off when
the screen is off) but it's hot pluggable! It introduces a new pin
that goes to the DP controller called RT-HPD for "really, truly hot
plug detect" that works even when the panel is off. The existing "HPD"
pin continues to mean that the panel is read to communicate. If the
drm_panel hardcodes "always connected" then I can't implement my
"pluggable eDP" system, right? However, if we leave it just like it is
today then my new system would be easy to implement. ;-)

The above example is obviously not truly a real one but I guess my
point is that I find it more intuitive / useful to say that we should
only implement "detect" if we truly think we can detect and that if
nobody says they can detect then we must be always connected.

As an aside; I think in general it's not always easy to fit every
possible graphics system into these "bridge chains" and the simple
sequence of pre-enable, enable, etc, so we have to do our best and
accept the fact that sometimes we'll need special cases. Dave
Stephenson's patches [1] should tell us that, at least.

[1] 
https://lore.kernel.org/all/cover.1646406653.git.dave.steven...@raspberrypi.com/


-Doug


Re: [PATCH 04/12] drm/msm/dpu: add changes to support writeback in hw_ctl

2022-04-14 Thread Abhinav Kumar




On 2/4/2022 2:19 PM, Dmitry Baryshkov wrote:

On 05/02/2022 00:17, Abhinav Kumar wrote:

Add changes to support writeback module in the dpu_hw_ctl
interface. In addition inroduce a reset_intf_cfg op to reset
the interface bits for the currently active interfaces in
the ctl path.

Signed-off-by: Abhinav Kumar 
---
  .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c   |  3 +-
  .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c   |  6 +-
  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 65 
--

  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 27 -
  4 files changed, 91 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c

index 34a6940..4cb72fa 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
@@ -1,5 +1,6 @@
  // SPDX-License-Identifier: GPL-2.0-only
  /*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights 
reserved.
   * Copyright (c) 2015-2018, 2020-2021 The Linux Foundation. All 
rights reserved.

   */
@@ -70,7 +71,7 @@ static void _dpu_encoder_phys_cmd_update_intf_cfg(
  intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_CMD;
  intf_cfg.stream_sel = cmd_enc->stream_sel;
  intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc);
-    ctl->ops.setup_intf_cfg(ctl, _cfg);
+    ctl->ops.setup_intf_cfg(ctl, _cfg, false);
  }
  static void dpu_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c

index ddd9d89..950fcd6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -1,5 +1,7 @@
  // SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2015-2018, 2020-2021 The Linux Foundation. All 
rights reserved.

+/*
+ *  Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights 
reserved.
+ *  Copyright (c) 2015-2018, 2020-2021 The Linux Foundation. All 
rights reserved.

   */
  #define pr_fmt(fmt)    "[drm:%s:%d] " fmt, __func__, __LINE__
@@ -290,7 +292,7 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
  spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
  phys_enc->hw_intf->ops.setup_timing_gen(phys_enc->hw_intf,
  _params, fmt);
-    phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, _cfg);
+    phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, _cfg, 
false);

  /* setup which pp blk will connect to this intf */
  if (phys_enc->hw_intf->ops.bind_pingpong_blk)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c

index 02da9ec..a2069af 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -1,5 +1,6 @@
  // SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights 
reserved.

+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
   */
  #include 
@@ -23,8 +24,10 @@
  #define   CTL_SW_RESET  0x030
  #define   CTL_LAYER_EXTN_OFFSET 0x40
  #define   CTL_MERGE_3D_ACTIVE   0x0E4
+#define   CTL_WB_ACTIVE 0x0EC
  #define   CTL_INTF_ACTIVE   0x0F4
  #define   CTL_MERGE_3D_FLUSH    0x100
+#define   CTL_WB_FLUSH  0x108
  #define   CTL_INTF_FLUSH    0x110
  #define   CTL_INTF_MASTER   0x134
  #define   CTL_FETCH_PIPE_ACTIVE 0x0FC
@@ -35,6 +38,7 @@
  #define DPU_REG_RESET_TIMEOUT_US    2000
  #define  MERGE_3D_IDX   23
  #define  INTF_IDX   31
+#define WB_IDX  16
  #define CTL_INVALID_BIT 0x
  #define CTL_DEFAULT_GROUP_ID    0xf
@@ -128,6 +132,9 @@ static inline void 
dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)

  if (ctx->pending_flush_mask & BIT(INTF_IDX))
  DPU_REG_WRITE(>hw, CTL_INTF_FLUSH,
  ctx->pending_intf_flush_mask);
+    if (ctx->pending_flush_mask & BIT(WB_IDX))
+    DPU_REG_WRITE(>hw, CTL_WB_FLUSH,
+    ctx->pending_wb_flush_mask);
  DPU_REG_WRITE(>hw, CTL_FLUSH, ctx->pending_flush_mask);
  }
@@ -248,6 +255,13 @@ static void 
dpu_hw_ctl_update_pending_flush_intf(struct dpu_hw_ctl *ctx,

  }
  }
+static void dpu_hw_ctl_update_pending_flush_wb_v1(struct dpu_hw_ctl 
*ctx,

+    enum dpu_wb wb)
+{
+    ctx->pending_wb_flush_mask |= BIT(wb - WB_0);
+    ctx->pending_flush_mask |= BIT(WB_IDX);
+}
+
  static void dpu_hw_ctl_update_pending_flush_intf_v1(struct 
dpu_hw_ctl *ctx,

  enum dpu_intf intf)
  {
@@ -493,10 +507,11 @@ static void dpu_hw_ctl_setup_blendstage(struct 
dpu_hw_ctl *ctx,

  static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
-    struct 

Re: [PATCH v5 03/10] drm/hdcp: Update property value on content type and user changes

2022-04-14 Thread Rodrigo Vivi
On Thu, Apr 14, 2022 at 03:58:02PM +, Sean Paul wrote:
> On Tue, Apr 12, 2022 at 09:25:59AM -0400, Rodrigo Vivi wrote:
> > On Mon, Apr 11, 2022 at 08:47:32PM +, Sean Paul wrote:
> > > From: Sean Paul 
> > > 
> > > This patch updates the connector's property value in 2 cases which were
> > > previously missed:
> > > 
> > > 1- Content type changes. The value should revert back to DESIRED from
> > >ENABLED in case the driver must re-authenticate the link due to the
> > >new content type.
> > > 
> > > 2- Userspace sets value to DESIRED while ENABLED. In this case, the
> > >value should be reset immediately to ENABLED since the link is
> > >actively being encrypted.
> > > 
> > > To accommodate these changes, I've split up the conditionals to make
> > > things a bit more clear (as much as one can with this mess of state).
> > > 
> > > Acked-by: Jani Nikula 
> > > Reviewed-by: Abhinav Kumar 
> > > Signed-off-by: Sean Paul 
> > > Link: 
> > > https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-4-s...@poorly.run
> > >  #v1
> > > Link: 
> > > https://patchwork.freedesktop.org/patch/msgid/20210915203834.1439-4-s...@poorly.run
> > >  #v2
> > > Link: 
> > > https://patchwork.freedesktop.org/patch/msgid/20211001151145.55916-4-s...@poorly.run
> > >  #v3
> > > Link: 
> > > https://patchwork.freedesktop.org/patch/msgid/20211105030434.2828845-4-s...@poorly.run
> > >  #v4
> > > 
> > > Changes in v2:
> > > -None
> > > Changes in v3:
> > > -Fixed indentation issue identified by 0-day
> > > Changes in v4:
> > > -None
> > > Changes in v5:
> > > -None
> > > ---
> > >  drivers/gpu/drm/drm_hdcp.c | 26 +-
> > >  1 file changed, 17 insertions(+), 9 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/drm_hdcp.c b/drivers/gpu/drm/drm_hdcp.c
> > > index dd8fa91c51d6..8c851d40cd45 100644
> > > --- a/drivers/gpu/drm/drm_hdcp.c
> > > +++ b/drivers/gpu/drm/drm_hdcp.c
> > > @@ -487,21 +487,29 @@ bool drm_hdcp_atomic_check(struct drm_connector 
> > > *connector,
> > >   return true;
> > >  
> > >   /*
> > > -  * Nothing to do if content type is unchanged and one of:
> > > -  *  - state didn't change
> > > +  * Content type changes require an HDCP disable/enable cycle.
> > > +  */
> > > + if (new_conn_state->hdcp_content_type != 
> > > old_conn_state->hdcp_content_type) {
> > 
> > shouldn't we add some && ( old_hdcp == 
> > DRM_MODE_CONTENT_PROTECTION_ENABLED)) {
> > here?
> 
> Thanks for your reviews Rodrigo.
> 
> I don't think so since the content type is changing the current state of old
> content protection is immaterial (ie: if we need to enable HDCP 2.x, the state
> of HDCP 1.x doesn't really matter), we need to re-evaluate whether the current
> level of HDCP is sufficient.
> 
> Hopefully that makes sense, but I could be missing something :-)

nope, I think I was just missing that the important is the content type change
as you pointed out in the item number 1 in the commit msg.

Reviewed-by: Rodrigo Vivi 


> 
> Sean
> 
> > 
> > > + new_conn_state->content_protection =
> > > + DRM_MODE_CONTENT_PROTECTION_DESIRED;
> > > + return true;
> > > + }
> > > +
> > > + /*
> > > +  * Ignore meaningless state changes:
> > >*  - HDCP was activated since the last commit
> > > -  *  - attempting to set to desired while already enabled
> > > +  *  - Attempting to set to desired while already enabled
> > >*/
> > > - if (old_hdcp == new_hdcp ||
> > > - (old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED &&
> > > + if ((old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED &&
> > >new_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) ||
> > >   (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED &&
> > >new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED)) {
> > > - if (old_conn_state->hdcp_content_type ==
> > > - new_conn_state->hdcp_content_type)
> > > - return false;
> > > + new_conn_state->content_protection =
> > > + DRM_MODE_CONTENT_PROTECTION_ENABLED;
> > > + return false;
> > >   }
> > >  
> > > - return true;
> > > + /* Finally, if state changes, we need action */
> > > + return old_hdcp != new_hdcp;
> > >  }
> > >  EXPORT_SYMBOL(drm_hdcp_atomic_check);
> > > -- 
> > > Sean Paul, Software Engineer, Google / Chromium OS
> > > 
> 
> -- 
> Sean Paul, Software Engineer, Google / Chromium OS


Re: [PATCH 02/12] drm/msm/dpu: add dpu_hw_wb abstraction for writeback blocks

2022-04-14 Thread Dmitry Baryshkov

On 15/04/2022 00:28, Abhinav Kumar wrote:

Hi Dmitry

Thanks for the review.

Finally got back to this series after getting acks on the drm_writeback 
core changes.



On 2/4/2022 2:56 PM, Dmitry Baryshkov wrote:

On 05/02/2022 00:17, Abhinav Kumar wrote:

Add the dpu_hw_wb abstraction to program registers related to the
writeback block. These will be invoked once all the configuration
is set and ready to be programmed to the registers.


Reviewed-by: Dmitry Baryshkov 

Few minor comments bellow.



Signed-off-by: Abhinav Kumar 
---
  drivers/gpu/drm/msm/Makefile  |   1 +
  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c | 267 
++

  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h | 145 
  3 files changed, 413 insertions(+)
  create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
  create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 03ab55c..c43ef35 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -66,6 +66,7 @@ msm-y := \
  disp/dpu1/dpu_hw_top.o \
  disp/dpu1/dpu_hw_util.o \
  disp/dpu1/dpu_hw_vbif.o \
+    disp/dpu1/dpu_hw_wb.o \
  disp/dpu1/dpu_io_util.o \
  disp/dpu1/dpu_kms.o \
  disp/dpu1/dpu_mdss.o \
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c

new file mode 100644
index 000..d395475
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
@@ -0,0 +1,267 @@
+// SPDX-License-Identifier: GPL-2.0-only
+ /*
+  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights 
reserved

+  */
+
+#include "dpu_hw_mdss.h"
+#include "dpu_hwio.h"
+#include "dpu_hw_catalog.h"
+#include "dpu_hw_wb.h"
+#include "dpu_formats.h"
+#include "dpu_kms.h"
+
+#define WB_DST_FORMAT 0x000
+#define WB_DST_OP_MODE    0x004
+#define WB_DST_PACK_PATTERN   0x008
+#define WB_DST0_ADDR  0x00C
+#define WB_DST1_ADDR  0x010
+#define WB_DST2_ADDR  0x014
+#define WB_DST3_ADDR  0x018
+#define WB_DST_YSTRIDE0   0x01C
+#define WB_DST_YSTRIDE1   0x020
+#define WB_DST_YSTRIDE1   0x020
+#define WB_DST_DITHER_BITDEPTH    0x024
+#define WB_DST_MATRIX_ROW0    0x030
+#define WB_DST_MATRIX_ROW1    0x034
+#define WB_DST_MATRIX_ROW2    0x038
+#define WB_DST_MATRIX_ROW3    0x03C
+#define WB_DST_WRITE_CONFIG   0x048
+#define WB_ROTATION_DNSCALER  0x050
+#define WB_ROTATOR_PIPE_DOWNSCALER    0x054
+#define WB_N16_INIT_PHASE_X_C03   0x060
+#define WB_N16_INIT_PHASE_X_C12   0x064
+#define WB_N16_INIT_PHASE_Y_C03   0x068
+#define WB_N16_INIT_PHASE_Y_C12   0x06C
+#define WB_OUT_SIZE   0x074
+#define WB_ALPHA_X_VALUE  0x078
+#define WB_DANGER_LUT 0x084
+#define WB_SAFE_LUT   0x088
+#define WB_QOS_CTRL   0x090
+#define WB_CREQ_LUT_0 0x098
+#define WB_CREQ_LUT_1 0x09C
+#define WB_UBWC_STATIC_CTRL   0x144
+#define WB_MUX    0x150
+#define WB_CROP_CTRL  0x154
+#define WB_CROP_OFFSET    0x158
+#define WB_CSC_BASE   0x260
+#define WB_DST_ADDR_SW_STATUS 0x2B0
+#define WB_CDP_CNTL   0x2B4
+#define WB_OUT_IMAGE_SIZE 0x2C0
+#define WB_OUT_XY 0x2C4
+
+/* WB_QOS_CTRL */
+#define WB_QOS_CTRL_DANGER_SAFE_EN    BIT(0)
+
+static const struct dpu_wb_cfg *_wb_offset(enum dpu_wb wb,
+    const struct dpu_mdss_cfg *m, void __iomem *addr,
+    struct dpu_hw_blk_reg_map *b)
+{
+    int i;
+
+    for (i = 0; i < m->wb_count; i++) {
+    if (wb == m->wb[i].id) {
+    b->base_off = addr;
+    b->blk_off = m->wb[i].base;
+    b->length = m->wb[i].len;
+    b->hwversion = m->hwversion;
+    return >wb[i];
+    }
+    }
+    return ERR_PTR(-EINVAL);
+}
+
+static void dpu_hw_wb_setup_outaddress(struct dpu_hw_wb *ctx,
+    struct dpu_hw_wb_cfg *data)
+{
+    struct dpu_hw_blk_reg_map *c = >hw;
+
+    DPU_REG_WRITE(c, WB_DST0_ADDR, data->dest.plane_addr[0]);
+    DPU_REG_WRITE(c, WB_DST1_ADDR, data->dest.plane_addr[1]);
+    DPU_REG_WRITE(c, WB_DST2_ADDR, data->dest.plane_addr[2]);
+    DPU_REG_WRITE(c, WB_DST3_ADDR, data->dest.plane_addr[3]);
+}
+
+static void dpu_hw_wb_setup_format(struct dpu_hw_wb *ctx,
+    struct dpu_hw_wb_cfg *data)
+{
+    struct dpu_hw_blk_reg_map *c = >hw;
+    const struct dpu_format *fmt = 

[git pull] drm fixes for 5.18-rc3

2022-04-14 Thread Dave Airlie
Hey Linus,

Eggs season holidays are among us, and I think I'd expect some smaller
pulls for 2 weeks then, rc5 having a blow out, as this seems eerily
quiet. One i915 fix, amdgpu has a bunch and msm. I didn't see a misc
pull this week, so I expect that will catch up next week.

Dave.

drm-fixes-2022-04-15:
drm fixes for 5.18-rc3

i915:
- Correct legacy mmap disabling to use GRAPHICS_VER_FULL

msm:
- system suspend fix
- kzalloc return checks
- misc display fix
- iommu_present removal

amdgpu:
- Fix for alpha properly in pre-multiplied mode
- Fix VCN 3.1.2 firmware name
- Suspend/resume fix
- Add a gfxoff quirk for Mac vega20 board
- DCN 3.1.6 spread spectrum fix
The following changes since commit ce522ba9ef7e2d9fb22a39eb3371c0c64e2a433e:

  Linux 5.18-rc2 (2022-04-10 14:21:36 -1000)

are available in the Git repository at:

  git://anongit.freedesktop.org/drm/drm tags/drm-fixes-2022-04-15

for you to fetch changes up to 8e401ff5380a921c309d4c73cacf27b0bdb5f168:

  Merge tag 'amd-drm-fixes-5.18-2022-04-13' of
https://gitlab.freedesktop.org/agd5f/linux into drm-fixes (2022-04-15
07:14:20 +1000)


drm fixes for 5.18-rc3

i915:
- Correct legacy mmap disabling to use GRAPHICS_VER_FULL

msm:
- system suspend fix
- kzalloc return checks
- misc display fix
- iommu_present removal

amdgpu:
- Fix for alpha properly in pre-multiplied mode
- Fix VCN 3.1.2 firmware name
- Suspend/resume fix
- Add a gfxoff quirk for Mac vega20 board
- DCN 3.1.6 spread spectrum fix


Alex Deucher (1):
  drm/amdgpu: fix VCN 3.1.2 firmware name

Charlene Liu (1):
  drm/amd/display: remove dtbclk_ss compensation for dcn316

Dave Airlie (3):
  Merge tag 'drm-intel-fixes-2022-04-13' of
git://anongit.freedesktop.org/drm/drm-intel into drm-fixes
  Merge tag 'drm-msm-fixes-2022-04-13' of
https://gitlab.freedesktop.org/drm/msm into drm-fixes
  Merge tag 'amd-drm-fixes-5.18-2022-04-13' of
https://gitlab.freedesktop.org/agd5f/linux into drm-fixes

Dmitry Baryshkov (1):
  dt-bindings: display/msm: another fix for the dpu-qcm2290 example

Kai-Heng Feng (1):
  drm/amdgpu: Ensure HDA function is suspended before ASIC reset

Kuogee Hsieh (1):
  drm/msm/dp: add fail safe mode outside of event_mutex context

Marijn Suijten (1):
  drm/msm/dpu: Use indexed array initializer to prevent mismatches

Matt Roper (1):
  drm/i915: Sunset igpu legacy mmap support based on GRAPHICS_VER_FULL

Melissa Wen (1):
  drm/amd/display: don't ignore alpha property on pre-multiplied mode

Nathan Chancellor (1):
  drm/msm/gpu: Avoid -Wunused-function with !CONFIG_PM_SLEEP

Rob Clark (5):
  drm/msm/gpu: Rename runtime suspend/resume functions
  drm/msm/gpu: Park scheduler threads for system suspend
  drm/msm/gpu: Remove mutex from wait_event condition
  drm/msm: Add missing put_task_struct() in debugfs path
  drm/msm: Fix range size vs end confusion

Robin Murphy (1):
  drm/msm: Stop using iommu_present()

Stephen Boyd (1):
  drm/msm/dsi: Use connector directly in msm_dsi_manager_connector_init()

Tomasz Moń (1):
  drm/amdgpu: Enable gfxoff quirk on MacBook Pro

Xiaoke Wang (2):
  drm/msm/disp: check the return value of kzalloc()
  drm/msm/mdp5: check the return of kzalloc()

 .../bindings/display/msm/dpu-qcm2290.yaml  |  4 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c| 18 +++--
 drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c|  2 +-
 drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c  |  2 +
 .../amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c|  2 +-
 .../amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c |  4 +-
 drivers/gpu/drm/amd/display/dc/dc.h|  2 +-
 .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c  | 14 ++--
 drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 14 ++--
 drivers/gpu/drm/i915/gem/i915_gem_mman.c   |  2 +-
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c  |  2 +-
 drivers/gpu/drm/msm/adreno/adreno_device.c | 80 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c  | 34 -
 drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c |  3 +
 drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c  |  2 +
 drivers/gpu/drm/msm/dp/dp_display.c|  6 ++
 drivers/gpu/drm/msm/dp/dp_panel.c  | 20 +++---
 drivers/gpu/drm/msm/dp/dp_panel.h  |  1 +
 drivers/gpu/drm/msm/dsi/dsi_manager.c  |  2 +-
 drivers/gpu/drm/msm/msm_drv.c  |  2 +-
 drivers/gpu/drm/msm/msm_gem.c  |  1 +
 21 files changed, 147 insertions(+), 70 deletions(-)


Re: [PATCH v4] drm/msm/dp: stop event kernel thread when DP unbind

2022-04-14 Thread Dmitry Baryshkov

On 15/04/2022 00:26, Kuogee Hsieh wrote:

Current DP driver implementation, event thread is kept running
after DP display is unbind. This patch fix this problem by disabling
DP irq and stop event thread to exit gracefully at dp_display_unbind().

Changes in v2:
-- start event thread at dp_display_bind()

Changes in v3:
-- disable all HDP interrupts at unbind
-- replace dp_hpd_event_setup() with dp_hpd_event_thread_start()
-- replace dp_hpd_event_stop() with dp_hpd_event_thread_stop()
-- move init_waitqueue_head(>event_q) to probe()
-- move spin_lock_init(>event_lock) to probe()

Changes in v4:
-- relocate both dp_display_bind() and dp_display_unbind() to bottom of file


Ugh, no. I think Stephen asked to do it in the followup (= additional) 
patch. Doing it in the same patch squashes unrelated changes and makes 
review harder. The previous one was nearly ideal.




Fixes: e91e3065a806 ("drm/msm/dp: Add DP compliance tests on Snapdragon 
Chipsets")
Signed-off-by: Kuogee Hsieh 
Reported-by: Dmitry Baryshkov 
---
  drivers/gpu/drm/msm/dp/dp_display.c | 345 +++-
  1 file changed, 182 insertions(+), 163 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 01453db..198df6b 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -113,6 +113,7 @@ struct dp_display_private {
u32 hpd_state;
u32 event_pndx;
u32 event_gndx;
+   struct task_struct *ev_tsk;
struct dp_event event_list[DP_EVENT_Q_MAX];
spinlock_t event_lock;
  
@@ -230,65 +231,6 @@ void dp_display_signal_audio_complete(struct msm_dp *dp_display)

complete_all(>audio_comp);
  }
  
-static int dp_display_bind(struct device *dev, struct device *master,

-  void *data)
-{
-   int rc = 0;
-   struct dp_display_private *dp = dev_get_dp_display_private(dev);
-   struct msm_drm_private *priv;
-   struct drm_device *drm;
-
-   drm = dev_get_drvdata(master);
-
-   dp->dp_display.drm_dev = drm;
-   priv = drm->dev_private;
-   priv->dp[dp->id] = >dp_display;
-
-   rc = dp->parser->parse(dp->parser, dp->dp_display.connector_type);
-   if (rc) {
-   DRM_ERROR("device tree parsing failed\n");
-   goto end;
-   }
-
-   dp->dp_display.panel_bridge = dp->parser->panel_bridge;
-
-   dp->aux->drm_dev = drm;
-   rc = dp_aux_register(dp->aux);
-   if (rc) {
-   DRM_ERROR("DRM DP AUX register failed\n");
-   goto end;
-   }
-
-   rc = dp_power_client_init(dp->power);
-   if (rc) {
-   DRM_ERROR("Power client create failed\n");
-   goto end;
-   }
-
-   rc = dp_register_audio_driver(dev, dp->audio);
-   if (rc)
-   DRM_ERROR("Audio registration Dp failed\n");
-
-end:
-   return rc;
-}
-
-static void dp_display_unbind(struct device *dev, struct device *master,
- void *data)
-{
-   struct dp_display_private *dp = dev_get_dp_display_private(dev);
-   struct drm_device *drm = dev_get_drvdata(master);
-   struct msm_drm_private *priv = drm->dev_private;
-
-   dp_power_client_deinit(dp->power);
-   dp_aux_unregister(dp->aux);
-   priv->dp[dp->id] = NULL;
-}
-
-static const struct component_ops dp_display_comp_ops = {
-   .bind = dp_display_bind,
-   .unbind = dp_display_unbind,
-};
  
  static bool dp_display_is_ds_bridge(struct dp_panel *panel)

  {
@@ -1054,7 +996,7 @@ static int hpd_event_thread(void *data)
  
  	dp_priv = (struct dp_display_private *)data;
  
-	while (1) {

+   while (!kthread_should_stop()) {
if (timeout_mode) {
wait_event_timeout(dp_priv->event_q,
(dp_priv->event_pndx == dp_priv->event_gndx),
@@ -1132,14 +1074,6 @@ static int hpd_event_thread(void *data)
return 0;
  }
  
-static void dp_hpd_event_setup(struct dp_display_private *dp_priv)

-{
-   init_waitqueue_head(_priv->event_q);
-   spin_lock_init(_priv->event_lock);
-
-   kthread_run(hpd_event_thread, dp_priv, "dp_hpd_handler");
-}
-
  static irqreturn_t dp_display_irq_handler(int irq, void *dev_id)
  {
struct dp_display_private *dp = dev_id;
@@ -1237,65 +1171,6 @@ static const struct msm_dp_desc 
*dp_display_get_desc(struct platform_device *pde
return NULL;
  }
  
-static int dp_display_probe(struct platform_device *pdev)

-{
-   int rc = 0;
-   struct dp_display_private *dp;
-   const struct msm_dp_desc *desc;
-
-   if (!pdev || !pdev->dev.of_node) {
-   DRM_ERROR("pdev not found\n");
-   return -ENODEV;
-   }
-
-   dp = devm_kzalloc(>dev, sizeof(*dp), GFP_KERNEL);
-   if (!dp)
-   return -ENOMEM;
-
-   desc = dp_display_get_desc(pdev, >id);
-   if (!desc)
-   return -EINVAL;
-
-   

Re: [PATCH 03/12] drm/msm/dpu: add writeback blocks to DPU RM

2022-04-14 Thread Abhinav Kumar




On 2/4/2022 3:43 PM, Dmitry Baryshkov wrote:

On 05/02/2022 00:17, Abhinav Kumar wrote:

Add writeback blocks to DPU resource manager so that
writeback encoders can request for writeback hardware blocks
through RM and their usage can be tracked.

Signed-off-by: Abhinav Kumar 


[please excuse me for the duplicate, I've sent the email without the 
proper distribution list]


We have WB blocks being allocated manually. Could you please consider 
following the ideas from 
https://patchwork.freedesktop.org/patch/470394/?series=99175=1 ?


I think it simplifies the code and shows exact correspondence between WB 
and dpu_encoder.


Yes, will rebase on the latest msm-next which i think already has this 
change and refactor this.





---
  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h |  3 ++
  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |  2 +
  drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c  | 71 
+

  drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h  |  2 +
  4 files changed, 78 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h

index e241914..cc10436 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -1,5 +1,6 @@
  /* SPDX-License-Identifier: GPL-2.0-only */
  /*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights 
reserved.

   * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
   * Copyright (C) 2013 Red Hat
   * Author: Rob Clark 
@@ -21,9 +22,11 @@
  /**
   * Encoder functions and data types
   * @intfs:    Interfaces this encoder is using, INTF_MODE_NONE if 
unused

+ * @wbs:    Writeback blocks this encoder is using
   */
  struct dpu_encoder_hw_resources {
  enum dpu_intf_mode intfs[INTF_MAX];
+    enum dpu_intf_mode wbs[WB_MAX];
  };
  /**
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h

index 2d385b4..1e00804 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -1,5 +1,6 @@
  /* SPDX-License-Identifier: GPL-2.0-only */
  /*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights 
reserved.

   * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
   * Copyright (C) 2013 Red Hat
   * Author: Rob Clark 
@@ -146,6 +147,7 @@ struct dpu_global_state {
  uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
  uint32_t intf_to_enc_id[INTF_MAX - INTF_0];
  uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
+    uint32_t wb_to_enc_id[WB_MAX - WB_0];
  };
  struct dpu_global_state
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c

index f9c83d6..edd0b7a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -1,5 +1,6 @@
  // SPDX-License-Identifier: GPL-2.0-only
  /*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights 
reserved.

   * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
   */
@@ -9,6 +10,7 @@
  #include "dpu_hw_ctl.h"
  #include "dpu_hw_pingpong.h"
  #include "dpu_hw_intf.h"
+#include "dpu_hw_wb.h"
  #include "dpu_hw_dspp.h"
  #include "dpu_hw_merge3d.h"
  #include "dpu_encoder.h"
@@ -75,6 +77,14 @@ int dpu_rm_destroy(struct dpu_rm *rm)
  dpu_hw_intf_destroy(hw);
  }
  }
+    for (i = 0; i < ARRAY_SIZE(rm->wb_blks); i++) {
+    struct dpu_hw_wb *hw;
+
+    if (rm->wb_blks[i]) {
+    hw = to_dpu_hw_wb(rm->wb_blks[i]);
+    dpu_hw_wb_destroy(hw);
+    }
+    }
  return 0;
  }
@@ -187,6 +197,24 @@ int dpu_rm_init(struct dpu_rm *rm,
  rm->intf_blks[intf->id - INTF_0] = >base;
  }
+    for (i = 0; i < cat->wb_count; i++) {
+    struct dpu_hw_wb *hw;
+    const struct dpu_wb_cfg *wb = >wb[i];
+
+    if (wb->id < WB_0 || wb->id >= WB_MAX) {
+    DPU_ERROR("skip intf %d with invalid id\n", wb->id);
+    continue;
+    }
+
+    hw = dpu_hw_wb_init(wb->id, mmio, cat);
+    if (IS_ERR_OR_NULL(hw)) {
+    rc = PTR_ERR(hw);
+    DPU_ERROR("failed wb object creation: err %d\n", rc);
+    goto fail;
+    }
+    rm->wb_blks[wb->id - WB_0] = >base;
+    }
+
  for (i = 0; i < cat->ctl_count; i++) {
  struct dpu_hw_ctl *hw;
  const struct dpu_ctl_cfg *ctl = >ctl[i];
@@ -479,6 +507,33 @@ static int _dpu_rm_reserve_intf(
  return 0;
  }
+static int _dpu_rm_reserve_wb(
+    struct dpu_rm *rm,
+    struct dpu_global_state *global_state,
+    uint32_t enc_id,
+    uint32_t id)
+{
+    int idx = id - WB_0;
+
+    if (idx < 0 || idx >= ARRAY_SIZE(rm->wb_blks)) {
+    DPU_ERROR("invalid intf id: %d", id);
+    return -EINVAL;
+    }
+
+    if (!rm->wb_blks[idx]) {
+    DPU_ERROR("couldn't find wb id %d\n", id);
+    return -EINVAL;
+    }
+
+    if (reserved_by_other(global_state->wb_to_enc_id, idx, enc_id)) {
+   

Re: [PATCH 02/12] drm/msm/dpu: add dpu_hw_wb abstraction for writeback blocks

2022-04-14 Thread Abhinav Kumar

Hi Dmitry

Thanks for the review.

Finally got back to this series after getting acks on the drm_writeback 
core changes.



On 2/4/2022 2:56 PM, Dmitry Baryshkov wrote:

On 05/02/2022 00:17, Abhinav Kumar wrote:

Add the dpu_hw_wb abstraction to program registers related to the
writeback block. These will be invoked once all the configuration
is set and ready to be programmed to the registers.


Reviewed-by: Dmitry Baryshkov 

Few minor comments bellow.



Signed-off-by: Abhinav Kumar 
---
  drivers/gpu/drm/msm/Makefile  |   1 +
  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c | 267 
++

  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h | 145 
  3 files changed, 413 insertions(+)
  create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
  create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 03ab55c..c43ef35 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -66,6 +66,7 @@ msm-y := \
  disp/dpu1/dpu_hw_top.o \
  disp/dpu1/dpu_hw_util.o \
  disp/dpu1/dpu_hw_vbif.o \
+    disp/dpu1/dpu_hw_wb.o \
  disp/dpu1/dpu_io_util.o \
  disp/dpu1/dpu_kms.o \
  disp/dpu1/dpu_mdss.o \
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c

new file mode 100644
index 000..d395475
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
@@ -0,0 +1,267 @@
+// SPDX-License-Identifier: GPL-2.0-only
+ /*
+  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights 
reserved

+  */
+
+#include "dpu_hw_mdss.h"
+#include "dpu_hwio.h"
+#include "dpu_hw_catalog.h"
+#include "dpu_hw_wb.h"
+#include "dpu_formats.h"
+#include "dpu_kms.h"
+
+#define WB_DST_FORMAT 0x000
+#define WB_DST_OP_MODE    0x004
+#define WB_DST_PACK_PATTERN   0x008
+#define WB_DST0_ADDR  0x00C
+#define WB_DST1_ADDR  0x010
+#define WB_DST2_ADDR  0x014
+#define WB_DST3_ADDR  0x018
+#define WB_DST_YSTRIDE0   0x01C
+#define WB_DST_YSTRIDE1   0x020
+#define WB_DST_YSTRIDE1   0x020
+#define WB_DST_DITHER_BITDEPTH    0x024
+#define WB_DST_MATRIX_ROW0    0x030
+#define WB_DST_MATRIX_ROW1    0x034
+#define WB_DST_MATRIX_ROW2    0x038
+#define WB_DST_MATRIX_ROW3    0x03C
+#define WB_DST_WRITE_CONFIG   0x048
+#define WB_ROTATION_DNSCALER  0x050
+#define WB_ROTATOR_PIPE_DOWNSCALER    0x054
+#define WB_N16_INIT_PHASE_X_C03   0x060
+#define WB_N16_INIT_PHASE_X_C12   0x064
+#define WB_N16_INIT_PHASE_Y_C03   0x068
+#define WB_N16_INIT_PHASE_Y_C12   0x06C
+#define WB_OUT_SIZE   0x074
+#define WB_ALPHA_X_VALUE  0x078
+#define WB_DANGER_LUT 0x084
+#define WB_SAFE_LUT   0x088
+#define WB_QOS_CTRL   0x090
+#define WB_CREQ_LUT_0 0x098
+#define WB_CREQ_LUT_1 0x09C
+#define WB_UBWC_STATIC_CTRL   0x144
+#define WB_MUX    0x150
+#define WB_CROP_CTRL  0x154
+#define WB_CROP_OFFSET    0x158
+#define WB_CSC_BASE   0x260
+#define WB_DST_ADDR_SW_STATUS 0x2B0
+#define WB_CDP_CNTL   0x2B4
+#define WB_OUT_IMAGE_SIZE 0x2C0
+#define WB_OUT_XY 0x2C4
+
+/* WB_QOS_CTRL */
+#define WB_QOS_CTRL_DANGER_SAFE_EN    BIT(0)
+
+static const struct dpu_wb_cfg *_wb_offset(enum dpu_wb wb,
+    const struct dpu_mdss_cfg *m, void __iomem *addr,
+    struct dpu_hw_blk_reg_map *b)
+{
+    int i;
+
+    for (i = 0; i < m->wb_count; i++) {
+    if (wb == m->wb[i].id) {
+    b->base_off = addr;
+    b->blk_off = m->wb[i].base;
+    b->length = m->wb[i].len;
+    b->hwversion = m->hwversion;
+    return >wb[i];
+    }
+    }
+    return ERR_PTR(-EINVAL);
+}
+
+static void dpu_hw_wb_setup_outaddress(struct dpu_hw_wb *ctx,
+    struct dpu_hw_wb_cfg *data)
+{
+    struct dpu_hw_blk_reg_map *c = >hw;
+
+    DPU_REG_WRITE(c, WB_DST0_ADDR, data->dest.plane_addr[0]);
+    DPU_REG_WRITE(c, WB_DST1_ADDR, data->dest.plane_addr[1]);
+    DPU_REG_WRITE(c, WB_DST2_ADDR, data->dest.plane_addr[2]);
+    DPU_REG_WRITE(c, WB_DST3_ADDR, data->dest.plane_addr[3]);
+}
+
+static void dpu_hw_wb_setup_format(struct dpu_hw_wb *ctx,
+    struct dpu_hw_wb_cfg *data)
+{
+    struct dpu_hw_blk_reg_map *c = >hw;
+    const struct dpu_format *fmt = data->dest.format;
+    u32 dst_format, pattern, 

[PATCH v4] drm/msm/dp: stop event kernel thread when DP unbind

2022-04-14 Thread Kuogee Hsieh
Current DP driver implementation, event thread is kept running
after DP display is unbind. This patch fix this problem by disabling
DP irq and stop event thread to exit gracefully at dp_display_unbind().

Changes in v2:
-- start event thread at dp_display_bind()

Changes in v3:
-- disable all HDP interrupts at unbind
-- replace dp_hpd_event_setup() with dp_hpd_event_thread_start()
-- replace dp_hpd_event_stop() with dp_hpd_event_thread_stop()
-- move init_waitqueue_head(>event_q) to probe()
-- move spin_lock_init(>event_lock) to probe()

Changes in v4:
-- relocate both dp_display_bind() and dp_display_unbind() to bottom of file

Fixes: e91e3065a806 ("drm/msm/dp: Add DP compliance tests on Snapdragon 
Chipsets")
Signed-off-by: Kuogee Hsieh 
Reported-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/dp/dp_display.c | 345 +++-
 1 file changed, 182 insertions(+), 163 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 01453db..198df6b 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -113,6 +113,7 @@ struct dp_display_private {
u32 hpd_state;
u32 event_pndx;
u32 event_gndx;
+   struct task_struct *ev_tsk;
struct dp_event event_list[DP_EVENT_Q_MAX];
spinlock_t event_lock;
 
@@ -230,65 +231,6 @@ void dp_display_signal_audio_complete(struct msm_dp 
*dp_display)
complete_all(>audio_comp);
 }
 
-static int dp_display_bind(struct device *dev, struct device *master,
-  void *data)
-{
-   int rc = 0;
-   struct dp_display_private *dp = dev_get_dp_display_private(dev);
-   struct msm_drm_private *priv;
-   struct drm_device *drm;
-
-   drm = dev_get_drvdata(master);
-
-   dp->dp_display.drm_dev = drm;
-   priv = drm->dev_private;
-   priv->dp[dp->id] = >dp_display;
-
-   rc = dp->parser->parse(dp->parser, dp->dp_display.connector_type);
-   if (rc) {
-   DRM_ERROR("device tree parsing failed\n");
-   goto end;
-   }
-
-   dp->dp_display.panel_bridge = dp->parser->panel_bridge;
-
-   dp->aux->drm_dev = drm;
-   rc = dp_aux_register(dp->aux);
-   if (rc) {
-   DRM_ERROR("DRM DP AUX register failed\n");
-   goto end;
-   }
-
-   rc = dp_power_client_init(dp->power);
-   if (rc) {
-   DRM_ERROR("Power client create failed\n");
-   goto end;
-   }
-
-   rc = dp_register_audio_driver(dev, dp->audio);
-   if (rc)
-   DRM_ERROR("Audio registration Dp failed\n");
-
-end:
-   return rc;
-}
-
-static void dp_display_unbind(struct device *dev, struct device *master,
- void *data)
-{
-   struct dp_display_private *dp = dev_get_dp_display_private(dev);
-   struct drm_device *drm = dev_get_drvdata(master);
-   struct msm_drm_private *priv = drm->dev_private;
-
-   dp_power_client_deinit(dp->power);
-   dp_aux_unregister(dp->aux);
-   priv->dp[dp->id] = NULL;
-}
-
-static const struct component_ops dp_display_comp_ops = {
-   .bind = dp_display_bind,
-   .unbind = dp_display_unbind,
-};
 
 static bool dp_display_is_ds_bridge(struct dp_panel *panel)
 {
@@ -1054,7 +996,7 @@ static int hpd_event_thread(void *data)
 
dp_priv = (struct dp_display_private *)data;
 
-   while (1) {
+   while (!kthread_should_stop()) {
if (timeout_mode) {
wait_event_timeout(dp_priv->event_q,
(dp_priv->event_pndx == dp_priv->event_gndx),
@@ -1132,14 +1074,6 @@ static int hpd_event_thread(void *data)
return 0;
 }
 
-static void dp_hpd_event_setup(struct dp_display_private *dp_priv)
-{
-   init_waitqueue_head(_priv->event_q);
-   spin_lock_init(_priv->event_lock);
-
-   kthread_run(hpd_event_thread, dp_priv, "dp_hpd_handler");
-}
-
 static irqreturn_t dp_display_irq_handler(int irq, void *dev_id)
 {
struct dp_display_private *dp = dev_id;
@@ -1237,65 +1171,6 @@ static const struct msm_dp_desc 
*dp_display_get_desc(struct platform_device *pde
return NULL;
 }
 
-static int dp_display_probe(struct platform_device *pdev)
-{
-   int rc = 0;
-   struct dp_display_private *dp;
-   const struct msm_dp_desc *desc;
-
-   if (!pdev || !pdev->dev.of_node) {
-   DRM_ERROR("pdev not found\n");
-   return -ENODEV;
-   }
-
-   dp = devm_kzalloc(>dev, sizeof(*dp), GFP_KERNEL);
-   if (!dp)
-   return -ENOMEM;
-
-   desc = dp_display_get_desc(pdev, >id);
-   if (!desc)
-   return -EINVAL;
-
-   dp->pdev = pdev;
-   dp->name = "drm_dp";
-   dp->dp_display.connector_type = desc->connector_type;
-
-   rc = dp_init_sub_modules(dp);
-   if (rc) {
-   DRM_ERROR("init sub module failed\n");
-   return 

Re: [PATCH v4 04/10] drm/msm/gem: Split out inuse helper

2022-04-14 Thread Dmitry Baryshkov

On 12/04/2022 00:58, Rob Clark wrote:

From: Rob Clark 

Prep for a following patch, where it gets a bit more complicated.

Signed-off-by: Rob Clark 


Reviewed-by: Dmitry Baryshkov 


---
  drivers/gpu/drm/msm/msm_gem.c | 2 +-
  drivers/gpu/drm/msm/msm_gem.h | 1 +
  drivers/gpu/drm/msm/msm_gem_vma.c | 9 +++--
  3 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index a4f61972667b..f96d1dc72021 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -938,7 +938,7 @@ void msm_gem_describe(struct drm_gem_object *obj, struct 
seq_file *m,
name, comm ? ":" : "", comm ? comm : "",
vma->aspace, vma->iova,
vma->mapped ? "mapped" : "unmapped",
-   vma->inuse);
+   msm_gem_vma_inuse(vma));
kfree(comm);
}
  
diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h

index 947ff7d9b471..1b7f0f0b88bf 100644
--- a/drivers/gpu/drm/msm/msm_gem.h
+++ b/drivers/gpu/drm/msm/msm_gem.h
@@ -61,6 +61,7 @@ struct msm_gem_vma {
  int msm_gem_init_vma(struct msm_gem_address_space *aspace,
struct msm_gem_vma *vma, int npages,
u64 range_start, u64 range_end);
+bool msm_gem_vma_inuse(struct msm_gem_vma *vma);
  void msm_gem_purge_vma(struct msm_gem_address_space *aspace,
struct msm_gem_vma *vma);
  void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c 
b/drivers/gpu/drm/msm/msm_gem_vma.c
index 64906594fc65..dc2ae097805e 100644
--- a/drivers/gpu/drm/msm/msm_gem_vma.c
+++ b/drivers/gpu/drm/msm/msm_gem_vma.c
@@ -37,6 +37,11 @@ msm_gem_address_space_get(struct msm_gem_address_space 
*aspace)
return aspace;
  }
  
+bool msm_gem_vma_inuse(struct msm_gem_vma *vma)

+{
+   return !!vma->inuse;
+}
+
  /* Actually unmap memory for the vma */
  void msm_gem_purge_vma(struct msm_gem_address_space *aspace,
struct msm_gem_vma *vma)
@@ -44,7 +49,7 @@ void msm_gem_purge_vma(struct msm_gem_address_space *aspace,
unsigned size = vma->node.size << PAGE_SHIFT;
  
  	/* Print a message if we try to purge a vma in use */

-   if (GEM_WARN_ON(vma->inuse > 0))
+   if (GEM_WARN_ON(msm_gem_vma_inuse(vma)))
return;
  
  	/* Don't do anything if the memory isn't mapped */

@@ -100,7 +105,7 @@ msm_gem_map_vma(struct msm_gem_address_space *aspace,
  void msm_gem_close_vma(struct msm_gem_address_space *aspace,
struct msm_gem_vma *vma)
  {
-   if (GEM_WARN_ON(vma->inuse > 0 || vma->mapped))
+   if (GEM_WARN_ON(msm_gem_vma_inuse(vma) || vma->mapped))
return;
  
  	spin_lock(>lock);



--
With best wishes
Dmitry


Re: [PATCH v4 03/10] drm/msm/gem: Convert some missed GEM_WARN_ON()s

2022-04-14 Thread Dmitry Baryshkov

On 12/04/2022 00:58, Rob Clark wrote:

From: Rob Clark 

Signed-off-by: Rob Clark 


Reviewed-by: Dmitry Baryshkov 


---
  drivers/gpu/drm/msm/msm_gem_vma.c | 10 +-
  1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c 
b/drivers/gpu/drm/msm/msm_gem_vma.c
index f914ddbaea89..64906594fc65 100644
--- a/drivers/gpu/drm/msm/msm_gem_vma.c
+++ b/drivers/gpu/drm/msm/msm_gem_vma.c
@@ -44,7 +44,7 @@ void msm_gem_purge_vma(struct msm_gem_address_space *aspace,
unsigned size = vma->node.size << PAGE_SHIFT;
  
  	/* Print a message if we try to purge a vma in use */

-   if (WARN_ON(vma->inuse > 0))
+   if (GEM_WARN_ON(vma->inuse > 0))
return;
  
  	/* Don't do anything if the memory isn't mapped */

@@ -61,7 +61,7 @@ void msm_gem_purge_vma(struct msm_gem_address_space *aspace,
  void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
struct msm_gem_vma *vma)
  {
-   if (!WARN_ON(!vma->iova))
+   if (!GEM_WARN_ON(!vma->iova))
vma->inuse--;
  }
  
@@ -73,7 +73,7 @@ msm_gem_map_vma(struct msm_gem_address_space *aspace,

unsigned size = npages << PAGE_SHIFT;
int ret = 0;
  
-	if (WARN_ON(!vma->iova))

+   if (GEM_WARN_ON(!vma->iova))
return -EINVAL;
  
  	/* Increase the usage counter */

@@ -100,7 +100,7 @@ msm_gem_map_vma(struct msm_gem_address_space *aspace,
  void msm_gem_close_vma(struct msm_gem_address_space *aspace,
struct msm_gem_vma *vma)
  {
-   if (WARN_ON(vma->inuse > 0 || vma->mapped))
+   if (GEM_WARN_ON(vma->inuse > 0 || vma->mapped))
return;
  
  	spin_lock(>lock);

@@ -120,7 +120,7 @@ int msm_gem_init_vma(struct msm_gem_address_space *aspace,
  {
int ret;
  
-	if (WARN_ON(vma->iova))

+   if (GEM_WARN_ON(vma->iova))
return -EBUSY;
  
  	spin_lock(>lock);



--
With best wishes
Dmitry


Re: [PATCH v7 1/4] drm/msm/dp: Add eDP support via aux_bus

2022-04-14 Thread Dmitry Baryshkov

On 14/04/2022 23:09, Doug Anderson wrote:

Hi,

On Thu, Apr 14, 2022 at 12:40 PM Stephen Boyd  wrote:


Quoting Dmitry Baryshkov (2022-04-14 12:16:14)


I think it's too verbose and a bit incorrect.


Not sure which part you're asserting is incorrect, but shorter is OK w/ me too.


I was referring to the "If we don't implement the ops..." part. For some 
reason I thought that panel implements detect() callback (and thus the 
DRM will not care because the next bridge takes precedence).


However I was mistaken, please excuse me. Your description was correct 
and I was wrong. The panel bridge doesn't implement callback. Most 
probably I mixed it with the display_connector bridge.


So... your description is more correct.





This is a bit saner:
/*
   * These ops do not make sense for eDP, since they are provided
   * by the panel-bridge corresponding to the attached eDP panel.
   */

My question was whether we really need to disable them for eDP since for
eDP the detect and and get_modes will be overridden anyway.


Hmm, interesting. Probably for DRM_BRIDGE_OP_MODES that will work?
It's definitely worth confirming but from my reading of the code it
_probably_ wouldn't hurt.

One thing someone would want to confirm would be what would happen if
we move this code and the panel code to implement DRM_BRIDGE_OP_EDID
properly. It looks as if both actually ought to be implementing that
instead of DRM_BRIDGE_OP_MODES, at least in some cases. A fix for a
future day. Could we get into trouble if one moved before the other?
Then the panel would no longer override the eDP controller and the eDP
controller would try to read from a possibly unpowered panel?


That would depend on the way the get_edid would be implemented in DP 
driver. Currently the edid is cached via the 
dp_display_process_hpd_high() -> dp_panel_read_sink_caps() call chain.


With this patchset, the dp_hpd_plug_handle() -> 
dp_display_usbpd_configure_cb() -> dp_display_process_hpd_high() will be 
called too late for the get_modes/get_edid (from dp_bridge's enable() op).


There is another issue. drm_panel has only get_modes() callback, so 
panel_bridge can not implement get_edid() unless we extend the panel 
interface (which might be a good idea).




So I guess in the end my preference would be that we know that driving
the EDID read from the controller isn't a great idea for eDP (since we
have no way to ensure that the panel is powered) so why risk it and
set the bit saying we can do it?


Yep.



For hotplug/detect I'm even less confident that setting the bits would
be harmless. I haven't sat down and traced everything, but from what I
can see the panel _doesn't_ set these bits, does it? I believe that
the rule is that when every bridge in the chain _doesn't_ implement
detect/hotplug that the panel is always present. The moment someone
says "hey, I can detect" then it suddenly becomes _not_ always
present. Yes, I guess we could have the panel implement "detect" and
return true, but I'm not convinced that's actually better...


I think it makes sense to implement OP_DETECT in panel bridge (that 
always returns connector_status_connected) at least to override the 
possible detect ops in previous bridges.



And to go further, I'd expect that a bridge should expose the
functionality that it supports, regardless of what is connected down the
chain. Otherwise we won't be able to mix and match bridges because the
code is brittle, making assumptions about what is connected.


 From my point of view the bridge simply doesn't support any of the
three things when we're in eDP mode. Yes, it's the same driver. Yes,
eDP and DP share nearly the same signalling on the wire. Yes, it's
easily possible to make a single controller that supports DP and eDP.
...but the rules around detection and power sequencing are simply
different for the two cases.


I just hope that during refactoring this can be expressed in a more 
natural way.



The controller simply _cannot_ detect
whether the panel is connected in the eDP case and it _must_ assume
that the panel is always connected. Yes, it has an HPD pin. No, that
HPD pin doesn't tell when the panel is present. The panel is always
present. The panel is always present.


Yep, I remember regarding the HPD pin. And I still think that panel-edp 
(and panel bridge) should provide an overriding OP_DETECT.



So, IMO, it is _incorrect_ to say we can support HPD and DETECT if we
know we're in eDP mode.


I see your point. Let's do it this way. Maybe (hopefully) it will become 
more logical during refactoring. Or maybe I'll just tune myself into the 
DP/eDP logic :D


--
With best wishes
Dmitry


[PATCH] drm/msm/dp: tear down main link at unplug handle immediately

2022-04-14 Thread Kuogee Hsieh
Two stages are required to setup up main link to be ready to transmit
video stream.
Stage 1: dp_hpd_plug_handle() perform link training to set up main link
stage 2: user space framework (msm_dp_display_enable()) to enable pixel
clock and transfer main link to video ready state.

At current implementation, when dongle unplugged dp_hdp_unplug_handle()
has to wait until stage 2 completed before it can send link down uevent
to user space framework to disable pixel clock followed by tearing down
main link.  This introduce unnecessary latency if dongle unplugged happen
after stage 1 and before stage 2. It also has possibility leave main link
stay at ready state after dongle unplugged if framework does not response
to link down uevent notification. This will prevent next dongle plug in
from working. This scenario could possibly happen when dongle unplug while
system in the middle of suspending.

This patch allow unplug handle to tear down main link and notify
framework link down immediately if dongle unplugged happen after
stage 1 and before stage 2. With this approach, dp driver is much
more resilient to any different scenarios. Also redundant both
dp_connect_pending_timeout() and dp_disconnect_pending_timeout()
are removed to reduce logic complexity.

Fixes: 8ede2ecc3e5e ("drm/msm/dp: Add DP compliance tests on Snapdragon 
Chipsets")
Signed-off-by: Kuogee Hsieh 
---
 drivers/gpu/drm/msm/dp/dp_ctrl.c|  29 +++
 drivers/gpu/drm/msm/dp/dp_ctrl.h|   1 +
 drivers/gpu/drm/msm/dp/dp_display.c | 101 +++-
 3 files changed, 59 insertions(+), 72 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index 1a13e50..c2d060d 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -1891,6 +1891,35 @@ int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl)
return ret;
 }
 
+int dp_ctrl_off_link(struct dp_ctrl *dp_ctrl)
+{
+   struct dp_ctrl_private *ctrl;
+   struct dp_io *dp_io;
+   struct phy *phy;
+   int ret;
+
+   ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+   dp_io = >parser->io;
+   phy = dp_io->phy;
+
+   dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false);
+
+   ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, false);
+   if (ret) {
+   DRM_ERROR("Failed to disable link clocks. ret=%d\n", ret);
+   }
+
+   DRM_DEBUG_DP("Before, phy=%p init_count=%d power_on=%d\n",
+   phy, phy->init_count, phy->power_count);
+
+   phy_power_off(phy);
+
+   DRM_DEBUG_DP("After, phy=%p init_count=%d power_on=%d\n",
+   phy, phy->init_count, phy->power_count);
+
+   return ret;
+}
+
 int dp_ctrl_off(struct dp_ctrl *dp_ctrl)
 {
struct dp_ctrl_private *ctrl;
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h
index 2433edb..ffafe17 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.h
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h
@@ -22,6 +22,7 @@ struct dp_ctrl {
 int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl);
 int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl);
 int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl);
+int dp_ctrl_off_link(struct dp_ctrl *dp_ctrl);
 int dp_ctrl_off(struct dp_ctrl *dp_ctrl);
 void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl);
 void dp_ctrl_isr(struct dp_ctrl *dp_ctrl);
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 01453db..f5bd8f5 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -57,14 +57,11 @@ enum {
EV_IRQ_HPD_INT,
EV_HPD_UNPLUG_INT,
EV_USER_NOTIFICATION,
-   EV_CONNECT_PENDING_TIMEOUT,
-   EV_DISCONNECT_PENDING_TIMEOUT,
 };
 
 #define EVENT_TIMEOUT  (HZ/10) /* 100ms */
 #define DP_EVENT_Q_MAX 8
 
-#define DP_TIMEOUT_5_SECOND(5000/EVENT_TIMEOUT)
 #define DP_TIMEOUT_NONE0
 
 #define WAIT_FOR_RESUME_TIMEOUT_JIFFIES (HZ / 2)
@@ -430,6 +427,11 @@ static int dp_display_usbpd_configure_cb(struct device 
*dev)
 
 static int dp_display_usbpd_disconnect_cb(struct device *dev)
 {
+   return 0;
+}
+
+static int dp_display_notify_disconnect(struct device *dev)
+{
struct dp_display_private *dp = dev_get_dp_display_private(dev);
 
dp_add_event(dp, EV_USER_NOTIFICATION, false, 0);
@@ -512,7 +514,6 @@ static int dp_hpd_plug_handle(struct dp_display_private 
*dp, u32 data)
 {
struct dp_usbpd *hpd = dp->usbpd;
u32 state;
-   u32 tout = DP_TIMEOUT_5_SECOND;
int ret;
 
if (!hpd)
@@ -539,14 +540,11 @@ static int dp_hpd_plug_handle(struct dp_display_private 
*dp, u32 data)
return 0;
}
 
-   dp->hpd_state = ST_CONNECT_PENDING;
-
ret = dp_display_usbpd_configure_cb(>pdev->dev);
if (ret) {  /* link train failed */
dp->hpd_state = ST_DISCONNECTED;
} else {
-   /* start sentinel checking in case of 

Re: [PATCH 1/1] drm/vkms: check plane_composer->map[0] before using it

2022-04-14 Thread Melissa Wen
On 04/11, Tales Lelo da Aparecida wrote:
> Fix a copypasta error, which resulted in checking repeatedly if the
> primary_composer->map[0] was null, instead of checking each
> plane_composer while composing planes.
> 
> Signed-off-by: Tales Lelo da Aparecida 

Hi Tales,

Nice catch!

I suggest you detail this issue with more information. The caller of
compose_plane() already checks primary_composer->map. In constrast,
plane_composer->map is never verified here before handling.
Also, add the 'Fixes' tag pointing to the commit that introduced this
issue.

Can you send a next version addressing these suggestions and already
adding Andre's reviewed-by tag?

Thanks for your patch.

Melissa

> ---
>  drivers/gpu/drm/vkms/vkms_composer.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/vkms/vkms_composer.c 
> b/drivers/gpu/drm/vkms/vkms_composer.c
> index c6a1036bf2ea..b47ac170108c 100644
> --- a/drivers/gpu/drm/vkms/vkms_composer.c
> +++ b/drivers/gpu/drm/vkms/vkms_composer.c
> @@ -157,7 +157,7 @@ static void compose_plane(struct vkms_composer 
> *primary_composer,
>   void *vaddr;
>   void (*pixel_blend)(const u8 *p_src, u8 *p_dst);
>  
> - if (WARN_ON(iosys_map_is_null(_composer->map[0])))
> + if (WARN_ON(iosys_map_is_null(_composer->map[0])))
>   return;
>  
>   vaddr = plane_composer->map[0].vaddr;
> -- 
> 2.35.1
> 


signature.asc
Description: PGP signature


dim question: How to revert patches?

2022-04-14 Thread Helge Deller
Hello dri-devel & dim users,

I committed this patch to the drm-misc-next branch:

commit d6cd978f7e6b6f6895f8d0c4ce6e5d2c8e979afe
video: fbdev: fbmem: fix pointer reference to null device field

then I noticed that it was fixed already in another branch which led to this 
error:

Merging drm-misc/drm-misc-next... dim:
dim: FAILURE: Could not merge drm-misc/drm-misc-next
dim: See the section "Resolving Conflicts when Rebuilding drm-tip"
dim: in the drm-tip.rst documentation for how to handle this situation.

I fixed it by reverting that patch above with this new commit in the 
drm-misc-next branch:

commit cabfa2bbe617ddf0a0cc4d01f72b584dae4939ad (HEAD -> drm-misc-next, 
drm-misc/for-linux-next, drm-misc/drm-misc-next)
Author: Helge Deller 
Revert "video: fbdev: fbmem: fix pointer reference to null device field"

My question (as "dim" newbie):
Was that the right solution?
Is there a possibility to drop those two patches from the drm-misc-next branch 
before it gets pushed upstream?

TIA,
Helge


Re: [Freedreno] [PATCH v7 0/4] Add support for the eDP panel over aux_bus

2022-04-14 Thread Dmitry Baryshkov

On 14/04/2022 23:19, Abhinav Kumar wrote:



On 4/14/2022 1:03 PM, Dmitry Baryshkov wrote:

On 14/04/2022 23:00, Abhinav Kumar wrote:

Hi Dmitry

On 4/14/2022 12:43 PM, Stephen Boyd wrote:

Quoting Dmitry Baryshkov (2022-04-14 12:20:31)

On 14/04/2022 19:40, Doug Anderson wrote:

Hi,

On Thu, Apr 14, 2022 at 5:19 AM Sankeerth Billakanti
 wrote:


This series adds support for generic eDP panel over aux_bus.

These changes are dependent on the following series:
https://patchwork.kernel.org/project/linux-arm-msm/list/?series=613654=* 



You're basically depending on the last two patches of that series.
What's the plan there? In patchwork they're marked as "Not
Applicable". If they're good to go, maybe we should land them? If 
not,

maybe you should include them (with Dmitry as the author, of course)
at the beginning of your series?


No, please do not resend patches. The patches in question are 
marked as

'Not applicable' as they are really not applicable to Bjorn's tree.
It would be better to point to the correct patchwork:

https://patchwork.freedesktop.org/series/98585/

Note those patches still lack the R-B tag. I can include them anyway,
basing on Sankeerth's Tested-by tag, but the formal R-B would also 
be good.




Can you resend those as not RFC?


Yes, please resend these, I can ack them.

Previously I held off my ack, as kuogee ran into some issues testing 
them which was later concluded to be a mismatch in QC internal trees 
due to different versions of the changes.( another reason why we 
should get these landed ).


Now, that Sankeerth has tested these, if you can remove RFC and post 
them, I can ack the.


Well, you can ack those patches without them being resent. You have 
already added your Reviewed-by to first three patches (which were 
merged during last window).


I thought you might have to rebase them :) that way you could have 
resent the rebased patch with the RFC tag removed.


If you dont, you now have my R-b.


Thank you!

--
With best wishes
Dmitry


Re: [Freedreno] [PATCH v7 0/4] Add support for the eDP panel over aux_bus

2022-04-14 Thread Abhinav Kumar




On 4/14/2022 1:03 PM, Dmitry Baryshkov wrote:

On 14/04/2022 23:00, Abhinav Kumar wrote:

Hi Dmitry

On 4/14/2022 12:43 PM, Stephen Boyd wrote:

Quoting Dmitry Baryshkov (2022-04-14 12:20:31)

On 14/04/2022 19:40, Doug Anderson wrote:

Hi,

On Thu, Apr 14, 2022 at 5:19 AM Sankeerth Billakanti
 wrote:


This series adds support for generic eDP panel over aux_bus.

These changes are dependent on the following series:
https://patchwork.kernel.org/project/linux-arm-msm/list/?series=613654=* 



You're basically depending on the last two patches of that series.
What's the plan there? In patchwork they're marked as "Not
Applicable". If they're good to go, maybe we should land them? If not,
maybe you should include them (with Dmitry as the author, of course)
at the beginning of your series?


No, please do not resend patches. The patches in question are marked as
'Not applicable' as they are really not applicable to Bjorn's tree.
It would be better to point to the correct patchwork:

https://patchwork.freedesktop.org/series/98585/

Note those patches still lack the R-B tag. I can include them anyway,
basing on Sankeerth's Tested-by tag, but the formal R-B would also 
be good.




Can you resend those as not RFC?


Yes, please resend these, I can ack them.

Previously I held off my ack, as kuogee ran into some issues testing 
them which was later concluded to be a mismatch in QC internal trees 
due to different versions of the changes.( another reason why we 
should get these landed ).


Now, that Sankeerth has tested these, if you can remove RFC and post 
them, I can ack the.


Well, you can ack those patches without them being resent. You have 
already added your Reviewed-by to first three patches (which were merged 
during last window).


I thought you might have to rebase them :) that way you could have 
resent the rebased patch with the RFC tag removed.


If you dont, you now have my R-b.

Thanks

Abhinav




Re: [RFC PATCH v2 4/5] drm/msm/dp: replace dp_connector with drm_bridge_connector

2022-04-14 Thread Abhinav Kumar




On 3/16/2022 9:45 AM, Sankeerth Billakanti (QUIC) wrote:

Subject: Re: [RFC PATCH v2 4/5] drm/msm/dp: replace dp_connector with
drm_bridge_connector
Date: Wed, 23 Feb 2022 16:40:56 -0800
From: Kuogee Hsieh 
To: Stephen Boyd , Dmitry Baryshkov

CC: Abhinav Kumar , Bjorn Andersson
, Rob Clark , Sean Paul
, David Airlie , Daniel Vetter
, linux-arm-...@vger.kernel.org, dri-
de...@lists.freedesktop.org, freedr...@lists.freedesktop.org


On 2/23/2022 1:33 PM, Stephen Boyd wrote:

Quoting Kuogee Hsieh (2022-02-23 10:27:26)

On 2/23/2022 10:22 AM, Dmitry Baryshkov wrote:

On 23/02/2022 20:21, Kuogee Hsieh wrote:

In the panel device node.

Can you please share it too?


 {
   edp_power_supply: edp_power {
   compatible = "regulator-fixed";
   regulator-name = "edp_backlight_power";

   regulator-always-on;
   regulator-boot-on;
   };

   edp_backlight: edp_backlight {
   compatible = "pwm-backlight";

   pwms = <_pwm 3 65535>;
   power-supply = <_power_supply>;
   enable-gpio = <_gpios 7 GPIO_ACTIVE_HIGH>;

   pinctrl-names = "default";
   pinctrl-0 = <_pwm_default>;
   };

   edp_panel: edp_panel {
   compatible = "sharp_lq140m1jw46";

Is that supposed to be sharp,lq140m1jw46 with a comma instead of an
underscore?


Stephen,

This is our internal branch which does not have patches up to date yet.

I will cherry-pick newer edp related patches which are under review now to
re test it.


Tested-by: Sankeerth Billakanti 

Reviewed-by: Abhinav Kumar 


Detect returned eDP not connected because the panel power was not on and 
mode_valid was failing because the DP mode_valid is different from eDP


Re: [RFC PATCH v2 5/5] drm/msm/dp: remove extra wrappers and public functions

2022-04-14 Thread Abhinav Kumar




On 3/16/2022 9:31 AM, Sankeerth Billakanti (QUIC) wrote:

Subject: [RFC PATCH v2 5/5] drm/msm/dp: remove extra wrappers and
public functions
Date: Sat, 12 Feb 2022 01:40:06 +0300
From: Dmitry Baryshkov 
To: Bjorn Andersson , Rob Clark
, Sean Paul , Abhinav Kumar
, Kuogee Hsieh 
CC: Stephen Boyd , David Airlie ,
Daniel Vetter , linux-arm-...@vger.kernel.org, dri-
de...@lists.freedesktop.org, freedr...@lists.freedesktop.org

dp_bridge's functions are thin wrappers around the msm_dp_display_*
family. Squash dp_bridge callbacks into respective msm_dp_display
functions, removing the latter functions from public space.

Signed-off-by: Dmitry Baryshkov 



Tested-by: Sankeerth Billakanti 

Reviewed-by: Abhinav Kumar 





---
   drivers/gpu/drm/msm/dp/dp_display.c | 54 +++---
   drivers/gpu/drm/msm/dp/dp_display.h |  1 -
   drivers/gpu/drm/msm/dp/dp_drm.c | 72 ++---
   drivers/gpu/drm/msm/dp/dp_drm.h | 22 -
   drivers/gpu/drm/msm/msm_drv.h   | 31 -
   5 files changed, 60 insertions(+), 120 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c
b/drivers/gpu/drm/msm/dp/dp_display.c
index 59e5e5b8e5b4..a9b641a68bff 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -10,7 +10,6 @@
   #include 
   #include 
   #include 
-#include 
#include "msm_drv.h"
   #include "msm_kms.h"
@@ -945,18 +944,36 @@ int dp_display_set_plugged_cb(struct msm_dp
*dp_display,
   return 0;
   }
   -int dp_display_validate_mode(struct msm_dp *dp, u32 mode_pclk_khz)
+/**
+ * dp_bridge_mode_valid - callback to determine if specified mode is
+valid
+ * @bridge: Pointer to drm bridge structure
+ * @info: display info
+ * @mode: Pointer to drm mode structure
+ * Returns: Validity status for specified mode  */ enum drm_mode_status
+dp_bridge_mode_valid(struct drm_bridge *bridge,
+   const struct drm_display_info *info,
+   const struct drm_display_mode
*mode)
   {
   const u32 num_components = 3, default_bpp = 24;
   struct dp_display_private *dp_display;
   struct dp_link_info *link_info;
   u32 mode_rate_khz = 0, supported_rate_khz = 0, mode_bpp = 0;
+ struct msm_dp *dp;
+ int mode_pclk_khz = mode->clock;
+
+ dp = to_dp_bridge(bridge)->dp_display;
   if (!dp || !mode_pclk_khz || !dp->connector) {
   DRM_ERROR("invalid params\n");
   return -EINVAL;
   }
   +   if ((dp->max_pclk_khz <= 0) ||
+ (dp->max_pclk_khz > DP_MAX_PIXEL_CLK_KHZ) ||
+ (mode->clock > dp->max_pclk_khz))
+ return MODE_BAD;
+
   dp_display = container_of(dp, struct dp_display_private,
dp_display);
   link_info = _display->panel->link_info;
   @@ -1501,7 +1518,7 @@ int msm_dp_modeset_init(struct msm_dp
*dp_display, struct drm_device *dev,
   dp_display->encoder = encoder;
   -   dp_display->bridge = msm_dp_bridge_init(dp_display, dev,
encoder);
+ dp_display->bridge = dp_bridge_init(dp_display, dev, encoder);
   if (IS_ERR(dp_display->bridge)) {
   ret = PTR_ERR(dp_display->bridge);
   DRM_DEV_ERROR(dev->dev,
@@ -1528,8 +1545,10 @@ int msm_dp_modeset_init(struct msm_dp
*dp_display, struct drm_device *dev,
   return 0;
   }
   -int msm_dp_display_enable(struct msm_dp *dp, struct drm_encoder
*encoder)
+void dp_bridge_enable(struct drm_bridge *drm_bridge)
   {
+ struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge);
+ struct msm_dp *dp = dp_bridge->dp_display;
   int rc = 0;
   struct dp_display_private *dp_display;
   u32 state;
@@ -1537,7 +1556,7 @@ int msm_dp_display_enable(struct msm_dp *dp,
struct drm_encoder *encoder)
   dp_display = container_of(dp, struct dp_display_private,
dp_display);
   if (!dp_display->dp_mode.drm_mode.clock) {
   DRM_ERROR("invalid params\n");
- return -EINVAL;
+ return;
   }
   mutex_lock(_display->event_mutex);
@@ -1549,14 +1568,14 @@ int msm_dp_display_enable(struct msm_dp *dp,
struct drm_encoder *encoder)
   if (rc) {
   DRM_ERROR("Failed to perform a mode set, rc=%d\n", rc);
   mutex_unlock(_display->event_mutex);
- return rc;
+ return;
   }
   rc = dp_display_prepare(dp);
   if (rc) {
   DRM_ERROR("DP display prepare failed, rc=%d\n", rc);
   mutex_unlock(_display->event_mutex);
- return rc;
+ return;
   }
   state =  dp_display->hpd_state;
@@ -1581,23 +1600,23 @@ int msm_dp_display_enable(struct msm_dp *dp,
struct drm_encoder *encoder)
   dp_display->hpd_state = ST_CONNECTED;
   mutex_unlock(_display->event_mutex);
-
- return rc;
   }
   -int msm_dp_display_pre_disable(struct msm_dp *dp, struct drm_encoder
*encoder)
+void dp_bridge_disable(struct drm_bridge *drm_bridge)
   {
+ 

Re: [PATCH v7 1/4] drm/msm/dp: Add eDP support via aux_bus

2022-04-14 Thread Doug Anderson
Hi,

On Thu, Apr 14, 2022 at 12:40 PM Stephen Boyd  wrote:
>
> Quoting Dmitry Baryshkov (2022-04-14 12:16:14)
> >
> > I think it's too verbose and a bit incorrect.

Not sure which part you're asserting is incorrect, but shorter is OK w/ me too.


> > This is a bit saner:
> > /*
> >   * These ops do not make sense for eDP, since they are provided
> >   * by the panel-bridge corresponding to the attached eDP panel.
> >   */
> >
> > My question was whether we really need to disable them for eDP since for
> > eDP the detect and and get_modes will be overridden anyway.

Hmm, interesting. Probably for DRM_BRIDGE_OP_MODES that will work?
It's definitely worth confirming but from my reading of the code it
_probably_ wouldn't hurt.

One thing someone would want to confirm would be what would happen if
we move this code and the panel code to implement DRM_BRIDGE_OP_EDID
properly. It looks as if both actually ought to be implementing that
instead of DRM_BRIDGE_OP_MODES, at least in some cases. A fix for a
future day. Could we get into trouble if one moved before the other?
Then the panel would no longer override the eDP controller and the eDP
controller would try to read from a possibly unpowered panel?

So I guess in the end my preference would be that we know that driving
the EDID read from the controller isn't a great idea for eDP (since we
have no way to ensure that the panel is powered) so why risk it and
set the bit saying we can do it?


For hotplug/detect I'm even less confident that setting the bits would
be harmless. I haven't sat down and traced everything, but from what I
can see the panel _doesn't_ set these bits, does it? I believe that
the rule is that when every bridge in the chain _doesn't_ implement
detect/hotplug that the panel is always present. The moment someone
says "hey, I can detect" then it suddenly becomes _not_ always
present. Yes, I guess we could have the panel implement "detect" and
return true, but I'm not convinced that's actually better...


> And to go further, I'd expect that a bridge should expose the
> functionality that it supports, regardless of what is connected down the
> chain. Otherwise we won't be able to mix and match bridges because the
> code is brittle, making assumptions about what is connected.

>From my point of view the bridge simply doesn't support any of the
three things when we're in eDP mode. Yes, it's the same driver. Yes,
eDP and DP share nearly the same signalling on the wire. Yes, it's
easily possible to make a single controller that supports DP and eDP.
...but the rules around detection and power sequencing are simply
different for the two cases. The controller simply _cannot_ detect
whether the panel is connected in the eDP case and it _must_ assume
that the panel is always connected. Yes, it has an HPD pin. No, that
HPD pin doesn't tell when the panel is present. The panel is always
present. The panel is always present.

So, IMO, it is _incorrect_ to say we can support HPD and DETECT if we
know we're in eDP mode.

-Doug


Re: [PATCH 3/9] vfio/mdev: Pass in a struct vfio_device * to vfio_pin/unpin_pages()

2022-04-14 Thread Eric Farman
On Tue, 2022-04-12 at 12:53 -0300, Jason Gunthorpe wrote:
> Every caller has a readily available vfio_device pointer, use that
> instead
> of passing in a generic struct device. The struct vfio_device already
> contains the group we need so this avoids complexity, extra
> refcountings,
> and a confusing lifecycle model.
> 
> Signed-off-by: Jason Gunthorpe 
> ---
>  .../driver-api/vfio-mediated-device.rst   |  4 +-
>  drivers/s390/cio/vfio_ccw_cp.c|  6 +--
>  drivers/s390/crypto/vfio_ap_ops.c |  8 ++--
>  drivers/vfio/vfio.c   | 40 ++---
> --
>  include/linux/vfio.h  |  4 +-
>  5 files changed, 24 insertions(+), 38 deletions(-)

For the -ccw bits:

Acked-by: Eric Farman 

> 
> diff --git a/Documentation/driver-api/vfio-mediated-device.rst
> b/Documentation/driver-api/vfio-mediated-device.rst
> index 9f26079cacae35..6aeca741dc9be1 100644
> --- a/Documentation/driver-api/vfio-mediated-device.rst
> +++ b/Documentation/driver-api/vfio-mediated-device.rst
> @@ -279,10 +279,10 @@ Translation APIs for Mediated Devices
>  The following APIs are provided for translating user pfn to host pfn
> in a VFIO
>  driver::
>  
> - extern int vfio_pin_pages(struct device *dev, unsigned long
> *user_pfn,
> + extern int vfio_pin_pages(struct vfio_device *vdev, unsigned
> long *user_pfn,
> int npage, int prot, unsigned long
> *phys_pfn);
>  
> - extern int vfio_unpin_pages(struct device *dev, unsigned long
> *user_pfn,
> + extern int vfio_unpin_pages(struct vfio_device *vdev, unsigned
> long *user_pfn,
>   int npage);
>  
>  These functions call back into the back-end IOMMU module by using
> the pin_pages
> diff --git a/drivers/s390/cio/vfio_ccw_cp.c
> b/drivers/s390/cio/vfio_ccw_cp.c
> index af5048a1ba8894..e362cb962a7234 100644
> --- a/drivers/s390/cio/vfio_ccw_cp.c
> +++ b/drivers/s390/cio/vfio_ccw_cp.c
> @@ -103,13 +103,13 @@ static int pfn_array_pin(struct pfn_array *pa,
> struct vfio_device *vdev)
>  {
>   int ret = 0;
>  
> - ret = vfio_pin_pages(vdev->dev, pa->pa_iova_pfn, pa->pa_nr,
> + ret = vfio_pin_pages(vdev, pa->pa_iova_pfn, pa->pa_nr,
>IOMMU_READ | IOMMU_WRITE, pa->pa_pfn);
>  
>   if (ret < 0) {
>   goto err_out;
>   } else if (ret > 0 && ret != pa->pa_nr) {
> - vfio_unpin_pages(vdev->dev, pa->pa_iova_pfn, ret);
> + vfio_unpin_pages(vdev, pa->pa_iova_pfn, ret);
>   ret = -EINVAL;
>   goto err_out;
>   }
> @@ -127,7 +127,7 @@ static void pfn_array_unpin_free(struct pfn_array
> *pa, struct vfio_device *vdev)
>  {
>   /* Only unpin if any pages were pinned to begin with */
>   if (pa->pa_nr)
> - vfio_unpin_pages(vdev->dev, pa->pa_iova_pfn, pa-
> >pa_nr);
> + vfio_unpin_pages(vdev, pa->pa_iova_pfn, pa->pa_nr);
>   pa->pa_nr = 0;
>   kfree(pa->pa_iova_pfn);
>  }
> diff --git a/drivers/s390/crypto/vfio_ap_ops.c
> b/drivers/s390/crypto/vfio_ap_ops.c
> index 69768061cd7bd9..a10b3369d76c41 100644
> --- a/drivers/s390/crypto/vfio_ap_ops.c
> +++ b/drivers/s390/crypto/vfio_ap_ops.c
> @@ -124,7 +124,7 @@ static void vfio_ap_free_aqic_resources(struct
> vfio_ap_queue *q)
>   q->saved_isc = VFIO_AP_ISC_INVALID;
>   }
>   if (q->saved_pfn && !WARN_ON(!q->matrix_mdev)) {
> - vfio_unpin_pages(mdev_dev(q->matrix_mdev->mdev),
> + vfio_unpin_pages(>matrix_mdev->vdev,
>>saved_pfn, 1);
>   q->saved_pfn = 0;
>   }
> @@ -258,7 +258,7 @@ static struct ap_queue_status
> vfio_ap_irq_enable(struct vfio_ap_queue *q,
>   return status;
>   }
>  
> - ret = vfio_pin_pages(mdev_dev(q->matrix_mdev->mdev), _pfn, 1,
> + ret = vfio_pin_pages(>matrix_mdev->vdev, _pfn, 1,
>IOMMU_READ | IOMMU_WRITE, _pfn);
>   switch (ret) {
>   case 1:
> @@ -301,7 +301,7 @@ static struct ap_queue_status
> vfio_ap_irq_enable(struct vfio_ap_queue *q,
>   break;
>   case AP_RESPONSE_OTHERWISE_CHANGED:
>   /* We could not modify IRQ setings: clear new
> configuration */
> - vfio_unpin_pages(mdev_dev(q->matrix_mdev->mdev),
> _pfn, 1);
> + vfio_unpin_pages(>matrix_mdev->vdev, _pfn, 1);
>   kvm_s390_gisc_unregister(kvm, isc);
>   break;
>   default:
> @@ -1250,7 +1250,7 @@ static int vfio_ap_mdev_iommu_notifier(struct
> notifier_block *nb,
>   struct vfio_iommu_type1_dma_unmap *unmap = data;
>   unsigned long g_pfn = unmap->iova >> PAGE_SHIFT;
>  
> - vfio_unpin_pages(mdev_dev(matrix_mdev->mdev), _pfn,
> 1);
> + vfio_unpin_pages(_mdev->vdev, _pfn, 1);
>   return NOTIFY_OK;
>   }
>  
> diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
> index 

Re: [Freedreno] [PATCH v7 0/4] Add support for the eDP panel over aux_bus

2022-04-14 Thread Dmitry Baryshkov

On 14/04/2022 23:00, Abhinav Kumar wrote:

Hi Dmitry

On 4/14/2022 12:43 PM, Stephen Boyd wrote:

Quoting Dmitry Baryshkov (2022-04-14 12:20:31)

On 14/04/2022 19:40, Doug Anderson wrote:

Hi,

On Thu, Apr 14, 2022 at 5:19 AM Sankeerth Billakanti
 wrote:


This series adds support for generic eDP panel over aux_bus.

These changes are dependent on the following series:
https://patchwork.kernel.org/project/linux-arm-msm/list/?series=613654=* 



You're basically depending on the last two patches of that series.
What's the plan there? In patchwork they're marked as "Not
Applicable". If they're good to go, maybe we should land them? If not,
maybe you should include them (with Dmitry as the author, of course)
at the beginning of your series?


No, please do not resend patches. The patches in question are marked as
'Not applicable' as they are really not applicable to Bjorn's tree.
It would be better to point to the correct patchwork:

https://patchwork.freedesktop.org/series/98585/

Note those patches still lack the R-B tag. I can include them anyway,
basing on Sankeerth's Tested-by tag, but the formal R-B would also be 
good.




Can you resend those as not RFC?


Yes, please resend these, I can ack them.

Previously I held off my ack, as kuogee ran into some issues testing 
them which was later concluded to be a mismatch in QC internal trees due 
to different versions of the changes.( another reason why we should get 
these landed ).


Now, that Sankeerth has tested these, if you can remove RFC and post 
them, I can ack the.


Well, you can ack those patches without them being resent. You have 
already added your Reviewed-by to first three patches (which were merged 
during last window).



--
With best wishes
Dmitry


Re: [Freedreno] [PATCH v7 0/4] Add support for the eDP panel over aux_bus

2022-04-14 Thread Abhinav Kumar

Hi Dmitry

On 4/14/2022 12:43 PM, Stephen Boyd wrote:

Quoting Dmitry Baryshkov (2022-04-14 12:20:31)

On 14/04/2022 19:40, Doug Anderson wrote:

Hi,

On Thu, Apr 14, 2022 at 5:19 AM Sankeerth Billakanti
 wrote:


This series adds support for generic eDP panel over aux_bus.

These changes are dependent on the following series:
https://patchwork.kernel.org/project/linux-arm-msm/list/?series=613654=*


You're basically depending on the last two patches of that series.
What's the plan there? In patchwork they're marked as "Not
Applicable". If they're good to go, maybe we should land them? If not,
maybe you should include them (with Dmitry as the author, of course)
at the beginning of your series?


No, please do not resend patches. The patches in question are marked as
'Not applicable' as they are really not applicable to Bjorn's tree.
It would be better to point to the correct patchwork:

https://patchwork.freedesktop.org/series/98585/

Note those patches still lack the R-B tag. I can include them anyway,
basing on Sankeerth's Tested-by tag, but the formal R-B would also be good.



Can you resend those as not RFC?


Yes, please resend these, I can ack them.

Previously I held off my ack, as kuogee ran into some issues testing 
them which was later concluded to be a mismatch in QC internal trees due 
to different versions of the changes.( another reason why we should get 
these landed ).


Now, that Sankeerth has tested these, if you can remove RFC and post 
them, I can ack the.


Thanks

Abhinav


Re: [PATCH v3] drm/msm/dp: stop event kernel thread when DP unbind

2022-04-14 Thread Dmitry Baryshkov

On 14/04/2022 20:25, Kuogee Hsieh wrote:

Current DP driver implementation, event thread is kept running
after DP display is unbind. This patch fix this problem by disabling
DP irq and stop event thread to exit gracefully at dp_display_unbind().

Changes in v2:
-- start event thread at dp_display_bind()

Changes in v3:
-- disable all HDP interrupts at unbind
-- replace dp_hpd_event_setup() with dp_hpd_event_thread_start()
-- replace dp_hpd_event_stop() with dp_hpd_event_thread_stop()
-- move init_waitqueue_head(>event_q) to probe()
-- move spin_lock_init(>event_lock) to probe()

Fixes: e91e3065a806 ("drm/msm/dp: Add DP compliance tests on Snapdragon 
Chipsets")
Signed-off-by: Kuogee Hsieh 
Reported-by: Dmitry Baryshkov 
---
  drivers/gpu/drm/msm/dp/dp_display.c | 42 -
  1 file changed, 32 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 01453db..0b9a96f 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -113,6 +113,7 @@ struct dp_display_private {
u32 hpd_state;
u32 event_pndx;
u32 event_gndx;
+   struct task_struct *ev_tsk;
struct dp_event event_list[DP_EVENT_Q_MAX];
spinlock_t event_lock;
  
@@ -230,6 +231,29 @@ void dp_display_signal_audio_complete(struct msm_dp *dp_display)

complete_all(>audio_comp);
  }
  
+static int hpd_event_thread(void *data);

+
+static int dp_hpd_event_thread_start(struct dp_display_private *dp_priv)
+{
+   int err = 0;
+
+   dp_priv->ev_tsk = kthread_run(hpd_event_thread, dp_priv, 
"dp_hpd_handler");
+   if (IS_ERR(dp_priv->ev_tsk)) {
+   DRM_ERROR("failed to create DP event thread\n");
+   err = PTR_ERR(dp_priv->ev_tsk);
+   }
+   return err;


Generally the preference is for the following style:

if (error) {
   return error;
}

return 0;

It makes it clear that at the end the function succeeds.



+}
+
+static void dp_hpd_event_thread_stop(struct dp_display_private *dp_priv)
+{
+   kthread_stop(dp_priv->ev_tsk);
+
+   /* reset event q to empty */
+   dp_priv->event_gndx = 0;
+   dp_priv->event_pndx = 0;
+}
+
  static int dp_display_bind(struct device *dev, struct device *master,
   void *data)
  {
@@ -269,6 +293,7 @@ static int dp_display_bind(struct device *dev, struct 
device *master,
if (rc)
DRM_ERROR("Audio registration Dp failed\n");


Isn't 'goto end' missing here?

That's why it's suggested not to mix error and success paths.

  
+	rc = dp_hpd_event_thread_start(dp);

  end:
return rc;
  }
@@ -280,6 +305,9 @@ static void dp_display_unbind(struct device *dev, struct 
device *master,
struct drm_device *drm = dev_get_drvdata(master);
struct msm_drm_private *priv = drm->dev_private;
  
+	/* disable all HPD interrupts */

+   dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_INT_MASK, false);


Generic nit: if we had _enable and _disable functions, one wouldn't need 
the comment here. It would be obvious from the code itself.




+   dp_hpd_event_thread_stop(dp);
dp_power_client_deinit(dp->power);
dp_aux_unregister(dp->aux);
priv->dp[dp->id] = NULL;
@@ -1054,7 +1082,7 @@ static int hpd_event_thread(void *data)
  
  	dp_priv = (struct dp_display_private *)data;
  
-	while (1) {

+   while (!kthread_should_stop()) {
if (timeout_mode) {
wait_event_timeout(dp_priv->event_q,
(dp_priv->event_pndx == dp_priv->event_gndx),
@@ -1132,13 +1160,6 @@ static int hpd_event_thread(void *data)
return 0;
  }
  
-static void dp_hpd_event_setup(struct dp_display_private *dp_priv)

-{
-   init_waitqueue_head(_priv->event_q);
-   spin_lock_init(_priv->event_lock);
-
-   kthread_run(hpd_event_thread, dp_priv, "dp_hpd_handler");
-}
  
  static irqreturn_t dp_display_irq_handler(int irq, void *dev_id)

  {
@@ -1266,7 +1287,10 @@ static int dp_display_probe(struct platform_device *pdev)
return -EPROBE_DEFER;
}
  
+	/* setup event q */

mutex_init(>event_mutex);
+   init_waitqueue_head(>event_q);
+   spin_lock_init(>event_lock);
  
  	/* Store DP audio handle inside DP display */

dp->dp_display.dp_audio = dp->audio;
@@ -1441,8 +1465,6 @@ void msm_dp_irq_postinstall(struct msm_dp *dp_display)
  
  	dp = container_of(dp_display, struct dp_display_private, dp_display);
  
-	dp_hpd_event_setup(dp);

-
dp_add_event(dp, EV_HPD_INIT_SETUP, 0, 100);
  }
  



--
With best wishes
Dmitry


Re: [PATCH 2/9] vfio/ccw: Remove mdev from struct channel_program

2022-04-14 Thread Eric Farman
On Tue, 2022-04-12 at 12:53 -0300, Jason Gunthorpe wrote:
> The next patch wants the vfio_device instead. There is no reason to
> store
> a pointer here since we can container_of back to the vfio_device.
> 
> Signed-off-by: Jason Gunthorpe 
> ---
>  drivers/s390/cio/vfio_ccw_cp.c  | 44 +++--
> 
>  drivers/s390/cio/vfio_ccw_cp.h  |  4 +--
>  drivers/s390/cio/vfio_ccw_fsm.c |  3 +--
>  3 files changed, 28 insertions(+), 23 deletions(-)

There's opportunity for simplification here, but I'll handle that when
I get to some other work in this space. For this series, this is fine.

Reviewed-by: Eric Farman 

> 
> diff --git a/drivers/s390/cio/vfio_ccw_cp.c
> b/drivers/s390/cio/vfio_ccw_cp.c
> index 8d1b2771c1aa02..af5048a1ba8894 100644
> --- a/drivers/s390/cio/vfio_ccw_cp.c
> +++ b/drivers/s390/cio/vfio_ccw_cp.c
> @@ -16,6 +16,7 @@
>  #include 
>  
>  #include "vfio_ccw_cp.h"
> +#include "vfio_ccw_private.h"
>  
>  struct pfn_array {
>   /* Starting guest physical I/O address. */
> @@ -98,17 +99,17 @@ static int pfn_array_alloc(struct pfn_array *pa,
> u64 iova, unsigned int len)
>   * If the pin request partially succeeds, or fails completely,
>   * all pages are left unpinned and a negative error value is
> returned.
>   */
> -static int pfn_array_pin(struct pfn_array *pa, struct device *mdev)
> +static int pfn_array_pin(struct pfn_array *pa, struct vfio_device
> *vdev)
>  {
>   int ret = 0;
>  
> - ret = vfio_pin_pages(mdev, pa->pa_iova_pfn, pa->pa_nr,
> + ret = vfio_pin_pages(vdev->dev, pa->pa_iova_pfn, pa->pa_nr,
>IOMMU_READ | IOMMU_WRITE, pa->pa_pfn);
>  
>   if (ret < 0) {
>   goto err_out;
>   } else if (ret > 0 && ret != pa->pa_nr) {
> - vfio_unpin_pages(mdev, pa->pa_iova_pfn, ret);
> + vfio_unpin_pages(vdev->dev, pa->pa_iova_pfn, ret);
>   ret = -EINVAL;
>   goto err_out;
>   }
> @@ -122,11 +123,11 @@ static int pfn_array_pin(struct pfn_array *pa,
> struct device *mdev)
>  }
>  
>  /* Unpin the pages before releasing the memory. */
> -static void pfn_array_unpin_free(struct pfn_array *pa, struct device
> *mdev)
> +static void pfn_array_unpin_free(struct pfn_array *pa, struct
> vfio_device *vdev)
>  {
>   /* Only unpin if any pages were pinned to begin with */
>   if (pa->pa_nr)
> - vfio_unpin_pages(mdev, pa->pa_iova_pfn, pa->pa_nr);
> + vfio_unpin_pages(vdev->dev, pa->pa_iova_pfn, pa-
> >pa_nr);
>   pa->pa_nr = 0;
>   kfree(pa->pa_iova_pfn);
>  }
> @@ -190,7 +191,7 @@ static void convert_ccw0_to_ccw1(struct ccw1
> *source, unsigned long len)
>   * Within the domain (@mdev), copy @n bytes from a guest physical
>   * address (@iova) to a host physical address (@to).
>   */
> -static long copy_from_iova(struct device *mdev,
> +static long copy_from_iova(struct vfio_device *vdev,
>  void *to, u64 iova,
>  unsigned long n)
>  {
> @@ -203,9 +204,9 @@ static long copy_from_iova(struct device *mdev,
>   if (ret < 0)
>   return ret;
>  
> - ret = pfn_array_pin(, mdev);
> + ret = pfn_array_pin(, vdev);
>   if (ret < 0) {
> - pfn_array_unpin_free(, mdev);
> + pfn_array_unpin_free(, vdev);
>   return ret;
>   }
>  
> @@ -226,7 +227,7 @@ static long copy_from_iova(struct device *mdev,
>   break;
>   }
>  
> - pfn_array_unpin_free(, mdev);
> + pfn_array_unpin_free(, vdev);
>  
>   return l;
>  }
> @@ -423,11 +424,13 @@ static int ccwchain_loop_tic(struct ccwchain
> *chain,
>  
>  static int ccwchain_handle_ccw(u32 cda, struct channel_program *cp)
>  {
> + struct vfio_device *vdev =
> + _of(cp, struct vfio_ccw_private, cp)->vdev;
>   struct ccwchain *chain;
>   int len, ret;
>  
>   /* Copy 2K (the most we support today) of possible CCWs */
> - len = copy_from_iova(cp->mdev, cp->guest_cp, cda,
> + len = copy_from_iova(vdev, cp->guest_cp, cda,
>CCWCHAIN_LEN_MAX * sizeof(struct ccw1));
>   if (len)
>   return len;
> @@ -508,6 +511,8 @@ static int ccwchain_fetch_direct(struct ccwchain
> *chain,
>int idx,
>struct channel_program *cp)
>  {
> + struct vfio_device *vdev =
> + _of(cp, struct vfio_ccw_private, cp)->vdev;
>   struct ccw1 *ccw;
>   struct pfn_array *pa;
>   u64 iova;
> @@ -526,7 +531,7 @@ static int ccwchain_fetch_direct(struct ccwchain
> *chain,
>   if (ccw_is_idal(ccw)) {
>   /* Read first IDAW to see if it's 4K-aligned or not. */
>   /* All subsequent IDAws will be 4K-aligned. */
> - ret = copy_from_iova(cp->mdev, , ccw->cda,
> sizeof(iova));
> + ret = copy_from_iova(vdev, , ccw->cda,
> sizeof(iova));
>   if (ret)
>   return 

Re: [PATCH v3] drm/msm/dp: stop event kernel thread when DP unbind

2022-04-14 Thread Stephen Boyd
Quoting Kuogee Hsieh (2022-04-14 10:25:37)
> Current DP driver implementation, event thread is kept running
> after DP display is unbind. This patch fix this problem by disabling
> DP irq and stop event thread to exit gracefully at dp_display_unbind().
>
> Changes in v2:
> -- start event thread at dp_display_bind()
>
> Changes in v3:
> -- disable all HDP interrupts at unbind
> -- replace dp_hpd_event_setup() with dp_hpd_event_thread_start()
> -- replace dp_hpd_event_stop() with dp_hpd_event_thread_stop()
> -- move init_waitqueue_head(>event_q) to probe()
> -- move spin_lock_init(>event_lock) to probe()
>
> Fixes: e91e3065a806 ("drm/msm/dp: Add DP compliance tests on Snapdragon 
> Chipsets")
> Signed-off-by: Kuogee Hsieh 
> Reported-by: Dmitry Baryshkov 
> ---
>  drivers/gpu/drm/msm/dp/dp_display.c | 42 
> -
>  1 file changed, 32 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
> b/drivers/gpu/drm/msm/dp/dp_display.c
> index 01453db..0b9a96f 100644
> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> @@ -230,6 +231,29 @@ void dp_display_signal_audio_complete(struct msm_dp 
> *dp_display)
> complete_all(>audio_comp);
>  }
>
> +static int hpd_event_thread(void *data);
> +
> +static int dp_hpd_event_thread_start(struct dp_display_private *dp_priv)
> +{
> +   int err = 0;

Drop local.

> +
> +   dp_priv->ev_tsk = kthread_run(hpd_event_thread, dp_priv, 
> "dp_hpd_handler");
> +   if (IS_ERR(dp_priv->ev_tsk)) {
> +   DRM_ERROR("failed to create DP event thread\n");
> +   err = PTR_ERR(dp_priv->ev_tsk);

return PTR_ERR(dp_priv->ev_tsk);

> +   }

Newline

> +   return err;

return 0;

> +}
> +
> +static void dp_hpd_event_thread_stop(struct dp_display_private *dp_priv)
> +{
> +   kthread_stop(dp_priv->ev_tsk);
> +
> +   /* reset event q to empty */
> +   dp_priv->event_gndx = 0;
> +   dp_priv->event_pndx = 0;
> +}
> +
>  static int dp_display_bind(struct device *dev, struct device *master,
>void *data)
>  {
> @@ -269,6 +293,7 @@ static int dp_display_bind(struct device *dev, struct 
> device *master,
> if (rc)
> DRM_ERROR("Audio registration Dp failed\n");
>
> +   rc = dp_hpd_event_thread_start(dp);

Forward declare this new function?

>  end:
> return rc;
>  }
> @@ -280,6 +305,9 @@ static void dp_display_unbind(struct device *dev, struct 
> device *master,
> struct drm_device *drm = dev_get_drvdata(master);
> struct msm_drm_private *priv = drm->dev_private;
>
> +   /* disable all HPD interrupts */
> +   dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_INT_MASK, false);
> +   dp_hpd_event_thread_stop(dp);
> dp_power_client_deinit(dp->power);
> dp_aux_unregister(dp->aux);
> priv->dp[dp->id] = NULL;
> @@ -1054,7 +1082,7 @@ static int hpd_event_thread(void *data)
>
> dp_priv = (struct dp_display_private *)data;
>
> -   while (1) {
> +   while (!kthread_should_stop()) {
> if (timeout_mode) {
> wait_event_timeout(dp_priv->event_q,
> (dp_priv->event_pndx == dp_priv->event_gndx),
> @@ -1132,13 +1160,6 @@ static int hpd_event_thread(void *data)
> return 0;
>  }
>
> -static void dp_hpd_event_setup(struct dp_display_private *dp_priv)
> -{
> -   init_waitqueue_head(_priv->event_q);
> -   spin_lock_init(_priv->event_lock);
> -
> -   kthread_run(hpd_event_thread, dp_priv, "dp_hpd_handler");
> -}

And then dp_hpd_event_thread_start() be defined here? The bind/unbind
functions should be moved to the bottom of this file because they're
probe/remove basically. Please do that in a followup patch.

>
>  static irqreturn_t dp_display_irq_handler(int irq, void *dev_id)
>  {


Re: [PATCH v7 0/4] Add support for the eDP panel over aux_bus

2022-04-14 Thread Stephen Boyd
Quoting Dmitry Baryshkov (2022-04-14 12:20:31)
> On 14/04/2022 19:40, Doug Anderson wrote:
> > Hi,
> >
> > On Thu, Apr 14, 2022 at 5:19 AM Sankeerth Billakanti
> >  wrote:
> >>
> >> This series adds support for generic eDP panel over aux_bus.
> >>
> >> These changes are dependent on the following series:
> >> https://patchwork.kernel.org/project/linux-arm-msm/list/?series=613654=*
> >
> > You're basically depending on the last two patches of that series.
> > What's the plan there? In patchwork they're marked as "Not
> > Applicable". If they're good to go, maybe we should land them? If not,
> > maybe you should include them (with Dmitry as the author, of course)
> > at the beginning of your series?
>
> No, please do not resend patches. The patches in question are marked as
> 'Not applicable' as they are really not applicable to Bjorn's tree.
> It would be better to point to the correct patchwork:
>
> https://patchwork.freedesktop.org/series/98585/
>
> Note those patches still lack the R-B tag. I can include them anyway,
> basing on Sankeerth's Tested-by tag, but the formal R-B would also be good.
>

Can you resend those as not RFC?


Re: [PATCH 1/9] vfio: Make vfio_(un)register_notifier accept a vfio_device

2022-04-14 Thread Eric Farman
On Tue, 2022-04-12 at 12:53 -0300, Jason Gunthorpe wrote:
> All callers have a struct vfio_device trivially available, pass it in
> directly and avoid calling the expensive vfio_group_get_from_dev().
> 
> To support the unconverted kvmgt mdev driver add
> mdev_legacy_get_vfio_device() which will return the vfio_device
> pointer
> vfio_mdev.c puts in the drv_data.
> 
> Signed-off-by: Jason Gunthorpe 
> ---
>  drivers/gpu/drm/i915/gvt/kvmgt.c  | 15 +--
>  drivers/s390/cio/vfio_ccw_ops.c   |  7 +++
>  drivers/s390/crypto/vfio_ap_ops.c | 14 +++---
>  drivers/vfio/mdev/vfio_mdev.c | 12 
>  drivers/vfio/vfio.c   | 25 +++--
>  include/linux/mdev.h  |  1 +
>  include/linux/vfio.h  |  4 ++--
>  7 files changed, 41 insertions(+), 37 deletions(-)

For the -ccw bits:

Acked-by: Eric Farman 

> 
> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c
> b/drivers/gpu/drm/i915/gvt/kvmgt.c
> index 057ec449010458..bb59d21cf898ab 100644
> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> @@ -904,6 +904,7 @@ static int intel_vgpu_group_notifier(struct
> notifier_block *nb,
>  
>  static int intel_vgpu_open_device(struct mdev_device *mdev)
>  {
> + struct vfio_device *vfio_dev =
> mdev_legacy_get_vfio_device(mdev);
>   struct intel_vgpu *vgpu = mdev_get_drvdata(mdev);
>   struct kvmgt_vdev *vdev = kvmgt_vdev(vgpu);
>   unsigned long events;
> @@ -914,7 +915,7 @@ static int intel_vgpu_open_device(struct
> mdev_device *mdev)
>   vdev->group_notifier.notifier_call = intel_vgpu_group_notifier;
>  
>   events = VFIO_IOMMU_NOTIFY_DMA_UNMAP;
> - ret = vfio_register_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY,
> ,
> + ret = vfio_register_notifier(vfio_dev, VFIO_IOMMU_NOTIFY,
> ,
>   >iommu_notifier);
>   if (ret != 0) {
>   gvt_vgpu_err("vfio_register_notifier for iommu failed:
> %d\n",
> @@ -923,7 +924,7 @@ static int intel_vgpu_open_device(struct
> mdev_device *mdev)
>   }
>  
>   events = VFIO_GROUP_NOTIFY_SET_KVM;
> - ret = vfio_register_notifier(mdev_dev(mdev), VFIO_GROUP_NOTIFY,
> ,
> + ret = vfio_register_notifier(vfio_dev, VFIO_GROUP_NOTIFY,
> ,
>   >group_notifier);
>   if (ret != 0) {
>   gvt_vgpu_err("vfio_register_notifier for group failed:
> %d\n",
> @@ -961,11 +962,11 @@ static int intel_vgpu_open_device(struct
> mdev_device *mdev)
>   vdev->vfio_group = NULL;
>  
>  undo_register:
> - vfio_unregister_notifier(mdev_dev(mdev), VFIO_GROUP_NOTIFY,
> + vfio_unregister_notifier(vfio_dev, VFIO_GROUP_NOTIFY,
>   >group_notifier);
>  
>  undo_iommu:
> - vfio_unregister_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY,
> + vfio_unregister_notifier(vfio_dev, VFIO_IOMMU_NOTIFY,
>   >iommu_notifier);
>  out:
>   return ret;
> @@ -988,6 +989,7 @@ static void __intel_vgpu_release(struct
> intel_vgpu *vgpu)
>   struct kvmgt_vdev *vdev = kvmgt_vdev(vgpu);
>   struct drm_i915_private *i915 = vgpu->gvt->gt->i915;
>   struct kvmgt_guest_info *info;
> + struct vfio_device *vfio_dev;
>   int ret;
>  
>   if (!handle_valid(vgpu->handle))
> @@ -998,12 +1000,13 @@ static void __intel_vgpu_release(struct
> intel_vgpu *vgpu)
>  
>   intel_gvt_ops->vgpu_release(vgpu);
>  
> - ret = vfio_unregister_notifier(mdev_dev(vdev->mdev),
> VFIO_IOMMU_NOTIFY,
> + vfio_dev = mdev_legacy_get_vfio_device(vdev->mdev);
> + ret = vfio_unregister_notifier(vfio_dev, VFIO_IOMMU_NOTIFY,
>   >iommu_notifier);
>   drm_WARN(>drm, ret,
>"vfio_unregister_notifier for iommu failed: %d\n",
> ret);
>  
> - ret = vfio_unregister_notifier(mdev_dev(vdev->mdev),
> VFIO_GROUP_NOTIFY,
> + ret = vfio_unregister_notifier(vfio_dev, VFIO_GROUP_NOTIFY,
>   >group_notifier);
>   drm_WARN(>drm, ret,
>"vfio_unregister_notifier for group failed: %d\n",
> ret);
> diff --git a/drivers/s390/cio/vfio_ccw_ops.c
> b/drivers/s390/cio/vfio_ccw_ops.c
> index d8589afac272f1..e1ce24d8fb2555 100644
> --- a/drivers/s390/cio/vfio_ccw_ops.c
> +++ b/drivers/s390/cio/vfio_ccw_ops.c
> @@ -183,7 +183,7 @@ static int vfio_ccw_mdev_open_device(struct
> vfio_device *vdev)
>  
>   private->nb.notifier_call = vfio_ccw_mdev_notifier;
>  
> - ret = vfio_register_notifier(vdev->dev, VFIO_IOMMU_NOTIFY,
> + ret = vfio_register_notifier(vdev, VFIO_IOMMU_NOTIFY,
>, >nb);
>   if (ret)
>   return ret;
> @@ -204,8 +204,7 @@ static int vfio_ccw_mdev_open_device(struct
> vfio_device *vdev)
>  
>  out_unregister:
>   vfio_ccw_unregister_dev_regions(private);
> - vfio_unregister_notifier(vdev->dev, VFIO_IOMMU_NOTIFY,
> -  >nb);
> +  

Re: [PATCH v7 1/4] drm/msm/dp: Add eDP support via aux_bus

2022-04-14 Thread Stephen Boyd
Quoting Dmitry Baryshkov (2022-04-14 12:16:14)
>
> I think it's too verbose and a bit incorrect.
> This is a bit saner:
> /*
>   * These ops do not make sense for eDP, since they are provided
>   * by the panel-bridge corresponding to the attached eDP panel.
>   */
>
> My question was whether we really need to disable them for eDP since for
> eDP the detect and and get_modes will be overridden anyway.

And to go further, I'd expect that a bridge should expose the
functionality that it supports, regardless of what is connected down the
chain. Otherwise we won't be able to mix and match bridges because the
code is brittle, making assumptions about what is connected.


Re: [PATCH v2] drm/msm/dp: enhance both connect and disconnect pending_timeout handle

2022-04-14 Thread Stephen Boyd
Quoting Kuogee Hsieh (2022-04-14 09:34:55)
>
> On 4/13/2022 5:02 PM, Stephen Boyd wrote:
> > The subject is still misleading. It is fixing something. It may be
> > enhancing it as well but it is clearly fixing it first.
> >
[...]
> > I'd prefer this part to be a different patch. It can come after the fix
> > to ease backporting.
> >
> > Also, is there any response to Dmitry's question yet? I haven't seen
> > anything.
>
> Sorry, since our internal review does not like this approach.

The internal review shouldn't prevent you from responding to code review
on the mailing list.


Re: [PATCH v7 0/4] Add support for the eDP panel over aux_bus

2022-04-14 Thread Dmitry Baryshkov

On 14/04/2022 19:40, Doug Anderson wrote:

Hi,

On Thu, Apr 14, 2022 at 5:19 AM Sankeerth Billakanti
 wrote:


This series adds support for generic eDP panel over aux_bus.

These changes are dependent on the following series:
https://patchwork.kernel.org/project/linux-arm-msm/list/?series=613654=*


You're basically depending on the last two patches of that series.
What's the plan there? In patchwork they're marked as "Not
Applicable". If they're good to go, maybe we should land them? If not,
maybe you should include them (with Dmitry as the author, of course)
at the beginning of your series?


No, please do not resend patches. The patches in question are marked as 
'Not applicable' as they are really not applicable to Bjorn's tree.

It would be better to point to the correct patchwork:

https://patchwork.freedesktop.org/series/98585/

Note those patches still lack the R-B tag. I can include them anyway, 
basing on Sankeerth's Tested-by tag, but the formal R-B would also be good.







Sankeerth Billakanti (4):
   drm/msm/dp: Add eDP support via aux_bus
   drm/msm/dp: Support only IRQ_HPD and REPLUG interrupts for eDP
   drm/msm/dp: wait for hpd high before aux transaction
   Support the eDP modes given by panel


One of these things is not like the others. One of these things just
doesn't belong. Can you spot which patch is missing the prefix by
looking at the subject line of all 4 patches? ;-)


:-)


--
With best wishes
Dmitry


Re: [PATCH v7 1/4] drm/msm/dp: Add eDP support via aux_bus

2022-04-14 Thread Dmitry Baryshkov

On 14/04/2022 19:39, Doug Anderson wrote:

Hi,

On Thu, Apr 14, 2022 at 5:20 AM Sankeerth Billakanti
 wrote:


@@ -1530,6 +1532,60 @@ void msm_dp_debugfs_init(struct msm_dp *dp_display, 
struct drm_minor *minor)
 }
  }

+static int dp_display_get_next_bridge(struct msm_dp *dp)
+{
+   int rc;
+   struct dp_display_private *dp_priv;
+   struct device_node *aux_bus;
+   struct device *dev;
+
+   dp_priv = container_of(dp, struct dp_display_private, dp_display);
+   dev = _priv->pdev->dev;
+   aux_bus = of_get_child_by_name(dev->of_node, "aux-bus");
+
+   if (aux_bus && dp->is_edp) {
+   dp_display_host_init(dp_priv);
+   dp_catalog_ctrl_hpd_config(dp_priv->catalog);
+   dp_display_host_phy_init(dp_priv);
+   enable_irq(dp_priv->irq);
+
+   rc = devm_of_dp_aux_populate_ep_devices(dp_priv->aux);
+   of_node_put(aux_bus);
+   if (rc) {
+   disable_irq(dp_priv->irq);
+   dp_display_host_phy_exit(dp_priv);
+   dp_display_host_deinit(dp_priv);
+   return rc;
+   }
+   } else if (dp->is_edp) {
+   DRM_ERROR("eDP aux_bus not found\n");
+   return -ENODEV;
+   }
+
+   /*
+* External bridges are mandatory for eDP interfaces: one has to
+* provide at least an eDP panel (which gets wrapped into panel-bridge).
+*
+* For DisplayPort interfaces external bridges are optional, so
+* silently ignore an error if one is not present (-ENODEV).
+*/
+   rc = dp_parser_find_next_bridge(dp_priv->parser);


This gets into the same problem that Dmitry pointed out that ps8640
has that's addressed by my recent series [1].  Namely it's not
guaranteed that the panel will have finished probing by the time
devm_of_dp_aux_populate_ep_devices() finishes probing. I don't think
it's going to be really solvable without the bigger rewrite that we've
been discussing, though. ...it's probably OK to land something like
what you have here, but it might at least deserve a comment in the
code?

[1] https://lore.kernel.org/r/20220409023628.2104952-1-diand...@chromium.org


We agreed that rework would follow up in a timely manner if these 
patches are applied. However a comment would be still a good thing.






+   if (rc == -ENODEV) {
+   if (dp->is_edp) {
+   DRM_ERROR("eDP: next bridge is not present\n");
+   return rc;
+   }
+   } else if (rc) {
+   if (rc != -EPROBE_DEFER)
+   DRM_ERROR("DP: error parsing next bridge: %d\n", rc);
+   return rc;


In both of your two error returns here isn't it a problem that you don't do:

   disable_irq(dp_priv->irq);
   dp_display_host_phy_exit(dp_priv);
   dp_display_host_deinit(dp_priv);

Should probably at least fix that clear error before landing, unless
I'm misunderstanding and there's some reason not to do that?


As discussed previously, I'm not convinced that we've covered every
corner case for properly doing and undoing the above things. I'm
hoping that once we do the cleanup and move to pm_runtime() management
that it will be cleaned up?



@@ -114,10 +114,12 @@ struct drm_bridge *dp_bridge_init(struct msm_dp 
*dp_display, struct drm_device *
 bridge->funcs = _bridge_ops;
 bridge->type = dp_display->connector_type;

-   bridge->ops =
-   DRM_BRIDGE_OP_DETECT |
-   DRM_BRIDGE_OP_HPD |
-   DRM_BRIDGE_OP_MODES;
+   if (!dp_display->is_edp) {
+   bridge->ops =
+   DRM_BRIDGE_OP_DETECT |
+   DRM_BRIDGE_OP_HPD |
+   DRM_BRIDGE_OP_MODES;


Given that Dmitry had questions about why eDP has different ops in his
previous review of this code, the above probably deserves an inline
code comment. If you want to use my wording, you could paste this into
your code:

   /*
* Many ops only make sense for DP. Why?
* - Detect/HPD are used by DRM to know if a display is _physically_
*   there, not whether the display is powered on / finished initting.
*   On eDP we assume the display is always there because you can't
*   know until power is applied. If we don't implement the ops DRM will
*   assume our display is always there.
* - Currently eDP mode reading is driven by the panel driver. This
*   allows the panel driver to properly power itself on to read the
*   modes.
*/


I think it's too verbose and a bit incorrect.
This is a bit saner:
/*
 * These ops do not make sense for eDP, since they are provided
 * by the panel-bridge corresponding to the attached eDP panel.
 */

My question was whether we really need to disable them for eDP since for 
eDP the detect and and get_modes will be overridden anyway.



Overall: as discussed, I think 

[PATCH v2 2/3] drm/msm/a6xx: Add speedbin support for A619 GPU

2022-04-14 Thread Konrad Dybcio
There are various SKUs of A619, ranging from 565 MHz to 850 MHz, depending
on the bin. Add support for distinguishing them, so that proper frequency
ranges can be applied, depending on the HW.

Signed-off-by: Konrad Dybcio 
---
 drivers/gpu/drm/msm/adreno/a6xx_gmu.c |  2 +-
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 19 +++
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c 
b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index e8d4cca6cd46..2cd632fdd890 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -1540,7 +1540,7 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct 
device_node *node)
SZ_16M - SZ_16K, 0x04000, "icache");
if (ret)
goto err_memory;
-   } else {
+   } else if (adreno_is_a640_family(adreno_gpu)) {
ret = a6xx_gmu_memory_alloc(gmu, >icache,
SZ_256K - SZ_16K, 0x04000, "icache");
if (ret)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index ddeb04a77662..57d07ae86b2a 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -1836,6 +1836,22 @@ static u32 a618_get_speed_bin(u32 fuse)
return UINT_MAX;
 }
 
+static u32 a619_get_speed_bin(u32 fuse)
+{
+   if (fuse == 0)
+   return 0;
+   else if (fuse == 120)
+   return 4;
+   else if (fuse == 138)
+   return 3;
+   else if (fuse == 169)
+   return 2;
+   else if (fuse == 180)
+   return 1;
+
+   return UINT_MAX;
+}
+
 static u32 adreno_7c3_get_speed_bin(u32 fuse)
 {
if (fuse == 0)
@@ -1855,6 +1871,9 @@ static u32 fuse_to_supp_hw(struct device *dev, struct 
adreno_rev rev, u32 fuse)
if (adreno_cmp_rev(ADRENO_REV(6, 1, 8, ANY_ID), rev))
val = a618_get_speed_bin(fuse);
 
+   if (adreno_cmp_rev(ADRENO_REV(6, 1, 9, ANY_ID), rev))
+   val = a619_get_speed_bin(fuse);
+
if (adreno_cmp_rev(ADRENO_REV(6, 3, 5, ANY_ID), rev))
val = adreno_7c3_get_speed_bin(fuse);
 
-- 
2.35.2



[PATCH v2 1/3] drm/msm/adreno: Add A619 support

2022-04-14 Thread Konrad Dybcio
Add support for the Adreno 619 GPU, as found in Snapdragon 690 (SM6350),
480 (SM4350) and 750G (SM7225).

Signed-off-by: Konrad Dybcio 
---
Changes in v2:
- Don't reserve icache/dcache regions on legacy GMUs, as that
is apparently not necessary and simply a downstream leftover.


 drivers/gpu/drm/msm/adreno/a6xx_gmu.c  | 11 ++--
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c  | 70 +-
 drivers/gpu/drm/msm/adreno/a6xx_hfi.c  | 66 +++-
 drivers/gpu/drm/msm/adreno/adreno_device.c | 14 +
 drivers/gpu/drm/msm/adreno/adreno_gpu.h| 13 +++-
 5 files changed, 166 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c 
b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 3e325e2a2b1b..e8d4cca6cd46 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -527,6 +527,8 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)
pdc_in_aop = true;
else if (adreno_is_a618(adreno_gpu) || 
adreno_is_a640_family(adreno_gpu))
pdc_address_offset = 0x30090;
+   else if (adreno_is_a619(adreno_gpu))
+   pdc_address_offset = 0x300a0;
else
pdc_address_offset = 0x30080;
 
@@ -601,7 +603,8 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)
 
pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_MSGID + 4, 0x10108);
pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_ADDR + 4, 0x3);
-   if (adreno_is_a618(adreno_gpu) || adreno_is_a650_family(adreno_gpu))
+   if (adreno_is_a618(adreno_gpu) || adreno_is_a619(adreno_gpu) ||
+   adreno_is_a650_family(adreno_gpu))
pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_DATA + 4, 0x2);
else
pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_DATA + 4, 0x3);
@@ -1537,7 +1540,7 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct 
device_node *node)
SZ_16M - SZ_16K, 0x04000, "icache");
if (ret)
goto err_memory;
-   } else if (adreno_is_a640_family(adreno_gpu)) {
+   } else {
ret = a6xx_gmu_memory_alloc(gmu, >icache,
SZ_256K - SZ_16K, 0x04000, "icache");
if (ret)
@@ -1547,9 +1550,9 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct 
device_node *node)
SZ_256K - SZ_16K, 0x44000, "dcache");
if (ret)
goto err_memory;
-   } else {
-   BUG_ON(adreno_is_a660_family(adreno_gpu));
+   }
 
+   if (adreno_is_a630(adreno_gpu) || adreno_is_a615_family(adreno_gpu)) {
/* HFI v1, has sptprac */
gmu->legacy = true;
 
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 83c31b2ad865..ddeb04a77662 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -252,6 +252,74 @@ static void a6xx_submit(struct msm_gpu *gpu, struct 
msm_gem_submit *submit)
a6xx_flush(gpu, ring);
 }
 
+/* For a615 family (a615, a616, a618 and a619) */
+const struct adreno_reglist a615_hwcg[] = {
+   {REG_A6XX_RBBM_CLOCK_CNTL_SP0,  0x0222},
+   {REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x0220},
+   {REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x0080},
+   {REG_A6XX_RBBM_CLOCK_HYST_SP0,  0xF3CF},
+   {REG_A6XX_RBBM_CLOCK_CNTL_TP0,  0x0222},
+   {REG_A6XX_RBBM_CLOCK_CNTL_TP1,  0x0222},
+   {REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x},
+   {REG_A6XX_RBBM_CLOCK_CNTL2_TP1, 0x},
+   {REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x},
+   {REG_A6XX_RBBM_CLOCK_CNTL3_TP1, 0x},
+   {REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x0002},
+   {REG_A6XX_RBBM_CLOCK_CNTL4_TP1, 0x0002},
+   {REG_A6XX_RBBM_CLOCK_HYST_TP0,  0x},
+   {REG_A6XX_RBBM_CLOCK_HYST_TP1,  0x},
+   {REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x},
+   {REG_A6XX_RBBM_CLOCK_HYST2_TP1, 0x},
+   {REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x},
+   {REG_A6XX_RBBM_CLOCK_HYST3_TP1, 0x},
+   {REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x0007},
+   {REG_A6XX_RBBM_CLOCK_HYST4_TP1, 0x0007},
+   {REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x},
+   {REG_A6XX_RBBM_CLOCK_DELAY_TP1, 0x},
+   {REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x},
+   {REG_A6XX_RBBM_CLOCK_DELAY2_TP1, 0x},
+   {REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x},
+   {REG_A6XX_RBBM_CLOCK_DELAY3_TP1, 0x},
+   {REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x0001},
+   {REG_A6XX_RBBM_CLOCK_DELAY4_TP1, 0x0001},
+   {REG_A6XX_RBBM_CLOCK_CNTL_UCHE,  0x},
+   {REG_A6XX_RBBM_CLOCK_CNTL2_UCHE, 0x},
+   {REG_A6XX_RBBM_CLOCK_CNTL3_UCHE, 0x},
+   {REG_A6XX_RBBM_CLOCK_CNTL4_UCHE, 0x0022},
+   {REG_A6XX_RBBM_CLOCK_HYST_UCHE,  0x0004},
+   

[PATCH v2 3/3] drm/msm/adreno: Fix up formatting

2022-04-14 Thread Konrad Dybcio
Leading spaces are not something checkpatch likes, and it says so when
they are present. Use tabs consistently to indent function body and
unwrap a 83-char-long line, as 100 is cool nowadays.

Signed-off-by: Konrad Dybcio 
---
 drivers/gpu/drm/msm/adreno/adreno_gpu.h | 17 -
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h 
b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index a13a3e5a294b..f73f7b5dfd10 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -199,7 +199,7 @@ static inline int adreno_is_a420(struct adreno_gpu *gpu)
 
 static inline int adreno_is_a430(struct adreno_gpu *gpu)
 {
-   return gpu->revn == 430;
+   return gpu->revn == 430;
 }
 
 static inline int adreno_is_a506(struct adreno_gpu *gpu)
@@ -239,7 +239,7 @@ static inline int adreno_is_a540(struct adreno_gpu *gpu)
 
 static inline int adreno_is_a618(struct adreno_gpu *gpu)
 {
-   return gpu->revn == 618;
+   return gpu->revn == 618;
 }
 
 static inline int adreno_is_a619(struct adreno_gpu *gpu)
@@ -249,7 +249,7 @@ static inline int adreno_is_a619(struct adreno_gpu *gpu)
 
 static inline int adreno_is_a630(struct adreno_gpu *gpu)
 {
-   return gpu->revn == 630;
+   return gpu->revn == 630;
 }
 
 static inline int adreno_is_a640_family(struct adreno_gpu *gpu)
@@ -259,18 +259,18 @@ static inline int adreno_is_a640_family(struct adreno_gpu 
*gpu)
 
 static inline int adreno_is_a650(struct adreno_gpu *gpu)
 {
-   return gpu->revn == 650;
+   return gpu->revn == 650;
 }
 
 static inline int adreno_is_7c3(struct adreno_gpu *gpu)
 {
/* The order of args is important here to handle ANY_ID correctly */
-   return adreno_cmp_rev(ADRENO_REV(6, 3, 5, ANY_ID), gpu->rev);
+   return adreno_cmp_rev(ADRENO_REV(6, 3, 5, ANY_ID), gpu->rev);
 }
 
 static inline int adreno_is_a660(struct adreno_gpu *gpu)
 {
-   return gpu->revn == 660;
+   return gpu->revn == 660;
 }
 
 /* check for a615, a616, a618, a619 or any derivatives */
@@ -281,14 +281,13 @@ static inline int adreno_is_a615_family(struct adreno_gpu 
*gpu)
 
 static inline int adreno_is_a660_family(struct adreno_gpu *gpu)
 {
-   return adreno_is_a660(gpu) || adreno_is_7c3(gpu);
+   return adreno_is_a660(gpu) || adreno_is_7c3(gpu);
 }
 
 /* check for a650, a660, or any derivatives */
 static inline int adreno_is_a650_family(struct adreno_gpu *gpu)
 {
-   return gpu->revn == 650 || gpu->revn == 620 ||
-  adreno_is_a660_family(gpu);
+   return gpu->revn == 650 || gpu->revn == 620 || 
adreno_is_a660_family(gpu);
 }
 
 int adreno_get_param(struct msm_gpu *gpu, struct msm_file_private *ctx,
-- 
2.35.2



[PATCH v2 1/1] i915/gem: drop wbinvd_on_all_cpus usage

2022-04-14 Thread Michael Cheng
Previous concern with using drm_clflush_sg was that we don't know what the
sg_table is pointing to, thus the usage of wbinvd_on_all_cpus to flush
everything at once to avoid paranoia.

To make i915 more architecture-neutral and be less paranoid, lets attempt to
use drm_clflush_sg to flush the pages for when the GPU wants to read
from main memory.

Signed-off-by: Michael Cheng 
---
 drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 9 ++---
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c 
b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
index f5062d0c6333..b0a5baaebc43 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
@@ -8,6 +8,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -250,16 +251,10 @@ static int i915_gem_object_get_pages_dmabuf(struct 
drm_i915_gem_object *obj)
 * DG1 is special here since it still snoops transactions even with
 * CACHE_NONE. This is not the case with other HAS_SNOOP platforms. We
 * might need to revisit this as we add new discrete platforms.
-*
-* XXX: Consider doing a vmap flush or something, where possible.
-* Currently we just do a heavy handed wbinvd_on_all_cpus() here since
-* the underlying sg_table might not even point to struct pages, so we
-* can't just call drm_clflush_sg or similar, like we do elsewhere in
-* the driver.
 */
if (i915_gem_object_can_bypass_llc(obj) ||
(!HAS_LLC(i915) && !IS_DG1(i915)))
-   wbinvd_on_all_cpus();
+   drm_clflush_sg(pages);
 
sg_page_sizes = i915_sg_dma_sizes(pages->sgl);
__i915_gem_object_set_pages(obj, pages, sg_page_sizes);
-- 
2.25.1



[PATCH v2 0/1] Drop wbinvd_on_all_cpus usage

2022-04-14 Thread Michael Cheng
To align with the discussion in [1][2], this patch series drops all usage of
wbvind_on_all_cpus within i915 by either replacing the call with certain
drm clflush helpers, or reverting to a previous logic.  

 
[1]. https://lists.freedesktop.org/archives/dri-devel/2021-November/330928.html 
[2]. https://patchwork.freedesktop.org/patch/475752/?series=1=5 

v2 (Michael Cheng) : Per feedback from Thomas and Tvrtko, this series should be
split into two parts; First part is to unblock i915 from build errors and 
second part will focus on implementing range flushes on the propose reverts.


Michael Cheng (1):
  i915/gem: drop wbinvd_on_all_cpus usage

 drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 9 ++---
 1 file changed, 2 insertions(+), 7 deletions(-)

-- 
2.25.1



[PATCH v2 0/1]

2022-04-14 Thread Michael Cheng
To align with the discussion in [1][2], this patch series drops all usage of
wbvind_on_all_cpus within i915 by either replacing the call with certain
drm clflush helpers, or reverting to a previous logic.  

 
[1]. https://lists.freedesktop.org/archives/dri-devel/2021-November/330928.html 
[2]. https://patchwork.freedesktop.org/patch/475752/?series=1=5 

v2 (Michael Cheng) : Per feedback from Thomas and Tvrtko, this series should be
split into two parts; First part is to unblock i915 from build errors and 
second part will focus on implementing range flushes on the propose reverts.


Michael Cheng (1):
  i915/gem: drop wbinvd_on_all_cpus usage

 drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 9 ++---
 1 file changed, 2 insertions(+), 7 deletions(-)

-- 
2.25.1



[PATCH v2 1/1] i915/gem: drop wbinvd_on_all_cpus usage

2022-04-14 Thread Michael Cheng
Previous concern with using drm_clflush_sg was that we don't know what the
sg_table is pointing to, thus the usage of wbinvd_on_all_cpus to flush
everything at once to avoid paranoia.

To make i915 more architecture-neutral and be less paranoid, lets attempt to
use drm_clflush_sg to flush the pages for when the GPU wants to read
from main memory.

Signed-off-by: Michael Cheng 
---
 drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 9 ++---
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c 
b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
index f5062d0c6333..b0a5baaebc43 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
@@ -8,6 +8,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -250,16 +251,10 @@ static int i915_gem_object_get_pages_dmabuf(struct 
drm_i915_gem_object *obj)
 * DG1 is special here since it still snoops transactions even with
 * CACHE_NONE. This is not the case with other HAS_SNOOP platforms. We
 * might need to revisit this as we add new discrete platforms.
-*
-* XXX: Consider doing a vmap flush or something, where possible.
-* Currently we just do a heavy handed wbinvd_on_all_cpus() here since
-* the underlying sg_table might not even point to struct pages, so we
-* can't just call drm_clflush_sg or similar, like we do elsewhere in
-* the driver.
 */
if (i915_gem_object_can_bypass_llc(obj) ||
(!HAS_LLC(i915) && !IS_DG1(i915)))
-   wbinvd_on_all_cpus();
+   drm_clflush_sg(pages);
 
sg_page_sizes = i915_sg_dma_sizes(pages->sgl);
__i915_gem_object_set_pages(obj, pages, sg_page_sizes);
-- 
2.25.1



[PATCH v3] drm/msm/dp: stop event kernel thread when DP unbind

2022-04-14 Thread Kuogee Hsieh
Current DP driver implementation, event thread is kept running
after DP display is unbind. This patch fix this problem by disabling
DP irq and stop event thread to exit gracefully at dp_display_unbind().

Changes in v2:
-- start event thread at dp_display_bind()

Changes in v3:
-- disable all HDP interrupts at unbind
-- replace dp_hpd_event_setup() with dp_hpd_event_thread_start()
-- replace dp_hpd_event_stop() with dp_hpd_event_thread_stop()
-- move init_waitqueue_head(>event_q) to probe()
-- move spin_lock_init(>event_lock) to probe()

Fixes: e91e3065a806 ("drm/msm/dp: Add DP compliance tests on Snapdragon 
Chipsets")
Signed-off-by: Kuogee Hsieh 
Reported-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/dp/dp_display.c | 42 -
 1 file changed, 32 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 01453db..0b9a96f 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -113,6 +113,7 @@ struct dp_display_private {
u32 hpd_state;
u32 event_pndx;
u32 event_gndx;
+   struct task_struct *ev_tsk;
struct dp_event event_list[DP_EVENT_Q_MAX];
spinlock_t event_lock;
 
@@ -230,6 +231,29 @@ void dp_display_signal_audio_complete(struct msm_dp 
*dp_display)
complete_all(>audio_comp);
 }
 
+static int hpd_event_thread(void *data);
+
+static int dp_hpd_event_thread_start(struct dp_display_private *dp_priv)
+{
+   int err = 0;
+
+   dp_priv->ev_tsk = kthread_run(hpd_event_thread, dp_priv, 
"dp_hpd_handler");
+   if (IS_ERR(dp_priv->ev_tsk)) {
+   DRM_ERROR("failed to create DP event thread\n");
+   err = PTR_ERR(dp_priv->ev_tsk);
+   }
+   return err;
+}
+
+static void dp_hpd_event_thread_stop(struct dp_display_private *dp_priv)
+{
+   kthread_stop(dp_priv->ev_tsk);
+
+   /* reset event q to empty */
+   dp_priv->event_gndx = 0;
+   dp_priv->event_pndx = 0;
+}
+
 static int dp_display_bind(struct device *dev, struct device *master,
   void *data)
 {
@@ -269,6 +293,7 @@ static int dp_display_bind(struct device *dev, struct 
device *master,
if (rc)
DRM_ERROR("Audio registration Dp failed\n");
 
+   rc = dp_hpd_event_thread_start(dp);
 end:
return rc;
 }
@@ -280,6 +305,9 @@ static void dp_display_unbind(struct device *dev, struct 
device *master,
struct drm_device *drm = dev_get_drvdata(master);
struct msm_drm_private *priv = drm->dev_private;
 
+   /* disable all HPD interrupts */
+   dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_INT_MASK, false);
+   dp_hpd_event_thread_stop(dp);
dp_power_client_deinit(dp->power);
dp_aux_unregister(dp->aux);
priv->dp[dp->id] = NULL;
@@ -1054,7 +1082,7 @@ static int hpd_event_thread(void *data)
 
dp_priv = (struct dp_display_private *)data;
 
-   while (1) {
+   while (!kthread_should_stop()) {
if (timeout_mode) {
wait_event_timeout(dp_priv->event_q,
(dp_priv->event_pndx == dp_priv->event_gndx),
@@ -1132,13 +1160,6 @@ static int hpd_event_thread(void *data)
return 0;
 }
 
-static void dp_hpd_event_setup(struct dp_display_private *dp_priv)
-{
-   init_waitqueue_head(_priv->event_q);
-   spin_lock_init(_priv->event_lock);
-
-   kthread_run(hpd_event_thread, dp_priv, "dp_hpd_handler");
-}
 
 static irqreturn_t dp_display_irq_handler(int irq, void *dev_id)
 {
@@ -1266,7 +1287,10 @@ static int dp_display_probe(struct platform_device *pdev)
return -EPROBE_DEFER;
}
 
+   /* setup event q */
mutex_init(>event_mutex);
+   init_waitqueue_head(>event_q);
+   spin_lock_init(>event_lock);
 
/* Store DP audio handle inside DP display */
dp->dp_display.dp_audio = dp->audio;
@@ -1441,8 +1465,6 @@ void msm_dp_irq_postinstall(struct msm_dp *dp_display)
 
dp = container_of(dp_display, struct dp_display_private, dp_display);
 
-   dp_hpd_event_setup(dp);
-
dp_add_event(dp, EV_HPD_INIT_SETUP, 0, 100);
 }
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



Re: [PATCH v3 5/5] drm/i915: stolen memory use ttm backend

2022-04-14 Thread Robert Beckett




On 14/04/2022 15:41, Thomas Hellström wrote:

Hi,


On 4/12/22 21:38, Robert Beckett wrote:

+struct ttm_resource *
+i915_gem_stolen_reserve_range(struct drm_i915_private *i915,
+  resource_size_t size,
+  u64 start, u64 end)
  {
-    int ret;
+    struct intel_memory_region *mem = i915->mm.stolen_region;
-    if (!drm_mm_initialized(>mm.stolen))
-    return -ENODEV;
-
-    /* WaSkipStolenMemoryFirstPage:bdw+ */
-    if (GRAPHICS_VER(i915) >= 8 && start < 4096)
-    start = 4096;


Did we lose this Workaround?


woops, looks like we did. Nice catch.
I'll add a reservation at start of day if wa is needed when I issue v4.



Need to continue reviewing this patchnext week.


Thx,

Thomas





-
-    mutex_lock(>mm.stolen_lock);
-    ret = drm_mm_insert_node_in_range(>mm.stolen, node,
-  size, alignment, 0,
-  start, end, DRM_MM_INSERT_BEST);
-    mutex_unlock(>mm.stolen_lock);
+    if (!mem)
+    return ERR_PTR(-ENODEV);
+    return intel_region_ttm_resource_alloc(mem, size, start, end, 
I915_BO_ALLOC_CONTIGUOUS);

+}
-


Re: [PATCH v2] drm/msm/dp: stop event kernel thread when DP unbind

2022-04-14 Thread Kuogee Hsieh



On 4/13/2022 4:19 PM, Stephen Boyd wrote:

Quoting Kuogee Hsieh (2022-04-13 14:04:25)

Current DP driver implementation, event thread is kept running
after DP display is unbind. This patch fix this problem by disabling
DP irq and stop event thread to exit gracefully at dp_display_unbind().

Changes in v2:
-- start event thread at dp_display_bind()

Fixes: e91e3065a806 ("drm/msm/dp: Add DP compliance tests on Snapdragon 
Chipsets")
Signed-off-by: Kuogee Hsieh 
Reported-by: Dmitry Baryshkov 
---
  drivers/gpu/drm/msm/dp/dp_display.c | 40 +++--
  1 file changed, 30 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 01453db..943e4f1 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -113,6 +113,7 @@ struct dp_display_private {
 u32 hpd_state;
 u32 event_pndx;
 u32 event_gndx;
+   struct task_struct *ev_tsk;
 struct dp_event event_list[DP_EVENT_Q_MAX];
 spinlock_t event_lock;

@@ -230,6 +231,31 @@ void dp_display_signal_audio_complete(struct msm_dp 
*dp_display)
 complete_all(>audio_comp);
  }

+static int hpd_event_thread(void *data);

Is there a reason why this is needed vs. defining the kthread start
function after hpd_event_thread()?

too many code need to be relocated.



+
+static void dp_hpd_event_setup(struct dp_display_private *dp_priv)

Maybe dp_hpd_event_thread_start()?


+{
+   init_waitqueue_head(_priv->event_q);
+   spin_lock_init(_priv->event_lock);
+
+   dp_priv->ev_tsk = kthread_run(hpd_event_thread, dp_priv, 
"dp_hpd_handler");
+
+   if (IS_ERR(dp_priv->ev_tsk))
+   DRM_ERROR("failed to create DP event thread\n");

Can we return an error from this function?


+}
+
+static void dp_hpd_event_stop(struct dp_display_private *dp_priv)

Maybe dp_hpd_event_thread_stop()?


+{
+   if (IS_ERR(dp_priv->ev_tsk))
+   return;

If we handled the error then this check becomes impossible.


+
+   kthread_stop(dp_priv->ev_tsk);
+
+   /* reset event q to empty */
+   dp_priv->event_gndx = 0;
+   dp_priv->event_pndx = 0;
+}
+
  static int dp_display_bind(struct device *dev, struct device *master,
void *data)
  {
@@ -269,6 +295,7 @@ static int dp_display_bind(struct device *dev, struct 
device *master,
 if (rc)
 DRM_ERROR("Audio registration Dp failed\n");

+   dp_hpd_event_setup(dp); /* start event thread */

The comment is useless, please remove.


  end:
 return rc;
  }
@@ -280,6 +307,8 @@ static void dp_display_unbind(struct device *dev, struct 
device *master,
 struct drm_device *drm = dev_get_drvdata(master);
 struct msm_drm_private *priv = drm->dev_private;

+   disable_irq(dp->irq);

Is the disable_irq() necessary? It would be nicer to silence the
hardware and remove the disable_irq() so that we can reason about the
code assuming the irq is always enabled after it is requested.


+   dp_hpd_event_stop(dp); /* stop event thread */
 dp_power_client_deinit(dp->power);
 dp_aux_unregister(dp->aux);
 priv->dp[dp->id] = NULL;


Re: [PATCH v7 0/4] Add support for the eDP panel over aux_bus

2022-04-14 Thread Doug Anderson
Hi,

On Thu, Apr 14, 2022 at 5:19 AM Sankeerth Billakanti
 wrote:
>
> This series adds support for generic eDP panel over aux_bus.
>
> These changes are dependent on the following series:
> https://patchwork.kernel.org/project/linux-arm-msm/list/?series=613654=*

You're basically depending on the last two patches of that series.
What's the plan there? In patchwork they're marked as "Not
Applicable". If they're good to go, maybe we should land them? If not,
maybe you should include them (with Dmitry as the author, of course)
at the beginning of your series?


> Sankeerth Billakanti (4):
>   drm/msm/dp: Add eDP support via aux_bus
>   drm/msm/dp: Support only IRQ_HPD and REPLUG interrupts for eDP
>   drm/msm/dp: wait for hpd high before aux transaction
>   Support the eDP modes given by panel

One of these things is not like the others. One of these things just
doesn't belong. Can you spot which patch is missing the prefix by
looking at the subject line of all 4 patches? ;-)


Re: [PATCH v7 4/4] Support the eDP modes given by panel

2022-04-14 Thread Doug Anderson
Hi,

On Thu, Apr 14, 2022 at 5:20 AM Sankeerth Billakanti
 wrote:
>
> The eDP controller does not have a reliable way keep panel
> powered on to read the sink capabilities. So, the controller
> driver cannot validate if a mode can be supported by the
> source. We will rely on the panel driver to populate only
> the supported modes for now.
>
> Signed-off-by: Sankeerth Billakanti 
> ---
>  drivers/gpu/drm/msm/dp/dp_display.c | 8 
>  1 file changed, 8 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
> b/drivers/gpu/drm/msm/dp/dp_display.c
> index c7277f0..0f18a16 100644
> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> @@ -998,6 +998,14 @@ enum drm_mode_status dp_bridge_mode_valid(struct 
> drm_bridge *bridge,
> return -EINVAL;
> }
>
> +   /*
> +* The eDP controller currently does not have a reliable way of
> +* enabling panel power to read sink capabilities. So, we rely
> +* on the panel driver to populate only supported modes for now.
> +*/
> +   if (dp->is_edp)
> +   return MODE_OK;

As discussed out-of-band, I agree that this is the right thing for now
and making this assumption won't break anything. In general the set of
eDP panels is known ahead of time it's fairly unlikely someone would
set things up so that a panel couldn't use the mode it was reporting.

Longer term we should figure out a way to solve this but it doesn't
have to be today. To properly implement mode_valid() we've got to
combine knowledge from the panel (mostly rates supported and number of
lanes supported) with the controller (rates supported, number of lanes
supported/hooked up on this board).

In any case:

Reviewed-by: Douglas Anderson 


Re: [PATCH v7 3/4] drm/msm/dp: wait for hpd high before aux transaction

2022-04-14 Thread Doug Anderson
Hi,

On Thu, Apr 14, 2022 at 5:20 AM Sankeerth Billakanti
 wrote:
>
> The source device should ensure the sink is ready before proceeding to
> read the sink capability or perform any aux transactions. The sink
> will indicate its readiness by asserting the HPD line. The controller
> driver needs to wait for the hpd line to be asserted by the sink before
> it performs any aux transactions.
>
> The eDP sink is assumed to be always connected. It needs power from the
> source and its HPD line will be asserted only after the panel is powered
> on. The panel power will be enabled from the panel-edp driver and only
> after that, the hpd line will be asserted.
>
> Whereas for DP, the sink can be hotplugged and unplugged anytime. The hpd
> line gets asserted to indicate the sink is connected and ready. Hence
> there is no need to wait for the hpd line to be asserted for a DP sink.
>
> Signed-off-by: Sankeerth Billakanti 
> ---

It might be worth mentioning "after the cut" that we may eventually
end up changing the rules if people like my proposal [1]. However,
what your code is doing here for eDP is correct as things are
currently intended to work and it would make sense to land it while we
debate about whether we want to add the is_hpd_asserted() callback
like my patch does.

[1] 
https://lore.kernel.org/r/20220408193536.RFC.3.Icf57bb12233a47727013c6ab69eebf803e22ebc1@changeid/


> Changes in v7:
>   - add a comment to say why the wait si done for eDP
>   - correct the commit text
>
> Changes in v6:
>   - Wait for hpd high only for eDP
>   - Split into smaller patches
>
>  drivers/gpu/drm/msm/dp/dp_aux.c | 21 -
>  drivers/gpu/drm/msm/dp/dp_aux.h |  3 ++-
>  drivers/gpu/drm/msm/dp/dp_catalog.c | 13 +
>  drivers/gpu/drm/msm/dp/dp_catalog.h |  1 +
>  drivers/gpu/drm/msm/dp/dp_display.c |  2 +-
>  5 files changed, 37 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c
> index 6d36f63..cf0739f 100644
> --- a/drivers/gpu/drm/msm/dp/dp_aux.c
> +++ b/drivers/gpu/drm/msm/dp/dp_aux.c
> @@ -36,6 +36,7 @@ struct dp_aux_private {
> bool initted;
> u32 offset;
> u32 segment;
> +   bool is_edp;

Kinda nitty, but can you put it next to the other booleans? This will
help with structure packing.


> struct drm_dp_aux dp_aux;
>  };
> @@ -337,6 +338,22 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux,
> goto exit;
> }
>
> +   /*
> +* For eDP it's important to give a reasonably long wait here for HPD
> +* to be asserted. This is because the panel driver may have _just_
> +* turned on the panel and then tried to do an AUX transfer. The panel
> +* driver has no way of knowing when the panel is ready, so it's up
> +* to us to wait. For DP we never get into this situation so let's
> +* avoid ever doing the extra long wait for DP.
> +*/
> +   if (aux->is_edp) {
> +   ret = dp_catalog_aux_wait_for_hpd_connect_state(aux->catalog);
> +   if (ret) {
> +   DRM_DEBUG_DP("Panel not ready for aux 
> transactions\n");
> +   goto exit;
> +   }
> +   }
> +
> dp_aux_update_offset_and_segment(aux, msg);
> dp_aux_transfer_helper(aux, msg, true);
>
> @@ -491,7 +508,8 @@ void dp_aux_unregister(struct drm_dp_aux *dp_aux)
> drm_dp_aux_unregister(dp_aux);
>  }
>
> -struct drm_dp_aux *dp_aux_get(struct device *dev, struct dp_catalog *catalog)
> +struct drm_dp_aux *dp_aux_get(struct device *dev, struct dp_catalog *catalog,
> +   bool is_edp)

nit: I think indentation rules for this file are that the type of the
argument for the 2nd line should line up right under the 1st. Thus you
should delete one tab character and insert 6 spaces before the "bool".

Similar in other places, like your header file.


Stuff above is all nits and this looks right to me. I'm happy with:

Reviewed-by: Douglas Anderson 


Re: [PATCH v7 2/4] drm/msm/dp: Support only IRQ_HPD and REPLUG interrupts for eDP

2022-04-14 Thread Doug Anderson
Hi,

On Thu, Apr 14, 2022 at 5:20 AM Sankeerth Billakanti
 wrote:
>
> The panel-edp enables the eDP panel power during probe, get_modes
> and enable.

Technically the panel-edp powers on the panel in pre_enable()


> The eDP connect and disconnect interrupts for the eDP/DP
> controller are directly dependent on panel power. As eDP display can be
> assumed as always connected, the controller driver can skip the eDP
> connect and disconnect interrupts. Any disruption in the link status
> will be indicated via the IRQ_HPD interrupts.
>
> So, the eDP controller driver can just enable the IRQ_HPD and replug
> interrupts. The DP controller driver still needs to enable all the
> interrupts.
>
> Signed-off-by: Sankeerth Billakanti 
> ---
>
> Changes in v7:
>   - reordered the patch in the series
>   - modified the return statement for isr
>   - connector check modified to just check for eDP
>
>  drivers/gpu/drm/msm/dp/dp_catalog.c |  9 +++--
>  drivers/gpu/drm/msm/dp/dp_display.c | 22 +-
>  2 files changed, 24 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c 
> b/drivers/gpu/drm/msm/dp/dp_catalog.c
> index fac815f..07f2389 100644
> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
> @@ -569,10 +569,6 @@ void dp_catalog_ctrl_hpd_config(struct dp_catalog 
> *dp_catalog)
>
> u32 reftimer = dp_read_aux(catalog, REG_DP_DP_HPD_REFTIMER);
>
> -   /* enable HPD plug and unplug interrupts */
> -   dp_catalog_hpd_config_intr(dp_catalog,
> -   DP_DP_HPD_PLUG_INT_MASK | DP_DP_HPD_UNPLUG_INT_MASK, true);
> -
> /* Configure REFTIMER and enable it */
> reftimer |= DP_DP_HPD_REFTIMER_ENABLE;
> dp_write_aux(catalog, REG_DP_DP_HPD_REFTIMER, reftimer);
> @@ -599,13 +595,14 @@ u32 dp_catalog_hpd_get_intr_status(struct dp_catalog 
> *dp_catalog)
>  {
> struct dp_catalog_private *catalog = container_of(dp_catalog,
> struct dp_catalog_private, dp_catalog);
> -   int isr = 0;
> +   int isr, mask;
>
> isr = dp_read_aux(catalog, REG_DP_DP_HPD_INT_STATUS);
> dp_write_aux(catalog, REG_DP_DP_HPD_INT_ACK,
>  (isr & DP_DP_HPD_INT_MASK));
> +   mask = dp_read_aux(catalog, REG_DP_DP_HPD_INT_MASK);
>
> -   return isr;
> +   return isr & (mask | ~DP_DP_HPD_INT_MASK);

Please add a comment above this explaining what the goal of the above
statement is. I guess it's something like this, though you might want
to modify it to remove snark and insert the real reason unless you
like being snarky:

  /*
   * Report the raw status of all interrupts (AKA we still report the
   * interrupt as asserted even if it's masked) _except_ for HPD-related.
   * interrupts. We only report HPD-related interrupts if they're
   * unmasked. We do it this way because we thought it would be extra
   * confusing for readers of this code and we were bribed by Mordac to
   * confuse you.  OK, maybe that's not true. We actually do it this way
   * because of .
   */

Along the same lines as my comments in patch #1, I don't have a great
feel for exactly when the various HPD bits are enabled / disabled and
it feels like it need to be made super obvious / well documented. That
being said, I'd be OK w/ that happening in the proposed cleanup.


-Doug


Re: [PATCH v7 1/4] drm/msm/dp: Add eDP support via aux_bus

2022-04-14 Thread Doug Anderson
Hi,

On Thu, Apr 14, 2022 at 5:20 AM Sankeerth Billakanti
 wrote:
>
> @@ -1530,6 +1532,60 @@ void msm_dp_debugfs_init(struct msm_dp *dp_display, 
> struct drm_minor *minor)
> }
>  }
>
> +static int dp_display_get_next_bridge(struct msm_dp *dp)
> +{
> +   int rc;
> +   struct dp_display_private *dp_priv;
> +   struct device_node *aux_bus;
> +   struct device *dev;
> +
> +   dp_priv = container_of(dp, struct dp_display_private, dp_display);
> +   dev = _priv->pdev->dev;
> +   aux_bus = of_get_child_by_name(dev->of_node, "aux-bus");
> +
> +   if (aux_bus && dp->is_edp) {
> +   dp_display_host_init(dp_priv);
> +   dp_catalog_ctrl_hpd_config(dp_priv->catalog);
> +   dp_display_host_phy_init(dp_priv);
> +   enable_irq(dp_priv->irq);
> +
> +   rc = devm_of_dp_aux_populate_ep_devices(dp_priv->aux);
> +   of_node_put(aux_bus);
> +   if (rc) {
> +   disable_irq(dp_priv->irq);
> +   dp_display_host_phy_exit(dp_priv);
> +   dp_display_host_deinit(dp_priv);
> +   return rc;
> +   }
> +   } else if (dp->is_edp) {
> +   DRM_ERROR("eDP aux_bus not found\n");
> +   return -ENODEV;
> +   }
> +
> +   /*
> +* External bridges are mandatory for eDP interfaces: one has to
> +* provide at least an eDP panel (which gets wrapped into 
> panel-bridge).
> +*
> +* For DisplayPort interfaces external bridges are optional, so
> +* silently ignore an error if one is not present (-ENODEV).
> +*/
> +   rc = dp_parser_find_next_bridge(dp_priv->parser);

This gets into the same problem that Dmitry pointed out that ps8640
has that's addressed by my recent series [1].  Namely it's not
guaranteed that the panel will have finished probing by the time
devm_of_dp_aux_populate_ep_devices() finishes probing. I don't think
it's going to be really solvable without the bigger rewrite that we've
been discussing, though. ...it's probably OK to land something like
what you have here, but it might at least deserve a comment in the
code?

[1] https://lore.kernel.org/r/20220409023628.2104952-1-diand...@chromium.org


> +   if (rc == -ENODEV) {
> +   if (dp->is_edp) {
> +   DRM_ERROR("eDP: next bridge is not present\n");
> +   return rc;
> +   }
> +   } else if (rc) {
> +   if (rc != -EPROBE_DEFER)
> +   DRM_ERROR("DP: error parsing next bridge: %d\n", rc);
> +   return rc;

In both of your two error returns here isn't it a problem that you don't do:

  disable_irq(dp_priv->irq);
  dp_display_host_phy_exit(dp_priv);
  dp_display_host_deinit(dp_priv);

Should probably at least fix that clear error before landing, unless
I'm misunderstanding and there's some reason not to do that?


As discussed previously, I'm not convinced that we've covered every
corner case for properly doing and undoing the above things. I'm
hoping that once we do the cleanup and move to pm_runtime() management
that it will be cleaned up?


> @@ -114,10 +114,12 @@ struct drm_bridge *dp_bridge_init(struct msm_dp 
> *dp_display, struct drm_device *
> bridge->funcs = _bridge_ops;
> bridge->type = dp_display->connector_type;
>
> -   bridge->ops =
> -   DRM_BRIDGE_OP_DETECT |
> -   DRM_BRIDGE_OP_HPD |
> -   DRM_BRIDGE_OP_MODES;
> +   if (!dp_display->is_edp) {
> +   bridge->ops =
> +   DRM_BRIDGE_OP_DETECT |
> +   DRM_BRIDGE_OP_HPD |
> +   DRM_BRIDGE_OP_MODES;

Given that Dmitry had questions about why eDP has different ops in his
previous review of this code, the above probably deserves an inline
code comment. If you want to use my wording, you could paste this into
your code:

  /*
   * Many ops only make sense for DP. Why?
   * - Detect/HPD are used by DRM to know if a display is _physically_
   *   there, not whether the display is powered on / finished initting.
   *   On eDP we assume the display is always there because you can't
   *   know until power is applied. If we don't implement the ops DRM will
   *   assume our display is always there.
   * - Currently eDP mode reading is driven by the panel driver. This
   *   allows the panel driver to properly power itself on to read the
   *   modes.
   */


Overall: as discussed, I think that the current implementation is a
bit fragile and might have some wrong corner cases since it's hard for
me to reason about exactly when we init/de-init things. Even if it
works great, the fact that it's hard to reason about isn't wonderful.
That being said, I honestly believe that would benefit upstream to get
this landed and iterate on it. I don't think this should be causing
any existing behavior to be 

Re: [PATCH v2] drm/msm/dp: enhance both connect and disconnect pending_timeout handle

2022-04-14 Thread Kuogee Hsieh



On 4/13/2022 5:02 PM, Stephen Boyd wrote:

The subject is still misleading. It is fixing something. It may be
enhancing it as well but it is clearly fixing it first.

Quoting Kuogee Hsieh (2022-04-06 14:28:13)

dp_hpd_plug_handle() is responsible for setting up main link and send
uevent to notify user space framework to start video stream. Similarly,
dp_hdp_unplug_handle is responsible to send uevent to notify user space
framework to stop video stream and then tear down main link.
However there are rare cases, such as in the middle of system suspending,
that uevent could not be delivered to user space framework. Therefore
some kind of recover mechanism armed by timer need to be in place in the
case of user space framework does not respond to uevent.

This patch have both dp_conenct_pending_timeout and
dp_disconnect_pending_timeout are used to stop video stream and tear down
main link and eventually restore DP driver state to known default
DISCONNECTED state in the case of timer fired due to framework does not
respond to uevent so that DP driver can recover itself gracefully at next
dongle unplug followed by plugin event.

Changes in v2:
-- replace dp_display_usbpd_disconnect_cb with dp_display_notify_disconnect

I'd prefer this part to be a different patch. It can come after the fix
to ease backporting.

Also, is there any response to Dmitry's question yet? I haven't seen
anything.


Sorry, since our internal review does not like this approach.

I will upload new patch for review soon.


diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h
index 2433edb..ffafe17 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.h
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h
@@ -22,6 +22,7 @@ struct dp_ctrl {
  int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl);
  int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl);
  int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl);
+int dp_ctrl_off_link(struct dp_ctrl *dp_ctrl);
  int dp_ctrl_off(struct dp_ctrl *dp_ctrl);
  void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl);
  void dp_ctrl_isr(struct dp_ctrl *dp_ctrl);
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 178b774..a6200a5 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -451,11 +451,14 @@ static int dp_display_usbpd_configure_cb(struct device 
*dev)

  static int dp_display_usbpd_disconnect_cb(struct device *dev)

We shouldn't need to keep around an empty function.


  {
+   return 0;
+}
+
+static void dp_display_notify_disconnect(struct device *dev)
+{
 struct dp_display_private *dp = dev_get_dp_display_private(dev);

 dp_add_event(dp, EV_USER_NOTIFICATION, false, 0);
-
-   return 0;
  }

  static void dp_display_handle_video_request(struct dp_display_private *dp)
@@ -593,10 +596,16 @@ static int dp_connect_pending_timeout(struct 
dp_display_private *dp, u32 data)

 mutex_lock(>event_mutex);

+   /*
+* main link had been setup but video is not ready yet
+* only tear down main link
+*/
 state = dp->hpd_state;
 if (state == ST_CONNECT_PENDING) {
-   dp->hpd_state = ST_CONNECTED;
 DRM_DEBUG_DP("type=%d\n", dp->dp_display.connector_type);
+   dp_ctrl_off_link(dp->ctrl);
+   dp_display_host_phy_exit(dp);
+   dp->hpd_state = ST_DISCONNECTED;
 }

 mutex_unlock(>event_mutex);
@@ -645,6 +654,7 @@ static int dp_hpd_unplug_handle(struct dp_display_private 
*dp, u32 data)
 if (dp->link->sink_count == 0) {
 dp_display_host_phy_exit(dp);
 }
+   dp_display_notify_disconnect(>pdev->dev);
 mutex_unlock(>event_mutex);
 return 0;
 }
@@ -661,19 +671,22 @@ static int dp_hpd_unplug_handle(struct dp_display_private 
*dp, u32 data)
 return 0;
 }

-   dp->hpd_state = ST_DISCONNECT_PENDING;
-
 /* disable HPD plug interrupts */
 dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK, 
false);

 /*
  * We don't need separate work for disconnect as
  * connect/attention interrupts are disabled
-*/
-   dp_display_usbpd_disconnect_cb(>pdev->dev);
+   */

This comment end is wrong. It should be unchanged.


+   dp_display_notify_disconnect(>pdev->dev);

-   /* start sentinel checking in case of missing uevent */
-   dp_add_event(dp, EV_DISCONNECT_PENDING_TIMEOUT, 0, DP_TIMEOUT_5_SECOND);
+   if (state == ST_DISPLAY_OFF) {
+   dp->hpd_state = ST_DISCONNECTED;
+   } else {
+   /* start sentinel checking in case of missing uevent */
+   dp_add_event(dp, EV_DISCONNECT_PENDING_TIMEOUT, 0, 
DP_TIMEOUT_5_SECOND);
+   dp->hpd_state = ST_DISCONNECT_PENDING;
+   }

 /* signal the disconnect event early to ensure proper teardown */
 

RE: [Intel-gfx] [PATCH] drm/i915/guc/slpc: Use i915_probe_error instead of drm_err

2022-04-14 Thread Gupta, Anshuman


> -Original Message-
> From: Belgaumkar, Vinay 
> Sent: Thursday, April 14, 2022 8:38 PM
> To: Gupta, Anshuman 
> Cc: intel-...@lists.freedesktop.org; dri-devel@lists.freedesktop.org
> Subject: Re: [Intel-gfx] [PATCH] drm/i915/guc/slpc: Use i915_probe_error
> instead of drm_err
> 
> 
> On 4/13/2022 11:41 PM, Anshuman Gupta wrote:
> > On 2022-04-13 at 04:18:52 +0530, Vinay Belgaumkar wrote:
> >> This will ensure we don't have false positives when we run error
> >> injection tests.
> >>
> >> Signed-off-by: Vinay Belgaumkar 
> >> ---
> >>   drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 42 ++---
> >>   1 file changed, 21 insertions(+), 21 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> >> b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> >> index b170238aa15c..639de3c10545 100644
> >> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> >> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> >> @@ -152,8 +152,8 @@ static int slpc_query_task_state(struct
> >> intel_guc_slpc *slpc)
> >>
> >>ret = guc_action_slpc_query(guc, offset);
> >>if (unlikely(ret))
> > As commit logs describe, this code patch can hit, when we run error 
> > injection
> test.
> > Do we need unlikely() here?
> > Br,
> > Anshuman Gupta.
> 
> I think we still need the unlikely(). Majority of the time, we still need the
> compiler optimization.
> 
> Only in the rare case of running the error injection test will it not be 
> needed.
Reviewed-by: Anshuman Gupta 
> 
> Thanks,
> 
> Vinay.
> 
> >> -  drm_err(>drm, "Failed to query task state (%pe)\n",
> >> -  ERR_PTR(ret));
> >> +  i915_probe_error(i915, "Failed to query task state (%pe)\n",
> >> +   ERR_PTR(ret));
> >>
> >>drm_clflush_virt_range(slpc->vaddr, SLPC_PAGE_SIZE_BYTES);
> >>
> >> @@ -170,8 +170,8 @@ static int slpc_set_param(struct intel_guc_slpc
> >> *slpc, u8 id, u32 value)
> >>
> >>ret = guc_action_slpc_set_param(guc, id, value);
> >>if (ret)
> >> -  drm_err(>drm, "Failed to set param %d to %u (%pe)\n",
> >> -  id, value, ERR_PTR(ret));
> >> +  i915_probe_error(i915, "Failed to set param %d to %u (%pe)\n",
> >> +   id, value, ERR_PTR(ret));
> >>
> >>return ret;
> >>   }
> >> @@ -211,8 +211,8 @@ static int slpc_force_min_freq(struct intel_guc_slpc
> *slpc, u32 freq)
> >>
> SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ,
> >> freq);
> >>if (ret)
> >> -  drm_err(>drm, "Unable to force min freq to %u:
> %d",
> >> -  freq, ret);
> >> +  i915_probe_error(i915, "Unable to force min freq to
> %u: %d",
> >> +   freq, ret);
> >>}
> >>
> >>return ret;
> >> @@ -247,9 +247,9 @@ int intel_guc_slpc_init(struct intel_guc_slpc
> >> *slpc)
> >>
> >>err = intel_guc_allocate_and_map_vma(guc, size, >vma, (void
> **)>vaddr);
> >>if (unlikely(err)) {
> >> -  drm_err(>drm,
> >> -  "Failed to allocate SLPC struct (err=%pe)\n",
> >> -  ERR_PTR(err));
> >> +  i915_probe_error(i915,
> >> +   "Failed to allocate SLPC struct (err=%pe)\n",
> >> +   ERR_PTR(err));
> >>return err;
> >>}
> >>
> >> @@ -316,15 +316,15 @@ static int slpc_reset(struct intel_guc_slpc *slpc)
> >>ret = guc_action_slpc_reset(guc, offset);
> >>
> >>if (unlikely(ret < 0)) {
> >> -  drm_err(>drm, "SLPC reset action failed (%pe)\n",
> >> -  ERR_PTR(ret));
> >> +  i915_probe_error(i915, "SLPC reset action failed (%pe)\n",
> >> +   ERR_PTR(ret));
> >>return ret;
> >>}
> >>
> >>if (!ret) {
> >>if (wait_for(slpc_is_running(slpc), SLPC_RESET_TIMEOUT_MS)) {
> >> -  drm_err(>drm, "SLPC not enabled! State = %s\n",
> >> -  slpc_get_state_string(slpc));
> >> +  i915_probe_error(i915, "SLPC not enabled! State =
> %s\n",
> >> +   slpc_get_state_string(slpc));
> >>return -EIO;
> >>}
> >>}
> >> @@ -616,8 +616,8 @@ int intel_guc_slpc_enable(struct intel_guc_slpc
> >> *slpc)
> >>
> >>ret = slpc_reset(slpc);
> >>if (unlikely(ret < 0)) {
> >> -  drm_err(>drm, "SLPC Reset event returned (%pe)\n",
> >> -  ERR_PTR(ret));
> >> +  i915_probe_error(i915, "SLPC Reset event returned (%pe)\n",
> >> +   ERR_PTR(ret));
> >>return ret;
> >>}
> >>
> >> @@ -632,24 +632,24 @@ int intel_guc_slpc_enable(struct intel_guc_slpc
> *slpc)
> >>/* Ignore efficient freq and set min to platform min */
> >>ret = slpc_ignore_eff_freq(slpc, true);
> >>if (unlikely(ret)) {
> >> -  drm_err(>drm, "Failed to set SLPC min to RPn (%pe)\n",
> >> 

Re: [Intel-gfx] [PATCH] drm/i915/guc/slpc: Use i915_probe_error instead of drm_err

2022-04-14 Thread Jani Nikula
On Thu, 14 Apr 2022, "Belgaumkar, Vinay"  wrote:
> On 4/13/2022 11:41 PM, Anshuman Gupta wrote:
>> On 2022-04-13 at 04:18:52 +0530, Vinay Belgaumkar wrote:
>>> This will ensure we don't have false positives when we run
>>> error injection tests.
>>>
>>> Signed-off-by: Vinay Belgaumkar 
>>> ---
>>>   drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 42 ++---
>>>   1 file changed, 21 insertions(+), 21 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c 
>>> b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>>> index b170238aa15c..639de3c10545 100644
>>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>>> @@ -152,8 +152,8 @@ static int slpc_query_task_state(struct intel_guc_slpc 
>>> *slpc)
>>>   
>>> ret = guc_action_slpc_query(guc, offset);
>>> if (unlikely(ret))
>> As commit logs describe, this code patch can hit, when we run error 
>> injection test.
>> Do we need unlikely() here?
>> Br,
>> Anshuman Gupta.
>
> I think we still need the unlikely(). Majority of the time, we still 
> need the compiler optimization.
>
> Only in the rare case of running the error injection test will it not be 
> needed.

IMO most uses of likely/unlikely (and inline for that matter) are
premature optimization that just shouldn't be there. They're a
distraction to human readers, and a style that all too easily gets cargo
culted all over the place. In most cases, please just let the compiler
do what it does best.

And *then* if you still need to squeeze extra cycles out of the code,
and can quantify it, by all means optimize. But in that case, maybe the
root cause is somewhere other than a missing likely/unlikely/inline?


BR,
Jani.


>
> Thanks,
>
> Vinay.
>
>>> -   drm_err(>drm, "Failed to query task state (%pe)\n",
>>> -   ERR_PTR(ret));
>>> +   i915_probe_error(i915, "Failed to query task state (%pe)\n",
>>> +ERR_PTR(ret));
>>>   
>>> drm_clflush_virt_range(slpc->vaddr, SLPC_PAGE_SIZE_BYTES);
>>>   
>>> @@ -170,8 +170,8 @@ static int slpc_set_param(struct intel_guc_slpc *slpc, 
>>> u8 id, u32 value)
>>>   
>>> ret = guc_action_slpc_set_param(guc, id, value);
>>> if (ret)
>>> -   drm_err(>drm, "Failed to set param %d to %u (%pe)\n",
>>> -   id, value, ERR_PTR(ret));
>>> +   i915_probe_error(i915, "Failed to set param %d to %u (%pe)\n",
>>> +id, value, ERR_PTR(ret));
>>>   
>>> return ret;
>>>   }
>>> @@ -211,8 +211,8 @@ static int slpc_force_min_freq(struct intel_guc_slpc 
>>> *slpc, u32 freq)
>>>  SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ,
>>>  freq);
>>> if (ret)
>>> -   drm_err(>drm, "Unable to force min freq to %u: 
>>> %d",
>>> -   freq, ret);
>>> +   i915_probe_error(i915, "Unable to force min freq to %u: 
>>> %d",
>>> +freq, ret);
>>> }
>>>   
>>> return ret;
>>> @@ -247,9 +247,9 @@ int intel_guc_slpc_init(struct intel_guc_slpc *slpc)
>>>   
>>> err = intel_guc_allocate_and_map_vma(guc, size, >vma, (void 
>>> **)>vaddr);
>>> if (unlikely(err)) {
>>> -   drm_err(>drm,
>>> -   "Failed to allocate SLPC struct (err=%pe)\n",
>>> -   ERR_PTR(err));
>>> +   i915_probe_error(i915,
>>> +"Failed to allocate SLPC struct (err=%pe)\n",
>>> +ERR_PTR(err));
>>> return err;
>>> }
>>>   
>>> @@ -316,15 +316,15 @@ static int slpc_reset(struct intel_guc_slpc *slpc)
>>> ret = guc_action_slpc_reset(guc, offset);
>>>   
>>> if (unlikely(ret < 0)) {
>>> -   drm_err(>drm, "SLPC reset action failed (%pe)\n",
>>> -   ERR_PTR(ret));
>>> +   i915_probe_error(i915, "SLPC reset action failed (%pe)\n",
>>> +ERR_PTR(ret));
>>> return ret;
>>> }
>>>   
>>> if (!ret) {
>>> if (wait_for(slpc_is_running(slpc), SLPC_RESET_TIMEOUT_MS)) {
>>> -   drm_err(>drm, "SLPC not enabled! State = %s\n",
>>> -   slpc_get_state_string(slpc));
>>> +   i915_probe_error(i915, "SLPC not enabled! State = %s\n",
>>> +slpc_get_state_string(slpc));
>>> return -EIO;
>>> }
>>> }
>>> @@ -616,8 +616,8 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
>>>   
>>> ret = slpc_reset(slpc);
>>> if (unlikely(ret < 0)) {
>>> -   drm_err(>drm, "SLPC Reset event returned (%pe)\n",
>>> -   ERR_PTR(ret));
>>> +   i915_probe_error(i915, "SLPC Reset event returned (%pe)\n",
>>> +ERR_PTR(ret));
>>> return ret;
>>> }
>>>   
>>> @@ -632,24 +632,24 @@ int 

Re: [PATCH v2 4/5] drm/i915: ttm backend dont provide mmap_offset for kernel buffers

2022-04-14 Thread Robert Beckett




On 14/04/2022 15:05, Thomas Hellström wrote:

On Tue, 2022-04-12 at 15:18 +, Robert Beckett wrote:

stolen/kernel buffers should not be mmapable by userland.
do not provide callbacks to facilitate this for these buffers.

Signed-off-by: Robert Beckett 
---
  drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 32 +--
--
  1 file changed, 27 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
index a878910a563c..b20f81836c54 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -1092,8 +1092,8 @@ static void i915_ttm_unmap_virtual(struct
drm_i915_gem_object *obj)
 ttm_bo_unmap_virtual(i915_gem_to_ttm(obj));
  }
  
-static const struct drm_i915_gem_object_ops i915_gem_ttm_obj_ops = {

-   .name = "i915_gem_object_ttm",
+static const struct drm_i915_gem_object_ops
i915_gem_ttm_user_obj_ops = {
+   .name = "i915_gem_object_ttm_user",
 .flags = I915_GEM_OBJECT_IS_SHRINKABLE |
  I915_GEM_OBJECT_SELF_MANAGED_SHRINK_LIST,
  
@@ -,6 +,21 @@ static const struct drm_i915_gem_object_ops

i915_gem_ttm_obj_ops = {
 .mmap_ops = _ops_ttm,
  };
  
+static const struct drm_i915_gem_object_ops

i915_gem_ttm_kern_obj_ops = {
+   .name = "i915_gem_object_ttm_kern",
+   .flags = I915_GEM_OBJECT_IS_SHRINKABLE |
+    I915_GEM_OBJECT_SELF_MANAGED_SHRINK_LIST,
+
+   .get_pages = i915_ttm_get_pages,
+   .put_pages = i915_ttm_put_pages,
+   .truncate = i915_ttm_truncate,
+   .shrink = i915_ttm_shrink,
+
+   .adjust_lru = i915_ttm_adjust_lru,
+   .delayed_free = i915_ttm_delayed_free,
+   .migrate = i915_ttm_migrate,
+};


Do we really need two different ops here?

Since if we don't have mmap ops, basically that tells GEM it should do
the mmapping rather than TTM.

That might of course come in handy for the shmem backend, but I don't
fully follow why we need this for stolen.


the main rationale for doing this was to avoid 
drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c:can_mmap() presuming 
that is can use I915_MMAP_TYPE_FIXED


As the original backend also did not have mmap_offset handlers for 
stolen, this seemed like a reasonable design.


If desired, we could add a special case for the testing logic, but those 
special cases have tendency to multiply.




Also for the framebuffer handed over from BIOS to fbdev, Does that need
mmapping and if so, how do we handle that?



I'm not sure of the usecase there. Do you know of any igt test that 
tests this? I can investigate further if you do not.




/Thomas





+
  void i915_ttm_bo_destroy(struct ttm_buffer_object *bo)
  {
 struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
@@ -1165,10 +1180,19 @@ int __i915_gem_ttm_object_init(struct
intel_memory_region *mem,
 .no_wait_gpu = false,
 };
 enum ttm_bo_type bo_type;
+   const struct drm_i915_gem_object_ops *ops;
 int ret;
  
 drm_gem_private_object_init(>drm, >base, size);

-   i915_gem_object_init(obj, _gem_ttm_obj_ops, _class,
flags);
+
+   if (flags & I915_BO_ALLOC_USER &&
intel_region_to_ttm_type(mem) != I915_PL_STOLEN) {
+   bo_type = ttm_bo_type_device;
+   ops = _gem_ttm_user_obj_ops;
+   } else {
+   bo_type = ttm_bo_type_kernel;
+   ops = _gem_ttm_kern_obj_ops;
+   }
+   i915_gem_object_init(obj, ops, _class, flags);
  
 obj->bo_offset = offset;
  
@@ -1178,8 +1202,6 @@ int __i915_gem_ttm_object_init(struct

intel_memory_region *mem,
  
 INIT_RADIX_TREE(>ttm.get_io_page.radix, GFP_KERNEL |

__GFP_NOWARN);
 mutex_init(>ttm.get_io_page.lock);
-   bo_type = (obj->flags & I915_BO_ALLOC_USER) ?
ttm_bo_type_device :
-   ttm_bo_type_kernel;
  
 obj->base.vma_node.driver_private = i915_gem_to_ttm(obj);
  





Re: [PATCH v5 00/10] drm/hdcp: Pull HDCP auth/exchange/check into helpers

2022-04-14 Thread Sean Paul
On Tue, Apr 12, 2022 at 09:41:35AM -0400, Rodrigo Vivi wrote:
> On Mon, Apr 11, 2022 at 08:47:29PM +, Sean Paul wrote:
> > From: Sean Paul 
> > 
> > Rebased set from November. Fixed a nit from Stephen in the msm patch and
> > moved hdcp registers into the trogdor dtsi file to avoid differences
> > with sc7180-based windows devices. The set is 4 patches lighter since
> > some of the changes were accepted into msm.
> > 
> > I'm still waiting for Intel review of the first 7 patches. Rodrigo/Jani,
> > would you please provide your input so we can move forward with this
> > set?
> 
> I'm a bit concerned with patches 4 and 7. It is hard to map the removals
> and additions and there are some changes that looks like changing behaviors,
> but end up not being clear in the big patch. Also with big patch it is prune
> to the rebasing and backport conflicts.

I had the same concerns when I was writing this. I originally had it split up,
but it seemed really cluttered with 2 sets of helpers (intel-internal + drm)
that worked slightly differently.

I'll try again now that some time has passed, perhaps a fresh look will help.

Sean

> 
> Would be possible to split some work in moving individual functions from i915
> to drm little by little with smaller patches?
> 
> But thank you for this great work. It is also good to align our drm drivers.
> 
> Thanks,
> Rodrigo.
> 
> > 
> > Thanks,
> > 
> > Sean
> > 
> > Link: https://patchwork.freedesktop.org/series/94623/ #v1
> > Link: https://patchwork.freedesktop.org/series/94713/ #v2
> > Link: https://patchwork.freedesktop.org/series/94712/ #v3
> > Link: https://patchwork.freedesktop.org/series/94712/ #v4
> > 
> > Sean Paul (10):
> >   drm/hdcp: Add drm_hdcp_atomic_check()
> >   drm/hdcp: Avoid changing crtc state in hdcp atomic check
> >   drm/hdcp: Update property value on content type and user changes
> >   drm/hdcp: Expand HDCP helper library for enable/disable/check
> >   drm/i915/hdcp: Consolidate HDCP setup/state cache
> >   drm/i915/hdcp: Retain hdcp_capable return codes
> >   drm/i915/hdcp: Use HDCP helpers for i915
> >   dt-bindings: msm/dp: Add bindings for HDCP registers
> >   arm64: dts: qcom: sc7180: Add support for HDCP in dp-controller
> >   drm/msm: Implement HDCP 1.x using the new drm HDCP helpers
> > 
> >  .../bindings/display/msm/dp-controller.yaml   |7 +-
> >  arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi  |8 +
> >  arch/arm64/boot/dts/qcom/sc7180.dtsi  |6 +-
> >  drivers/gpu/drm/drm_hdcp.c| 1197 -
> >  drivers/gpu/drm/i915/display/intel_atomic.c   |7 +-
> >  drivers/gpu/drm/i915/display/intel_ddi.c  |   29 +-
> >  .../drm/i915/display/intel_display_debugfs.c  |   11 +-
> >  .../drm/i915/display/intel_display_types.h|   58 +-
> >  drivers/gpu/drm/i915/display/intel_dp_hdcp.c  |  345 ++---
> >  drivers/gpu/drm/i915/display/intel_dp_mst.c   |   17 +-
> >  drivers/gpu/drm/i915/display/intel_hdcp.c | 1011 +++---
> >  drivers/gpu/drm/i915/display/intel_hdcp.h |   36 +-
> >  drivers/gpu/drm/i915/display/intel_hdmi.c |  256 ++--
> >  drivers/gpu/drm/msm/Makefile  |1 +
> >  drivers/gpu/drm/msm/dp/dp_debug.c |   46 +-
> >  drivers/gpu/drm/msm/dp/dp_debug.h |6 +-
> >  drivers/gpu/drm/msm/dp/dp_display.c   |   46 +-
> >  drivers/gpu/drm/msm/dp/dp_display.h   |5 +
> >  drivers/gpu/drm/msm/dp/dp_drm.c   |   68 +-
> >  drivers/gpu/drm/msm/dp/dp_drm.h   |5 +
> >  drivers/gpu/drm/msm/dp/dp_hdcp.c  |  453 +++
> >  drivers/gpu/drm/msm/dp/dp_hdcp.h  |   27 +
> >  drivers/gpu/drm/msm/dp/dp_parser.c|   20 +-
> >  drivers/gpu/drm/msm/dp/dp_parser.h|4 +
> >  drivers/gpu/drm/msm/dp/dp_reg.h   |   32 +-
> >  drivers/gpu/drm/msm/msm_atomic.c  |   15 +
> >  include/drm/drm_hdcp.h|  194 +++
> >  27 files changed, 2582 insertions(+), 1328 deletions(-)
> >  create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.c
> >  create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.h
> > 
> > -- 
> > Sean Paul, Software Engineer, Google / Chromium OS
> > 

-- 
Sean Paul, Software Engineer, Google / Chromium OS


Re: [PATCH v5 03/10] drm/hdcp: Update property value on content type and user changes

2022-04-14 Thread Sean Paul
On Tue, Apr 12, 2022 at 09:25:59AM -0400, Rodrigo Vivi wrote:
> On Mon, Apr 11, 2022 at 08:47:32PM +, Sean Paul wrote:
> > From: Sean Paul 
> > 
> > This patch updates the connector's property value in 2 cases which were
> > previously missed:
> > 
> > 1- Content type changes. The value should revert back to DESIRED from
> >ENABLED in case the driver must re-authenticate the link due to the
> >new content type.
> > 
> > 2- Userspace sets value to DESIRED while ENABLED. In this case, the
> >value should be reset immediately to ENABLED since the link is
> >actively being encrypted.
> > 
> > To accommodate these changes, I've split up the conditionals to make
> > things a bit more clear (as much as one can with this mess of state).
> > 
> > Acked-by: Jani Nikula 
> > Reviewed-by: Abhinav Kumar 
> > Signed-off-by: Sean Paul 
> > Link: 
> > https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-4-s...@poorly.run
> >  #v1
> > Link: 
> > https://patchwork.freedesktop.org/patch/msgid/20210915203834.1439-4-s...@poorly.run
> >  #v2
> > Link: 
> > https://patchwork.freedesktop.org/patch/msgid/20211001151145.55916-4-s...@poorly.run
> >  #v3
> > Link: 
> > https://patchwork.freedesktop.org/patch/msgid/20211105030434.2828845-4-s...@poorly.run
> >  #v4
> > 
> > Changes in v2:
> > -None
> > Changes in v3:
> > -Fixed indentation issue identified by 0-day
> > Changes in v4:
> > -None
> > Changes in v5:
> > -None
> > ---
> >  drivers/gpu/drm/drm_hdcp.c | 26 +-
> >  1 file changed, 17 insertions(+), 9 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/drm_hdcp.c b/drivers/gpu/drm/drm_hdcp.c
> > index dd8fa91c51d6..8c851d40cd45 100644
> > --- a/drivers/gpu/drm/drm_hdcp.c
> > +++ b/drivers/gpu/drm/drm_hdcp.c
> > @@ -487,21 +487,29 @@ bool drm_hdcp_atomic_check(struct drm_connector 
> > *connector,
> > return true;
> >  
> > /*
> > -* Nothing to do if content type is unchanged and one of:
> > -*  - state didn't change
> > +* Content type changes require an HDCP disable/enable cycle.
> > +*/
> > +   if (new_conn_state->hdcp_content_type != 
> > old_conn_state->hdcp_content_type) {
> 
> shouldn't we add some && ( old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED)) {
> here?

Thanks for your reviews Rodrigo.

I don't think so since the content type is changing the current state of old
content protection is immaterial (ie: if we need to enable HDCP 2.x, the state
of HDCP 1.x doesn't really matter), we need to re-evaluate whether the current
level of HDCP is sufficient.

Hopefully that makes sense, but I could be missing something :-)

Sean

> 
> > +   new_conn_state->content_protection =
> > +   DRM_MODE_CONTENT_PROTECTION_DESIRED;
> > +   return true;
> > +   }
> > +
> > +   /*
> > +* Ignore meaningless state changes:
> >  *  - HDCP was activated since the last commit
> > -*  - attempting to set to desired while already enabled
> > +*  - Attempting to set to desired while already enabled
> >  */
> > -   if (old_hdcp == new_hdcp ||
> > -   (old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED &&
> > +   if ((old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED &&
> >  new_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) ||
> > (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED &&
> >  new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED)) {
> > -   if (old_conn_state->hdcp_content_type ==
> > -   new_conn_state->hdcp_content_type)
> > -   return false;
> > +   new_conn_state->content_protection =
> > +   DRM_MODE_CONTENT_PROTECTION_ENABLED;
> > +   return false;
> > }
> >  
> > -   return true;
> > +   /* Finally, if state changes, we need action */
> > +   return old_hdcp != new_hdcp;
> >  }
> >  EXPORT_SYMBOL(drm_hdcp_atomic_check);
> > -- 
> > Sean Paul, Software Engineer, Google / Chromium OS
> > 

-- 
Sean Paul, Software Engineer, Google / Chromium OS


Re: [PATCH v18 07/10] drm/mediatek: add mediatek-drm of vdosys0 support for mt8195

2022-04-14 Thread kernel test robot
Hi "jason-jh.lin",

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on drm/drm-next]
[also build test WARNING on robh/for-next krzk/for-next linus/master v5.18-rc2 
next-20220414]
[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/intel-lab-lkp/linux/commits/jason-jh-lin/Add-Mediatek-Soc-DRM-vdosys0-support-for-mt8195/20220412-183359
base:   git://anongit.freedesktop.org/drm/drm drm-next
config: arm64-buildonly-randconfig-r001-20220413 
(https://download.01.org/0day-ci/archive/20220414/202204142333.qxgcgmi1-...@intel.com/config)
compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project 
6b7e6ea489f6dd45a9b0da9ac20871560917b9b0)
reproduce (this is a W=1 build):
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# install arm64 cross compiling tool for clang build
# apt-get install binutils-aarch64-linux-gnu
# 
https://github.com/intel-lab-lkp/linux/commit/7c175317aa80bbc885609a730214448147a46b47
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review 
jason-jh-lin/Add-Mediatek-Soc-DRM-vdosys0-support-for-mt8195/20220412-183359
git checkout 7c175317aa80bbc885609a730214448147a46b47
# save the config file to linux build tree
mkdir build_dir
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 
O=build_dir ARCH=arm64 SHELL=/bin/bash drivers/gpu/drm/mediatek/

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

All warnings (new ones prefixed by >>):

   drivers/gpu/drm/mediatek/mtk_drm_drv.c:707:15: warning: cast to smaller 
integer type 'enum mtk_ddp_comp_type' from 'const void *' 
[-Wvoid-pointer-to-enum-cast]
   comp_type = (enum mtk_ddp_comp_type)of_id->data;
   ^~~
>> drivers/gpu/drm/mediatek/mtk_drm_drv.c:203:42: warning: unused variable 
>> 'mt2701_mmsys_match_data' [-Wunused-const-variable]
   static const struct mtk_mmsys_match_data mt2701_mmsys_match_data = {
^
>> drivers/gpu/drm/mediatek/mtk_drm_drv.c:218:42: warning: unused variable 
>> 'mt7623_mmsys_match_data' [-Wunused-const-variable]
   static const struct mtk_mmsys_match_data mt7623_mmsys_match_data = {
^
>> drivers/gpu/drm/mediatek/mtk_drm_drv.c:234:42: warning: unused variable 
>> 'mt2712_mmsys_match_data' [-Wunused-const-variable]
   static const struct mtk_mmsys_match_data mt2712_mmsys_match_data = {
^
>> drivers/gpu/drm/mediatek/mtk_drm_drv.c:246:42: warning: unused variable 
>> 'mt8167_mmsys_match_data' [-Wunused-const-variable]
   static const struct mtk_mmsys_match_data mt8167_mmsys_match_data = {
^
>> drivers/gpu/drm/mediatek/mtk_drm_drv.c:260:42: warning: unused variable 
>> 'mt8173_mmsys_match_data' [-Wunused-const-variable]
   static const struct mtk_mmsys_match_data mt8173_mmsys_match_data = {
^
>> drivers/gpu/drm/mediatek/mtk_drm_drv.c:274:42: warning: unused variable 
>> 'mt8183_mmsys_match_data' [-Wunused-const-variable]
   static const struct mtk_mmsys_match_data mt8183_mmsys_match_data = {
^
>> drivers/gpu/drm/mediatek/mtk_drm_drv.c:288:42: warning: unused variable 
>> 'mt8192_mmsys_match_data' [-Wunused-const-variable]
   static const struct mtk_mmsys_match_data mt8192_mmsys_match_data = {
^
>> drivers/gpu/drm/mediatek/mtk_drm_drv.c:305:42: warning: unused variable 
>> 'mt8195_mmsys_match_data' [-Wunused-const-variable]
   static const struct mtk_mmsys_match_data mt8195_mmsys_match_data = {
^
   9 warnings generated.


vim +/mt2701_mmsys_match_data +203 drivers/gpu/drm/mediatek/mtk_drm_drv.c

   202  
 > 203  static const struct mtk_mmsys_match_data mt2701_mmsys_match_data = {
   204  .num_drv_data = 1,
   205  .drv_data = {
   206  _mmsys_driver_data,
   207  },
   208  };
   209  
   210  static const struct mtk_mmsys_driver_data mt7623_mmsys_driver_data = {
   211  .main_path = mt7623_mtk_ddp_main,
   212  .main_len = ARRAY_SIZE(mt7623_mtk_ddp_main),
   213  .ext_path = mt7623_mtk_ddp_ext,
   214  .ext_len = ARRAY_SIZE(mt7623_mtk_ddp_ext),
   215  .shadow_register = true,
   216  };
   217  
 > 218  static const struct

Re: [PATCH] drm/radeon: Add build directory to include path

2022-04-14 Thread Masahiro Yamada
Hi.

On Thu, Apr 14, 2022 at 10:50 PM Michel Dänzer
 wrote:
>
> On 2022-04-14 15:34, Alex Deucher wrote:
> > On Thu, Apr 14, 2022 at 4:44 AM Christian König
> >  wrote:
> >> Am 14.04.22 um 09:37 schrieb Michel Dänzer:
> >>> On 2022-04-14 08:24, Christian König wrote:
>  Am 13.04.22 um 18:14 schrieb Michel Dänzer:
> > From: Michel Dänzer 
> >
> > Fixes compile errors with out-of-tree builds, e.g.
> >
> > ../drivers/gpu/drm/radeon/r420.c:38:10: fatal error: r420_reg_safe.h: 
> > No such file or directory
> >  38 | #include "r420_reg_safe.h"
> > |  ^
> 
>  Well stuff like that usually points to a broken build environment.
> >>> Just a separate build directory. Specifically, I'm hitting the errors with
> >>>
> >>>   make -C build-amd64 M=drivers/gpu/drm


Maybe

make  O=build-arm64   drivers/gpu/drm/

is the way you were searching for.

It builds only drivers/gpu/drm/
in the separate directory.




> >>>
> >>> Generated headers such as r420_reg_safe.h reside in the build directory, 
> >>> so source files in the source directory can't find them without an 
> >>> explicit search path.
> >>
> >> I'm trying to swap back into my brain how all of this used to work, but
> >> that's a really long time ago that I tried this as well.
> >>
> >>> Are you saying that should get added automagically somehow?


For the kernel tree, yes, it is done automatically.

See the code in scripts/Makefile.lib:

# $(srctree)/$(src) for including checkin headers from generated source files
# $(objtree)/$(obj) for including generated headers from checkin source files
ifeq ($(KBUILD_EXTMOD),)
ifdef building_out_of_srctree
_c_flags   += -I $(srctree)/$(src) -I $(objtree)/$(obj)
_a_flags   += -I $(srctree)/$(src) -I $(objtree)/$(obj)
_cpp_flags += -I $(srctree)/$(src) -I $(objtree)/$(obj)
endif
endif




But, you used M=drivers/gpu/drm.
So, it did not work.



M= is intended for building external modules.

I do not recommend it for in-tree drivers.






> >>
> >> Yes, exactly that. I'm like 95% sure that used to work, but I don't know
> >> why exactly either.
> >>
> >>> FWIW, this is pretty common in the kernel according to git grep.
> >>
> >> Maybe Alex or somebody else with some more background in the kernel
> >> Makefiles could jump in and help here.
> >
> > I don't remember either.  I vaguely recall the build support for the
> > mkregtable stuff being reworked a while ago.  A quick zip through the
> > git logs shows a series from Masahiro Yamada from 2020.
>
> Yamada-san, can you help us? :)
>
> See https://patchwork.freedesktop.org/patch/482011/ for my patch.
>
>
> --
> Earthling Michel Dänzer|  https://redhat.com
> Libre software enthusiast  | Mesa and Xwayland developer



--
Best Regards
Masahiro Yamada


[PATCH 19/19] drm/edid: sunset drm_find_cea_extension()

2022-04-14 Thread Jani Nikula
Convert drm_find_cea_extension() to a predicate function to check if the
EDID has a CTA extension or a DisplayID CTA data block. This is mainly
to avoid adding new users that only find the first CTA extension.

Cc: Ville Syrjälä 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_edid.c | 19 +--
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index ccd7d075eeb8..4eeea4212f3a 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -3582,30 +3582,29 @@ const u8 *drm_find_edid_extension(const struct edid 
*edid,
return edid_ext;
 }
 
-static const u8 *drm_find_cea_extension(const struct edid *edid)
+/* Return true if the EDID has a CTA extension or a DisplayID CTA data block */
+static bool drm_edid_has_cta_extension(const struct edid *edid)
 {
const struct displayid_block *block;
struct displayid_iter iter;
-   const u8 *cea;
int ext_index = 0;
+   bool found = false;
 
/* Look for a top level CEA extension block */
-   /* FIXME: make callers iterate through multiple CEA ext blocks? */
-   cea = drm_find_edid_extension(edid, CEA_EXT, _index);
-   if (cea)
-   return cea;
+   if (drm_find_edid_extension(edid, CEA_EXT, _index))
+   return true;
 
/* CEA blocks can also be found embedded in a DisplayID block */
displayid_iter_edid_begin(edid, );
displayid_iter_for_each(block, ) {
if (block->tag == DATA_BLOCK_CTA) {
-   cea = (const u8 *)block;
+   found = true;
break;
}
}
displayid_iter_end();
 
-   return cea;
+   return found;
 }
 
 static __always_inline const struct drm_display_mode *cea_mode_for_vic(u8 vic)
@@ -3878,8 +3877,8 @@ add_alternate_cea_modes(struct drm_connector *connector, 
const struct edid *edid
LIST_HEAD(list);
int modes = 0;
 
-   /* Don't add CEA modes if the CEA extension block is missing */
-   if (!drm_find_cea_extension(edid))
+   /* Don't add CTA modes if the CTA extension block is missing */
+   if (!drm_edid_has_cta_extension(edid))
return 0;
 
/*
-- 
2.30.2



[PATCH 18/19] drm/edid: skip CTA extension scan in drm_edid_to_eld() just for CTA rev

2022-04-14 Thread Jani Nikula
The DisplayID CTA data block version does not necessarily match the CTA
revision. Simplify by postponing drm_edid_to_eld() slightly, and reusing
the CTA revision extracted by drm_parse_cea_ext().

By not bailing out early in drm_edid_to_eld() we may end up filling
meaningless data to the ELD. However, the main decision for audio is not
the ELD, but rather drm_detect_monitor_audio() called by drivers.

(Arguably a future cleanup could do that in drm_add_edid_modes() and
cache the result in the connector.)

Cc: Ville Syrjälä 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_edid.c | 15 +--
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index fad9fd13937b..ccd7d075eeb8 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -4887,10 +4887,10 @@ static void clear_eld(struct drm_connector *connector)
 static void drm_edid_to_eld(struct drm_connector *connector,
const struct edid *edid)
 {
+   const struct drm_display_info *info = >display_info;
const struct cea_db *db;
struct cea_db_iter iter;
uint8_t *eld = connector->eld;
-   const u8 *cea;
int total_sad_count = 0;
int mnl;
 
@@ -4899,16 +4899,10 @@ static void drm_edid_to_eld(struct drm_connector 
*connector,
if (!edid)
return;
 
-   cea = drm_find_cea_extension(edid);
-   if (!cea) {
-   DRM_DEBUG_KMS("ELD: no CEA Extension found\n");
-   return;
-   }
-
mnl = get_monitor_name(edid, [DRM_ELD_MONITOR_NAME_STRING]);
DRM_DEBUG_KMS("ELD monitor %s\n", [DRM_ELD_MONITOR_NAME_STRING]);
 
-   eld[DRM_ELD_CEA_EDID_VER_MNL] = cea[1] << DRM_ELD_CEA_EDID_VER_SHIFT;
+   eld[DRM_ELD_CEA_EDID_VER_MNL] = info->cea_rev << 
DRM_ELD_CEA_EDID_VER_SHIFT;
eld[DRM_ELD_CEA_EDID_VER_MNL] |= mnl;
 
eld[DRM_ELD_VER] = DRM_ELD_VER_CEA861D;
@@ -5847,8 +5841,6 @@ static int drm_edid_connector_update(struct drm_connector 
*connector,
return 0;
}
 
-   drm_edid_to_eld(connector, edid);
-
/*
 * CEA-861-F adds ycbcr capability map block, for HDMI 2.0 sinks.
 * To avoid multiple parsing of same block, lets parse that map
@@ -5856,6 +5848,9 @@ static int drm_edid_connector_update(struct drm_connector 
*connector,
 */
quirks = drm_add_display_info(connector, edid);
 
+   /* Depends on info->cea_rev set by drm_add_display_info() above */
+   drm_edid_to_eld(connector, edid);
+
/*
 * EDID spec says modes should be preferred in this order:
 * - preferred detailed mode
-- 
2.30.2



[PATCH 17/19] drm/edid: detect color formats and CTA revision in all CTA extensions

2022-04-14 Thread Jani Nikula
Convert drm_find_cea_extension() to EDID block iterator in color format
and CTA revision detection. Detect them in all CTA extensions.

Also parse CTA Data Blocks in DisplayID even if there's no CTA EDID
extension.

Cc: Ville Syrjälä 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_edid.c | 24 
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 091f68102f77..fad9fd13937b 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -5470,32 +5470,40 @@ static void drm_parse_cea_ext(struct drm_connector 
*connector,
  const struct edid *edid)
 {
struct drm_display_info *info = >display_info;
+   struct drm_edid_iter edid_iter;
const struct cea_db *db;
struct cea_db_iter iter;
const u8 *edid_ext;
 
-   edid_ext = drm_find_cea_extension(edid);
-   if (!edid_ext)
-   return;
+   drm_edid_iter_begin(edid, _iter);
+   drm_edid_iter_for_each(edid_ext, _iter) {
+   if (edid_ext[0] != CEA_EXT)
+   continue;
 
-   info->cea_rev = edid_ext[1];
+   if (!info->cea_rev)
+   info->cea_rev = edid_ext[1];
 
-   /* The existence of a CEA block should imply RGB support */
-   info->color_formats = DRM_COLOR_FORMAT_RGB444;
+   if (info->cea_rev != edid_ext[1])
+   DRM_DEBUG_KMS("CEA extension version mismatch %u != 
%u\n",
+ info->cea_rev, edid_ext[1]);
 
-   /* CTA DisplayID Data Block does not have byte #3 */
-   if (edid_ext[0] == CEA_EXT) {
+   /* The existence of a CTA extension should imply RGB support */
+   info->color_formats = DRM_COLOR_FORMAT_RGB444;
if (edid_ext[3] & EDID_CEA_YCRCB444)
info->color_formats |= DRM_COLOR_FORMAT_YCBCR444;
if (edid_ext[3] & EDID_CEA_YCRCB422)
info->color_formats |= DRM_COLOR_FORMAT_YCBCR422;
}
+   drm_edid_iter_end(_iter);
 
cea_db_iter_edid_begin(edid, );
cea_db_iter_for_each(db, ) {
/* FIXME: convert parsers to use struct cea_db */
const u8 *data = (const u8 *)db;
 
+   /* The existence of a CTA block should imply RGB support */
+   info->color_formats = DRM_COLOR_FORMAT_RGB444;
+
if (cea_db_is_hdmi_vsdb(db))
drm_parse_hdmi_vsdb_video(connector, data);
if (cea_db_is_hdmi_forum_vsdb(db) ||
-- 
2.30.2



[PATCH 16/19] drm/edid: detect basic audio in all CEA extensions

2022-04-14 Thread Jani Nikula
Convert drm_find_cea_extension() to EDID block iterator in basic audio
detection. Detect basic audio in all CEA extensions.

Cc: Ville Syrjälä 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_edid.c | 16 ++--
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 1fc4e8754cd4..091f68102f77 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -5136,17 +5136,21 @@ EXPORT_SYMBOL(drm_detect_hdmi_monitor);
  */
 bool drm_detect_monitor_audio(const struct edid *edid)
 {
+   struct drm_edid_iter edid_iter;
const struct cea_db *db;
struct cea_db_iter iter;
const u8 *edid_ext;
bool has_audio = false;
 
-   edid_ext = drm_find_cea_extension(edid);
-   if (!edid_ext)
-   goto end;
-
-   has_audio = (edid_ext[0] == CEA_EXT &&
-   (edid_ext[3] & EDID_BASIC_AUDIO) != 0);
+   drm_edid_iter_begin(edid, _iter);
+   drm_edid_iter_for_each(edid_ext, _iter) {
+   if (edid_ext[0] == CEA_EXT) {
+   has_audio = edid_ext[3] & EDID_BASIC_AUDIO;
+   if (has_audio)
+   break;
+   }
+   }
+   drm_edid_iter_end(_iter);
 
if (has_audio) {
DRM_DEBUG_KMS("Monitor has basic audio support\n");
-- 
2.30.2



[PATCH 15/19] drm/edid: restore some type safety to cea_db_*() functions

2022-04-14 Thread Jani Nikula
During the transition, we accepted a void pointer for a poor C
programmer's version of polymorphism. Switch the functions to use struct
cea_db * to regain some more type safety.

Cc: Ville Syrjälä 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_edid.c | 21 +
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 7ed0258c0edf..1fc4e8754cd4 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -4408,11 +4408,8 @@ struct cea_db {
u8 data[];
 } __packed;
 
-static int cea_db_tag(const void *_db)
+static int cea_db_tag(const struct cea_db *db)
 {
-   /* FIXME: Transition to passing struct cea_db * everywhere. */
-   const struct cea_db *db = _db;
-
return db->tag_length >> 5;
 }
 
@@ -4579,47 +4576,47 @@ static void cea_db_iter_end(struct cea_db_iter *iter)
memset(iter, 0, sizeof(*iter));
 }
 
-static bool cea_db_is_hdmi_vsdb(const void *db)
+static bool cea_db_is_hdmi_vsdb(const struct cea_db *db)
 {
return cea_db_is_vendor(db, HDMI_IEEE_OUI) &&
cea_db_payload_len(db) >= 5;
 }
 
-static bool cea_db_is_hdmi_forum_vsdb(const void *db)
+static bool cea_db_is_hdmi_forum_vsdb(const struct cea_db *db)
 {
return cea_db_is_vendor(db, HDMI_FORUM_IEEE_OUI) &&
cea_db_payload_len(db) >= 7;
 }
 
-static bool cea_db_is_microsoft_vsdb(const void *db)
+static bool cea_db_is_microsoft_vsdb(const struct cea_db *db)
 {
return cea_db_is_vendor(db, MICROSOFT_IEEE_OUI) &&
cea_db_payload_len(db) == 21;
 }
 
-static bool cea_db_is_vcdb(const void *db)
+static bool cea_db_is_vcdb(const struct cea_db *db)
 {
return cea_db_is_extended_tag(db, CTA_EXT_DB_VIDEO_CAP) &&
cea_db_payload_len(db) == 2;
 }
 
-static bool cea_db_is_hdmi_forum_scdb(const void *db)
+static bool cea_db_is_hdmi_forum_scdb(const struct cea_db *db)
 {
return cea_db_is_extended_tag(db, CTA_EXT_DB_HF_SCDB) &&
cea_db_payload_len(db) >= 7;
 }
 
-static bool cea_db_is_y420cmdb(const void *db)
+static bool cea_db_is_y420cmdb(const struct cea_db *db)
 {
return cea_db_is_extended_tag(db, CTA_EXT_DB_420_VIDEO_CAP_MAP);
 }
 
-static bool cea_db_is_y420vdb(const void *db)
+static bool cea_db_is_y420vdb(const struct cea_db *db)
 {
return cea_db_is_extended_tag(db, CTA_EXT_DB_420_VIDEO_DATA);
 }
 
-static bool cea_db_is_hdmi_hdr_metadata_block(const void *db)
+static bool cea_db_is_hdmi_hdr_metadata_block(const struct cea_db *db)
 {
return cea_db_is_extended_tag(db, CTA_EXT_DB_HDR_STATIC_METADATA) &&
cea_db_payload_len(db) >= 3;
-- 
2.30.2



[PATCH 12/19] drm/edid: convert drm_parse_cea_ext() to use cea db iter

2022-04-14 Thread Jani Nikula
Iterate through all CTA data blocks across all CTA Extensions and
DisplayID data blocks.

Cc: Ville Syrjälä 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_edid.c | 25 +
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index e47bbcd103e6..91f15b561d78 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -5520,8 +5520,9 @@ static void drm_parse_cea_ext(struct drm_connector 
*connector,
  const struct edid *edid)
 {
struct drm_display_info *info = >display_info;
+   const struct cea_db *db;
+   struct cea_db_iter iter;
const u8 *edid_ext;
-   int i, start, end;
 
edid_ext = drm_find_cea_extension(edid);
if (!edid_ext)
@@ -5540,26 +5541,26 @@ static void drm_parse_cea_ext(struct drm_connector 
*connector,
info->color_formats |= DRM_COLOR_FORMAT_YCBCR422;
}
 
-   if (cea_db_offsets(edid_ext, , ))
-   return;
-
-   for_each_cea_db(edid_ext, i, start, end) {
-   const u8 *db = _ext[i];
+   cea_db_iter_edid_begin(edid, );
+   cea_db_iter_for_each(db, ) {
+   /* FIXME: convert parsers to use struct cea_db */
+   const u8 *data = (const u8 *)db;
 
if (cea_db_is_hdmi_vsdb(db))
-   drm_parse_hdmi_vsdb_video(connector, db);
+   drm_parse_hdmi_vsdb_video(connector, data);
if (cea_db_is_hdmi_forum_vsdb(db) ||
cea_db_is_hdmi_forum_scdb(db))
-   drm_parse_hdmi_forum_vsdb(connector, db);
+   drm_parse_hdmi_forum_vsdb(connector, data);
if (cea_db_is_microsoft_vsdb(db))
-   drm_parse_microsoft_vsdb(connector, db);
+   drm_parse_microsoft_vsdb(connector, data);
if (cea_db_is_y420cmdb(db))
-   drm_parse_y420cmdb_bitmap(connector, db);
+   drm_parse_y420cmdb_bitmap(connector, data);
if (cea_db_is_vcdb(db))
-   drm_parse_vcdb(connector, db);
+   drm_parse_vcdb(connector, data);
if (cea_db_is_hdmi_hdr_metadata_block(db))
-   drm_parse_hdr_metadata_block(connector, db);
+   drm_parse_hdr_metadata_block(connector, data);
}
+   cea_db_iter_end();
 }
 
 static
-- 
2.30.2



[PATCH 14/19] drm/edid: sunset the old unused cea data block iterators

2022-04-14 Thread Jani Nikula
All CTA data block iteration has now been converted to the new cea db
iterators.

Cc: Ville Syrjälä 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_edid.c | 45 --
 1 file changed, 45 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index fa7f2bf68da3..7ed0258c0edf 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -4373,48 +4373,6 @@ cea_revision(const u8 *cea)
return cea[1];
 }
 
-static int
-cea_db_offsets(const u8 *cea, int *start, int *end)
-{
-   /* DisplayID CTA extension blocks and top-level CEA EDID
-* block header definitions differ in the following bytes:
-*   1) Byte 2 of the header specifies length differently,
-*   2) Byte 3 is only present in the CEA top level block.
-*
-* The different definitions for byte 2 follow.
-*
-* DisplayID CTA extension block defines byte 2 as:
-*   Number of payload bytes
-*
-* CEA EDID block defines byte 2 as:
-*   Byte number (decimal) within this block where the 18-byte
-*   DTDs begin. If no non-DTD data is present in this extension
-*   block, the value should be set to 04h (the byte after next).
-*   If set to 00h, there are no DTDs present in this block and
-*   no non-DTD data.
-*/
-   if (cea[0] == DATA_BLOCK_CTA) {
-   /*
-* for_each_displayid_db() has already verified
-* that these stay within expected bounds.
-*/
-   *start = 3;
-   *end = *start + cea[2];
-   } else if (cea[0] == CEA_EXT) {
-   /* Data block offset in CEA extension block */
-   *start = 4;
-   *end = cea[2];
-   if (*end == 0)
-   *end = 127;
-   if (*end < 4 || *end > 127)
-   return -ERANGE;
-   } else {
-   return -EOPNOTSUPP;
-   }
-
-   return 0;
-}
-
 /*
  * CTA Data Block iterator.
  *
@@ -4667,9 +4625,6 @@ static bool cea_db_is_hdmi_hdr_metadata_block(const void 
*db)
cea_db_payload_len(db) >= 3;
 }
 
-#define for_each_cea_db(cea, i, start, end) \
-   for ((i) = (start); (i) < (end) && (i) + 
cea_db_payload_len(&(cea)[(i)]) < (end); (i) += cea_db_payload_len(&(cea)[(i)]) 
+ 1)
-
 static void drm_parse_y420cmdb_bitmap(struct drm_connector *connector,
  const u8 *db)
 {
-- 
2.30.2



[PATCH 09/19] drm/edid: convert drm_edid_to_sad() to use cea db iter

2022-04-14 Thread Jani Nikula
Use the cea db iterator for short audio descriptors. We'll still stop at
the first audio data block, but not at the first CTA Extension if that
doesn't have the info.

Cc: Ville Syrjälä 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_edid.c | 34 +-
 1 file changed, 9 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index dac6a400905b..164a2020f9e1 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -5031,40 +5031,21 @@ static void drm_edid_to_eld(struct drm_connector 
*connector,
  */
 int drm_edid_to_sad(const struct edid *edid, struct cea_sad **sads)
 {
+   const struct cea_db *db;
+   struct cea_db_iter iter;
int count = 0;
-   int i, start, end, dbl;
-   const u8 *cea;
-
-   cea = drm_find_cea_extension(edid);
-   if (!cea) {
-   DRM_DEBUG_KMS("SAD: no CEA Extension found\n");
-   return 0;
-   }
-
-   if (cea_revision(cea) < 3) {
-   DRM_DEBUG_KMS("SAD: wrong CEA revision\n");
-   return 0;
-   }
-
-   if (cea_db_offsets(cea, , )) {
-   DRM_DEBUG_KMS("SAD: invalid data block offsets\n");
-   return -EPROTO;
-   }
-
-   for_each_cea_db(cea, i, start, end) {
-   const u8 *db = [i];
 
+   cea_db_iter_edid_begin(edid, );
+   cea_db_iter_for_each(db, ) {
if (cea_db_tag(db) == CTA_DB_AUDIO) {
int j;
 
-   dbl = cea_db_payload_len(db);
-
-   count = dbl / 3; /* SAD is 3B */
+   count = cea_db_payload_len(db) / 3; /* SAD is 3B */
*sads = kcalloc(count, sizeof(**sads), GFP_KERNEL);
if (!*sads)
return -ENOMEM;
for (j = 0; j < count; j++) {
-   const u8 *sad = [1 + j * 3];
+   const u8 *sad = >data[j * 3];
 
(*sads)[j].format = (sad[0] & 0x78) >> 3;
(*sads)[j].channels = sad[0] & 0x7;
@@ -5074,6 +5055,9 @@ int drm_edid_to_sad(const struct edid *edid, struct 
cea_sad **sads)
break;
}
}
+   cea_db_iter_end();
+
+   DRM_DEBUG_KMS("Found %d Short Audio Descriptors\n", count);
 
return count;
 }
-- 
2.30.2



[PATCH 13/19] drm/edid: convert drm_edid_to_eld() to use cea db iter

2022-04-14 Thread Jani Nikula
Iterate through all CTA data blocks across all CTA extensions and
DisplayID data blocks. This may gather more data than before, and if
there's duplicated data, some is overwritten by whichever comes last.

Cc: Ville Syrjälä 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_edid.c | 64 +-
 1 file changed, 29 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 91f15b561d78..fa7f2bf68da3 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -4935,12 +4935,12 @@ static void clear_eld(struct drm_connector *connector)
 static void drm_edid_to_eld(struct drm_connector *connector,
const struct edid *edid)
 {
+   const struct cea_db *db;
+   struct cea_db_iter iter;
uint8_t *eld = connector->eld;
const u8 *cea;
-   const u8 *db;
int total_sad_count = 0;
int mnl;
-   int dbl;
 
clear_eld(connector);
 
@@ -4966,43 +4966,37 @@ static void drm_edid_to_eld(struct drm_connector 
*connector,
eld[DRM_ELD_PRODUCT_CODE0] = edid->prod_code[0];
eld[DRM_ELD_PRODUCT_CODE1] = edid->prod_code[1];
 
-   if (cea_revision(cea) >= 3) {
-   int i, start, end;
+   cea_db_iter_edid_begin(edid, );
+   cea_db_iter_for_each(db, ) {
+   const u8 *data = cea_db_data(db);
+   int len = cea_db_payload_len(db);
int sad_count;
 
-   if (cea_db_offsets(cea, , )) {
-   start = 0;
-   end = 0;
-   }
-
-   for_each_cea_db(cea, i, start, end) {
-   db = [i];
-   dbl = cea_db_payload_len(db);
-
-   switch (cea_db_tag(db)) {
-   case CTA_DB_AUDIO:
-   /* Audio Data Block, contains SADs */
-   sad_count = min(dbl / 3, 15 - total_sad_count);
-   if (sad_count >= 1)
-   memcpy([DRM_ELD_CEA_SAD(mnl, 
total_sad_count)],
-  [1], sad_count * 3);
-   total_sad_count += sad_count;
-   break;
-   case CTA_DB_SPEAKER:
-   /* Speaker Allocation Data Block */
-   if (dbl >= 1)
-   eld[DRM_ELD_SPEAKER] = db[1];
-   break;
-   case CTA_DB_VENDOR:
-   /* HDMI Vendor-Specific Data Block */
-   if (cea_db_is_hdmi_vsdb(db))
-   drm_parse_hdmi_vsdb_audio(connector, 
db);
-   break;
-   default:
-   break;
-   }
+   switch (cea_db_tag(db)) {
+   case CTA_DB_AUDIO:
+   /* Audio Data Block, contains SADs */
+   sad_count = min(len / 3, 15 - total_sad_count);
+   if (sad_count >= 1)
+   memcpy([DRM_ELD_CEA_SAD(mnl, 
total_sad_count)],
+  data, sad_count * 3);
+   total_sad_count += sad_count;
+   break;
+   case CTA_DB_SPEAKER:
+   /* Speaker Allocation Data Block */
+   if (len >= 1)
+   eld[DRM_ELD_SPEAKER] = data[0];
+   break;
+   case CTA_DB_VENDOR:
+   /* HDMI Vendor-Specific Data Block */
+   if (cea_db_is_hdmi_vsdb(db))
+   drm_parse_hdmi_vsdb_audio(connector, (const u8 
*)db);
+   break;
+   default:
+   break;
}
}
+   cea_db_iter_end();
+
eld[DRM_ELD_SAD_COUNT_CONN_TYPE] |= total_sad_count << 
DRM_ELD_SAD_COUNT_SHIFT;
 
if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
-- 
2.30.2



Re: [Intel-gfx] [PATCH] drm/i915/guc/slpc: Use i915_probe_error instead of drm_err

2022-04-14 Thread Belgaumkar, Vinay



On 4/13/2022 11:41 PM, Anshuman Gupta wrote:

On 2022-04-13 at 04:18:52 +0530, Vinay Belgaumkar wrote:

This will ensure we don't have false positives when we run
error injection tests.

Signed-off-by: Vinay Belgaumkar 
---
  drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 42 ++---
  1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
index b170238aa15c..639de3c10545 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
@@ -152,8 +152,8 @@ static int slpc_query_task_state(struct intel_guc_slpc 
*slpc)
  
  	ret = guc_action_slpc_query(guc, offset);

if (unlikely(ret))

As commit logs describe, this code patch can hit, when we run error injection 
test.
Do we need unlikely() here?
Br,
Anshuman Gupta.


I think we still need the unlikely(). Majority of the time, we still 
need the compiler optimization.


Only in the rare case of running the error injection test will it not be 
needed.


Thanks,

Vinay.


-   drm_err(>drm, "Failed to query task state (%pe)\n",
-   ERR_PTR(ret));
+   i915_probe_error(i915, "Failed to query task state (%pe)\n",
+ERR_PTR(ret));
  
  	drm_clflush_virt_range(slpc->vaddr, SLPC_PAGE_SIZE_BYTES);
  
@@ -170,8 +170,8 @@ static int slpc_set_param(struct intel_guc_slpc *slpc, u8 id, u32 value)
  
  	ret = guc_action_slpc_set_param(guc, id, value);

if (ret)
-   drm_err(>drm, "Failed to set param %d to %u (%pe)\n",
-   id, value, ERR_PTR(ret));
+   i915_probe_error(i915, "Failed to set param %d to %u (%pe)\n",
+id, value, ERR_PTR(ret));
  
  	return ret;

  }
@@ -211,8 +211,8 @@ static int slpc_force_min_freq(struct intel_guc_slpc *slpc, 
u32 freq)
 SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ,
 freq);
if (ret)
-   drm_err(>drm, "Unable to force min freq to %u: 
%d",
-   freq, ret);
+   i915_probe_error(i915, "Unable to force min freq to %u: 
%d",
+freq, ret);
}
  
  	return ret;

@@ -247,9 +247,9 @@ int intel_guc_slpc_init(struct intel_guc_slpc *slpc)
  
  	err = intel_guc_allocate_and_map_vma(guc, size, >vma, (void **)>vaddr);

if (unlikely(err)) {
-   drm_err(>drm,
-   "Failed to allocate SLPC struct (err=%pe)\n",
-   ERR_PTR(err));
+   i915_probe_error(i915,
+"Failed to allocate SLPC struct (err=%pe)\n",
+ERR_PTR(err));
return err;
}
  
@@ -316,15 +316,15 @@ static int slpc_reset(struct intel_guc_slpc *slpc)

ret = guc_action_slpc_reset(guc, offset);
  
  	if (unlikely(ret < 0)) {

-   drm_err(>drm, "SLPC reset action failed (%pe)\n",
-   ERR_PTR(ret));
+   i915_probe_error(i915, "SLPC reset action failed (%pe)\n",
+ERR_PTR(ret));
return ret;
}
  
  	if (!ret) {

if (wait_for(slpc_is_running(slpc), SLPC_RESET_TIMEOUT_MS)) {
-   drm_err(>drm, "SLPC not enabled! State = %s\n",
-   slpc_get_state_string(slpc));
+   i915_probe_error(i915, "SLPC not enabled! State = %s\n",
+slpc_get_state_string(slpc));
return -EIO;
}
}
@@ -616,8 +616,8 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
  
  	ret = slpc_reset(slpc);

if (unlikely(ret < 0)) {
-   drm_err(>drm, "SLPC Reset event returned (%pe)\n",
-   ERR_PTR(ret));
+   i915_probe_error(i915, "SLPC Reset event returned (%pe)\n",
+ERR_PTR(ret));
return ret;
}
  
@@ -632,24 +632,24 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)

/* Ignore efficient freq and set min to platform min */
ret = slpc_ignore_eff_freq(slpc, true);
if (unlikely(ret)) {
-   drm_err(>drm, "Failed to set SLPC min to RPn (%pe)\n",
-   ERR_PTR(ret));
+   i915_probe_error(i915, "Failed to set SLPC min to RPn (%pe)\n",
+ERR_PTR(ret));
return ret;
}
  
  	/* Set SLPC max limit to RP0 */

ret = slpc_use_fused_rp0(slpc);
if (unlikely(ret)) {
-   drm_err(>drm, "Failed to set SLPC max to RP0 (%pe)\n",
-   ERR_PTR(ret));
+   i915_probe_error(i915, "Failed to set SLPC max to RP0 (%pe)\n",
+

[PATCH 11/19] drm/edid: convert drm_detect_monitor_audio() to use cea db iter

2022-04-14 Thread Jani Nikula
Iterate through all CEA data blocks.

Cc: Ville Syrjälä 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_edid.c | 23 +--
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index b1fac281fd85..e47bbcd103e6 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -5190,10 +5190,10 @@ EXPORT_SYMBOL(drm_detect_hdmi_monitor);
  */
 bool drm_detect_monitor_audio(const struct edid *edid)
 {
+   const struct cea_db *db;
+   struct cea_db_iter iter;
const u8 *edid_ext;
-   int i, j;
bool has_audio = false;
-   int start_offset, end_offset;
 
edid_ext = drm_find_cea_extension(edid);
if (!edid_ext)
@@ -5207,18 +5207,21 @@ bool drm_detect_monitor_audio(const struct edid *edid)
goto end;
}
 
-   if (cea_db_offsets(edid_ext, _offset, _offset))
-   goto end;
+   cea_db_iter_edid_begin(edid, );
+   cea_db_iter_for_each(db, ) {
+   if (cea_db_tag(db) == CTA_DB_AUDIO) {
+   const u8 *data = cea_db_data(db);
+   int i;
 
-   for_each_cea_db(edid_ext, i, start_offset, end_offset) {
-   if (cea_db_tag(_ext[i]) == CTA_DB_AUDIO) {
-   has_audio = true;
-   for (j = 1; j < cea_db_payload_len(_ext[i]) + 1; j 
+= 3)
+   for (i = 0; i < cea_db_payload_len(db); i += 3)
DRM_DEBUG_KMS("CEA audio format %d\n",
- (edid_ext[i + j] >> 3) & 0xf);
-   goto end;
+ (data[i] >> 3) & 0xf);
+   has_audio = true;
+   break;
}
}
+   cea_db_iter_end();
+
 end:
return has_audio;
 }
-- 
2.30.2



[PATCH 10/19] drm/edid: convert drm_detect_hdmi_monitor() to use cea db iter

2022-04-14 Thread Jani Nikula
Iterate through all CTA data blocks, not just the first CTA extension.

Cc: Ville Syrjälä 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_edid.c | 25 +++--
 1 file changed, 11 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 164a2020f9e1..b1fac281fd85 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -5155,27 +5155,24 @@ EXPORT_SYMBOL(drm_av_sync_delay);
  */
 bool drm_detect_hdmi_monitor(const struct edid *edid)
 {
-   const u8 *edid_ext;
-   int i;
-   int start_offset, end_offset;
-
-   edid_ext = drm_find_cea_extension(edid);
-   if (!edid_ext)
-   return false;
-
-   if (cea_db_offsets(edid_ext, _offset, _offset))
-   return false;
+   const struct cea_db *db;
+   struct cea_db_iter iter;
+   bool hdmi = false;
 
/*
 * Because HDMI identifier is in Vendor Specific Block,
 * search it from all data blocks of CEA extension.
 */
-   for_each_cea_db(edid_ext, i, start_offset, end_offset) {
-   if (cea_db_is_hdmi_vsdb(_ext[i]))
-   return true;
+   cea_db_iter_edid_begin(edid, );
+   cea_db_iter_for_each(db, ) {
+   if (cea_db_is_hdmi_vsdb(db)) {
+   hdmi = true;
+   break;
+   }
}
+   cea_db_iter_end();
 
-   return false;
+   return hdmi;
 }
 EXPORT_SYMBOL(drm_detect_hdmi_monitor);
 
-- 
2.30.2



[PATCH 07/19] drm/edid: convert add_cea_modes() to use cea db iter

2022-04-14 Thread Jani Nikula
Iterate through all CTA EDID extension blocks and DisplayID CTA data
blocks to add CEA modes.

Cc: Ville Syrjälä 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_edid.c | 67 ++
 1 file changed, 31 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 34897b1417a5..d02588637879 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -4713,46 +4713,41 @@ static void drm_parse_y420cmdb_bitmap(struct 
drm_connector *connector,
 static int
 add_cea_modes(struct drm_connector *connector, const struct edid *edid)
 {
-   const u8 *cea = drm_find_cea_extension(edid);
-   const u8 *db, *hdmi = NULL, *video = NULL;
-   u8 dbl, hdmi_len, video_len = 0;
+   const struct cea_db *db;
+   struct cea_db_iter iter;
int modes = 0;
 
-   if (cea && cea_revision(cea) >= 3) {
-   int i, start, end;
-
-   if (cea_db_offsets(cea, , ))
-   return 0;
-
-   for_each_cea_db(cea, i, start, end) {
-   db = [i];
-   dbl = cea_db_payload_len(db);
-
-   if (cea_db_tag(db) == CTA_DB_VIDEO) {
-   video = db + 1;
-   video_len = dbl;
-   modes += do_cea_modes(connector, video, dbl);
-   } else if (cea_db_is_hdmi_vsdb(db)) {
-   hdmi = db;
-   hdmi_len = dbl;
-   } else if (cea_db_is_y420vdb(db)) {
-   const u8 *vdb420 = [2];
-
-   /* Add 4:2:0(only) modes present in EDID */
-   modes += do_y420vdb_modes(connector,
- vdb420,
- dbl - 1);
-   }
+   cea_db_iter_edid_begin(edid, );
+   cea_db_iter_for_each(db, ) {
+   const u8 *hdmi = NULL, *video = NULL;
+   u8 hdmi_len = 0, video_len = 0;
+
+   if (cea_db_tag(db) == CTA_DB_VIDEO) {
+   video = cea_db_data(db);
+   video_len = cea_db_payload_len(db);
+   modes += do_cea_modes(connector, video, video_len);
+   } else if (cea_db_is_hdmi_vsdb(db)) {
+   /* FIXME: Switch to use cea_db_data() */
+   hdmi = (const u8 *)db;
+   hdmi_len = cea_db_payload_len(db);
+   } else if (cea_db_is_y420vdb(db)) {
+   const u8 *vdb420 = cea_db_data(db) + 1;
+
+   /* Add 4:2:0(only) modes present in EDID */
+   modes += do_y420vdb_modes(connector, vdb420,
+ cea_db_payload_len(db) - 1);
}
-   }
 
-   /*
-* We parse the HDMI VSDB after having added the cea modes as we will
-* be patching their flags when the sink supports stereo 3D.
-*/
-   if (hdmi)
-   modes += do_hdmi_vsdb_modes(connector, hdmi, hdmi_len, video,
-   video_len);
+   /*
+* We parse the HDMI VSDB after having added the cea modes as we
+* will be patching their flags when the sink supports stereo
+* 3D.
+*/
+   if (hdmi)
+   modes += do_hdmi_vsdb_modes(connector, hdmi, hdmi_len,
+   video, video_len);
+   }
+   cea_db_iter_end();
 
return modes;
 }
-- 
2.30.2



[PATCH 08/19] drm/edid: convert drm_edid_to_speaker_allocation() to use cea db iter

2022-04-14 Thread Jani Nikula
Use the cea db iterator for speaker allocation. We'll still stop at the
first speaker data block, but not at the first CTA extension if that
doesn't have the info.

Cc: Ville Syrjälä 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_edid.c | 47 --
 1 file changed, 15 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index d02588637879..dac6a400905b 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -5093,42 +5093,25 @@ EXPORT_SYMBOL(drm_edid_to_sad);
  */
 int drm_edid_to_speaker_allocation(const struct edid *edid, u8 **sadb)
 {
+   const struct cea_db *db;
+   struct cea_db_iter iter;
int count = 0;
-   int i, start, end, dbl;
-   const u8 *cea;
 
-   cea = drm_find_cea_extension(edid);
-   if (!cea) {
-   DRM_DEBUG_KMS("SAD: no CEA Extension found\n");
-   return 0;
-   }
-
-   if (cea_revision(cea) < 3) {
-   DRM_DEBUG_KMS("SAD: wrong CEA revision\n");
-   return 0;
-   }
-
-   if (cea_db_offsets(cea, , )) {
-   DRM_DEBUG_KMS("SAD: invalid data block offsets\n");
-   return -EPROTO;
-   }
-
-   for_each_cea_db(cea, i, start, end) {
-   const u8 *db = [i];
-
-   if (cea_db_tag(db) == CTA_DB_SPEAKER) {
-   dbl = cea_db_payload_len(db);
-
-   /* Speaker Allocation Data Block */
-   if (dbl == 3) {
-   *sadb = kmemdup([1], dbl, GFP_KERNEL);
-   if (!*sadb)
-   return -ENOMEM;
-   count = dbl;
-   break;
-   }
+   cea_db_iter_edid_begin(edid, );
+   cea_db_iter_for_each(db, ) {
+   if (cea_db_tag(db) == CTA_DB_SPEAKER &&
+   cea_db_payload_len(db) == 3) {
+   *sadb = kmemdup(db->data, cea_db_payload_len(db),
+   GFP_KERNEL);
+   if (!*sadb)
+   return -ENOMEM;
+   count = cea_db_payload_len(db);
+   break;
}
}
+   cea_db_iter_end();
+
+   DRM_DEBUG_KMS("Found %d Speaker Allocation Data Blocks\n", count);
 
return count;
 }
-- 
2.30.2



[PATCH 04/19] drm/edid: add iterator for EDID base and extension blocks

2022-04-14 Thread Jani Nikula
Add an iterator abstraction for going through all the EDID blocks.

Cc: Ville Syrjälä 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_edid.c | 48 ++
 1 file changed, 48 insertions(+)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 18b0ff223885..40ffd7aba157 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -1600,6 +1600,54 @@ static const void *edid_extension_block_data(const 
struct edid *edid, int index)
return edid_block_data(edid, index + 1);
 }
 
+/*
+ * EDID base and extension block iterator.
+ *
+ * struct drm_edid_iter iter;
+ * const u8 *block;
+ *
+ * drm_edid_iter_begin(edid, );
+ * drm_edid_iter_for_each(block, ) {
+ * // do stuff with block
+ * }
+ * drm_edid_iter_end();
+ */
+struct drm_edid_iter {
+   const struct edid *edid;
+
+   /* Current block index. */
+   int index;
+};
+
+static void drm_edid_iter_begin(const struct edid *edid,
+   struct drm_edid_iter *iter)
+{
+   memset(iter, 0, sizeof(*iter));
+
+   iter->edid = edid;
+}
+
+static const void *__drm_edid_iter_next(struct drm_edid_iter *iter)
+{
+   const void *block = NULL;
+
+   if (!iter->edid)
+   return NULL;
+
+   if (iter->index < edid_block_count(iter->edid))
+   block = edid_block_data(iter->edid, iter->index++);
+
+   return block;
+}
+
+#define drm_edid_iter_for_each(__block, __iter)\
+   while (((__block) = __drm_edid_iter_next(__iter)))
+
+static void drm_edid_iter_end(struct drm_edid_iter *iter)
+{
+   memset(iter, 0, sizeof(*iter));
+}
+
 static const u8 edid_header[] = {
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
 };
-- 
2.30.2



[PATCH 06/19] drm/edid: clean up cea_db_is_*() functions

2022-04-14 Thread Jani Nikula
Abstract helpers for matching vendor data blocks and extended tags, and
use them to simplify all the cea_db_is_*() functions.

Take void pointer as parameter to allow transitional use for both u8 *
and struct cea_db *.

v2: Remove superfluous parens (Ville)

Cc: Ville Syrjälä 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_edid.c | 127 -
 1 file changed, 40 insertions(+), 87 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 43d9e04f8fb9..34897b1417a5 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -4360,12 +4360,6 @@ do_hdmi_vsdb_modes(struct drm_connector *connector, 
const u8 *db, u8 len,
return modes;
 }
 
-static int
-cea_db_extended_tag(const u8 *db)
-{
-   return db[1];
-}
-
 static int
 cea_revision(const u8 *cea)
 {
@@ -4477,6 +4471,22 @@ static const void *cea_db_data(const struct cea_db *db)
return db->data;
 }
 
+static bool cea_db_is_extended_tag(const struct cea_db *db, int tag)
+{
+   return cea_db_tag(db) == CTA_DB_EXTENDED_TAG &&
+   cea_db_payload_len(db) >= 1 &&
+   db->data[0] == tag;
+}
+
+static bool cea_db_is_vendor(const struct cea_db *db, int vendor_oui)
+{
+   const u8 *data = cea_db_data(db);
+
+   return cea_db_tag(db) == CTA_DB_VENDOR &&
+   cea_db_payload_len(db) >= 3 &&
+   oui(data[2], data[1], data[0]) == vendor_oui;
+}
+
 static void cea_db_iter_edid_begin(const struct edid *edid, struct cea_db_iter 
*iter)
 {
memset(iter, 0, sizeof(*iter));
@@ -4611,93 +4621,50 @@ static void cea_db_iter_end(struct cea_db_iter *iter)
memset(iter, 0, sizeof(*iter));
 }
 
-static bool cea_db_is_hdmi_vsdb(const u8 *db)
+static bool cea_db_is_hdmi_vsdb(const void *db)
 {
-   if (cea_db_tag(db) != CTA_DB_VENDOR)
-   return false;
-
-   if (cea_db_payload_len(db) < 5)
-   return false;
-
-   return oui(db[3], db[2], db[1]) == HDMI_IEEE_OUI;
+   return cea_db_is_vendor(db, HDMI_IEEE_OUI) &&
+   cea_db_payload_len(db) >= 5;
 }
 
-static bool cea_db_is_hdmi_forum_vsdb(const u8 *db)
+static bool cea_db_is_hdmi_forum_vsdb(const void *db)
 {
-   if (cea_db_tag(db) != CTA_DB_VENDOR)
-   return false;
-
-   if (cea_db_payload_len(db) < 7)
-   return false;
-
-   return oui(db[3], db[2], db[1]) == HDMI_FORUM_IEEE_OUI;
+   return cea_db_is_vendor(db, HDMI_FORUM_IEEE_OUI) &&
+   cea_db_payload_len(db) >= 7;
 }
 
-static bool cea_db_is_microsoft_vsdb(const u8 *db)
+static bool cea_db_is_microsoft_vsdb(const void *db)
 {
-   if (cea_db_tag(db) != CTA_DB_VENDOR)
-   return false;
-
-   if (cea_db_payload_len(db) != 21)
-   return false;
-
-   return oui(db[3], db[2], db[1]) == MICROSOFT_IEEE_OUI;
+   return cea_db_is_vendor(db, MICROSOFT_IEEE_OUI) &&
+   cea_db_payload_len(db) == 21;
 }
 
-static bool cea_db_is_vcdb(const u8 *db)
+static bool cea_db_is_vcdb(const void *db)
 {
-   if (cea_db_tag(db) != CTA_DB_EXTENDED_TAG)
-   return false;
-
-   if (cea_db_payload_len(db) != 2)
-   return false;
-
-   if (cea_db_extended_tag(db) != CTA_EXT_DB_VIDEO_CAP)
-   return false;
-
-   return true;
+   return cea_db_is_extended_tag(db, CTA_EXT_DB_VIDEO_CAP) &&
+   cea_db_payload_len(db) == 2;
 }
 
-static bool cea_db_is_hdmi_forum_scdb(const u8 *db)
+static bool cea_db_is_hdmi_forum_scdb(const void *db)
 {
-   if (cea_db_tag(db) != CTA_DB_EXTENDED_TAG)
-   return false;
-
-   if (cea_db_payload_len(db) < 7)
-   return false;
-
-   if (cea_db_extended_tag(db) != CTA_EXT_DB_HF_SCDB)
-   return false;
-
-   return true;
+   return cea_db_is_extended_tag(db, CTA_EXT_DB_HF_SCDB) &&
+   cea_db_payload_len(db) >= 7;
 }
 
-static bool cea_db_is_y420cmdb(const u8 *db)
+static bool cea_db_is_y420cmdb(const void *db)
 {
-   if (cea_db_tag(db) != CTA_DB_EXTENDED_TAG)
-   return false;
-
-   if (!cea_db_payload_len(db))
-   return false;
-
-   if (cea_db_extended_tag(db) != CTA_EXT_DB_420_VIDEO_CAP_MAP)
-   return false;
-
-   return true;
+   return cea_db_is_extended_tag(db, CTA_EXT_DB_420_VIDEO_CAP_MAP);
 }
 
-static bool cea_db_is_y420vdb(const u8 *db)
+static bool cea_db_is_y420vdb(const void *db)
 {
-   if (cea_db_tag(db) != CTA_DB_EXTENDED_TAG)
-   return false;
-
-   if (!cea_db_payload_len(db))
-   return false;
-
-   if (cea_db_extended_tag(db) != CTA_EXT_DB_420_VIDEO_DATA)
-   return false;
+   return cea_db_is_extended_tag(db, CTA_EXT_DB_420_VIDEO_DATA);
+}
 
-   return true;
+static bool cea_db_is_hdmi_hdr_metadata_block(const void *db)
+{
+   return cea_db_is_extended_tag(db, CTA_EXT_DB_HDR_STATIC_METADATA) &&
+

  1   2   >