RE: [PATCH] WIP: drm/dp_mst: Add support for dumping topology ref histories from debugfs

2022-04-24 Thread Lin, Wayne
[AMD Official Use Only - General]

Thank you Lyude!

I just have a tentative patch set to deal with this. Would like to give a test 
on some platforms first.
If the result is positive, will send out for review immediately.

Thanks for tracking on this : )

Regards,
Wayne Lin

> -Original Message-
> From: Lyude Paul 
> Sent: Thursday, April 21, 2022 7:01 AM
> To: Lin, Wayne 
> Cc: dri-devel@lists.freedesktop.org; amd-...@lists.freedesktop.org
> Subject: Re: [PATCH] WIP: drm/dp_mst: Add support for dumping topology ref 
> histories from debugfs
>
> Hey! Figured I'd check if there's been any status updates here since it's been
> a while, just to make sure I haven't dropped this issue from my radar. No
> problem if you're busy :)
>
> On Wed, 2022-03-16 at 10:46 +, Lin, Wayne wrote:
> > [Public]
> >
> > > -Original Message-
> > > From: Lyude Paul 
> > > Sent: Wednesday, March 16, 2022 8:48 AM
> > > To: Lin, Wayne 
> > > Cc: dri-devel@lists.freedesktop.org; amd-...@lists.freedesktop.org
> > > Subject: Re: [PATCH] WIP: drm/dp_mst: Add support for dumping topology ref
> > > histories from debugfs
> > >
> > > (Adding this back to the dri-devel mailing list since I didn't notice it
> > > got
> > > dropped from there)
> > >
> > > Hm, some comments on this issue down below. Sorry for the delayed
> > > response, I
> > > was going to try this right after I finished the MST legacy removal but
> > > that's
> > > ending up taking longer than I hoped.
> > >
> > > On Tue, 2022-03-08 at 01:46 +, Lin, Wayne wrote:
> > > > [AMD Official Use Only]
> > > >
> > > > Oops...
> > > > I didn't notice that I replied to wrong mail previously : P
> > > > Sorry for the confusion and reply to the correct thread.
> > > >
> > > > Good day!
> > > > I probably know why you can't reproduce the issue there. Please refer to
> > > > the
> > > > attached
> > > > patch file which makes me easier to explain this.
> > > >
> > > > In dm_dp_mst_get_modes(), we will create a new dc_sink by calling
> > > > dc_link_add_remote_sink() and add that dc_sink into the array dc_link-
> > > > > remote_sinks[].
> > > > However, if we find that aconnector->dc_sink is not null, then we won't
> > > > create a new
> > > > dc_sink for that aconnector and won't add the sink to the array dc_link-
> > > > > remote_sinks[].
> > > >
> > > > When the issue that I mentioned before occurs, we won't be able to
> > > > release
> > > > the dc_sink
> > > > for the aconnector when we unplug the sst monitor. Hence, we can't
> > > > create
> > > > new dc_sink
> > > > for the latter on connected new stream sink of that port. Which leads to
> > > > two
> > > > issues
> > > > 1. Unplug monitor and plug in another monitor "to the same port"
> > > > =>  Since we use the same dc_sink to reflect the capability of the new
> > > > connected stream
> > > > sink, we might send out inappropriate stream to the new connected sink.
> > > > 2. Because we can't release dc_sink in the array dc_link-
> > > > >remote_sinks[],
> > > > when we
> > > > plug/unplug sst monitor to more than 4 different mst port, we will break
> > > > the
> > > > criteria
> > > > "dc_link->sink_count >= MAX_SINKS_PER_LINK" in
> > > > link_add_remote_sink_helper().
> > >
> > > Ok, a lot of this seems to be happening in amdgpu which certainly explains
> > > why
> > > I had so much trouble following along with this originally (also, having
> > > learned a bit more about how DC works definitely has helped a bit). I
> > > already
> > > see a bunch of issues though with how this code is structured that would
> > > definitely break things, though note I haven't sat down and tried this on
> > > a
> > > real machine yet - will try tomorrow.
> > >
> > > So - it seems like dc_sink == a bunch of hotplugging state for a dm
> > > connector,
> > > which actually tells me for one that this is definitely the wrong spot for
> > > this code. get_modes() really should just handle filling out DRM modes and
> > > pretty much nothing else, because callers from DRM aren't going to expect
> > > side-effects like this when get_modes() is called - which could
> > > potentially
> > > lead to all sorts of weirdness down the line if the DRM call paths that
> > > use
> > > this ever change. i915 and nouveau have good examples of what these
> > > functions
> > > should typically look like, and amdgpu actually seems to mostly follow
> > > this
> > > advice for it's other get_modes() callback.
> > >
> > > Note there's also another problem here: the assumption "no EDID ==
> > > disconnected" isn't correct. It's totally possible to run into EDID-less
> > > displays if the display is some ancient pre-historic relic, or if the ROM
> > > (or
> > > EEPROM? can't remember what type of chip computer displays tend to use...)
> > > chip
> > > in the monitor containing the EDID has died. Note that the second
> > > situation is
> > > suprisingly more common then one might think! I ran into a 140Hz 4k ASUS
> > > display where this happened, and I 

[PATCH] drm/msm/disp/dpu1: set vbif hw config to NULL to avoid use after memory free during pm runtime resume

2022-04-24 Thread Vinod Polimera
BUG: Unable to handle kernel paging request at virtual address 006b6b6b6b6b6be3

Call trace:
  dpu_vbif_init_memtypes+0x40/0xb8
  dpu_runtime_resume+0xcc/0x1c0
  pm_generic_runtime_resume+0x30/0x44
  __genpd_runtime_resume+0x68/0x7c
  genpd_runtime_resume+0x134/0x258
  __rpm_callback+0x98/0x138
  rpm_callback+0x30/0x88
  rpm_resume+0x36c/0x49c
  __pm_runtime_resume+0x80/0xb0
  dpu_core_irq_uninstall+0x30/0xb0
  dpu_irq_uninstall+0x18/0x24
  msm_drm_uninit+0xd8/0x16c

Fixes: 25fdd5933e4 ("drm/msm: Add SDM845 DPU support")
Signed-off-by: Vinod Polimera 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 9c346ce..59982d3 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -793,8 +793,10 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms)
for (i = 0; i < dpu_kms->catalog->vbif_count; i++) {
u32 vbif_idx = dpu_kms->catalog->vbif[i].id;
 
-   if ((vbif_idx < VBIF_MAX) && dpu_kms->hw_vbif[vbif_idx])
+   if ((vbif_idx < VBIF_MAX) && 
dpu_kms->hw_vbif[vbif_idx]) {
dpu_hw_vbif_destroy(dpu_kms->hw_vbif[vbif_idx]);
+   dpu_kms->hw_vbif[vbif_idx] = NULL;
+   }
}
}
 
-- 
2.7.4



RE: [PATCH v9 2/4] drm/msm/dp: Support only IRQ_HPD and REPLUG interrupts for eDP

2022-04-24 Thread Sankeerth Billakanti (QUIC)
Hi Stephen,

>Quoting Sankeerth Billakanti (2022-04-22 02:11:04)
>> The panel-edp enables the eDP panel power during probe, get_modes and
>> 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 
>
>The sprinkling of if conditions and manual driving of the DP plug/unplug state
>machine is pretty convoluted. To make it better the driver needs an overhaul.
>Anyway, it looks mostly fine to me except for this replug interrupt question
>below. Otherwise
>
>Reviewed-by: Stephen Boyd 
>
>>  int dp_catalog_ctrl_get_interrupt(struct dp_catalog *dp_catalog) diff
>> --git a/drivers/gpu/drm/msm/dp/dp_display.c
>> b/drivers/gpu/drm/msm/dp/dp_display.c
>> index 055681a..dea4de9 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_display.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
>> @@ -1096,6 +1097,13 @@ static void dp_display_config_hpd(struct
>dp_display_private *dp)
>> dp_display_host_init(dp);
>> dp_catalog_ctrl_hpd_config(dp->catalog);
>>
>> +   /* Enable plug and unplug interrupts only for external DisplayPort */
>> +   if (!dp->dp_display.is_edp)
>> +   dp_catalog_hpd_config_intr(dp->catalog,
>> +   DP_DP_HPD_PLUG_INT_MASK |
>> +   DP_DP_HPD_UNPLUG_INT_MASK,
>> +   true);
>> +
>
>It seems like only the plug and unplug is enabled for DP here. Is replug
>enabled for eDP when it shouldn't be?
>

By default, all the interrupts are masked. This function is not executed for eDP
anymore because the host_init, phy_init and enable_irq are all done from
modeset_init for eDP with aux_bus. So, none of the eDP hpd interrupts are
enabled or unmasked before pre-enable.

The replug interrupt is unmasked for DP and eDP from the dp_hpd_plug_handle()
and masked from dp_hpd_unplug_handle().

>> /* Enable interrupt first time
>>  * we are leaving dp clocks on during disconnect
>>  * and never disable interrupt


[PATCH v5 17/19] drm/msm/dpu: add writeback blocks to the display snapshot

2022-04-24 Thread Abhinav Kumar
Add writeback block information while capturing the display
snapshot.

Signed-off-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 9a406e1..b18bff8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -945,6 +945,11 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state 
*disp_state, struct msm_k
msm_disp_snapshot_add_block(disp_state, cat->mixer[i].len,
dpu_kms->mmio + cat->mixer[i].base, "lm_%d", i);
 
+   /* dump WB sub-blocks HW regs info */
+   for (i = 0; i < cat->wb_count; i++)
+   msm_disp_snapshot_add_block(disp_state, cat->wb[i].len,
+   dpu_kms->mmio + cat->wb[i].base, "wb_%d", i);
+
msm_disp_snapshot_add_block(disp_state, top->hw.length,
dpu_kms->mmio + top->hw.blk_off, "top");
 
-- 
2.7.4



[PATCH v5 19/19] drm/msm/dpu: add wb_idx to DRM traces in dpu_encoder

2022-04-24 Thread Abhinav Kumar
Change the DRM traces to include both the intf_mode
and wb_idx similar to the DRM prints in the previous change.

Signed-off-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 13 -
 drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h   | 26 ++
 2 files changed, 26 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 6d093cf..3bd1790 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1354,8 +1354,9 @@ static void dpu_encoder_frame_done_callback(
 * suppress frame_done without waiter,
 * likely autorefresh
 */
-   trace_dpu_enc_frame_done_cb_not_busy(DRMID(drm_enc),
-   event, ready_phys->intf_idx);
+   trace_dpu_enc_frame_done_cb_not_busy(DRMID(drm_enc), 
event,
+   
dpu_encoder_helper_get_intf_type(ready_phys->intf_mode),
+   ready_phys->intf_idx, 
ready_phys->wb_idx);
return;
}
 
@@ -1433,9 +1434,11 @@ static void _dpu_encoder_trigger_flush(struct 
drm_encoder *drm_enc,
if (ctl->ops.get_pending_flush)
ret = ctl->ops.get_pending_flush(ctl);
 
-   trace_dpu_enc_trigger_flush(DRMID(drm_enc), phys->intf_idx,
-   pending_kickoff_cnt, ctl->idx,
-   extra_flush_bits, ret);
+   trace_dpu_enc_trigger_flush(DRMID(drm_enc),
+   dpu_encoder_helper_get_intf_type(phys->intf_mode),
+   phys->intf_idx, phys->wb_idx,
+   pending_kickoff_cnt, ctl->idx,
+   extra_flush_bits, ret);
 }
 
 /**
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
index 58b411f..1106d44 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
@@ -380,20 +380,26 @@ TRACE_EVENT(dpu_enc_rc,
 );
 
 TRACE_EVENT(dpu_enc_frame_done_cb_not_busy,
-   TP_PROTO(uint32_t drm_id, u32 event, enum dpu_intf intf_idx),
-   TP_ARGS(drm_id, event, intf_idx),
+   TP_PROTO(uint32_t drm_id, u32 event, char *intf_mode, enum dpu_intf 
intf_idx,
+   enum dpu_wb wb_idx),
+   TP_ARGS(drm_id, event, intf_mode, intf_idx, wb_idx),
TP_STRUCT__entry(
__field(uint32_t,   drm_id  )
__field(u32,event   )
+   __string(   intf_mode_str,  intf_mode   )
__field(enum dpu_intf,  intf_idx)
+   __field(enum dpu_wb,  wb_idx)
),
TP_fast_assign(
__entry->drm_id = drm_id;
__entry->event = event;
+   __assign_str(intf_mode_str, intf_mode);
__entry->intf_idx = intf_idx;
+   __entry->wb_idx = wb_idx;
),
-   TP_printk("id=%u, event=%u, intf=%d", __entry->drm_id, __entry->event,
- __entry->intf_idx)
+   TP_printk("id=%u, event=%u, intf_mode=%s intf=%d wb=%d", 
__entry->drm_id,
+   __entry->event, __get_str(intf_mode_str),
+   __entry->intf_idx, __entry->wb_idx)
 );
 
 TRACE_EVENT(dpu_enc_frame_done_cb,
@@ -415,14 +421,16 @@ TRACE_EVENT(dpu_enc_frame_done_cb,
 );
 
 TRACE_EVENT(dpu_enc_trigger_flush,
-   TP_PROTO(uint32_t drm_id, enum dpu_intf intf_idx,
+   TP_PROTO(uint32_t drm_id, char *intf_mode, enum dpu_intf intf_idx, enum 
dpu_wb wb_idx,
 int pending_kickoff_cnt, int ctl_idx, u32 extra_flush_bits,
 u32 pending_flush_ret),
-   TP_ARGS(drm_id, intf_idx, pending_kickoff_cnt, ctl_idx,
+   TP_ARGS(drm_id, intf_mode, intf_idx, pending_kickoff_cnt, ctl_idx,
extra_flush_bits, pending_flush_ret),
TP_STRUCT__entry(
__field(uint32_t,   drm_id  )
+   __string(   intf_mode_str,  intf_mode   )
__field(enum dpu_intf,  intf_idx)
+   __field(enum dpu_wb,  wb_idx)
__field(int,pending_kickoff_cnt )
__field(int,ctl_idx )
__field(u32,extra_flush_bits)
@@ -430,15 +438,17 @@ TRACE_EVENT(dpu_enc_trigger_flush,
),
TP_fast_assign(
__entry->drm_id = drm_id;
+   __assign_str(intf_mode_str, intf_mode);
__entry->intf_idx = intf_idx;
+   __entry->wb_idx = wb_idx;
__entry->pending_kickoff_cnt = 

[PATCH v5 18/19] drm/msm/dpu: add wb_idx to existing DRM prints in dpu_encoder

2022-04-24 Thread Abhinav Kumar
Add wb_idx to existing DRM prints in dpu_encoder and also
print the intf_mode so that its clear that for any INTF_CMD/VID
there will be a valid intf_idx and any INTF_WB_* there will be a
valid wb_idx.

Update the debugfs to add the same information. Here is a sample
output with this change:

root:/sys/kernel/debug/dri/0/encoder31# cat status
intf:1  wb:-1  vsync: 31  underrun: 0mode: INTF_MODE_VIDEO
root:/sys/kernel/debug/dri/0/encoder33# cat status
intf:-1  wb:2  vsync:  7  underrun: 0mode: INTF_MODE_WB_LINE

Also remove DPU_DEBUG_PHYS macros as its unused because the
respective dpu_encoder_phys_* files have their own macros.

changes in v2:
- use switch case instead of if/else-if for get_intf_type

Signed-off-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 52 +
 1 file changed, 24 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 90ef807..6d093cf 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -38,18 +38,6 @@
 #define DPU_ERROR_ENC(e, fmt, ...) DPU_ERROR("enc%d " fmt,\
(e) ? (e)->base.base.id : -1, ##__VA_ARGS__)
 
-#define DPU_DEBUG_PHYS(p, fmt, ...) DRM_DEBUG_ATOMIC("enc%d intf%d pp%d " fmt,\
-   (p) ? (p)->parent->base.id : -1, \
-   (p) ? (p)->intf_idx - INTF_0 : -1, \
-   (p) ? ((p)->hw_pp ? (p)->hw_pp->idx - PINGPONG_0 : -1) : -1, \
-   ##__VA_ARGS__)
-
-#define DPU_ERROR_PHYS(p, fmt, ...) DPU_ERROR("enc%d intf%d pp%d " fmt,\
-   (p) ? (p)->parent->base.id : -1, \
-   (p) ? (p)->intf_idx - INTF_0 : -1, \
-   (p) ? ((p)->hw_pp ? (p)->hw_pp->idx - PINGPONG_0 : -1) : -1, \
-   ##__VA_ARGS__)
-
 /*
  * Two to anticipate panels that can do cmd/vid dynamic switching
  * plan is to create all possible physical encoder types, and switch between
@@ -263,12 +251,30 @@ static void _dpu_encoder_setup_dither(struct 
dpu_hw_pingpong *hw_pp, unsigned bp
hw_pp->ops.setup_dither(hw_pp, _cfg);
 }
 
+static char *dpu_encoder_helper_get_intf_type(enum dpu_intf_mode intf_mode)
+{
+   switch (intf_mode) {
+   case INTF_MODE_VIDEO:
+   return "INTF_MODE_VIDEO";
+   case INTF_MODE_CMD:
+   return "INTF_MODE_CMD";
+   case INTF_MODE_WB_BLOCK:
+   return "INTF_MODE_WB_BLOCK";
+   case INTF_MODE_WB_LINE:
+   return "INTF_MODE_WB_LINE";
+   default:
+   return "INTF_MODE_UNKNOWN";
+   }
+}
+
 void dpu_encoder_helper_report_irq_timeout(struct dpu_encoder_phys *phys_enc,
enum dpu_intr_idx intr_idx)
 {
-   DRM_ERROR("irq timeout id=%u, intf=%d, pp=%d, intr=%d\n",
- DRMID(phys_enc->parent), phys_enc->intf_idx - INTF_0,
- phys_enc->hw_pp->idx - PINGPONG_0, intr_idx);
+   DRM_ERROR("irq timeout id=%u, intf_mode=%s intf=%d wb=%d, pp=%d, 
intr=%d\n",
+   DRMID(phys_enc->parent),
+   dpu_encoder_helper_get_intf_type(phys_enc->intf_mode),
+   phys_enc->intf_idx - INTF_0, phys_enc->wb_idx - WB_0,
+   phys_enc->hw_pp->idx - PINGPONG_0, intr_idx);
 
if (phys_enc->parent_ops->handle_frame_done)
phys_enc->parent_ops->handle_frame_done(
@@ -2049,22 +2055,12 @@ static int _dpu_encoder_status_show(struct seq_file *s, 
void *data)
for (i = 0; i < dpu_enc->num_phys_encs; i++) {
struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
 
-   seq_printf(s, "intf:%dvsync:%8d underrun:%8d",
-   phys->intf_idx - INTF_0,
+   seq_printf(s, "intf:%d  wb:%d  vsync:%8d underrun:%8d",
+   phys->intf_idx - INTF_0, phys->wb_idx - WB_0,
atomic_read(>vsync_cnt),
atomic_read(>underrun_cnt));
 
-   switch (phys->intf_mode) {
-   case INTF_MODE_VIDEO:
-   seq_puts(s, "mode: video\n");
-   break;
-   case INTF_MODE_CMD:
-   seq_puts(s, "mode: command\n");
-   break;
-   default:
-   seq_puts(s, "mode: ???\n");
-   break;
-   }
+   seq_printf(s, "mode: %s\n", 
dpu_encoder_helper_get_intf_type(phys->intf_mode));
}
mutex_unlock(_enc->enc_lock);
 
-- 
2.7.4



[PATCH v5 15/19] drm/msm/dpu: initialize dpu encoder and connector for writeback

2022-04-24 Thread Abhinav Kumar
Initialize dpu encoder and connector for writeback if the
target supports it in the catalog.

changes in v2:
- start initialing the encoder for writeback since we
have migrated to using drm_writeback_connector_init_with_encoder()
- instead of checking for WB_2 inside _dpu_kms_initialize_writeback
call it only when its WB_2
- rebase on tip of msm-next and remove usage of priv->encoders

changes in v3:
- none

changes in v4:
- fix copyright years order

Signed-off-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 27 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 61 -
 2 files changed, 80 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 24870eb..2d79002 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2102,7 +2102,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)
 {
@@ -2121,7 +2121,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)) {
@@ -2134,7 +2134,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)) {
@@ -2147,6 +2147,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
@@ -2248,9 +2261,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");
}
@@ -2367,8 +2379,9 @@ 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);
+ drm_enc_mode, NULL);
if (rc) {
devm_kfree(dev->dev, dpu_enc);
return ERR_PTR(rc);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index c683cab..9a406e1 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -1,7 +1,9 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
  * Author: Rob Clark 
  */
 
@@ -15,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "msm_drv.h"
 #include "msm_mmu.h"
@@ -29,6 +32,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"
@@ -648,6 +652,45 @@ 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,
+  

[PATCH v5 09/19] drm/msm/dpu: add an API to reset the encoder related hw blocks

2022-04-24 Thread Abhinav Kumar
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.

changes in v4:
- none

Signed-off-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c  | 85 +++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h |  7 ++
 2 files changed, 91 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 4523693..25c7eda 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1,7 +1,9 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2014-2018, 2020-2021 The Linux Foundation. All rights 
reserved.
  * Copyright (C) 2013 Red Hat
+ * Copyright (c) 2014-2018, 2020-2021 The Linux Foundation. All rights 
reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
  * Author: Rob Clark 
  */
 
@@ -22,6 +24,7 @@
 #include "dpu_hw_ctl.h"
 #include "dpu_hw_dspp.h"
 #include "dpu_hw_dsc.h"
+#include "dpu_hw_merge3d.h"
 #include "dpu_formats.h"
 #include "dpu_encoder_phys.h"
 #include "dpu_crtc.h"
@@ -1838,6 +1841,86 @@ 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);
+
+   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);
+
+   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 *dpu_enc;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h 

[PATCH v5 16/19] drm/msm/dpu: gracefully handle null fb commits for writeback

2022-04-24 Thread Abhinav Kumar
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.

changes in v2:
- rename dpu_encoder_has_valid_fb to dpu_encoder_is_valid_for_commit

changes in v3:
- none

Signed-off-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
---
 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 7763558..d65e124 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_is_valid_for_commit(encoder)) {
+   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 2d79002..90ef807 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1862,6 +1862,27 @@ void dpu_encoder_prepare_for_kickoff(struct drm_encoder 
*drm_enc)
dpu_encoder_prep_dsc(dpu_enc, dpu_enc->dsc);
 }
 
+bool dpu_encoder_is_valid_for_commit(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.is_valid_for_commit && 
!phys->ops.is_valid_for_commit(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 6ceec1d..781d41c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -196,4 +196,10 @@ void dpu_encoder_prepare_wb_job(struct drm_encoder 
*drm_enc,
 void dpu_encoder_cleanup_wb_job(struct drm_encoder *drm_enc,
struct drm_writeback_job *job);
 
+/**
+ * dpu_encoder_is_valid_for_commit - check if encode has valid parameters for 
commit.
+ * @drm_enc:Pointer to drm encoder structure
+ */
+bool dpu_encoder_is_valid_for_commit(struct drm_encoder *drm_enc);
+
 #endif /* __DPU_ENCODER_H__ */
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 bed4523..f2af07d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -142,6 +142,7 @@ struct dpu_encoder_phys_ops {
struct drm_writeback_job *job);
void (*cleanup_wb_job)(struct dpu_encoder_phys *phys_enc,
struct drm_writeback_job *job);
+   bool (*is_valid_for_commit)(struct dpu_encoder_phys *phys_enc);
 };
 
 /**
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
index 4ab2699..cb5c7da 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
@@ -667,6 +667,16 @@ static void dpu_encoder_phys_wb_cleanup_wb_job(struct 
dpu_encoder_phys *phys_enc
wb_enc->wb_conn = NULL;
 }
 
+static bool dpu_encoder_phys_wb_is_valid_for_commit(struct dpu_encoder_phys 
*phys_enc)
+{
+   struct 

[PATCH v5 07/19] drm/msm/dpu: add writeback blocks to DPU RM

2022-04-24 Thread Abhinav Kumar
Add writeback blocks to DPU resource manager so that
the encoders can directly request them through RM.

changes in v4:
- absorb dpu_rm.h header change from [1]
- since its a trivial change absorbed from an approved
  patch, preserving the previous ack on this

[1] https://patchwork.freedesktop.org/patch/483099/?series=102964=2

Signed-off-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 22 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 12 
 2 files changed, 34 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index 0e6634b..06f03e7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -9,6 +9,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_hw_dsc.h"
@@ -87,6 +88,9 @@ int dpu_rm_destroy(struct dpu_rm *rm)
}
}
 
+   for (i = 0; i < ARRAY_SIZE(rm->hw_wb); i++)
+   dpu_hw_wb_destroy(rm->hw_wb[i]);
+
return 0;
 }
 
@@ -186,6 +190,24 @@ int dpu_rm_init(struct dpu_rm *rm,
rm->hw_intf[intf->id - INTF_0] = hw;
}
 
+   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(hw)) {
+   rc = PTR_ERR(hw);
+   DPU_ERROR("failed wb object creation: err %d\n", rc);
+   goto fail;
+   }
+   rm->hw_wb[wb->id - WB_0] = hw;
+   }
+
for (i = 0; i < cat->ctl_count; i++) {
struct dpu_hw_ctl *hw;
const struct dpu_ctl_cfg *ctl = >ctl[i];
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index 32e0d8a..2f34a31 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -19,6 +19,7 @@ struct dpu_global_state;
  * @mixer_blks: array of layer mixer hardware resources
  * @ctl_blks: array of ctl hardware resources
  * @hw_intf: array of intf hardware resources
+ * @hw_wb: array of wb hardware resources
  * @dspp_blks: array of dspp hardware resources
  */
 struct dpu_rm {
@@ -26,6 +27,7 @@ struct dpu_rm {
struct dpu_hw_blk *mixer_blks[LM_MAX - LM_0];
struct dpu_hw_blk *ctl_blks[CTL_MAX - CTL_0];
struct dpu_hw_intf *hw_intf[INTF_MAX - INTF_0];
+   struct dpu_hw_wb *hw_wb[WB_MAX - WB_0];
struct dpu_hw_blk *dspp_blks[DSPP_MAX - DSPP_0];
struct dpu_hw_blk *merge_3d_blks[MERGE_3D_MAX - MERGE_3D_0];
struct dpu_hw_blk *dsc_blks[DSC_MAX - DSC_0];
@@ -96,5 +98,15 @@ static inline struct dpu_hw_intf *dpu_rm_get_intf(struct 
dpu_rm *rm, enum dpu_in
return rm->hw_intf[intf_idx - INTF_0];
 }
 
+/**
+ * dpu_rm_get_wb - Return a struct dpu_hw_wb instance given it's index.
+ * @rm: DPU Resource Manager handle
+ * @wb_idx: WB index
+ */
+static inline struct dpu_hw_wb *dpu_rm_get_wb(struct dpu_rm *rm, enum dpu_wb 
wb_idx)
+{
+   return rm->hw_wb[wb_idx - WB_0];
+}
+
 #endif /* __DPU_RM_H__ */
 
-- 
2.7.4



[PATCH v5 05/19] drm/msm/dpu: rename dpu_hw_pipe_cdp_cfg to dpu_hw_cdp_cfg

2022-04-24 Thread Abhinav Kumar
Rename dpu_hw_pipe_cdp_cfg to dpu_hw_cdp_cfg and move it
to dpu_hw_utils file so that other modules in addition to
SSPP such as writeback can use it as all the fields can
be used by writeback as well.

Suggested-by: Dmitry Baryshkov 
Signed-off-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c |  2 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h | 18 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h | 15 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c   |  4 ++--
 4 files changed, 19 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
index 09cdc35..0a0864d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
@@ -627,7 +627,7 @@ static void dpu_hw_sspp_setup_qos_ctrl(struct dpu_hw_pipe 
*ctx,
 }
 
 static void dpu_hw_sspp_setup_cdp(struct dpu_hw_pipe *ctx,
-   struct dpu_hw_pipe_cdp_cfg *cfg,
+   struct dpu_hw_cdp_cfg *cfg,
enum dpu_sspp_multirect_index index)
 {
u32 idx;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
index 92b071b..a81e166 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
@@ -193,22 +193,6 @@ enum {
 };
 
 /**
- * struct dpu_hw_pipe_cdp_cfg : CDP configuration
- * @enable: true to enable CDP
- * @ubwc_meta_enable: true to enable ubwc metadata preload
- * @tile_amortize_enable: true to enable amortization control for tile format
- * @preload_ahead: number of request to preload ahead
- * DPU_SSPP_CDP_PRELOAD_AHEAD_32,
- * DPU_SSPP_CDP_PRELOAD_AHEAD_64
- */
-struct dpu_hw_pipe_cdp_cfg {
-   bool enable;
-   bool ubwc_meta_enable;
-   bool tile_amortize_enable;
-   u32 preload_ahead;
-};
-
-/**
  * struct dpu_hw_pipe_ts_cfg - traffic shaper configuration
  * @size: size to prefill in bytes, or zero to disable
  * @time: time to prefill in usec, or zero to disable
@@ -359,7 +343,7 @@ struct dpu_hw_sspp_ops {
 * @index: rectangle index in multirect
 */
void (*setup_cdp)(struct dpu_hw_pipe *ctx,
-   struct dpu_hw_pipe_cdp_cfg *cfg,
+   struct dpu_hw_cdp_cfg *cfg,
enum dpu_sspp_multirect_index index);
 };
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h
index 3913475..a200df1 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h
@@ -298,6 +298,21 @@ struct dpu_drm_scaler_v2 {
struct dpu_drm_de_v1 de;
 };
 
+/**
+ * struct dpu_hw_cdp_cfg : CDP configuration
+ * @enable: true to enable CDP
+ * @ubwc_meta_enable: true to enable ubwc metadata preload
+ * @tile_amortize_enable: true to enable amortization control for tile format
+ * @preload_ahead: number of request to preload ahead
+ * DPU_*_CDP_PRELOAD_AHEAD_32,
+ * DPU_*_CDP_PRELOAD_AHEAD_64
+ */
+struct dpu_hw_cdp_cfg {
+   bool enable;
+   bool ubwc_meta_enable;
+   bool tile_amortize_enable;
+   u32 preload_ahead;
+};
 
 u32 *dpu_hw_util_get_log_mask_ptr(void);
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index c77c3d9d..08b8c64 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -1246,9 +1246,9 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane 
*plane)
pstate->multirect_index);
 
if (pdpu->pipe_hw->ops.setup_cdp) {
-   struct dpu_hw_pipe_cdp_cfg cdp_cfg;
+   struct dpu_hw_cdp_cfg cdp_cfg;
 
-   memset(_cfg, 0, sizeof(struct dpu_hw_pipe_cdp_cfg));
+   memset(_cfg, 0, sizeof(struct dpu_hw_cdp_cfg));
 
cdp_cfg.enable = pdpu->catalog->perf.cdp_cfg
[DPU_PERF_CDP_USAGE_RT].rd_enable;
-- 
2.7.4



[PATCH v5 12/19] drm/msm/dpu: move _dpu_plane_get_qos_lut to dpu_hw_util file

2022-04-24 Thread Abhinav Kumar
_dpu_plane_get_qos_lut() is not specific to just dpu_plane.
It can take any fill level and return the LUT matching it.
This can be used even for other modules like dpu_writeback.

Move _dpu_plane_get_qos_lut() to the common dpu_hw_util file
and rename it to _dpu_hw_get_qos_lut().

Signed-off-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c | 25 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h |  4 
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c   | 27 +--
 3 files changed, 30 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c
index aad8511..512316f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c
@@ -422,3 +422,28 @@ void dpu_hw_csc_setup(struct dpu_hw_blk_reg_map *c,
DPU_REG_WRITE(c, csc_reg_off + 0x3c, data->csc_post_bv[1]);
DPU_REG_WRITE(c, csc_reg_off + 0x40, data->csc_post_bv[2]);
 }
+
+/**
+ * _dpu_hw_get_qos_lut - get LUT mapping based on fill level
+ * @tbl:   Pointer to LUT table
+ * @total_fl:  fill level
+ * Return: LUT setting corresponding to the fill level
+ */
+u64 _dpu_hw_get_qos_lut(const struct dpu_qos_lut_tbl *tbl,
+   u32 total_fl)
+{
+   int i;
+
+   if (!tbl || !tbl->nentry || !tbl->entries)
+   return 0;
+
+   for (i = 0; i < tbl->nentry; i++)
+   if (total_fl <= tbl->entries[i].fl)
+   return tbl->entries[i].lut;
+
+   /* if last fl is zero, use as default */
+   if (!tbl->entries[i-1].fl)
+   return tbl->entries[i-1].lut;
+
+   return 0;
+}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h
index a200df1..e4a65eb 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include "dpu_hw_mdss.h"
+#include "dpu_hw_catalog.h"
 
 #define REG_MASK(n) ((BIT(n)) - 1)
 
@@ -339,4 +340,7 @@ void dpu_hw_csc_setup(struct dpu_hw_blk_reg_map  *c,
u32 csc_reg_off,
const struct dpu_csc_cfg *data, bool csc10);
 
+u64 _dpu_hw_get_qos_lut(const struct dpu_qos_lut_tbl *tbl,
+   u32 total_fl);
+
 #endif /* _DPU_HW_UTIL_H */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index 08b8c64..9d2f036 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -280,31 +280,6 @@ static int _dpu_plane_calc_fill_level(struct drm_plane 
*plane,
 }
 
 /**
- * _dpu_plane_get_qos_lut - get LUT mapping based on fill level
- * @tbl:   Pointer to LUT table
- * @total_fl:  fill level
- * Return: LUT setting corresponding to the fill level
- */
-static u64 _dpu_plane_get_qos_lut(const struct dpu_qos_lut_tbl *tbl,
-   u32 total_fl)
-{
-   int i;
-
-   if (!tbl || !tbl->nentry || !tbl->entries)
-   return 0;
-
-   for (i = 0; i < tbl->nentry; i++)
-   if (total_fl <= tbl->entries[i].fl)
-   return tbl->entries[i].lut;
-
-   /* if last fl is zero, use as default */
-   if (!tbl->entries[i-1].fl)
-   return tbl->entries[i-1].lut;
-
-   return 0;
-}
-
-/**
  * _dpu_plane_set_qos_lut - set QoS LUT of the given plane
  * @plane: Pointer to drm plane
  * @fb:Pointer to framebuffer associated with the 
given plane
@@ -333,7 +308,7 @@ static void _dpu_plane_set_qos_lut(struct drm_plane *plane,
lut_usage = DPU_QOS_LUT_USAGE_MACROTILE;
}
 
-   qos_lut = _dpu_plane_get_qos_lut(
+   qos_lut = _dpu_hw_get_qos_lut(
>catalog->perf.qos_lut_tbl[lut_usage], total_fl);
 
trace_dpu_perf_set_qos_luts(pdpu->pipe - SSPP_VIG0,
-- 
2.7.4



[PATCH v5 06/19] drm/msm/dpu: add dpu_hw_wb abstraction for writeback blocks

2022-04-24 Thread Abhinav Kumar
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.

changes in v3:
- start using the common struct dpu_hw_cdp_cfg
- leave a comment about DPU non-DPU_WB_QOS_8LVL chipsets

Signed-off-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/Makefile  |   1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c | 279 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h | 115 
 3 files changed, 395 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 d5ca2e6..ca779c1 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -74,6 +74,7 @@ msm-$(CONFIG_DRM_MSM_DPU) += \
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_kms.o \
disp/dpu1/dpu_plane.o \
disp/dpu1/dpu_rm.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..be2
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
@@ -0,0 +1,279 @@
+// 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_MODE0x004
+#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_BITDEPTH0x024
+#define WB_DST_MATRIX_ROW00x030
+#define WB_DST_MATRIX_ROW10x034
+#define WB_DST_MATRIX_ROW20x038
+#define WB_DST_MATRIX_ROW30x03C
+#define WB_DST_WRITE_CONFIG   0x048
+#define WB_ROTATION_DNSCALER  0x050
+#define WB_ROTATOR_PIPE_DOWNSCALER0x054
+#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_MUX0x150
+#define WB_CROP_CTRL  0x154
+#define WB_CROP_OFFSET0x158
+#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_ENBIT(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;

[PATCH v5 13/19] drm/msm/dpu: introduce the dpu_encoder_phys_* for writeback

2022-04-24 Thread Abhinav Kumar
Introduce the dpu_encoder_phys_* for the writeback interface
to handle writeback specific hardware programming.

changes in v4:
- squash the encoder_phys_wb bits from [1]
- since its a trivial change of a previously acked change
  preserving the ack

[1] https://patchwork.freedesktop.org/patch/483099/?series=102964=2

Signed-off-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/Makefile   |   1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h   |  30 +
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c| 751 +
 3 files changed, 782 insertions(+)
 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 ca779c1..0387f22 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -60,6 +60,7 @@ msm-$(CONFIG_DRM_MSM_DPU) += \
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 a42ed4b..bed4523 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -150,6 +150,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,
@@ -157,6 +158,7 @@ enum dpu_intr_idx {
INTR_IDX_UNDERRUN,
INTR_IDX_CTL_START,
INTR_IDX_RDPTR,
+   INTR_IDX_WB_DONE,
INTR_IDX_MAX,
 };
 
@@ -226,6 +228,27 @@ 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
+ * @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 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
@@ -295,6 +318,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..4ab2699
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
@@ -0,0 +1,751 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#define pr_fmt(fmt)"[drm:%s:%d] " fmt, __func__, __LINE__
+
+#include 
+
+#include "dpu_encoder_phys.h"
+#include "dpu_formats.h"
+#include "dpu_hw_top.h"
+#include "dpu_hw_wb.h"
+#include "dpu_hw_lm.h"
+#include "dpu_hw_blk.h"
+#include "dpu_hw_merge3d.h"
+#include "dpu_hw_interrupts.h"
+#include "dpu_core_irq.h"
+#include "dpu_vbif.h"
+#include "dpu_crtc.h"
+#include "disp/msm_disp_snapshot.h"
+
+#define DEFAULT_MAX_WRITEBACK_WIDTH 2048
+
+#define to_dpu_encoder_phys_wb(x) \
+   container_of(x, struct dpu_encoder_phys_wb, base)
+
+/**
+ * dpu_encoder_phys_wb_is_master - report wb always as master encoder
+ */
+static bool dpu_encoder_phys_wb_is_master(struct dpu_encoder_phys *phys_enc)
+{
+   /* there is only one physical enc for dpu_writeback */
+   return true;
+}
+
+/**
+ * dpu_encoder_phys_wb_set_ot_limit - set OT limit for writeback interface
+ * @phys_enc:  Pointer 

[PATCH v5 14/19] drm/msm/dpu: add the writeback connector layer

2022-04-24 Thread Abhinav Kumar
Introduce the dpu_writeback module which serves as the
interface between dpu operations and the drm_writeback.

This module manages the connector related operations for
dpu writeback.

changes in v2:
- start using drm_writeback_connector_init_with_encoder()
- drop unnecessary arguments from dpu_writeback_init()
- rebase on msm-next tip and remove usage of priv->connectors

changes in v3:
- none

changes in v4:
- none

changes in v5:
- store the drm_enc in the dpu_wb_conn to be used while
  using dpu_encoder APIs

Signed-off-by: Abhinav Kumar 
---
 drivers/gpu/drm/msm/Makefile  |  1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c | 76 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.h | 31 +++
 3 files changed, 108 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.h

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 0387f22..66395ee 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -80,6 +80,7 @@ msm-$(CONFIG_DRM_MSM_DPU) += \
disp/dpu1/dpu_plane.o \
disp/dpu1/dpu_rm.o \
disp/dpu1/dpu_vbif.o \
+   disp/dpu1/dpu_writeback.o
 
 msm-$(CONFIG_DRM_MSM_MDSS) += \
msm_mdss.o \
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c
new file mode 100644
index 000..7620ffe
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include "dpu_writeback.h"
+
+static int dpu_wb_conn_get_modes(struct drm_connector *connector)
+{
+   struct drm_device *dev = connector->dev;
+
+   return drm_add_modes_noedid(connector, dev->mode_config.max_width,
+   dev->mode_config.max_height);
+}
+
+static const struct drm_connector_funcs dpu_wb_conn_funcs = {
+   .reset = drm_atomic_helper_connector_reset,
+   .fill_modes = drm_helper_probe_single_connector_modes,
+   .destroy = drm_connector_cleanup,
+   .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+   .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int dpu_wb_conn_prepare_job(struct drm_writeback_connector *connector,
+   struct drm_writeback_job *job)
+{
+
+   struct dpu_wb_connector *dpu_wb_conn = to_dpu_wb_conn(connector);
+
+   if (!job->fb)
+   return 0;
+
+   dpu_encoder_prepare_wb_job(dpu_wb_conn->wb_enc, job);
+
+   return 0;
+}
+
+static void dpu_wb_conn_cleanup_job(struct drm_writeback_connector *connector,
+   struct drm_writeback_job *job)
+{
+   struct dpu_wb_connector *dpu_wb_conn = to_dpu_wb_conn(connector);
+
+   if (!job->fb)
+   return;
+
+   dpu_encoder_cleanup_wb_job(dpu_wb_conn->wb_enc, job);
+}
+
+static const struct drm_connector_helper_funcs dpu_wb_conn_helper_funcs = {
+   .get_modes = dpu_wb_conn_get_modes,
+   .prepare_writeback_job = dpu_wb_conn_prepare_job,
+   .cleanup_writeback_job = dpu_wb_conn_cleanup_job,
+};
+
+int dpu_writeback_init(struct drm_device *dev, struct drm_encoder *enc,
+   const u32 *format_list, u32 num_formats)
+{
+   struct dpu_wb_connector *dpu_wb_conn;
+   int rc = 0;
+
+   dpu_wb_conn = devm_kzalloc(dev->dev, sizeof(*dpu_wb_conn), GFP_KERNEL);
+
+   drm_connector_helper_add(_wb_conn->base.base, 
_wb_conn_helper_funcs);
+
+   /* DPU initializes the encoder and sets it up completely for writeback
+* cases and hence should use the new API 
drm_writeback_connector_init_with_encoder
+* to initialize the writeback connector
+*/
+   rc = drm_writeback_connector_init_with_encoder(dev, _wb_conn->base, 
enc,
+   _wb_conn_funcs, format_list, num_formats);
+
+   if (!rc)
+   dpu_wb_conn->wb_enc = enc;
+
+   return rc;
+}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.h
new file mode 100644
index 000..5a75ea9
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _DPU_WRITEBACK_H
+#define _DPU_WRITEBACK_H
+
+#include 
+#include 
+#include 
+#include 
+
+#include "msm_drv.h"
+#include "dpu_kms.h"
+#include "dpu_encoder_phys.h"
+
+struct dpu_wb_connector {
+   struct drm_writeback_connector base;
+   struct drm_encoder *wb_enc;
+};
+
+static inline struct dpu_wb_connector *to_dpu_wb_conn(struct 
drm_writeback_connector *conn)
+{
+   return container_of(conn, struct dpu_wb_connector, base);
+}
+
+int 

[PATCH v5 08/19] drm/msm/dpu: add changes to support writeback in hw_ctl

2022-04-24 Thread Abhinav Kumar
Add changes to support writeback module in the dpu_hw_ctl
interface.

changes in v4:
- fix the copyright year order

Signed-off-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 52 --
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 13 
 2 files changed, 63 insertions(+), 2 deletions(-)

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 524f024..254fdf0 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.
  */
 
 #include 
@@ -23,10 +24,12 @@
 #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_FLUSH0x100
 #define   CTL_DSC_ACTIVE0x0E8
 #define   CTL_DSC_FLUSH0x104
+#define   CTL_WB_FLUSH  0x108
 #define   CTL_INTF_FLUSH0x110
 #define   CTL_INTF_MASTER   0x134
 #define   CTL_FETCH_PIPE_ACTIVE 0x0FC
@@ -38,6 +41,7 @@
 #define  MERGE_3D_IDX   23
 #define  DSC_IDX22
 #define  INTF_IDX   31
+#define WB_IDX  16
 #define CTL_INVALID_BIT 0x
 #define CTL_DEFAULT_GROUP_ID   0xf
 
@@ -135,6 +139,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);
 }
@@ -255,6 +262,26 @@ static void dpu_hw_ctl_update_pending_flush_intf(struct 
dpu_hw_ctl *ctx,
}
 }
 
+static void dpu_hw_ctl_update_pending_flush_wb(struct dpu_hw_ctl *ctx,
+   enum dpu_wb wb)
+{
+   switch (wb) {
+   case WB_0:
+   case WB_1:
+   case WB_2:
+   ctx->pending_flush_mask |= BIT(WB_IDX);
+   default:
+   break;
+   }
+}
+
+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)
 {
@@ -504,6 +531,7 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
 {
struct dpu_hw_blk_reg_map *c = >hw;
u32 intf_active = 0;
+   u32 wb_active = 0;
u32 mode_sel = 0;
 
/* CTL_TOP[31:28] carries group_id to collate CTL paths
@@ -520,10 +548,18 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
mode_sel |= BIT(17);
 
intf_active = DPU_REG_READ(c, CTL_INTF_ACTIVE);
-   intf_active |= BIT(cfg->intf - INTF_0);
+   wb_active = DPU_REG_READ(c, CTL_WB_ACTIVE);
+
+   if (cfg->intf)
+   intf_active |= BIT(cfg->intf - INTF_0);
+
+   if (cfg->wb)
+   wb_active |= BIT(cfg->wb - WB_0);
 
DPU_REG_WRITE(c, CTL_TOP, mode_sel);
DPU_REG_WRITE(c, CTL_INTF_ACTIVE, intf_active);
+   DPU_REG_WRITE(c, CTL_WB_ACTIVE, wb_active);
+
if (cfg->merge_3d)
DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE,
  BIT(cfg->merge_3d - MERGE_3D_0));
@@ -546,6 +582,9 @@ static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
intf_cfg |= (cfg->mode_3d - 0x1) << 20;
}
 
+   if (cfg->wb)
+   intf_cfg |= (cfg->wb & 0x3) + 2;
+
switch (cfg->intf_mode_sel) {
case DPU_CTL_MODE_SEL_VID:
intf_cfg &= ~BIT(17);
@@ -568,12 +607,13 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct 
dpu_hw_ctl *ctx,
 {
struct dpu_hw_blk_reg_map *c = >hw;
u32 intf_active = 0;
+   u32 wb_active = 0;
u32 merge3d_active = 0;
 
/*
 * This API resets each portion of the CTL path namely,
 * clearing the sspps staged on the lm, merge_3d block,
-* interfaces etc to ensure clean teardown of the pipeline.
+* interfaces , writeback etc to ensure clean teardown of the pipeline.
 * This will be used for writeback to begin with to have a
 * proper teardown of the writeback session but upon further
 * validation, this can be extended to all interfaces.
@@ -592,6 +632,12 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl 

[PATCH v5 04/19] drm/msm/dpu: add reset_intf_cfg operation for dpu_hw_ctl

2022-04-24 Thread Abhinav Kumar
Add a reset_intf_cfg operation for dpu_hw_ctl to reset the
entire CTL path by disabling each component namely layer mixer,
3d-merge and interface blocks.

changes in v3:
- none

Signed-off-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 32 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h |  8 
 2 files changed, 40 insertions(+)

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 dc27579..524f024 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -563,6 +563,37 @@ static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
DPU_REG_WRITE(c, CTL_TOP, intf_cfg);
 }
 
+static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx,
+   struct dpu_hw_intf_cfg *cfg)
+{
+   struct dpu_hw_blk_reg_map *c = >hw;
+   u32 intf_active = 0;
+   u32 merge3d_active = 0;
+
+   /*
+* This API resets each portion of the CTL path namely,
+* clearing the sspps staged on the lm, merge_3d block,
+* interfaces etc to ensure clean teardown of the pipeline.
+* This will be used for writeback to begin with to have a
+* proper teardown of the writeback session but upon further
+* validation, this can be extended to all interfaces.
+*/
+   if (cfg->merge_3d) {
+   merge3d_active = DPU_REG_READ(c, CTL_MERGE_3D_ACTIVE);
+   merge3d_active &= ~BIT(cfg->merge_3d - MERGE_3D_0);
+   DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE,
+   merge3d_active);
+   }
+
+   dpu_hw_ctl_clear_all_blendstages(ctx);
+
+   if (cfg->intf) {
+   intf_active = DPU_REG_READ(c, CTL_INTF_ACTIVE);
+   intf_active &= ~BIT(cfg->intf - INTF_0);
+   DPU_REG_WRITE(c, CTL_INTF_ACTIVE, intf_active);
+   }
+}
+
 static void dpu_hw_ctl_set_fetch_pipe_active(struct dpu_hw_ctl *ctx,
unsigned long *fetch_active)
 {
@@ -586,6 +617,7 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
if (cap & BIT(DPU_CTL_ACTIVE_CFG)) {
ops->trigger_flush = dpu_hw_ctl_trigger_flush_v1;
ops->setup_intf_cfg = dpu_hw_ctl_intf_cfg_v1;
+   ops->reset_intf_cfg = dpu_hw_ctl_reset_intf_cfg_v1;
ops->update_pending_flush_intf =
dpu_hw_ctl_update_pending_flush_intf_v1;
ops->update_pending_flush_merge_3d =
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
index 97f326d..c61a8fd 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
@@ -140,6 +140,14 @@ struct dpu_hw_ctl_ops {
void (*setup_intf_cfg)(struct dpu_hw_ctl *ctx,
struct dpu_hw_intf_cfg *cfg);
 
+   /**
+* reset ctl_path interface config
+* @ctx: ctl path ctx pointer
+* @cfg: interface config structure pointer
+*/
+   void (*reset_intf_cfg)(struct dpu_hw_ctl *ctx,
+   struct dpu_hw_intf_cfg *cfg);
+
int (*reset)(struct dpu_hw_ctl *c);
 
/*
-- 
2.7.4



[PATCH v5 11/19] drm/msm/dpu: add encoder operations to prepare/cleanup wb job

2022-04-24 Thread Abhinav Kumar
add dpu encoder APIs to prepare and cleanup writeback job
for the writeback encoder. These shall be invoked from the
prepare_wb_job/cleanup_wb_job hooks of the drm_writeback
framework.

changes in v3:
- none

Signed-off-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c  | 34 
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h  | 16 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h |  5 
 3 files changed, 55 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index d1e92d89..24870eb 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -913,6 +913,40 @@ static int dpu_encoder_resource_control(struct drm_encoder 
*drm_enc,
return 0;
 }
 
+void dpu_encoder_prepare_wb_job(struct drm_encoder *drm_enc,
+   struct drm_writeback_job *job)
+{
+   struct dpu_encoder_virt *dpu_enc;
+   int i;
+
+   dpu_enc = to_dpu_encoder_virt(drm_enc);
+
+   for (i = 0; i < dpu_enc->num_phys_encs; i++) {
+   struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
+
+   if (phys->ops.prepare_wb_job)
+   phys->ops.prepare_wb_job(phys, job);
+
+   }
+}
+
+void dpu_encoder_cleanup_wb_job(struct drm_encoder *drm_enc,
+   struct drm_writeback_job *job)
+{
+   struct dpu_encoder_virt *dpu_enc;
+   int i;
+
+   dpu_enc = to_dpu_encoder_virt(drm_enc);
+
+   for (i = 0; i < dpu_enc->num_phys_encs; i++) {
+   struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
+
+   if (phys->ops.cleanup_wb_job)
+   phys->ops.cleanup_wb_job(phys, job);
+
+   }
+}
+
 static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
 struct drm_crtc_state *crtc_state,
 struct drm_connector_state 
*conn_state)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
index 2903e65..6ceec1d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -180,4 +180,20 @@ bool dpu_encoder_is_widebus_enabled(const struct 
drm_encoder *drm_enc);
  */
 bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc);
 
+/**
+ * dpu_encoder_prepare_wb_job - prepare writeback job for the encoder.
+ * @drm_enc:Pointer to previously created drm encoder structure
+ * @job:Pointer to the current drm writeback job
+ */
+void dpu_encoder_prepare_wb_job(struct drm_encoder *drm_enc,
+   struct drm_writeback_job *job);
+
+/**
+ * dpu_encoder_cleanup_wb_job - cleanup writeback job for the encoder.
+ * @drm_enc:Pointer to previously created drm encoder structure
+ * @job:Pointer to the current drm writeback job
+ */
+void dpu_encoder_cleanup_wb_job(struct drm_encoder *drm_enc,
+   struct drm_writeback_job *job);
+
 #endif /* __DPU_ENCODER_H__ */
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 c84b8e8..a42ed4b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -7,6 +7,7 @@
 #ifndef __DPU_ENCODER_PHYS_H__
 #define __DPU_ENCODER_PHYS_H__
 
+#include 
 #include 
 
 #include "dpu_kms.h"
@@ -137,6 +138,10 @@ struct dpu_encoder_phys_ops {
void (*restore)(struct dpu_encoder_phys *phys);
int (*get_line_count)(struct dpu_encoder_phys *phys);
int (*get_frame_count)(struct dpu_encoder_phys *phys);
+   void (*prepare_wb_job)(struct dpu_encoder_phys *phys_enc,
+   struct drm_writeback_job *job);
+   void (*cleanup_wb_job)(struct dpu_encoder_phys *phys_enc,
+   struct drm_writeback_job *job);
 };
 
 /**
-- 
2.7.4



[PATCH v5 10/19] drm/msm/dpu: make changes to dpu_encoder to support virtual encoder

2022-04-24 Thread Abhinav Kumar
Make changes to dpu_encoder to support virtual encoder needed
to support writeback for dpu.

changes in v4:
- squash dpu_encoder pieces from [1]

[1] https://patchwork.freedesktop.org/patch/483099/?series=102964=2

Signed-off-by: Abhinav Kumar 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c  | 94 +++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h |  7 ++
 2 files changed, 83 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 25c7eda..d1e92d89 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1013,9 +1013,18 @@ static void dpu_encoder_virt_atomic_mode_set(struct 
drm_encoder *drm_enc,
if (phys->intf_idx >= INTF_0 && phys->intf_idx < INTF_MAX)
phys->hw_intf = dpu_rm_get_intf(_kms->rm, 
phys->intf_idx);
 
-   if (!phys->hw_intf) {
+   if (phys->wb_idx >= WB_0 && phys->wb_idx < WB_MAX)
+   phys->hw_wb = dpu_rm_get_wb(_kms->rm, phys->wb_idx);
+
+   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;
+   }
+
+   if (phys->hw_intf && phys->hw_wb) {
+   DPU_ERROR_ENC(dpu_enc,
+   "invalid phys both intf and wb block at 
idx: %d\n", i);
return;
}
 
@@ -1163,16 +1172,35 @@ static enum dpu_intf dpu_encoder_get_intf(struct 
dpu_mdss_cfg *catalog,
 {
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;
+   }
}
}
 
return INTF_MAX;
 }
 
+static enum dpu_wb dpu_encoder_get_wb(struct dpu_mdss_cfg *catalog,
+   enum dpu_intf_type type, u32 controller_id)
+{
+   int i = 0;
+
+   if (type != INTF_WB)
+   goto end;
+
+   for (i = 0; i < catalog->wb_count; i++) {
+   if (catalog->wb[i].id == controller_id)
+   return catalog->wb[i].id;
+   }
+
+end:
+   return WB_MAX;
+}
+
 static void dpu_encoder_vblank_callback(struct drm_encoder *drm_enc,
struct dpu_encoder_phys *phy_enc)
 {
@@ -1887,16 +1915,32 @@ void dpu_encoder_helper_phys_cleanup(struct 
dpu_encoder_phys *phys_enc)
 
dpu_encoder_helper_reset_mixers(phys_enc);
 
-   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);
+   /*
+* TODO: move the once-only operation like CTL flush/trigger
+* into dpu_encoder_virt_disable() and all operations which need
+* to be done per phys encoder into the phys_disable() op.
+*/
+   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 */
+ 

[PATCH v5 03/19] drm/msm/dpu: add writeback blocks to the sm8250 DPU catalog

2022-04-24 Thread Abhinav Kumar
Add writeback blocks to the sm8250 DPU hardware catalog. Other
chipsets support writeback too but add it to sm8250 to prototype
the feature so that it can be easily extended to other chipsets.

changes in v4:
- fix the copyright year order

Signed-off-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 72 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 66 ++-
 2 files changed, 137 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
index b0a0ef7..7e3f0f4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.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.
  */
 
 #define pr_fmt(fmt)"[drm:%s:%d] " fmt, __func__, __LINE__
@@ -120,6 +121,16 @@
  BIT(MDP_AD4_0_INTR) | \
  BIT(MDP_AD4_1_INTR))
 
+#define WB_SM8250_MASK (BIT(DPU_WB_LINE_MODE) | \
+BIT(DPU_WB_UBWC) | \
+BIT(DPU_WB_YUV_CONFIG) | \
+BIT(DPU_WB_PIPE_ALPHA) | \
+BIT(DPU_WB_XY_ROI_OFFSET) | \
+BIT(DPU_WB_QOS) | \
+BIT(DPU_WB_QOS_8LVL) | \
+BIT(DPU_WB_CDP) | \
+BIT(DPU_WB_INPUT_CTRL))
+
 #define DEFAULT_PIXEL_RAM_SIZE (50 * 1024)
 #define DEFAULT_DPU_LINE_WIDTH 2048
 #define DEFAULT_DPU_OUTPUT_LINE_WIDTH  2560
@@ -211,6 +222,40 @@ static const u32 rotation_v2_formats[] = {
/* TODO add formats after validation */
 };
 
+static const uint32_t wb2_formats[] = {
+   DRM_FORMAT_RGB565,
+   DRM_FORMAT_BGR565,
+   DRM_FORMAT_RGB888,
+   DRM_FORMAT_ARGB,
+   DRM_FORMAT_RGBA,
+   DRM_FORMAT_ABGR,
+   DRM_FORMAT_XRGB,
+   DRM_FORMAT_RGBX,
+   DRM_FORMAT_XBGR,
+   DRM_FORMAT_ARGB1555,
+   DRM_FORMAT_RGBA5551,
+   DRM_FORMAT_XRGB1555,
+   DRM_FORMAT_RGBX5551,
+   DRM_FORMAT_ARGB,
+   DRM_FORMAT_RGBA,
+   DRM_FORMAT_RGBX,
+   DRM_FORMAT_XRGB,
+   DRM_FORMAT_BGR565,
+   DRM_FORMAT_BGR888,
+   DRM_FORMAT_ABGR,
+   DRM_FORMAT_BGRA,
+   DRM_FORMAT_BGRX,
+   DRM_FORMAT_XBGR,
+   DRM_FORMAT_ABGR1555,
+   DRM_FORMAT_BGRA5551,
+   DRM_FORMAT_XBGR1555,
+   DRM_FORMAT_BGRX5551,
+   DRM_FORMAT_ABGR,
+   DRM_FORMAT_BGRA,
+   DRM_FORMAT_BGRX,
+   DRM_FORMAT_XBGR,
+};
+
 /*
  * DPU sub blocks config
  */
@@ -448,6 +493,8 @@ static const struct dpu_mdp_cfg sm8250_mdp[] = {
.reg_off = 0x2C4, .bit_off = 8},
.clk_ctrls[DPU_CLK_CTRL_REG_DMA] = {
.reg_off = 0x2BC, .bit_off = 20},
+   .clk_ctrls[DPU_CLK_CTRL_WB2] = {
+   .reg_off = 0x3B8, .bit_off = 24},
},
 };
 
@@ -1235,6 +1282,29 @@ static const struct dpu_intf_cfg qcm2290_intf[] = {
 };
 
 /*
+ * Writeback blocks config
+ */
+#define WB_BLK(_name, _id, _base, _features, _clk_ctrl, \
+   __xin_id, vbif_id, _reg, _wb_done_bit) \
+   { \
+   .name = _name, .id = _id, \
+   .base = _base, .len = 0x2c8, \
+   .features = _features, \
+   .format_list = wb2_formats, \
+   .num_formats = ARRAY_SIZE(wb2_formats), \
+   .clk_ctrl = _clk_ctrl, \
+   .xin_id = __xin_id, \
+   .vbif_idx = vbif_id, \
+   .maxlinewidth = DEFAULT_DPU_LINE_WIDTH, \
+   .intr_wb_done = DPU_IRQ_IDX(_reg, _wb_done_bit) \
+   }
+
+static const struct dpu_wb_cfg sm8250_wb[] = {
+   WB_BLK("wb_2", WB_2, 0x65000, WB_SM8250_MASK, DPU_CLK_CTRL_WB2, 6,
+   VBIF_RT, MDP_SSPP_TOP0_INTR, 4),
+};
+
+/*
  * VBIF sub blocks config
  */
 /* VBIF QOS remap */
@@ -1832,6 +1902,8 @@ static void sm8250_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
.intf = sm8150_intf,
.vbif_count = ARRAY_SIZE(sdm845_vbif),
.vbif = sdm845_vbif,
+   .wb_count = ARRAY_SIZE(sm8250_wb),
+   .wb = sm8250_wb,
.reg_dma_count = 1,
.dma_cfg = sm8250_regdma,
.perf = sm8250_perf_data,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
index 866fd7a..8cb6d1f 

[PATCH v5 01/19] drm: allow passing possible_crtcs to drm_writeback_connector_init()

2022-04-24 Thread Abhinav Kumar
Clients of drm_writeback_connector_init() initialize the
possible_crtcs and then invoke the call to this API.

To simplify things, allow passing possible_crtcs as a parameter
to drm_writeback_connector_init() and make changes to the
other drm drivers to make them compatible with this change.

changes in v2:
- split the changes according to their functionality

changes in v3:
- allow passing possible_crtcs for existing users of
  drm_writeback_connector_init()
- squash the vendor changes into the same commit so
  that each patch in the series can compile individually

changes in v4:
- keep only changes related to possible_crtcs
- add line breaks after ARRAY_SIZE
- stop using temporary variables for possible_crtcs

changes in v5:
- None

changes in v6:
- None

changes in v7:
- wrap long lines to match the coding style of existing drivers
- Fix indentation and remove parenthesis where not needed
- use u32 instead of uint32_t for possible_crtcs

Signed-off-by: Abhinav Kumar 
Acked-by: Liviu Dudau 
Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Laurent Pinchart 
---
 drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c | 4 ++--
 drivers/gpu/drm/arm/malidp_mw.c  | 4 ++--
 drivers/gpu/drm/drm_writeback.c  | 7 ++-
 drivers/gpu/drm/rcar-du/rcar_du_writeback.c  | 4 ++--
 drivers/gpu/drm/vc4/vc4_txp.c| 3 ++-
 drivers/gpu/drm/vkms/vkms_writeback.c| 4 ++--
 include/drm/drm_writeback.h  | 3 ++-
 7 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c 
b/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c
index e465cc4..ce4b760 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c
@@ -155,7 +155,6 @@ static int komeda_wb_connector_add(struct komeda_kms_dev 
*kms,
kwb_conn->wb_layer = kcrtc->master->wb_layer;
 
wb_conn = _conn->base;
-   wb_conn->encoder.possible_crtcs = BIT(drm_crtc_index(>base));
 
formats = komeda_get_layer_fourcc_list(>fmt_tbl,
   kwb_conn->wb_layer->layer_type,
@@ -164,7 +163,8 @@ static int komeda_wb_connector_add(struct komeda_kms_dev 
*kms,
err = drm_writeback_connector_init(>base, wb_conn,
   _wb_connector_funcs,
   _wb_encoder_helper_funcs,
-  formats, n_formats);
+  formats, n_formats,
+  BIT(drm_crtc_index(>base)));
komeda_put_fourcc_list(formats);
if (err) {
kfree(kwb_conn);
diff --git a/drivers/gpu/drm/arm/malidp_mw.c b/drivers/gpu/drm/arm/malidp_mw.c
index f5847a7..204c869 100644
--- a/drivers/gpu/drm/arm/malidp_mw.c
+++ b/drivers/gpu/drm/arm/malidp_mw.c
@@ -212,7 +212,6 @@ int malidp_mw_connector_init(struct drm_device *drm)
if (!malidp->dev->hw->enable_memwrite)
return 0;
 
-   malidp->mw_connector.encoder.possible_crtcs = 1 << 
drm_crtc_index(>crtc);
drm_connector_helper_add(>mw_connector.base,
 _mw_connector_helper_funcs);
 
@@ -223,7 +222,8 @@ int malidp_mw_connector_init(struct drm_device *drm)
ret = drm_writeback_connector_init(drm, >mw_connector,
   _mw_connector_funcs,
   _mw_encoder_helper_funcs,
-  formats, n_formats);
+  formats, n_formats,
+  1 << drm_crtc_index(>crtc));
kfree(formats);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/drm_writeback.c b/drivers/gpu/drm/drm_writeback.c
index dccf4504..9e0b845 100644
--- a/drivers/gpu/drm/drm_writeback.c
+++ b/drivers/gpu/drm/drm_writeback.c
@@ -157,6 +157,7 @@ static const struct drm_encoder_funcs 
drm_writeback_encoder_funcs = {
  * @enc_helper_funcs: Encoder helper funcs vtable to be used by the internal 
encoder
  * @formats: Array of supported pixel formats for the writeback engine
  * @n_formats: Length of the formats array
+ * @possible_crtcs: possible crtcs for the internal writeback encoder
  *
  * This function creates the writeback-connector-specific properties if they
  * have not been already created, initializes the connector as
@@ -174,7 +175,8 @@ int drm_writeback_connector_init(struct drm_device *dev,
 struct drm_writeback_connector *wb_connector,
 const struct drm_connector_funcs *con_funcs,
 const struct drm_encoder_helper_funcs 

[PATCH v5 02/19] drm: introduce drm_writeback_connector_init_with_encoder() API

2022-04-24 Thread Abhinav Kumar
For vendors drivers which pass an already allocated and
initialized encoder especially for cases where the encoder
hardware is shared OR the writeback encoder shares the resources
with the rest of the display pipeline introduce a new API,
drm_writeback_connector_init_with_encoder() which expects
an initialized encoder as a parameter and only sets up the
writeback connector.

changes in v5:
- fix the encoder doc to indicate that its not valid for
  users of drm_writeback_connector_init_with_encoder()

Reviewed-by: Liviu Dudau 
Signed-off-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Laurent Pinchart 
---
 drivers/gpu/drm/drm_writeback.c | 72 +
 include/drm/drm_writeback.h |  8 +
 2 files changed, 66 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/drm_writeback.c b/drivers/gpu/drm/drm_writeback.c
index 9e0b845..99fd15d 100644
--- a/drivers/gpu/drm/drm_writeback.c
+++ b/drivers/gpu/drm/drm_writeback.c
@@ -178,6 +178,62 @@ int drm_writeback_connector_init(struct drm_device *dev,
 const u32 *formats, int n_formats,
 u32 possible_crtcs)
 {
+   int ret = 0;
+
+   drm_encoder_helper_add(_connector->encoder, enc_helper_funcs);
+
+   wb_connector->encoder.possible_crtcs = possible_crtcs;
+
+   ret = drm_encoder_init(dev, _connector->encoder,
+  _writeback_encoder_funcs,
+  DRM_MODE_ENCODER_VIRTUAL, NULL);
+   if (ret)
+   return ret;
+
+   ret = drm_writeback_connector_init_with_encoder(dev, wb_connector, 
_connector->encoder,
+   con_funcs, formats, n_formats);
+
+   if (ret)
+   drm_encoder_cleanup(_connector->encoder);
+
+   return ret;
+}
+EXPORT_SYMBOL(drm_writeback_connector_init);
+
+/**
+ * drm_writeback_connector_init_with_encoder - Initialize a writeback 
connector with
+ * a custom encoder
+ *
+ * @dev: DRM device
+ * @wb_connector: Writeback connector to initialize
+ * @enc: handle to the already initialized drm encoder
+ * @con_funcs: Connector funcs vtable
+ * @formats: Array of supported pixel formats for the writeback engine
+ * @n_formats: Length of the formats array
+ *
+ * This function creates the writeback-connector-specific properties if they
+ * have not been already created, initializes the connector as
+ * type DRM_MODE_CONNECTOR_WRITEBACK, and correctly initializes the property
+ * values.
+ *
+ * This function assumes that the drm_writeback_connector's encoder has 
already been
+ * created and initialized before invoking this function.
+ *
+ * In addition, this function also assumes that callers of this API will manage
+ * assigning the encoder helper functions, possible_crtcs and any other encoder
+ * specific operation.
+ *
+ * Drivers should always use this function instead of drm_connector_init() to
+ * set up writeback connectors if they want to manage themselves the lifetime 
of the
+ * associated encoder.
+ *
+ * Returns: 0 on success, or a negative error code
+ */
+int drm_writeback_connector_init_with_encoder(struct drm_device *dev,
+   struct drm_writeback_connector *wb_connector, struct 
drm_encoder *enc,
+   const struct drm_connector_funcs *con_funcs, const u32 *formats,
+   int n_formats)
+{
struct drm_property_blob *blob;
struct drm_connector *connector = _connector->base;
struct drm_mode_config *config = >mode_config;
@@ -191,15 +247,6 @@ int drm_writeback_connector_init(struct drm_device *dev,
if (IS_ERR(blob))
return PTR_ERR(blob);
 
-   drm_encoder_helper_add(_connector->encoder, enc_helper_funcs);
-
-   wb_connector->encoder.possible_crtcs = possible_crtcs;
-
-   ret = drm_encoder_init(dev, _connector->encoder,
-  _writeback_encoder_funcs,
-  DRM_MODE_ENCODER_VIRTUAL, NULL);
-   if (ret)
-   goto fail;
 
connector->interlace_allowed = 0;
 
@@ -208,8 +255,7 @@ int drm_writeback_connector_init(struct drm_device *dev,
if (ret)
goto connector_fail;
 
-   ret = drm_connector_attach_encoder(connector,
-   _connector->encoder);
+   ret = drm_connector_attach_encoder(connector, enc);
if (ret)
goto attach_fail;
 
@@ -238,12 +284,10 @@ int drm_writeback_connector_init(struct drm_device *dev,
 attach_fail:
drm_connector_cleanup(connector);
 connector_fail:
-   drm_encoder_cleanup(_connector->encoder);
-fail:
drm_property_blob_put(blob);
return ret;
 }
-EXPORT_SYMBOL(drm_writeback_connector_init);
+EXPORT_SYMBOL(drm_writeback_connector_init_with_encoder);
 
 int drm_writeback_set_fb(struct drm_connector_state *conn_state,
 struct drm_framebuffer *fb)
diff --git 

[PATCH v5 00/19] Add writeback block support for DPU

2022-04-24 Thread Abhinav Kumar
This series adds support for writeback block on DPU. Writeback
block is extremely useful to validate boards having no physical displays
in addition to many other use-cases where we want to get the output
of the display pipeline to examine whether issue is with the display
pipeline or with the panel.

These changes have been validated on SM8250 RB5 boards with IGT KMS
writeback test-suite thereby further increasing the IGT test coverage
for DPU. I am sharing the test results below.

root@linaro-developer:~/igt_repo/igt-gpu-tools/build/tests# ./kms_writeback
[   35.066157] Console: switching to colour dummy device 80x25
[   35.071964] [IGT] kms_writeback: executing
IGT-Version: 1.26-gae2eb9e1 (aarch64) (Linux: 5.16.0-rc2-62171-g132577e2697b 
aarch64)
[   35.611418] [IGT] kms_writeback: starting subtest writeback-pixel-formats
Starting subtest: writeback-pixel-formats
[   35.618528] [IGT] kms_writeback: starting subtest 
writeback-invalid-parameters
Subtest writeback-pixel-formats: SUCCESS (0.000s)
Starting subtest: writeback-invalid-parameters
Subtest writeback-invalid-parameters: SUCCESS (0.028s)   35.657437] [IGT] 
kms_writeback: starting subtest writeback-fb-id
Starting subtest: writeback-fb-id
Subtest writeback-fb-id: SUCCESS (0.030s)
[   35.698957] [IGT] kms_writeback: starting subtest writeback-check-output
Starting subtest: writeback-check-output
[   35.852834] [IGT] kms_writeback: exiting, ret=0
Subtest writeback-check-output: SUCCESS (0.142s)
[   35.861291] Console: switching to colour frame buffer device 240x67
root@linaro-developer:~/igt_repo/igt-gpu-tools/build/tests# 

The changes can easily be extended to support any other chipset using
the DPU driver by adding the support in the catalog.

Writeback block supports various formats and features. The support
for all of them can be incrementally added on top of this framework when
validation is improved and the test frameworks are extended to validate
them.

changes in v5:
- fix drm_writeback_connector_init_with_encoder() API doc as
  suggested by Laurent  
- fix encoder doc as suggested by Laurent
- drop 
https://patchwork.freedesktop.org/patch/483118/?series=99724=4
  and let individual drivers manage the encoder 

Abhinav Kumar (19):
  drm: allow passing possible_crtcs to drm_writeback_connector_init()
  drm: introduce drm_writeback_connector_init_with_encoder() API
  drm/msm/dpu: add writeback blocks to the sm8250 DPU catalog
  drm/msm/dpu: add reset_intf_cfg operation for dpu_hw_ctl
  drm/msm/dpu: rename dpu_hw_pipe_cdp_cfg to dpu_hw_cdp_cfg
  drm/msm/dpu: add dpu_hw_wb abstraction for writeback blocks
  drm/msm/dpu: add writeback blocks to DPU RM
  drm/msm/dpu: add changes to support writeback in hw_ctl
  drm/msm/dpu: add an API to reset the encoder related hw blocks
  drm/msm/dpu: make changes to dpu_encoder to support virtual encoder
  drm/msm/dpu: add encoder operations to prepare/cleanup wb job
  drm/msm/dpu: move _dpu_plane_get_qos_lut to dpu_hw_util file
  drm/msm/dpu: introduce the dpu_encoder_phys_* for writeback
  drm/msm/dpu: add the writeback connector layer
  drm/msm/dpu: initialize dpu encoder and connector for writeback
  drm/msm/dpu: gracefully handle null fb commits for writeback
  drm/msm/dpu: add writeback blocks to the display snapshot
  drm/msm/dpu: add wb_idx to existing DRM prints in dpu_encoder
  drm/msm/dpu: add wb_idx to DRM traces in dpu_encoder

 .../drm/arm/display/komeda/komeda_wb_connector.c   |   4 +-
 drivers/gpu/drm/arm/malidp_mw.c|   4 +-
 drivers/gpu/drm/drm_writeback.c|  73 +-
 drivers/gpu/drm/msm/Makefile   |   3 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c   |   9 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c| 306 +++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h|  22 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h   |  50 ++
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c| 763 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c |  72 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h |  66 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c |  82 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h |  21 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c|   2 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h|  18 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c|  25 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h|  19 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c  | 279 
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h  | 115 
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c|  66 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c  |  31 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c |  22 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h |  12 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h  |  26 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c  |  76 ++
 

Re: [Freedreno] [PATCH v4 03/20] drm: allow real encoder to be passed for drm_writeback_connector

2022-04-24 Thread Abhinav Kumar

Hi Laurent

On 4/24/2022 2:12 PM, Abhinav Kumar wrote:

Hi Laurent

On 4/24/2022 12:59 PM, Laurent Pinchart wrote:

Hi Abhinav,

On Sun, Apr 24, 2022 at 11:23:20AM -0700, Abhinav Kumar wrote:

On 4/24/2022 11:12 AM, Abhinav Kumar wrote:

On 4/24/2022 7:50 AM, Laurent Pinchart wrote:

On Fri, Apr 22, 2022 at 04:06:38PM -0700, Abhinav Kumar wrote:

For some vendor driver implementations, display hardware can
be shared between the encoder used for writeback and the physical
display.

In addition resources such as clocks and interrupts can
also be shared between writeback and the real encoder.

To accommodate such vendor drivers and hardware, allow
real encoder to be passed for drm_writeback_connector.

For existing clients, drm_writeback_connector_init() will use
an internal_encoder under the hood and hence no changes will
be needed.

changes in v7:
 - move this change before the vc4 change in the series
   to minimize the changes to vendor drivers in drm core
   changes


Why is this needed ? The drm_writeback_connector functions don't need
the drm_encoder after drm_writeback_connector_init() (or
drm_writeback_connector_init_with_encoder()) returns.



Sorry I didnt follow this comment. This change log is incorrect, so
after changing the previous change in the series and modifying this, no
further changes are needed to vc4, so I decided to drop the next 
change.

So this change log is incorrect. I can remove this.

Is that what you meant?


So till the previous change, the only user of
drm_writeback_connector_init_with_encoder() was
drm_writeback_connector_init() which was still passing its own
internal_encoder.

Only if the wb_connector->encoder is changed to a pointer, other vendor
drivers can pass their own encoder to
drm_writeback_connector_init_with_encoder().

Hence you are right that drm_writeback_connector functions do not need
drm_encoder after init() returns, but till this change is done, other
vendor drivers cannot directly call
drm_writeback_connector_init_with_encoder() because the encoder will not
be valid till then.


Users of drm_writeback_connector_init_with_encoder() handle the encoder
themselves, they can simply ignore drm_writeback_connector.encoder. The
documentation of the encoder field needs to be updated though (I'd do so
in the previous patch), to clearly mention that the field is valid only
when using drm_writeback_connector_init(), not when calling
drm_writeback_connector_init_with_encoder().


So you are suggesting to drop this change and just update the doc in 
patch 2?


If so, I dont think it would be correct to assume that even though 
drm_writeback_connector_init_with_encoder() is used 
drm_writeback_connector.encoder should not be used.


The reason is that, lets consider, prepare_wb_job() and 
cleanup_writeback_job().


These pass only the connector to the vendor hooks.

1126  *
1127  * This callback is used by the atomic modeset helpers.
1128  */
1129 int (*prepare_writeback_job)(struct drm_writeback_connector 
*connector,

1130  struct drm_writeback_job *job);

Now, if you assume connector->encoder is not valid, this adds more 
confusion because now we are putting an extra condition that 
connector->encoder is not valid anymore.


Thats why I think we should leave it as-it-is to not allow room for such 
discrepancies.


I was able to abandon this change and still make writeback work with 
just trivial changes to MSM driver.


So we are okay to drop this change as you requested and let the vendor 
driver manage the encoder completely.


If you do think that this change is worth re-visiting sometime, let me 
know I can absorb it as a separate change.


Thanks

Abhinav





Hope this clarifies it.


Signed-off-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
---
   drivers/gpu/drm/drm_writeback.c | 18 --
   drivers/gpu/drm/vc4/vc4_txp.c   |  4 ++--
   include/drm/drm_writeback.h | 22 --
   3 files changed, 34 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/drm_writeback.c
b/drivers/gpu/drm/drm_writeback.c
index 92658ad..0538674 100644
--- a/drivers/gpu/drm/drm_writeback.c
+++ b/drivers/gpu/drm/drm_writeback.c
@@ -180,21 +180,21 @@ int drm_writeback_connector_init(struct
drm_device *dev,
   {
   int ret = 0;
-    drm_encoder_helper_add(_connector->encoder, 
enc_helper_funcs);
+    drm_encoder_helper_add(_connector->internal_encoder, 
enc_helper_funcs);

-    wb_connector->encoder.possible_crtcs = possible_crtcs;
+    wb_connector->internal_encoder.possible_crtcs = possible_crtcs;
-    ret = drm_encoder_init(dev, _connector->encoder,
+    ret = drm_encoder_init(dev, _connector->internal_encoder,
  _writeback_encoder_funcs,
  DRM_MODE_ENCODER_VIRTUAL, NULL);
   if (ret)
   return ret;
-    ret = drm_writeback_connector_init_with_encoder(dev, 
wb_connector, _connector->encoder,

-    con_funcs, formats, 

Re: [PATCH] drm: rcar-du: Add setting to PnALPHAR register on Gen3

2022-04-24 Thread Laurent Pinchart
Hi Biju,

On Sun, Apr 24, 2022 at 04:12:08PM +, Biju Das wrote:
> > Subject: Re: [PATCH] drm: rcar-du: Add setting to PnALPHAR register on Gen3
> > On Sat, Apr 23, 2022 at 08:37:28AM +0100, Biju Das wrote:
> > > From: LUU HOAI 
> > >
> > > In Gen3, when Alpha blend is enabled in the PnMR register, depending
> > > on the initial value of the PnALPHAR register, either channel of DU
> > > might be black screen.
> > > Therefore, this patch prevents the black screen by setting the
> > > PnALPHAR register to all 0.
> > >
> > > In addition, PnALPHAR register will be released in the R-Car Gen3
> > > Hardware Manual Rev 2.4 (Sep. 2021).
> > >
> > > Signed-off-by: LUU HOAI 
> > > Signed-off-by: Biju Das 
> > > ---
> > > This patch is based on [1]
> > > [1]
> > >
> > > Not sure this patches has to go with Fixes tag for stable??
> > >
> > > Tested the changes on RZ/G2M board
> > >
> > > root@hihope-rzg2m:/cip-test-scripts#  modetest -M rcar-du -w
> > > 54:alpha:5 root@hihope-rzg2m:/cip-test-scripts# modetest -M rcar-du
> > -s "93@90:1024x768@AR24" -d -P "54@90:400x300+200+200@XR24"
> > > setting mode 1024x768-75Hz@AR24 on connectors 93, crtc 90 testing
> > > 400x300@XR24 overlay plane 54
> > > ---
> > >  drivers/gpu/drm/rcar-du/rcar_du_plane.c | 6 ++
> > >  1 file changed, 6 insertions(+)
> > >
> > > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> > > b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> > > index 5c1c7bb04f3f..aff39b9253f8 100644
> > > --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> > > +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> > > @@ -510,6 +510,12 @@ static void
> > > rcar_du_plane_setup_format_gen3(struct rcar_du_group *rgrp,
> > >
> > >   rcar_du_plane_write(rgrp, index, PnDDCR4,
> > >   state->format->edf | PnDDCR4_CODE);
> > > +
> > > + /* In Gen3, PnALPHAR register need to be set to 0
> > > +  * to avoid black screen issue when alpha blend is enable
> > > +  * on DU module
> > > +  */
> > 
> > Comments should start with /* on a line of its own, and you can also
> > reflow the text to 80 columns:
> 
> OK.
> 
> > /*
> >  * In Gen3, PnALPHAR register need to be set to 0 to avoid black screen
> >  * issue when alpha blend is enable on DU module.
> >  */
> > 
> > It would however be nicer to document the exact behaviour, but the latest
> > version of the documentation I have access to is rev 2.3 and it lists
> > PnALPHAR as not available on Gen3.
> 
> I don't have access to rev 2.4, but I got access to 
> "R-Car-Gen3_Common_OPC_Customer_Notifications_V30.1.pdf" 
> where it is mentioned about this issue and solution for fix
> which is inline with the patch from R-Car BSP.
> 
> "The reason is that a register is not initialized by reset.
> This could lead to output wrong image data of other plane or 
> wrong color set from BPOR (Background plane output register)."
> 
> > Furthermore, is this really the right fix, shouldn't we instead avoid
> > enabling alpha-blending in PnMR on Gen3 ?
> 
> Avoid enabling alpha-blending in PnMR on Gen3, will it help here?

It's hard to tell without knowing the exact cause of the issue. Clearing
PnALPHAR probably makes sense on Gen3 if the register exists,
independently from disabling alpha blending in PnMR. It would be nice if
the commit messsage could reference the issue described in
R-Car-Gen3_Common_OPC_Customer_Notifications_V30.1.pdf. I would also
expand the comment a little bit:

 /*
  * On Gen3, some DU channels have two planes, each being wired to a separate
  * VSPD instance. The DU can then blend two two planes. While this feature
  * isn't used by the driver, issues related to alpha blending (such as
  * incorrect colors or planes being invisible) may still occur if the PnALPHAR
  * register has a stale value. Set the register to 0 to avoid this.
  */

> Here the issue they mentioned as "register is not initialized by reset"
> 
> > > + rcar_du_plane_write(rgrp, index, PnALPHAR, 0x);

I'd write 0 instead of 0x to match the rest of the driver.

Would you mind sending a v2 with these changed and an expanded commit
message ?

> > >  }
> > >
> > >  static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,

-- 
Regards,

Laurent Pinchart


[PATCH] drm: rcar-du: Drop file name from comment header blocks

2022-04-24 Thread Laurent Pinchart
The comment blocks at the beginning of each file have a one-line
summary description of the file that includes the file name. While the
description is useful, the file name only creates opportunities for
mistakes (as seen in rcar_du_vsp.c) without any added value. Drop it.

Reported-by: Biju Das 
Suggested-by: Geert Uytterhoeven 
Signed-off-by: Laurent Pinchart 
---
 drivers/gpu/drm/rcar-du/rcar_cmm.c   | 2 +-
 drivers/gpu/drm/rcar-du/rcar_cmm.h   | 2 +-
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c   | 2 +-
 drivers/gpu/drm/rcar-du/rcar_du_crtc.h   | 2 +-
 drivers/gpu/drm/rcar-du/rcar_du_drv.c| 2 +-
 drivers/gpu/drm/rcar-du/rcar_du_drv.h| 2 +-
 drivers/gpu/drm/rcar-du/rcar_du_encoder.c| 2 +-
 drivers/gpu/drm/rcar-du/rcar_du_encoder.h| 2 +-
 drivers/gpu/drm/rcar-du/rcar_du_group.c  | 2 +-
 drivers/gpu/drm/rcar-du/rcar_du_group.h  | 2 +-
 drivers/gpu/drm/rcar-du/rcar_du_kms.c| 2 +-
 drivers/gpu/drm/rcar-du/rcar_du_kms.h| 2 +-
 drivers/gpu/drm/rcar-du/rcar_du_plane.c  | 2 +-
 drivers/gpu/drm/rcar-du/rcar_du_plane.h  | 2 +-
 drivers/gpu/drm/rcar-du/rcar_du_regs.h   | 2 +-
 drivers/gpu/drm/rcar-du/rcar_du_vsp.c| 2 +-
 drivers/gpu/drm/rcar-du/rcar_du_vsp.h| 2 +-
 drivers/gpu/drm/rcar-du/rcar_du_writeback.c  | 2 +-
 drivers/gpu/drm/rcar-du/rcar_du_writeback.h  | 2 +-
 drivers/gpu/drm/rcar-du/rcar_lvds.c  | 2 +-
 drivers/gpu/drm/rcar-du/rcar_lvds.h  | 2 +-
 drivers/gpu/drm/rcar-du/rcar_lvds_regs.h | 2 +-
 drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c  | 2 +-
 drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h | 2 +-
 24 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.c 
b/drivers/gpu/drm/rcar-du/rcar_cmm.c
index 382d53f8a22e..e2a67dda4658 100644
--- a/drivers/gpu/drm/rcar-du/rcar_cmm.c
+++ b/drivers/gpu/drm/rcar-du/rcar_cmm.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * rcar_cmm.c -- R-Car Display Unit Color Management Module
+ * R-Car Display Unit Color Management Module
  *
  * Copyright (C) 2019 Jacopo Mondi 
  */
diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.h 
b/drivers/gpu/drm/rcar-du/rcar_cmm.h
index b5f7ec6db04a..628072acc98b 100644
--- a/drivers/gpu/drm/rcar-du/rcar_cmm.h
+++ b/drivers/gpu/drm/rcar-du/rcar_cmm.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0+ */
 /*
- * rcar_cmm.h -- R-Car Display Unit Color Management Module
+ * R-Car Display Unit Color Management Module
  *
  * Copyright (C) 2019 Jacopo Mondi 
  */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c 
b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 23e1aedf8dc0..621bbccb95d4 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * rcar_du_crtc.c  --  R-Car Display Unit CRTCs
+ * R-Car Display Unit CRTCs
  *
  * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h 
b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
index 66e8839db708..d0f38a8b3561 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0+ */
 /*
- * rcar_du_crtc.h  --  R-Car Display Unit CRTCs
+ * R-Car Display Unit CRTCs
  *
  * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c 
b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 1bc7325aa356..70d85610d720 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * rcar_du_drv.c  --  R-Car Display Unit DRM driver
+ * R-Car Display Unit DRM driver
  *
  * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h 
b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index 83530721e373..bfad7775d9a1 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0+ */
 /*
- * rcar_du_drv.h  --  R-Car Display Unit DRM driver
+ * R-Car Display Unit DRM driver
  *
  * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c 
b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index 3977aaa1ab5a..bf76a60776bd 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * rcar_du_encoder.c  --  R-Car Display Unit Encoder
+ * R-Car Display Unit Encoder
  *
  * Copyright (C) 2013-2014 Renesas Electronics Corporation
  *
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h 
b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
index 73560563fb31..e5ec8fbb3979 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: 

Re: [Freedreno] [PATCH v4 03/20] drm: allow real encoder to be passed for drm_writeback_connector

2022-04-24 Thread Abhinav Kumar

Hi Laurent

On 4/24/2022 12:59 PM, Laurent Pinchart wrote:

Hi Abhinav,

On Sun, Apr 24, 2022 at 11:23:20AM -0700, Abhinav Kumar wrote:

On 4/24/2022 11:12 AM, Abhinav Kumar wrote:

On 4/24/2022 7:50 AM, Laurent Pinchart wrote:

On Fri, Apr 22, 2022 at 04:06:38PM -0700, Abhinav Kumar wrote:

For some vendor driver implementations, display hardware can
be shared between the encoder used for writeback and the physical
display.

In addition resources such as clocks and interrupts can
also be shared between writeback and the real encoder.

To accommodate such vendor drivers and hardware, allow
real encoder to be passed for drm_writeback_connector.

For existing clients, drm_writeback_connector_init() will use
an internal_encoder under the hood and hence no changes will
be needed.

changes in v7:
 - move this change before the vc4 change in the series
   to minimize the changes to vendor drivers in drm core
   changes


Why is this needed ? The drm_writeback_connector functions don't need
the drm_encoder after drm_writeback_connector_init() (or
drm_writeback_connector_init_with_encoder()) returns.



Sorry I didnt follow this comment. This change log is incorrect, so
after changing the previous change in the series and modifying this, no
further changes are needed to vc4, so I decided to drop the next change.
So this change log is incorrect. I can remove this.

Is that what you meant?


So till the previous change, the only user of
drm_writeback_connector_init_with_encoder() was
drm_writeback_connector_init() which was still passing its own
internal_encoder.

Only if the wb_connector->encoder is changed to a pointer, other vendor
drivers can pass their own encoder to
drm_writeback_connector_init_with_encoder().

Hence you are right that drm_writeback_connector functions do not need
drm_encoder after init() returns, but till this change is done, other
vendor drivers cannot directly call
drm_writeback_connector_init_with_encoder() because the encoder will not
be valid till then.


Users of drm_writeback_connector_init_with_encoder() handle the encoder
themselves, they can simply ignore drm_writeback_connector.encoder. The
documentation of the encoder field needs to be updated though (I'd do so
in the previous patch), to clearly mention that the field is valid only
when using drm_writeback_connector_init(), not when calling
drm_writeback_connector_init_with_encoder().


So you are suggesting to drop this change and just update the doc in 
patch 2?


If so, I dont think it would be correct to assume that even though 
drm_writeback_connector_init_with_encoder() is used 
drm_writeback_connector.encoder should not be used.


The reason is that, lets consider, prepare_wb_job() and 
cleanup_writeback_job().


These pass only the connector to the vendor hooks.

1126 *
1127 * This callback is used by the atomic modeset helpers.
1128 */
1129 	int (*prepare_writeback_job)(struct drm_writeback_connector 
*connector,

1130 struct drm_writeback_job *job);

Now, if you assume connector->encoder is not valid, this adds more 
confusion because now we are putting an extra condition that 
connector->encoder is not valid anymore.


Thats why I think we should leave it as-it-is to not allow room for such 
discrepancies.





Hope this clarifies it.


Signed-off-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
---
   drivers/gpu/drm/drm_writeback.c | 18 --
   drivers/gpu/drm/vc4/vc4_txp.c   |  4 ++--
   include/drm/drm_writeback.h | 22 --
   3 files changed, 34 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/drm_writeback.c
b/drivers/gpu/drm/drm_writeback.c
index 92658ad..0538674 100644
--- a/drivers/gpu/drm/drm_writeback.c
+++ b/drivers/gpu/drm/drm_writeback.c
@@ -180,21 +180,21 @@ int drm_writeback_connector_init(struct
drm_device *dev,
   {
   int ret = 0;
-    drm_encoder_helper_add(_connector->encoder, enc_helper_funcs);
+    drm_encoder_helper_add(_connector->internal_encoder, enc_helper_funcs);
-    wb_connector->encoder.possible_crtcs = possible_crtcs;
+    wb_connector->internal_encoder.possible_crtcs = possible_crtcs;
-    ret = drm_encoder_init(dev, _connector->encoder,
+    ret = drm_encoder_init(dev, _connector->internal_encoder,
  _writeback_encoder_funcs,
  DRM_MODE_ENCODER_VIRTUAL, NULL);
   if (ret)
   return ret;
-    ret = drm_writeback_connector_init_with_encoder(dev, wb_connector, 
_connector->encoder,
-    con_funcs, formats, n_formats);
+    ret = drm_writeback_connector_init_with_encoder(dev, wb_connector,
+    _connector->internal_encoder, con_funcs, formats, n_formats);
   if (ret)
-    drm_encoder_cleanup(_connector->encoder);
+    drm_encoder_cleanup(_connector->internal_encoder);
   return ret;
   }
@@ -239,6 +239,12 @@ int drm_writeback_connector_init_with_encoder(struct 
drm_device *dev,
   struct 

RE: [PATCH] drm/amd/display: fix if == else warning

2022-04-24 Thread Liu, Zhan
[AMD Official Use Only - General]

> -Original Message-
> From: Guo Zhengkui 
> Sent: 2022/April/24, Sunday 5:06 AM
> To: Wentland, Harry ; Li, Sun peng (Leo)
> ; Siqueira, Rodrigo ;
> Deucher, Alexander ; Koenig, Christian
> ; Pan, Xinhui ; David Airlie
> ; Daniel Vetter ; Liu, Charlene
> ; Lei, Jun ; Guo Zhengkui
> ; Liu, Zhan ; José Expósito
> ; open list:AMD DISPLAY CORE  g...@lists.freedesktop.org>; open list:DRM DRIVERS  de...@lists.freedesktop.org>; open list 
> Cc: zhengkui_...@outlook.com
> Subject: [PATCH] drm/amd/display: fix if == else warning
>
> Fix the following coccicheck warning:
>
> drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.c:98:8-10:
> WARNING: possible condition with no effect (if == else)
>
> Signed-off-by: Guo Zhengkui 

Thanks a lot for fixing this warning.

Reviewed-by: Zhan Liu 

> ---
>  drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.c | 2 --
>  1 file changed, 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.c
> b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.c
> index fe22530242d2..05b3fba9ccce 100644
> --- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.c
> +++ b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.c
> @@ -95,8 +95,6 @@ static void gpu_addr_to_uma(struct dce_hwseq *hwseq,
>   } else if (hwseq->fb_offset.quad_part <= addr->quad_part &&
>   addr->quad_part <= hwseq->uma_top.quad_part) {
>   is_in_uma = true;
> - } else if (addr->quad_part == 0) {
> - is_in_uma = false;
>   } else {
>   is_in_uma = false;
>   }
> --
> 2.20.1



Re: [PATCH v3 13/14] drm/sun4i: Add support for D1 TCONs

2022-04-24 Thread Jernej Å krabec
Dne nedelja, 24. april 2022 ob 18:26:31 CEST je Samuel Holland napisal(a):
> D1 has a TCON TOP, so its quirks are similar to those for the R40 TCONs.
> While there are some register changes, the part of the TCON TV supported
> by the driver matches the R40 quirks, so that quirks structure can be
> reused. D1 has the first supported TCON LCD with a TCON TOP, so the TCON
> LCD needs a new quirks structure.
> 
> D1's TCON LCD hardware supports LVDS; in fact it provides dual-link LVDS
> from a single TCON. However, it comes with a brand new LVDS PHY. Since
> this PHY has not been tested, leave out LVDS driver support for now.
> 
> Signed-off-by: Samuel Holland 

Reviewed-by: Jernej Skrabec 

Best regards,
Jernej Skrabec

> ---
> 
> (no changes since v1)
> 
>  drivers/gpu/drm/sun4i/sun4i_tcon.c | 8 
>  1 file changed, 8 insertions(+)
> 
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/
sun4i_tcon.c
> index 88db2d2a9336..2ee158aaeb9e 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> @@ -1542,6 +1542,12 @@ static const struct sun4i_tcon_quirks 
sun9i_a80_tcon_tv_quirks = {
>   .needs_edp_reset = true,
>  };
>  
> +static const struct sun4i_tcon_quirks sun20i_d1_lcd_quirks = {
> + .has_channel_0  = true,
> + .dclk_min_div   = 1,
> + .set_mux= sun8i_r40_tcon_tv_set_mux,
> +};
> +
>  /* sun4i_drv uses this list to check if a device node is a TCON */
>  const struct of_device_id sun4i_tcon_of_table[] = {
>   { .compatible = "allwinner,sun4i-a10-tcon", .data = 
_a10_quirks },
> @@ -1559,6 +1565,8 @@ const struct of_device_id sun4i_tcon_of_table[] = {
>   { .compatible = "allwinner,sun8i-v3s-tcon", .data = 
_v3s_quirks },
>   { .compatible = "allwinner,sun9i-a80-tcon-lcd", .data = 
_a80_tcon_lcd_quirks },
>   { .compatible = "allwinner,sun9i-a80-tcon-tv", .data = 
_a80_tcon_tv_quirks },
> + { .compatible = "allwinner,sun20i-d1-tcon-lcd", .data = 
_d1_lcd_quirks },
> + { .compatible = "allwinner,sun20i-d1-tcon-tv", .data = 
_r40_tv_quirks },
>   { }
>  };
>  MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table);
> -- 
> 2.35.1
> 
> 




Re: [PATCH v3 12/14] drm/sun4i: Add support for D1 TCON TOP

2022-04-24 Thread Jernej Å krabec
Dne nedelja, 24. april 2022 ob 18:26:30 CEST je Samuel Holland napisal(a):
> D1 has a TCON TOP with TCON TV0 and DSI, but no TCON TV1. This puts the
> DSI clock name at index 1 in clock-output-names. Support this by only
> incrementing the index for clocks that are actually supported.
> 
> Signed-off-by: Samuel Holland 

Reviewed-by: Jernej Skrabec 

Best regards,
Jernej Skrabec

> ---
> 
> (no changes since v1)
> 
>  drivers/gpu/drm/sun4i/sun8i_tcon_top.c | 15 ---
>  1 file changed, 12 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c b/drivers/gpu/drm/sun4i/
sun8i_tcon_top.c
> index 1b9b8b48f4a7..da97682b6835 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
> +++ b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
> @@ -189,22 +189,23 @@ static int sun8i_tcon_top_bind(struct device *dev, 
struct device *master,
>* if TVE is active on each TCON TV. If it is, mux should be 
switched
>* to TVE clock parent.
>*/
> + i = 0;
>   clk_data->hws[CLK_TCON_TOP_TV0] =
>   sun8i_tcon_top_register_gate(dev, "tcon-tv0", regs,
>_top-
>reg_lock,
> -  
TCON_TOP_TCON_TV0_GATE, 0);
> +  
TCON_TOP_TCON_TV0_GATE, i++);
>  
>   if (quirks->has_tcon_tv1)
>   clk_data->hws[CLK_TCON_TOP_TV1] =
>   sun8i_tcon_top_register_gate(dev, "tcon-
tv1", regs,
>
_top->reg_lock,
> -  
TCON_TOP_TCON_TV1_GATE, 1);
> +  
TCON_TOP_TCON_TV1_GATE, i++);
>  
>   if (quirks->has_dsi)
>   clk_data->hws[CLK_TCON_TOP_DSI] =
>   sun8i_tcon_top_register_gate(dev, "dsi", 
regs,
>
_top->reg_lock,
> -  
TCON_TOP_TCON_DSI_GATE, 2);
> +  
TCON_TOP_TCON_DSI_GATE, i++);
>  
>   for (i = 0; i < CLK_NUM; i++)
>   if (IS_ERR(clk_data->hws[i])) {
> @@ -272,6 +273,10 @@ static const struct sun8i_tcon_top_quirks 
sun8i_r40_tcon_top_quirks = {
>   .has_dsi= true,
>  };
>  
> +static const struct sun8i_tcon_top_quirks sun20i_d1_tcon_top_quirks = {
> + .has_dsi= true,
> +};
> +
>  static const struct sun8i_tcon_top_quirks sun50i_h6_tcon_top_quirks = {
>   /* Nothing special */
>  };
> @@ -282,6 +287,10 @@ const struct of_device_id sun8i_tcon_top_of_table[] = {
>   .compatible = "allwinner,sun8i-r40-tcon-top",
>   .data = _r40_tcon_top_quirks
>   },
> + {
> + .compatible = "allwinner,sun20i-d1-tcon-top",
> + .data = _d1_tcon_top_quirks
> + },
>   {
>   .compatible = "allwinner,sun50i-h6-tcon-top",
>   .data = _h6_tcon_top_quirks
> -- 
> 2.35.1
> 
> 




Re: [PATCH v3 10/14] drm/sun4i: csc: Add support for the new MMIO layout

2022-04-24 Thread Jernej Å krabec
Dne nedelja, 24. april 2022 ob 18:26:28 CEST je Samuel Holland napisal(a):
> D1 changes the MMIO offsets for the CSC blocks in the first mixer. The
> mixers' ccsc property is used as an index into the ccsc_base array. Use
> an enumeration to describe this index, and add the new set of offsets.
> 
> Signed-off-by: Samuel Holland 

Reviewed-by: Jernej Skrabec 

Best regards,
Jernej Skrabec

> ---
> 
> (no changes since v2)
> 
> Changes in v2:
>  - Use an enumeration for the ccsc value.
> 
>  drivers/gpu/drm/sun4i/sun8i_csc.c   |  7 ---
>  drivers/gpu/drm/sun4i/sun8i_csc.h   |  1 +
>  drivers/gpu/drm/sun4i/sun8i_mixer.c | 18 +-
>  drivers/gpu/drm/sun4i/sun8i_mixer.h | 14 ++
>  4 files changed, 24 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c b/drivers/gpu/drm/sun4i/
sun8i_csc.c
> index 9bd62de0c288..58480d8e4f70 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_csc.c
> +++ b/drivers/gpu/drm/sun4i/sun8i_csc.c
> @@ -8,9 +8,10 @@
>  #include "sun8i_csc.h"
>  #include "sun8i_mixer.h"
>  
> -static const u32 ccsc_base[2][2] = {
> - {CCSC00_OFFSET, CCSC01_OFFSET},
> - {CCSC10_OFFSET, CCSC11_OFFSET},
> +static const u32 ccsc_base[][2] = {
> + [CCSC_MIXER0_LAYOUT]= {CCSC00_OFFSET, CCSC01_OFFSET},
> + [CCSC_MIXER1_LAYOUT]= {CCSC10_OFFSET, CCSC11_OFFSET},
> + [CCSC_D1_MIXER0_LAYOUT] = {CCSC00_OFFSET, 
CCSC01_D1_OFFSET},
>  };
>  
>  /*
> diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.h b/drivers/gpu/drm/sun4i/
sun8i_csc.h
> index 022cafa6c06c..828b86fd0cab 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_csc.h
> +++ b/drivers/gpu/drm/sun4i/sun8i_csc.h
> @@ -13,6 +13,7 @@ struct sun8i_mixer;
>  /* VI channel CSC units offsets */
>  #define CCSC00_OFFSET 0xAA050
>  #define CCSC01_OFFSET 0xFA050
> +#define CCSC01_D1_OFFSET 0xFA000
>  #define CCSC10_OFFSET 0xA
>  #define CCSC11_OFFSET 0xF
>  
> diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/
sun8i_mixer.c
> index 6b1711a9a71f..4ce593c99807 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
> +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
> @@ -564,7 +564,7 @@ static int sun8i_mixer_remove(struct platform_device 
*pdev)
>  }
>  
>  static const struct sun8i_mixer_cfg sun8i_a83t_mixer0_cfg = {
> - .ccsc   = 0,
> + .ccsc   = CCSC_MIXER0_LAYOUT,
>   .scaler_mask= 0xf,
>   .scanline_yuv   = 2048,
>   .ui_num = 3,
> @@ -572,7 +572,7 @@ static const struct sun8i_mixer_cfg 
sun8i_a83t_mixer0_cfg = {
>  };
>  
>  static const struct sun8i_mixer_cfg sun8i_a83t_mixer1_cfg = {
> - .ccsc   = 1,
> + .ccsc   = CCSC_MIXER1_LAYOUT,
>   .scaler_mask= 0x3,
>   .scanline_yuv   = 2048,
>   .ui_num = 1,
> @@ -580,7 +580,7 @@ static const struct sun8i_mixer_cfg 
sun8i_a83t_mixer1_cfg = {
>  };
>  
>  static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg = {
> - .ccsc   = 0,
> + .ccsc   = CCSC_MIXER0_LAYOUT,
>   .mod_rate   = 43200,
>   .scaler_mask= 0xf,
>   .scanline_yuv   = 2048,
> @@ -589,7 +589,7 @@ static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg 
= {
>  };
>  
>  static const struct sun8i_mixer_cfg sun8i_r40_mixer0_cfg = {
> - .ccsc   = 0,
> + .ccsc   = CCSC_MIXER0_LAYOUT,
>   .mod_rate   = 29700,
>   .scaler_mask= 0xf,
>   .scanline_yuv   = 2048,
> @@ -598,7 +598,7 @@ static const struct sun8i_mixer_cfg sun8i_r40_mixer0_cfg 
= {
>  };
>  
>  static const struct sun8i_mixer_cfg sun8i_r40_mixer1_cfg = {
> - .ccsc   = 1,
> + .ccsc   = CCSC_MIXER1_LAYOUT,
>   .mod_rate   = 29700,
>   .scaler_mask= 0x3,
>   .scanline_yuv   = 2048,
> @@ -611,12 +611,12 @@ static const struct sun8i_mixer_cfg 
sun8i_v3s_mixer_cfg = {
>   .ui_num = 1,
>   .scaler_mask = 0x3,
>   .scanline_yuv = 2048,
> - .ccsc = 0,
> + .ccsc = CCSC_MIXER0_LAYOUT,
>   .mod_rate = 15000,
>  };
>  
>  static const struct sun8i_mixer_cfg sun50i_a64_mixer0_cfg = {
> - .ccsc   = 0,
> + .ccsc   = CCSC_MIXER0_LAYOUT,
>   .mod_rate   = 29700,
>   .scaler_mask= 0xf,
>   .scanline_yuv   = 4096,
> @@ -625,7 +625,7 @@ static const struct sun8i_mixer_cfg 
sun50i_a64_mixer0_cfg = {
>  };
>  
>  static const struct sun8i_mixer_cfg sun50i_a64_mixer1_cfg = {
> - .ccsc   = 1,
> + .ccsc   = CCSC_MIXER1_LAYOUT,
>   .mod_rate   = 29700,
>   .scaler_mask= 0x3,
>   .scanline_yuv   = 2048,
> @@ -634,7 +634,7 @@ static const struct sun8i_mixer_cfg 
sun50i_a64_mixer1_cfg = {
>  };
>  
>  static const struct sun8i_mixer_cfg sun50i_h6_mixer0_cfg = {
> - .ccsc   = 0,
> + .ccsc   = CCSC_MIXER0_LAYOUT,
>   .is_de3 = true,
>   .mod_rate   = 6,
>   .scaler_mask= 0xf,
> diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h 

Re: [PATCH v3 09/14] drm/sun4i: Allow VI layers to be primary planes

2022-04-24 Thread Jernej Å krabec
Dne nedelja, 24. april 2022 ob 18:26:27 CEST je Samuel Holland napisal(a):
> D1's mixer 1 has no UI layers, only a single VI layer. That means the
> mixer can only be used if the primary plane comes from this VI layer.
> Add the code to handle this case.
> 
> Signed-off-by: Samuel Holland 

Reviewed-by: Jernej Skrabec 

Best regards,
Jernej Skrabec

> ---
> 
> (no changes since v2)
> 
> Changes in v2:
>  - Use Jernej's patches for mixer mode setting.
> 
>  drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 6 +-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/
sun8i_vi_layer.c
> index bb7c43036dfa..f7d0b082d634 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
> +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
> @@ -542,6 +542,7 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct 
drm_device *drm,
>  struct 
sun8i_mixer *mixer,
>  int index)
>  {
> + enum drm_plane_type type = DRM_PLANE_TYPE_OVERLAY;
>   u32 supported_encodings, supported_ranges;
>   unsigned int plane_cnt, format_count;
>   struct sun8i_vi_layer *layer;
> @@ -560,12 +561,15 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct 
drm_device *drm,
>   format_count = ARRAY_SIZE(sun8i_vi_layer_formats);
>   }
>  
> + if (!mixer->cfg->ui_num && index == 0)
> + type = DRM_PLANE_TYPE_PRIMARY;
> +
>   /* possible crtcs are set later */
>   ret = drm_universal_plane_init(drm, >plane, 0,
>  _vi_layer_funcs,
>  formats, format_count,
>  sun8i_layer_modifiers,
> -DRM_PLANE_TYPE_OVERLAY, 
NULL);
> +type, NULL);
>   if (ret) {
>   dev_err(drm->dev, "Couldn't initialize layer\n");
>   return ERR_PTR(ret);
> -- 
> 2.35.1
> 
> 




Re: [PATCH v3 04/14] drm/sun4i: hdmi: Use more portable I/O helpers

2022-04-24 Thread Jernej Å krabec
Dne nedelja, 24. april 2022 ob 18:26:22 CEST je Samuel Holland napisal(a):
> readsb/writesb are unavailable on some architectures. In preparation for
> removing the Kconfig architecture dependency, switch to the equivalent
> but more portable ioread/write8_rep helpers.
> 
> Reported-by: kernel test robot 
> Signed-off-by: Samuel Holland 

Reviewed-by: Jernej Skrabec 

Best regards,
Jernej Skrabec

> ---
> 
> (no changes since v2)
> 
> Changes in v2:
>  - New patch: I/O helper portability
> 
>  drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c b/drivers/gpu/drm/sun4i/
sun4i_hdmi_i2c.c
> index b66fa27fe6ea..c7d7e9fff91c 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c
> @@ -56,9 +56,9 @@ static int fifo_transfer(struct sun4i_hdmi *hdmi, u8 *buf, 
int len, bool read)
>   return -EIO;
>  
>   if (read)
> - readsb(hdmi->base + hdmi->variant->ddc_fifo_reg, buf, 
len);
> + ioread8_rep(hdmi->base + hdmi->variant->ddc_fifo_reg, 
buf, len);
>   else
> - writesb(hdmi->base + hdmi->variant->ddc_fifo_reg, buf, 
len);
> + iowrite8_rep(hdmi->base + hdmi->variant->ddc_fifo_reg, 
buf, len);
>  
>   /* Clear FIFO request bit by forcing a write to that bit */
>   regmap_field_force_write(hdmi->field_ddc_int_status,
> -- 
> 2.35.1
> 
> 




Re: [Freedreno] [PATCH v4 03/20] drm: allow real encoder to be passed for drm_writeback_connector

2022-04-24 Thread Laurent Pinchart
Hi Abhinav,

On Sun, Apr 24, 2022 at 11:23:20AM -0700, Abhinav Kumar wrote:
> On 4/24/2022 11:12 AM, Abhinav Kumar wrote:
> > On 4/24/2022 7:50 AM, Laurent Pinchart wrote:
> >> On Fri, Apr 22, 2022 at 04:06:38PM -0700, Abhinav Kumar wrote:
> >>> For some vendor driver implementations, display hardware can
> >>> be shared between the encoder used for writeback and the physical
> >>> display.
> >>>
> >>> In addition resources such as clocks and interrupts can
> >>> also be shared between writeback and the real encoder.
> >>>
> >>> To accommodate such vendor drivers and hardware, allow
> >>> real encoder to be passed for drm_writeback_connector.
> >>>
> >>> For existing clients, drm_writeback_connector_init() will use
> >>> an internal_encoder under the hood and hence no changes will
> >>> be needed.
> >>>
> >>> changes in v7:
> >>> - move this change before the vc4 change in the series
> >>>   to minimize the changes to vendor drivers in drm core
> >>>   changes
> >>
> >> Why is this needed ? The drm_writeback_connector functions don't need
> >> the drm_encoder after drm_writeback_connector_init() (or
> >> drm_writeback_connector_init_with_encoder()) returns.
> >>
> > 
> > Sorry I didnt follow this comment. This change log is incorrect, so 
> > after changing the previous change in the series and modifying this, no 
> > further changes are needed to vc4, so I decided to drop the next change.
> > So this change log is incorrect. I can remove this.
> > 
> > Is that what you meant?
> 
> So till the previous change, the only user of 
> drm_writeback_connector_init_with_encoder() was 
> drm_writeback_connector_init() which was still passing its own 
> internal_encoder.
> 
> Only if the wb_connector->encoder is changed to a pointer, other vendor 
> drivers can pass their own encoder to 
> drm_writeback_connector_init_with_encoder().
> 
> Hence you are right that drm_writeback_connector functions do not need 
> drm_encoder after init() returns, but till this change is done, other 
> vendor drivers cannot directly call 
> drm_writeback_connector_init_with_encoder() because the encoder will not 
> be valid till then.

Users of drm_writeback_connector_init_with_encoder() handle the encoder
themselves, they can simply ignore drm_writeback_connector.encoder. The
documentation of the encoder field needs to be updated though (I'd do so
in the previous patch), to clearly mention that the field is valid only
when using drm_writeback_connector_init(), not when calling
drm_writeback_connector_init_with_encoder().

> Hope this clarifies it.
> 
> >>> Signed-off-by: Abhinav Kumar 
> >>> Reviewed-by: Dmitry Baryshkov 
> >>> ---
> >>>   drivers/gpu/drm/drm_writeback.c | 18 --
> >>>   drivers/gpu/drm/vc4/vc4_txp.c   |  4 ++--
> >>>   include/drm/drm_writeback.h | 22 --
> >>>   3 files changed, 34 insertions(+), 10 deletions(-)
> >>>
> >>> diff --git a/drivers/gpu/drm/drm_writeback.c 
> >>> b/drivers/gpu/drm/drm_writeback.c
> >>> index 92658ad..0538674 100644
> >>> --- a/drivers/gpu/drm/drm_writeback.c
> >>> +++ b/drivers/gpu/drm/drm_writeback.c
> >>> @@ -180,21 +180,21 @@ int drm_writeback_connector_init(struct 
> >>> drm_device *dev,
> >>>   {
> >>>   int ret = 0;
> >>> -    drm_encoder_helper_add(_connector->encoder, enc_helper_funcs);
> >>> +    drm_encoder_helper_add(_connector->internal_encoder, 
> >>> enc_helper_funcs);
> >>> -    wb_connector->encoder.possible_crtcs = possible_crtcs;
> >>> +    wb_connector->internal_encoder.possible_crtcs = possible_crtcs;
> >>> -    ret = drm_encoder_init(dev, _connector->encoder,
> >>> +    ret = drm_encoder_init(dev, _connector->internal_encoder,
> >>>  _writeback_encoder_funcs,
> >>>  DRM_MODE_ENCODER_VIRTUAL, NULL);
> >>>   if (ret)
> >>>   return ret;
> >>> -    ret = drm_writeback_connector_init_with_encoder(dev, wb_connector, 
> >>> _connector->encoder,
> >>> -    con_funcs, formats, n_formats);
> >>> +    ret = drm_writeback_connector_init_with_encoder(dev, wb_connector,
> >>> +    _connector->internal_encoder, con_funcs, formats, 
> >>> n_formats);
> >>>   if (ret)
> >>> -    drm_encoder_cleanup(_connector->encoder);
> >>> +    drm_encoder_cleanup(_connector->internal_encoder);
> >>>   return ret;
> >>>   }
> >>> @@ -239,6 +239,12 @@ int drm_writeback_connector_init_with_encoder(struct 
> >>> drm_device *dev,
> >>>   struct drm_mode_config *config = >mode_config;
> >>>   int ret = create_writeback_properties(dev);
> >>> +    /*
> >>> + * Assign the encoder passed to this API to the wb_connector's 
> >>> encoder.
> >>> + * For drm_writeback_connector_init(), this shall be the 
> >>> internal_encoder
> >>> + */
> >>> +    wb_connector->encoder = enc;
> >>> +
> >>>   if (ret != 0)
> >>>   return ret;
> >>> diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
> >>> index 3447eb6..7e063a9 

[PATCH v5 16/17] drm/shmem-helper: Make drm_gem_shmem_is_purgeable() private

2022-04-24 Thread Dmitry Osipenko
Panfrost driver was the only user of the drm_gem_shmem_is_purgeable()
helper. Panfrost driver was converted to use new generic memory shrinker
and the helper doesn't have external users anymore, hence make it private
to the drm_gem_shmem_helper.c to keep the code clean.

Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/drm_gem_shmem_helper.c | 9 -
 include/drm/drm_gem_shmem_helper.h | 7 ---
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c 
b/drivers/gpu/drm/drm_gem_shmem_helper.c
index 7ec5f8002f68..045921ad4795 100644
--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -169,6 +169,13 @@ static bool drm_gem_shmem_is_evictable(struct 
drm_gem_shmem_object *shmem)
!shmem->base.import_attach && shmem->sgt && !shmem->evicted;
 }
 
+static bool drm_gem_shmem_is_purgeable(struct drm_gem_shmem_object *shmem)
+{
+   return (shmem->madv > 0) && !shmem->purge_disable_count &&
+   !shmem->vmap_use_count && !shmem->base.dma_buf &&
+   !shmem->base.import_attach && shmem->sgt;
+}
+
 static void
 drm_gem_shmem_update_pages_state_locked(struct drm_gem_shmem_object *shmem)
 {
@@ -182,7 +189,7 @@ drm_gem_shmem_update_pages_state_locked(struct 
drm_gem_shmem_object *shmem)
 
mutex_lock(_shrinker->lock);
 
-   if (drm_gem_shmem_is_purgeable(shmem) && !shmem->purge_disable_count) {
+   if (drm_gem_shmem_is_purgeable(shmem)) {
drm_gem_shmem_add_pages_to_shrinker(shmem);
list_move_tail(>madv_list, _shrinker->lru_purgeable);
} else if (drm_gem_shmem_is_evictable(shmem)) {
diff --git a/include/drm/drm_gem_shmem_helper.h 
b/include/drm/drm_gem_shmem_helper.h
index 5b351933c293..972687bf9717 100644
--- a/include/drm/drm_gem_shmem_helper.h
+++ b/include/drm/drm_gem_shmem_helper.h
@@ -194,13 +194,6 @@ int drm_gem_shmem_madvise(struct drm_gem_shmem_object 
*shmem, int madv);
 int drm_gem_shmem_set_purgeable(struct drm_gem_shmem_object *shmem);
 int drm_gem_shmem_set_purgeable_and_evictable(struct drm_gem_shmem_object 
*shmem);
 
-static inline bool drm_gem_shmem_is_purgeable(struct drm_gem_shmem_object 
*shmem)
-{
-   return (shmem->madv > 0) &&
-   !shmem->vmap_use_count && shmem->sgt &&
-   !shmem->base.dma_buf && !shmem->base.import_attach;
-}
-
 int drm_gem_shmem_swap_in_locked(struct drm_gem_shmem_object *shmem);
 void drm_gem_shmem_purge_locked(struct drm_gem_shmem_object *shmem);
 
-- 
2.35.1



[PATCH v5 15/17] drm/shmem-helper: Make drm_gem_shmem_get_pages() private

2022-04-24 Thread Dmitry Osipenko
VirtIO-GPU driver was the only user of drm_gem_shmem_get_pages()
and it now uses drm_gem_shmem_get_pages_sgt(). Make the get_pages()
private to drm_gem_shmem_helper.

Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/drm_gem_shmem_helper.c | 3 +--
 include/drm/drm_gem_shmem_helper.h | 1 -
 2 files changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c 
b/drivers/gpu/drm/drm_gem_shmem_helper.c
index 25e9bc2803ee..7ec5f8002f68 100644
--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -490,7 +490,7 @@ static int drm_gem_shmem_get_pages_locked(struct 
drm_gem_shmem_object *shmem)
  * Returns:
  * 0 on success or a negative error code on failure.
  */
-int drm_gem_shmem_get_pages(struct drm_gem_shmem_object *shmem)
+static int drm_gem_shmem_get_pages(struct drm_gem_shmem_object *shmem)
 {
int ret;
 
@@ -507,7 +507,6 @@ int drm_gem_shmem_get_pages(struct drm_gem_shmem_object 
*shmem)
 
return ret;
 }
-EXPORT_SYMBOL(drm_gem_shmem_get_pages);
 
 static void drm_gem_shmem_get_pages_no_fail(struct drm_gem_shmem_object *shmem)
 {
diff --git a/include/drm/drm_gem_shmem_helper.h 
b/include/drm/drm_gem_shmem_helper.h
index 638cb16a4576..5b351933c293 100644
--- a/include/drm/drm_gem_shmem_helper.h
+++ b/include/drm/drm_gem_shmem_helper.h
@@ -180,7 +180,6 @@ struct drm_gem_shmem_object {
 struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, 
size_t size);
 void drm_gem_shmem_free(struct drm_gem_shmem_object *shmem);
 
-int drm_gem_shmem_get_pages(struct drm_gem_shmem_object *shmem);
 void drm_gem_shmem_put_pages(struct drm_gem_shmem_object *shmem);
 int drm_gem_shmem_pin(struct drm_gem_shmem_object *shmem);
 void drm_gem_shmem_unpin(struct drm_gem_shmem_object *shmem);
-- 
2.35.1



[PATCH v5 12/17] drm/shmem-helper: Add generic memory shrinker

2022-04-24 Thread Dmitry Osipenko
Introduce a common DRM SHMEM shrinker. It allows to reduce code
duplication among DRM drivers that implement theirs own shrinkers.
This is initial version of the shrinker that covers basic needs of
GPU drivers, both purging and eviction of shmem objects are supported.

This patch is based on a couple ideas borrowed from Rob's Clark MSM
shrinker and Thomas' Zimmermann variant of SHMEM shrinker.

In order to start using DRM SHMEM shrinker drivers should:

1. Optionally implement new purge(), evict() + swap_in() shmem objects
   callbacks.
2. Register shrinker using drm_gem_shmem_shrinker_register(drm_device).
3. Use drm_gem_shmem_set_purgeable_and_evictable(shmem) and alike API
   functions to activate shrinking of shmem GEMs.

Signed-off-by: Daniel Almeida 
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/drm_gem_shmem_helper.c | 734 +++--
 include/drm/drm_device.h   |   4 +
 include/drm/drm_gem_shmem_helper.h | 115 +++-
 3 files changed, 820 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c 
b/drivers/gpu/drm/drm_gem_shmem_helper.c
index cc90a4c28ace..25e9bc2803ee 100644
--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -89,6 +89,13 @@ __drm_gem_shmem_create(struct drm_device *dev, size_t size, 
bool private)
mutex_init(>vmap_lock);
INIT_LIST_HEAD(>madv_list);
 
+   /*
+* Eviction and purging are disabled by default, shmem user must enable
+* them explicitly using drm_gem_shmem_set_evictable/purgeable().
+*/
+   shmem->eviction_disable_count = 1;
+   shmem->purge_disable_count = 1;
+
if (!private) {
/*
 * Our buffers are kept pinned, so allocating them
@@ -127,6 +134,77 @@ struct drm_gem_shmem_object *drm_gem_shmem_create(struct 
drm_device *dev, size_t
 }
 EXPORT_SYMBOL_GPL(drm_gem_shmem_create);
 
+static void
+drm_gem_shmem_add_pages_to_shrinker(struct drm_gem_shmem_object *shmem)
+{
+   struct drm_gem_object *obj = >base;
+   struct drm_gem_shmem_shrinker *gem_shrinker = obj->dev->shmem_shrinker;
+   size_t page_count = obj->size >> PAGE_SHIFT;
+
+   if (!shmem->pages_accounted_by_shrinker) {
+   WARN_ON(gem_shrinker->shrinkable_count + page_count < 
page_count);
+   gem_shrinker->shrinkable_count += page_count;
+   shmem->pages_accounted_by_shrinker = true;
+   }
+}
+
+static void
+drm_gem_shmem_remove_pages_from_shrinker(struct drm_gem_shmem_object *shmem)
+{
+   struct drm_gem_object *obj = >base;
+   struct drm_gem_shmem_shrinker *gem_shrinker = obj->dev->shmem_shrinker;
+   size_t page_count = obj->size >> PAGE_SHIFT;
+
+   if (shmem->pages_accounted_by_shrinker) {
+   WARN_ON(gem_shrinker->shrinkable_count < page_count);
+   gem_shrinker->shrinkable_count -= page_count;
+   shmem->pages_accounted_by_shrinker = false;
+   }
+}
+
+static bool drm_gem_shmem_is_evictable(struct drm_gem_shmem_object *shmem)
+{
+   return (shmem->madv >= 0) && !shmem->eviction_disable_count &&
+   !shmem->vmap_use_count && !shmem->base.dma_buf &&
+   !shmem->base.import_attach && shmem->sgt && !shmem->evicted;
+}
+
+static void
+drm_gem_shmem_update_pages_state_locked(struct drm_gem_shmem_object *shmem)
+{
+   struct drm_gem_object *obj = >base;
+   struct drm_gem_shmem_shrinker *gem_shrinker = obj->dev->shmem_shrinker;
+
+   if (!gem_shrinker || obj->import_attach)
+   return;
+
+   lockdep_assert_held(>resv->lock.base);
+
+   mutex_lock(_shrinker->lock);
+
+   if (drm_gem_shmem_is_purgeable(shmem) && !shmem->purge_disable_count) {
+   drm_gem_shmem_add_pages_to_shrinker(shmem);
+   list_move_tail(>madv_list, _shrinker->lru_purgeable);
+   } else if (drm_gem_shmem_is_evictable(shmem)) {
+   drm_gem_shmem_add_pages_to_shrinker(shmem);
+   list_move_tail(>madv_list, _shrinker->lru_evictable);
+   } else if (shmem->madv < 0) {
+   drm_gem_shmem_remove_pages_from_shrinker(shmem);
+   list_del_init(>madv_list);
+   } else if (shmem->evicted) {
+   drm_gem_shmem_remove_pages_from_shrinker(shmem);
+   list_move_tail(>madv_list, _shrinker->lru_evicted);
+   } else if (!shmem->pages) {
+   drm_gem_shmem_remove_pages_from_shrinker(shmem);
+   list_del_init(>madv_list);
+   } else {
+   drm_gem_shmem_remove_pages_from_shrinker(shmem);
+   list_move_tail(>madv_list, _shrinker->lru_active);
+   }
+
+   mutex_unlock(_shrinker->lock);
+}
+
 /**
  * drm_gem_shmem_free - Free resources associated with a shmem GEM object
  * @shmem: shmem GEM object to free
@@ -138,6 +216,9 @@ void drm_gem_shmem_free(struct drm_gem_shmem_object *shmem)
 {
struct drm_gem_object *obj = >base;
 
+

[PATCH v5 17/17] drm/shmem-helper: Remove drm_gem_shmem_purge_locked()

2022-04-24 Thread Dmitry Osipenko
Panfrost driver was the only user of the drm_gem_shmem_purge_locked()
helper. Panfrost driver was converted to use new generic memory shrinker
and the helper doesn't have users anymore, remove it.

Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/drm_gem_shmem_helper.c | 30 --
 include/drm/drm_gem_shmem_helper.h |  1 -
 2 files changed, 31 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c 
b/drivers/gpu/drm/drm_gem_shmem_helper.c
index 045921ad4795..ef7691c84fa8 100644
--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -899,36 +899,6 @@ static void drm_gem_shmem_unpin_pages_locked(struct 
drm_gem_shmem_object *shmem)
shmem->sgt = NULL;
 }
 
-void drm_gem_shmem_purge_locked(struct drm_gem_shmem_object *shmem)
-{
-   struct drm_gem_object *obj = >base;
-   struct drm_device *dev = obj->dev;
-
-   WARN_ON(!drm_gem_shmem_is_purgeable(shmem));
-
-   dma_unmap_sgtable(dev->dev, shmem->sgt, DMA_BIDIRECTIONAL, 0);
-   sg_free_table(shmem->sgt);
-   kfree(shmem->sgt);
-   shmem->sgt = NULL;
-
-   drm_gem_shmem_put_pages_locked(shmem);
-
-   shmem->madv = -1;
-
-   drm_vma_node_unmap(>vma_node, dev->anon_inode->i_mapping);
-   drm_gem_free_mmap_offset(obj);
-
-   /* Our goal here is to return as much of the memory as
-* is possible back to the system as we are called from OOM.
-* To do this we must instruct the shmfs to drop all of its
-* backing pages, *now*.
-*/
-   shmem_truncate_range(file_inode(obj->filp), 0, (loff_t)-1);
-
-   invalidate_mapping_pages(file_inode(obj->filp)->i_mapping, 0, 
(loff_t)-1);
-}
-EXPORT_SYMBOL(drm_gem_shmem_purge_locked);
-
 /**
  * drm_gem_shmem_dumb_create - Create a dumb shmem buffer object
  * @file: DRM file structure to create the dumb buffer for
diff --git a/include/drm/drm_gem_shmem_helper.h 
b/include/drm/drm_gem_shmem_helper.h
index 972687bf9717..8d7053c36fa6 100644
--- a/include/drm/drm_gem_shmem_helper.h
+++ b/include/drm/drm_gem_shmem_helper.h
@@ -195,7 +195,6 @@ int drm_gem_shmem_set_purgeable(struct drm_gem_shmem_object 
*shmem);
 int drm_gem_shmem_set_purgeable_and_evictable(struct drm_gem_shmem_object 
*shmem);
 
 int drm_gem_shmem_swap_in_locked(struct drm_gem_shmem_object *shmem);
-void drm_gem_shmem_purge_locked(struct drm_gem_shmem_object *shmem);
 
 struct sg_table *drm_gem_shmem_get_sg_table(struct drm_gem_shmem_object 
*shmem);
 struct sg_table *drm_gem_shmem_get_pages_sgt(struct drm_gem_shmem_object 
*shmem);
-- 
2.35.1



[PATCH v5 13/17] drm/virtio: Support memory shrinking

2022-04-24 Thread Dmitry Osipenko
Support generic DRM SHMEM memory shrinker and add new madvise IOCTL
to the VirtIO-GPU driver. Userspace (BO cache manager of Mesa driver)
will mark BOs as "don't need" using the new IOCTL to let shrinker purge
the marked BOs on OOM, the shrinker will also evict unpurgeable shmem BOs
from memory if guest supports SWAP. Altogether this allows to prevent OOM
kills of guest applications that use VirGL by lowering memory pressure.

Signed-off-by: Daniel Almeida 
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/virtio/virtgpu_drv.h|  15 ++-
 drivers/gpu/drm/virtio/virtgpu_gem.c|  46 +
 drivers/gpu/drm/virtio/virtgpu_ioctl.c  |  37 +++
 drivers/gpu/drm/virtio/virtgpu_kms.c|   9 ++
 drivers/gpu/drm/virtio/virtgpu_object.c | 130 +++-
 drivers/gpu/drm/virtio/virtgpu_plane.c  |  22 +++-
 drivers/gpu/drm/virtio/virtgpu_vq.c |  40 
 include/uapi/drm/virtgpu_drm.h  |  14 +++
 8 files changed, 283 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h 
b/drivers/gpu/drm/virtio/virtgpu_drv.h
index b2d93cb12ebf..c8918a271e1c 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.h
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
@@ -274,7 +274,7 @@ struct virtio_gpu_fpriv {
 };
 
 /* virtgpu_ioctl.c */
-#define DRM_VIRTIO_NUM_IOCTLS 12
+#define DRM_VIRTIO_NUM_IOCTLS 13
 extern struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS];
 void virtio_gpu_create_context(struct drm_device *dev, struct drm_file *file);
 
@@ -310,6 +310,10 @@ void virtio_gpu_array_put_free(struct 
virtio_gpu_object_array *objs);
 void virtio_gpu_array_put_free_delayed(struct virtio_gpu_device *vgdev,
   struct virtio_gpu_object_array *objs);
 void virtio_gpu_array_put_free_work(struct work_struct *work);
+int virtio_gpu_array_prepare(struct virtio_gpu_device *vgdev,
+struct virtio_gpu_object_array *objs);
+int virtio_gpu_gem_host_mem_release(struct virtio_gpu_object *bo);
+bool virtio_gpu_gem_madvise(struct virtio_gpu_object *obj, int madv);
 
 /* virtgpu_vq.c */
 int virtio_gpu_alloc_vbufs(struct virtio_gpu_device *vgdev);
@@ -321,6 +325,8 @@ void virtio_gpu_cmd_create_resource(struct 
virtio_gpu_device *vgdev,
struct virtio_gpu_fence *fence);
 void virtio_gpu_cmd_unref_resource(struct virtio_gpu_device *vgdev,
   struct virtio_gpu_object *bo);
+int virtio_gpu_cmd_release_resource(struct virtio_gpu_device *vgdev,
+   struct virtio_gpu_object *bo);
 void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev,
uint64_t offset,
uint32_t width, uint32_t height,
@@ -341,6 +347,9 @@ void virtio_gpu_object_attach(struct virtio_gpu_device 
*vgdev,
  struct virtio_gpu_object *obj,
  struct virtio_gpu_mem_entry *ents,
  unsigned int nents);
+void virtio_gpu_object_detach(struct virtio_gpu_device *vgdev,
+ struct virtio_gpu_object *obj,
+ struct virtio_gpu_fence *fence);
 int virtio_gpu_attach_status_page(struct virtio_gpu_device *vgdev);
 int virtio_gpu_detach_status_page(struct virtio_gpu_device *vgdev);
 void virtio_gpu_cursor_ping(struct virtio_gpu_device *vgdev,
@@ -483,4 +492,8 @@ void virtio_gpu_vram_unmap_dma_buf(struct device *dev,
   struct sg_table *sgt,
   enum dma_data_direction dir);
 
+/* virtgpu_gem_shrinker.c */
+int virtio_gpu_gem_shrinker_init(struct virtio_gpu_device *vgdev);
+void virtio_gpu_gem_shrinker_fini(struct virtio_gpu_device *vgdev);
+
 #endif
diff --git a/drivers/gpu/drm/virtio/virtgpu_gem.c 
b/drivers/gpu/drm/virtio/virtgpu_gem.c
index 7db48d17ee3a..08189ad43736 100644
--- a/drivers/gpu/drm/virtio/virtgpu_gem.c
+++ b/drivers/gpu/drm/virtio/virtgpu_gem.c
@@ -294,3 +294,49 @@ void virtio_gpu_array_put_free_work(struct work_struct 
*work)
}
spin_unlock(>obj_free_lock);
 }
+
+int virtio_gpu_array_prepare(struct virtio_gpu_device *vgdev,
+struct virtio_gpu_object_array *objs)
+{
+   struct drm_gem_shmem_object *shmem;
+   int ret = 0;
+   u32 i;
+
+   for (i = 0; i < objs->nents; i++) {
+   shmem = to_drm_gem_shmem_obj(objs->objs[i]);
+   ret = drm_gem_shmem_swap_in_locked(shmem);
+   if (ret)
+   break;
+   }
+
+   return ret;
+}
+
+bool virtio_gpu_gem_madvise(struct virtio_gpu_object *bo, int madv)
+{
+   /*
+* For now we support only purging BOs that are backed by guest's
+* memory.
+*/
+   if (!virtio_gpu_is_shmem(bo))
+   return true;
+
+   return drm_gem_shmem_madvise(>base, madv);
+}
+
+int 

[PATCH v5 14/17] drm/panfrost: Switch to generic memory shrinker

2022-04-24 Thread Dmitry Osipenko
Replace Panfrost's memory shrinker with a generic DRM SHMEM memory
shrinker.

Tested-by: Steven Price 
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/panfrost/Makefile |   1 -
 drivers/gpu/drm/panfrost/panfrost_device.h|   4 -
 drivers/gpu/drm/panfrost/panfrost_drv.c   |  19 +--
 drivers/gpu/drm/panfrost/panfrost_gem.c   |  28 ++--
 drivers/gpu/drm/panfrost/panfrost_gem.h   |   9 --
 .../gpu/drm/panfrost/panfrost_gem_shrinker.c  | 122 --
 drivers/gpu/drm/panfrost/panfrost_job.c   |  18 ++-
 7 files changed, 37 insertions(+), 164 deletions(-)
 delete mode 100644 drivers/gpu/drm/panfrost/panfrost_gem_shrinker.c

diff --git a/drivers/gpu/drm/panfrost/Makefile 
b/drivers/gpu/drm/panfrost/Makefile
index b71935862417..ecf0864cb515 100644
--- a/drivers/gpu/drm/panfrost/Makefile
+++ b/drivers/gpu/drm/panfrost/Makefile
@@ -5,7 +5,6 @@ panfrost-y := \
panfrost_device.o \
panfrost_devfreq.o \
panfrost_gem.o \
-   panfrost_gem_shrinker.o \
panfrost_gpu.o \
panfrost_job.o \
panfrost_mmu.o \
diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h 
b/drivers/gpu/drm/panfrost/panfrost_device.h
index 8b25278f34c8..fe04b21fc044 100644
--- a/drivers/gpu/drm/panfrost/panfrost_device.h
+++ b/drivers/gpu/drm/panfrost/panfrost_device.h
@@ -115,10 +115,6 @@ struct panfrost_device {
atomic_t pending;
} reset;
 
-   struct mutex shrinker_lock;
-   struct list_head shrinker_list;
-   struct shrinker shrinker;
-
struct panfrost_devfreq pfdevfreq;
 };
 
diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c 
b/drivers/gpu/drm/panfrost/panfrost_drv.c
index 7fcbc2a5b6cd..57a93555813f 100644
--- a/drivers/gpu/drm/panfrost/panfrost_drv.c
+++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
@@ -160,7 +160,6 @@ panfrost_lookup_bos(struct drm_device *dev,
break;
}
 
-   atomic_inc(>gpu_usecount);
job->mappings[i] = mapping;
}
 
@@ -391,7 +390,6 @@ static int panfrost_ioctl_madvise(struct drm_device *dev, 
void *data,
 {
struct panfrost_file_priv *priv = file_priv->driver_priv;
struct drm_panfrost_madvise *args = data;
-   struct panfrost_device *pfdev = dev->dev_private;
struct drm_gem_object *gem_obj;
struct panfrost_gem_object *bo;
int ret = 0;
@@ -404,7 +402,6 @@ static int panfrost_ioctl_madvise(struct drm_device *dev, 
void *data,
 
bo = to_panfrost_bo(gem_obj);
 
-   mutex_lock(>shrinker_lock);
mutex_lock(>mappings.lock);
if (args->madv == PANFROST_MADV_DONTNEED) {
struct panfrost_gem_mapping *first;
@@ -430,17 +427,8 @@ static int panfrost_ioctl_madvise(struct drm_device *dev, 
void *data,
 
args->retained = drm_gem_shmem_madvise(>base, args->madv);
 
-   if (args->retained) {
-   if (args->madv == PANFROST_MADV_DONTNEED)
-   list_add_tail(>base.madv_list,
- >shrinker_list);
-   else if (args->madv == PANFROST_MADV_WILLNEED)
-   list_del_init(>base.madv_list);
-   }
-
 out_unlock_mappings:
mutex_unlock(>mappings.lock);
-   mutex_unlock(>shrinker_lock);
 
drm_gem_object_put(gem_obj);
return ret;
@@ -571,9 +559,6 @@ static int panfrost_probe(struct platform_device *pdev)
ddev->dev_private = pfdev;
pfdev->ddev = ddev;
 
-   mutex_init(>shrinker_lock);
-   INIT_LIST_HEAD(>shrinker_list);
-
err = panfrost_device_init(pfdev);
if (err) {
if (err != -EPROBE_DEFER)
@@ -595,7 +580,7 @@ static int panfrost_probe(struct platform_device *pdev)
if (err < 0)
goto err_out1;
 
-   panfrost_gem_shrinker_init(ddev);
+   drm_gem_shmem_shrinker_register(ddev);
 
return 0;
 
@@ -613,8 +598,8 @@ static int panfrost_remove(struct platform_device *pdev)
struct panfrost_device *pfdev = platform_get_drvdata(pdev);
struct drm_device *ddev = pfdev->ddev;
 
+   drm_gem_shmem_shrinker_unregister(ddev);
drm_dev_unregister(ddev);
-   panfrost_gem_shrinker_cleanup(ddev);
 
pm_runtime_get_sync(pfdev->dev);
pm_runtime_disable(pfdev->dev);
diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.c 
b/drivers/gpu/drm/panfrost/panfrost_gem.c
index 293e799e2fe8..f91ef0726e5e 100644
--- a/drivers/gpu/drm/panfrost/panfrost_gem.c
+++ b/drivers/gpu/drm/panfrost/panfrost_gem.c
@@ -19,16 +19,6 @@ static void panfrost_gem_free_object(struct drm_gem_object 
*obj)
struct panfrost_gem_object *bo = to_panfrost_bo(obj);
struct panfrost_device *pfdev = obj->dev->dev_private;
 
-   /*
-* Make sure the BO is no longer inserted in the shrinker list before
-* taking care of the destruction itself. If we don't do that we have a
-* race condition between this function and 

[PATCH v5 09/17] drm/virtio: Use dev_is_pci()

2022-04-24 Thread Dmitry Osipenko
Use common dev_is_pci() helper to replace the strcmp("pci") used by driver.

Suggested-by: Robin Murphy 
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/virtio/virtgpu_drv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c 
b/drivers/gpu/drm/virtio/virtgpu_drv.c
index 0141b7df97ec..0035affc3e59 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.c
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.c
@@ -87,7 +87,7 @@ static int virtio_gpu_probe(struct virtio_device *vdev)
return PTR_ERR(dev);
vdev->priv = dev;
 
-   if (!strcmp(vdev->dev.parent->bus->name, "pci")) {
+   if (dev_is_pci(vdev->dev.parent)) {
ret = virtio_gpu_pci_quirk(dev);
if (ret)
goto err_free;
-- 
2.35.1



[PATCH v5 11/17] drm/shmem-helper: Take reservation lock instead of drm_gem_shmem locks

2022-04-24 Thread Dmitry Osipenko
Replace drm_gem_shmem locks with the reservation lock to make GEM
lockings more consistent.

Previously drm_gem_shmem_vmap() and drm_gem_shmem_get_pages() were
protected by separate locks, now it's the same lock for non-imported GEMs.
For imported GEMs with still use a separate lock in vmap/vunmap() to
avoid recursive locking of reservations, the reservation's locking isn't
needed in this case.

Suggested-by: Daniel Vetter 
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/drm_gem_shmem_helper.c| 54 ---
 drivers/gpu/drm/lima/lima_gem.c   |  8 +--
 .../gpu/drm/panfrost/panfrost_gem_shrinker.c  |  4 +-
 drivers/gpu/drm/panfrost/panfrost_mmu.c   | 15 +++---
 include/drm/drm_gem_shmem_helper.h|  5 --
 5 files changed, 50 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c 
b/drivers/gpu/drm/drm_gem_shmem_helper.c
index 5c7a7106b41d..cc90a4c28ace 100644
--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -86,7 +86,6 @@ __drm_gem_shmem_create(struct drm_device *dev, size_t size, 
bool private)
if (ret)
goto err_release;
 
-   mutex_init(>pages_lock);
mutex_init(>vmap_lock);
INIT_LIST_HEAD(>madv_list);
 
@@ -157,8 +156,6 @@ void drm_gem_shmem_free(struct drm_gem_shmem_object *shmem)
WARN_ON(shmem->pages_use_count);
 
drm_gem_object_release(obj);
-   mutex_destroy(>pages_lock);
-   mutex_destroy(>vmap_lock);
kfree(shmem);
 }
 EXPORT_SYMBOL_GPL(drm_gem_shmem_free);
@@ -209,11 +206,11 @@ int drm_gem_shmem_get_pages(struct drm_gem_shmem_object 
*shmem)
 
WARN_ON(shmem->base.import_attach);
 
-   ret = mutex_lock_interruptible(>pages_lock);
+   ret = dma_resv_lock_interruptible(shmem->base.resv, NULL);
if (ret)
return ret;
ret = drm_gem_shmem_get_pages_locked(shmem);
-   mutex_unlock(>pages_lock);
+   dma_resv_unlock(shmem->base.resv);
 
return ret;
 }
@@ -248,9 +245,9 @@ static void drm_gem_shmem_put_pages_locked(struct 
drm_gem_shmem_object *shmem)
  */
 void drm_gem_shmem_put_pages(struct drm_gem_shmem_object *shmem)
 {
-   mutex_lock(>pages_lock);
+   dma_resv_lock(shmem->base.resv, NULL);
drm_gem_shmem_put_pages_locked(shmem);
-   mutex_unlock(>pages_lock);
+   dma_resv_unlock(shmem->base.resv);
 }
 EXPORT_SYMBOL(drm_gem_shmem_put_pages);
 
@@ -310,7 +307,7 @@ static int drm_gem_shmem_vmap_locked(struct 
drm_gem_shmem_object *shmem,
} else {
pgprot_t prot = PAGE_KERNEL;
 
-   ret = drm_gem_shmem_get_pages(shmem);
+   ret = drm_gem_shmem_get_pages_locked(shmem);
if (ret)
goto err_zero_use;
 
@@ -358,13 +355,22 @@ static int drm_gem_shmem_vmap_locked(struct 
drm_gem_shmem_object *shmem,
 int drm_gem_shmem_vmap(struct drm_gem_shmem_object *shmem,
   struct iosys_map *map)
 {
+   struct drm_gem_object *obj = >base;
int ret;
 
-   ret = mutex_lock_interruptible(>vmap_lock);
+   if (obj->import_attach)
+   ret = mutex_lock_interruptible(>vmap_lock);
+   else
+   ret = dma_resv_lock_interruptible(shmem->base.resv, NULL);
+
if (ret)
return ret;
ret = drm_gem_shmem_vmap_locked(shmem, map);
-   mutex_unlock(>vmap_lock);
+
+   if (obj->import_attach)
+   mutex_unlock(>vmap_lock);
+   else
+   dma_resv_unlock(shmem->base.resv);
 
return ret;
 }
@@ -385,7 +391,7 @@ static void drm_gem_shmem_vunmap_locked(struct 
drm_gem_shmem_object *shmem,
dma_buf_vunmap(obj->import_attach->dmabuf, map);
} else {
vunmap(shmem->vaddr);
-   drm_gem_shmem_put_pages(shmem);
+   drm_gem_shmem_put_pages_locked(shmem);
}
 
shmem->vaddr = NULL;
@@ -406,9 +412,19 @@ static void drm_gem_shmem_vunmap_locked(struct 
drm_gem_shmem_object *shmem,
 void drm_gem_shmem_vunmap(struct drm_gem_shmem_object *shmem,
  struct iosys_map *map)
 {
-   mutex_lock(>vmap_lock);
+   struct drm_gem_object *obj = >base;
+
+   if (obj->import_attach)
+   mutex_lock(>vmap_lock);
+   else
+   dma_resv_lock(shmem->base.resv, NULL);
+
drm_gem_shmem_vunmap_locked(shmem, map);
-   mutex_unlock(>vmap_lock);
+
+   if (obj->import_attach)
+   mutex_unlock(>vmap_lock);
+   else
+   dma_resv_unlock(shmem->base.resv);
 }
 EXPORT_SYMBOL(drm_gem_shmem_vunmap);
 
@@ -442,14 +458,14 @@ drm_gem_shmem_create_with_handle(struct drm_file 
*file_priv,
  */
 int drm_gem_shmem_madvise(struct drm_gem_shmem_object *shmem, int madv)
 {
-   mutex_lock(>pages_lock);
+   dma_resv_lock(shmem->base.resv, NULL);
 
if (shmem->madv >= 0)
shmem->madv = madv;
 
madv = 

[PATCH v5 07/17] drm/virtio: Simplify error handling of virtio_gpu_object_create()

2022-04-24 Thread Dmitry Osipenko
Change the order of SHMEM initialization and reservation locking to
make code cleaner a tad and to prepare to transitioning of the common
GEM SHMEM code to use the GEM's reservation lock instead of the
shmem.page_lock.

There is no need to lock reservation during allocation of the SHMEM pages
because the lock is needed only to avoid racing with the async host-side
allocation. Hence we can safely move the SHMEM initialization out of the
reservation lock.

Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/virtio/virtgpu_object.c | 13 -
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c 
b/drivers/gpu/drm/virtio/virtgpu_object.c
index 21c19cdedce0..18f70ef6b4d0 100644
--- a/drivers/gpu/drm/virtio/virtgpu_object.c
+++ b/drivers/gpu/drm/virtio/virtgpu_object.c
@@ -236,6 +236,10 @@ int virtio_gpu_object_create(struct virtio_gpu_device 
*vgdev,
 
bo->dumb = params->dumb;
 
+   ret = virtio_gpu_object_shmem_init(vgdev, bo, , );
+   if (ret != 0)
+   goto err_put_id;
+
if (fence) {
ret = -ENOMEM;
objs = virtio_gpu_array_alloc(1);
@@ -248,15 +252,6 @@ int virtio_gpu_object_create(struct virtio_gpu_device 
*vgdev,
goto err_put_objs;
}
 
-   ret = virtio_gpu_object_shmem_init(vgdev, bo, , );
-   if (ret != 0) {
-   if (fence)
-   virtio_gpu_array_unlock_resv(objs);
-   virtio_gpu_array_put_free(objs);
-   virtio_gpu_free_object(_obj->base);
-   return ret;
-   }
-
if (params->blob) {
if (params->blob_mem == VIRTGPU_BLOB_MEM_GUEST)
bo->guest_blob = true;
-- 
2.35.1



[PATCH v5 10/17] drm/shmem-helper: Correct doc-comment of drm_gem_shmem_get_sg_table()

2022-04-24 Thread Dmitry Osipenko
drm_gem_shmem_get_sg_table() never returns NULL on error, but a ERR_PTR.
Correct the doc comment which says that it returns NULL on error.

Acked-by: Thomas Zimmermann 
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/drm_gem_shmem_helper.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c 
b/drivers/gpu/drm/drm_gem_shmem_helper.c
index 8ad0e02991ca..5c7a7106b41d 100644
--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -662,7 +662,8 @@ EXPORT_SYMBOL(drm_gem_shmem_print_info);
  * drm_gem_shmem_get_pages_sgt() instead.
  *
  * Returns:
- * A pointer to the scatter/gather table of pinned pages or NULL on failure.
+ * A pointer to the scatter/gather table of pinned pages or an 
ERR_PTR()-encoded
+ * error code on failure.
  */
 struct sg_table *drm_gem_shmem_get_sg_table(struct drm_gem_shmem_object *shmem)
 {
@@ -688,7 +689,8 @@ EXPORT_SYMBOL_GPL(drm_gem_shmem_get_sg_table);
  * drm_gem_shmem_get_sg_table() should not be directly called by drivers.
  *
  * Returns:
- * A pointer to the scatter/gather table of pinned pages or errno on failure.
+ * A pointer to the scatter/gather table of pinned pages or an 
ERR_PTR()-encoded
+ * error code on failure.
  */
 struct sg_table *drm_gem_shmem_get_pages_sgt(struct drm_gem_shmem_object 
*shmem)
 {
-- 
2.35.1



[PATCH v5 08/17] drm/virtio: Improve DMA API usage for shmem BOs

2022-04-24 Thread Dmitry Osipenko
DRM API requires the DRM's driver to be backed with the device that can
be used for generic DMA operations. The VirtIO-GPU device can't perform
DMA operations if it uses PCI transport because PCI device driver creates
a virtual VirtIO-GPU device that isn't associated with the PCI. Use PCI's
GPU device for the DRM's device instead of the VirtIO-GPU device and drop
DMA-related hacks from the VirtIO-GPU driver.

Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/virtio/virtgpu_drv.c| 51 ++
 drivers/gpu/drm/virtio/virtgpu_drv.h|  5 +--
 drivers/gpu/drm/virtio/virtgpu_kms.c|  7 ++--
 drivers/gpu/drm/virtio/virtgpu_object.c | 56 +
 drivers/gpu/drm/virtio/virtgpu_vq.c | 13 +++---
 5 files changed, 32 insertions(+), 100 deletions(-)

diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c 
b/drivers/gpu/drm/virtio/virtgpu_drv.c
index 5f25a8d15464..0141b7df97ec 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.c
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.c
@@ -46,12 +46,11 @@ static int virtio_gpu_modeset = -1;
 MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
 module_param_named(modeset, virtio_gpu_modeset, int, 0400);
 
-static int virtio_gpu_pci_quirk(struct drm_device *dev, struct virtio_device 
*vdev)
+static int virtio_gpu_pci_quirk(struct drm_device *dev)
 {
-   struct pci_dev *pdev = to_pci_dev(vdev->dev.parent);
+   struct pci_dev *pdev = to_pci_dev(dev->dev);
const char *pname = dev_name(>dev);
bool vga = (pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA;
-   char unique[20];
int ret;
 
DRM_INFO("pci: %s detected at %s\n",
@@ -63,39 +62,7 @@ static int virtio_gpu_pci_quirk(struct drm_device *dev, 
struct virtio_device *vd
return ret;
}
 
-   /*
-* Normally the drm_dev_set_unique() call is done by core DRM.
-* The following comment covers, why virtio cannot rely on it.
-*
-* Unlike the other virtual GPU drivers, virtio abstracts the
-* underlying bus type by using struct virtio_device.
-*
-* Hence the dev_is_pci() check, used in core DRM, will fail
-* and the unique returned will be the virtio_device "virtio0",
-* while a "pci:..." one is required.
-*
-* A few other ideas were considered:
-* - Extend the dev_is_pci() check [in drm_set_busid] to
-*   consider virtio.
-*   Seems like a bigger hack than what we have already.
-*
-* - Point drm_device::dev to the parent of the virtio_device
-*   Semantic changes:
-*   * Using the wrong device for i2c, framebuffer_alloc and
-* prime import.
-*   Visual changes:
-*   * Helpers such as DRM_DEV_ERROR, dev_info, drm_printer,
-* will print the wrong information.
-*
-* We could address the latter issues, by introducing
-* drm_device::bus_dev, ... which would be used solely for this.
-*
-* So for the moment keep things as-is, with a bulky comment
-* for the next person who feels like removing this
-* drm_dev_set_unique() quirk.
-*/
-   snprintf(unique, sizeof(unique), "pci:%s", pname);
-   return drm_dev_set_unique(dev, unique);
+   return 0;
 }
 
 static int virtio_gpu_probe(struct virtio_device *vdev)
@@ -109,18 +76,24 @@ static int virtio_gpu_probe(struct virtio_device *vdev)
if (virtio_gpu_modeset == 0)
return -EINVAL;
 
-   dev = drm_dev_alloc(, >dev);
+   /*
+* The virtio-gpu device is a virtual device that doesn't have DMA
+* ops assigned to it, nor DMA mask set and etc. Its parent device
+* is actual GPU device we want to use it for the DRM's device in
+* order to benefit from using generic DRM APIs.
+*/
+   dev = drm_dev_alloc(, vdev->dev.parent);
if (IS_ERR(dev))
return PTR_ERR(dev);
vdev->priv = dev;
 
if (!strcmp(vdev->dev.parent->bus->name, "pci")) {
-   ret = virtio_gpu_pci_quirk(dev, vdev);
+   ret = virtio_gpu_pci_quirk(dev);
if (ret)
goto err_free;
}
 
-   ret = virtio_gpu_init(dev);
+   ret = virtio_gpu_init(vdev, dev);
if (ret)
goto err_free;
 
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h 
b/drivers/gpu/drm/virtio/virtgpu_drv.h
index 0a194aaad419..b2d93cb12ebf 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.h
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
@@ -100,8 +100,6 @@ struct virtio_gpu_object {
 
 struct virtio_gpu_object_shmem {
struct virtio_gpu_object base;
-   struct sg_table *pages;
-   uint32_t mapped;
 };
 
 struct virtio_gpu_object_vram {
@@ -214,7 +212,6 @@ struct virtio_gpu_drv_cap_cache {
 };
 
 struct virtio_gpu_device {
-   struct device *dev;
struct drm_device *ddev;
 
struct virtio_device 

[PATCH v5 05/17] drm/virtio: Unlock reservations on dma_resv_reserve_fences() error

2022-04-24 Thread Dmitry Osipenko
Unlock reservations on dma_resv_reserve_fences() error to fix recursive
locking of the reservations when this error happens.

Cc: sta...@vger.kernel.org
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/virtio/virtgpu_gem.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/virtio/virtgpu_gem.c 
b/drivers/gpu/drm/virtio/virtgpu_gem.c
index 580a78809836..7db48d17ee3a 100644
--- a/drivers/gpu/drm/virtio/virtgpu_gem.c
+++ b/drivers/gpu/drm/virtio/virtgpu_gem.c
@@ -228,8 +228,10 @@ int virtio_gpu_array_lock_resv(struct 
virtio_gpu_object_array *objs)
 
for (i = 0; i < objs->nents; ++i) {
ret = dma_resv_reserve_fences(objs->objs[i]->resv, 1);
-   if (ret)
+   if (ret) {
+   virtio_gpu_array_unlock_resv(objs);
return ret;
+   }
}
return ret;
 }
-- 
2.35.1



[PATCH v5 06/17] drm/virtio: Use appropriate atomic state in virtio_gpu_plane_cleanup_fb()

2022-04-24 Thread Dmitry Osipenko
Make virtio_gpu_plane_cleanup_fb() to clean the state which DRM core
wants to clean up and not the current plane's state. Normally the older
atomic state is cleaned up, but the newer state could also be cleaned up
in case of aborted commits.

Cc: sta...@vger.kernel.org
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/virtio/virtgpu_plane.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c 
b/drivers/gpu/drm/virtio/virtgpu_plane.c
index 6d3cc9e238a4..7148f3813d8b 100644
--- a/drivers/gpu/drm/virtio/virtgpu_plane.c
+++ b/drivers/gpu/drm/virtio/virtgpu_plane.c
@@ -266,14 +266,14 @@ static int virtio_gpu_plane_prepare_fb(struct drm_plane 
*plane,
 }
 
 static void virtio_gpu_plane_cleanup_fb(struct drm_plane *plane,
-   struct drm_plane_state *old_state)
+   struct drm_plane_state *state)
 {
struct virtio_gpu_framebuffer *vgfb;
 
-   if (!plane->state->fb)
+   if (!state->fb)
return;
 
-   vgfb = to_virtio_gpu_framebuffer(plane->state->fb);
+   vgfb = to_virtio_gpu_framebuffer(state->fb);
if (vgfb->fence) {
dma_fence_put(>fence->f);
vgfb->fence = NULL;
-- 
2.35.1



[PATCH v5 04/17] drm/virtio: Unlock reservations on virtio_gpu_object_shmem_init() error

2022-04-24 Thread Dmitry Osipenko
Unlock reservations in the error code path of virtio_gpu_object_create()
to silence debug warning splat produced by ww_mutex_destroy(>lock)
when GEM is released with the held lock.

Cc: sta...@vger.kernel.org
Reviewed-by: Emil Velikov 
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/virtio/virtgpu_object.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c 
b/drivers/gpu/drm/virtio/virtgpu_object.c
index 3d0c8d4d1c20..21c19cdedce0 100644
--- a/drivers/gpu/drm/virtio/virtgpu_object.c
+++ b/drivers/gpu/drm/virtio/virtgpu_object.c
@@ -250,6 +250,8 @@ int virtio_gpu_object_create(struct virtio_gpu_device 
*vgdev,
 
ret = virtio_gpu_object_shmem_init(vgdev, bo, , );
if (ret != 0) {
+   if (fence)
+   virtio_gpu_array_unlock_resv(objs);
virtio_gpu_array_put_free(objs);
virtio_gpu_free_object(_obj->base);
return ret;
-- 
2.35.1



[PATCH v5 03/17] drm/virtio: Check whether transferred 2D BO is shmem

2022-04-24 Thread Dmitry Osipenko
Transferred 2D BO always must be a shmem BO. Add check for that to prevent
NULL dereference if userspace passes a VRAM BO.

Cc: sta...@vger.kernel.org
Reviewed-by: Emil Velikov 
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/virtio/virtgpu_vq.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c 
b/drivers/gpu/drm/virtio/virtgpu_vq.c
index 7c052efe8836..2edf31806b74 100644
--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -595,7 +595,7 @@ void virtio_gpu_cmd_transfer_to_host_2d(struct 
virtio_gpu_device *vgdev,
bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev);
struct virtio_gpu_object_shmem *shmem = to_virtio_gpu_shmem(bo);
 
-   if (use_dma_api)
+   if (virtio_gpu_is_shmem(bo) && use_dma_api)
dma_sync_sgtable_for_device(vgdev->vdev->dev.parent,
shmem->pages, DMA_TO_DEVICE);
 
-- 
2.35.1



[PATCH v5 01/17] drm/panfrost: Put mapping instead of shmem obj on panfrost_mmu_map_fault_addr() error

2022-04-24 Thread Dmitry Osipenko
When panfrost_mmu_map_fault_addr() fails, the BO's mapping should be
unreferenced and not the shmem object that backs that mapping.

Cc: sta...@vger.kernel.org
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/panfrost/panfrost_mmu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c 
b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index d3f82b26a631..b285a8001b1d 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -518,7 +518,7 @@ static int panfrost_mmu_map_fault_addr(struct 
panfrost_device *pfdev, int as,
 err_pages:
drm_gem_shmem_put_pages(>base);
 err_bo:
-   drm_gem_object_put(>base.base);
+   panfrost_gem_mapping_put(bomapping);
return ret;
 }
 
-- 
2.35.1



[PATCH v5 02/17] drm/virtio: Correct drm_gem_shmem_get_sg_table() error handling

2022-04-24 Thread Dmitry Osipenko
drm_gem_shmem_get_sg_table() never ever returned NULL on error. Correct
the error handling to avoid crash on OOM.

Cc: sta...@vger.kernel.org
Reviewed-by: Emil Velikov 
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/virtio/virtgpu_object.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c 
b/drivers/gpu/drm/virtio/virtgpu_object.c
index f293e6ad52da..3d0c8d4d1c20 100644
--- a/drivers/gpu/drm/virtio/virtgpu_object.c
+++ b/drivers/gpu/drm/virtio/virtgpu_object.c
@@ -168,9 +168,11 @@ static int virtio_gpu_object_shmem_init(struct 
virtio_gpu_device *vgdev,
 * since virtio_gpu doesn't support dma-buf import from other devices.
 */
shmem->pages = drm_gem_shmem_get_sg_table(>base);
-   if (!shmem->pages) {
+   ret = PTR_ERR_OR_ZERO(shmem->pages);
+   if (ret) {
drm_gem_shmem_unpin(>base);
-   return -EINVAL;
+   shmem->pages = NULL;
+   return ret;
}
 
if (use_dma_api) {
-- 
2.35.1



[PATCH v5 00/17] Add generic memory shrinker to VirtIO-GPU and Panfrost DRM drivers

2022-04-24 Thread Dmitry Osipenko
Hello,

This patchset introduces memory shrinker for the VirtIO-GPU DRM driver.
During OOM, the shrinker will release BOs that are marked as "not needed"
by userspace using the new madvise IOCTL, it will also evict idling BOs
to SWAP. The userspace in this case is the Mesa VirGL driver, it will mark
the cached BOs as "not needed", allowing kernel driver to release memory
of the cached shmem BOs on lowmem situations, preventing OOM kills.

This patchset adds memory purging and eviction support to VirtIO-GPU driver.

The Panfrost driver is switched to use generic memory shrinker. Eviction
support will come later on, after resolving the blocker bug in Panfrost.

This patchset also includes couple improvements and fixes for various
minor things that I found while was working on the shrinker.

The Mesa and IGT patches will be kept on hold until this kernel series
will be approved and merged.

This patchset was tested using Qemu and crosvm, including both cases of
IOMMU off/on.

Mesa: https://gitlab.freedesktop.org/digetx/mesa/-/commits/virgl-madvise
IGT:  
https://gitlab.freedesktop.org/digetx/igt-gpu-tools/-/commits/virtio-madvise
  
https://gitlab.freedesktop.org/digetx/igt-gpu-tools/-/commits/panfrost-madvise

Changelog:

v5: - Added new for-stable patch "drm/panfrost: Put mapping instead of
  shmem obj on panfrost_mmu_map_fault_addr() error" that corrects GEM's
  refcounting in case of error.

- The drm_gem_shmem_v[un]map() now takes a separate vmap_lock for
  imported GEMs to avoid recursive locking of DMA reservations.
  This addresses v4 comment from Thomas Zimmermann about the potential
  deadlocking of vmapping.

- Added ack from Thomas Zimmermann to "drm/shmem-helper: Correct
  doc-comment of drm_gem_shmem_get_sg_table()" patch.

- Dropped explicit shmem states from the generic shrinker patch as
  was requested by Thomas Zimmermann.

- Improved variable names and comments of the generic shrinker code.

- Extended drm_gem_shmem_print_info() with the shrinker-state info in
  the "drm/virtio: Support memory shrinking" patch.

- Moved evict()/swap_in()/purge() callbacks from drm_gem_object_funcs
  to drm_gem_shmem_object in the generic shrinker patch, for more
  consistency.

- Corrected bisectability of the patches that was broken in v4
  by accident.

- The virtio_gpu_plane_prepare_fb() now uses drm_gem_shmem_pin() instead
  of drm_gem_shmem_set_unpurgeable_and_unevictable() and does it only for
  shmem BOs in the "drm/virtio: Support memory shrinking" patch.

- Made more functions private to drm_gem_shmem_helper.c as was requested
  by Thomas Zimmermann. This minimizes number of the public shmem helpers.

v4: - Corrected minor W=1 warnings reported by kernel test robot for v3.

- Renamed DRM_GEM_SHMEM_PAGES_STATE_ACTIVE/INACTIVE to PINNED/UNPINNED,
  for more clarity.

v3: - Hardened shrinker's count() with usage of READ_ONCE() since we don't
  use atomic type for counting and technically compiler is free to
  re-fetch counter's variable.

- "Correct drm_gem_shmem_get_sg_table() error handling" now uses
  PTR_ERR_OR_ZERO(), fixing typo that was made in v2.

- Removed obsoleted shrinker from the Panfrost driver, which I missed to
  do in v2 by accident and Alyssa Rosenzweig managed to notice it.

- CCed stable kernels in all patches that make fixes, even the minor ones,
  like was suggested by Emil Velikov and added his r-b to the patches.

- Added t-b from Steven Price to the Panfrost's shrinker patch.

- Corrected doc-comment of drm_gem_shmem_object.madv, like was suggested
  by Steven Price. Comment now says that madv=1 means "object is purged"
  instead of saying that value is unused.

- Added more doc-comments to the new shmem shrinker API.

- The "Improve DMA API usage for shmem BOs" patch got more improvements
  by removing the obsoleted drm_dev_set_unique() quirk and its comment.

- Added patch that makes Virtio-GPU driver to use common dev_is_pci()
  helper, which was suggested by Robin Murphy.

- Added new "drm/shmem-helper: Take GEM reservation lock instead of
  drm_gem_shmem locks" patch, which was suggested by Daniel Vetter.

- Added new "drm/virtio: Simplify error handling of
  virtio_gpu_object_create()" patch.

- Improved "Correct doc-comment of drm_gem_shmem_get_sg_table()" patch,
  like was suggested by Daniel Vetter, by saying that function returns
  ERR_PTR() and not errno.

- virtio_gpu_purge_object() is fenced properly now, turned out
  virtio_gpu_notify() doesn't do fencing as I was supposing before.
  Stress testing of memory eviction revealed that.

- Added new patch that corrects virtio_gpu_plane_cleanup_fb() to use
  appropriate atomic plane state.

- SHMEM shrinker got eviction support.

- VirtIO-GPU driver now supports memory eviction. It's enabled 

Re: [PATCH v2 00/48] ARM: PXA multiplatform support

2022-04-24 Thread Arnd Bergmann
On Sun, Apr 24, 2022 at 5:28 PM Guenter Roeck  wrote:
> On 4/24/22 01:52, Arnd Bergmann wrote:
> > On Sun, Apr 24, 2022 at 4:09 AM Guenter Roeck  wrote:
> > into the defconfig file, otherwise the multiplatform target defaults to
> > an ARMv7 instead of ARMv5 build. For an OMAP15xx as in the SX1,
> > you also need to enable CONFIG_ARCH_MULTI_V4T.
> >
> > This is slightly unfortunate, but I don't see any way to avoid it, and the
> > modified defconfig will still work fine with older kernel trees.
> >
>
> Yes, that works. I changed it in my configuration.

Ok, great!. I managed to boot the z2 machine with PCMCIA support
and it gets around the issue with my patch, correctly detecting the
CF card.

> >>> One thing I keep having to apply myself is this snippet:
> >>>
> >>> diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S
> >>> index 0bfad62ea858..87c695703580 100644
> >>> --- a/arch/arm/mm/proc-arm925.S
> >>> +++ b/arch/arm/mm/proc-arm925.S
> >>> @@ -441,7 +441,6 @@ __arm925_setup:
> >>>
> >>>#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
> >>>   mov r0, #4  @ disable write-back
> >>> on caches explicitly
> >>> -   mcr p15, 7, r0, c15, c0, 0
> >>>#endif
> >>
> >> it does not have CONFIG_CPU_DCACHE_WRITETHROUGH enabled.
> >
> > Maybe it was disabled explicitly for the sx1_defconfig because of this
> > bug. I would think that this is required for actual sx1 hardware because the
> > option is default-enabled for ARM925T, and that CPU core is exclusively
> > used in OMAP15xx.
> >
>
> That looks like a bug in qemu. ARM925T instruction support is limited to V4T
> instructions. qemu doesn't have explicit 5T support. It is either V4T
> or V5.

I'm not entirely sure what instructions the CPU supports, but Linux
treats it as ARMv4T as well, and qemu supports some of the 925t
specific instructions as "ti925t" in target/arm/cpu_tcg.c, it just seems
it's missing some others.

  Arnd


[PATCH] drm/v3d: Fix null pointer dereference of pointer perfmon

2022-04-24 Thread Colin Ian King
In the unlikely event that pointer perfmon is null the WARN_ON return path
occurs after the pointer has already been deferenced. Fix this by only
dereferencing perfmon after it has been null checked.

Fixes: 26a4dc29b74a ("drm/v3d: Expose performance counters to userspace")
Signed-off-by: Colin Ian King 
---
 drivers/gpu/drm/v3d/v3d_perfmon.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/v3d/v3d_perfmon.c 
b/drivers/gpu/drm/v3d/v3d_perfmon.c
index 0288ef063513..f6a88abccc7d 100644
--- a/drivers/gpu/drm/v3d/v3d_perfmon.c
+++ b/drivers/gpu/drm/v3d/v3d_perfmon.c
@@ -25,11 +25,12 @@ void v3d_perfmon_start(struct v3d_dev *v3d, struct 
v3d_perfmon *perfmon)
 {
unsigned int i;
u32 mask;
-   u8 ncounters = perfmon->ncounters;
+   u8 ncounters;
 
if (WARN_ON_ONCE(!perfmon || v3d->active_perfmon))
return;
 
+   ncounters = perfmon->ncounters;
mask = GENMASK(ncounters - 1, 0);
 
for (i = 0; i < ncounters; i++) {
-- 
2.35.1



Re: [Freedreno] [PATCH v4 03/20] drm: allow real encoder to be passed for drm_writeback_connector

2022-04-24 Thread Abhinav Kumar




On 4/24/2022 11:12 AM, Abhinav Kumar wrote:

Hi Laurent

On 4/24/2022 7:50 AM, Laurent Pinchart wrote:

Hi Abhinav,

Thank you for the patch.

On Fri, Apr 22, 2022 at 04:06:38PM -0700, Abhinav Kumar wrote:

For some vendor driver implementations, display hardware can
be shared between the encoder used for writeback and the physical
display.

In addition resources such as clocks and interrupts can
also be shared between writeback and the real encoder.

To accommodate such vendor drivers and hardware, allow
real encoder to be passed for drm_writeback_connector.

For existing clients, drm_writeback_connector_init() will use
an internal_encoder under the hood and hence no changes will
be needed.

changes in v7:
- move this change before the vc4 change in the series
  to minimize the changes to vendor drivers in drm core
  changes


Why is this needed ? The drm_writeback_connector functions don't need
the drm_encoder after drm_writeback_connector_init() (or
drm_writeback_connector_init_with_encoder()) returns.



Sorry I didnt follow this comment. This change log is incorrect, so 
after changing the previous change in the series and modifying this, no 
further changes are needed to vc4, so I decided to drop the next change.

So this change log is incorrect. I can remove this.

Is that what you meant?


So till the previous change, the only user of 
drm_writeback_connector_init_with_encoder() was 
drm_writeback_connector_init() which was still passing its own 
internal_encoder.


Only if the wb_connector->encoder is changed to a pointer, other vendor 
drivers can pass their own encoder to 
drm_writeback_connector_init_with_encoder().


Hence you are right that drm_writeback_connector functions do not need 
drm_encoder after init() returns, but till this change is done, other 
vendor drivers cannot directly call 
drm_writeback_connector_init_with_encoder() because the encoder will not 
be valid till then.


Hope this clarifies it.




Signed-off-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
---
  drivers/gpu/drm/drm_writeback.c | 18 --
  drivers/gpu/drm/vc4/vc4_txp.c   |  4 ++--
  include/drm/drm_writeback.h | 22 --
  3 files changed, 34 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/drm_writeback.c 
b/drivers/gpu/drm/drm_writeback.c

index 92658ad..0538674 100644
--- a/drivers/gpu/drm/drm_writeback.c
+++ b/drivers/gpu/drm/drm_writeback.c
@@ -180,21 +180,21 @@ int drm_writeback_connector_init(struct 
drm_device *dev,

  {
  int ret = 0;
-    drm_encoder_helper_add(_connector->encoder, enc_helper_funcs);
+    drm_encoder_helper_add(_connector->internal_encoder, 
enc_helper_funcs);

-    wb_connector->encoder.possible_crtcs = possible_crtcs;
+    wb_connector->internal_encoder.possible_crtcs = possible_crtcs;
-    ret = drm_encoder_init(dev, _connector->encoder,
+    ret = drm_encoder_init(dev, _connector->internal_encoder,
 _writeback_encoder_funcs,
 DRM_MODE_ENCODER_VIRTUAL, NULL);
  if (ret)
  return ret;
-    ret = drm_writeback_connector_init_with_encoder(dev, 
wb_connector, _connector->encoder,

-    con_funcs, formats, n_formats);
+    ret = drm_writeback_connector_init_with_encoder(dev, wb_connector,
+    _connector->internal_encoder, con_funcs, formats, 
n_formats);

  if (ret)
-    drm_encoder_cleanup(_connector->encoder);
+    drm_encoder_cleanup(_connector->internal_encoder);
  return ret;
  }
@@ -239,6 +239,12 @@ int 
drm_writeback_connector_init_with_encoder(struct drm_device *dev,

  struct drm_mode_config *config = >mode_config;
  int ret = create_writeback_properties(dev);
+    /*
+ * Assign the encoder passed to this API to the wb_connector's 
encoder.
+ * For drm_writeback_connector_init(), this shall be the 
internal_encoder

+ */
+    wb_connector->encoder = enc;
+
  if (ret != 0)
  return ret;
diff --git a/drivers/gpu/drm/vc4/vc4_txp.c 
b/drivers/gpu/drm/vc4/vc4_txp.c

index 3447eb6..7e063a9 100644
--- a/drivers/gpu/drm/vc4/vc4_txp.c
+++ b/drivers/gpu/drm/vc4/vc4_txp.c
@@ -159,7 +159,7 @@ struct vc4_txp {
  static inline struct vc4_txp *encoder_to_vc4_txp(struct drm_encoder 
*encoder)

  {
-    return container_of(encoder, struct vc4_txp, connector.encoder);
+    return container_of(encoder, struct vc4_txp, 
connector.internal_encoder);

  }
  static inline struct vc4_txp *connector_to_vc4_txp(struct 
drm_connector *conn)
@@ -507,7 +507,7 @@ static int vc4_txp_bind(struct device *dev, 
struct device *master, void *data)

  if (ret)
  return ret;
-    encoder = >connector.encoder;
+    encoder = txp->connector.encoder;
  encoder->possible_crtcs = drm_crtc_mask(crtc);
  ret = devm_request_irq(dev, irq, vc4_txp_interrupt, 0,
diff --git a/include/drm/drm_writeback.h b/include/drm/drm_writeback.h
index bb306fa..3fbae9d 100644
--- a/include/drm/drm_writeback.h
+++ 

Re: [PATCH v4 03/20] drm: allow real encoder to be passed for drm_writeback_connector

2022-04-24 Thread Abhinav Kumar

Hi Laurent

On 4/24/2022 7:50 AM, Laurent Pinchart wrote:

Hi Abhinav,

Thank you for the patch.

On Fri, Apr 22, 2022 at 04:06:38PM -0700, Abhinav Kumar wrote:

For some vendor driver implementations, display hardware can
be shared between the encoder used for writeback and the physical
display.

In addition resources such as clocks and interrupts can
also be shared between writeback and the real encoder.

To accommodate such vendor drivers and hardware, allow
real encoder to be passed for drm_writeback_connector.

For existing clients, drm_writeback_connector_init() will use
an internal_encoder under the hood and hence no changes will
be needed.

changes in v7:
- move this change before the vc4 change in the series
  to minimize the changes to vendor drivers in drm core
  changes


Why is this needed ? The drm_writeback_connector functions don't need
the drm_encoder after drm_writeback_connector_init() (or
drm_writeback_connector_init_with_encoder()) returns.



Sorry I didnt follow this comment. This change log is incorrect, so 
after changing the previous change in the series and modifying this, no 
further changes are needed to vc4, so I decided to drop the next change.

So this change log is incorrect. I can remove this.

Is that what you meant?


Signed-off-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
---
  drivers/gpu/drm/drm_writeback.c | 18 --
  drivers/gpu/drm/vc4/vc4_txp.c   |  4 ++--
  include/drm/drm_writeback.h | 22 --
  3 files changed, 34 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/drm_writeback.c b/drivers/gpu/drm/drm_writeback.c
index 92658ad..0538674 100644
--- a/drivers/gpu/drm/drm_writeback.c
+++ b/drivers/gpu/drm/drm_writeback.c
@@ -180,21 +180,21 @@ int drm_writeback_connector_init(struct drm_device *dev,
  {
int ret = 0;
  
-	drm_encoder_helper_add(_connector->encoder, enc_helper_funcs);

+   drm_encoder_helper_add(_connector->internal_encoder, 
enc_helper_funcs);
  
-	wb_connector->encoder.possible_crtcs = possible_crtcs;

+   wb_connector->internal_encoder.possible_crtcs = possible_crtcs;
  
-	ret = drm_encoder_init(dev, _connector->encoder,

+   ret = drm_encoder_init(dev, _connector->internal_encoder,
   _writeback_encoder_funcs,
   DRM_MODE_ENCODER_VIRTUAL, NULL);
if (ret)
return ret;
  
-	ret = drm_writeback_connector_init_with_encoder(dev, wb_connector, _connector->encoder,

-   con_funcs, formats, n_formats);
+   ret = drm_writeback_connector_init_with_encoder(dev, wb_connector,
+   _connector->internal_encoder, con_funcs, formats, 
n_formats);
  
  	if (ret)

-   drm_encoder_cleanup(_connector->encoder);
+   drm_encoder_cleanup(_connector->internal_encoder);
  
  	return ret;

  }
@@ -239,6 +239,12 @@ int drm_writeback_connector_init_with_encoder(struct 
drm_device *dev,
struct drm_mode_config *config = >mode_config;
int ret = create_writeback_properties(dev);
  
+	/*

+* Assign the encoder passed to this API to the wb_connector's encoder.
+* For drm_writeback_connector_init(), this shall be the 
internal_encoder
+*/
+   wb_connector->encoder = enc;
+
if (ret != 0)
return ret;
  
diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c

index 3447eb6..7e063a9 100644
--- a/drivers/gpu/drm/vc4/vc4_txp.c
+++ b/drivers/gpu/drm/vc4/vc4_txp.c
@@ -159,7 +159,7 @@ struct vc4_txp {
  
  static inline struct vc4_txp *encoder_to_vc4_txp(struct drm_encoder *encoder)

  {
-   return container_of(encoder, struct vc4_txp, connector.encoder);
+   return container_of(encoder, struct vc4_txp, 
connector.internal_encoder);
  }
  
  static inline struct vc4_txp *connector_to_vc4_txp(struct drm_connector *conn)

@@ -507,7 +507,7 @@ static int vc4_txp_bind(struct device *dev, struct device 
*master, void *data)
if (ret)
return ret;
  
-	encoder = >connector.encoder;

+   encoder = txp->connector.encoder;
encoder->possible_crtcs = drm_crtc_mask(crtc);
  
  	ret = devm_request_irq(dev, irq, vc4_txp_interrupt, 0,

diff --git a/include/drm/drm_writeback.h b/include/drm/drm_writeback.h
index bb306fa..3fbae9d 100644
--- a/include/drm/drm_writeback.h
+++ b/include/drm/drm_writeback.h
@@ -25,13 +25,31 @@ struct drm_writeback_connector {
struct drm_connector base;
  
  	/**

-* @encoder: Internal encoder used by the connector to fulfill
+* @encoder: handle to drm_encoder used by the connector to fulfill
 * the DRM framework requirements. The users of the
 * @drm_writeback_connector control the behaviour of the @encoder
 * by passing the @enc_funcs parameter to drm_writeback_connector_init()
 * function.
+*
+* For some vendor drivers, the hardware 

Re: [PATCH 5.10.y] drm/cirrus: fix a NULL vs IS_ERR() checks

2022-04-24 Thread Shile Zhang

Hi David and Daniel,

Sorry but could you please help to check this issue?
Due to the function 'drm_gem_shmem_vmap' could return ERROR pointers 
which will cause the kernel crash due to 'cirrus_fb_blit_rect' only 
check the pointer.


Since the related code has been refactoring in mainline, so this issue 
only happened in stable 5.10.y branch.


@Greg
I think it is probably not realistic to backport the related refactoring 
from mainline directly, so I just give this bugfix patch only for 5.10.y 
branch.


Thanks!

On 2021/12/29 22:51, Shile Zhang wrote:



On 2021/12/29 21:31, Greg Kroah-Hartman wrote:

On Wed, Dec 29, 2021 at 08:48:53AM +0800, Shile Zhang wrote:



On 2021/12/28 22:39, Greg Kroah-Hartman wrote:

On Tue, Dec 28, 2021 at 10:19:30PM +0800, Shile Zhang wrote:



On 2021/12/28 22:05, Greg Kroah-Hartman wrote:

On Tue, Dec 28, 2021 at 09:56:25PM +0800, Shile Zhang wrote:



On 2021/12/28 21:51, Greg Kroah-Hartman wrote:

On Tue, Dec 28, 2021 at 09:25:56PM +0800, Shile Zhang wrote:
The function drm_gem_shmem_vmap can returns error pointers as 
well,

which could cause following kernel crash:

BUG: unable to handle page fault for address: fffc
PGD 1426a12067 P4D 1426a12067 PUD 1426a14067 PMD 0
Oops:  [#1] SMP NOPTI
CPU: 12 PID: 3598532 Comm: stress-ng Kdump: loaded Not tainted 
5.10.50.x86_64 #1

...
RIP: 0010:memcpy_toio+0x23/0x50
Code: 00 00 00 00 0f 1f 00 0f 1f 44 00 00 48 85 d2 74 28 40 f6 
c7 01 75 2b 48 83 fa 01 76 06 40 f6 c7 02 75 17 48 89 d1 48 c1 
e9 02  a5 f6 c2 02 74 02 66 a5 f6 c2 01 74 01 a4 c3 66 a5 
48 83 ea 02

RSP: 0018:afbf8a203c68 EFLAGS: 00010216
RAX:  RBX: fffc RCX: 0200
RDX: 0800 RSI: fffc RDI: afbf8200
RBP: afbf8200 R08: 0002 R09: 
R10: 02b5 R11:  R12: 0800
R13: 8a6801099300 R14: 0001 R15: 0300
FS:  7f4a6bc5f740() GS:8a864190() 
knlGS:

CS:  0010 DS:  ES:  CR0: 80050033
CR2: fffc CR3: 0016d3874001 CR4: 003606e0
Call Trace:
 drm_fb_memcpy_dstclip+0x5e/0x80 [drm_kms_helper]
 cirrus_fb_blit_rect.isra.0+0xb7/0xe0 [cirrus]
 cirrus_pipe_update+0x9f/0xa8 [cirrus]
 drm_atomic_helper_commit_planes+0xb8/0x220 [drm_kms_helper]
 drm_atomic_helper_commit_tail+0x42/0x80 [drm_kms_helper]
 commit_tail+0xce/0x130 [drm_kms_helper]
 drm_atomic_helper_commit+0x113/0x140 [drm_kms_helper]
 drm_client_modeset_commit_atomic+0x1c4/0x200 [drm]
 drm_client_modeset_commit_locked+0x53/0x80 [drm]
 drm_client_modeset_commit+0x24/0x40 [drm]
 drm_fbdev_client_restore+0x48/0x85 [drm_kms_helper]
 drm_client_dev_restore+0x64/0xb0 [drm]
 drm_release+0xf2/0x110 [drm]
 __fput+0x96/0x240
 task_work_run+0x5c/0x90
 exit_to_user_mode_loop+0xce/0xd0
 exit_to_user_mode_prepare+0x6a/0x70
 syscall_exit_to_user_mode+0x12/0x40
 entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x7f4a6bd82c2b

Fixes: ab3e023b1b4c9 ("drm/cirrus: rewrite and modernize driver.")

CC: sta...@vger.kernel.org
Reported-by: Wen Kang 
Signed-off-by: Shile Zhang 
---
 drivers/gpu/drm/tiny/cirrus.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)


What is the git commit id of this patch in Linus's tree?


Sorry, I checked that this issue seems fixed by the improvement 
in following

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


I do not understand, that is a huge patch series.  What individual
commit in Linus's tree resolves this?


Sorry,
1. This crash only happened in 5.10.y tree now, which fixed in 
Linus's tree

by refactoring in above huge series.


Which specific patch resolved the issue?


2. It's hard to get the individual commit to fix this issue from that
series. So I try to send this simple fix help to fix only for 
5.10.y, which

is needless to Linus's tree.


'git bisect' should be able to help you out.


Thanks for your guidance!




3. If this patch is not OK for stable tree, Could you please help to
backport the correct fix from Linus's tree in next version of 5.10.y?


If you can provide the commit id of the fix, sure.


Thanks!
I think it is this commit, which refactor the drm_gem_shmem_vmap 
makes the

pointer returned by new added parameter.
https://github.com/torvalds/linux/commit/49a3f51dfeeecb52c5aa28c5cb9592fe5e39bf95 



Have you tested it to be sure?  If so, can you please provide a
backported version that works?  As-is, it does not apply at all.


Yes, we've tested that the mainline code fixed this issue.
But sorry, I have not backported the bugfix from mainline due to that a 
huge series for code refactoring, with more dependencies an conflicts.


So I just work out a simple patch help to fix the crash.



Note, if this is to bit of a change for a stable tree (and I think it
is), your original patch might be correct, but I need some acks from the

[PATCH v2 1/2] drm: bridge: adv7511: enable CEC support for ADV7535

2022-04-24 Thread Alvin Å ipraga
From: Alvin Å ipraga 

Like the ADV7533, the ADV7535 has an offset for the CEC register map,
and it is the same value (ADV7533_REG_CEC_OFFSET = 0x70).

Rather than testing for numerous chip types in the offset calculations
throughout the driver, just compute it during driver probe and put it in
the private adv7511 data structure.

Signed-off-by: Alvin Å ipraga 
Reviewed-by: Robert Foss 
---
 drivers/gpu/drm/bridge/adv7511/adv7511.h |  1 +
 drivers/gpu/drm/bridge/adv7511/adv7511_cec.c | 18 ++
 drivers/gpu/drm/bridge/adv7511/adv7511_drv.c |  5 +++--
 3 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511.h 
b/drivers/gpu/drm/bridge/adv7511/adv7511.h
index 6a882891d91c..da6d8ee2cd84 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511.h
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511.h
@@ -335,6 +335,7 @@ struct adv7511 {
 
struct regmap *regmap;
struct regmap *regmap_cec;
+   unsigned int reg_cec_offset;
enum drm_connector_status status;
bool powered;
 
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c 
b/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
index 28d9becc939c..1f619389e201 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
@@ -21,8 +21,7 @@
 
 static void adv_cec_tx_raw_status(struct adv7511 *adv7511, u8 tx_raw_status)
 {
-   unsigned int offset = adv7511->type == ADV7533 ?
-   ADV7533_REG_CEC_OFFSET : 0;
+   unsigned int offset = adv7511->reg_cec_offset;
unsigned int val;
 
if (regmap_read(adv7511->regmap_cec,
@@ -73,8 +72,7 @@ static void adv_cec_tx_raw_status(struct adv7511 *adv7511, u8 
tx_raw_status)
 
 void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1)
 {
-   unsigned int offset = adv7511->type == ADV7533 ?
-   ADV7533_REG_CEC_OFFSET : 0;
+   unsigned int offset = adv7511->reg_cec_offset;
const u32 irq_tx_mask = ADV7511_INT1_CEC_TX_READY |
ADV7511_INT1_CEC_TX_ARBIT_LOST |
ADV7511_INT1_CEC_TX_RETRY_TIMEOUT;
@@ -118,8 +116,7 @@ void adv7511_cec_irq_process(struct adv7511 *adv7511, 
unsigned int irq1)
 static int adv7511_cec_adap_enable(struct cec_adapter *adap, bool enable)
 {
struct adv7511 *adv7511 = cec_get_drvdata(adap);
-   unsigned int offset = adv7511->type == ADV7533 ?
-   ADV7533_REG_CEC_OFFSET : 0;
+   unsigned int offset = adv7511->reg_cec_offset;
 
if (adv7511->i2c_cec == NULL)
return -EIO;
@@ -165,8 +162,7 @@ static int adv7511_cec_adap_enable(struct cec_adapter 
*adap, bool enable)
 static int adv7511_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
 {
struct adv7511 *adv7511 = cec_get_drvdata(adap);
-   unsigned int offset = adv7511->type == ADV7533 ?
-   ADV7533_REG_CEC_OFFSET : 0;
+   unsigned int offset = adv7511->reg_cec_offset;
unsigned int i, free_idx = ADV7511_MAX_ADDRS;
 
if (!adv7511->cec_enabled_adap)
@@ -235,8 +231,7 @@ static int adv7511_cec_adap_transmit(struct cec_adapter 
*adap, u8 attempts,
 u32 signal_free_time, struct cec_msg *msg)
 {
struct adv7511 *adv7511 = cec_get_drvdata(adap);
-   unsigned int offset = adv7511->type == ADV7533 ?
-   ADV7533_REG_CEC_OFFSET : 0;
+   unsigned int offset = adv7511->reg_cec_offset;
u8 len = msg->len;
unsigned int i;
 
@@ -289,8 +284,7 @@ static int adv7511_cec_parse_dt(struct device *dev, struct 
adv7511 *adv7511)
 
 int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511)
 {
-   unsigned int offset = adv7511->type == ADV7533 ?
-   ADV7533_REG_CEC_OFFSET : 0;
+   unsigned int offset = adv7511->reg_cec_offset;
int ret = adv7511_cec_parse_dt(dev, adv7511);
 
if (ret)
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c 
b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
index b3f10c54e064..556ba1b447ba 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
@@ -1027,8 +1027,7 @@ static bool adv7511_cec_register_volatile(struct device 
*dev, unsigned int reg)
struct i2c_client *i2c = to_i2c_client(dev);
struct adv7511 *adv7511 = i2c_get_clientdata(i2c);
 
-   if (adv7511->type == ADV7533 || adv7511->type == ADV7535)
-   reg -= ADV7533_REG_CEC_OFFSET;
+   reg -= adv7511->reg_cec_offset;
 
switch (reg) {
case ADV7511_REG_CEC_RX_FRAME_HDR:
@@ -1073,6 +1072,8 @@ static int adv7511_init_cec_regmap(struct adv7511 *adv)
ret = adv7533_patch_cec_registers(adv);
if (ret)
goto err;
+
+   

[PATCH v2 0/2] drm: bridge: adv7511: CEC support for ADV7535

2022-04-24 Thread Alvin Å ipraga
From: Alvin Å ipraga 

Changes:

v1->v2:
  - add Robert's r-b
  - fix up 'case XXX...YYY+14' statements to read nicer in the 2nd patch


We have an ADV7535 which is nominally supported by this driver. These
two patches fix up the driver to get CEC working too.

The first adds the basic support by correcting some register offsets.

The second addresses an issue we saw with CEC RX on the ADV7535. It
hasn't been tested with the other chips (e.g. ADV7533), although it
should be compatible. I'm sending it against drm-misc-next because the
issue wasn't reported for other chips, and ADV7535 didn't have CEC
support before. But feel free to take it into -fixes instead.


Alvin Å ipraga (2):
  drm: bridge: adv7511: enable CEC support for ADV7535
  drm: bridge: adv7511: use non-legacy mode for CEC RX

 drivers/gpu/drm/bridge/adv7511/adv7511.h |  27 -
 drivers/gpu/drm/bridge/adv7511/adv7511_cec.c | 116 +--
 drivers/gpu/drm/bridge/adv7511/adv7511_drv.c |  19 ++-
 3 files changed, 116 insertions(+), 46 deletions(-)

-- 
2.35.1



[PATCH v2 2/2] drm: bridge: adv7511: use non-legacy mode for CEC RX

2022-04-24 Thread Alvin Å ipraga
From: Alvin Å ipraga 

The ADV7511 family of bridges supports two modes for CEC RX: legacy and
non-legacy mode. The only difference is whether the chip uses a single
CEC RX buffer, or uses all three available RX buffers. Currently the
adv7511 driver uses legacy mode.

While debugging a stall in CEC RX on an ADV7535, we reached out to
Analog Devices, who suggested to use non-legacy mode instead.  According
to the programming guide for the ADV7511 [1], and the register control
manual of the ADV7535 [2], this is the default behaviour on reset. As
previously stated, the adv7511 driver currently overrides this to legacy
mode.

This patch updates the adv7511 driver to instead use non-legacy mode
with all three CEC RX buffers. As a result of this change, we no longer
experience any stalling of CEC RX with the ADV7535. It is not known why
non-legacy mode solves this particular issue, but besides this, no
functional change is to be expected by this patch. Please note that this
has only been tested on an ADV7535.

What follows is a brief description of the non-legacy mode interrupt
handling behaviour. The programming guide in [1] gives a more detailed
explanation.

With three RX buffers, the interrupt handler checks the CEC_RX_STATUS
register (renamed from CEC_RX_ENABLE in this patch), which contains
2-bit psuedo-timestamps for each of the RX buffers. The RX timestamps
for each buffer represent the time of arrival for the CEC frame held in
a given buffer, with lower timestamp values indicating chronologically
older frames. A special value of 0 indicates that the given RX buffer
is inactive and should be skipped. The interrupt handler parses these
timestamps and then reads the active RX buffers in the prescribed order
using the same logic as before. Changes have been made to ensure that
the correct RX buffer is cleared after processing. This clearing
procesure also sets the timestamp of the given RX buffer to 0 to mark it
as inactive.

[1] 
https://www.analog.com/media/en/technical-documentation/user-guides/ADV7511_Programming_Guide.pdf
cf. CEC Map, register 0x4A, bit 3, default value 1:
0 = Use only buffer 0 to store CEC frames (Legacy mode)
1 = Use all 3 buffers to stores the CEC frames (Non-legacy mode)

[2] The ADV7535 register control manual is under NDA, but trust me when
I say that non-legacy CEC RX mode is the default here too. Here the
register is offset by 0x70 and has an address of 0xBA in the DSI_CEC
regiser map.

Signed-off-by: Alvin Å ipraga 
Reviewed-by: Robert Foss 
---
 drivers/gpu/drm/bridge/adv7511/adv7511.h | 26 +-
 drivers/gpu/drm/bridge/adv7511/adv7511_cec.c | 98 +++-
 drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 14 ++-
 3 files changed, 106 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511.h 
b/drivers/gpu/drm/bridge/adv7511/adv7511.h
index da6d8ee2cd84..9e3bb8a8ee40 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511.h
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511.h
@@ -209,10 +209,16 @@
 #define ADV7511_REG_CEC_TX_ENABLE  0x11
 #define ADV7511_REG_CEC_TX_RETRY   0x12
 #define ADV7511_REG_CEC_TX_LOW_DRV_CNT 0x14
-#define ADV7511_REG_CEC_RX_FRAME_HDR   0x15
-#define ADV7511_REG_CEC_RX_FRAME_DATA0 0x16
-#define ADV7511_REG_CEC_RX_FRAME_LEN   0x25
-#define ADV7511_REG_CEC_RX_ENABLE  0x26
+#define ADV7511_REG_CEC_RX1_FRAME_HDR  0x15
+#define ADV7511_REG_CEC_RX1_FRAME_DATA00x16
+#define ADV7511_REG_CEC_RX1_FRAME_LEN  0x25
+#define ADV7511_REG_CEC_RX_STATUS  0x26
+#define ADV7511_REG_CEC_RX2_FRAME_HDR  0x27
+#define ADV7511_REG_CEC_RX2_FRAME_DATA00x28
+#define ADV7511_REG_CEC_RX2_FRAME_LEN  0x37
+#define ADV7511_REG_CEC_RX3_FRAME_HDR  0x38
+#define ADV7511_REG_CEC_RX3_FRAME_DATA00x39
+#define ADV7511_REG_CEC_RX3_FRAME_LEN  0x48
 #define ADV7511_REG_CEC_RX_BUFFERS 0x4a
 #define ADV7511_REG_CEC_LOG_ADDR_MASK  0x4b
 #define ADV7511_REG_CEC_LOG_ADDR_0_1   0x4c
@@ -220,6 +226,18 @@
 #define ADV7511_REG_CEC_CLK_DIV0x4e
 #define ADV7511_REG_CEC_SOFT_RESET 0x50
 
+static const u8 ADV7511_REG_CEC_RX_FRAME_HDR[] = {
+   ADV7511_REG_CEC_RX1_FRAME_HDR,
+   ADV7511_REG_CEC_RX2_FRAME_HDR,
+   ADV7511_REG_CEC_RX3_FRAME_HDR,
+};
+
+static const u8 ADV7511_REG_CEC_RX_FRAME_LEN[] = {
+   ADV7511_REG_CEC_RX1_FRAME_LEN,
+   ADV7511_REG_CEC_RX2_FRAME_LEN,
+   ADV7511_REG_CEC_RX3_FRAME_LEN,
+};
+
 #define ADV7533_REG_CEC_OFFSET 0x70
 
 enum adv7511_input_clock {
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c 
b/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
index 1f619389e201..399f625a50c8 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
@@ -17,7 +17,8 @@
 
 #define ADV7511_INT1_CEC_MASK \
(ADV7511_INT1_CEC_TX_READY | ADV7511_INT1_CEC_TX_ARBIT_LOST | \
-ADV7511_INT1_CEC_TX_RETRY_TIMEOUT | ADV7511_INT1_CEC_RX_READY1)
+ADV7511_INT1_CEC_TX_RETRY_TIMEOUT | 

[PATCH v3 13/14] drm/sun4i: Add support for D1 TCONs

2022-04-24 Thread Samuel Holland
D1 has a TCON TOP, so its quirks are similar to those for the R40 TCONs.
While there are some register changes, the part of the TCON TV supported
by the driver matches the R40 quirks, so that quirks structure can be
reused. D1 has the first supported TCON LCD with a TCON TOP, so the TCON
LCD needs a new quirks structure.

D1's TCON LCD hardware supports LVDS; in fact it provides dual-link LVDS
from a single TCON. However, it comes with a brand new LVDS PHY. Since
this PHY has not been tested, leave out LVDS driver support for now.

Signed-off-by: Samuel Holland 
---

(no changes since v1)

 drivers/gpu/drm/sun4i/sun4i_tcon.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c 
b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 88db2d2a9336..2ee158aaeb9e 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -1542,6 +1542,12 @@ static const struct sun4i_tcon_quirks 
sun9i_a80_tcon_tv_quirks = {
.needs_edp_reset = true,
 };
 
+static const struct sun4i_tcon_quirks sun20i_d1_lcd_quirks = {
+   .has_channel_0  = true,
+   .dclk_min_div   = 1,
+   .set_mux= sun8i_r40_tcon_tv_set_mux,
+};
+
 /* sun4i_drv uses this list to check if a device node is a TCON */
 const struct of_device_id sun4i_tcon_of_table[] = {
{ .compatible = "allwinner,sun4i-a10-tcon", .data = _a10_quirks },
@@ -1559,6 +1565,8 @@ const struct of_device_id sun4i_tcon_of_table[] = {
{ .compatible = "allwinner,sun8i-v3s-tcon", .data = _v3s_quirks },
{ .compatible = "allwinner,sun9i-a80-tcon-lcd", .data = 
_a80_tcon_lcd_quirks },
{ .compatible = "allwinner,sun9i-a80-tcon-tv", .data = 
_a80_tcon_tv_quirks },
+   { .compatible = "allwinner,sun20i-d1-tcon-lcd", .data = 
_d1_lcd_quirks },
+   { .compatible = "allwinner,sun20i-d1-tcon-tv", .data = 
_r40_tv_quirks },
{ }
 };
 MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table);
-- 
2.35.1



[PATCH v3 14/14] drm/sun4i: Add compatible for D1 display engine

2022-04-24 Thread Samuel Holland
Now that the various blocks in the D1 display engine pipeline are
supported, we can enable the overall engine.

Acked-by: Jernej Skrabec 
Signed-off-by: Samuel Holland 
---

(no changes since v1)

 drivers/gpu/drm/sun4i/sun4i_drv.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c 
b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 6a9ba8a77c77..275f7e4a03ae 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -418,6 +418,7 @@ static const struct of_device_id sun4i_drv_of_table[] = {
{ .compatible = "allwinner,sun8i-r40-display-engine" },
{ .compatible = "allwinner,sun8i-v3s-display-engine" },
{ .compatible = "allwinner,sun9i-a80-display-engine" },
+   { .compatible = "allwinner,sun20i-d1-display-engine" },
{ .compatible = "allwinner,sun50i-a64-display-engine" },
{ .compatible = "allwinner,sun50i-h6-display-engine" },
{ }
-- 
2.35.1



[PATCH v3 11/14] drm/sun4i: Add support for D1 mixers

2022-04-24 Thread Samuel Holland
D1 has a display engine with the usual pair of mixers, albeit with
relatively few layers. In fact, D1 appears to be the first SoC to have
a mixer without any UI layers. Add support for these new variants.

Acked-by: Jernej Skrabec 
Signed-off-by: Samuel Holland 
---

(no changes since v1)

 drivers/gpu/drm/sun4i/sun8i_mixer.c | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c 
b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 4ce593c99807..875a1156c04e 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -615,6 +615,24 @@ static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
.mod_rate = 15000,
 };
 
+static const struct sun8i_mixer_cfg sun20i_d1_mixer0_cfg = {
+   .ccsc   = CCSC_D1_MIXER0_LAYOUT,
+   .mod_rate   = 29700,
+   .scaler_mask= 0x3,
+   .scanline_yuv   = 2048,
+   .ui_num = 1,
+   .vi_num = 1,
+};
+
+static const struct sun8i_mixer_cfg sun20i_d1_mixer1_cfg = {
+   .ccsc   = CCSC_MIXER1_LAYOUT,
+   .mod_rate   = 29700,
+   .scaler_mask= 0x1,
+   .scanline_yuv   = 1024,
+   .ui_num = 0,
+   .vi_num = 1,
+};
+
 static const struct sun8i_mixer_cfg sun50i_a64_mixer0_cfg = {
.ccsc   = CCSC_MIXER0_LAYOUT,
.mod_rate   = 29700,
@@ -668,6 +686,14 @@ static const struct of_device_id sun8i_mixer_of_table[] = {
.compatible = "allwinner,sun8i-v3s-de2-mixer",
.data = _v3s_mixer_cfg,
},
+   {
+   .compatible = "allwinner,sun20i-d1-de2-mixer-0",
+   .data = _d1_mixer0_cfg,
+   },
+   {
+   .compatible = "allwinner,sun20i-d1-de2-mixer-1",
+   .data = _d1_mixer1_cfg,
+   },
{
.compatible = "allwinner,sun50i-a64-de2-mixer-0",
.data = _a64_mixer0_cfg,
-- 
2.35.1



[PATCH v3 10/14] drm/sun4i: csc: Add support for the new MMIO layout

2022-04-24 Thread Samuel Holland
D1 changes the MMIO offsets for the CSC blocks in the first mixer. The
mixers' ccsc property is used as an index into the ccsc_base array. Use
an enumeration to describe this index, and add the new set of offsets.

Signed-off-by: Samuel Holland 
---

(no changes since v2)

Changes in v2:
 - Use an enumeration for the ccsc value.

 drivers/gpu/drm/sun4i/sun8i_csc.c   |  7 ---
 drivers/gpu/drm/sun4i/sun8i_csc.h   |  1 +
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 18 +-
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 14 ++
 4 files changed, 24 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c 
b/drivers/gpu/drm/sun4i/sun8i_csc.c
index 9bd62de0c288..58480d8e4f70 100644
--- a/drivers/gpu/drm/sun4i/sun8i_csc.c
+++ b/drivers/gpu/drm/sun4i/sun8i_csc.c
@@ -8,9 +8,10 @@
 #include "sun8i_csc.h"
 #include "sun8i_mixer.h"
 
-static const u32 ccsc_base[2][2] = {
-   {CCSC00_OFFSET, CCSC01_OFFSET},
-   {CCSC10_OFFSET, CCSC11_OFFSET},
+static const u32 ccsc_base[][2] = {
+   [CCSC_MIXER0_LAYOUT]= {CCSC00_OFFSET, CCSC01_OFFSET},
+   [CCSC_MIXER1_LAYOUT]= {CCSC10_OFFSET, CCSC11_OFFSET},
+   [CCSC_D1_MIXER0_LAYOUT] = {CCSC00_OFFSET, CCSC01_D1_OFFSET},
 };
 
 /*
diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.h 
b/drivers/gpu/drm/sun4i/sun8i_csc.h
index 022cafa6c06c..828b86fd0cab 100644
--- a/drivers/gpu/drm/sun4i/sun8i_csc.h
+++ b/drivers/gpu/drm/sun4i/sun8i_csc.h
@@ -13,6 +13,7 @@ struct sun8i_mixer;
 /* VI channel CSC units offsets */
 #define CCSC00_OFFSET 0xAA050
 #define CCSC01_OFFSET 0xFA050
+#define CCSC01_D1_OFFSET 0xFA000
 #define CCSC10_OFFSET 0xA
 #define CCSC11_OFFSET 0xF
 
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c 
b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 6b1711a9a71f..4ce593c99807 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -564,7 +564,7 @@ static int sun8i_mixer_remove(struct platform_device *pdev)
 }
 
 static const struct sun8i_mixer_cfg sun8i_a83t_mixer0_cfg = {
-   .ccsc   = 0,
+   .ccsc   = CCSC_MIXER0_LAYOUT,
.scaler_mask= 0xf,
.scanline_yuv   = 2048,
.ui_num = 3,
@@ -572,7 +572,7 @@ static const struct sun8i_mixer_cfg sun8i_a83t_mixer0_cfg = 
{
 };
 
 static const struct sun8i_mixer_cfg sun8i_a83t_mixer1_cfg = {
-   .ccsc   = 1,
+   .ccsc   = CCSC_MIXER1_LAYOUT,
.scaler_mask= 0x3,
.scanline_yuv   = 2048,
.ui_num = 1,
@@ -580,7 +580,7 @@ static const struct sun8i_mixer_cfg sun8i_a83t_mixer1_cfg = 
{
 };
 
 static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg = {
-   .ccsc   = 0,
+   .ccsc   = CCSC_MIXER0_LAYOUT,
.mod_rate   = 43200,
.scaler_mask= 0xf,
.scanline_yuv   = 2048,
@@ -589,7 +589,7 @@ static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg = {
 };
 
 static const struct sun8i_mixer_cfg sun8i_r40_mixer0_cfg = {
-   .ccsc   = 0,
+   .ccsc   = CCSC_MIXER0_LAYOUT,
.mod_rate   = 29700,
.scaler_mask= 0xf,
.scanline_yuv   = 2048,
@@ -598,7 +598,7 @@ static const struct sun8i_mixer_cfg sun8i_r40_mixer0_cfg = {
 };
 
 static const struct sun8i_mixer_cfg sun8i_r40_mixer1_cfg = {
-   .ccsc   = 1,
+   .ccsc   = CCSC_MIXER1_LAYOUT,
.mod_rate   = 29700,
.scaler_mask= 0x3,
.scanline_yuv   = 2048,
@@ -611,12 +611,12 @@ static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = 
{
.ui_num = 1,
.scaler_mask = 0x3,
.scanline_yuv = 2048,
-   .ccsc = 0,
+   .ccsc = CCSC_MIXER0_LAYOUT,
.mod_rate = 15000,
 };
 
 static const struct sun8i_mixer_cfg sun50i_a64_mixer0_cfg = {
-   .ccsc   = 0,
+   .ccsc   = CCSC_MIXER0_LAYOUT,
.mod_rate   = 29700,
.scaler_mask= 0xf,
.scanline_yuv   = 4096,
@@ -625,7 +625,7 @@ static const struct sun8i_mixer_cfg sun50i_a64_mixer0_cfg = 
{
 };
 
 static const struct sun8i_mixer_cfg sun50i_a64_mixer1_cfg = {
-   .ccsc   = 1,
+   .ccsc   = CCSC_MIXER1_LAYOUT,
.mod_rate   = 29700,
.scaler_mask= 0x3,
.scanline_yuv   = 2048,
@@ -634,7 +634,7 @@ static const struct sun8i_mixer_cfg sun50i_a64_mixer1_cfg = 
{
 };
 
 static const struct sun8i_mixer_cfg sun50i_h6_mixer0_cfg = {
-   .ccsc   = 0,
+   .ccsc   = CCSC_MIXER0_LAYOUT,
.is_de3 = true,
.mod_rate   = 6,
.scaler_mask= 0xf,
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h 
b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 5b3fbee18671..85c94884fb9a 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -141,6 +141,15 @@
 #define SUN50I_MIXER_CDC0_EN   0xd
 #define SUN50I_MIXER_CDC1_EN   0xd8000
 
+enum {
+  

[PATCH v3 09/14] drm/sun4i: Allow VI layers to be primary planes

2022-04-24 Thread Samuel Holland
D1's mixer 1 has no UI layers, only a single VI layer. That means the
mixer can only be used if the primary plane comes from this VI layer.
Add the code to handle this case.

Signed-off-by: Samuel Holland 
---

(no changes since v2)

Changes in v2:
 - Use Jernej's patches for mixer mode setting.

 drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c 
b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index bb7c43036dfa..f7d0b082d634 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -542,6 +542,7 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct 
drm_device *drm,
   struct sun8i_mixer *mixer,
   int index)
 {
+   enum drm_plane_type type = DRM_PLANE_TYPE_OVERLAY;
u32 supported_encodings, supported_ranges;
unsigned int plane_cnt, format_count;
struct sun8i_vi_layer *layer;
@@ -560,12 +561,15 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct 
drm_device *drm,
format_count = ARRAY_SIZE(sun8i_vi_layer_formats);
}
 
+   if (!mixer->cfg->ui_num && index == 0)
+   type = DRM_PLANE_TYPE_PRIMARY;
+
/* possible crtcs are set later */
ret = drm_universal_plane_init(drm, >plane, 0,
   _vi_layer_funcs,
   formats, format_count,
   sun8i_layer_modifiers,
-  DRM_PLANE_TYPE_OVERLAY, NULL);
+  type, NULL);
if (ret) {
dev_err(drm->dev, "Couldn't initialize layer\n");
return ERR_PTR(ret);
-- 
2.35.1



[PATCH v3 12/14] drm/sun4i: Add support for D1 TCON TOP

2022-04-24 Thread Samuel Holland
D1 has a TCON TOP with TCON TV0 and DSI, but no TCON TV1. This puts the
DSI clock name at index 1 in clock-output-names. Support this by only
incrementing the index for clocks that are actually supported.

Signed-off-by: Samuel Holland 
---

(no changes since v1)

 drivers/gpu/drm/sun4i/sun8i_tcon_top.c | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c 
b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
index 1b9b8b48f4a7..da97682b6835 100644
--- a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
+++ b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
@@ -189,22 +189,23 @@ static int sun8i_tcon_top_bind(struct device *dev, struct 
device *master,
 * if TVE is active on each TCON TV. If it is, mux should be switched
 * to TVE clock parent.
 */
+   i = 0;
clk_data->hws[CLK_TCON_TOP_TV0] =
sun8i_tcon_top_register_gate(dev, "tcon-tv0", regs,
 _top->reg_lock,
-TCON_TOP_TCON_TV0_GATE, 0);
+TCON_TOP_TCON_TV0_GATE, i++);
 
if (quirks->has_tcon_tv1)
clk_data->hws[CLK_TCON_TOP_TV1] =
sun8i_tcon_top_register_gate(dev, "tcon-tv1", regs,
 _top->reg_lock,
-TCON_TOP_TCON_TV1_GATE, 1);
+TCON_TOP_TCON_TV1_GATE, 
i++);
 
if (quirks->has_dsi)
clk_data->hws[CLK_TCON_TOP_DSI] =
sun8i_tcon_top_register_gate(dev, "dsi", regs,
 _top->reg_lock,
-TCON_TOP_TCON_DSI_GATE, 2);
+TCON_TOP_TCON_DSI_GATE, 
i++);
 
for (i = 0; i < CLK_NUM; i++)
if (IS_ERR(clk_data->hws[i])) {
@@ -272,6 +273,10 @@ static const struct sun8i_tcon_top_quirks 
sun8i_r40_tcon_top_quirks = {
.has_dsi= true,
 };
 
+static const struct sun8i_tcon_top_quirks sun20i_d1_tcon_top_quirks = {
+   .has_dsi= true,
+};
+
 static const struct sun8i_tcon_top_quirks sun50i_h6_tcon_top_quirks = {
/* Nothing special */
 };
@@ -282,6 +287,10 @@ const struct of_device_id sun8i_tcon_top_of_table[] = {
.compatible = "allwinner,sun8i-r40-tcon-top",
.data = _r40_tcon_top_quirks
},
+   {
+   .compatible = "allwinner,sun20i-d1-tcon-top",
+   .data = _d1_tcon_top_quirks
+   },
{
.compatible = "allwinner,sun50i-h6-tcon-top",
.data = _h6_tcon_top_quirks
-- 
2.35.1



[PATCH v3 07/14] sun4i/drm: backend: use mode_set engine callback

2022-04-24 Thread Samuel Holland
From: Jernej Skrabec 

Newly introduced mode_set callback in engine structure is a much better
place for setting backend output size and interlace mode for following
reasons:
1. Aforementioned properties change only when mode changes, so it's
   enough to be set only once per mode set. Currently it's done whenever
   properties of primary plane are changed.
2. It's assumed that primary plane will always cover whole screen. While
   this is true most of the time, it's not always. Planes are universal.
   There is no reason to add artificial limitation to primary plane.

Signed-off-by: Jernej Skrabec 
[Samuel: drop unused 'interlaced' variable]
Signed-off-by: Samuel Holland 
---

(no changes since v2)

Changes in v2:
 - Use Jernej's patches for mixer mode setting.

 drivers/gpu/drm/sun4i/sun4i_backend.c | 40 +--
 1 file changed, 20 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c 
b/drivers/gpu/drm/sun4i/sun4i_backend.c
index f52ff4e6c662..decd95ad519d 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -172,14 +172,6 @@ int sun4i_backend_update_layer_coord(struct sun4i_backend 
*backend,
 
DRM_DEBUG_DRIVER("Updating layer %d\n", layer);
 
-   if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
-   DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: 
%u\n",
-state->crtc_w, state->crtc_h);
-   regmap_write(backend->engine.regs, SUN4I_BACKEND_DISSIZE_REG,
-SUN4I_BACKEND_DISSIZE(state->crtc_w,
-  state->crtc_h));
-   }
-
/* Set height and width */
DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n",
 state->crtc_w, state->crtc_h);
@@ -259,7 +251,6 @@ int sun4i_backend_update_layer_formats(struct sun4i_backend 
*backend,
 {
struct drm_plane_state *state = plane->state;
struct drm_framebuffer *fb = state->fb;
-   bool interlaced = false;
u32 val;
int ret;
 
@@ -267,17 +258,6 @@ int sun4i_backend_update_layer_formats(struct 
sun4i_backend *backend,
regmap_update_bits(backend->engine.regs, 
SUN4I_BACKEND_ATTCTL_REG0(layer),
   SUN4I_BACKEND_ATTCTL_REG0_LAY_YUVEN, 0);
 
-   if (plane->state->crtc)
-   interlaced = plane->state->crtc->state->adjusted_mode.flags
-   & DRM_MODE_FLAG_INTERLACE;
-
-   regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_MODCTL_REG,
-  SUN4I_BACKEND_MODCTL_ITLMOD_EN,
-  interlaced ? SUN4I_BACKEND_MODCTL_ITLMOD_EN : 0);
-
-   DRM_DEBUG_DRIVER("Switching display backend interlaced mode %s\n",
-interlaced ? "on" : "off");
-
val = SUN4I_BACKEND_ATTCTL_REG0_LAY_GLBALPHA(state->alpha >> 8);
if (state->alpha != DRM_BLEND_ALPHA_OPAQUE)
val |= SUN4I_BACKEND_ATTCTL_REG0_LAY_GLBALPHA_EN;
@@ -654,6 +634,25 @@ static void sun4i_backend_vblank_quirk(struct sunxi_engine 
*engine)
spin_unlock(>frontend_lock);
 };
 
+static void sun4i_backend_mode_set(struct sunxi_engine *engine,
+  const struct drm_display_mode *mode)
+{
+   bool interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
+
+   DRM_DEBUG_DRIVER("Updating global size W: %u H: %u\n",
+mode->hdisplay, mode->vdisplay);
+
+   regmap_write(engine->regs, SUN4I_BACKEND_DISSIZE_REG,
+SUN4I_BACKEND_DISSIZE(mode->hdisplay, mode->vdisplay));
+
+   regmap_update_bits(engine->regs, SUN4I_BACKEND_MODCTL_REG,
+  SUN4I_BACKEND_MODCTL_ITLMOD_EN,
+  interlaced ? SUN4I_BACKEND_MODCTL_ITLMOD_EN : 0);
+
+   DRM_DEBUG_DRIVER("Switching display backend interlaced mode %s\n",
+interlaced ? "on" : "off");
+}
+
 static int sun4i_backend_init_sat(struct device *dev) {
struct sun4i_backend *backend = dev_get_drvdata(dev);
int ret;
@@ -765,6 +764,7 @@ static const struct sunxi_engine_ops 
sun4i_backend_engine_ops = {
.apply_color_correction = sun4i_backend_apply_color_correction,
.disable_color_correction   = 
sun4i_backend_disable_color_correction,
.vblank_quirk   = sun4i_backend_vblank_quirk,
+   .mode_set   = sun4i_backend_mode_set,
 };
 
 static const struct regmap_config sun4i_backend_regmap_config = {
-- 
2.35.1



[PATCH v3 05/14] drm/sun4i: Allow building the driver on RISC-V

2022-04-24 Thread Samuel Holland
Allwinner D1 is a RISC-V SoC which contains a DE 2.0 engine. Let's
remove the dependency on a specific CPU architecture, so the driver can
be built wherever ARCH_SUNXI is selected.

Acked-by: Jernej Skrabec 
Signed-off-by: Samuel Holland 
---

(no changes since v1)

 drivers/gpu/drm/sun4i/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index befc5a80222d..3a43c436c74a 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 config DRM_SUN4I
tristate "DRM Support for Allwinner A10 Display Engine"
-   depends on DRM && (ARM || ARM64) && COMMON_CLK
+   depends on DRM && COMMON_CLK
depends on ARCH_SUNXI || COMPILE_TEST
select DRM_GEM_CMA_HELPER
select DRM_KMS_HELPER
-- 
2.35.1



[PATCH v3 08/14] sun4i/drm: sun8i: use mode_set engine callback

2022-04-24 Thread Samuel Holland
From: Jernej Skrabec 

Newly introduced mode_set callback in engine structure is a much better
place for setting mixer output size and interlace mode for the following
reasons:
1. Aforementioned properties change only when mode changes, so it's
   enough to be set only once per mode set. Currently it's done whenever
   properties of primary plane are changed.
2. It's assumed that primary plane will always cover whole screen. While
   this is true most of the time, it's not always. DE2/3 planes are
   universal and mostly equal in functionality. There is no reason to
   add artificial limitation to primary planes.
3. The current code only works for UI layers, but some mixers do not
   have any UI layers.

Signed-off-by: Jernej Skrabec 
[Samuel: update commit message]
Signed-off-by: Samuel Holland 
---

(no changes since v2)

Changes in v2:
 - Use Jernej's patches for mixer mode setting.

 drivers/gpu/drm/sun4i/sun8i_mixer.c| 30 ++
 drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 30 --
 2 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c 
b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index f5e8aeaa3cdf..6b1711a9a71f 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -298,9 +298,39 @@ static struct drm_plane **sun8i_layers_init(struct 
drm_device *drm,
return planes;
 }
 
+static void sun8i_mixer_mode_set(struct sunxi_engine *engine,
+const struct drm_display_mode *mode)
+{
+   struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine);
+   u32 bld_base, size, val;
+   bool interlaced;
+
+   bld_base = sun8i_blender_base(mixer);
+   interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
+   size = SUN8I_MIXER_SIZE(mode->hdisplay, mode->vdisplay);
+
+   DRM_DEBUG_DRIVER("Updating global size W: %u H: %u\n",
+mode->hdisplay, mode->vdisplay);
+
+   regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_SIZE, size);
+   regmap_write(engine->regs, SUN8I_MIXER_BLEND_OUTSIZE(bld_base), size);
+
+   if (interlaced)
+   val = SUN8I_MIXER_BLEND_OUTCTL_INTERLACED;
+   else
+   val = 0;
+
+   regmap_update_bits(engine->regs, SUN8I_MIXER_BLEND_OUTCTL(bld_base),
+  SUN8I_MIXER_BLEND_OUTCTL_INTERLACED, val);
+
+   DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n",
+interlaced ? "on" : "off");
+}
+
 static const struct sunxi_engine_ops sun8i_engine_ops = {
.commit = sun8i_mixer_commit,
.layers_init= sun8i_layers_init,
+   .mode_set   = sun8i_mixer_mode_set,
 };
 
 static const struct regmap_config sun8i_mixer_regmap_config = {
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c 
b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
index 7845c2a53a7f..4632dea2dc1e 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
@@ -120,36 +120,6 @@ static int sun8i_ui_layer_update_coord(struct sun8i_mixer 
*mixer, int channel,
insize = SUN8I_MIXER_SIZE(src_w, src_h);
outsize = SUN8I_MIXER_SIZE(dst_w, dst_h);
 
-   if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
-   bool interlaced = false;
-   u32 val;
-
-   DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: 
%u\n",
-dst_w, dst_h);
-   regmap_write(mixer->engine.regs,
-SUN8I_MIXER_GLOBAL_SIZE,
-outsize);
-   regmap_write(mixer->engine.regs,
-SUN8I_MIXER_BLEND_OUTSIZE(bld_base), outsize);
-
-   if (state->crtc)
-   interlaced = state->crtc->state->adjusted_mode.flags
-   & DRM_MODE_FLAG_INTERLACE;
-
-   if (interlaced)
-   val = SUN8I_MIXER_BLEND_OUTCTL_INTERLACED;
-   else
-   val = 0;
-
-   regmap_update_bits(mixer->engine.regs,
-  SUN8I_MIXER_BLEND_OUTCTL(bld_base),
-  SUN8I_MIXER_BLEND_OUTCTL_INTERLACED,
-  val);
-
-   DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n",
-interlaced ? "on" : "off");
-   }
-
/* Set height and width */
DRM_DEBUG_DRIVER("Layer source offset X: %d Y: %d\n",
 state->src.x1 >> 16, state->src.y1 >> 16);
-- 
2.35.1



[PATCH v3 04/14] drm/sun4i: hdmi: Use more portable I/O helpers

2022-04-24 Thread Samuel Holland
readsb/writesb are unavailable on some architectures. In preparation for
removing the Kconfig architecture dependency, switch to the equivalent
but more portable ioread/write8_rep helpers.

Reported-by: kernel test robot 
Signed-off-by: Samuel Holland 
---

(no changes since v2)

Changes in v2:
 - New patch: I/O helper portability

 drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c 
b/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c
index b66fa27fe6ea..c7d7e9fff91c 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c
@@ -56,9 +56,9 @@ static int fifo_transfer(struct sun4i_hdmi *hdmi, u8 *buf, 
int len, bool read)
return -EIO;
 
if (read)
-   readsb(hdmi->base + hdmi->variant->ddc_fifo_reg, buf, len);
+   ioread8_rep(hdmi->base + hdmi->variant->ddc_fifo_reg, buf, len);
else
-   writesb(hdmi->base + hdmi->variant->ddc_fifo_reg, buf, len);
+   iowrite8_rep(hdmi->base + hdmi->variant->ddc_fifo_reg, buf, 
len);
 
/* Clear FIFO request bit by forcing a write to that bit */
regmap_field_force_write(hdmi->field_ddc_int_status,
-- 
2.35.1



[PATCH v3 06/14] sun4i/drm: engine: Add mode_set callback

2022-04-24 Thread Samuel Holland
From: Jernej Skrabec 

This optional callback is useful for setting properties which depends
only on current mode. Such properties are width, height and interlaced
output.

These properties are currently set in update layer callback for primary
plane which is less than ideal. More about that in follow up patches,
which will migrate that code to this newly defined callback.

Signed-off-by: Jernej Skrabec 
Signed-off-by: Samuel Holland 
---

(no changes since v2)

Changes in v2:
 - Use Jernej's patches for mixer mode setting.

 drivers/gpu/drm/sun4i/sun4i_crtc.c   |  1 +
 drivers/gpu/drm/sun4i/sunxi_engine.h | 27 +++
 2 files changed, 28 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c 
b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index 45d9eb552d86..c06d7cd45388 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -146,6 +146,7 @@ static void sun4i_crtc_mode_set_nofb(struct drm_crtc *crtc)
struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
 
sun4i_tcon_mode_set(scrtc->tcon, encoder, mode);
+   sunxi_engine_mode_set(scrtc->engine, mode);
 }
 
 static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = {
diff --git a/drivers/gpu/drm/sun4i/sunxi_engine.h 
b/drivers/gpu/drm/sun4i/sunxi_engine.h
index 548710a936d5..ec8cf9b2bda4 100644
--- a/drivers/gpu/drm/sun4i/sunxi_engine.h
+++ b/drivers/gpu/drm/sun4i/sunxi_engine.h
@@ -9,6 +9,7 @@
 struct drm_plane;
 struct drm_device;
 struct drm_crtc_state;
+struct drm_display_mode;
 
 struct sunxi_engine;
 
@@ -108,6 +109,17 @@ struct sunxi_engine_ops {
 * This function is optional.
 */
void (*vblank_quirk)(struct sunxi_engine *engine);
+
+   /**
+* @mode_set
+*
+* This callback is used to set mode related parameters
+* like interlacing, screen size, etc. once per mode set.
+*
+* This function is optional.
+*/
+   void (*mode_set)(struct sunxi_engine *engine,
+const struct drm_display_mode *mode);
 };
 
 /**
@@ -181,4 +193,19 @@ sunxi_engine_disable_color_correction(struct sunxi_engine 
*engine)
if (engine->ops && engine->ops->disable_color_correction)
engine->ops->disable_color_correction(engine);
 }
+
+/**
+ * sunxi_engine_mode_set - Inform engine of a new mode
+ * @engine:pointer to the engine
+ * @mode:  new mode
+ *
+ * Engine can use this functionality to set specifics once per mode change.
+ */
+static inline void
+sunxi_engine_mode_set(struct sunxi_engine *engine,
+ const struct drm_display_mode *mode)
+{
+   if (engine->ops && engine->ops->mode_set)
+   engine->ops->mode_set(engine, mode);
+}
 #endif /* _SUNXI_ENGINE_H_ */
-- 
2.35.1



[PATCH v3 01/14] dt-bindings: display: Separate clock item lists by compatible

2022-04-24 Thread Samuel Holland
So far, the binding and driver have relied on the fact that the H6
clocks are both a prefix and a subset of the R40 clocks. This allows
them to share the clocks/clock-names items and the clock-output-names
order between the hardware variants.

However, the D1 hardware has TCON TV0 and DSI, but no TCON TV1. This
cannot be supported by the existing scheme because it puts a gap in the
middle of the item lists. To prepare for adding D1 support, use separate
lists for variants with different combinations of clocks.

Reviewed-by: Krzysztof Kozlowski 
Signed-off-by: Samuel Holland 
---

Changes in v3:
 - Drop redundant minItems and maxItems

 .../display/allwinner,sun8i-r40-tcon-top.yaml | 105 ++
 1 file changed, 61 insertions(+), 44 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/display/allwinner,sun8i-r40-tcon-top.yaml 
b/Documentation/devicetree/bindings/display/allwinner,sun8i-r40-tcon-top.yaml
index 61ef7b337218..449fa99aa51b 100644
--- 
a/Documentation/devicetree/bindings/display/allwinner,sun8i-r40-tcon-top.yaml
+++ 
b/Documentation/devicetree/bindings/display/allwinner,sun8i-r40-tcon-top.yaml
@@ -48,31 +48,15 @@ properties:
 
   clocks:
 minItems: 2
-items:
-  - description: The TCON TOP interface clock
-  - description: The TCON TOP TV0 clock
-  - description: The TCON TOP TVE0 clock
-  - description: The TCON TOP TV1 clock
-  - description: The TCON TOP TVE1 clock
-  - description: The TCON TOP MIPI DSI clock
+maxItems: 6
 
   clock-names:
 minItems: 2
-items:
-  - const: bus
-  - const: tcon-tv0
-  - const: tve0
-  - const: tcon-tv1
-  - const: tve1
-  - const: dsi
+maxItems: 6
 
   clock-output-names:
 minItems: 1
 maxItems: 3
-description: >
-  The first item is the name of the clock created for the TV0
-  channel, the second item is the name of the TCON TV1 channel
-  clock and the third one is the name of the DSI channel clock.
 
   resets:
 maxItems: 1
@@ -129,32 +113,65 @@ required:
 
 additionalProperties: false
 
-if:
-  properties:
-compatible:
-  contains:
-const: allwinner,sun50i-h6-tcon-top
-
-then:
-  properties:
-clocks:
-  maxItems: 2
-
-clock-output-names:
-  maxItems: 1
-
-else:
-  properties:
-clocks:
-  minItems: 6
-
-clock-output-names:
-  minItems: 3
-
-ports:
-  required:
-- port@2
-- port@3
+allOf:
+  - if:
+  properties:
+compatible:
+  contains:
+const: allwinner,sun8i-r40-tcon-top
+
+then:
+  properties:
+clocks:
+  items:
+- description: The TCON TOP interface clock
+- description: The TCON TOP TV0 clock
+- description: The TCON TOP TVE0 clock
+- description: The TCON TOP TV1 clock
+- description: The TCON TOP TVE1 clock
+- description: The TCON TOP MIPI DSI clock
+
+clock-names:
+  items:
+- const: bus
+- const: tcon-tv0
+- const: tve0
+- const: tcon-tv1
+- const: tve1
+- const: dsi
+
+clock-output-names:
+  items:
+- description: TCON TV0 output clock name
+- description: TCON TV1 output clock name
+- description: DSI output clock name
+
+ports:
+  required:
+- port@2
+- port@3
+
+  - if:
+  properties:
+compatible:
+  contains:
+const: allwinner,sun50i-h6-tcon-top
+
+then:
+  properties:
+clocks:
+  items:
+- description: The TCON TOP interface clock
+- description: The TCON TOP TV0 clock
+
+clock-names:
+  items:
+- const: bus
+- const: tcon-tv0
+
+clock-output-names:
+  items:
+- description: TCON TV0 output clock name
 
 examples:
   - |
-- 
2.35.1



[PATCH v3 03/14] drm/sun4i: Remove obsolete references to PHYS_OFFSET

2022-04-24 Thread Samuel Holland
commit b4bdc4fbf8d0 ("soc: sunxi: Deal with the MBUS DMA offsets in a
central place") added a platform device notifier that sets the DMA
offset for all of the display engine frontend and backend devices.

The code applying the offset to DMA buffer physical addresses was then
removed from the backend driver in commit 756668ba682e ("drm/sun4i:
backend: Remove the MBUS quirks"), but the code subtracting PHYS_OFFSET
was left in the frontend driver.

As a result, the offset was applied twice in the frontend driver. This
likely went unnoticed because it only affects specific configurations
(scaling or certain pixel formats) where the frontend is used, on boards
with both one of these older SoCs and more than 1 GB of DRAM.

In addition, the references to PHYS_OFFSET prevent compiling the driver
on architectures where PHYS_OFFSET is not defined.

Fixes: b4bdc4fbf8d0 ("soc: sunxi: Deal with the MBUS DMA offsets in a central 
place")
Reviewed-by: Jernej Skrabec 
Signed-off-by: Samuel Holland 
---

(no changes since v1)

 drivers/gpu/drm/sun4i/sun4i_frontend.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c 
b/drivers/gpu/drm/sun4i/sun4i_frontend.c
index 56ae38389db0..462fae73eae9 100644
--- a/drivers/gpu/drm/sun4i/sun4i_frontend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c
@@ -222,13 +222,11 @@ void sun4i_frontend_update_buffer(struct sun4i_frontend 
*frontend,
 
/* Set the physical address of the buffer in memory */
paddr = drm_fb_cma_get_gem_addr(fb, state, 0);
-   paddr -= PHYS_OFFSET;
DRM_DEBUG_DRIVER("Setting buffer #0 address to %pad\n", );
regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR0_REG, paddr);
 
if (fb->format->num_planes > 1) {
paddr = drm_fb_cma_get_gem_addr(fb, state, swap ? 2 : 1);
-   paddr -= PHYS_OFFSET;
DRM_DEBUG_DRIVER("Setting buffer #1 address to %pad\n", );
regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR1_REG,
 paddr);
@@ -236,7 +234,6 @@ void sun4i_frontend_update_buffer(struct sun4i_frontend 
*frontend,
 
if (fb->format->num_planes > 2) {
paddr = drm_fb_cma_get_gem_addr(fb, state, swap ? 1 : 2);
-   paddr -= PHYS_OFFSET;
DRM_DEBUG_DRIVER("Setting buffer #2 address to %pad\n", );
regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR2_REG,
 paddr);
-- 
2.35.1



[PATCH v3 02/14] dt-bindings: display: Add D1 display engine compatibles

2022-04-24 Thread Samuel Holland
Allwinner D1 contains a display engine 2.0. It features two mixers, a
TCON TOP (with DSI and HDMI), one TCON LCD, and one TCON TV.

Reviewed-by: Krzysztof Kozlowski 
Signed-off-by: Samuel Holland 
---

Changes in v3:
 - Drop redundant minItems and maxItems

 .../allwinner,sun4i-a10-display-engine.yaml   |  1 +
 .../display/allwinner,sun4i-a10-tcon.yaml |  2 ++
 .../allwinner,sun8i-a83t-de2-mixer.yaml   |  2 ++
 .../display/allwinner,sun8i-r40-tcon-top.yaml | 28 +++
 4 files changed, 33 insertions(+)

diff --git 
a/Documentation/devicetree/bindings/display/allwinner,sun4i-a10-display-engine.yaml
 
b/Documentation/devicetree/bindings/display/allwinner,sun4i-a10-display-engine.yaml
index d4412aea7b73..c388ae5da1e4 100644
--- 
a/Documentation/devicetree/bindings/display/allwinner,sun4i-a10-display-engine.yaml
+++ 
b/Documentation/devicetree/bindings/display/allwinner,sun4i-a10-display-engine.yaml
@@ -62,6 +62,7 @@ properties:
   - allwinner,sun8i-r40-display-engine
   - allwinner,sun8i-v3s-display-engine
   - allwinner,sun9i-a80-display-engine
+  - allwinner,sun20i-d1-display-engine
   - allwinner,sun50i-a64-display-engine
   - allwinner,sun50i-h6-display-engine
 
diff --git 
a/Documentation/devicetree/bindings/display/allwinner,sun4i-a10-tcon.yaml 
b/Documentation/devicetree/bindings/display/allwinner,sun4i-a10-tcon.yaml
index 3a7d5d731712..4a92a4c7dcd7 100644
--- a/Documentation/devicetree/bindings/display/allwinner,sun4i-a10-tcon.yaml
+++ b/Documentation/devicetree/bindings/display/allwinner,sun4i-a10-tcon.yaml
@@ -33,6 +33,8 @@ properties:
   - const: allwinner,sun8i-v3s-tcon
   - const: allwinner,sun9i-a80-tcon-lcd
   - const: allwinner,sun9i-a80-tcon-tv
+  - const: allwinner,sun20i-d1-tcon-lcd
+  - const: allwinner,sun20i-d1-tcon-tv
 
   - items:
   - enum:
diff --git 
a/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml 
b/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml
index 4f91eec26de9..cb243bc58ef7 100644
--- 
a/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml
+++ 
b/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml
@@ -19,6 +19,8 @@ properties:
   - allwinner,sun8i-r40-de2-mixer-0
   - allwinner,sun8i-r40-de2-mixer-1
   - allwinner,sun8i-v3s-de2-mixer
+  - allwinner,sun20i-d1-de2-mixer-0
+  - allwinner,sun20i-d1-de2-mixer-1
   - allwinner,sun50i-a64-de2-mixer-0
   - allwinner,sun50i-a64-de2-mixer-1
   - allwinner,sun50i-h6-de3-mixer-0
diff --git 
a/Documentation/devicetree/bindings/display/allwinner,sun8i-r40-tcon-top.yaml 
b/Documentation/devicetree/bindings/display/allwinner,sun8i-r40-tcon-top.yaml
index 449fa99aa51b..845e226d7aff 100644
--- 
a/Documentation/devicetree/bindings/display/allwinner,sun8i-r40-tcon-top.yaml
+++ 
b/Documentation/devicetree/bindings/display/allwinner,sun8i-r40-tcon-top.yaml
@@ -41,6 +41,7 @@ properties:
   compatible:
 enum:
   - allwinner,sun8i-r40-tcon-top
+  - allwinner,sun20i-d1-tcon-top
   - allwinner,sun50i-h6-tcon-top
 
   reg:
@@ -151,6 +152,33 @@ allOf:
 - port@2
 - port@3
 
+  - if:
+  properties:
+compatible:
+  contains:
+const: allwinner,sun20i-d1-tcon-top
+
+then:
+  properties:
+clocks:
+  items:
+- description: The TCON TOP interface clock
+- description: The TCON TOP TV0 clock
+- description: The TCON TOP TVE0 clock
+- description: The TCON TOP MIPI DSI clock
+
+clock-names:
+  items:
+- const: bus
+- const: tcon-tv0
+- const: tve0
+- const: dsi
+
+clock-output-names:
+  items:
+- description: TCON TV0 output clock name
+- description: DSI output clock name
+
   - if:
   properties:
 compatible:
-- 
2.35.1



[PATCH v3 00/14] drm/sun4i: Allwinner D1 Display Engine 2.0 Support

2022-04-24 Thread Samuel Holland
This series adds binding and driver support for Display Engine 2.0
variant found in the Allwinner D1.

So far it has only been tested with HDMI. I will be sending the HDMI
support series separately, because the hardware comes with a brand new
custom HDMI PHY, which requires some refactoring to support cleanly.

This series was tested on A33, D1 and H3.

Changes in v3:
 - Drop redundant minItems and maxItems

Changes in v2:
 - New patch: I/O helper portability
 - Use Jernej's patches for mixer mode setting.
 - Use an enumeration for the ccsc value.

Jernej Skrabec (3):
  sun4i/drm: engine: Add mode_set callback
  sun4i/drm: backend: use mode_set engine callback
  sun4i/drm: sun8i: use mode_set engine callback

Samuel Holland (11):
  dt-bindings: display: Separate clock item lists by compatible
  dt-bindings: display: Add D1 display engine compatibles
  drm/sun4i: Remove obsolete references to PHYS_OFFSET
  drm/sun4i: hdmi: Use more portable I/O helpers
  drm/sun4i: Allow building the driver on RISC-V
  drm/sun4i: Allow VI layers to be primary planes
  drm/sun4i: csc: Add support for the new MMIO layout
  drm/sun4i: Add support for D1 mixers
  drm/sun4i: Add support for D1 TCON TOP
  drm/sun4i: Add support for D1 TCONs
  drm/sun4i: Add compatible for D1 display engine

 .../allwinner,sun4i-a10-display-engine.yaml   |   1 +
 .../display/allwinner,sun4i-a10-tcon.yaml |   2 +
 .../allwinner,sun8i-a83t-de2-mixer.yaml   |   2 +
 .../display/allwinner,sun8i-r40-tcon-top.yaml | 133 --
 drivers/gpu/drm/sun4i/Kconfig |   2 +-
 drivers/gpu/drm/sun4i/sun4i_backend.c |  40 +++---
 drivers/gpu/drm/sun4i/sun4i_crtc.c|   1 +
 drivers/gpu/drm/sun4i/sun4i_drv.c |   1 +
 drivers/gpu/drm/sun4i/sun4i_frontend.c|   3 -
 drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c|   4 +-
 drivers/gpu/drm/sun4i/sun4i_tcon.c|   8 ++
 drivers/gpu/drm/sun4i/sun8i_csc.c |   7 +-
 drivers/gpu/drm/sun4i/sun8i_csc.h |   1 +
 drivers/gpu/drm/sun4i/sun8i_mixer.c   |  74 --
 drivers/gpu/drm/sun4i/sun8i_mixer.h   |  14 +-
 drivers/gpu/drm/sun4i/sun8i_tcon_top.c|  15 +-
 drivers/gpu/drm/sun4i/sun8i_ui_layer.c|  30 
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c|   6 +-
 drivers/gpu/drm/sun4i/sunxi_engine.h  |  27 
 19 files changed, 251 insertions(+), 120 deletions(-)

-- 
2.35.1



RE: [PATCH v3 2/4] drm: rcar-du: Fix typo

2022-04-24 Thread Biju Das
Hi Laurent,

> Subject: Re: [PATCH v3 2/4] drm: rcar-du: Fix typo
> 
> Hello,
> 
> On Fri, Apr 22, 2022 at 09:38:00AM +, Biju Das wrote:
> > > Subject: Re: [PATCH v3 2/4] drm: rcar-du: Fix typo On Thu, Apr 21,
> > > 2022 at 6:31 PM Biju Das wrote:
> > > > Fix typo rcar_du_vsp.h->rcar_du_vsp.c
> > > >
> > > > Signed-off-by: Biju Das 
> > >
> > > Thanks for your patch!
> > >
> > > > --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
> > > > +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
> > > > @@ -1,6 +1,6 @@
> > > >  // SPDX-License-Identifier: GPL-2.0+
> > > >  /*
> > > > - * rcar_du_vsp.h  --  R-Car Display Unit VSP-Based Compositor
> > > > + * rcar_du_vsp.c  --  R-Car Display Unit VSP-Based Compositor
> > >
> > > Perhaps drop the file name completely instead?
> >
> > Currently all the R-Car DU files have file name. May be A single patch
> > to remove all off them if we are planning to do.
> >
> > Laurent, please share your thoughts on this.
> 
> Geert has a point, the file names cause issues and don't add much value.
> Would you like to send a patch to drop them all, to replace this one ? I
> can also handle it myself if you prefer.

OK, I don't have any preference. I Just noticed that issue. Feel free to post 
the patch.

Cheers,
Biju


RE: [PATCH] drm: rcar-du: Add setting to PnALPHAR register on Gen3

2022-04-24 Thread Biju Das
Hi Laurent,

Thanks for the feedback.

> Subject: Re: [PATCH] drm: rcar-du: Add setting to PnALPHAR register on
> Gen3
> 
> Hi Biju,
> 
> Thank you for the patch.
> 
> On Sat, Apr 23, 2022 at 08:37:28AM +0100, Biju Das wrote:
> > From: LUU HOAI 
> >
> > In Gen3, when Alpha blend is enabled in the PnMR register, depending
> > on the initial value of the PnALPHAR register, either channel of DU
> > might be black screen.
> > Therefore, this patch prevents the black screen by setting the
> > PnALPHAR register to all 0.
> >
> > In addition, PnALPHAR register will be released in the R-Car Gen3
> > Hardware Manual Rev 2.4 (Sep. 2021).
> >
> > Signed-off-by: LUU HOAI 
> > Signed-off-by: Biju Das 
> > ---
> > This patch is based on [1]
> > [1]
> >
> > Not sure this patches has to go with Fixes tag for stable??
> >
> > Tested the changes on RZ/G2M board
> >
> > root@hihope-rzg2m:/cip-test-scripts#  modetest -M rcar-du -w
> > 54:alpha:5 root@hihope-rzg2m:/cip-test-scripts# modetest -M rcar-du
> -s "93@90:1024x768@AR24" -d -P "54@90:400x300+200+200@XR24"
> > setting mode 1024x768-75Hz@AR24 on connectors 93, crtc 90 testing
> > 400x300@XR24 overlay plane 54
> > ---
> >  drivers/gpu/drm/rcar-du/rcar_du_plane.c | 6 ++
> >  1 file changed, 6 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> > b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> > index 5c1c7bb04f3f..aff39b9253f8 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> > @@ -510,6 +510,12 @@ static void
> > rcar_du_plane_setup_format_gen3(struct rcar_du_group *rgrp,
> >
> > rcar_du_plane_write(rgrp, index, PnDDCR4,
> > state->format->edf | PnDDCR4_CODE);
> > +
> > +   /* In Gen3, PnALPHAR register need to be set to 0
> > +* to avoid black screen issue when alpha blend is enable
> > +* on DU module
> > +*/
> 
> Comments should start with /* on a line of its own, and you can also
> reflow the text to 80 columns:

OK.

> 
>   /*
>* In Gen3, PnALPHAR register need to be set to 0 to avoid black
> screen
>* issue when alpha blend is enable on DU module.
>*/
> 
> It would however be nicer to document the exact behaviour, but the latest
> version of the documentation I have access to is rev 2.3 and it lists
> PnALPHAR as not available on Gen3.

I don't have access to rev 2.4, but I got access to 
"R-Car-Gen3_Common_OPC_Customer_Notifications_V30.1.pdf" 
where it is mentioned about this issue and solution for fix
which is inline with the patch from R-Car BSP.

"The reason is that a register is not initialized by reset.
This could lead to output wrong image data of other plane or 
wrong color set from BPOR (Background plane output register)."

> 
> Furthermore, is this really the right fix, shouldn't we instead avoid
> enabling alpha-blending in PnMR on Gen3 ?

Avoid enabling alpha-blending in PnMR on Gen3, will it help here?

Here the issue they mentioned as "register is not initialized by reset"

Cheers,
Biju

> 
> > +   rcar_du_plane_write(rgrp, index, PnALPHAR, 0x);
> >  }
> >
> >  static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
> 
> --
> Regards,
> 
> Laurent Pinchart


Re: [PATCH v3 2/4] drm: rcar-du: Fix typo

2022-04-24 Thread Laurent Pinchart
Hello,

On Fri, Apr 22, 2022 at 09:38:00AM +, Biju Das wrote:
> > Subject: Re: [PATCH v3 2/4] drm: rcar-du: Fix typo
> > On Thu, Apr 21, 2022 at 6:31 PM Biju Das wrote:
> > > Fix typo rcar_du_vsp.h->rcar_du_vsp.c
> > >
> > > Signed-off-by: Biju Das 
> > 
> > Thanks for your patch!
> > 
> > > --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
> > > +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
> > > @@ -1,6 +1,6 @@
> > >  // SPDX-License-Identifier: GPL-2.0+
> > >  /*
> > > - * rcar_du_vsp.h  --  R-Car Display Unit VSP-Based Compositor
> > > + * rcar_du_vsp.c  --  R-Car Display Unit VSP-Based Compositor
> > 
> > Perhaps drop the file name completely instead?
> 
> Currently all the R-Car DU files have file name. May be
> A single patch to remove all off them if we are planning to do.
> 
> Laurent, please share your thoughts on this.

Geert has a point, the file names cause issues and don't add much value.
Would you like to send a patch to drop them all, to replace this one ? I
can also handle it myself if you prefer.

-- 
Regards,

Laurent Pinchart


Re: [PATCH] drm: rcar-du: Add setting to PnALPHAR register on Gen3

2022-04-24 Thread Laurent Pinchart
Hi Biju,

Thank you for the patch.

On Sat, Apr 23, 2022 at 08:37:28AM +0100, Biju Das wrote:
> From: LUU HOAI 
> 
> In Gen3, when Alpha blend is enabled in the PnMR register,
> depending on the initial value of the PnALPHAR register,
> either channel of DU might be black screen.
> Therefore, this patch prevents the black screen by setting
> the PnALPHAR register to all 0.
> 
> In addition, PnALPHAR register will be released in
> the R-Car Gen3 Hardware Manual Rev 2.4 (Sep. 2021).
> 
> Signed-off-by: LUU HOAI 
> Signed-off-by: Biju Das 
> ---
> This patch is based on [1]
> [1] 
> https://github.com/renesas-rcar/linux-bsp/commit/fcb34fe338cbde0a64919430733541035f20a784
> 
> Not sure this patches has to go with Fixes tag for stable??
> 
> Tested the changes on RZ/G2M board
> 
> root@hihope-rzg2m:/cip-test-scripts#  modetest -M rcar-du -w 54:alpha:5
> root@hihope-rzg2m:/cip-test-scripts# modetest -M rcar-du -s 
> "93@90:1024x768@AR24" -d -P "54@90:400x300+200+200@XR24"
> setting mode 1024x768-75Hz@AR24 on connectors 93, crtc 90
> testing 400x300@XR24 overlay plane 54
> ---
>  drivers/gpu/drm/rcar-du/rcar_du_plane.c | 6 ++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c 
> b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> index 5c1c7bb04f3f..aff39b9253f8 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> @@ -510,6 +510,12 @@ static void rcar_du_plane_setup_format_gen3(struct 
> rcar_du_group *rgrp,
>  
>   rcar_du_plane_write(rgrp, index, PnDDCR4,
>   state->format->edf | PnDDCR4_CODE);
> +
> + /* In Gen3, PnALPHAR register need to be set to 0
> +  * to avoid black screen issue when alpha blend is enable
> +  * on DU module
> +  */

Comments should start with /* on a line of its own, and you can also
reflow the text to 80 columns:

/*
 * In Gen3, PnALPHAR register need to be set to 0 to avoid black screen
 * issue when alpha blend is enable on DU module.
 */

It would however be nicer to document the exact behaviour, but the
latest version of the documentation I have access to is rev 2.3 and it
lists PnALPHAR as not available on Gen3.

Furthermore, is this really the right fix, shouldn't we instead avoid
enabling alpha-blending in PnMR on Gen3 ?

> + rcar_du_plane_write(rgrp, index, PnALPHAR, 0x);
>  }
>  
>  static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,

-- 
Regards,

Laurent Pinchart


Re: [PATCH v2 00/48] ARM: PXA multiplatform support

2022-04-24 Thread Guenter Roeck

On 4/24/22 01:52, Arnd Bergmann wrote:

On Sun, Apr 24, 2022 at 4:09 AM Guenter Roeck  wrote:

On 4/23/22 12:55, Arnd Bergmann wrote:

On Sat, Apr 23, 2022 at 1:41 AM Guenter Roeck  wrote:

On Sat, Apr 23, 2022 at 12:04:31AM +0200, Arnd Bergmann wrote:


Odd, I can't reproduce this at all. Do you get any console output at
all for this?

Is this the plain omap1_defconfig, or something else?



No, it is my own sx1 specific configuration.

https://github.com/groeck/linux-build-test/blob/master/rootfs/arm/qemu_sx1_defconfig

I don't recall where I got it from but ...


Ok, that explains it, thanks!

I fixed all the defconfig files that come with the kernel, but for your own
ones you have to add

# CONFIG_ARCH_MULTI_V7 is not set

into the defconfig file, otherwise the multiplatform target defaults to
an ARMv7 instead of ARMv5 build. For an OMAP15xx as in the SX1,
you also need to enable CONFIG_ARCH_MULTI_V4T.

This is slightly unfortunate, but I don't see any way to avoid it, and the
modified defconfig will still work fine with older kernel trees.



Yes, that works. I changed it in my configuration.


One thing I keep having to apply myself is this snippet:

diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S
index 0bfad62ea858..87c695703580 100644
--- a/arch/arm/mm/proc-arm925.S
+++ b/arch/arm/mm/proc-arm925.S
@@ -441,7 +441,6 @@ __arm925_setup:

   #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
  mov r0, #4  @ disable write-back
on caches explicitly
-   mcr p15, 7, r0, c15, c0, 0
   #endif


it does not have CONFIG_CPU_DCACHE_WRITETHROUGH enabled.


Maybe it was disabled explicitly for the sx1_defconfig because of this
bug. I would think that this is required for actual sx1 hardware because the
option is default-enabled for ARM925T, and that CPU core is exclusively
used in OMAP15xx.



That looks like a bug in qemu. ARM925T instruction support is limited to V4T
instructions. qemu doesn't have explicit 5T support. It is either V4T
or V5.

Guenter


Re: [PATCH v4 03/20] drm: allow real encoder to be passed for drm_writeback_connector

2022-04-24 Thread Laurent Pinchart
Hi Abhinav,

Thank you for the patch.

On Fri, Apr 22, 2022 at 04:06:38PM -0700, Abhinav Kumar wrote:
> For some vendor driver implementations, display hardware can
> be shared between the encoder used for writeback and the physical
> display.
> 
> In addition resources such as clocks and interrupts can
> also be shared between writeback and the real encoder.
> 
> To accommodate such vendor drivers and hardware, allow
> real encoder to be passed for drm_writeback_connector.
> 
> For existing clients, drm_writeback_connector_init() will use
> an internal_encoder under the hood and hence no changes will
> be needed.
> 
> changes in v7:
>   - move this change before the vc4 change in the series
> to minimize the changes to vendor drivers in drm core
> changes

Why is this needed ? The drm_writeback_connector functions don't need
the drm_encoder after drm_writeback_connector_init() (or
drm_writeback_connector_init_with_encoder()) returns.

> Signed-off-by: Abhinav Kumar 
> Reviewed-by: Dmitry Baryshkov 
> ---
>  drivers/gpu/drm/drm_writeback.c | 18 --
>  drivers/gpu/drm/vc4/vc4_txp.c   |  4 ++--
>  include/drm/drm_writeback.h | 22 --
>  3 files changed, 34 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_writeback.c b/drivers/gpu/drm/drm_writeback.c
> index 92658ad..0538674 100644
> --- a/drivers/gpu/drm/drm_writeback.c
> +++ b/drivers/gpu/drm/drm_writeback.c
> @@ -180,21 +180,21 @@ int drm_writeback_connector_init(struct drm_device *dev,
>  {
>   int ret = 0;
>  
> - drm_encoder_helper_add(_connector->encoder, enc_helper_funcs);
> + drm_encoder_helper_add(_connector->internal_encoder, 
> enc_helper_funcs);
>  
> - wb_connector->encoder.possible_crtcs = possible_crtcs;
> + wb_connector->internal_encoder.possible_crtcs = possible_crtcs;
>  
> - ret = drm_encoder_init(dev, _connector->encoder,
> + ret = drm_encoder_init(dev, _connector->internal_encoder,
>  _writeback_encoder_funcs,
>  DRM_MODE_ENCODER_VIRTUAL, NULL);
>   if (ret)
>   return ret;
>  
> - ret = drm_writeback_connector_init_with_encoder(dev, wb_connector, 
> _connector->encoder,
> - con_funcs, formats, n_formats);
> + ret = drm_writeback_connector_init_with_encoder(dev, wb_connector,
> + _connector->internal_encoder, con_funcs, formats, 
> n_formats);
>  
>   if (ret)
> - drm_encoder_cleanup(_connector->encoder);
> + drm_encoder_cleanup(_connector->internal_encoder);
>  
>   return ret;
>  }
> @@ -239,6 +239,12 @@ int drm_writeback_connector_init_with_encoder(struct 
> drm_device *dev,
>   struct drm_mode_config *config = >mode_config;
>   int ret = create_writeback_properties(dev);
>  
> + /*
> +  * Assign the encoder passed to this API to the wb_connector's encoder.
> +  * For drm_writeback_connector_init(), this shall be the 
> internal_encoder
> +  */
> + wb_connector->encoder = enc;
> +
>   if (ret != 0)
>   return ret;
>  
> diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
> index 3447eb6..7e063a9 100644
> --- a/drivers/gpu/drm/vc4/vc4_txp.c
> +++ b/drivers/gpu/drm/vc4/vc4_txp.c
> @@ -159,7 +159,7 @@ struct vc4_txp {
>  
>  static inline struct vc4_txp *encoder_to_vc4_txp(struct drm_encoder *encoder)
>  {
> - return container_of(encoder, struct vc4_txp, connector.encoder);
> + return container_of(encoder, struct vc4_txp, 
> connector.internal_encoder);
>  }
>  
>  static inline struct vc4_txp *connector_to_vc4_txp(struct drm_connector 
> *conn)
> @@ -507,7 +507,7 @@ static int vc4_txp_bind(struct device *dev, struct device 
> *master, void *data)
>   if (ret)
>   return ret;
>  
> - encoder = >connector.encoder;
> + encoder = txp->connector.encoder;
>   encoder->possible_crtcs = drm_crtc_mask(crtc);
>  
>   ret = devm_request_irq(dev, irq, vc4_txp_interrupt, 0,
> diff --git a/include/drm/drm_writeback.h b/include/drm/drm_writeback.h
> index bb306fa..3fbae9d 100644
> --- a/include/drm/drm_writeback.h
> +++ b/include/drm/drm_writeback.h
> @@ -25,13 +25,31 @@ struct drm_writeback_connector {
>   struct drm_connector base;
>  
>   /**
> -  * @encoder: Internal encoder used by the connector to fulfill
> +  * @encoder: handle to drm_encoder used by the connector to fulfill
>* the DRM framework requirements. The users of the
>* @drm_writeback_connector control the behaviour of the @encoder
>* by passing the @enc_funcs parameter to drm_writeback_connector_init()
>* function.
> +  *
> +  * For some vendor drivers, the hardware resources are shared between
> +  * writeback encoder and rest of the display pipeline.
> +  * To accommodate such cases, encoder is a handle to the real encoder
> +  * hardware.
> +  *
> +

Re: [PATCH v4 02/20] drm: introduce drm_writeback_connector_init_with_encoder() API

2022-04-24 Thread Laurent Pinchart
Hi Abhinav,

Thank you for the patch.

On Fri, Apr 22, 2022 at 04:06:37PM -0700, Abhinav Kumar wrote:
> For vendors drivers which pass an already allocated and
> initialized encoder especially for cases where the encoder
> hardware is shared OR the writeback encoder shares the resources
> with the rest of the display pipeline introduce a new API,
> drm_writeback_connector_init_with_encoder() which expects
> an initialized encoder as a parameter and only sets up the
> writeback connector.
> 
> changes in v4:
>   - removed the possible_crtcs part
> 
> changes in v5:
>   - reorder this change to come before in the series
> to avoid incorrect functionality in subsequent changes
>   - continue using struct drm_encoder instead of
> struct drm_encoder * and switch it in next change
> 
> changes in v6:
>   - remove drm_writeback_connector_setup() and instead
> directly call drm_writeback_connector_init_with_encoder()
>   - fix a drm_writeback_connector typo and function doc which
> incorrectly shows that the function accepts enc_helper_funcs
>   - pass encoder as a parameter explicitly to the new API
> for better readability
> 
> changes in v7:
>   - fix the function doc slightly as suggested by Liviu
> 
> Reviewed-by: Liviu Dudau 
> Signed-off-by: Abhinav Kumar 
> Reviewed-by: Dmitry Baryshkov 
> ---
>  drivers/gpu/drm/drm_writeback.c | 72 
> +
>  include/drm/drm_writeback.h |  6 
>  2 files changed, 64 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_writeback.c b/drivers/gpu/drm/drm_writeback.c
> index 9e0b845..92658ad 100644
> --- a/drivers/gpu/drm/drm_writeback.c
> +++ b/drivers/gpu/drm/drm_writeback.c
> @@ -178,6 +178,62 @@ int drm_writeback_connector_init(struct drm_device *dev,
>const u32 *formats, int n_formats,
>u32 possible_crtcs)
>  {
> + int ret = 0;
> +
> + drm_encoder_helper_add(_connector->encoder, enc_helper_funcs);
> +
> + wb_connector->encoder.possible_crtcs = possible_crtcs;
> +
> + ret = drm_encoder_init(dev, _connector->encoder,
> +_writeback_encoder_funcs,
> +DRM_MODE_ENCODER_VIRTUAL, NULL);
> + if (ret)
> + return ret;
> +
> + ret = drm_writeback_connector_init_with_encoder(dev, wb_connector, 
> _connector->encoder,
> + con_funcs, formats, n_formats);
> +
> + if (ret)
> + drm_encoder_cleanup(_connector->encoder);
> +
> + return ret;
> +}
> +EXPORT_SYMBOL(drm_writeback_connector_init);
> +
> +/**
> + * drm_writeback_connector_init_with_encoder - Initialize a writeback 
> connector and its properties
> + * using the encoder which already assigned and initialized

That sounds a bit convoluted to me. How about

 * drm_writeback_connector_init_with_encoder - Initialize a writeback connector
 * with a custom encoder

Reviewed-by: Laurent Pinchart 

> + *
> + * @dev: DRM device
> + * @wb_connector: Writeback connector to initialize
> + * @enc: handle to the already initialized drm encoder
> + * @con_funcs: Connector funcs vtable
> + * @formats: Array of supported pixel formats for the writeback engine
> + * @n_formats: Length of the formats array
> + *
> + * This function creates the writeback-connector-specific properties if they
> + * have not been already created, initializes the connector as
> + * type DRM_MODE_CONNECTOR_WRITEBACK, and correctly initializes the property
> + * values.
> + *
> + * This function assumes that the drm_writeback_connector's encoder has 
> already been
> + * created and initialized before invoking this function.
> + *
> + * In addition, this function also assumes that callers of this API will 
> manage
> + * assigning the encoder helper functions, possible_crtcs and any other 
> encoder
> + * specific operation.
> + *
> + * Drivers should always use this function instead of drm_connector_init() to
> + * set up writeback connectors if they want to manage themselves the 
> lifetime of the
> + * associated encoder.
> + *
> + * Returns: 0 on success, or a negative error code
> + */
> +int drm_writeback_connector_init_with_encoder(struct drm_device *dev,
> + struct drm_writeback_connector *wb_connector, struct 
> drm_encoder *enc,
> + const struct drm_connector_funcs *con_funcs, const u32 *formats,
> + int n_formats)
> +{
>   struct drm_property_blob *blob;
>   struct drm_connector *connector = _connector->base;
>   struct drm_mode_config *config = >mode_config;
> @@ -191,15 +247,6 @@ int drm_writeback_connector_init(struct drm_device *dev,
>   if (IS_ERR(blob))
>   return PTR_ERR(blob);
>  
> - drm_encoder_helper_add(_connector->encoder, enc_helper_funcs);
> -
> - wb_connector->encoder.possible_crtcs = possible_crtcs;
> -
> - ret = drm_encoder_init(dev, 

Re: [PATCH v4 01/20] drm: allow passing possible_crtcs to drm_writeback_connector_init()

2022-04-24 Thread Laurent Pinchart
Hi Abhinav,

Thank you for the patch.

On Fri, Apr 22, 2022 at 04:06:36PM -0700, Abhinav Kumar wrote:
> Clients of drm_writeback_connector_init() initialize the
> possible_crtcs and then invoke the call to this API.
> 
> To simplify things, allow passing possible_crtcs as a parameter
> to drm_writeback_connector_init() and make changes to the
> other drm drivers to make them compatible with this change.
> 
> changes in v2:
>   - split the changes according to their functionality
> 
> changes in v3:
>   - allow passing possible_crtcs for existing users of
> drm_writeback_connector_init()
>   - squash the vendor changes into the same commit so
> that each patch in the series can compile individually
> 
> changes in v4:
> - keep only changes related to possible_crtcs
>   - add line breaks after ARRAY_SIZE
>   - stop using temporary variables for possible_crtcs
> 
> changes in v5:
> - None
> 
> changes in v6:
> - None
> 
> changes in v7:
>   - wrap long lines to match the coding style of existing drivers
>   - Fix indentation and remove parenthesis where not needed
>   - use u32 instead of uint32_t for possible_crtcs
> 
> Signed-off-by: Abhinav Kumar 
> Acked-by: Liviu Dudau 
> Reviewed-by: Dmitry Baryshkov 

Reviewed-by: Laurent Pinchart 

> ---
>  drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c | 4 ++--
>  drivers/gpu/drm/arm/malidp_mw.c  | 4 ++--
>  drivers/gpu/drm/drm_writeback.c  | 7 ++-
>  drivers/gpu/drm/rcar-du/rcar_du_writeback.c  | 4 ++--
>  drivers/gpu/drm/vc4/vc4_txp.c| 3 ++-
>  drivers/gpu/drm/vkms/vkms_writeback.c| 4 ++--
>  include/drm/drm_writeback.h  | 3 ++-
>  7 files changed, 18 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c 
> b/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c
> index e465cc4..ce4b760 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c
> @@ -155,7 +155,6 @@ static int komeda_wb_connector_add(struct komeda_kms_dev 
> *kms,
>   kwb_conn->wb_layer = kcrtc->master->wb_layer;
>  
>   wb_conn = _conn->base;
> - wb_conn->encoder.possible_crtcs = BIT(drm_crtc_index(>base));
>  
>   formats = komeda_get_layer_fourcc_list(>fmt_tbl,
>  kwb_conn->wb_layer->layer_type,
> @@ -164,7 +163,8 @@ static int komeda_wb_connector_add(struct komeda_kms_dev 
> *kms,
>   err = drm_writeback_connector_init(>base, wb_conn,
>  _wb_connector_funcs,
>  _wb_encoder_helper_funcs,
> -formats, n_formats);
> +formats, n_formats,
> +BIT(drm_crtc_index(>base)));
>   komeda_put_fourcc_list(formats);
>   if (err) {
>   kfree(kwb_conn);
> diff --git a/drivers/gpu/drm/arm/malidp_mw.c b/drivers/gpu/drm/arm/malidp_mw.c
> index f5847a7..204c869 100644
> --- a/drivers/gpu/drm/arm/malidp_mw.c
> +++ b/drivers/gpu/drm/arm/malidp_mw.c
> @@ -212,7 +212,6 @@ int malidp_mw_connector_init(struct drm_device *drm)
>   if (!malidp->dev->hw->enable_memwrite)
>   return 0;
>  
> - malidp->mw_connector.encoder.possible_crtcs = 1 << 
> drm_crtc_index(>crtc);
>   drm_connector_helper_add(>mw_connector.base,
>_mw_connector_helper_funcs);
>  
> @@ -223,7 +222,8 @@ int malidp_mw_connector_init(struct drm_device *drm)
>   ret = drm_writeback_connector_init(drm, >mw_connector,
>  _mw_connector_funcs,
>  _mw_encoder_helper_funcs,
> -formats, n_formats);
> +formats, n_formats,
> +1 << drm_crtc_index(>crtc));
>   kfree(formats);
>   if (ret)
>   return ret;
> diff --git a/drivers/gpu/drm/drm_writeback.c b/drivers/gpu/drm/drm_writeback.c
> index dccf4504..9e0b845 100644
> --- a/drivers/gpu/drm/drm_writeback.c
> +++ b/drivers/gpu/drm/drm_writeback.c
> @@ -157,6 +157,7 @@ static const struct drm_encoder_funcs 
> drm_writeback_encoder_funcs = {
>   * @enc_helper_funcs: Encoder helper funcs vtable to be used by the internal 
> encoder
>   * @formats: Array of supported pixel formats for the writeback engine
>   * @n_formats: Length of the formats array
> + * @possible_crtcs: possible crtcs for the internal writeback encoder
>   *
>   * This function creates the writeback-connector-specific properties if they
>   * have not been already created, initializes the connector as
> @@ -174,7 +175,8 @@ int drm_writeback_connector_init(struct 

[PATCH] drm/amd/display: fix if == else warning

2022-04-24 Thread Guo Zhengkui
Fix the following coccicheck warning:

drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.c:98:8-10:
WARNING: possible condition with no effect (if == else)

Signed-off-by: Guo Zhengkui 
---
 drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.c
index fe22530242d2..05b3fba9ccce 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.c
@@ -95,8 +95,6 @@ static void gpu_addr_to_uma(struct dce_hwseq *hwseq,
} else if (hwseq->fb_offset.quad_part <= addr->quad_part &&
addr->quad_part <= hwseq->uma_top.quad_part) {
is_in_uma = true;
-   } else if (addr->quad_part == 0) {
-   is_in_uma = false;
} else {
is_in_uma = false;
}
-- 
2.20.1



[PATCH] drm/kmb: Fix unsigned function returning negative constant

2022-04-24 Thread Haowen Bai
The function check_pixel_format has an unsigned return type, but returns a
negative constant to indicate an error condition. So we change unsigned
to int.

Signed-off-by: Haowen Bai 
---
 drivers/gpu/drm/kmb/kmb_plane.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/kmb/kmb_plane.c b/drivers/gpu/drm/kmb/kmb_plane.c
index 2735b8eb3537..5071b7029da6 100644
--- a/drivers/gpu/drm/kmb/kmb_plane.c
+++ b/drivers/gpu/drm/kmb/kmb_plane.c
@@ -65,7 +65,7 @@ static const u32 kmb_formats_v[] = {
DRM_FORMAT_NV12, DRM_FORMAT_NV21,
 };
 
-static unsigned int check_pixel_format(struct drm_plane *plane, u32 format)
+static int check_pixel_format(struct drm_plane *plane, u32 format)
 {
struct kmb_drm_private *kmb;
struct kmb_plane *kmb_plane = to_kmb_plane(plane);
-- 
2.7.4



Re: [PATCH v2 00/48] ARM: PXA multiplatform support

2022-04-24 Thread Arnd Bergmann
On Sun, Apr 24, 2022 at 4:09 AM Guenter Roeck  wrote:
> On 4/23/22 12:55, Arnd Bergmann wrote:
> > On Sat, Apr 23, 2022 at 1:41 AM Guenter Roeck  wrote:
> >> On Sat, Apr 23, 2022 at 12:04:31AM +0200, Arnd Bergmann wrote:
> >
> > Odd, I can't reproduce this at all. Do you get any console output at
> > all for this?
> >
> > Is this the plain omap1_defconfig, or something else?
> >
>
> No, it is my own sx1 specific configuration.
>
> https://github.com/groeck/linux-build-test/blob/master/rootfs/arm/qemu_sx1_defconfig
>
> I don't recall where I got it from but ...

Ok, that explains it, thanks!

I fixed all the defconfig files that come with the kernel, but for your own
ones you have to add

# CONFIG_ARCH_MULTI_V7 is not set

into the defconfig file, otherwise the multiplatform target defaults to
an ARMv7 instead of ARMv5 build. For an OMAP15xx as in the SX1,
you also need to enable CONFIG_ARCH_MULTI_V4T.

This is slightly unfortunate, but I don't see any way to avoid it, and the
modified defconfig will still work fine with older kernel trees.

> > One thing I keep having to apply myself is this snippet:
> >
> > diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S
> > index 0bfad62ea858..87c695703580 100644
> > --- a/arch/arm/mm/proc-arm925.S
> > +++ b/arch/arm/mm/proc-arm925.S
> > @@ -441,7 +441,6 @@ __arm925_setup:
> >
> >   #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
> >  mov r0, #4  @ disable write-back
> > on caches explicitly
> > -   mcr p15, 7, r0, c15, c0, 0
> >   #endif
>
> it does not have CONFIG_CPU_DCACHE_WRITETHROUGH enabled.

Maybe it was disabled explicitly for the sx1_defconfig because of this
bug. I would think that this is required for actual sx1 hardware because the
option is default-enabled for ARM925T, and that CPU core is exclusively
used in OMAP15xx.

Arnd