From patchwork Tue Jun 28 21:52:23 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Kevin Brace X-Patchwork-Id: 12898983 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id D409FC433EF for ; Tue, 28 Jun 2022 21:54:16 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 60BB110F58E; Tue, 28 Jun 2022 21:54:13 +0000 (UTC) Received: from mout.gmx.net (mout.gmx.net [212.227.15.15]) by gabe.freedesktop.org (Postfix) with ESMTPS id 82EF710F539 for ; Tue, 28 Jun 2022 21:54:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.net; s=badeba3b8450; t=1656453244; bh=G3vWKYkYM/vTX38+A0o/osqsuZtpk2/ky+zUR6oF68w=; h=X-UI-Sender-Class:From:To:Cc:Subject:Date:In-Reply-To:References; b=MAEx1zV6DVC+nxk6+jKdH4fM0k//l7Izms3yTkNUZxZh+OoSmsPLj49c2BN+zLSEM b9Qs5a9dUOh7+QZY6hkcaMDvzW9XDnB0/PrsWBsgruZl/vbG9ofq1G+6SKF9z2Gx3I A+khAqULHMz4jr4bcnPDSNE6MNhPy3uginwoTxPM= X-UI-Sender-Class: 01bb95c1-4bf8-414a-932a-4f6e2808ef9c Received: from localhost.localdomain ([174.250.0.5]) by mail.gmx.net (mrgmx005 [212.227.17.184]) with ESMTPSA (Nemesis) id 1N5G9n-1ngm580D6z-0116lJ; Tue, 28 Jun 2022 23:54:04 +0200 From: Kevin Brace To: dri-devel@lists.freedesktop.org Subject: [PATCH v2 09/32] drm/via: Add via_cursor.c Date: Tue, 28 Jun 2022 16:52:23 -0500 Message-Id: <20220628215246.19706-10-kevinbrace@gmx.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220628215246.19706-1-kevinbrace@gmx.com> References: <20220628215246.19706-1-kevinbrace@gmx.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:mI8P9obFtHeQb9RWBccCVA0QrDPQ+L2XdWhKN87nXnxGcwV4wPn 9tHgsqDhhCWG9Qiy+mnnK5zlj795sr0Zn8tvMYu+KDRVA5geg54ICTf8Nef4ojz2MTApRr5 2UpRltjthfxkr1KoCHI9IfUFjY/xFLkdg70vmvjYjyuz1oegryQ4Jqe6aZTwfctGjcM9nhc bcVSCwqvWqlwJVn+QRu0A== X-UI-Out-Filterresults: notjunk:1;V03:K0:S6BEF63u734=:l7yeIJeZZmrmgA1ESivXCk NuAyClv/Ix3ukDU2MNXTN1MH55GWfNn+Z8q2p2NwsNq9nu4nBbeUeO5wxH9j0m76CW5HeoPFP sI0o1jsp7TPmQ1vrFcQa9LnNmRCXbSNlrZc9t3qEHvSj6le1P6hYcpqEV6HxXAtXLXnbyOooT NipNz2n80/2lzjzlmgkE15kn4tGY0I0xUBygX7zOdMlSg73lqA97UH1O5d5Oxz7vtkC68Bk3v 0OKpqN5oFTl9h1VVo5fMGX5dHRNkKQ+NZzvi4PQna7IisE3hSqa7ObYz2/bHr3vAyWTkVzHQk Ej4hZ01pq9mrtbWnlG73nOrIfVIDaZzG4oOE0eO0/h7B5ByFEpp9YVUqNtNP3TQ2vFMMEgmwS bzn//W4yxqqlqBmGkXyHQLuxCVzjC+rfwSr0bP0qbjhQ9rnW0N7KwwVJSJ1LyGqKk1RHCjY38 sDL5dugzwJnkHIADpXg2MRRqSJUTQas1P3NbqoGOvBxvhjhFhujcaFRqwHHqfuU0tpySRt71X jKua3tYUyBvPrjFnT/I6Bb7P39Df6KN8yE4VGFmqnnnrBs3+LscnhT4r59X43KnZ0NgvPljEA 4zeKAigYOtJTcfEr2H+D2BNirm8qEsQ6dymlJPjFbXHj299Brf9OFbrRt86DcfDOHaCYbeHCF ngJIVNwIy7JJsxFVJsVknokA9Hzf4gPF9CnfH7CYgbSOcv1+CFw2GUs9BKFzv7OxZ8iFEo/m3 GAjLDiPMzs/qVIxETdIZv4IzRLme1D6l/A2qm19pK8bFSsgHliVcVRUXqxr63Sou7FJv+O9Z/ E7Cqoa0zAwFfDmZRnobfFRTm1RpCFEoidthpGBEp3LrunHi02ci7nOl30TrgX16gTTfsw9Jp2 PDJlXk7XoSXiAqgFRDHBP9FQ2ZsUFwtoeEB02T+AWzhHNlg0BS1IvzV8nKGYSMpYrICvPsLAr iSDUFJBYjhr3UdtQ/fR24+tCgXpINv3UM6bqyYFWbFxXqEpmsu3jmmEWigYU9KqELru3a6T3F Ua8jjk+Q+dlRoQbus0Y6g2pbpv5mCIRUhropsbNH/2q9E4Fs2eEFUyBmWBZ5M5HITQp11SP4/ 7vOMZ02iOLQhvGVhRsZa8vBIzuuNplPYVhuBc9QSS0g7jvAdomErJ4a1g== X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Brace Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" From: Kevin Brace Signed-off-by: Kevin Brace --- drivers/gpu/drm/via/via_cursor.c | 419 +++++++++++++++++++++++++++++++ 1 file changed, 419 insertions(+) create mode 100644 drivers/gpu/drm/via/via_cursor.c -- 2.35.1 diff --git a/drivers/gpu/drm/via/via_cursor.c b/drivers/gpu/drm/via/via_cursor.c new file mode 100644 index 000000000000..9a6bce1cf922 --- /dev/null +++ b/drivers/gpu/drm/via/via_cursor.c @@ -0,0 +1,419 @@ +/* + * Copyright © 2019-2020 Kevin Brace. + * Copyright 2012 James Simmons. All Rights Reserved. + * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2009 S3 Graphics, Inc. All Rights Reserved. + * + * 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 AUTHOR(S) OR COPYRIGHT HOLDER(S) 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. + * + * Author(s): + * Kevin Brace + * James Simmons + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "via_drv.h" + + +static void via_hide_cursor(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct pci_dev *pdev = to_pci_dev(dev->dev); + struct via_crtc *iga = container_of(crtc, + struct via_crtc, base); + struct via_drm_priv *dev_priv = to_via_drm_priv(dev); + uint32_t temp; + + switch (pdev->device) { + case PCI_DEVICE_ID_VIA_VT3157: + case PCI_DEVICE_ID_VIA_VT3343: + case PCI_DEVICE_ID_VIA_P4M900: + case PCI_DEVICE_ID_VIA_VT1122: + case PCI_DEVICE_ID_VIA_VX875: + case PCI_DEVICE_ID_VIA_VX900_VGA: + if (iga->index) { + temp = VIA_READ(HI_CONTROL); + VIA_WRITE(HI_CONTROL, temp & 0xFFFFFFFA); + } else { + temp = VIA_READ(PRIM_HI_CTRL); + VIA_WRITE(PRIM_HI_CTRL, temp & 0xFFFFFFFA); + } + + break; + default: + temp = VIA_READ(HI_CONTROL); + VIA_WRITE(HI_CONTROL, temp & 0xFFFFFFFA); + break; + } +} + +static void via_show_cursor(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct pci_dev *pdev = to_pci_dev(dev->dev); + struct via_crtc *iga = container_of(crtc, + struct via_crtc, base); + struct via_drm_priv *dev_priv = to_via_drm_priv(dev); + + switch (pdev->device) { + case PCI_DEVICE_ID_VIA_VT3157: + case PCI_DEVICE_ID_VIA_VT3343: + case PCI_DEVICE_ID_VIA_P4M900: + case PCI_DEVICE_ID_VIA_VT1122: + case PCI_DEVICE_ID_VIA_VX875: + case PCI_DEVICE_ID_VIA_VX900_VGA: + /* + * Program Hardware Icon (HI) FIFO, foreground color, + * and background color. + */ + if (iga->index) { + VIA_WRITE(HI_TRANSPARENT_COLOR, 0x00000000); + VIA_WRITE(HI_INVTCOLOR, 0x00FFFFFF); + VIA_WRITE(ALPHA_V3_PREFIFO_CONTROL, + 0x000E0000); + VIA_WRITE(ALPHA_V3_FIFO_CONTROL, 0x0E0F0000); + } else { + VIA_WRITE(PRIM_HI_TRANSCOLOR, 0x00000000); + VIA_WRITE(PRIM_HI_INVTCOLOR, 0x00FFFFFF); + VIA_WRITE(V327_HI_INVTCOLOR, 0x00FFFFFF); + VIA_WRITE(PRIM_HI_FIFO, 0x0D000D0F); + } + + break; + default: + /* + * Program Hardware Icon (HI) FIFO, foreground color, + * and background color. + */ + VIA_WRITE(HI_TRANSPARENT_COLOR, 0x00000000); + VIA_WRITE(HI_INVTCOLOR, 0x00FFFFFF); + VIA_WRITE(ALPHA_V3_PREFIFO_CONTROL, 0x000E0000); + VIA_WRITE(ALPHA_V3_FIFO_CONTROL, 0xE0F0000); + break; + } + + switch (pdev->device) { + case PCI_DEVICE_ID_VIA_VT3157: + case PCI_DEVICE_ID_VIA_VT3343: + case PCI_DEVICE_ID_VIA_P4M900: + case PCI_DEVICE_ID_VIA_VT1122: + case PCI_DEVICE_ID_VIA_VX875: + case PCI_DEVICE_ID_VIA_VX900_VGA: + /* + * Turn on Hardware Icon (HI). + */ + if (iga->index) { + VIA_WRITE(HI_CONTROL, 0xB6000005); + } else { + VIA_WRITE(PRIM_HI_CTRL, 0x36000005); + } + + break; + default: + /* + * Turn on Hardware Icon (HI). + */ + if (iga->index) { + VIA_WRITE(HI_CONTROL, 0xB6000005); + } else { + VIA_WRITE(HI_CONTROL, 0x36000005); + } + + break; + } +} + +static void via_cursor_address(struct drm_crtc *crtc, + struct ttm_buffer_object *ttm_bo) +{ + struct drm_device *dev = crtc->dev; + struct pci_dev *pdev = to_pci_dev(dev->dev); + struct via_crtc *iga = container_of(crtc, + struct via_crtc, base); + struct via_drm_priv *dev_priv = to_via_drm_priv(dev); + + switch (pdev->device) { + case PCI_DEVICE_ID_VIA_VT3157: + case PCI_DEVICE_ID_VIA_VT3343: + case PCI_DEVICE_ID_VIA_P4M900: + case PCI_DEVICE_ID_VIA_VT1122: + case PCI_DEVICE_ID_VIA_VX875: + case PCI_DEVICE_ID_VIA_VX900_VGA: + /* + * Program Hardware Icon (HI) offset. + */ + if (iga->index) { + VIA_WRITE(HI_FBOFFSET, + ttm_bo->resource->start << PAGE_SHIFT); + } else { + VIA_WRITE(PRIM_HI_FBOFFSET, + ttm_bo->resource->start << PAGE_SHIFT); + } + break; + default: + /* + * Program Hardware Icon (HI) offset. + */ + VIA_WRITE(HI_FBOFFSET, ttm_bo->resource->start << PAGE_SHIFT); + break; + } + + return; +} + +static void via_set_hi_location(struct drm_crtc *crtc, int crtc_x, int crtc_y) +{ + struct drm_device *dev = crtc->dev; + struct pci_dev *pdev = to_pci_dev(dev->dev); + struct via_crtc *iga = container_of(crtc, + struct via_crtc, base); + struct via_drm_priv *dev_priv = to_via_drm_priv(dev); + uint32_t location_x = 0, location_y = 0; + uint32_t offset_x = 0, offset_y = 0; + + if (crtc_x < 0) { + offset_x = -crtc_x; + } else { + location_x = crtc_x; + } + + if (crtc_y < 0) { + offset_y = -crtc_y; + } else { + location_y = crtc_y; + } + + switch (pdev->device) { + case PCI_DEVICE_ID_VIA_VT3157: + case PCI_DEVICE_ID_VIA_VT3343: + case PCI_DEVICE_ID_VIA_P4M900: + case PCI_DEVICE_ID_VIA_VT1122: + case PCI_DEVICE_ID_VIA_VX875: + case PCI_DEVICE_ID_VIA_VX900_VGA: + if (iga->index) { + VIA_WRITE(HI_POSSTART, + (((location_x & 0x07ff) << 16) | + (location_y & 0x07ff))); + VIA_WRITE(HI_CENTEROFFSET, + (((offset_x & 0x07ff) << 16) | + (offset_y & 0x07ff))); + } else { + VIA_WRITE(PRIM_HI_POSSTART, + (((location_x & 0x07ff) << 16) | + (location_y & 0x07ff))); + VIA_WRITE(PRIM_HI_CENTEROFFSET, + (((offset_x & 0x07ff) << 16) | + (offset_y & 0x07ff))); + } + + break; + default: + VIA_WRITE(HI_POSSTART, + (((location_x & 0x07ff) << 16) | + (location_y & 0x07ff))); + VIA_WRITE(HI_CENTEROFFSET, + (((offset_x & 0x07ff) << 16) | + (offset_y & 0x07ff))); + break; + } +} + +static int via_cursor_prepare_fb(struct drm_plane *plane, + struct drm_plane_state *new_state) +{ + struct drm_gem_object *gem; + struct ttm_buffer_object *ttm_bo; + struct via_bo *bo; + int ret = 0; + + DRM_DEBUG_KMS("Entered %s.\n", __func__); + + if (!new_state->fb) { + goto exit; + } + + gem = new_state->fb->obj[0]; + ttm_bo = container_of(gem, struct ttm_buffer_object, base); + bo = to_ttm_bo(ttm_bo); + + ret = ttm_bo_reserve(ttm_bo, true, false, NULL); + if (ret) { + goto exit; + } + + ret = via_bo_pin(bo, TTM_PL_VRAM); + ttm_bo_unreserve(ttm_bo); + ret = ttm_bo_kmap(ttm_bo, 0, ttm_bo->resource->num_pages, &bo->kmap); + if (ret) { + goto exit; + } + +exit: + DRM_DEBUG_KMS("Exiting %s.\n", __func__); + return ret; +} + +static void via_cursor_cleanup_fb(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct drm_gem_object *gem; + struct ttm_buffer_object *ttm_bo; + struct via_bo *bo; + int ret; + + DRM_DEBUG_KMS("Entered %s.\n", __func__); + + if (!old_state->fb) { + goto exit; + } + + gem = old_state->fb->obj[0]; + ttm_bo = container_of(gem, struct ttm_buffer_object, base); + bo = to_ttm_bo(ttm_bo); + + ttm_bo_kunmap(&bo->kmap); + ret = ttm_bo_reserve(ttm_bo, true, false, NULL); + if (ret) { + goto exit; + } + + via_bo_unpin(bo); + ttm_bo_unreserve(ttm_bo); + +exit: + DRM_DEBUG_KMS("Exiting %s.\n", __func__); +} + +static int via_cursor_atomic_check(struct drm_plane *plane, + struct drm_atomic_state *state) +{ + struct drm_plane_state *new_plane_state = + drm_atomic_get_new_plane_state(state, plane); + struct drm_crtc_state *new_crtc_state; + struct drm_framebuffer *fb = new_plane_state->fb; + int ret = 0; + + DRM_DEBUG_KMS("Entered %s.\n", __func__); + + if ((!new_plane_state->crtc) || (!new_plane_state->visible)) { + goto exit; + } + + if (fb->width != fb->height) { + DRM_ERROR("Hardware cursor is expected to have " + "square dimensions.\n"); + ret = -EINVAL; + goto exit; + } + + new_crtc_state = drm_atomic_get_new_crtc_state(state, + new_plane_state->crtc); + ret = drm_atomic_helper_check_plane_state( + new_plane_state, + new_crtc_state, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + true, true); +exit: + DRM_DEBUG_KMS("Exiting %s.\n", __func__); + return ret; +} + +static void via_cursor_atomic_update(struct drm_plane *plane, + struct drm_atomic_state *state) +{ + struct drm_plane_state *new_state = + drm_atomic_get_new_plane_state(state, plane); + struct drm_plane_state *old_state = + drm_atomic_get_old_plane_state(state, plane); + struct drm_crtc *crtc = new_state->crtc; + struct drm_gem_object *gem; + struct ttm_buffer_object *ttm_bo; + + DRM_DEBUG_KMS("Entered %s.\n", __func__); + + if (new_state->fb != old_state->fb) { + gem = new_state->fb->obj[0]; + ttm_bo = container_of(gem, struct ttm_buffer_object, base); + via_cursor_address(crtc, ttm_bo); + } + + via_set_hi_location(crtc, new_state->crtc_x, new_state->crtc_y); + via_show_cursor(crtc); + + DRM_DEBUG_KMS("Exiting %s.\n", __func__); +} + +void via_cursor_atomic_disable(struct drm_plane *plane, + struct drm_atomic_state *state) +{ + struct drm_plane_state *new_state = + drm_atomic_get_new_plane_state(state, plane); + struct drm_crtc *crtc = new_state->crtc; + + DRM_DEBUG_KMS("Entered %s.\n", __func__); + + if (crtc) { + via_hide_cursor(crtc); + } + + DRM_DEBUG_KMS("Exiting %s.\n", __func__); +} + +const struct drm_plane_helper_funcs via_cursor_drm_plane_helper_funcs = { + .prepare_fb = via_cursor_prepare_fb, + .cleanup_fb = via_cursor_cleanup_fb, + .atomic_check = via_cursor_atomic_check, + .atomic_update = via_cursor_atomic_update, + .atomic_disable = via_cursor_atomic_disable, +}; + +const struct drm_plane_funcs via_cursor_drm_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + .reset = drm_atomic_helper_plane_reset, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, +}; + +const uint32_t via_cursor_formats[] = { + DRM_FORMAT_ARGB8888, +}; + +const unsigned int via_cursor_formats_size = + ARRAY_SIZE(via_cursor_formats);