From d180649238f04183950d9c8a7d8a2c2f1788a89c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Larumbe?= Date: Tue, 26 Mar 2024 13:48:10 +0000 Subject: [PATCH 01/32] ABI: sysfs-driver-panfrost-profiling: fix indentation problem MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also add a newline character at the end of the last one. Fixes: b12f3ea7c188 ("drm/panfrost: Replace fdinfo's profiling debugfs knob with sysfs") Reported-by: Stephen Rothwell Closes: https://lore.kernel.org/dri-devel/20240326160110.4c00e1e5@canb.auug.org.au/ Signed-off-by: Adrián Larumbe Acked-by: Randy Dunlap Tested-by: Randy Dunlap Reviewed-by: Steven Price Signed-off-by: Steven Price Link: https://patchwork.freedesktop.org/patch/msgid/20240326134812.4008775-1-adrian.larumbe@collabora.com --- Documentation/ABI/testing/sysfs-driver-panfrost-profiling | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-driver-panfrost-profiling b/Documentation/ABI/testing/sysfs-driver-panfrost-profiling index 1d8bb0978920..7597c420e54b 100644 --- a/Documentation/ABI/testing/sysfs-driver-panfrost-profiling +++ b/Documentation/ABI/testing/sysfs-driver-panfrost-profiling @@ -7,4 +7,4 @@ Description: Valid values are: 0: Don't enable fdinfo job profiling sources. 1: Enable fdinfo job profiling sources, this enables both the GPU's - timestamp and cycle counter registers. \ No newline at end of file + timestamp and cycle counter registers. From 0716e348d13fea9f5798e9cf8b5c08f6d593cff9 Mon Sep 17 00:00:00 2001 From: Ian Forbes Date: Wed, 14 Feb 2024 15:04:40 -0600 Subject: [PATCH 02/32] drm/vmwgfx: Remove unused code Remove unused structs, members, and file. Many of these are written but never read. Signed-off-by: Ian Forbes Signed-off-by: Zack Rusin Link: https://patchwork.freedesktop.org/patch/msgid/20240214210440.26167-1-ian.forbes@broadcom.com --- drivers/gpu/drm/vmwgfx/ttm_object.c | 4 - drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 27 ----- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 12 --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 16 --- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 3 - drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c | 110 --------------------- drivers/gpu/drm/vmwgfx/vmwgfx_validation.c | 19 +--- drivers/gpu/drm/vmwgfx/vmwgfx_validation.h | 7 -- 8 files changed, 1 insertion(+), 197 deletions(-) delete mode 100644 drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c diff --git a/drivers/gpu/drm/vmwgfx/ttm_object.c b/drivers/gpu/drm/vmwgfx/ttm_object.c index 6806c05e57f6..3353e97687d1 100644 --- a/drivers/gpu/drm/vmwgfx/ttm_object.c +++ b/drivers/gpu/drm/vmwgfx/ttm_object.c @@ -87,14 +87,11 @@ struct ttm_object_file { * * @object_lock: lock that protects idr. * - * @object_count: Per device object count. - * * This is the per-device data structure needed for ttm object management. */ struct ttm_object_device { spinlock_t object_lock; - atomic_t object_count; struct dma_buf_ops ops; void (*dmabuf_release)(struct dma_buf *dma_buf); struct idr idr; @@ -431,7 +428,6 @@ ttm_object_device_init(const struct dma_buf_ops *ops) return NULL; spin_lock_init(&tdev->object_lock); - atomic_set(&tdev->object_count, 0); /* * Our base is at VMWGFX_NUM_MOB + 1 because we want to create diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 12efecc17df6..01f41fbb9c3b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -117,25 +117,8 @@ struct vmwgfx_hash_item { unsigned long key; }; - -/** - * struct vmw_validate_buffer - Carries validation info about buffers. - * - * @base: Validation info for TTM. - * @hash: Hash entry for quick lookup of the TTM buffer object. - * - * This structure contains also driver private validation info - * on top of the info needed by TTM. - */ -struct vmw_validate_buffer { - struct ttm_validate_buffer base; - struct vmwgfx_hash_item hash; - bool validate_as_mob; -}; - struct vmw_res_func; - /** * struct vmw-resource - base class for hardware resources * @@ -445,15 +428,6 @@ struct vmw_sw_context{ struct vmw_legacy_display; struct vmw_overlay; -struct vmw_vga_topology_state { - uint32_t width; - uint32_t height; - uint32_t primary; - uint32_t pos_x; - uint32_t pos_y; -}; - - /* * struct vmw_otable - Guest Memory OBject table metadata * @@ -501,7 +475,6 @@ struct vmw_private { struct drm_device drm; struct ttm_device bdev; - struct drm_vma_offset_manager vma_manager; u32 pci_id; resource_size_t io_start; resource_size_t vram_start; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index cd4925346ed4..09214f9339b2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -775,7 +775,6 @@ vmw_du_cursor_plane_atomic_update(struct drm_plane *plane, hotspot_y = du->hotspot_y + new_state->hotspot_y; du->cursor_surface = vps->surf; - du->cursor_bo = vps->bo; if (!vps->surf && !vps->bo) { vmw_cursor_update_position(dev_priv, false, 0, 0); @@ -858,15 +857,6 @@ int vmw_du_primary_plane_atomic_check(struct drm_plane *plane, DRM_PLANE_NO_SCALING, DRM_PLANE_NO_SCALING, false, true); - - if (!ret && new_fb) { - struct drm_crtc *crtc = new_state->crtc; - struct vmw_display_unit *du = vmw_crtc_to_du(crtc); - - vmw_connector_state_to_vcs(du->connector.state); - } - - return ret; } @@ -1361,7 +1351,6 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv, drm_helper_mode_fill_fb_struct(dev, &vfbs->base.base, mode_cmd); vfbs->surface = vmw_surface_reference(surface); - vfbs->base.user_handle = mode_cmd->handles[0]; vfbs->is_bo_proxy = is_bo_proxy; *out = &vfbs->base; @@ -1529,7 +1518,6 @@ static int vmw_kms_new_framebuffer_bo(struct vmw_private *dev_priv, drm_helper_mode_fill_fb_struct(dev, &vfbd->base.base, mode_cmd); vfbd->base.bo = true; vfbd->buffer = vmw_bo_reference(bo); - vfbd->base.user_handle = mode_cmd->handles[0]; *out = &vfbd->base; ret = drm_framebuffer_init(dev, &vfbd->base.base, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index a94947b588e8..4a2e3cac1c22 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h @@ -217,21 +217,11 @@ struct vmw_kms_dirty { struct vmw_framebuffer { struct drm_framebuffer base; bool bo; - uint32_t user_handle; -}; - -/* - * Clip rectangle - */ -struct vmw_clip_rect { - int x1, x2, y1, y2; }; struct vmw_framebuffer_surface { struct vmw_framebuffer base; struct vmw_surface *surface; - struct vmw_bo *buffer; - struct list_head head; bool is_bo_proxy; /* true if this is proxy surface for DMA buf */ }; @@ -359,7 +349,6 @@ struct vmw_display_unit { struct vmw_cursor_plane cursor; struct vmw_surface *cursor_surface; - struct vmw_bo *cursor_bo; size_t cursor_age; int cursor_x; @@ -389,11 +378,6 @@ struct vmw_display_unit { int set_gui_y; }; -struct vmw_validation_ctx { - struct vmw_resource *res; - struct vmw_bo *buf; -}; - #define vmw_crtc_to_du(x) \ container_of(x, struct vmw_display_unit, crtc) #define vmw_connector_to_du(x) \ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index 30c3ad27b662..c6e646895f9e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -89,7 +89,6 @@ struct vmw_kms_sou_define_gmrfb { struct vmw_screen_object_unit { struct vmw_display_unit base; - unsigned long buffer_size; /**< Size of allocated buffer */ struct vmw_bo *buffer; /**< Backing store buffer */ bool defined; @@ -240,7 +239,6 @@ static void vmw_sou_crtc_mode_set_nofb(struct drm_crtc *crtc) int x, y; sou->buffer = vps->bo; - sou->buffer_size = vps->bo_size; conn_state = sou->base.connector.state; vmw_conn_state = vmw_connector_state_to_vcs(conn_state); @@ -255,7 +253,6 @@ static void vmw_sou_crtc_mode_set_nofb(struct drm_crtc *crtc) } else { sou->buffer = NULL; - sou->buffer_size = 0; } } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c deleted file mode 100644 index 90097d04b45f..000000000000 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c +++ /dev/null @@ -1,110 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR MIT -/************************************************************************** - * - * Copyright 2009-2011 VMware, Inc., Palo Alto, CA., USA - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "vmwgfx_drv.h" - -static int vmw_bo_vm_lookup(struct ttm_device *bdev, - struct drm_file *filp, - unsigned long offset, - unsigned long pages, - struct ttm_buffer_object **p_bo) -{ - struct vmw_private *dev_priv = container_of(bdev, struct vmw_private, bdev); - struct drm_device *drm = &dev_priv->drm; - struct drm_vma_offset_node *node; - int ret; - - *p_bo = NULL; - - drm_vma_offset_lock_lookup(bdev->vma_manager); - - node = drm_vma_offset_lookup_locked(bdev->vma_manager, offset, pages); - if (likely(node)) { - *p_bo = container_of(node, struct ttm_buffer_object, - base.vma_node); - *p_bo = ttm_bo_get_unless_zero(*p_bo); - } - - drm_vma_offset_unlock_lookup(bdev->vma_manager); - - if (!*p_bo) { - drm_err(drm, "Could not find buffer object to map\n"); - return -EINVAL; - } - - if (!drm_vma_node_is_allowed(node, filp)) { - ret = -EACCES; - goto out_no_access; - } - - return 0; -out_no_access: - ttm_bo_put(*p_bo); - return ret; -} - -int vmw_mmap(struct file *filp, struct vm_area_struct *vma) -{ - static const struct vm_operations_struct vmw_vm_ops = { - .pfn_mkwrite = vmw_bo_vm_mkwrite, - .page_mkwrite = vmw_bo_vm_mkwrite, - .fault = vmw_bo_vm_fault, - .open = ttm_bo_vm_open, - .close = ttm_bo_vm_close, - }; - struct drm_file *file_priv = filp->private_data; - struct vmw_private *dev_priv = vmw_priv(file_priv->minor->dev); - struct ttm_device *bdev = &dev_priv->bdev; - struct ttm_buffer_object *bo; - int ret; - - if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET_START)) - return -EINVAL; - - ret = vmw_bo_vm_lookup(bdev, file_priv, vma->vm_pgoff, vma_pages(vma), &bo); - if (unlikely(ret != 0)) - return ret; - - ret = ttm_bo_mmap_obj(vma, bo); - if (unlikely(ret != 0)) - goto out_unref; - - vma->vm_ops = &vmw_vm_ops; - - /* Use VM_PFNMAP rather than VM_MIXEDMAP if not a COW mapping */ - if (!is_cow_mapping(vma->vm_flags)) - vm_flags_mod(vma, VM_PFNMAP, VM_MIXEDMAP); - - ttm_bo_put(bo); /* release extra ref taken by ttm_bo_mmap_obj() */ - - return 0; - -out_unref: - ttm_bo_put(bo); - return ret; -} - diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c index aaacbdcbd742..e7625b3f71e0 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c @@ -32,9 +32,6 @@ #include - -#define VMWGFX_VALIDATION_MEM_GRAN (16*PAGE_SIZE) - /** * struct vmw_validation_bo_node - Buffer object validation metadata. * @base: Metadata used for TTM reservation- and validation. @@ -112,20 +109,10 @@ void *vmw_validation_mem_alloc(struct vmw_validation_context *ctx, return NULL; if (ctx->mem_size_left < size) { - struct page *page; - - if (ctx->vm && ctx->vm_size_left < PAGE_SIZE) { - ctx->vm_size_left += VMWGFX_VALIDATION_MEM_GRAN; - ctx->total_mem += VMWGFX_VALIDATION_MEM_GRAN; - } - - page = alloc_page(GFP_KERNEL | __GFP_ZERO); + struct page *page = alloc_page(GFP_KERNEL | __GFP_ZERO); if (!page) return NULL; - if (ctx->vm) - ctx->vm_size_left -= PAGE_SIZE; - list_add_tail(&page->lru, &ctx->page_list); ctx->page_address = page_address(page); ctx->mem_size_left = PAGE_SIZE; @@ -155,10 +142,6 @@ static void vmw_validation_mem_free(struct vmw_validation_context *ctx) } ctx->mem_size_left = 0; - if (ctx->vm && ctx->total_mem) { - ctx->total_mem = 0; - ctx->vm_size_left = 0; - } } /** diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h index 240ee0c4ebfd..353d837907d8 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h @@ -52,10 +52,6 @@ * buffer objects * @mem_size_left: Free memory left in the last page in @page_list * @page_address: Kernel virtual address of the last page in @page_list - * @vm: A pointer to the memory reservation interface or NULL if no - * memory reservation is needed. - * @vm_size_left: Amount of reserved memory that so far has not been allocated. - * @total_mem: Amount of reserved memory. */ struct vmw_validation_context { struct vmw_sw_context *sw_context; @@ -68,9 +64,6 @@ struct vmw_validation_context { unsigned int merge_dups; unsigned int mem_size_left; u8 *page_address; - struct vmw_validation_mem *vm; - size_t vm_size_left; - size_t total_mem; }; struct vmw_bo; From bfbc68e4d8695497f858a45a142665e22a512ea3 Mon Sep 17 00:00:00 2001 From: Christian Hewitt Date: Tue, 9 Jan 2024 23:07:04 +0000 Subject: [PATCH 03/32] drm/meson: vclk: fix calculation of 59.94 fractional rates Playing 4K media with 59.94 fractional rate (typically VP9) causes the screen to lose sync with the following error reported in the system log: [ 89.610280] Fatal Error, invalid HDMI vclk freq 593406 Modetest shows the following: 3840x2160 59.94 3840 4016 4104 4400 2160 2168 2178 2250 593407 flags: xxxx, xxxx, drm calculated value -------------------------------------^ Change the fractional rate calculation to stop DIV_ROUND_CLOSEST rounding down which results in vclk freq failing to match correctly. Fixes: e5fab2ec9ca4 ("drm/meson: vclk: add support for YUV420 setup") Signed-off-by: Christian Hewitt Reviewed-by: Neil Armstrong Link: https://lore.kernel.org/r/20240109230704.4120561-1-christianshewitt@gmail.com Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20240109230704.4120561-1-christianshewitt@gmail.com --- drivers/gpu/drm/meson/meson_vclk.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c index 2a82119eb58e..2a942dc6a6dc 100644 --- a/drivers/gpu/drm/meson/meson_vclk.c +++ b/drivers/gpu/drm/meson/meson_vclk.c @@ -790,13 +790,13 @@ meson_vclk_vic_supported_freq(struct meson_drm *priv, unsigned int phy_freq, FREQ_1000_1001(params[i].pixel_freq)); DRM_DEBUG_DRIVER("i = %d phy_freq = %d alt = %d\n", i, params[i].phy_freq, - FREQ_1000_1001(params[i].phy_freq/10)*10); + FREQ_1000_1001(params[i].phy_freq/1000)*1000); /* Match strict frequency */ if (phy_freq == params[i].phy_freq && vclk_freq == params[i].vclk_freq) return MODE_OK; /* Match 1000/1001 variant */ - if (phy_freq == (FREQ_1000_1001(params[i].phy_freq/10)*10) && + if (phy_freq == (FREQ_1000_1001(params[i].phy_freq/1000)*1000) && vclk_freq == FREQ_1000_1001(params[i].vclk_freq)) return MODE_OK; } @@ -1070,7 +1070,7 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target, for (freq = 0 ; params[freq].pixel_freq ; ++freq) { if ((phy_freq == params[freq].phy_freq || - phy_freq == FREQ_1000_1001(params[freq].phy_freq/10)*10) && + phy_freq == FREQ_1000_1001(params[freq].phy_freq/1000)*1000) && (vclk_freq == params[freq].vclk_freq || vclk_freq == FREQ_1000_1001(params[freq].vclk_freq))) { if (vclk_freq != params[freq].vclk_freq) From 59237fc04ee1c4cdf62ad5dba18244713970e36f Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Mon, 25 Mar 2024 08:49:55 -0500 Subject: [PATCH 04/32] dt-bindings: vendor-prefix: Add prefix for GameForce GameForce is a company that produces handheld game consoles. https://gameforce.fun/ Signed-off-by: Chris Morgan Acked-by: Rob Herring Link: https://lore.kernel.org/r/20240325134959.11807-2-macroalpha82@gmail.com Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20240325134959.11807-2-macroalpha82@gmail.com --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 96e47742e250..fa210145e584 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -518,6 +518,8 @@ patternProperties: description: FX Technology Ltd. "^galaxycore,.*": description: GalaxyCore Inc. + "^gameforce,.*": + description: GameForce "^gardena,.*": description: GARDENA GmbH "^gateway,.*": From 387974a21a63b1c7efcbc19c48b9930f6ef5ac63 Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Mon, 25 Mar 2024 08:49:56 -0500 Subject: [PATCH 05/32] dt-bindings: display: Add GameForce Chi Panel The GameForce Chi panel is a panel specific to the GameForce Chi handheld device that measures 3.5" diagonally with a resolution of 640x480. Signed-off-by: Chris Morgan Acked-by: Rob Herring Link: https://lore.kernel.org/r/20240325134959.11807-3-macroalpha82@gmail.com Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20240325134959.11807-3-macroalpha82@gmail.com --- .../devicetree/bindings/display/panel/rocktech,jh057n00900.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml b/Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml index 6ec471284f97..4ae152cc55e0 100644 --- a/Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml +++ b/Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml @@ -22,6 +22,8 @@ properties: enum: # Anberic RG353V-V2 5.0" 640x480 TFT LCD panel - anbernic,rg353v-panel-v2 + # GameForce Chi 3.5" 640x480 TFT LCD panel + - gameforce,chi-panel # Powkiddy RGB10MAX3 5.0" 720x1280 TFT LCD panel - powkiddy,rgb10max3-panel # Powkiddy RGB30 3.0" 720x720 TFT LCD panel From 4c4f33be7e4d476566246e7166c54ef175287e00 Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Mon, 25 Mar 2024 08:49:57 -0500 Subject: [PATCH 06/32] drm/panel: st7703: Add GameForce Chi Panel Support The GameForce Chi is a handheld device with a 3.5" 640x480 ST7703 based display panel. Signed-off-by: Chris Morgan Acked-by: Jessica Zhang Link: https://lore.kernel.org/r/20240325134959.11807-4-macroalpha82@gmail.com Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20240325134959.11807-4-macroalpha82@gmail.com --- drivers/gpu/drm/panel/panel-sitronix-st7703.c | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c b/drivers/gpu/drm/panel/panel-sitronix-st7703.c index a3e142f156d5..7d8302cca091 100644 --- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c +++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c @@ -612,6 +612,92 @@ static const struct st7703_panel_desc rgb10max3_panel_desc = { .init_sequence = rgb10max3_panel_init_sequence, }; +static int gameforcechi_init_sequence(struct st7703 *ctx) +{ + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); + + /* + * Init sequence was supplied by the panel vendor. Panel will not + * respond to commands until it is brought out of sleep mode first. + */ + + mipi_dsi_dcs_exit_sleep_mode(dsi); + msleep(250); + + mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83); + mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI, 0x31, 0x81, 0x05, 0xf9, + 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x44, 0x25, 0x00, 0x91, 0x0a, 0x00, + 0x00, 0x02, 0x4f, 0xd1, 0x00, 0x00, 0x37); + mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT, 0x25); + mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00); + mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF, 0x0c, 0x10, 0x0a, + 0x50, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00); + mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50, + 0x00, 0x00, 0x08, 0x70, 0x00); + mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x46); + mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0b); + mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80); + mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP, 0x00, 0x13, 0xf0); + mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b, + 0x03, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, + 0xc0, 0x10); + mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER, 0x53, 0x00, 0x1e, + 0x1e, 0x77, 0xe1, 0xcc, 0xdd, 0x67, 0x77, 0x33, + 0x33); + mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP, 0x10, 0x10); + mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM, 0x6c, 0x7c); + mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1, 0x08, 0x00, 0x0e, 0x00, + 0x00, 0xb0, 0xb1, 0x11, 0x31, 0x23, 0x28, 0x10, + 0xb0, 0xb1, 0x27, 0x08, 0x00, 0x04, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, + 0x88, 0x88, 0xba, 0x60, 0x24, 0x08, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0xba, 0x71, 0x35, + 0x18, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00); + mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2, 0x97, 0x0a, 0x82, 0x02, + 0x13, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x88, 0xba, 0x17, 0x53, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x81, 0x88, 0xba, 0x06, 0x42, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x10, + 0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00); + mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA, 0x00, 0x07, 0x0b, + 0x27, 0x2d, 0x3f, 0x3b, 0x37, 0x05, 0x0a, 0x0b, + 0x0f, 0x11, 0x0f, 0x12, 0x12, 0x18, 0x00, 0x07, + 0x0b, 0x27, 0x2d, 0x3f, 0x3b, 0x37, 0x05, 0xa0, + 0x0b, 0x0f, 0x11, 0x0f, 0x12, 0x12, 0x18); + + return 0; +} + +static const struct drm_display_mode gameforcechi_mode = { + .hdisplay = 640, + .hsync_start = 640 + 40, + .hsync_end = 640 + 40 + 2, + .htotal = 640 + 40 + 2 + 80, + .vdisplay = 480, + .vsync_start = 480 + 17, + .vsync_end = 480 + 17 + 5, + .vtotal = 480 + 17 + 5 + 13, + .clock = 23546, + .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, + .width_mm = 71, + .height_mm = 53, +}; + +static const struct st7703_panel_desc gameforcechi_desc = { + .mode = &gameforcechi_mode, + .lanes = 2, + .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | + MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_MODE_LPM, + .format = MIPI_DSI_FMT_RGB888, + .init_sequence = gameforcechi_init_sequence, +}; + static int st7703_enable(struct drm_panel *panel) { struct st7703 *ctx = panel_to_st7703(panel); @@ -887,6 +973,7 @@ static void st7703_remove(struct mipi_dsi_device *dsi) static const struct of_device_id st7703_of_match[] = { { .compatible = "anbernic,rg353v-panel-v2", .data = &rg353v2_desc }, + { .compatible = "gameforce,chi-panel", .data = &gameforcechi_desc }, { .compatible = "powkiddy,rgb10max3-panel", .data = &rgb10max3_panel_desc }, { .compatible = "powkiddy,rgb30-panel", .data = &rgb30panel_desc }, { .compatible = "rocktech,jh057n00900", .data = &jh057n00900_panel_desc }, From 11f0275cc1b90b4b9bf37a5ebc27c0a9b2451b4e Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Tue, 26 Mar 2024 12:12:03 +0100 Subject: [PATCH 07/32] drm/panthor: Fix IO-page mmap() for 32-bit userspace on 64-bit kernel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When mapping an IO region, the pseudo-file offset is dependent on the userspace architecture. panthor_device_mmio_offset() abstracts that away for us by turning a userspace MMIO offset into its kernel equivalent, but we were not updating vm_area_struct::vm_pgoff accordingly, leading us to attach the MMIO region to the wrong file offset. This has implications when we start mixing 64 bit and 32 bit apps, but that's only really a problem when we start having more that 2^43 bytes of memory allocated, which is very unlikely to happen. What's more problematic is the fact this turns our unmap_mapping_range(DRM_PANTHOR_USER_MMIO_OFFSET) calls, which are supposed to kill the MMIO mapping when entering suspend, into NOPs. Which means we either keep the dummy flush_id mapping active at all times, or we risk a BUS_FAULT if the MMIO region was mapped, and the GPU is suspended after that. Solve that by patching vm_pgoff early in panthor_mmap(). With this in place, we no longer need the panthor_device_mmio_offset() helper. v3: - No changes v2: - Kill panthor_device_mmio_offset() Fixes: 5fe909cae118 ("drm/panthor: Add the device logical block") Reported-by: Adrián Larumbe Reported-by: Lukas F. Hartmann Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/10835 Signed-off-by: Boris Brezillon Reviewed-by: Steven Price Reviewed-by: Liviu Dudau Link: https://patchwork.freedesktop.org/patch/msgid/20240326111205.510019-1-boris.brezillon@collabora.com --- drivers/gpu/drm/panthor/panthor_device.c | 8 ++++---- drivers/gpu/drm/panthor/panthor_device.h | 24 ------------------------ drivers/gpu/drm/panthor/panthor_drv.c | 17 ++++++++++++++++- 3 files changed, 20 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/panthor/panthor_device.c index 8b00f342d1b1..75276cbeba20 100644 --- a/drivers/gpu/drm/panthor/panthor_device.c +++ b/drivers/gpu/drm/panthor/panthor_device.c @@ -348,7 +348,7 @@ static vm_fault_t panthor_mmio_vm_fault(struct vm_fault *vmf) { struct vm_area_struct *vma = vmf->vma; struct panthor_device *ptdev = vma->vm_private_data; - u64 id = (u64)vma->vm_pgoff << PAGE_SHIFT; + u64 offset = (u64)vma->vm_pgoff << PAGE_SHIFT; unsigned long pfn; pgprot_t pgprot; vm_fault_t ret; @@ -361,7 +361,7 @@ static vm_fault_t panthor_mmio_vm_fault(struct vm_fault *vmf) mutex_lock(&ptdev->pm.mmio_lock); active = atomic_read(&ptdev->pm.state) == PANTHOR_DEVICE_PM_STATE_ACTIVE; - switch (panthor_device_mmio_offset(id)) { + switch (offset) { case DRM_PANTHOR_USER_FLUSH_ID_MMIO_OFFSET: if (active) pfn = __phys_to_pfn(ptdev->phys_addr + CSF_GPU_LATEST_FLUSH_ID); @@ -392,9 +392,9 @@ static const struct vm_operations_struct panthor_mmio_vm_ops = { int panthor_device_mmap_io(struct panthor_device *ptdev, struct vm_area_struct *vma) { - u64 id = (u64)vma->vm_pgoff << PAGE_SHIFT; + u64 offset = (u64)vma->vm_pgoff << PAGE_SHIFT; - switch (panthor_device_mmio_offset(id)) { + switch (offset) { case DRM_PANTHOR_USER_FLUSH_ID_MMIO_OFFSET: if (vma->vm_end - vma->vm_start != PAGE_SIZE || (vma->vm_flags & (VM_WRITE | VM_EXEC))) diff --git a/drivers/gpu/drm/panthor/panthor_device.h b/drivers/gpu/drm/panthor/panthor_device.h index c84c27dcc92c..b68e8821d219 100644 --- a/drivers/gpu/drm/panthor/panthor_device.h +++ b/drivers/gpu/drm/panthor/panthor_device.h @@ -365,30 +365,6 @@ static int panthor_request_ ## __name ## _irq(struct panthor_device *ptdev, \ pirq); \ } -/** - * panthor_device_mmio_offset() - Turn a user MMIO offset into a kernel one - * @offset: Offset to convert. - * - * With 32-bit systems being limited by the 32-bit representation of mmap2's - * pgoffset field, we need to make the MMIO offset arch specific. This function - * converts a user MMIO offset into something the kernel driver understands. - * - * If the kernel and userspace architecture match, the offset is unchanged. If - * the kernel is 64-bit and userspace is 32-bit, the offset is adjusted to match - * 64-bit offsets. 32-bit kernel with 64-bit userspace is impossible. - * - * Return: Adjusted offset. - */ -static inline u64 panthor_device_mmio_offset(u64 offset) -{ -#ifdef CONFIG_ARM64 - if (test_tsk_thread_flag(current, TIF_32BIT)) - offset += DRM_PANTHOR_USER_MMIO_OFFSET_64BIT - DRM_PANTHOR_USER_MMIO_OFFSET_32BIT; -#endif - - return offset; -} - extern struct workqueue_struct *panthor_cleanup_wq; #endif diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/panthor/panthor_drv.c index 11b3ccd58f85..730dd0c69cb8 100644 --- a/drivers/gpu/drm/panthor/panthor_drv.c +++ b/drivers/gpu/drm/panthor/panthor_drv.c @@ -1327,7 +1327,22 @@ static int panthor_mmap(struct file *filp, struct vm_area_struct *vma) if (!drm_dev_enter(file->minor->dev, &cookie)) return -ENODEV; - if (panthor_device_mmio_offset(offset) >= DRM_PANTHOR_USER_MMIO_OFFSET) +#ifdef CONFIG_ARM64 + /* + * With 32-bit systems being limited by the 32-bit representation of + * mmap2's pgoffset field, we need to make the MMIO offset arch + * specific. This converts a user MMIO offset into something the kernel + * driver understands. + */ + if (test_tsk_thread_flag(current, TIF_32BIT) && + offset >= DRM_PANTHOR_USER_MMIO_OFFSET_32BIT) { + offset += DRM_PANTHOR_USER_MMIO_OFFSET_64BIT - + DRM_PANTHOR_USER_MMIO_OFFSET_32BIT; + vma->vm_pgoff = offset >> PAGE_SHIFT; + } +#endif + + if (offset >= DRM_PANTHOR_USER_MMIO_OFFSET) ret = panthor_device_mmap_io(ptdev, vma); else ret = drm_gem_mmap(filp, vma); From 1de434e0b2757061b09b347264f1ff5bdf996e58 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Tue, 26 Mar 2024 12:12:04 +0100 Subject: [PATCH 08/32] drm/panthor: Fix ordering in _irq_suspend() Make sure we set suspended=true last to avoid generating an irq storm in the unlikely case where an IRQ happens between the suspended=true assignment and the _INT_MASK update. We also move the mask=0 assignment before writing to the _INT_MASK register to prevent the thread handler from unmasking the interrupt behind our back. This means we might lose events if there were some pending when we get to suspend the IRQ, but that's fine. The synchronize_irq() we have in the _irq_suspend() path was not there to make sure all IRQs are processed, just to make sure we don't have registers accesses coming from the irq handlers after _irq_suspend() has been called. If there's a need to have all pending IRQs processed, it should happen before _irq_suspend() is called. v3: - Add Steve's R-b v2: - New patch Fixes: 5fe909cae118 ("drm/panthor: Add the device logical block") Reported-by: Steven Price Signed-off-by: Boris Brezillon Reviewed-by: Steven Price Acked-by: Liviu Dudau Link: https://patchwork.freedesktop.org/patch/msgid/20240326111205.510019-2-boris.brezillon@collabora.com --- drivers/gpu/drm/panthor/panthor_device.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/panthor/panthor_device.h b/drivers/gpu/drm/panthor/panthor_device.h index b68e8821d219..8ced04dad3a8 100644 --- a/drivers/gpu/drm/panthor/panthor_device.h +++ b/drivers/gpu/drm/panthor/panthor_device.h @@ -325,7 +325,7 @@ static inline void panthor_ ## __name ## _irq_suspend(struct panthor_irq *pirq) { \ int cookie; \ \ - atomic_set(&pirq->suspended, true); \ + pirq->mask = 0; \ \ if (drm_dev_enter(&pirq->ptdev->base, &cookie)) { \ gpu_write(pirq->ptdev, __reg_prefix ## _INT_MASK, 0); \ @@ -333,7 +333,7 @@ static inline void panthor_ ## __name ## _irq_suspend(struct panthor_irq *pirq) drm_dev_exit(cookie); \ } \ \ - pirq->mask = 0; \ + atomic_set(&pirq->suspended, true); \ } \ \ static inline void panthor_ ## __name ## _irq_resume(struct panthor_irq *pirq, u32 mask) \ From 962f88b9c91647f3ff4a0d3709662641baed5164 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Tue, 26 Mar 2024 12:12:05 +0100 Subject: [PATCH 09/32] drm/panthor: Drop the dev_enter/exit() sections in _irq_suspend/resume() There's no reason for _irq_suspend/resume() to be called after the device has been unplugged, and keeping this dev_enter/exit() section in _irq_suspend() is turns _irq_suspend() into a NOP when called from the _unplug() functions, which we don't want. v3: - New patch Fixes: 5fe909cae118 ("drm/panthor: Add the device logical block") Signed-off-by: Boris Brezillon Reviewed-by: Liviu Dudau Reviewed-by: Steven Price Link: https://patchwork.freedesktop.org/patch/msgid/20240326111205.510019-3-boris.brezillon@collabora.com --- drivers/gpu/drm/panthor/panthor_device.h | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/panthor/panthor_device.h b/drivers/gpu/drm/panthor/panthor_device.h index 8ced04dad3a8..dc3e9c666b5b 100644 --- a/drivers/gpu/drm/panthor/panthor_device.h +++ b/drivers/gpu/drm/panthor/panthor_device.h @@ -326,13 +326,8 @@ static inline void panthor_ ## __name ## _irq_suspend(struct panthor_irq *pirq) int cookie; \ \ pirq->mask = 0; \ - \ - if (drm_dev_enter(&pirq->ptdev->base, &cookie)) { \ - gpu_write(pirq->ptdev, __reg_prefix ## _INT_MASK, 0); \ - synchronize_irq(pirq->irq); \ - drm_dev_exit(cookie); \ - } \ - \ + gpu_write(pirq->ptdev, __reg_prefix ## _INT_MASK, 0); \ + synchronize_irq(pirq->irq); \ atomic_set(&pirq->suspended, true); \ } \ \ @@ -342,12 +337,8 @@ static inline void panthor_ ## __name ## _irq_resume(struct panthor_irq *pirq, u \ atomic_set(&pirq->suspended, false); \ pirq->mask = mask; \ - \ - if (drm_dev_enter(&pirq->ptdev->base, &cookie)) { \ - gpu_write(pirq->ptdev, __reg_prefix ## _INT_CLEAR, mask); \ - gpu_write(pirq->ptdev, __reg_prefix ## _INT_MASK, mask); \ - drm_dev_exit(cookie); \ - } \ + gpu_write(pirq->ptdev, __reg_prefix ## _INT_CLEAR, mask); \ + gpu_write(pirq->ptdev, __reg_prefix ## _INT_MASK, mask); \ } \ \ static int panthor_request_ ## __name ## _irq(struct panthor_device *ptdev, \ From d76653c32dd16d78e56208b4819134e766257c06 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Thu, 28 Mar 2024 09:22:07 -0700 Subject: [PATCH 10/32] drm/panthor: Fix clang -Wunused-but-set-variable in tick_ctx_apply() Clang warns (or errors with CONFIG_WERROR): drivers/gpu/drm/panthor/panthor_sched.c:2048:6: error: variable 'csg_mod_mask' set but not used [-Werror,-Wunused-but-set-variable] 2048 | u32 csg_mod_mask = 0, free_csg_slots = 0; | ^ 1 error generated. The variable is an artifact left over from refactoring that occurred during the development of the initial series for this driver. Remove it to resolve the warning. Fixes: de8548813824 ("drm/panthor: Add the scheduler logical block") Signed-off-by: Nathan Chancellor Reviewed-by: Steven Price Reviewed-by: Justin Stitt Signed-off-by: Boris Brezillon Link: https://patchwork.freedesktop.org/patch/msgid/20240328-panthor-drop-csg_mod_mask-v1-1-5a80be3df581@kernel.org --- drivers/gpu/drm/panthor/panthor_sched.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c index 5f7803b6fc48..e5a710f190d2 100644 --- a/drivers/gpu/drm/panthor/panthor_sched.c +++ b/drivers/gpu/drm/panthor/panthor_sched.c @@ -2045,7 +2045,7 @@ tick_ctx_apply(struct panthor_scheduler *sched, struct panthor_sched_tick_ctx *c struct panthor_device *ptdev = sched->ptdev; struct panthor_csg_slot *csg_slot; int prio, new_csg_prio = MAX_CSG_PRIO, i; - u32 csg_mod_mask = 0, free_csg_slots = 0; + u32 free_csg_slots = 0; struct panthor_csg_slots_upd_ctx upd_ctx; int ret; @@ -2139,7 +2139,6 @@ tick_ctx_apply(struct panthor_scheduler *sched, struct panthor_sched_tick_ctx *c csg_iface = panthor_fw_get_csg_iface(ptdev, csg_id); csg_slot = &sched->csg_slots[csg_id]; - csg_mod_mask |= BIT(csg_id); group_bind_locked(group, csg_id); csg_slot_prog_locked(ptdev, csg_id, new_csg_prio--); csgs_upd_ctx_queue_reqs(ptdev, &upd_ctx, csg_id, From 8463b66b41add540ef99f5950f42fa10d1a01023 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 25 Mar 2024 21:06:46 +0100 Subject: [PATCH 11/32] drm/ast: Include where necessary Include to get of_property_read_u32() in the source files that need it. Avoids the proxy include via . Signed-off-by: Thomas Zimmermann Reviewed-by: Sui Jingfeng Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20240325200855.21150-2-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_drv.c | 1 + drivers/gpu/drm/ast/ast_main.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index 90bcb1eb9cd9..f8c49ba68e78 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -27,6 +27,7 @@ */ #include +#include #include #include diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 2f3ad5f949fc..0637abb70361 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -26,6 +26,7 @@ * Authors: Dave Airlie */ +#include #include #include From d66cdb638a49a47e616456ffbd1ec4722bc8fda6 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 25 Mar 2024 21:06:47 +0100 Subject: [PATCH 12/32] drm/ast: Fail probing if DDC channel could not be initialized Expect the hardware to provide a DDC channel. Fail probing if its initialization fails. Failing to initialize the DDC indicates a larger problem, so there's no point in continuing. v4: * give a rational in the commit message Signed-off-by: Thomas Zimmermann Reviewed-by: Patrik Jakobsson Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20240325200855.21150-3-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_drv.h | 2 -- drivers/gpu/drm/ast/ast_i2c.c | 7 +++-- drivers/gpu/drm/ast/ast_mode.c | 52 +++++++++++++--------------------- 3 files changed, 24 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 3be5ccf1f5f4..cb0e4f332be8 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -160,7 +160,6 @@ struct ast_i2c_chan { struct ast_vga_connector { struct drm_connector base; - struct ast_i2c_chan *i2c; }; static inline struct ast_vga_connector * @@ -171,7 +170,6 @@ to_ast_vga_connector(struct drm_connector *connector) struct ast_sil164_connector { struct drm_connector base; - struct ast_i2c_chan *i2c; }; static inline struct ast_sil164_connector * diff --git a/drivers/gpu/drm/ast/ast_i2c.c b/drivers/gpu/drm/ast/ast_i2c.c index e5d3f7121de4..c3046223a491 100644 --- a/drivers/gpu/drm/ast/ast_i2c.c +++ b/drivers/gpu/drm/ast/ast_i2c.c @@ -117,7 +117,7 @@ struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev) i2c = kzalloc(sizeof(struct ast_i2c_chan), GFP_KERNEL); if (!i2c) - return NULL; + return ERR_PTR(-ENOMEM); i2c->adapter.owner = THIS_MODULE; i2c->adapter.dev.parent = dev->dev; @@ -142,10 +142,11 @@ struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev) ret = drmm_add_action_or_reset(dev, ast_i2c_release, i2c); if (ret) - return NULL; + return ERR_PTR(ret); + return i2c; out_kfree: kfree(i2c); - return NULL; + return ERR_PTR(ret); } diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index a718646a66b8..38c31a7283a6 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -1345,22 +1345,18 @@ static int ast_crtc_init(struct drm_device *dev) static int ast_vga_connector_helper_get_modes(struct drm_connector *connector) { - struct ast_vga_connector *ast_vga_connector = to_ast_vga_connector(connector); struct drm_device *dev = connector->dev; struct ast_device *ast = to_ast_device(dev); struct edid *edid; int count; - if (!ast_vga_connector->i2c) - goto err_drm_connector_update_edid_property; - /* * Protect access to I/O registers from concurrent modesetting * by acquiring the I/O-register lock. */ mutex_lock(&ast->modeset_lock); - edid = drm_get_edid(connector, &ast_vga_connector->i2c->adapter); + edid = drm_get_edid(connector, connector->ddc); if (!edid) goto err_mutex_unlock; @@ -1373,7 +1369,6 @@ static int ast_vga_connector_helper_get_modes(struct drm_connector *connector) err_mutex_unlock: mutex_unlock(&ast->modeset_lock); -err_drm_connector_update_edid_property: drm_connector_update_edid_property(connector, NULL); return 0; } @@ -1394,19 +1389,18 @@ static int ast_vga_connector_init(struct drm_device *dev, struct ast_vga_connector *ast_vga_connector) { struct drm_connector *connector = &ast_vga_connector->base; + struct ast_i2c_chan *i2c; int ret; - ast_vga_connector->i2c = ast_i2c_create(dev); - if (!ast_vga_connector->i2c) - drm_err(dev, "failed to add ddc bus for connector\n"); + i2c = ast_i2c_create(dev); + if (IS_ERR(i2c)) { + ret = PTR_ERR(i2c); + drm_err(dev, "failed to add ddc bus for connector; ret=%d\n", ret); + return ret; + } - if (ast_vga_connector->i2c) - ret = drm_connector_init_with_ddc(dev, connector, &ast_vga_connector_funcs, - DRM_MODE_CONNECTOR_VGA, - &ast_vga_connector->i2c->adapter); - else - ret = drm_connector_init(dev, connector, &ast_vga_connector_funcs, - DRM_MODE_CONNECTOR_VGA); + ret = drm_connector_init_with_ddc(dev, connector, &ast_vga_connector_funcs, + DRM_MODE_CONNECTOR_VGA, &i2c->adapter); if (ret) return ret; @@ -1451,22 +1445,18 @@ static int ast_vga_output_init(struct ast_device *ast) static int ast_sil164_connector_helper_get_modes(struct drm_connector *connector) { - struct ast_sil164_connector *ast_sil164_connector = to_ast_sil164_connector(connector); struct drm_device *dev = connector->dev; struct ast_device *ast = to_ast_device(dev); struct edid *edid; int count; - if (!ast_sil164_connector->i2c) - goto err_drm_connector_update_edid_property; - /* * Protect access to I/O registers from concurrent modesetting * by acquiring the I/O-register lock. */ mutex_lock(&ast->modeset_lock); - edid = drm_get_edid(connector, &ast_sil164_connector->i2c->adapter); + edid = drm_get_edid(connector, connector->ddc); if (!edid) goto err_mutex_unlock; @@ -1479,7 +1469,6 @@ static int ast_sil164_connector_helper_get_modes(struct drm_connector *connector err_mutex_unlock: mutex_unlock(&ast->modeset_lock); -err_drm_connector_update_edid_property: drm_connector_update_edid_property(connector, NULL); return 0; } @@ -1500,19 +1489,18 @@ static int ast_sil164_connector_init(struct drm_device *dev, struct ast_sil164_connector *ast_sil164_connector) { struct drm_connector *connector = &ast_sil164_connector->base; + struct ast_i2c_chan *i2c; int ret; - ast_sil164_connector->i2c = ast_i2c_create(dev); - if (!ast_sil164_connector->i2c) - drm_err(dev, "failed to add ddc bus for connector\n"); + i2c = ast_i2c_create(dev); + if (IS_ERR(i2c)) { + ret = PTR_ERR(i2c); + drm_err(dev, "failed to add ddc bus for connector; ret=%d\n", ret); + return ret; + } - if (ast_sil164_connector->i2c) - ret = drm_connector_init_with_ddc(dev, connector, &ast_sil164_connector_funcs, - DRM_MODE_CONNECTOR_DVII, - &ast_sil164_connector->i2c->adapter); - else - ret = drm_connector_init(dev, connector, &ast_sil164_connector_funcs, - DRM_MODE_CONNECTOR_DVII); + ret = drm_connector_init_with_ddc(dev, connector, &ast_sil164_connector_funcs, + DRM_MODE_CONNECTOR_DVII, &i2c->adapter); if (ret) return ret; From c0af492c872b949cf3e8b91ef66094bc5f81e181 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 25 Mar 2024 21:06:48 +0100 Subject: [PATCH 13/32] drm/ast: Remove struct ast_{vga,sil165}_connector Both, struct ast_vga_connector and struct ast_sil164_connector, are now wrappers around struct drm_connector. Remove them. Signed-off-by: Thomas Zimmermann Reviewed-by: Patrik Jakobsson Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20240325200855.21150-4-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_drv.h | 24 ++---------------------- drivers/gpu/drm/ast/ast_mode.c | 22 ++++++++-------------- 2 files changed, 10 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index cb0e4f332be8..12ad1c0fe151 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -158,26 +158,6 @@ struct ast_i2c_chan { struct i2c_algo_bit_data bit; }; -struct ast_vga_connector { - struct drm_connector base; -}; - -static inline struct ast_vga_connector * -to_ast_vga_connector(struct drm_connector *connector) -{ - return container_of(connector, struct ast_vga_connector, base); -} - -struct ast_sil164_connector { - struct drm_connector base; -}; - -static inline struct ast_sil164_connector * -to_ast_sil164_connector(struct drm_connector *connector) -{ - return container_of(connector, struct ast_sil164_connector, base); -} - struct ast_bmc_connector { struct drm_connector base; struct drm_connector *physical_connector; @@ -220,11 +200,11 @@ struct ast_device { struct { struct { struct drm_encoder encoder; - struct ast_vga_connector vga_connector; + struct drm_connector connector; } vga; struct { struct drm_encoder encoder; - struct ast_sil164_connector sil164_connector; + struct drm_connector connector; } sil164; struct { struct drm_encoder encoder; diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 38c31a7283a6..cbda04fca710 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -1385,10 +1385,8 @@ static const struct drm_connector_funcs ast_vga_connector_funcs = { .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; -static int ast_vga_connector_init(struct drm_device *dev, - struct ast_vga_connector *ast_vga_connector) +static int ast_vga_connector_init(struct drm_device *dev, struct drm_connector *connector) { - struct drm_connector *connector = &ast_vga_connector->base; struct ast_i2c_chan *i2c; int ret; @@ -1419,8 +1417,7 @@ static int ast_vga_output_init(struct ast_device *ast) struct drm_device *dev = &ast->base; struct drm_crtc *crtc = &ast->crtc; struct drm_encoder *encoder = &ast->output.vga.encoder; - struct ast_vga_connector *ast_vga_connector = &ast->output.vga.vga_connector; - struct drm_connector *connector = &ast_vga_connector->base; + struct drm_connector *connector = &ast->output.vga.connector; int ret; ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_DAC); @@ -1428,7 +1425,7 @@ static int ast_vga_output_init(struct ast_device *ast) return ret; encoder->possible_crtcs = drm_crtc_mask(crtc); - ret = ast_vga_connector_init(dev, ast_vga_connector); + ret = ast_vga_connector_init(dev, connector); if (ret) return ret; @@ -1485,10 +1482,8 @@ static const struct drm_connector_funcs ast_sil164_connector_funcs = { .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; -static int ast_sil164_connector_init(struct drm_device *dev, - struct ast_sil164_connector *ast_sil164_connector) +static int ast_sil164_connector_init(struct drm_device *dev, struct drm_connector *connector) { - struct drm_connector *connector = &ast_sil164_connector->base; struct ast_i2c_chan *i2c; int ret; @@ -1519,8 +1514,7 @@ static int ast_sil164_output_init(struct ast_device *ast) struct drm_device *dev = &ast->base; struct drm_crtc *crtc = &ast->crtc; struct drm_encoder *encoder = &ast->output.sil164.encoder; - struct ast_sil164_connector *ast_sil164_connector = &ast->output.sil164.sil164_connector; - struct drm_connector *connector = &ast_sil164_connector->base; + struct drm_connector *connector = &ast->output.sil164.connector; int ret; ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS); @@ -1528,7 +1522,7 @@ static int ast_sil164_output_init(struct ast_device *ast) return ret; encoder->possible_crtcs = drm_crtc_mask(crtc); - ret = ast_sil164_connector_init(dev, ast_sil164_connector); + ret = ast_sil164_connector_init(dev, connector); if (ret) return ret; @@ -1940,13 +1934,13 @@ int ast_mode_config_init(struct ast_device *ast) ret = ast_vga_output_init(ast); if (ret) return ret; - physical_connector = &ast->output.vga.vga_connector.base; + physical_connector = &ast->output.vga.connector; } if (ast->tx_chip_types & AST_TX_SIL164_BIT) { ret = ast_sil164_output_init(ast); if (ret) return ret; - physical_connector = &ast->output.sil164.sil164_connector.base; + physical_connector = &ast->output.sil164.connector; } if (ast->tx_chip_types & AST_TX_DP501_BIT) { ret = ast_dp501_output_init(ast); From e14ab3037383f4e3d026e2aea1ad53644a3735ed Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 25 Mar 2024 21:06:49 +0100 Subject: [PATCH 14/32] drm/ast: Allocate instance of struct ast_i2c_chan with managed helpers Replace kzalloc() with drmm_kzalloc() and thereby put the release of the I2C instance into a separate action. Avoids explicit error roll- back in ast_i2c_chan_create(). No functional changes. Signed-off-by: Thomas Zimmermann Reviewed-by: Sui Jingfeng Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20240325200855.21150-5-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_i2c.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_i2c.c b/drivers/gpu/drm/ast/ast_i2c.c index c3046223a491..dc28a5cbb1c2 100644 --- a/drivers/gpu/drm/ast/ast_i2c.c +++ b/drivers/gpu/drm/ast/ast_i2c.c @@ -107,7 +107,6 @@ static void ast_i2c_release(struct drm_device *dev, void *res) struct ast_i2c_chan *i2c = res; i2c_del_adapter(&i2c->adapter); - kfree(i2c); } struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev) @@ -115,7 +114,7 @@ struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev) struct ast_i2c_chan *i2c; int ret; - i2c = kzalloc(sizeof(struct ast_i2c_chan), GFP_KERNEL); + i2c = drmm_kzalloc(dev->dev, sizeof(*i2c), GFP_KERNEL); if (!i2c) return ERR_PTR(-ENOMEM); @@ -137,7 +136,7 @@ struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev) ret = i2c_bit_add_bus(&i2c->adapter); if (ret) { drm_err(dev, "Failed to register bit i2c\n"); - goto out_kfree; + return ERR_PTR(ret); } ret = drmm_add_action_or_reset(dev, ast_i2c_release, i2c); @@ -145,8 +144,4 @@ struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev) return ERR_PTR(ret); return i2c; - -out_kfree: - kfree(i2c); - return ERR_PTR(ret); } From 0a7f04b433fc7c77d8c03eb6b2f32196a3d9b0c5 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 25 Mar 2024 21:06:50 +0100 Subject: [PATCH 15/32] drm/ast: Move DDC code to ast_ddc.{c,h} Rename ast_i2c.c to ast_ddc.c and move its interface into the new header ast_ddc.h. Update all include statements as necessary and change the adapter name to 'AST DDC bus'. This avoids including I2C headers in the driver's main header file, which doesn't need them. Renaming files to _ddc indicates that the code is about the DDC. I2C is really just the underlying bus here. Signed-off-by: Thomas Zimmermann Reviewed-by: Sui Jingfeng Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20240325200855.21150-6-tzimmermann@suse.de --- drivers/gpu/drm/ast/Makefile | 10 +++++++++- drivers/gpu/drm/ast/{ast_i2c.c => ast_ddc.c} | 4 ++-- drivers/gpu/drm/ast/ast_ddc.h | 19 +++++++++++++++++++ drivers/gpu/drm/ast/ast_drv.h | 13 +------------ drivers/gpu/drm/ast/ast_mode.c | 1 + 5 files changed, 32 insertions(+), 15 deletions(-) rename drivers/gpu/drm/ast/{ast_i2c.c => ast_ddc.c} (97%) create mode 100644 drivers/gpu/drm/ast/ast_ddc.h diff --git a/drivers/gpu/drm/ast/Makefile b/drivers/gpu/drm/ast/Makefile index 5a53ce51fb24..d794c076bc24 100644 --- a/drivers/gpu/drm/ast/Makefile +++ b/drivers/gpu/drm/ast/Makefile @@ -3,6 +3,14 @@ # Makefile for the drm device driver. This driver provides support for the # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. -ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o ast_post.o ast_dp501.o ast_dp.o +ast-y := \ + ast_ddc.o \ + ast_dp501.o \ + ast_dp.o \ + ast_drv.o \ + ast_main.o \ + ast_mm.o \ + ast_mode.o \ + ast_post.o obj-$(CONFIG_DRM_AST) := ast.o diff --git a/drivers/gpu/drm/ast/ast_i2c.c b/drivers/gpu/drm/ast/ast_ddc.c similarity index 97% rename from drivers/gpu/drm/ast/ast_i2c.c rename to drivers/gpu/drm/ast/ast_ddc.c index dc28a5cbb1c2..df604b4e9673 100644 --- a/drivers/gpu/drm/ast/ast_i2c.c +++ b/drivers/gpu/drm/ast/ast_ddc.c @@ -24,6 +24,7 @@ #include #include +#include "ast_ddc.h" #include "ast_drv.h" static void ast_i2c_setsda(void *i2c_priv, int data) @@ -122,8 +123,7 @@ struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev) i2c->adapter.dev.parent = dev->dev; i2c->dev = dev; i2c_set_adapdata(&i2c->adapter, i2c); - snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), - "AST i2c bit bus"); + snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), "AST DDC bus"); i2c->adapter.algo_data = &i2c->bit; i2c->bit.udelay = 20; diff --git a/drivers/gpu/drm/ast/ast_ddc.h b/drivers/gpu/drm/ast/ast_ddc.h new file mode 100644 index 000000000000..244666fd6c53 --- /dev/null +++ b/drivers/gpu/drm/ast/ast_ddc.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: MIT */ + +#ifndef __AST_DDC_H__ +#define __AST_DDC_H__ + +#include +#include + +struct drm_device; + +struct ast_i2c_chan { + struct i2c_adapter adapter; + struct drm_device *dev; + struct i2c_algo_bit_data bit; +}; + +struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev); + +#endif diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 12ad1c0fe151..ba3d86973995 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -28,8 +28,6 @@ #ifndef __AST_DRV_H__ #define __AST_DRV_H__ -#include -#include #include #include @@ -149,15 +147,9 @@ static inline struct ast_plane *to_ast_plane(struct drm_plane *plane) } /* - * Connector with i2c channel + * BMC */ -struct ast_i2c_chan { - struct i2c_adapter adapter; - struct drm_device *dev; - struct i2c_algo_bit_data bit; -}; - struct ast_bmc_connector { struct drm_connector base; struct drm_connector *physical_connector; @@ -476,9 +468,6 @@ bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata); u8 ast_get_dp501_max_clk(struct drm_device *dev); void ast_init_3rdtx(struct drm_device *dev); -/* ast_i2c.c */ -struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev); - /* aspeed DP */ bool ast_astdp_is_connected(struct ast_device *ast); int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata); diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index cbda04fca710..bdef2160726e 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -46,6 +46,7 @@ #include #include +#include "ast_ddc.h" #include "ast_drv.h" #include "ast_tables.h" From 42f4980da575ffbb1ff73bd8ffdd79662a23e8f6 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 25 Mar 2024 21:06:51 +0100 Subject: [PATCH 16/32] drm/ast: Rename struct ast_i2c_chan to struct ast_ddc The struct struct ast_i2c_chan represents the Display Data Channel (DDC); I2C is the underlying bus. Rename the structure, the variables and the helper ast_i2c_create() to ddc-like terms. No functional changes. Signed-off-by: Thomas Zimmermann Reviewed-by: Sui Jingfeng Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20240325200855.21150-7-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_ddc.c | 67 ++++++++++++++++++---------------- drivers/gpu/drm/ast/ast_ddc.h | 4 +- drivers/gpu/drm/ast/ast_mode.c | 24 ++++++------ 3 files changed, 50 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_ddc.c b/drivers/gpu/drm/ast/ast_ddc.c index df604b4e9673..c0e5d03c028d 100644 --- a/drivers/gpu/drm/ast/ast_ddc.c +++ b/drivers/gpu/drm/ast/ast_ddc.c @@ -29,8 +29,8 @@ static void ast_i2c_setsda(void *i2c_priv, int data) { - struct ast_i2c_chan *i2c = i2c_priv; - struct ast_device *ast = to_ast_device(i2c->dev); + struct ast_ddc *ddc = i2c_priv; + struct ast_device *ast = to_ast_device(ddc->dev); int i; u8 ujcrb7, jtemp; @@ -45,8 +45,8 @@ static void ast_i2c_setsda(void *i2c_priv, int data) static void ast_i2c_setscl(void *i2c_priv, int clock) { - struct ast_i2c_chan *i2c = i2c_priv; - struct ast_device *ast = to_ast_device(i2c->dev); + struct ast_ddc *ddc = i2c_priv; + struct ast_device *ast = to_ast_device(ddc->dev); int i; u8 ujcrb7, jtemp; @@ -61,8 +61,8 @@ static void ast_i2c_setscl(void *i2c_priv, int clock) static int ast_i2c_getsda(void *i2c_priv) { - struct ast_i2c_chan *i2c = i2c_priv; - struct ast_device *ast = to_ast_device(i2c->dev); + struct ast_ddc *ddc = i2c_priv; + struct ast_device *ast = to_ast_device(ddc->dev); uint32_t val, val2, count, pass; count = 0; @@ -83,8 +83,8 @@ static int ast_i2c_getsda(void *i2c_priv) static int ast_i2c_getscl(void *i2c_priv) { - struct ast_i2c_chan *i2c = i2c_priv; - struct ast_device *ast = to_ast_device(i2c->dev); + struct ast_ddc *ddc = i2c_priv; + struct ast_device *ast = to_ast_device(ddc->dev); uint32_t val, val2, count, pass; count = 0; @@ -103,45 +103,50 @@ static int ast_i2c_getscl(void *i2c_priv) return val & 1 ? 1 : 0; } -static void ast_i2c_release(struct drm_device *dev, void *res) +static void ast_ddc_release(struct drm_device *dev, void *res) { - struct ast_i2c_chan *i2c = res; + struct ast_ddc *ddc = res; - i2c_del_adapter(&i2c->adapter); + i2c_del_adapter(&ddc->adapter); } -struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev) +struct ast_ddc *ast_ddc_create(struct drm_device *dev) { - struct ast_i2c_chan *i2c; + struct ast_ddc *ddc; + struct i2c_adapter *adapter; + struct i2c_algo_bit_data *bit; int ret; - i2c = drmm_kzalloc(dev->dev, sizeof(*i2c), GFP_KERNEL); - if (!i2c) + ddc = drmm_kzalloc(dev, sizeof(*ddc), GFP_KERNEL); + if (!ddc) return ERR_PTR(-ENOMEM); + ddc->dev = dev; - i2c->adapter.owner = THIS_MODULE; - i2c->adapter.dev.parent = dev->dev; - i2c->dev = dev; - i2c_set_adapdata(&i2c->adapter, i2c); - snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), "AST DDC bus"); - i2c->adapter.algo_data = &i2c->bit; + adapter = &ddc->adapter; + adapter->owner = THIS_MODULE; + adapter->dev.parent = dev->dev; + i2c_set_adapdata(adapter, ddc); + snprintf(adapter->name, sizeof(adapter->name), "AST DDC bus"); - i2c->bit.udelay = 20; - i2c->bit.timeout = 2; - i2c->bit.data = i2c; - i2c->bit.setsda = ast_i2c_setsda; - i2c->bit.setscl = ast_i2c_setscl; - i2c->bit.getsda = ast_i2c_getsda; - i2c->bit.getscl = ast_i2c_getscl; - ret = i2c_bit_add_bus(&i2c->adapter); + bit = &ddc->bit; + bit->udelay = 20; + bit->timeout = 2; + bit->data = ddc; + bit->setsda = ast_i2c_setsda; + bit->setscl = ast_i2c_setscl; + bit->getsda = ast_i2c_getsda; + bit->getscl = ast_i2c_getscl; + + adapter->algo_data = bit; + ret = i2c_bit_add_bus(adapter); if (ret) { drm_err(dev, "Failed to register bit i2c\n"); return ERR_PTR(ret); } - ret = drmm_add_action_or_reset(dev, ast_i2c_release, i2c); + ret = drmm_add_action_or_reset(dev, ast_ddc_release, ddc); if (ret) return ERR_PTR(ret); - return i2c; + return ddc; } diff --git a/drivers/gpu/drm/ast/ast_ddc.h b/drivers/gpu/drm/ast/ast_ddc.h index 244666fd6c53..071f9be3e27d 100644 --- a/drivers/gpu/drm/ast/ast_ddc.h +++ b/drivers/gpu/drm/ast/ast_ddc.h @@ -8,12 +8,12 @@ struct drm_device; -struct ast_i2c_chan { +struct ast_ddc { struct i2c_adapter adapter; struct drm_device *dev; struct i2c_algo_bit_data bit; }; -struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev); +struct ast_ddc *ast_ddc_create(struct drm_device *dev); #endif diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index bdef2160726e..40cb495acc90 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -1388,18 +1388,18 @@ static const struct drm_connector_funcs ast_vga_connector_funcs = { static int ast_vga_connector_init(struct drm_device *dev, struct drm_connector *connector) { - struct ast_i2c_chan *i2c; + struct ast_ddc *ddc; int ret; - i2c = ast_i2c_create(dev); - if (IS_ERR(i2c)) { - ret = PTR_ERR(i2c); - drm_err(dev, "failed to add ddc bus for connector; ret=%d\n", ret); + ddc = ast_ddc_create(dev); + if (IS_ERR(ddc)) { + ret = PTR_ERR(ddc); + drm_err(dev, "failed to add DDC bus for connector; ret=%d\n", ret); return ret; } ret = drm_connector_init_with_ddc(dev, connector, &ast_vga_connector_funcs, - DRM_MODE_CONNECTOR_VGA, &i2c->adapter); + DRM_MODE_CONNECTOR_VGA, &ddc->adapter); if (ret) return ret; @@ -1485,18 +1485,18 @@ static const struct drm_connector_funcs ast_sil164_connector_funcs = { static int ast_sil164_connector_init(struct drm_device *dev, struct drm_connector *connector) { - struct ast_i2c_chan *i2c; + struct ast_ddc *ddc; int ret; - i2c = ast_i2c_create(dev); - if (IS_ERR(i2c)) { - ret = PTR_ERR(i2c); - drm_err(dev, "failed to add ddc bus for connector; ret=%d\n", ret); + ddc = ast_ddc_create(dev); + if (IS_ERR(ddc)) { + ret = PTR_ERR(ddc); + drm_err(dev, "failed to add DDC bus for connector; ret=%d\n", ret); return ret; } ret = drm_connector_init_with_ddc(dev, connector, &ast_sil164_connector_funcs, - DRM_MODE_CONNECTOR_DVII, &i2c->adapter); + DRM_MODE_CONNECTOR_DVII, &ddc->adapter); if (ret) return ret; From 0872fee2e1c8a0503006b5dab0ec32901b0bf247 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 25 Mar 2024 21:06:52 +0100 Subject: [PATCH 17/32] drm/ast: Pass AST device to ast_ddc_create() The DDC code needs the AST device. Pass it to ast_ddc_create() and avoid an internal upcast. Improves type safety within the DDC code. Signed-off-by: Thomas Zimmermann Reviewed-by: Sui Jingfeng Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20240325200855.21150-8-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_ddc.c | 3 ++- drivers/gpu/drm/ast/ast_ddc.h | 3 ++- drivers/gpu/drm/ast/ast_mode.c | 6 ++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_ddc.c b/drivers/gpu/drm/ast/ast_ddc.c index c0e5d03c028d..24b7d589f0d4 100644 --- a/drivers/gpu/drm/ast/ast_ddc.c +++ b/drivers/gpu/drm/ast/ast_ddc.c @@ -110,8 +110,9 @@ static void ast_ddc_release(struct drm_device *dev, void *res) i2c_del_adapter(&ddc->adapter); } -struct ast_ddc *ast_ddc_create(struct drm_device *dev) +struct ast_ddc *ast_ddc_create(struct ast_device *ast) { + struct drm_device *dev = &ast->base; struct ast_ddc *ddc; struct i2c_adapter *adapter; struct i2c_algo_bit_data *bit; diff --git a/drivers/gpu/drm/ast/ast_ddc.h b/drivers/gpu/drm/ast/ast_ddc.h index 071f9be3e27d..d423b144a345 100644 --- a/drivers/gpu/drm/ast/ast_ddc.h +++ b/drivers/gpu/drm/ast/ast_ddc.h @@ -6,6 +6,7 @@ #include #include +struct ast_device; struct drm_device; struct ast_ddc { @@ -14,6 +15,6 @@ struct ast_ddc { struct i2c_algo_bit_data bit; }; -struct ast_ddc *ast_ddc_create(struct drm_device *dev); +struct ast_ddc *ast_ddc_create(struct ast_device *ast); #endif diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 40cb495acc90..fc73d3b65b2a 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -1388,10 +1388,11 @@ static const struct drm_connector_funcs ast_vga_connector_funcs = { static int ast_vga_connector_init(struct drm_device *dev, struct drm_connector *connector) { + struct ast_device *ast = to_ast_device(dev); struct ast_ddc *ddc; int ret; - ddc = ast_ddc_create(dev); + ddc = ast_ddc_create(ast); if (IS_ERR(ddc)) { ret = PTR_ERR(ddc); drm_err(dev, "failed to add DDC bus for connector; ret=%d\n", ret); @@ -1485,10 +1486,11 @@ static const struct drm_connector_funcs ast_sil164_connector_funcs = { static int ast_sil164_connector_init(struct drm_device *dev, struct drm_connector *connector) { + struct ast_device *ast = to_ast_device(dev); struct ast_ddc *ddc; int ret; - ddc = ast_ddc_create(dev); + ddc = ast_ddc_create(ast); if (IS_ERR(ddc)) { ret = PTR_ERR(ddc); drm_err(dev, "failed to add DDC bus for connector; ret=%d\n", ret); From d95e92e195a6ccb49faa27433bcbb654a3f79b1b Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 25 Mar 2024 21:06:53 +0100 Subject: [PATCH 18/32] drm/ast: Store AST device in struct ast_ddc The DDC code needs the AST device. Store a pointer in struct ast_ddc and avoid internal upcasts. Improves type safety within the DDC code. Signed-off-by: Thomas Zimmermann Reviewed-by: Sui Jingfeng Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20240325200855.21150-9-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_ddc.c | 10 +++++----- drivers/gpu/drm/ast/ast_ddc.h | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_ddc.c b/drivers/gpu/drm/ast/ast_ddc.c index 24b7d589f0d4..47670285fd76 100644 --- a/drivers/gpu/drm/ast/ast_ddc.c +++ b/drivers/gpu/drm/ast/ast_ddc.c @@ -30,7 +30,7 @@ static void ast_i2c_setsda(void *i2c_priv, int data) { struct ast_ddc *ddc = i2c_priv; - struct ast_device *ast = to_ast_device(ddc->dev); + struct ast_device *ast = ddc->ast; int i; u8 ujcrb7, jtemp; @@ -46,7 +46,7 @@ static void ast_i2c_setsda(void *i2c_priv, int data) static void ast_i2c_setscl(void *i2c_priv, int clock) { struct ast_ddc *ddc = i2c_priv; - struct ast_device *ast = to_ast_device(ddc->dev); + struct ast_device *ast = ddc->ast; int i; u8 ujcrb7, jtemp; @@ -62,7 +62,7 @@ static void ast_i2c_setscl(void *i2c_priv, int clock) static int ast_i2c_getsda(void *i2c_priv) { struct ast_ddc *ddc = i2c_priv; - struct ast_device *ast = to_ast_device(ddc->dev); + struct ast_device *ast = ddc->ast; uint32_t val, val2, count, pass; count = 0; @@ -84,7 +84,7 @@ static int ast_i2c_getsda(void *i2c_priv) static int ast_i2c_getscl(void *i2c_priv) { struct ast_ddc *ddc = i2c_priv; - struct ast_device *ast = to_ast_device(ddc->dev); + struct ast_device *ast = ddc->ast; uint32_t val, val2, count, pass; count = 0; @@ -121,7 +121,7 @@ struct ast_ddc *ast_ddc_create(struct ast_device *ast) ddc = drmm_kzalloc(dev, sizeof(*ddc), GFP_KERNEL); if (!ddc) return ERR_PTR(-ENOMEM); - ddc->dev = dev; + ddc->ast = ast; adapter = &ddc->adapter; adapter->owner = THIS_MODULE; diff --git a/drivers/gpu/drm/ast/ast_ddc.h b/drivers/gpu/drm/ast/ast_ddc.h index d423b144a345..08f3994e09cc 100644 --- a/drivers/gpu/drm/ast/ast_ddc.h +++ b/drivers/gpu/drm/ast/ast_ddc.h @@ -7,11 +7,11 @@ #include struct ast_device; -struct drm_device; struct ast_ddc { + struct ast_device *ast; + struct i2c_adapter adapter; - struct drm_device *dev; struct i2c_algo_bit_data bit; }; From 660ed6ba8f62faab67c0d5c615de82e1a65a4d3f Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 25 Mar 2024 21:06:54 +0100 Subject: [PATCH 19/32] drm/ast: Rename struct i2c_algo_bit_data callbacks and their parameters Align the names of the algo-bit helpers with ast's convention of using an ast prefix plus the struct's name plus the callback's name for such function symbols. Change the parameter names of these helpers to 'data' and 'state', as used in the declaration of struct i2c_algo_bit_data. No functional changes. Signed-off-by: Thomas Zimmermann Reviewed-by: Sui Jingfeng Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20240325200855.21150-10-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_ddc.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_ddc.c b/drivers/gpu/drm/ast/ast_ddc.c index 47670285fd76..b84e656124f1 100644 --- a/drivers/gpu/drm/ast/ast_ddc.c +++ b/drivers/gpu/drm/ast/ast_ddc.c @@ -27,15 +27,15 @@ #include "ast_ddc.h" #include "ast_drv.h" -static void ast_i2c_setsda(void *i2c_priv, int data) +static void ast_ddc_algo_bit_data_setsda(void *data, int state) { - struct ast_ddc *ddc = i2c_priv; + struct ast_ddc *ddc = data; struct ast_device *ast = ddc->ast; int i; u8 ujcrb7, jtemp; for (i = 0; i < 0x10000; i++) { - ujcrb7 = ((data & 0x01) ? 0 : 1) << 2; + ujcrb7 = ((state & 0x01) ? 0 : 1) << 2; ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0xf1, ujcrb7); jtemp = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0x04); if (ujcrb7 == jtemp) @@ -43,15 +43,15 @@ static void ast_i2c_setsda(void *i2c_priv, int data) } } -static void ast_i2c_setscl(void *i2c_priv, int clock) +static void ast_ddc_algo_bit_data_setscl(void *data, int state) { - struct ast_ddc *ddc = i2c_priv; + struct ast_ddc *ddc = data; struct ast_device *ast = ddc->ast; int i; u8 ujcrb7, jtemp; for (i = 0; i < 0x10000; i++) { - ujcrb7 = ((clock & 0x01) ? 0 : 1); + ujcrb7 = ((state & 0x01) ? 0 : 1); ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0xf4, ujcrb7); jtemp = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0x01); if (ujcrb7 == jtemp) @@ -59,9 +59,9 @@ static void ast_i2c_setscl(void *i2c_priv, int clock) } } -static int ast_i2c_getsda(void *i2c_priv) +static int ast_ddc_algo_bit_data_getsda(void *data) { - struct ast_ddc *ddc = i2c_priv; + struct ast_ddc *ddc = data; struct ast_device *ast = ddc->ast; uint32_t val, val2, count, pass; @@ -81,9 +81,9 @@ static int ast_i2c_getsda(void *i2c_priv) return val & 1 ? 1 : 0; } -static int ast_i2c_getscl(void *i2c_priv) +static int ast_ddc_algo_bit_data_getscl(void *data) { - struct ast_ddc *ddc = i2c_priv; + struct ast_ddc *ddc = data; struct ast_device *ast = ddc->ast; uint32_t val, val2, count, pass; @@ -133,10 +133,10 @@ struct ast_ddc *ast_ddc_create(struct ast_device *ast) bit->udelay = 20; bit->timeout = 2; bit->data = ddc; - bit->setsda = ast_i2c_setsda; - bit->setscl = ast_i2c_setscl; - bit->getsda = ast_i2c_getsda; - bit->getscl = ast_i2c_getscl; + bit->setsda = ast_ddc_algo_bit_data_setsda; + bit->setscl = ast_ddc_algo_bit_data_setscl; + bit->getsda = ast_ddc_algo_bit_data_getsda; + bit->getscl = ast_ddc_algo_bit_data_getscl; adapter->algo_data = bit; ret = i2c_bit_add_bus(adapter); From dfff99cb56904087e35dbecec3d482aa8a95436a Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 25 Mar 2024 21:06:55 +0100 Subject: [PATCH 20/32] drm/ast: Acquire I/O-register lock in DDC code The modeset lock protects the DDC code from concurrent modeset operations, which use the same registers. Move that code from the connector helpers into the DDC helpers .pre_xfer() and .post_xfer(). Both, .pre_xfer() and .post_xfer(), enclose the transfer of data blocks over the I2C channel in the internal I2C function bit_xfer(). Both calls are executed unconditionally if present. Invoking DDC transfers from any where within the driver now takes the lock. Signed-off-by: Thomas Zimmermann Reviewed-by: Sui Jingfeng Reviewed-by: Jocelyn Falempe Tested-by: Sui Jingfeng Link: https://patchwork.freedesktop.org/patch/msgid/20240325200855.21150-11-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_ddc.c | 24 ++++++++++++++++++++++++ drivers/gpu/drm/ast/ast_mode.c | 30 ++++-------------------------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_ddc.c b/drivers/gpu/drm/ast/ast_ddc.c index b84e656124f1..b7718084422f 100644 --- a/drivers/gpu/drm/ast/ast_ddc.c +++ b/drivers/gpu/drm/ast/ast_ddc.c @@ -59,6 +59,28 @@ static void ast_ddc_algo_bit_data_setscl(void *data, int state) } } +static int ast_ddc_algo_bit_data_pre_xfer(struct i2c_adapter *adapter) +{ + struct ast_ddc *ddc = i2c_get_adapdata(adapter); + struct ast_device *ast = ddc->ast; + + /* + * Protect access to I/O registers from concurrent modesetting + * by acquiring the I/O-register lock. + */ + mutex_lock(&ast->modeset_lock); + + return 0; +} + +static void ast_ddc_algo_bit_data_post_xfer(struct i2c_adapter *adapter) +{ + struct ast_ddc *ddc = i2c_get_adapdata(adapter); + struct ast_device *ast = ddc->ast; + + mutex_unlock(&ast->modeset_lock); +} + static int ast_ddc_algo_bit_data_getsda(void *data) { struct ast_ddc *ddc = data; @@ -137,6 +159,8 @@ struct ast_ddc *ast_ddc_create(struct ast_device *ast) bit->setscl = ast_ddc_algo_bit_data_setscl; bit->getsda = ast_ddc_algo_bit_data_getsda; bit->getscl = ast_ddc_algo_bit_data_getscl; + bit->pre_xfer = ast_ddc_algo_bit_data_pre_xfer; + bit->post_xfer = ast_ddc_algo_bit_data_post_xfer; adapter->algo_data = bit; ret = i2c_bit_add_bus(adapter); diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index fc73d3b65b2a..8766a0f2eb3c 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -1346,30 +1346,19 @@ static int ast_crtc_init(struct drm_device *dev) static int ast_vga_connector_helper_get_modes(struct drm_connector *connector) { - struct drm_device *dev = connector->dev; - struct ast_device *ast = to_ast_device(dev); struct edid *edid; int count; - /* - * Protect access to I/O registers from concurrent modesetting - * by acquiring the I/O-register lock. - */ - mutex_lock(&ast->modeset_lock); - edid = drm_get_edid(connector, connector->ddc); if (!edid) - goto err_mutex_unlock; - - mutex_unlock(&ast->modeset_lock); + goto err_drm_get_edid; count = drm_add_edid_modes(connector, edid); kfree(edid); return count; -err_mutex_unlock: - mutex_unlock(&ast->modeset_lock); +err_drm_get_edid: drm_connector_update_edid_property(connector, NULL); return 0; } @@ -1444,30 +1433,19 @@ static int ast_vga_output_init(struct ast_device *ast) static int ast_sil164_connector_helper_get_modes(struct drm_connector *connector) { - struct drm_device *dev = connector->dev; - struct ast_device *ast = to_ast_device(dev); struct edid *edid; int count; - /* - * Protect access to I/O registers from concurrent modesetting - * by acquiring the I/O-register lock. - */ - mutex_lock(&ast->modeset_lock); - edid = drm_get_edid(connector, connector->ddc); if (!edid) - goto err_mutex_unlock; - - mutex_unlock(&ast->modeset_lock); + goto err_drm_get_edid; count = drm_add_edid_modes(connector, edid); kfree(edid); return count; -err_mutex_unlock: - mutex_unlock(&ast->modeset_lock); +err_drm_get_edid: drm_connector_update_edid_property(connector, NULL); return 0; } From 90170b186ff552ec080ede18b7c3c2aeb6d5b993 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 25 Mar 2024 21:06:56 +0100 Subject: [PATCH 21/32] drm/ast: Use drm_connector_helper_get_modes() The .get_modes() code for VGA and SIL164 connectors does not depend on either type of connector. Replace the driver code with the common helper drm_connector_helper_get_modes(). It reads EDID data via DDC and updates the connector's EDID property. Signed-off-by: Thomas Zimmermann Reviewed-by: Sui Jingfeng Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20240325200855.21150-12-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_mode.c | 42 ++-------------------------------- 1 file changed, 2 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 8766a0f2eb3c..71cc681d6188 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -1344,27 +1344,8 @@ static int ast_crtc_init(struct drm_device *dev) * VGA Connector */ -static int ast_vga_connector_helper_get_modes(struct drm_connector *connector) -{ - struct edid *edid; - int count; - - edid = drm_get_edid(connector, connector->ddc); - if (!edid) - goto err_drm_get_edid; - - count = drm_add_edid_modes(connector, edid); - kfree(edid); - - return count; - -err_drm_get_edid: - drm_connector_update_edid_property(connector, NULL); - return 0; -} - static const struct drm_connector_helper_funcs ast_vga_connector_helper_funcs = { - .get_modes = ast_vga_connector_helper_get_modes, + .get_modes = drm_connector_helper_get_modes, }; static const struct drm_connector_funcs ast_vga_connector_funcs = { @@ -1431,27 +1412,8 @@ static int ast_vga_output_init(struct ast_device *ast) * SIL164 Connector */ -static int ast_sil164_connector_helper_get_modes(struct drm_connector *connector) -{ - struct edid *edid; - int count; - - edid = drm_get_edid(connector, connector->ddc); - if (!edid) - goto err_drm_get_edid; - - count = drm_add_edid_modes(connector, edid); - kfree(edid); - - return count; - -err_drm_get_edid: - drm_connector_update_edid_property(connector, NULL); - return 0; -} - static const struct drm_connector_helper_funcs ast_sil164_connector_helper_funcs = { - .get_modes = ast_sil164_connector_helper_get_modes, + .get_modes = drm_connector_helper_get_modes, }; static const struct drm_connector_funcs ast_sil164_connector_funcs = { From 225a8d0bd93eb87fe49947069075260031bad8af Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 25 Mar 2024 21:06:57 +0100 Subject: [PATCH 22/32] drm/ast: Implement polling for VGA and SIL164 connectors Implement polling for VGA and SIL164 connectors. Set the flag DRM_CONNECTOR_POLL_DISCONNECT for each to detect the removal of the monitor cable. Implement struct drm_connector_helper_funcs.detect_ctx for each type of connector by testing for EDID data. The helper drm_connector_helper_detect_ctx() implements .detect_ctx() on top of the connector's DDC channel. The function can be used by other drivers as companion to drm_connector_helper_get_modes(). v6: - change helper name to drm_connector_helper_detec_from_ddc() (Maxime, Sui) v5: - share implementation in drm_connector_helper_detect_ctx() (Maxime) - test for DDC presence with drm_probe_ddc() (Maxime, Jani) Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Acked-by: Sui Jingfeng Acked-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20240325200855.21150-13-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_mode.c | 6 ++++-- drivers/gpu/drm/drm_probe_helper.c | 29 +++++++++++++++++++++++++++++ include/drm/drm_probe_helper.h | 4 ++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 71cc681d6188..b4e1c812520c 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -1346,6 +1346,7 @@ static int ast_crtc_init(struct drm_device *dev) static const struct drm_connector_helper_funcs ast_vga_connector_helper_funcs = { .get_modes = drm_connector_helper_get_modes, + .detect_ctx = drm_connector_helper_detect_from_ddc, }; static const struct drm_connector_funcs ast_vga_connector_funcs = { @@ -1379,7 +1380,7 @@ static int ast_vga_connector_init(struct drm_device *dev, struct drm_connector * connector->interlace_allowed = 0; connector->doublescan_allowed = 0; - connector->polled = DRM_CONNECTOR_POLL_CONNECT; + connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; return 0; } @@ -1414,6 +1415,7 @@ static int ast_vga_output_init(struct ast_device *ast) static const struct drm_connector_helper_funcs ast_sil164_connector_helper_funcs = { .get_modes = drm_connector_helper_get_modes, + .detect_ctx = drm_connector_helper_detect_from_ddc, }; static const struct drm_connector_funcs ast_sil164_connector_funcs = { @@ -1447,7 +1449,7 @@ static int ast_sil164_connector_init(struct drm_device *dev, struct drm_connecto connector->interlace_allowed = 0; connector->doublescan_allowed = 0; - connector->polled = DRM_CONNECTOR_POLL_CONNECT; + connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; return 0; } diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index bf2dd1f46b6c..8fb842c6c638 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -1279,3 +1279,32 @@ int drm_connector_helper_tv_get_modes(struct drm_connector *connector) return i; } EXPORT_SYMBOL(drm_connector_helper_tv_get_modes); + +/** + * drm_connector_helper_detect_from_ddc - Read EDID and detect connector status. + * @connector: The connector + * @ctx: Acquire context + * @force: Perform screen-destructive operations, if necessary + * + * Detects the connector status by reading the EDID using drm_probe_ddc(), + * which requires connector->ddc to be set. Returns connector_status_connected + * on success or connector_status_disconnected on failure. + * + * Returns: + * The connector status as defined by enum drm_connector_status. + */ +int drm_connector_helper_detect_from_ddc(struct drm_connector *connector, + struct drm_modeset_acquire_ctx *ctx, + bool force) +{ + struct i2c_adapter *ddc = connector->ddc; + + if (!ddc) + return connector_status_unknown; + + if (drm_probe_ddc(ddc)) + return connector_status_connected; + + return connector_status_disconnected; +} +EXPORT_SYMBOL(drm_connector_helper_detect_from_ddc); diff --git a/include/drm/drm_probe_helper.h b/include/drm/drm_probe_helper.h index 62741a88796b..e9dc32433631 100644 --- a/include/drm/drm_probe_helper.h +++ b/include/drm/drm_probe_helper.h @@ -37,4 +37,8 @@ int drm_connector_helper_get_modes_fixed(struct drm_connector *connector, int drm_connector_helper_get_modes(struct drm_connector *connector); int drm_connector_helper_tv_get_modes(struct drm_connector *connector); +int drm_connector_helper_detect_from_ddc(struct drm_connector *connector, + struct drm_modeset_acquire_ctx *ctx, + bool force); + #endif From 10021ef27310279c850cf6cb38542c443a995e92 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 25 Mar 2024 21:06:58 +0100 Subject: [PATCH 23/32] drm/ast: Automatically clean up poll helper Automatically clean up the conncetor-poll thread as part of the DRM device release. The new helper drmm_kms_helper_poll_init() provides a shared implementation for all drivers. v6: - fix kernel doc comment (Sui, kernel test robot) Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Acked-by: Sui Jingfeng Link: https://patchwork.freedesktop.org/patch/msgid/20240325200855.21150-14-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_mode.c | 4 +++- drivers/gpu/drm/drm_probe_helper.c | 27 +++++++++++++++++++++++++++ include/drm/drm_probe_helper.h | 2 ++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index b4e1c812520c..bb9b66aba9ee 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -1905,7 +1905,9 @@ int ast_mode_config_init(struct ast_device *ast) drm_mode_config_reset(dev); - drm_kms_helper_poll_init(dev); + ret = drmm_kms_helper_poll_init(dev); + if (ret) + return ret; return 0; } diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 8fb842c6c638..968a3ee66b1e 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -951,6 +952,32 @@ void drm_kms_helper_poll_fini(struct drm_device *dev) } EXPORT_SYMBOL(drm_kms_helper_poll_fini); +static void drm_kms_helper_poll_init_release(struct drm_device *dev, void *res) +{ + drm_kms_helper_poll_fini(dev); +} + +/** + * drmm_kms_helper_poll_init - initialize and enable output polling + * @dev: drm_device + * + * This function initializes and then also enables output polling support for + * @dev similar to drm_kms_helper_poll_init(). Polling will automatically be + * cleaned up when the DRM device goes away. + * + * See drm_kms_helper_poll_init() for more information. + * + * Returns: + * 0 on success, or a negative errno code otherwise. + */ +int drmm_kms_helper_poll_init(struct drm_device *dev) +{ + drm_kms_helper_poll_init(dev); + + return drmm_add_action_or_reset(dev, drm_kms_helper_poll_init_release, dev); +} +EXPORT_SYMBOL(drmm_kms_helper_poll_init); + static bool check_connector_changed(struct drm_connector *connector) { struct drm_device *dev = connector->dev; diff --git a/include/drm/drm_probe_helper.h b/include/drm/drm_probe_helper.h index e9dc32433631..d6ce7b218b77 100644 --- a/include/drm/drm_probe_helper.h +++ b/include/drm/drm_probe_helper.h @@ -16,6 +16,8 @@ int drm_helper_probe_single_connector_modes(struct drm_connector int drm_helper_probe_detect(struct drm_connector *connector, struct drm_modeset_acquire_ctx *ctx, bool force); + +int drmm_kms_helper_poll_init(struct drm_device *dev); void drm_kms_helper_poll_init(struct drm_device *dev); void drm_kms_helper_poll_fini(struct drm_device *dev); bool drm_helper_hpd_irq_event(struct drm_device *dev); From 00044169de061dac8d9da2cf930757c53006adff Mon Sep 17 00:00:00 2001 From: Liviu Dudau Date: Tue, 2 Apr 2024 22:54:22 +0100 Subject: [PATCH 24/32] drm/panthor: Cleanup unused variable 'cookie' Commit 962f88b9c916 ("drm/panthor: Drop the dev_enter/exit() sections in _irq_suspend/resume()") removed the code that used the 'cookie' variable but left the declaration in place. Remove it. Fixes: 962f88b9c916 ("drm/panthor: Drop the dev_enter/exit() sections in _irq_suspend/resume()") Cc: Boris Brezillon Cc: Steven Price Signed-off-by: Liviu Dudau Reviewed-by: Boris Brezillon Signed-off-by: Boris Brezillon Link: https://patchwork.freedesktop.org/patch/msgid/20240402215423.360341-1-liviu.dudau@arm.com --- drivers/gpu/drm/panthor/panthor_device.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/panthor/panthor_device.h b/drivers/gpu/drm/panthor/panthor_device.h index dc3e9c666b5b..2fdd671b38fd 100644 --- a/drivers/gpu/drm/panthor/panthor_device.h +++ b/drivers/gpu/drm/panthor/panthor_device.h @@ -323,8 +323,6 @@ static irqreturn_t panthor_ ## __name ## _irq_threaded_handler(int irq, void *da \ static inline void panthor_ ## __name ## _irq_suspend(struct panthor_irq *pirq) \ { \ - int cookie; \ - \ pirq->mask = 0; \ gpu_write(pirq->ptdev, __reg_prefix ## _INT_MASK, 0); \ synchronize_irq(pirq->irq); \ @@ -333,8 +331,6 @@ static inline void panthor_ ## __name ## _irq_suspend(struct panthor_irq *pirq) \ static inline void panthor_ ## __name ## _irq_resume(struct panthor_irq *pirq, u32 mask) \ { \ - int cookie; \ - \ atomic_set(&pirq->suspended, false); \ pirq->mask = mask; \ gpu_write(pirq->ptdev, __reg_prefix ## _INT_CLEAR, mask); \ From be7ffc821f5fc2eb30944562a04901c10892cc7c Mon Sep 17 00:00:00 2001 From: Liviu Dudau Date: Tue, 2 Apr 2024 22:54:23 +0100 Subject: [PATCH 25/32] drm/panthor: Fix some kerneldoc warnings When compiling with W=1 the build process will flag empty comments, misnamed documented variables and incorrect tagging of functions. Fix them in one go. Fixes: de8548813824 ("drm/panthor: Add the scheduler logical block") Cc: Boris Brezillon Cc: Steven Price Signed-off-by: Liviu Dudau Reviewed-by: Boris Brezillon Signed-off-by: Boris Brezillon Link: https://patchwork.freedesktop.org/patch/msgid/20240402215423.360341-2-liviu.dudau@arm.com --- drivers/gpu/drm/panthor/panthor_sched.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c index e5a710f190d2..a787f2fea33e 100644 --- a/drivers/gpu/drm/panthor/panthor_sched.c +++ b/drivers/gpu/drm/panthor/panthor_sched.c @@ -517,7 +517,7 @@ struct panthor_group { /** @max_compute_cores: Maximum number of shader cores used for compute jobs. */ u8 max_compute_cores; - /** @max_compute_cores: Maximum number of shader cores used for fragment jobs. */ + /** @max_fragment_cores: Maximum number of shader cores used for fragment jobs. */ u8 max_fragment_cores; /** @max_tiler_cores: Maximum number of tiler cores used for tiler jobs. */ @@ -993,7 +993,7 @@ cs_slot_prog_locked(struct panthor_device *ptdev, u32 csg_id, u32 cs_id) } /** - * @cs_slot_reset_locked() - Reset a queue slot + * cs_slot_reset_locked() - Reset a queue slot * @ptdev: Device. * @csg_id: Group slot. * @cs_id: Queue slot. @@ -1591,7 +1591,7 @@ static void sched_process_idle_event_locked(struct panthor_device *ptdev) } /** - * panthor_sched_process_global_irq() - Process the scheduling part of a global IRQ + * sched_process_global_irq_locked() - Process the scheduling part of a global IRQ * @ptdev: Device. */ static void sched_process_global_irq_locked(struct panthor_device *ptdev) @@ -1660,8 +1660,6 @@ static const struct dma_fence_ops panthor_queue_fence_ops = { .get_timeline_name = queue_fence_get_timeline_name, }; -/** - */ struct panthor_csg_slots_upd_ctx { u32 update_mask; u32 timedout_mask; From d33733263a550775c7574169f62bf144f74d8f9a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 2 Apr 2024 12:58:09 +0300 Subject: [PATCH 26/32] drm/panthor: Fix a couple -ENOMEM error codes These error paths forgot to set the error code to -ENOMEM. Fixes: 647810ec2476 ("drm/panthor: Add the MMU/VM logical block") Signed-off-by: Dan Carpenter Reviewed-by: Boris Brezillon Signed-off-by: Boris Brezillon Link: https://patchwork.freedesktop.org/patch/msgid/cf5bbba5-427e-4940-b91e-925f9fa71f8d@moroto.mountain --- drivers/gpu/drm/panthor/panthor_mmu.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/panthor/panthor_mmu.c index fdd35249169f..a26b40aab261 100644 --- a/drivers/gpu/drm/panthor/panthor_mmu.c +++ b/drivers/gpu/drm/panthor/panthor_mmu.c @@ -1264,8 +1264,10 @@ static int panthor_vm_prepare_map_op_ctx(struct panthor_vm_op_ctx *op_ctx, op_ctx->rsvd_page_tables.pages = kcalloc(pt_count, sizeof(*op_ctx->rsvd_page_tables.pages), GFP_KERNEL); - if (!op_ctx->rsvd_page_tables.pages) + if (!op_ctx->rsvd_page_tables.pages) { + ret = -ENOMEM; goto err_cleanup; + } ret = kmem_cache_alloc_bulk(pt_cache, GFP_KERNEL, pt_count, op_ctx->rsvd_page_tables.pages); @@ -1318,8 +1320,10 @@ static int panthor_vm_prepare_unmap_op_ctx(struct panthor_vm_op_ctx *op_ctx, op_ctx->rsvd_page_tables.pages = kcalloc(pt_count, sizeof(*op_ctx->rsvd_page_tables.pages), GFP_KERNEL); - if (!op_ctx->rsvd_page_tables.pages) + if (!op_ctx->rsvd_page_tables.pages) { + ret = -ENOMEM; goto err_cleanup; + } ret = kmem_cache_alloc_bulk(pt_cache, GFP_KERNEL, pt_count, op_ctx->rsvd_page_tables.pages); From 99b74db1e27145bdf0afb85559aa70d951569ac3 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 2 Apr 2024 12:56:19 +0300 Subject: [PATCH 27/32] drm/panthor: Fix error code in panthor_gpu_init() This code accidentally returns zero/success on error because of a typo. It should be "irq" instead of "ret". The other thing is that if platform_get_irq_byname() were to return zero then the error code would be cmplicated. Fortunately, it does not so we can just change <= to < 0. Fixes: 5cd894e258c4 ("drm/panthor: Add the GPU logical block") Signed-off-by: Dan Carpenter Reviewed-by: Boris Brezillon Signed-off-by: Boris Brezillon Link: https://patchwork.freedesktop.org/patch/msgid/d753e684-43ee-45c2-a1fd-86222da204e1@moroto.mountain --- drivers/gpu/drm/panthor/panthor_gpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/panthor/panthor_gpu.c b/drivers/gpu/drm/panthor/panthor_gpu.c index 0f7c962440d3..5251d8764e7d 100644 --- a/drivers/gpu/drm/panthor/panthor_gpu.c +++ b/drivers/gpu/drm/panthor/panthor_gpu.c @@ -211,8 +211,8 @@ int panthor_gpu_init(struct panthor_device *ptdev) return ret; irq = platform_get_irq_byname(to_platform_device(ptdev->base.dev), "gpu"); - if (irq <= 0) - return ret; + if (irq < 0) + return irq; ret = panthor_request_gpu_irq(ptdev, &ptdev->gpu->irq, irq, GPU_INTERRUPTS_MASK); if (ret) From 2b5890786014b926f845402ae80ebc71c4bd6d5c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 2 Apr 2024 12:56:42 +0300 Subject: [PATCH 28/32] drm/panthor: Fix off by one in panthor_fw_get_cs_iface() The ->iface.streams[csg_slot][] array has MAX_CS_PER_CSG elements so this > comparison needs to be >= to prevent an out of bounds access. Fixes: 2718d91816ee ("drm/panthor: Add the FW logical block") Signed-off-by: Dan Carpenter Reviewed-by: Boris Brezillon Signed-off-by: Boris Brezillon Link: https://patchwork.freedesktop.org/patch/msgid/62835c16-c85c-483d-a8fe-63be78d49d15@moroto.mountain --- drivers/gpu/drm/panthor/panthor_fw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/panthor/panthor_fw.c b/drivers/gpu/drm/panthor/panthor_fw.c index 33c87a59834e..181395e2859a 100644 --- a/drivers/gpu/drm/panthor/panthor_fw.c +++ b/drivers/gpu/drm/panthor/panthor_fw.c @@ -308,7 +308,7 @@ panthor_fw_get_csg_iface(struct panthor_device *ptdev, u32 csg_slot) struct panthor_fw_cs_iface * panthor_fw_get_cs_iface(struct panthor_device *ptdev, u32 csg_slot, u32 cs_slot) { - if (drm_WARN_ON(&ptdev->base, csg_slot >= MAX_CSGS || cs_slot > MAX_CS_PER_CSG)) + if (drm_WARN_ON(&ptdev->base, csg_slot >= MAX_CSGS || cs_slot >= MAX_CS_PER_CSG)) return NULL; return &ptdev->fw->iface.streams[csg_slot][cs_slot]; From 6e0718f21feda0ed97f932cee39b676817e457f2 Mon Sep 17 00:00:00 2001 From: Harshit Mogalapalli Date: Tue, 2 Apr 2024 03:40:40 -0700 Subject: [PATCH 29/32] drm/panthor: Fix NULL vs IS_ERR() bug in panthor_probe() The devm_drm_dev_alloc() function returns error pointers. Update the error handling to check for error pointers instead of NULL. Fixes: 4bdca1150792 ("drm/panthor: Add the driver frontend block") Signed-off-by: Harshit Mogalapalli Reviewed-by: Boris Brezillon Signed-off-by: Boris Brezillon Link: https://patchwork.freedesktop.org/patch/msgid/20240402104041.1689951-1-harshit.m.mogalapalli@oracle.com --- drivers/gpu/drm/panthor/panthor_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/panthor/panthor_drv.c index 730dd0c69cb8..5e3dc701d26d 100644 --- a/drivers/gpu/drm/panthor/panthor_drv.c +++ b/drivers/gpu/drm/panthor/panthor_drv.c @@ -1400,7 +1400,7 @@ static int panthor_probe(struct platform_device *pdev) ptdev = devm_drm_dev_alloc(&pdev->dev, &panthor_drm_driver, struct panthor_device, base); - if (!ptdev) + if (IS_ERR(ptdev)) return -ENOMEM; platform_set_drvdata(pdev, ptdev); From 45c734fdd43db14444025910b4c59dd2b8be714a Mon Sep 17 00:00:00 2001 From: Harshit Mogalapalli Date: Tue, 2 Apr 2024 07:14:11 -0700 Subject: [PATCH 30/32] drm/panthor: Don't return NULL from panthor_vm_get_heap_pool() The kernel doc says this function returns either a valid pointer or an ERR_PTR(), but in practice this function can return NULL if create=false. Fix the function to match the doc (return ERR_PTR(-ENOENT) instead of NULL) and adjust all call-sites accordingly. Fixes: 4bdca1150792 ("drm/panthor: Add the driver frontend block") Signed-off-by: Harshit Mogalapalli Reviewed-by: Boris Brezillon Signed-off-by: Boris Brezillon Link: https://patchwork.freedesktop.org/patch/msgid/20240402141412.1707949-1-harshit.m.mogalapalli@oracle.com --- drivers/gpu/drm/panthor/panthor_drv.c | 4 ++-- drivers/gpu/drm/panthor/panthor_mmu.c | 2 ++ drivers/gpu/drm/panthor/panthor_sched.c | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/panthor/panthor_drv.c index 5e3dc701d26d..b8a84f26b3ef 100644 --- a/drivers/gpu/drm/panthor/panthor_drv.c +++ b/drivers/gpu/drm/panthor/panthor_drv.c @@ -1090,8 +1090,8 @@ static int panthor_ioctl_tiler_heap_destroy(struct drm_device *ddev, void *data, return -EINVAL; pool = panthor_vm_get_heap_pool(vm, false); - if (!pool) { - ret = -EINVAL; + if (IS_ERR(pool)) { + ret = PTR_ERR(pool); goto out_put_vm; } diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/panthor/panthor_mmu.c index a26b40aab261..fa0a002b1016 100644 --- a/drivers/gpu/drm/panthor/panthor_mmu.c +++ b/drivers/gpu/drm/panthor/panthor_mmu.c @@ -1897,6 +1897,8 @@ struct panthor_heap_pool *panthor_vm_get_heap_pool(struct panthor_vm *vm, bool c vm->heaps.pool = panthor_heap_pool_get(pool); } else { pool = panthor_heap_pool_get(vm->heaps.pool); + if (!pool) + pool = ERR_PTR(-ENOENT); } mutex_unlock(&vm->heaps.lock); diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c index a787f2fea33e..d4bc652b34d5 100644 --- a/drivers/gpu/drm/panthor/panthor_sched.c +++ b/drivers/gpu/drm/panthor/panthor_sched.c @@ -1343,7 +1343,7 @@ static int group_process_tiler_oom(struct panthor_group *group, u32 cs_id) if (unlikely(csg_id < 0)) return 0; - if (!heaps || frag_end > vt_end || vt_end >= vt_start) { + if (IS_ERR(heaps) || frag_end > vt_end || vt_end >= vt_start) { ret = -EINVAL; } else { /* We do the allocation without holding the scheduler lock to avoid From f3d9683346d6b1d6e24f57e954385995601594d4 Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Mon, 4 Mar 2024 18:48:57 -0600 Subject: [PATCH 31/32] drm/bridge: adv7511: Allow IRQ to share GPIO pins The IRQ registration currently assumes that the GPIO is dedicated to it, but that may not necessarily be the case. If the board has another device sharing the GPIO, it won't be registered and the hot-plug detect fails to function. Currently, the handler reads two registers and blindly assumes one of them caused the interrupt and returns IRQ_HANDLED unless there is an error. In order to properly do this, the IRQ handler needs to check if it needs to handle the IRQ and return IRQ_NONE if there is nothing to handle. With the check added and the return code properly indicating whether or not it there was an IRQ, the IRQF_SHARED can be set to share a GPIO IRQ. V2: Add check to see if there is IRQ data to handle Signed-off-by: Adam Ford Reviewed-by: Laurent Pinchart Reviewed-by: Dmitry Baryshkov Signed-off-by: Dmitry Baryshkov Link: https://patchwork.freedesktop.org/patch/msgid/20240305004859.201085-1-aford173@gmail.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c index b5518ff97165..f3b4616a8fb6 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c @@ -477,6 +477,11 @@ static int adv7511_irq_process(struct adv7511 *adv7511, bool process_hpd) if (ret < 0) return ret; + /* If there is no IRQ to handle, exit indicating no IRQ data */ + if (!(irq0 & (ADV7511_INT0_HPD | ADV7511_INT0_EDID_READY)) && + !(irq1 & ADV7511_INT1_DDC_ERROR)) + return -ENODATA; + regmap_write(adv7511->regmap, ADV7511_REG_INT(0), irq0); regmap_write(adv7511->regmap, ADV7511_REG_INT(1), irq1); @@ -1318,7 +1323,8 @@ static int adv7511_probe(struct i2c_client *i2c) ret = devm_request_threaded_irq(dev, i2c->irq, NULL, adv7511_irq_handler, - IRQF_ONESHOT, dev_name(dev), + IRQF_ONESHOT | IRQF_SHARED, + dev_name(dev), adv7511); if (ret) goto err_unregister_audio; From d1ef8fc18be6adbbffdee06fbb5b33699e2852be Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 4 Apr 2024 14:40:51 +0200 Subject: [PATCH 32/32] drm: fix DRM_DISPLAY_DP_HELPER dependencies Both the exynos and rockchip drivers ran into link failures after a Kconfig cleanup: aarch64-linux-ld: drivers/gpu/drm/exynos/exynos_dp.o: in function `exynos_dp_resume': exynos_dp.c:(.text+0xc0): undefined reference to `analogix_dp_resume' aarch64-linux-ld: drivers/gpu/drm/exynos/exynos_dp.o: in function `exynos_dp_suspend': exynos_dp.c:(.text+0xf4): undefined reference to `analogix_dp_suspend' x86_64-linux-ld: drivers/gpu/drm/rockchip/cdn-dp-core.o: in function `cdn_dp_connector_mode_valid': cdn-dp-core.c:(.text+0x13a): undefined reference to `drm_dp_bw_code_to_link_rate' x86_64-linux-ld: cdn-dp-core.c:(.text+0x148): undefined reference to `drm_dp_bw_code_to_link_rate' x86_64-linux-ld: drivers/gpu/drm/rockchip/cdn-dp-core.o: in function `cdn_dp_check_link_status': cdn-dp-core.c:(.text+0x1396): undefined reference to `drm_dp_channel_eq_ok' In both cases, the problem is that ROCKCHIP_CDN_DP and DRM_EXYNOS_DP are 'bool' symbols that depend on the the 'tristate' DRM_DISPLAY_HELPER symbol, but end up not working when the SoC specific part is built-in but the helper is in a loadable module. Use the same trick that DRM_ROCKCHIP already uses for the EXTCON dependency and disallow DP support when it would not work. Fixes: 0323287de87d ("drm: Switch DRM_DISPLAY_DP_HELPER to depends on") Signed-off-by: Arnd Bergmann Link: https://patchwork.freedesktop.org/patch/msgid/20240404124101.2988099-1-arnd@kernel.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/exynos/Kconfig | 2 +- drivers/gpu/drm/rockchip/Kconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 6a26a0b8eff2..58cd77220741 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -68,7 +68,7 @@ config DRM_EXYNOS_DP bool "Exynos specific extensions for Analogix DP driver" depends on DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON depends on DRM_DISPLAY_DP_HELPER - depends on DRM_DISPLAY_HELPER + depends on DRM_DISPLAY_HELPER=y || (DRM_DISPLAY_HELPER=m && DRM_EXYNOS=m) select DRM_ANALOGIX_DP default DRM_EXYNOS select DRM_PANEL diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig index 4b49a14758fe..4b4ad75032fd 100644 --- a/drivers/gpu/drm/rockchip/Kconfig +++ b/drivers/gpu/drm/rockchip/Kconfig @@ -46,7 +46,7 @@ config ROCKCHIP_ANALOGIX_DP config ROCKCHIP_CDN_DP bool "Rockchip cdn DP" depends on DRM_DISPLAY_DP_HELPER - depends on DRM_DISPLAY_HELPER + depends on DRM_DISPLAY_HELPER=y || (DRM_DISPLAY_HELPER=m && DRM_ROCKCHIP=m) depends on EXTCON=y || (EXTCON=m && DRM_ROCKCHIP=m) help This selects support for Rockchip SoC specific extensions