RE: [PATCH] WIP: drm/dp_mst: Add support for dumping topology ref histories from debugfs
[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
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
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
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
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
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
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
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
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
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
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
_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
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
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
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
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
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
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
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
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()
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
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
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
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
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
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
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
[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
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
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
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
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
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
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
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
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
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()
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
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
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()
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
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()
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()
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
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
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()
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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()
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
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
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
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