From: Douglas Anderson dianders@chromium.org
[ Upstream commit a70e558c151043ce46a5e5999f4310e0b3551f57 ]
This is really just a revert of commit 58074b08c04a ("drm/bridge: ti-sn65dsi86: Read EDID blob over DDC"), resolving conflicts.
The old code failed to read the EDID properly in a very important case: before the bridge's pre_enable() was called. The way things need to work: 1. Read the EDID. 2. Based on the EDID, decide on video settings and pixel clock. 3. Enable the bridge w/ the desired settings.
The way things were working: 1. Try to read the EDID but fail; fall back to hardcoded values. 2. Based on hardcoded values, decide on video settings and pixel clock. 3. Enable the bridge w/ the desired settings. 4. Try again to read the EDID, it works now! 5. Realize that the hardcoded settings weren't quite right. 6. Disable / reenable the bridge w/ the right settings.
The reasons for the failures were twofold: a) Since we never ran the bridge chip's pre-enable then we never set the bit to ignore HPD. This meant the bridge chip didn't even _try_ to go out on the bus and communicate with the panel. b) Even if we fixed things to ignore HPD, the EDID still wouldn't read if the panel wasn't on.
Instead of reverting the code, we could fix it to set the HPD bit and also power on the panel. However, it also works nicely to just let the panel code read the EDID. Now that we've split the driver up we can expose the DDC AUX channel bus to the panel node. The panel can take charge of reading the EDID.
NOTE: in order for things to work, anyone that needs to read the EDID will need to instantiate their panel using the new DP AUX bus (AKA by listing their panel under the "aux-bus" node of the bridge chip in the device tree).
In the future if we want to use the bridge chip to provide a full external DP port (which won't have a panel) then we will have to conditinally add EDID reading back in.
Suggested-by: Andrzej Hajda a.hajda@samsung.com Signed-off-by: Douglas Anderson dianders@chromium.org Reviewed-by: Bjorn Andersson bjorn.andersson@linaro.org Link: https://patchwork.freedesktop.org/patch/msgid/20210611101711.v10.9.I9330684c... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 22 ---------------------- 1 file changed, 22 deletions(-)
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 45a2969afb2b..aef850296756 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -124,7 +124,6 @@ * @connector: Our connector. * @host_node: Remote DSI node. * @dsi: Our MIPI DSI source. - * @edid: Detected EDID of eDP panel. * @refclk: Our reference clock. * @panel: Our panel. * @enable_gpio: The GPIO we toggle to enable the bridge. @@ -154,7 +153,6 @@ struct ti_sn65dsi86 { struct drm_dp_aux aux; struct drm_bridge bridge; struct drm_connector connector; - struct edid *edid; struct device_node *host_node; struct mipi_dsi_device *dsi; struct clk *refclk; @@ -403,24 +401,6 @@ connector_to_ti_sn65dsi86(struct drm_connector *connector) static int ti_sn_bridge_connector_get_modes(struct drm_connector *connector) { struct ti_sn65dsi86 *pdata = connector_to_ti_sn65dsi86(connector); - struct edid *edid = pdata->edid; - int num, ret; - - if (!edid) { - pm_runtime_get_sync(pdata->dev); - edid = pdata->edid = drm_get_edid(connector, &pdata->aux.ddc); - pm_runtime_put_autosuspend(pdata->dev); - } - - if (edid && drm_edid_is_valid(edid)) { - ret = drm_connector_update_edid_property(connector, edid); - if (!ret) { - num = drm_add_edid_modes(connector, edid); - if (num) - return num; - } - } - return drm_panel_get_modes(pdata->panel, connector); }
@@ -1358,8 +1338,6 @@ static void ti_sn_bridge_remove(struct auxiliary_device *adev) mipi_dsi_device_unregister(pdata->dsi); }
- kfree(pdata->edid); - drm_bridge_remove(&pdata->bridge);
of_node_put(pdata->host_node);
From: Zack Rusin zackr@vmware.com
[ Upstream commit a12be0277316ed923411c9c80b2899ee74d2b033 ]
The has_dx variable was only set during the initialization which meant that UPDATE_SUBRESOURCE was never used. We were emulating it with UPDATE_GB_IMAGE but that's always been a stop-gap. Instead of has_dx which has been deprecated a long time ago we need to check for whether shader model 4.0 or newer is available to the device.
Signed-off-by: Zack Rusin zackr@vmware.com Reviewed-by: Roland Scheidegger sroland@vmware.com Reviewed-by: Martin Krastev krastevm@vmware.com Link: https://patchwork.freedesktop.org/patch/msgid/20210609172307.131929-4-zackr@... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c index 0835468bb2ee..47c03a276515 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c @@ -1872,7 +1872,6 @@ static void vmw_surface_dirty_range_add(struct vmw_resource *res, size_t start, static int vmw_surface_dirty_sync(struct vmw_resource *res) { struct vmw_private *dev_priv = res->dev_priv; - bool has_dx = 0; u32 i, num_dirty; struct vmw_surface_dirty *dirty = (struct vmw_surface_dirty *) res->dirty; @@ -1899,7 +1898,7 @@ static int vmw_surface_dirty_sync(struct vmw_resource *res) if (!num_dirty) goto out;
- alloc_size = num_dirty * ((has_dx) ? sizeof(*cmd1) : sizeof(*cmd2)); + alloc_size = num_dirty * ((has_sm4_context(dev_priv)) ? sizeof(*cmd1) : sizeof(*cmd2)); cmd = VMW_CMD_RESERVE(dev_priv, alloc_size); if (!cmd) return -ENOMEM; @@ -1917,7 +1916,7 @@ static int vmw_surface_dirty_sync(struct vmw_resource *res) * DX_UPDATE_SUBRESOURCE is aware of array surfaces. * UPDATE_GB_IMAGE is not. */ - if (has_dx) { + if (has_sm4_context(dev_priv)) { cmd1->header.id = SVGA_3D_CMD_DX_UPDATE_SUBRESOURCE; cmd1->header.size = sizeof(cmd1->body); cmd1->body.sid = res->id;
From: Zack Rusin zackr@vmware.com
[ Upstream commit 74231041d14030f1ae6582b9233bfe782ac23e33 ]
Fix some minor issues that Coverity spotted in the code. None of that are serious but they're all valid concerns so fixing them makes sense.
Signed-off-by: Zack Rusin zackr@vmware.com Reviewed-by: Roland Scheidegger sroland@vmware.com Reviewed-by: Martin Krastev krastevm@vmware.com Link: https://patchwork.freedesktop.org/patch/msgid/20210609172307.131929-5-zackr@... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/vmwgfx/ttm_memory.c | 2 ++ drivers/gpu/drm/vmwgfx/vmwgfx_binding.c | 20 ++++++++------------ drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c | 4 +++- drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 2 ++ drivers/gpu/drm/vmwgfx/vmwgfx_mob.c | 4 +++- drivers/gpu/drm/vmwgfx/vmwgfx_msg.c | 6 ++++-- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 8 ++++++-- drivers/gpu/drm/vmwgfx/vmwgfx_so.c | 3 ++- drivers/gpu/drm/vmwgfx/vmwgfx_validation.c | 4 ++-- 10 files changed, 33 insertions(+), 22 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/ttm_memory.c b/drivers/gpu/drm/vmwgfx/ttm_memory.c index aeb0a22a2c34..edd17c30d5a5 100644 --- a/drivers/gpu/drm/vmwgfx/ttm_memory.c +++ b/drivers/gpu/drm/vmwgfx/ttm_memory.c @@ -435,8 +435,10 @@ int ttm_mem_global_init(struct ttm_mem_global *glob, struct device *dev)
si_meminfo(&si);
+ spin_lock(&glob->lock); /* set it as 0 by default to keep original behavior of OOM */ glob->lower_mem_limit = 0; + spin_unlock(&glob->lock);
ret = ttm_mem_init_kernel_zone(glob, &si); if (unlikely(ret != 0)) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_binding.c b/drivers/gpu/drm/vmwgfx/vmwgfx_binding.c index 05b324825900..ea6d8c86985f 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_binding.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_binding.c @@ -715,7 +715,7 @@ static int vmw_binding_scrub_cb(struct vmw_ctx_bindinfo *bi, bool rebind) * without checking which bindings actually need to be emitted * * @cbs: Pointer to the context's struct vmw_ctx_binding_state - * @bi: Pointer to where the binding info array is stored in @cbs + * @biv: Pointer to where the binding info array is stored in @cbs * @max_num: Maximum number of entries in the @bi array. * * Scans the @bi array for bindings and builds a buffer of view id data. @@ -725,11 +725,9 @@ static int vmw_binding_scrub_cb(struct vmw_ctx_bindinfo *bi, bool rebind) * contains the command data. */ static void vmw_collect_view_ids(struct vmw_ctx_binding_state *cbs, - const struct vmw_ctx_bindinfo *bi, + const struct vmw_ctx_bindinfo_view *biv, u32 max_num) { - const struct vmw_ctx_bindinfo_view *biv = - container_of(bi, struct vmw_ctx_bindinfo_view, bi); unsigned long i;
cbs->bind_cmd_count = 0; @@ -838,7 +836,7 @@ static int vmw_emit_set_sr(struct vmw_ctx_binding_state *cbs, */ static int vmw_emit_set_rt(struct vmw_ctx_binding_state *cbs) { - const struct vmw_ctx_bindinfo *loc = &cbs->render_targets[0].bi; + const struct vmw_ctx_bindinfo_view *loc = &cbs->render_targets[0]; struct { SVGA3dCmdHeader header; SVGA3dCmdDXSetRenderTargets body; @@ -874,7 +872,7 @@ static int vmw_emit_set_rt(struct vmw_ctx_binding_state *cbs) * without checking which bindings actually need to be emitted * * @cbs: Pointer to the context's struct vmw_ctx_binding_state - * @bi: Pointer to where the binding info array is stored in @cbs + * @biso: Pointer to where the binding info array is stored in @cbs * @max_num: Maximum number of entries in the @bi array. * * Scans the @bi array for bindings and builds a buffer of SVGA3dSoTarget data. @@ -884,11 +882,9 @@ static int vmw_emit_set_rt(struct vmw_ctx_binding_state *cbs) * contains the command data. */ static void vmw_collect_so_targets(struct vmw_ctx_binding_state *cbs, - const struct vmw_ctx_bindinfo *bi, + const struct vmw_ctx_bindinfo_so_target *biso, u32 max_num) { - const struct vmw_ctx_bindinfo_so_target *biso = - container_of(bi, struct vmw_ctx_bindinfo_so_target, bi); unsigned long i; SVGA3dSoTarget *so_buffer = (SVGA3dSoTarget *) cbs->bind_cmd_buffer;
@@ -919,7 +915,7 @@ static void vmw_collect_so_targets(struct vmw_ctx_binding_state *cbs, */ static int vmw_emit_set_so_target(struct vmw_ctx_binding_state *cbs) { - const struct vmw_ctx_bindinfo *loc = &cbs->so_targets[0].bi; + const struct vmw_ctx_bindinfo_so_target *loc = &cbs->so_targets[0]; struct { SVGA3dCmdHeader header; SVGA3dCmdDXSetSOTargets body; @@ -1066,7 +1062,7 @@ static int vmw_emit_set_vb(struct vmw_ctx_binding_state *cbs)
static int vmw_emit_set_uav(struct vmw_ctx_binding_state *cbs) { - const struct vmw_ctx_bindinfo *loc = &cbs->ua_views[0].views[0].bi; + const struct vmw_ctx_bindinfo_view *loc = &cbs->ua_views[0].views[0]; struct { SVGA3dCmdHeader header; SVGA3dCmdDXSetUAViews body; @@ -1096,7 +1092,7 @@ static int vmw_emit_set_uav(struct vmw_ctx_binding_state *cbs)
static int vmw_emit_set_cs_uav(struct vmw_ctx_binding_state *cbs) { - const struct vmw_ctx_bindinfo *loc = &cbs->ua_views[1].views[0].bi; + const struct vmw_ctx_bindinfo_view *loc = &cbs->ua_views[1].views[0]; struct { SVGA3dCmdHeader header; SVGA3dCmdDXSetCSUAViews body; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c index 6bb4961e64a5..9656d4a2abff 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c @@ -516,7 +516,7 @@ static void vmw_cmdbuf_work_func(struct work_struct *work) struct vmw_cmdbuf_man *man = container_of(work, struct vmw_cmdbuf_man, work); struct vmw_cmdbuf_header *entry, *next; - uint32_t dummy; + uint32_t dummy = 0; bool send_fence = false; struct list_head restart_head[SVGA_CB_CONTEXT_MAX]; int i; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c index b262d61d839d..9487faff5229 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c @@ -159,6 +159,7 @@ void vmw_cmdbuf_res_commit(struct list_head *list) void vmw_cmdbuf_res_revert(struct list_head *list) { struct vmw_cmdbuf_res *entry, *next; + int ret;
list_for_each_entry_safe(entry, next, list, head) { switch (entry->state) { @@ -166,7 +167,8 @@ void vmw_cmdbuf_res_revert(struct list_head *list) vmw_cmdbuf_res_free(entry->man, entry); break; case VMW_CMDBUF_RES_DEL: - drm_ht_insert_item(&entry->man->resources, &entry->hash); + ret = drm_ht_insert_item(&entry->man->resources, &entry->hash); + BUG_ON(ret); list_del(&entry->head); list_add_tail(&entry->head, &entry->man->list); entry->state = VMW_CMDBUF_RES_COMMITTED; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index a2b8464b3f56..06e8332682c5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -2546,6 +2546,8 @@ static int vmw_cmd_dx_so_define(struct vmw_private *dev_priv,
so_type = vmw_so_cmd_to_type(header->id); res = vmw_context_cotable(ctx_node->ctx, vmw_so_cotables[so_type]); + if (IS_ERR(res)) + return PTR_ERR(res); cmd = container_of(header, typeof(*cmd), header); ret = vmw_cotable_notify(res, cmd->defined_id);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c b/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c index f2d625415458..2d8caf09f172 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c @@ -506,11 +506,13 @@ static void vmw_mob_pt_setup(struct vmw_mob *mob, { unsigned long num_pt_pages = 0; struct ttm_buffer_object *bo = mob->pt_bo; - struct vmw_piter save_pt_iter; + struct vmw_piter save_pt_iter = {0}; struct vmw_piter pt_iter; const struct vmw_sg_table *vsgt; int ret;
+ BUG_ON(num_data_pages == 0); + ret = ttm_bo_reserve(bo, false, true, NULL); BUG_ON(ret != 0);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c index 3d08f5700bdb..7e3f99722d02 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c @@ -155,6 +155,7 @@ static unsigned long vmw_port_hb_out(struct rpc_channel *channel, /* HB port can't access encrypted memory. */ if (hb && !mem_encrypt_active()) { unsigned long bp = channel->cookie_high; + u32 channel_id = (channel->channel_id << 16);
si = (uintptr_t) msg; di = channel->cookie_low; @@ -162,7 +163,7 @@ static unsigned long vmw_port_hb_out(struct rpc_channel *channel, VMW_PORT_HB_OUT( (MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG, msg_len, si, di, - VMWARE_HYPERVISOR_HB | (channel->channel_id << 16) | + VMWARE_HYPERVISOR_HB | channel_id | VMWARE_HYPERVISOR_OUT, VMW_HYPERVISOR_MAGIC, bp, eax, ebx, ecx, edx, si, di); @@ -210,6 +211,7 @@ static unsigned long vmw_port_hb_in(struct rpc_channel *channel, char *reply, /* HB port can't access encrypted memory */ if (hb && !mem_encrypt_active()) { unsigned long bp = channel->cookie_low; + u32 channel_id = (channel->channel_id << 16);
si = channel->cookie_high; di = (uintptr_t) reply; @@ -217,7 +219,7 @@ static unsigned long vmw_port_hb_in(struct rpc_channel *channel, char *reply, VMW_PORT_HB_IN( (MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG, reply_len, si, di, - VMWARE_HYPERVISOR_HB | (channel->channel_id << 16), + VMWARE_HYPERVISOR_HB | channel_id, VMW_HYPERVISOR_MAGIC, bp, eax, ebx, ecx, edx, si, di);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 7b45393ad98e..3b6f6044c325 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -114,6 +114,7 @@ static void vmw_resource_release(struct kref *kref) container_of(kref, struct vmw_resource, kref); struct vmw_private *dev_priv = res->dev_priv; int id; + int ret; struct idr *idr = &dev_priv->res_idr[res->func->res_type];
spin_lock(&dev_priv->resource_lock); @@ -122,7 +123,8 @@ static void vmw_resource_release(struct kref *kref) if (res->backup) { struct ttm_buffer_object *bo = &res->backup->base;
- ttm_bo_reserve(bo, false, false, NULL); + ret = ttm_bo_reserve(bo, false, false, NULL); + BUG_ON(ret); if (vmw_resource_mob_attached(res) && res->func->unbind != NULL) { struct ttm_validate_buffer val_buf; @@ -1001,7 +1003,9 @@ int vmw_resource_pin(struct vmw_resource *res, bool interruptible) if (res->backup) { vbo = res->backup;
- ttm_bo_reserve(&vbo->base, interruptible, false, NULL); + ret = ttm_bo_reserve(&vbo->base, interruptible, false, NULL); + if (ret) + goto out_no_validate; if (!vbo->base.pin_count) { ret = ttm_bo_validate (&vbo->base, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_so.c b/drivers/gpu/drm/vmwgfx/vmwgfx_so.c index c3a8d6e8380e..9efb4463ce99 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_so.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_so.c @@ -539,7 +539,8 @@ const SVGACOTableType vmw_so_cotables[] = { [vmw_so_ds] = SVGA_COTABLE_DEPTHSTENCIL, [vmw_so_rs] = SVGA_COTABLE_RASTERIZERSTATE, [vmw_so_ss] = SVGA_COTABLE_SAMPLER, - [vmw_so_so] = SVGA_COTABLE_STREAMOUTPUT + [vmw_so_so] = SVGA_COTABLE_STREAMOUTPUT, + [vmw_so_max]= SVGA_COTABLE_MAX };
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c index 8338b1d20f2a..b09094b50c5d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c @@ -586,13 +586,13 @@ int vmw_validation_bo_validate(struct vmw_validation_context *ctx, bool intr) container_of(entry->base.bo, typeof(*vbo), base);
if (entry->cpu_blit) { - struct ttm_operation_ctx ctx = { + struct ttm_operation_ctx ttm_ctx = { .interruptible = intr, .no_wait_gpu = false };
ret = ttm_bo_validate(entry->base.bo, - &vmw_nonfixed_placement, &ctx); + &vmw_nonfixed_placement, &ttm_ctx); } else { ret = vmw_validation_bo_validate_single (entry->base.bo, intr, entry->as_mob);
From: Dom Cobley popcornmix@gmail.com
[ Upstream commit 1698ecb218eb82587dbfc71a2e26ded66e5ecf59 ]
Symptom is random switching of speakers when using multichannel.
Repeatedly running speakertest -c8 occasionally starts with channels jumbled. This is fixed with HD_CTL_WHOLSMP.
The other bit looks beneficial and apears harmless in testing so I'd suggest adding it too.
Documentation says: HD_CTL_WHILSMP_SET Wait for whole sample. When this bit is set MAI transmit will start only when there is at least one whole sample available in the fifo.
Documentation says: HD_CTL_CHALIGN_SET Channel Align When Overflow. This bit is used to realign the audio channels in case of an overflow. If this bit is set, after the detection of an overflow, equal amount of dummy words to the missing words will be written to fifo, filling up the broken sample and maintaining alignment.
Signed-off-by: Dom Cobley popcornmix@gmail.com Signed-off-by: Maxime Ripard maxime@cerno.tech Reviewed-by: Nicolas Saenz Julienne nsaenz@kernel.org Link: https://patchwork.freedesktop.org/patch/msgid/20210525132354.297468-7-maxime... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/vc4/vc4_hdmi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index c2876731ee2d..ad92dbb128b3 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -1372,7 +1372,9 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd, HDMI_WRITE(HDMI_MAI_CTL, VC4_SET_FIELD(vc4_hdmi->audio.channels, VC4_HD_MAI_CTL_CHNUM) | - VC4_HD_MAI_CTL_ENABLE); + VC4_HD_MAI_CTL_WHOLSMP | + VC4_HD_MAI_CTL_CHALIGN | + VC4_HD_MAI_CTL_ENABLE); break; case SNDRV_PCM_TRIGGER_STOP: HDMI_WRITE(HDMI_MAI_CTL,
From: Andrey Grodzovsky andrey.grodzovsky@amd.com
[ Upstream commit 403797925768d9fa870f5b1ebcd20016b397083b ]
Problem: Under memory pressure when GTT domain is almost full multihop assert will come up when trying to evict LRU BO from VRAM to SYSTEM.
Fix: Don't assert on multihop error in evict code but rather do a retry as we do in ttm_bo_move_buffer
Signed-off-by: Andrey Grodzovsky andrey.grodzovsky@amd.com Reviewed-by: Christian König christian.koenig@amd.com Link: https://patchwork.freedesktop.org/patch/msgid/20210622162339.761651-6-andrey... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/ttm/ttm_bo.c | 63 +++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 29 deletions(-)
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 8d7fd65ccced..32202385073a 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -488,6 +488,31 @@ void ttm_bo_unlock_delayed_workqueue(struct ttm_device *bdev, int resched) } EXPORT_SYMBOL(ttm_bo_unlock_delayed_workqueue);
+static int ttm_bo_bounce_temp_buffer(struct ttm_buffer_object *bo, + struct ttm_resource **mem, + struct ttm_operation_ctx *ctx, + struct ttm_place *hop) +{ + struct ttm_placement hop_placement; + struct ttm_resource *hop_mem; + int ret; + + hop_placement.num_placement = hop_placement.num_busy_placement = 1; + hop_placement.placement = hop_placement.busy_placement = hop; + + /* find space in the bounce domain */ + ret = ttm_bo_mem_space(bo, &hop_placement, &hop_mem, ctx); + if (ret) + return ret; + /* move to the bounce domain */ + ret = ttm_bo_handle_move_mem(bo, hop_mem, false, ctx, NULL); + if (ret) { + ttm_resource_free(bo, &hop_mem); + return ret; + } + return 0; +} + static int ttm_bo_evict(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx) { @@ -527,12 +552,17 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, goto out; }
+bounce: ret = ttm_bo_handle_move_mem(bo, evict_mem, true, ctx, &hop); - if (unlikely(ret)) { - WARN(ret == -EMULTIHOP, "Unexpected multihop in eviction - likely driver bug\n"); - if (ret != -ERESTARTSYS) + if (ret == -EMULTIHOP) { + ret = ttm_bo_bounce_temp_buffer(bo, &evict_mem, ctx, &hop); + if (ret) { pr_err("Buffer eviction failed\n"); - ttm_resource_free(bo, &evict_mem); + ttm_resource_free(bo, &evict_mem); + goto out; + } + /* try and move to final place now. */ + goto bounce; } out: return ret; @@ -847,31 +877,6 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, } EXPORT_SYMBOL(ttm_bo_mem_space);
-static int ttm_bo_bounce_temp_buffer(struct ttm_buffer_object *bo, - struct ttm_resource **mem, - struct ttm_operation_ctx *ctx, - struct ttm_place *hop) -{ - struct ttm_placement hop_placement; - struct ttm_resource *hop_mem; - int ret; - - hop_placement.num_placement = hop_placement.num_busy_placement = 1; - hop_placement.placement = hop_placement.busy_placement = hop; - - /* find space in the bounce domain */ - ret = ttm_bo_mem_space(bo, &hop_placement, &hop_mem, ctx); - if (ret) - return ret; - /* move to the bounce domain */ - ret = ttm_bo_handle_move_mem(bo, hop_mem, false, ctx, NULL); - if (ret) { - ttm_resource_free(bo, &hop_mem); - return ret; - } - return 0; -} - static int ttm_bo_move_buffer(struct ttm_buffer_object *bo, struct ttm_placement *placement, struct ttm_operation_ctx *ctx)
From: Daniel Vetter daniel.vetter@ffwll.ch
[ Upstream commit 942d8344d5f14b9ea2ae43756f319b9f44216ba4 ]
I guess no one ever tried running omap together with lima or panfrost, not even sure that's possible. Anyway for consistency, fix this.
Reviewed-by: Tomi Valkeinen tomi.valkeinen@ideasonboard.com Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: Tomi Valkeinen tomba@kernel.org Link: https://patchwork.freedesktop.org/patch/msgid/20210622165511.3169559-12-dani... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/omapdrm/omap_plane.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 801da917507d..512af976b7e9 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -6,6 +6,7 @@
#include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_gem_atomic_helper.h> #include <drm/drm_plane_helper.h>
#include "omap_dmm_tiler.h" @@ -29,6 +30,8 @@ static int omap_plane_prepare_fb(struct drm_plane *plane, if (!new_state->fb) return 0;
+ drm_gem_plane_helper_prepare_fb(plane, new_state); + return omap_framebuffer_pin(new_state->fb); }
From: Luben Tuikov luben.tuikov@amd.com
[ Upstream commit dce4400e6516d18313d23de45b5be8a18980b00e ]
No need to account for the 2 bytes of EEPROM address--this is now well abstracted away by the fixes the the lower layers.
Cc: Andrey Grodzovsky andrey.grodzovsky@amd.com Cc: Alexander Deucher Alexander.Deucher@amd.com Signed-off-by: Luben Tuikov luben.tuikov@amd.com Acked-by: Alexander Deucher Alexander.Deucher@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index 38222de921d1..8dd151c9e459 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -325,7 +325,7 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control, return ret; }
- __decode_table_header_from_buff(hdr, &buff[2]); + __decode_table_header_from_buff(hdr, buff);
if (hdr->header == EEPROM_TABLE_HDR_VAL) { control->num_recs = (hdr->tbl_size - EEPROM_TABLE_HEADER_SIZE) /
From: Luben Tuikov luben.tuikov@amd.com
[ Upstream commit 1d9d2ca85b32605ac9c74c8fa42d0c1cfbe019d4 ]
Debugfs RAS EEPROM files are available when the ASIC supports RAS, and when the debugfs is enabled, an also when "ras_enable" module parameter is set to 0. However in this case, we get a kernel oops when accessing some of the "ras_..." controls in debugfs. The reason for this is that struct amdgpu_ras::adev is unset. This commit sets it, thus enabling access to those facilities. Note that this facilitates EEPROM access and not necessarily RAS features or functionality.
Cc: Alexander Deucher Alexander.Deucher@amd.com Cc: John Clements john.clements@amd.com Cc: Hawking Zhang Hawking.Zhang@amd.com Signed-off-by: Luben Tuikov luben.tuikov@amd.com Acked-by: Alexander Deucher Alexander.Deucher@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index fc66aca28594..95d5842385b3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1966,11 +1966,20 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev) bool exc_err_limit = false; int ret;
- if (adev->ras_enabled && con) - data = &con->eh_data; - else + if (!con) + return 0; + + /* Allow access to RAS EEPROM via debugfs, when the ASIC + * supports RAS and debugfs is enabled, but when + * adev->ras_enabled is unset, i.e. when "ras_enable" + * module parameter is set to 0. + */ + con->adev = adev; + + if (!adev->ras_enabled) return 0;
+ data = &con->eh_data; *data = kmalloc(sizeof(**data), GFP_KERNEL | __GFP_ZERO); if (!*data) { ret = -ENOMEM; @@ -1980,7 +1989,6 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev) mutex_init(&con->recovery_lock); INIT_WORK(&con->recovery_work, amdgpu_ras_do_recovery); atomic_set(&con->in_recovery, 0); - con->adev = adev;
max_eeprom_records_len = amdgpu_ras_eeprom_get_record_max_length(); amdgpu_ras_validate_threshold(adev, max_eeprom_records_len);
From: Tim Gover tim.gover@raspberrypi.com
[ Upstream commit 0b066a6809d0f8fd9868e383add36aa5a2fa409d ]
Adjust the DVP enable/disable sequence to avoid a pixel getting stuck in an internal, non resettable FIFO within PixelValve when changing HDMI resolution.
The blank pixels features of the DVP can prevent signals back to pixelvalve causing it to not clear the FIFO. Adjust the ordering and timing of operations to ensure the clear signal makes it through to pixelvalve.
Signed-off-by: Tim Gover tim.gover@raspberrypi.com Signed-off-by: Maxime Ripard maxime@cerno.tech Link: https://patchwork.freedesktop.org/patch/msgid/20210628130533.144617-1-maxime... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/vc4/vc4_hdmi.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index ad92dbb128b3..f91d37beb113 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -613,12 +613,12 @@ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder,
HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
- HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) | - VC4_HD_VID_CTL_CLRRGB | VC4_HD_VID_CTL_CLRSYNC); + HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_CLRRGB);
- HDMI_WRITE(HDMI_VID_CTL, - HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_BLANKPIX); + mdelay(1);
+ HDMI_WRITE(HDMI_VID_CTL, + HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE); vc4_hdmi_disable_scrambling(encoder); }
@@ -628,12 +628,12 @@ static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder, struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); int ret;
+ HDMI_WRITE(HDMI_VID_CTL, + HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_BLANKPIX); + if (vc4_hdmi->variant->phy_disable) vc4_hdmi->variant->phy_disable(vc4_hdmi);
- HDMI_WRITE(HDMI_VID_CTL, - HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE); - clk_disable_unprepare(vc4_hdmi->pixel_bvb_clock); clk_disable_unprepare(vc4_hdmi->pixel_clock);
@@ -1015,6 +1015,7 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder,
HDMI_WRITE(HDMI_VID_CTL, VC4_HD_VID_CTL_ENABLE | + VC4_HD_VID_CTL_CLRRGB | VC4_HD_VID_CTL_UNDERFLOW_ENABLE | VC4_HD_VID_CTL_FRAME_COUNTER_RESET | (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
From: Christian König christian.koenig@amd.com
[ Upstream commit 9d38814d1e346ea37a51cbf31f4424c9d059459e ]
As the name implies if testing all fences is requested we should indeed test all fences and not skip the exclusive one because we see shared ones.
v2: fix logic once more
Signed-off-by: Christian König christian.koenig@amd.com Reviewed-by: Daniel Vetter daniel.vetter@ffwll.ch Link: https://patchwork.freedesktop.org/patch/msgid/20210702111642.17259-3-christi... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/dma-buf/dma-resv.c | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-)
diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c index f26c71747d43..e744fd87c63c 100644 --- a/drivers/dma-buf/dma-resv.c +++ b/drivers/dma-buf/dma-resv.c @@ -615,25 +615,21 @@ static inline int dma_resv_test_signaled_single(struct dma_fence *passed_fence) */ bool dma_resv_test_signaled(struct dma_resv *obj, bool test_all) { - unsigned int seq, shared_count; + struct dma_fence *fence; + unsigned int seq; int ret;
rcu_read_lock(); retry: ret = true; - shared_count = 0; seq = read_seqcount_begin(&obj->seq);
if (test_all) { struct dma_resv_list *fobj = dma_resv_shared_list(obj); - unsigned int i; - - if (fobj) - shared_count = fobj->shared_count; + unsigned int i, shared_count;
+ shared_count = fobj ? fobj->shared_count : 0; for (i = 0; i < shared_count; ++i) { - struct dma_fence *fence; - fence = rcu_dereference(fobj->shared[i]); ret = dma_resv_test_signaled_single(fence); if (ret < 0) @@ -641,24 +637,19 @@ bool dma_resv_test_signaled(struct dma_resv *obj, bool test_all) else if (!ret) break; } - - if (read_seqcount_retry(&obj->seq, seq)) - goto retry; }
- if (!shared_count) { - struct dma_fence *fence_excl = dma_resv_excl_fence(obj); - - if (fence_excl) { - ret = dma_resv_test_signaled_single(fence_excl); - if (ret < 0) - goto retry; + fence = dma_resv_excl_fence(obj); + if (ret && fence) { + ret = dma_resv_test_signaled_single(fence); + if (ret < 0) + goto retry;
- if (read_seqcount_retry(&obj->seq, seq)) - goto retry; - } }
+ if (read_seqcount_retry(&obj->seq, seq)) + goto retry; + rcu_read_unlock(); return ret; }
Hi,
On Wed, Sep 8, 2021 at 6:46 PM Sasha Levin sashal@kernel.org wrote:
From: Douglas Anderson dianders@chromium.org
[ Upstream commit a70e558c151043ce46a5e5999f4310e0b3551f57 ]
This is really just a revert of commit 58074b08c04a ("drm/bridge: ti-sn65dsi86: Read EDID blob over DDC"), resolving conflicts.
The old code failed to read the EDID properly in a very important case: before the bridge's pre_enable() was called. The way things need to work:
- Read the EDID.
- Based on the EDID, decide on video settings and pixel clock.
- Enable the bridge w/ the desired settings.
The way things were working:
- Try to read the EDID but fail; fall back to hardcoded values.
- Based on hardcoded values, decide on video settings and pixel clock.
- Enable the bridge w/ the desired settings.
- Try again to read the EDID, it works now!
- Realize that the hardcoded settings weren't quite right.
- Disable / reenable the bridge w/ the right settings.
The reasons for the failures were twofold: a) Since we never ran the bridge chip's pre-enable then we never set the bit to ignore HPD. This meant the bridge chip didn't even _try_ to go out on the bus and communicate with the panel. b) Even if we fixed things to ignore HPD, the EDID still wouldn't read if the panel wasn't on.
Instead of reverting the code, we could fix it to set the HPD bit and also power on the panel. However, it also works nicely to just let the panel code read the EDID. Now that we've split the driver up we can expose the DDC AUX channel bus to the panel node. The panel can take charge of reading the EDID.
NOTE: in order for things to work, anyone that needs to read the EDID will need to instantiate their panel using the new DP AUX bus (AKA by listing their panel under the "aux-bus" node of the bridge chip in the device tree).
In the future if we want to use the bridge chip to provide a full external DP port (which won't have a panel) then we will have to conditinally add EDID reading back in.
Suggested-by: Andrzej Hajda a.hajda@samsung.com Signed-off-by: Douglas Anderson dianders@chromium.org Reviewed-by: Bjorn Andersson bjorn.andersson@linaro.org Link: https://patchwork.freedesktop.org/patch/msgid/20210611101711.v10.9.I9330684c... Signed-off-by: Sasha Levin sashal@kernel.org
drivers/gpu/drm/bridge/ti-sn65dsi86.c | 22 ---------------------- 1 file changed, 22 deletions(-)
I would suggest against backporting this one unless you're going to backport the whole pile of DP AUX bus patches, which probably doesn't make sense for stable. Even though the old EDID reading was broken for the first read, it still worked for later reads. ...and the first read didn't crash or anything--it just timed out.
-Doug
linux-stable-mirror@lists.linaro.org