From nobody Mon Sep 28 08:12:16 2026 Received: from mail-wm1-f43.google.com (mail-wm1-f43.google.com [209.85.128.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A49E512D1F1 for ; Tue, 25 Aug 2026 00:14:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787616885; cv=none; b=hVJEqjRXlTW0M00wsBB6X+vZlG0o6e7kEGzEErpn7pc9nJdozNNXFalwxfOUD+fMoQC+3HckKivteSFABpxv9U3g5qAtHIFc7P/5B4/eIo5odGBbw7DTXn6tK4Pl/c2r4iG1hdyStNci8kaWwHP2hnww5bqVDpLbDdCCitzhXuk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787616885; c=relaxed/simple; bh=plz2a+CWfqDmsfsV8vUbs5gQ2DLeAQR+DAafoCpZbOE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RrXsgjFfbUAFG7wsOvWbcLTlWUbVKELdd0hJNJpP3S/OLW0AIwi+9kNoBsY0K7PnaQWgdOtlMa7J17B1GUzvdrib7Llvyp9VqgTzIsTtKtaGIXQ5B7EU4zxbLo+PKERX1cgdc9ltkhTVA9G0DfZQhyGZCw61dTCpLLYUJtOQvd4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=QFPgbFqN; arc=none smtp.client-ip=209.85.128.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="QFPgbFqN" Received: by mail-wm1-f43.google.com with SMTP id 5b1f17b1804b1-49556f97a9dso23370155e9.1 for ; Mon, 24 Aug 2026 17:14:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787616882; x=1788221682; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=RuAEk+4LiQhkycCwL92SfZ2A4rYOkzcfHz0DHKAe0bE=; b=QFPgbFqNzLWeubX5OaYmvwktzLd8hl6ehe/Am+Vp+cmuuj/UZ0zyxpi+OJ0YaCJEv8 vta9+PjGriO8br9ZUUFcSZ5C+cnvbVhd1i2oyFrZ+oCJKbiOzzXR8bJEEHcc4SIf+7Qy sqvKQLjOJv7+f01FkfjcMRWwlSWVcU5ZdUM/NS3jfLbFw9hkL+DX9skUL1HjpAO3x903 ioh0PCYgmTIG1d33s55/BW5SJyh3q1RH93NmP85XBD6eIW07Ek66L5K3ssLHl92qLQbz w2iUHxpID+z4d8ndlEwKUjc8xtxm9h4QlL6f0FEMyKqH9m1uRN10d1VN/Af/qsJ4wOpx olcQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787616882; x=1788221682; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=RuAEk+4LiQhkycCwL92SfZ2A4rYOkzcfHz0DHKAe0bE=; b=QNoQyL5DukC2w2QXJ/fEC+AQ0oSKn1MVm2iPAJGw5cyd1yZFF3hDwtB23LvnS/gkXX bW7v+881o/iVZs40cF7MYhxg+knuZpJzw0h9txafvzzye+gX4BTeGUeg9EQQrwG3bmU2 ThVeNvoWmMIKtcNQ7ZtoOXNY9y/O0vEi0E7/ud7p5kK6OwvVkjenf1EPXLcSn1d369WA hq5n8XIt+Eij/uwcsKt91y/kOezhcFbI+upK20dW3n/5ysdv3TQ5CcCMZTnPSA7XBhQv l2E9wYWHsxe1RKk+ZmmDZU9WMwVcgNgiIriR3c3z580cJgoAxgKjOJ2U+i8MrVbSRR03 gwCQ== X-Gm-Message-State: AFuF++nW/sXoFYMvTYkXQ/YWRKm1AaBpCPfwmKWHxRTDb6aNh59hyGJk HKnfSEqTh4SRZ0kq4BhOygQGT7L3eAHDHZ2Jr3CQ97V3k2IN1EsWl5KqzKE1j6jh X-Gm-Gg: AR+sD12RA27TZg4k/ZYFilvvLGfBmRYCratfoGjywASAY99/QXl1aIlEV7WMsIwXal7 nHo1fIlFZZWxZQe+Xn3tbX72SCCOgoYNQ3UuCvSff6/RF0mqc7vwtzs58GyB4gs4o1fowYVpE+4 AmB4autJ2x9jtzI8R6tdE5+JsUw+TlTZr9DLLOl3uJW6uAXWqTxKXmE9hSXscGsTTjcPmbScbfp x9yPp78E64Qf+MvncJ2WIRyQEGLEHSNt/QPp/kNrnqW9OVsaLAB2e1Ttqg0HHYJOQlfz3VKyggL 7mN5vTlAL85QrmjsogHU0Xc+pd2ZC/iaHoG2P/N8k2/PblqDNhTxdoWiard3iwAF1Kp06ymFm09 gUjrV8Emef67Ss32pW/Wy772IlMEdvE/qdA86gQwk4FaJ0WRGWZuC3JMRRxyj2KUJCpD0M0p6LY Yu7vFBgDthH77+qQJNfnFnxY6eE3Ri09yuU8MYPzIn0mVfUAd2X4XZE0lVCTIzNLsMMH5YH9oXZ strCw== X-Received: by 2002:a05:600c:474a:b0:499:b65d:124f with SMTP id 5b1f17b1804b1-499b845709amr367619755e9.11.1787616881745; Mon, 24 Aug 2026 17:14:41 -0700 (PDT) Received: from fedora ([5.31.134.170]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-482c9b78ebfsm9770676f8f.12.2026.08.24.17.14.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Aug 2026 17:14:40 -0700 (PDT) From: Mohamed Ahmed To: linux-kernel@vger.kernel.org Cc: dri-devel@lists.freedesktop.org, Lyude Paul , Danilo Krummrich , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Mary Guillemard , nouveau@lists.freedesktop.org, Mohamed Ahmed , stable@vger.kernel.org Subject: [PATCH v3 01/10] drm/nouveau/disp: move GSP head-timing ISR and vblank helpers to tu102.c Date: Tue, 25 Aug 2026 04:13:59 +0400 Message-ID: <20260825001408.14219-2-mohamedahmedegypt2001@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260825001408.14219-1-mohamedahmedegypt2001@gmail.com> References: <20260825001408.14219-1-mohamedahmedegypt2001@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The GSP-RM display code in rm/r535/disp.c owns a handful of direct MMIO routines: the head-timing (vblank) interrupt handler and the per-head vblank enable/disable. They program display registers, not RM, so they belong with the rest of the per-chip register code in engine/disp/. Move them to tu102.c (Turing is the first GSP-capable generation) as tu102_disp_intr() and tu102_head_vblank_get()/put(), exported for rm/r535/disp.c, which keeps calling them by name for now. No functional change. Fixes: 6cc6e08d4542 ("drm/nouveau/kms: add support for GB20x") Cc: stable@vger.kernel.org Signed-off-by: Mohamed Ahmed Reviewed-by: Lyude Paul --- .../gpu/drm/nouveau/nvkm/engine/disp/head.h | 3 ++ .../gpu/drm/nouveau/nvkm/engine/disp/priv.h | 1 + .../gpu/drm/nouveau/nvkm/engine/disp/tu102.c | 50 ++++++++++++++++++ .../nouveau/nvkm/subdev/gsp/rm/r535/disp.c | 52 ++----------------- 4 files changed, 57 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h b/drivers/gpu/= drm/nouveau/nvkm/engine/disp/head.h index b642729c254f..986043e87554 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h @@ -56,6 +56,9 @@ int gv100_head_new(struct nvkm_disp *, int id); void gv100_head_state(struct nvkm_head *head, struct nvkm_head_state *stat= e); void gv100_head_rgpos(struct nvkm_head *head, u16 *hline, u16 *vline); =20 +void tu102_head_vblank_get(struct nvkm_head *); +void tu102_head_vblank_put(struct nvkm_head *); + #define HEAD_MSG(h,l,f,a...) do { = \ struct nvkm_head *_h =3D (h); \ nvkm_##l(&_h->disp->engine.subdev, "head-%d: "f"\n", _h->id, ##a); \ diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h b/drivers/gpu/= drm/nouveau/nvkm/engine/disp/priv.h index a3fd7cb7c488..722ec340e12a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h @@ -72,6 +72,7 @@ int gv100_disp_wndw_cnt(struct nvkm_disp *, unsigned long= *); int gv100_disp_caps_new(const struct nvkm_oclass *, void *, u32, struct nv= km_object **); =20 int tu102_disp_init(struct nvkm_disp *); +irqreturn_t tu102_disp_intr(struct nvkm_inth *); =20 void nv50_disp_dptmds_war_2(struct nvkm_disp *, struct dcb_output *); void nv50_disp_dptmds_war_3(struct nvkm_disp *, struct dcb_output *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c b/drivers/gpu= /drm/nouveau/nvkm/engine/disp/tu102.c index dcb9f8ba374c..7b70b466fa36 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c @@ -104,6 +104,56 @@ tu102_sor_new(struct nvkm_disp *disp, int id) return nvkm_ior_new_(&tu102_sor, disp, SOR, id, hda & BIT(id)); } =20 +/* The GSP-RM display path leaves head-timing (vblank) interrupts and their + * enables to us. These program the RM head-timing line (bit 1 of the + * per-head enable, not the bit nvkm's own gv100 path uses). + */ +void +tu102_head_vblank_put(struct nvkm_head *head) +{ + struct nvkm_device *device =3D head->disp->engine.subdev.device; + + nvkm_mask(device, 0x611d80 + (head->id * 4), 0x00000002, 0x00000000); +} + +void +tu102_head_vblank_get(struct nvkm_head *head) +{ + struct nvkm_device *device =3D head->disp->engine.subdev.device; + + nvkm_wr32(device, 0x611800 + (head->id * 4), 0x00000002); + nvkm_mask(device, 0x611d80 + (head->id * 4), 0x00000002, 0x00000002); +} + +static void +tu102_disp_intr_head_timing(struct nvkm_disp *disp, int head) +{ + struct nvkm_subdev *subdev =3D &disp->engine.subdev; + struct nvkm_device *device =3D subdev->device; + u32 stat =3D nvkm_rd32(device, 0x611c00 + (head * 0x04)); + + if (stat & 0x00000002) { + nvkm_disp_vblank(disp, head); + + nvkm_wr32(device, 0x611800 + (head * 0x04), 0x00000002); + } +} + +irqreturn_t +tu102_disp_intr(struct nvkm_inth *inth) +{ + struct nvkm_disp *disp =3D container_of(inth, typeof(*disp), engine.subde= v.inth); + struct nvkm_subdev *subdev =3D &disp->engine.subdev; + struct nvkm_device *device =3D subdev->device; + unsigned long mask =3D nvkm_rd32(device, 0x611ec0) & 0x000000ff; + int head; + + for_each_set_bit(head, &mask, 8) + tu102_disp_intr_head_timing(disp, head); + + return IRQ_HANDLED; +} + int tu102_disp_init(struct nvkm_disp *disp) { diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c b/drive= rs/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c index e77733a5d9c3..8e57bb6519e5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c @@ -608,29 +608,12 @@ r535_sor_cnt(struct nvkm_disp *disp, unsigned long *p= mask) return 4; } =20 -static void -r535_head_vblank_put(struct nvkm_head *head) -{ - struct nvkm_device *device =3D head->disp->engine.subdev.device; - - nvkm_mask(device, 0x611d80 + (head->id * 4), 0x00000002, 0x00000000); -} - -static void -r535_head_vblank_get(struct nvkm_head *head) -{ - struct nvkm_device *device =3D head->disp->engine.subdev.device; - - nvkm_wr32(device, 0x611800 + (head->id * 4), 0x00000002); - nvkm_mask(device, 0x611d80 + (head->id * 4), 0x00000002, 0x00000002); -} - static const struct nvkm_head_func r535_head =3D { .state =3D gv100_head_state, .rgpos =3D gv100_head_rgpos, - .vblank_get =3D r535_head_vblank_get, - .vblank_put =3D r535_head_vblank_put, + .vblank_get =3D tu102_head_vblank_get, + .vblank_put =3D tu102_head_vblank_put, }; =20 static struct nvkm_conn * @@ -1404,35 +1387,6 @@ static const struct nvkm_event_func r535_disp_event =3D { }; =20 -static void -r535_disp_intr_head_timing(struct nvkm_disp *disp, int head) -{ - struct nvkm_subdev *subdev =3D &disp->engine.subdev; - struct nvkm_device *device =3D subdev->device; - u32 stat =3D nvkm_rd32(device, 0x611c00 + (head * 0x04)); - - if (stat & 0x00000002) { - nvkm_disp_vblank(disp, head); - - nvkm_wr32(device, 0x611800 + (head * 0x04), 0x00000002); - } -} - -static irqreturn_t -r535_disp_intr(struct nvkm_inth *inth) -{ - struct nvkm_disp *disp =3D container_of(inth, typeof(*disp), engine.subde= v.inth); - struct nvkm_subdev *subdev =3D &disp->engine.subdev; - struct nvkm_device *device =3D subdev->device; - unsigned long mask =3D nvkm_rd32(device, 0x611ec0) & 0x000000ff; - int head; - - for_each_set_bit(head, &mask, 8) - r535_disp_intr_head_timing(disp, head); - - return IRQ_HANDLED; -} - static void r535_disp_fini(struct nvkm_disp *disp, bool suspend) { @@ -1708,7 +1662,7 @@ r535_disp_oneinit(struct nvkm_disp *disp) return ret; =20 ret =3D nvkm_inth_add(&device->vfn->intr, ret, NVKM_INTR_PRIO_NORMAL, &di= sp->engine.subdev, - r535_disp_intr, &disp->engine.subdev.inth); + tu102_disp_intr, &disp->engine.subdev.inth); if (ret) return ret; =20 --=20 2.55.0 From nobody Mon Sep 28 08:12:16 2026 Received: from mail-wr1-f42.google.com (mail-wr1-f42.google.com [209.85.221.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ADEC914883F for ; Tue, 25 Aug 2026 00:14:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787616893; cv=none; b=QuPm/ixnmQCVNwj/kGwEvGBWsVBMwxuK6+AxMT1pK55zwOjrgEhS6nS9vHlyZuv3iiLWKSB9fFpFqLseA/2TvBK4ae85dGgxqwG88MYeM3Eqx1YCld+ZWQideiR+G7Q+SsGpH7jnLKnHJ/+9dI9vNEW6/XuLgRN45rflVfBGkhU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787616893; c=relaxed/simple; bh=ze/HLi/pQf5IGVEyhSdxRYFBhUH7CZ1PfAlGbkDO+WU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YMHYNAdFOzA+8s6pXfMjHES9PC1T8fh9mkc4n6nLbVjry9uIiyuCf0gdN7U5PfgvVioDZ42ZCu50sXeHP0LN/enAqE2v4l2qE/iEniE+vbSt2IokEvLuxYs6FKeYiwJyzGwWqVPidZ0y58DGxRFIqVX1B1Fd+hTJlXT7Hfmb0X0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=kCFntH9A; arc=none smtp.client-ip=209.85.221.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="kCFntH9A" Received: by mail-wr1-f42.google.com with SMTP id ffacd0b85a97d-47fd66a094eso1187996f8f.3 for ; Mon, 24 Aug 2026 17:14:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787616890; x=1788221690; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=x04IiTfhYJXNOaOqTfXwDySQqeqgSixvxmzpY3etBHo=; b=kCFntH9AwbZEbdHtsrB1ilGtZ4X0so5UXVVRwUn67Ept6Dt7QkC8lDTrFz/ralsf3O V9dDtCbAYghIMrTXoX7KijUECKYFWNpmr7iohdVI2xILa756v6iCgmpBXMYNuQ/APvv/ t9mLUaH/GyVjnzR/PGPMF+ZUgLG19VVKXX/04u4gtdEYHFHGrQNAlIv939kEZMd3VrJG Ct9CHBl+mdiSO+SfoLtiiVCUx9DMOIshAc4YnJsFozVf4l2iCXtIvUCnsghpLsJW6ee2 fVaak9nZlUFS8h+XZOh9ouaVshmIK2NlaAwE1mPjJwvyMC9gV8BJPvPAGrFqu2wGXcL6 ZS5w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787616890; x=1788221690; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=x04IiTfhYJXNOaOqTfXwDySQqeqgSixvxmzpY3etBHo=; b=VfjHaUbunCTrm37c0Yuy/GIRcwN3xT57InO3FVfUu18oZYablkc29/rp/UNOIXJcdh D+V0tfMu9zzMG9PH4v3zyoKe8dSMXbvOL5anwIG1lbseKF1GPEtMYkMekYdfPMNWpF2U HMp9R9XwRK1KvV0kCNPEtg4bMa2NIfx2qgDrJFSIam/KX12XVQAZxkCdjGUJ2FB2ear5 rmobkA5fe4FuytsocRVCw2OL3rdwFiqgl+syKQu0YYtGlP/Fa3q8hrYCtK6tCLA+c3Ey YSpY6EDoxNnEOzM8sEIiA0z4Eh6wR5SWGKObJJ8d5nS91kcSn0Hc/WowVYdVAfOTnzEc Qsyw== X-Gm-Message-State: AFuF++lrHKKe+C1+tsuJZJbToAL+P56/cn4fYexDoc/knGORIAmaTO31 UadEuSZ2Cx79UwIOlVaqD0VSjG3uO+yY7eqmv+BX5xGKmQHQQa4Qawcy5dOKD4gR X-Gm-Gg: AR+sD12PYLxNvem88KxV+zjsLyH3Lp/wbpkDekX99/+1NMwtEaAHH/SFpmfuiVIR7Zm iRJ58WGT7O59HBWIG6+GKCNqtxxfEGw+M0IOGeYYJ8vCaqwfk+sQGNSpJzKAu8yAnmI58z2pP15 eOc1r59LneWI6YA3yOQaDQTjlu2PbGCmb/v8vRlAPi/wy6Ux0uUZq6mMcZypUY46sMH8K5aGM1B SxHMTCKSMDrU24rXRaDgsVHtNFklR8mfhPrBn53OCWg4QYeYe47qqTu3QYEuRxxh9GlstmvIOjR aDrZuZpxTWbor2IGO3HW5iyHInLi/POcNQYTdmH22iUtE1+sbqzfxF3J8YK8ETIzOx2zvSERFNY kRcWBkrPTMM2ui4+qYUc6zxFUuy4R4Z8MvngzJt/PHQd6yhhBjX0y2m2kLnabu9WhP41rAue4kq V1oLMRFMJ7PUJE5X5ADI0mf09WlOvaR3l8cweaGc+tn0OeDpTbSYjwnJCbp+Vg4H57qCi2WFCWg Mve3Q== X-Received: by 2002:a05:6000:2309:b0:47f:9447:62bf with SMTP id ffacd0b85a97d-482c0b54855mr37921273f8f.2.1787616889861; Mon, 24 Aug 2026 17:14:49 -0700 (PDT) Received: from fedora ([5.31.134.170]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-482c9b78ebfsm9770676f8f.12.2026.08.24.17.14.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Aug 2026 17:14:48 -0700 (PDT) From: Mohamed Ahmed To: linux-kernel@vger.kernel.org Cc: dri-devel@lists.freedesktop.org, Lyude Paul , Danilo Krummrich , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Mary Guillemard , nouveau@lists.freedesktop.org, Mohamed Ahmed , stable@vger.kernel.org Subject: [PATCH v3 02/10] drm/nouveau/disp: move the GSP HDMI GCP AVMute write to engine/disp Date: Tue, 25 Aug 2026 04:14:00 +0400 Message-ID: <20260825001408.14219-3-mohamedahmedegypt2001@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260825001408.14219-1-mohamedahmedegypt2001@gmail.com> References: <20260825001408.14219-1-mohamedahmedegypt2001@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" r535_sor_hdmi_audio() pairs two RM controls (a SET_OD_PACKET carrying the same General Control Packet, and the audio mute-stream toggle) with a direct write of the GCP AVMute bit through the SF GCP unit. The controls are RM and stay, but the direct write is register programming and moves next to the other per-chip display code as tu102_sor_hdmi_gcp(). No functional change. Fixes: 6cc6e08d4542 ("drm/nouveau/kms: add support for GB20x") Cc: stable@vger.kernel.org Signed-off-by: Mohamed Ahmed Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c | 15 +++++++++++++++ .../drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c | 9 +-------- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h b/drivers/gpu/d= rm/nouveau/nvkm/engine/disp/ior.h index 3ba04bead2f9..5d682a774f2d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h @@ -194,6 +194,7 @@ void gv100_sor_dp_audio_sym(struct nvkm_ior *, int, u16= , u32); void gv100_sor_dp_watermark(struct nvkm_ior *, int, u8); extern const struct nvkm_ior_func_hda gv100_sor_hda; =20 +void tu102_sor_hdmi_gcp(struct nvkm_ior *, int, bool); void tu102_sor_dp_vcpi(struct nvkm_ior *, int, u8, u8, u16, u16); =20 int nv50_pior_cnt(struct nvkm_disp *, unsigned long *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c b/drivers/gpu= /drm/nouveau/nvkm/engine/disp/tu102.c index 7b70b466fa36..6cfd52c9056f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c @@ -30,6 +30,21 @@ =20 #include =20 +/* General Control Packet: bracket an audio enable/disable with AVMute + * through the legacy GCP SF unit. Used by the GSP-RM path, which sends the + * equivalent packet via RM as well but keeps the direct write in sync. + */ +void +tu102_sor_hdmi_gcp(struct nvkm_ior *sor, int head, bool enable) +{ + struct nvkm_device *device =3D sor->disp->engine.subdev.device; + const u32 hdmi =3D head * 0x400; + + nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000000); + nvkm_wr32(device, 0x6f00cc + hdmi, !enable ? 0x00000001 : 0x00000010); + nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000001); +} + void tu102_sor_dp_vcpi(struct nvkm_ior *sor, int head, u8 slot, u8 slot_nr, u16= pbn, u16 aligned) { diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c b/drive= rs/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c index 8e57bb6519e5..cd4451e62512 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c @@ -545,16 +545,9 @@ r535_sor_hdmi_ctrl_audio(struct nvkm_outp *outp, bool = enable) static void r535_sor_hdmi_audio(struct nvkm_ior *sor, int head, bool enable) { - struct nvkm_device *device =3D sor->disp->engine.subdev.device; - const u32 hdmi =3D head * 0x400; - r535_sor_hdmi_ctrl_audio(sor->asy.outp, enable); r535_sor_hdmi_ctrl_audio_mute(sor->asy.outp, !enable); - - /* General Control (GCP). */ - nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000000); - nvkm_wr32(device, 0x6f00cc + hdmi, !enable ? 0x00000001 : 0x00000010); - nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000001); + tu102_sor_hdmi_gcp(sor, head, enable); } =20 static void --=20 2.55.0 From nobody Mon Sep 28 08:12:16 2026 Received: from mail-wr1-f46.google.com (mail-wr1-f46.google.com [209.85.221.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AA87B146A66 for ; Tue, 25 Aug 2026 00:14:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787616900; cv=none; b=MiZvsD+99KjU3q4mF7Cvb2VC+fTWIi1gIEcnJdDOMrsAJQihXO4545Qck5r6f1LXnS6XTQWf0kp98i7IVESeUuVJ4tnG5e8smktRnK4jNBlN0sMDJZJDPB/UZi3aBBCbhDql88v1V4Y0aPS2ygS8nDWgv1LRA5tnGx5I/B528Y0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787616900; c=relaxed/simple; bh=kNredZuAlzjuDwRpspH7wjFFwwIUPwrovOTOeiItUDo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=t/01N9YEt2qnTBUZVC3austW6zDmpNoaeU4tpKHiMBlNMYUVMfsjDwPzUVb761EFdb++8bAWCoZLUOoSkYKf9JsIKXSmV0r4ovQREMRdU8ikINdGyvquVQ6zRTJkC/Xqx6ipodtbiBiLTVvRtXCZPk2h7JP7Gd3EDpZowv7wi4s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Vh8iEzPQ; arc=none smtp.client-ip=209.85.221.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Vh8iEzPQ" Received: by mail-wr1-f46.google.com with SMTP id ffacd0b85a97d-47fecbb7000so1566628f8f.2 for ; Mon, 24 Aug 2026 17:14:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787616897; x=1788221697; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=d/NYE+hsr/DHtPZiO0MS/H4/xrbfs8tes2shrGKnSKU=; b=Vh8iEzPQYeXV0ywZY1Mf57XTZgwyJ3uookqLBBqheco/54FnbUSEDiahCIsmIxNl1R BEEyM0tU8c6QFgTLn8mVZHoFNf8tnROf4G8c75COnjz/ifL5U1oPIX+njT69dDHvW3Gt W6iEYD8yRxiveJOp4iSVsPHuExOCneIOuHYIYKhcZ701yHhl38TiQD3/h3Iz3dXHPTjA 4fpE4G/BMirMFwc0HCSdKBOoAZ69T9E7Pl8wZU9jMIz8cKRWnxpNk8JylLQg1n3mGeZN ivliYWM4A2/ADmfYvvPnUXIyeegj9OiVEuWNOSU7UuqdEPMTKW9mhd+TIrnQo7hkVCJ5 C49g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787616897; x=1788221697; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=d/NYE+hsr/DHtPZiO0MS/H4/xrbfs8tes2shrGKnSKU=; b=hJ6a/PgsusG3vOlU3EYTud5gbUls9HwyieOjNYhoT0w+RReIEIoHOu8c9W8wtY5Ygw aZhlKrgiL+yVytupYlfYd1Qs/pPVfkHPd4sB+mudR3vgOVMunNYKXzUdU+JgEbRmpxNL NX4G62hJYwWlG/6aTy5Sl5wm47iQyj4DBceSue9A/qOarwzi2D+NnZr06UEa4erIFEYe CXj7kqS1h6rjHy125ZeE63klOGM4qIaRgJziDjWJPu6EapKVeLWZxzlj/q07M/uDw+Fc cDkg/BcMI0fzIgwx+DRKRjieEBYng+pmLVl12dDYjC58DZ4C4oXD2aRh1zWfpLAXbI/6 dLlQ== X-Gm-Message-State: AFuF++l4Bjg7xn7nlSnv5sEX1HUcNVrehYHmj0wPQZpFedkWdte/OjwR VLGYfSUBKZbc9mE4qL7DZTF5tJVVox8Q9KWC895r6H+L8BLYjMOo5Oz6DxUk+yXq X-Gm-Gg: AR+sD13jtfXABeUKXgEOLmAZZ7QSTK8TFLc12aOQp8lYOtVyW4MI6osaetwGMU9r2IS PW0pdZGI+WY36l5sl0DAa6EOOQW7ysMaFg8ovK9gEbwDhxGmK2OsqTkQwIfrfJWy6ZoWytcwoiX 9edxQurOVWcYztN5X2aFtrTxYiGys3c3ma1VtreqO4vMSlm25YAB2UrFh50bvbbighQX7EFVK3K Ifv6LJRk4QoGHFTdg/yWMWPiXUu006Kv5g26rBySkZkF2ButNfUYoW+RyUA/2Y1yVFW9scAIxKk bPsHtOFaQkQ7tac/e/HJbaSe1sd+McbHEVY7Abfv4fFn8uLvBfqcl54fVk9nh88Vn3VbUnOSoZI 9BRvTlRD5MQEaTHX9m5s/miJWGrWS3AzlgWkBoAJCCu8IfL7fKGyJd3w5ZbrdEGAh1mb0pv/hbZ C+7hDGHs2TQN3CZaA2why2yPDeQ/YivB+B/1n3JTZac9vA87Nkc1w0HetlcK1FM+Q1pdtuTOEI0 U1W5A== X-Received: by 2002:a05:6000:2f88:b0:47f:6f6a:6a7f with SMTP id ffacd0b85a97d-482c817b196mr24504551f8f.8.1787616896742; Mon, 24 Aug 2026 17:14:56 -0700 (PDT) Received: from fedora ([5.31.134.170]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-482c9b78ebfsm9770676f8f.12.2026.08.24.17.14.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Aug 2026 17:14:55 -0700 (PDT) From: Mohamed Ahmed To: linux-kernel@vger.kernel.org Cc: dri-devel@lists.freedesktop.org, Lyude Paul , Danilo Krummrich , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Mary Guillemard , nouveau@lists.freedesktop.org, Mohamed Ahmed , stable@vger.kernel.org Subject: [PATCH v3 03/10] drm/nouveau/disp: route GSP-RM display MMIO through nvkm_disp_func hooks Date: Tue, 25 Aug 2026 04:14:01 +0400 Message-ID: <20260825001408.14219-4-mohamedahmedegypt2001@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260825001408.14219-1-mohamedahmedegypt2001@gmail.com> References: <20260825001408.14219-1-mohamedahmedegypt2001@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The GSP-RM display code in rm/r535/disp.c borrows a few register-programming routines from engine/disp (the head-timing interrupt handler, vblank enables, armed head state and scanout position readback, the AVI/VSI infoframe writers and the GCP AVMute write) and so far picked them by name, which means it has to know which chip it runs on the moment a generation changes any of them. Give nvkm_disp_func a .gsp table that each chip fills with exactly those hooks, add tu102_gsp_disp (TU1xx) and ga102_gsp_disp (GA10x onwards) carrying the current functions, hand them to r535_disp_new() instead of the full hardware tables, and make rm/r535/disp.c call through the hooks. The head hooks are a whole nvkm_head_func, so r535_head goes away and the chip's own table is handed to nvkm_head_new_(). r535_sor_hdmi gets infoframe forwarders, r535_sor_hdmi_audio() calls the GCP hook, and the interrupt handler comes from the table. The tables are per chip even though the two currently coincide, so a generation that changes a hook only touches its own file. rm/r535/disp.c no longer contains chip-specific register code, and a new display generation only has to provide its own table. No functional change. Fixes: 6cc6e08d4542 ("drm/nouveau/kms: add support for GB20x") Cc: stable@vger.kernel.org Signed-off-by: Mohamed Ahmed Reviewed-by: Lyude Paul --- .../gpu/drm/nouveau/nvkm/engine/disp/ga102.c | 13 +++++++- .../gpu/drm/nouveau/nvkm/engine/disp/head.h | 1 + .../gpu/drm/nouveau/nvkm/engine/disp/priv.h | 14 +++++++++ .../gpu/drm/nouveau/nvkm/engine/disp/tu102.c | 21 ++++++++++++- .../nouveau/nvkm/subdev/gsp/rm/r535/disp.c | 31 +++++++++++-------- 5 files changed, 65 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c b/drivers/gpu= /drm/nouveau/nvkm/engine/disp/ga102.c index ab0a85c92430..820834b5ee9b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c @@ -144,12 +144,23 @@ ga102_disp =3D { }, }; =20 +static const struct nvkm_disp_func +ga102_gsp_disp =3D { + .uevent =3D &gv100_disp_chan_uevent, + .ramht_size =3D 0x2000, + .gsp.intr =3D tu102_disp_intr, + .gsp.head =3D &tu102_gsp_head, + .gsp.hdmi_gcp =3D tu102_sor_hdmi_gcp, + .gsp.hdmi_infoframe_avi =3D gv100_sor_hdmi_infoframe_avi, + .gsp.hdmi_infoframe_vsi =3D gv100_sor_hdmi_infoframe_vsi, +}; + int ga102_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int= inst, struct nvkm_disp **pdisp) { if (nvkm_gsp_rm(device->gsp)) - return r535_disp_new(&ga102_disp, device, type, inst, pdisp); + return r535_disp_new(&ga102_gsp_disp, device, type, inst, pdisp); =20 return nvkm_disp_new_(&ga102_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h b/drivers/gpu/= drm/nouveau/nvkm/engine/disp/head.h index 986043e87554..784521c2aca1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h @@ -58,6 +58,7 @@ void gv100_head_rgpos(struct nvkm_head *head, u16 *hline,= u16 *vline); =20 void tu102_head_vblank_get(struct nvkm_head *); void tu102_head_vblank_put(struct nvkm_head *); +extern const struct nvkm_head_func tu102_gsp_head; =20 #define HEAD_MSG(h,l,f,a...) do { = \ struct nvkm_head *_h =3D (h); \ diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h b/drivers/gpu/= drm/nouveau/nvkm/engine/disp/priv.h index 722ec340e12a..a9dbda67a7d4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h @@ -5,6 +5,8 @@ #include #include struct nvkm_head; +struct nvkm_head_func; +struct nvkm_ior; struct nvkm_outp; struct dcb_output; =20 @@ -34,6 +36,18 @@ struct nvkm_disp_func { int (*new)(struct nvkm_disp *, int id); } wndw, head, dac, sor, pior; =20 + /* Register programming that the GSP-RM display path (rm/r535) needs from + * the chip, everything else on that path goes through RM. The hooks are + * called unconditionally and the head table is handed to nvkm_head_new_(= ). + */ + struct { + irqreturn_t (*intr)(struct nvkm_inth *); + const struct nvkm_head_func *head; + void (*hdmi_gcp)(struct nvkm_ior *, int head, bool enable); + void (*hdmi_infoframe_avi)(struct nvkm_ior *, int head, void *data, u32 = size); + void (*hdmi_infoframe_vsi)(struct nvkm_ior *, int head, void *data, u32 = size); + } gsp; + u16 ramht_size; =20 struct nvkm_sclass root; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c b/drivers/gpu= /drm/nouveau/nvkm/engine/disp/tu102.c index 6cfd52c9056f..948b1d2f954c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c @@ -140,6 +140,14 @@ tu102_head_vblank_get(struct nvkm_head *head) nvkm_mask(device, 0x611d80 + (head->id * 4), 0x00000002, 0x00000002); } =20 +const struct nvkm_head_func +tu102_gsp_head =3D { + .state =3D gv100_head_state, + .rgpos =3D gv100_head_rgpos, + .vblank_get =3D tu102_head_vblank_get, + .vblank_put =3D tu102_head_vblank_put, +}; + static void tu102_disp_intr_head_timing(struct nvkm_disp *disp, int head) { @@ -295,12 +303,23 @@ tu102_disp =3D { }, }; =20 +static const struct nvkm_disp_func +tu102_gsp_disp =3D { + .uevent =3D &gv100_disp_chan_uevent, + .ramht_size =3D 0x2000, + .gsp.intr =3D tu102_disp_intr, + .gsp.head =3D &tu102_gsp_head, + .gsp.hdmi_gcp =3D tu102_sor_hdmi_gcp, + .gsp.hdmi_infoframe_avi =3D gv100_sor_hdmi_infoframe_avi, + .gsp.hdmi_infoframe_vsi =3D gv100_sor_hdmi_infoframe_vsi, +}; + int tu102_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int= inst, struct nvkm_disp **pdisp) { if (nvkm_gsp_rm(device->gsp)) - return r535_disp_new(&tu102_disp, device, type, inst, pdisp); + return r535_disp_new(&tu102_gsp_disp, device, type, inst, pdisp); =20 return nvkm_disp_new_(&tu102_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c b/drive= rs/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c index cd4451e62512..bf97edcdfc95 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c @@ -547,7 +547,19 @@ r535_sor_hdmi_audio(struct nvkm_ior *sor, int head, bo= ol enable) { r535_sor_hdmi_ctrl_audio(sor->asy.outp, enable); r535_sor_hdmi_ctrl_audio_mute(sor->asy.outp, !enable); - tu102_sor_hdmi_gcp(sor, head, enable); + sor->disp->func->gsp.hdmi_gcp(sor, head, enable); +} + +static void +r535_sor_hdmi_infoframe_avi(struct nvkm_ior *sor, int head, void *data, u3= 2 size) +{ + sor->disp->func->gsp.hdmi_infoframe_avi(sor, head, data, size); +} + +static void +r535_sor_hdmi_infoframe_vsi(struct nvkm_ior *sor, int head, void *data, u3= 2 size) +{ + sor->disp->func->gsp.hdmi_infoframe_vsi(sor, head, data, size); } =20 static void @@ -575,8 +587,8 @@ r535_sor_hdmi =3D { .ctrl =3D r535_sor_hdmi_ctrl, .scdc =3D r535_sor_hdmi_scdc, /*TODO: SF_USER -> KMS. */ - .infoframe_avi =3D gv100_sor_hdmi_infoframe_avi, - .infoframe_vsi =3D gv100_sor_hdmi_infoframe_vsi, + .infoframe_avi =3D r535_sor_hdmi_infoframe_avi, + .infoframe_vsi =3D r535_sor_hdmi_infoframe_vsi, .audio =3D r535_sor_hdmi_audio, }; =20 @@ -601,14 +613,6 @@ r535_sor_cnt(struct nvkm_disp *disp, unsigned long *pm= ask) return 4; } =20 -static const struct nvkm_head_func -r535_head =3D { - .state =3D gv100_head_state, - .rgpos =3D gv100_head_rgpos, - .vblank_get =3D tu102_head_vblank_get, - .vblank_put =3D tu102_head_vblank_put, -}; - static struct nvkm_conn * r535_conn_new(struct nvkm_disp *disp, u32 id) { @@ -1606,7 +1610,7 @@ r535_disp_oneinit(struct nvkm_disp *disp) nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl); =20 for_each_set_bit(i, &disp->head.mask, disp->head.nr) { - ret =3D nvkm_head_new_(&r535_head, disp, i); + ret =3D nvkm_head_new_(disp->func->gsp.head, disp, i); if (ret) return ret; } @@ -1655,7 +1659,7 @@ r535_disp_oneinit(struct nvkm_disp *disp) return ret; =20 ret =3D nvkm_inth_add(&device->vfn->intr, ret, NVKM_INTR_PRIO_NORMAL, &di= sp->engine.subdev, - tu102_disp_intr, &disp->engine.subdev.inth); + disp->func->gsp.intr, &disp->engine.subdev.inth); if (ret) return ret; =20 @@ -1688,6 +1692,7 @@ r535_disp_new(const struct nvkm_disp_func *hw, struct= nvkm_device *device, rm->uevent =3D hw->uevent; rm->sor.cnt =3D r535_sor_cnt; rm->sor.new =3D r535_sor_new; + rm->gsp =3D hw->gsp; rm->ramht_size =3D hw->ramht_size; =20 rm->root.oclass =3D gpu->disp.class.root; --=20 2.55.0 From nobody Mon Sep 28 08:12:16 2026 Received: from mail-wr1-f48.google.com (mail-wr1-f48.google.com [209.85.221.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8E41321A453 for ; Tue, 25 Aug 2026 00:15:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787616907; cv=none; b=bfmjvkuFy0pNAkDvdCNw8XyqVfCA8LHPHrL5TCxIz16X803oE4QW8WR3PDht2iJ9M4at6PpL8EtTieZphK9JbICCKsukgm8dCbIqH8h4tLNgDRjr7E7Xj01ygWw3SnP7kupBXLwcn4gEE9oUXx/WY6qN/VO102iS0DiY3excF1Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787616907; c=relaxed/simple; bh=sI9/FTBY7qhv+vxZSFc/GzQbUU4cvn4PkrzIgjUcCEE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qvvHX/Cp37ypVr1uBk2cGJ6F2p92HYT+vdKSyZS4PMep75bYlBnDPUv6Ig+oiG6Q9dhA4IjTZxacVlCwcxuVndl7m/RjzhqbAL/FAoPKh+Kw3LL0aDBvNGdnfVE3lVwafURTvu0bdrK6TXEcRawyH1VfezSAdWbD6dA06sOzA7c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ONXycRO8; arc=none smtp.client-ip=209.85.221.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ONXycRO8" Received: by mail-wr1-f48.google.com with SMTP id ffacd0b85a97d-471eeac43bfso3231156f8f.3 for ; Mon, 24 Aug 2026 17:15:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787616904; x=1788221704; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Aqjw+bpJ2kJHTkTJl9c9Hk31X3a8EO/G2Xw/HngoD2Y=; b=ONXycRO8TVIMSUV4USjTInWmJeYmZayIonHmEL155+++PvZ23WSLbDdYjoafA0K1k9 HU8k+5ov6e/P+RfinjuvdTi1dIVv1CbshoZz7EZWgfYVgbA6GsVfmQbFXUcLIIF5W6uo Bd7u1AVL4C16/Oob8zf3mtsD4NUHw3GOBpz+rfexfTzjFDEi40AageCct27z93Cv7whd 75ewdvTsMaFPPOJooKwybTLxfQRSm/LyRfdYnIGizAoJaf3zhvLZTx7V7ujxZufeVIVT y0Pz9vkDC2jlV0699M4EdE9L73uQtn9fhaFLGtuU6V3bqJ4aWwNFt8dzcsE7jHBfh/IE GAKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787616904; x=1788221704; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=Aqjw+bpJ2kJHTkTJl9c9Hk31X3a8EO/G2Xw/HngoD2Y=; b=MOtv0KVutUXs4NNX6XDcCSA3MP3Fo5JLF1KQrRn8mRmozbkR4LixzaxDcXUtq9oZ3M nvmgQJDyitUzgYRP4unupFXZiDtDqc0/IvOWN6zvqWg6dWgJMRgeE2a3jSj1L9qAIpUg Ibyq8gVzrdT1Mojs+aC4Ccsk8qojpfDZK/KCos7yK563xXOfAj0nhf4GsgrzKDJgZAct ML+0KB4cq0F6aP6Cz6Yq8Zvxm0jctIz51GjyDJmN0LfJE3G/hmyY9bmJYIQIv/2hZ3/b AKp8PXeIdz6uXQs80r8z9gHqMgGf9UMnsZzyOX0NaVQVgK72oIC4FVU1xHWh9+BZfc3n nYQw== X-Gm-Message-State: AFuF++lu1mleRS6KQuS2WtiBGntqKlGgD6+g9xRiDPZWJ8SA4tpN5i9p k1FruPmn5jbDsHvfIKhdkyyqK9X46sjeoR9r7eXXHHIbLrGyPquo2hNdhbe+BYo8 X-Gm-Gg: AR+sD11R+sjoqybW82hfNr/kIhb2B5YnK/TJHyf47ZVO1Wy8B4me83d7GSjRINRjDwZ ttExwaxxQoRAq7aFa9xOEDzJLrzavRSwhgOyxNbU1ohQVPSBM1tC9wc/s4ZKjQBRWYdhJcrtgE0 WcFhla3FORqhNOQuLcg23nyY3Bf+WbtGB4P0OK+/R7EKycuhdAUYVNfRrD2eMBz3L4NVXIwdHDA WvS5SNrKzvNdXc+sMTJT73crP3jBqKsX5hP2Fq/uR/sgZTqGwoL16QHAIyOaZA6DknpFcv2KY39 KL6R95zSYZ99b1Apu7ZiqNi1fGqZL/rIuHQ1VAbjM4R+p2PeOKK1M6OenBHiUucecb59h2X3fZ1 fJVHeNK1jcniNiKdPN6HM+9vnjA4rSS2l5t/BdE16vHKdAWjseQkU0j7RE2tKQzFCHoMldCEkW1 AzKu4hkF/ZOnnaXzLoHILfpqyD+KTjp7XCuSpVJ3mkPKgSSdNG3KV6OFtSokwwRJXdfezofwTZA GP/Tw== X-Received: by 2002:a5d:588b:0:b0:482:a053:ebf with SMTP id ffacd0b85a97d-482c81c62cemr24067156f8f.19.1787616903638; Mon, 24 Aug 2026 17:15:03 -0700 (PDT) Received: from fedora ([5.31.134.170]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-482c9b78ebfsm9770676f8f.12.2026.08.24.17.14.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Aug 2026 17:15:02 -0700 (PDT) From: Mohamed Ahmed To: linux-kernel@vger.kernel.org Cc: dri-devel@lists.freedesktop.org, Lyude Paul , Danilo Krummrich , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Mary Guillemard , nouveau@lists.freedesktop.org, Mohamed Ahmed , stable@vger.kernel.org Subject: [PATCH v3 04/10] drm/nouveau/disp: fix HDMI vendor infoframes on GB20x Date: Tue, 25 Aug 2026 04:14:02 +0400 Message-ID: <20260825001408.14219-5-mohamedahmedegypt2001@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260825001408.14219-1-mohamedahmedegypt2001@gmail.com> References: <20260825001408.14219-1-mohamedahmedegypt2001@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The GSP path reuses the GV100 direct-MMIO infoframe writers on every chip. On GB20x that is only half right as while the legacy SF AVI unit is unchanged, the legacy VSI unit at 0x6f0100 was removed, so gv100_sor_hdmi_infoframe_vsi() writes into a reserved area and no vendor infoframe ever reaches the HW. This affects HDMI-VIC signalling which can impact some 4K modes for legacy HDMI 1.4 sinks. GB20x (NVDisplay 5.0+) reorganised the SF HDMI packet units. Per NVIDIA's published C971/CA71 DISP_SF_USER class headers, only three legacy units remain (AVI at +0x000, GCP at +0x040, ACR at +0x080), and vendor infoframes must instead be sent through the shared generic infoframe units at +0x130, whose 9-dword packet slots are loaded through the shared data port at +0x3f0/+0x3f4. Add a VSI writer using the same programming sequence OpenRM uses on these chips (nvhdmipkt_C971.c, programAdvancedInfoframeC971()): disable the unit and wait for it to idle, clear the SENT status, write the packet through the data port with a zero inserted in HB3 after the three header bytes, then enable the unit for every-frame transmission during vblank. Generic unit 1 is used for the VSI, matching the slot assignment in NVIDIA's nvkms (NVHDMIPKT_TYPE_SHARED_GENERIC2, unit 0 is reserved for extended metadata packets and unit 2 for the HDR DRM infoframe, if those are wired up later). GB20x so far shared GA10x's display entry point. Give it its own, gb202_disp_new(), with a gb202_gsp_disp table that supplies the VSI writer to the GSP path and otherwise carries the same hooks as GA10x. The following fixes fill in the rest of the GB20x differences there. Fixes: 6cc6e08d4542 ("drm/nouveau/kms: add support for GB20x") Cc: stable@vger.kernel.org Signed-off-by: Mohamed Ahmed Reviewed-by: Lyude Paul --- .../drm/nouveau/include/nvkm/engine/disp.h | 1 + .../gpu/drm/nouveau/nvkm/engine/device/base.c | 10 +-- .../gpu/drm/nouveau/nvkm/engine/disp/Kbuild | 1 + .../gpu/drm/nouveau/nvkm/engine/disp/gb202.c | 88 +++++++++++++++++++ 4 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/disp/gb202.c diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h b/drivers/g= pu/drm/nouveau/include/nvkm/engine/disp.h index 7903d7470d19..01145db32c53 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h @@ -87,4 +87,5 @@ int gp102_disp_new(struct nvkm_device *, enum nvkm_subdev= _type, int inst, struct int gv100_disp_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, = struct nvkm_disp **); int tu102_disp_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, = struct nvkm_disp **); int ga102_disp_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, = struct nvkm_disp **); +int gb202_disp_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, = struct nvkm_disp **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gp= u/drm/nouveau/nvkm/engine/device/base.c index ea62dc97f118..96c8a5b29999 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2846,7 +2846,7 @@ nv1b2_chipset =3D { .pci =3D { 0x00000001, gh100_pci_new }, .timer =3D { 0x00000001, gk20a_timer_new }, .vfn =3D { 0x00000001, ga100_vfn_new }, - .disp =3D { 0x00000001, ga102_disp_new }, + .disp =3D { 0x00000001, gb202_disp_new }, .fifo =3D { 0x00000001, ga102_fifo_new }, }; =20 @@ -2862,7 +2862,7 @@ nv1b3_chipset =3D { .pci =3D { 0x00000001, gh100_pci_new }, .timer =3D { 0x00000001, gk20a_timer_new }, .vfn =3D { 0x00000001, ga100_vfn_new }, - .disp =3D { 0x00000001, ga102_disp_new }, + .disp =3D { 0x00000001, gb202_disp_new }, .fifo =3D { 0x00000001, ga102_fifo_new }, }; =20 @@ -2878,7 +2878,7 @@ nv1b5_chipset =3D { .pci =3D { 0x00000001, gh100_pci_new }, .timer =3D { 0x00000001, gk20a_timer_new }, .vfn =3D { 0x00000001, ga100_vfn_new }, - .disp =3D { 0x00000001, ga102_disp_new }, + .disp =3D { 0x00000001, gb202_disp_new }, .fifo =3D { 0x00000001, ga102_fifo_new }, }; =20 @@ -2894,7 +2894,7 @@ nv1b6_chipset =3D { .pci =3D { 0x00000001, gh100_pci_new }, .timer =3D { 0x00000001, gk20a_timer_new }, .vfn =3D { 0x00000001, ga100_vfn_new }, - .disp =3D { 0x00000001, ga102_disp_new }, + .disp =3D { 0x00000001, gb202_disp_new }, .fifo =3D { 0x00000001, ga102_fifo_new }, }; =20 @@ -2910,7 +2910,7 @@ nv1b7_chipset =3D { .pci =3D { 0x00000001, gh100_pci_new }, .timer =3D { 0x00000001, gk20a_timer_new }, .vfn =3D { 0x00000001, ga100_vfn_new }, - .disp =3D { 0x00000001, ga102_disp_new }, + .disp =3D { 0x00000001, gb202_disp_new }, .fifo =3D { 0x00000001, ga102_fifo_new }, }; =20 diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild b/drivers/gpu/= drm/nouveau/nvkm/engine/disp/Kbuild index e1aecd3fe96c..98d6ca5ac311 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild @@ -27,6 +27,7 @@ nvkm-y +=3D nvkm/engine/disp/gp102.o nvkm-y +=3D nvkm/engine/disp/gv100.o nvkm-y +=3D nvkm/engine/disp/tu102.o nvkm-y +=3D nvkm/engine/disp/ga102.o +nvkm-y +=3D nvkm/engine/disp/gb202.o =20 nvkm-y +=3D nvkm/engine/disp/udisp.o nvkm-y +=3D nvkm/engine/disp/uconn.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gb202.c b/drivers/gpu= /drm/nouveau/nvkm/engine/disp/gb202.c new file mode 100644 index 000000000000..1e40de83e2bb --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gb202.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright 2026 Valve Corp. + */ +#include "priv.h" +#include "head.h" +#include "ior.h" + +#include + +/* GB20x (NVD5.0) reorganised the SF HDMI packet units. The AVI unit is + * unchanged from GV100, but the legacy VSI unit is gone. Vendor infoframes + * are sent through the shared generic infoframe units instead. Register + * layout per NVIDIA's clc971.h/clca71.h, programming sequence per + * nvhdmipkt_C971.c:programAdvancedInfoframeC971(). + */ +static void +gb202_sor_hdmi_infoframe_vsi(struct nvkm_ior *ior, int head, void *data, u= 32 size) +{ + struct nvkm_device *device =3D ior->disp->engine.subdev.device; + const u32 hoff =3D head * 0x400; + /* Generic infoframe unit 1, the slot NVIDIA's driver uses for the VSI. */ + const u32 ctrl =3D 0x6f0138 + hoff; + u8 buf[36] =3D {}; + int i; + + /* Disable the unit and wait for it to go idle. */ + nvkm_mask(device, ctrl, 0x00000001, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, ctrl) & 0x00400000)) + break; + ) < 0) + return; + + if (!size) + return; + + /* Clear SENT status, and point the data port at unit 1's slot. */ + nvkm_mask(device, ctrl, 0x00800000, 0x00800000); + nvkm_wr32(device, 0x6f03f0 + hoff, 0x00000001); + + /* The data port takes the raw packet, except that a zero is inserted + * in HB3 after the three header bytes. A slot is 9 dwords (HB0-3 plus + * up to 32 payload bytes). An HDMI infoframe carries at most PB0-27, + * so the tail stays zero, and we always write the whole slot. + */ + size =3D min_t(u32, size, 31); + memcpy(buf, data, min_t(u32, size, 3)); + if (size > 3) + memcpy(&buf[4], (u8 *)data + 3, size - 3); + + for (i =3D 0; i < 36; i +=3D 4) { + nvkm_wr32(device, 0x6f03f4 + hoff, buf[i + 0] | buf[i + 1] << 8 | + buf[i + 2] << 16 | + (u32)buf[i + 3] << 24); + } + + /* No flip ID or scanline matching. */ + nvkm_wr32(device, 0x6f013c + hoff, 0x00000000); + + /* ENABLE | RUN_MODE=3DALWAYS | LOC=3DVBLANK | OFFSET=3D1 | SIZE=3D0. */ + nvkm_wr32(device, ctrl, 0x00000041); + + /* Audio priority low (the init value). */ + nvkm_wr32(device, 0x6f03f8 + hoff, 0x00000002); +} + +/* GB20x is GSP-only. This table supplies the register programming the + * GSP-RM display path needs from the chip. + */ +static const struct nvkm_disp_func +gb202_gsp_disp =3D { + .uevent =3D &gv100_disp_chan_uevent, + .ramht_size =3D 0x2000, + .gsp.intr =3D tu102_disp_intr, + .gsp.head =3D &tu102_gsp_head, + .gsp.hdmi_gcp =3D tu102_sor_hdmi_gcp, + /* The legacy AVI unit is unchanged on GB20x. */ + .gsp.hdmi_infoframe_avi =3D gv100_sor_hdmi_infoframe_avi, + .gsp.hdmi_infoframe_vsi =3D gb202_sor_hdmi_infoframe_vsi, +}; + +int +gb202_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int= inst, + struct nvkm_disp **pdisp) +{ + return r535_disp_new(&gb202_gsp_disp, device, type, inst, pdisp); +} --=20 2.55.0 From nobody Mon Sep 28 08:12:16 2026 Received: from mail-wr1-f46.google.com (mail-wr1-f46.google.com [209.85.221.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C336678C9C for ; Tue, 25 Aug 2026 00:15:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787616914; cv=none; b=mQ/6/oGT8km0a6bCu4Le0wcBNlKUc/0SxW2Cbs9H/mjCCjrsnLGkMxeydAmKKlREbVWeOrTGnLIzqL3RtMsRcRDj6TSwIWRUkgcrh/5EYVJEYLrvEgUmthUvWxRKkUqkDZ7mq/wKMA/VWUM1Gj5JY9CV73WDca3fhiFfI4u1QGc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787616914; c=relaxed/simple; bh=VJand9sh9NHtem3pMUzMrNghJXYdaKFAaIcEQwTQ0Ik=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rvEQ6vr8gJ7gPwtT9KnC1tEG2g2gbPhXu0aL1Lvy0Wn07hd3qXSIQpjEJEIf3PJP8jro2zKQ/VP7juFKzQidgLmBGmaZSTvQYGJPtPOlL1g8KYZ/sS+fw81sfEvOcPZlg67m/JexnWsA622/4Rv37Q1Ap5V+kKLegFkJC9vTB2A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=noWgxaLl; arc=none smtp.client-ip=209.85.221.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="noWgxaLl" Received: by mail-wr1-f46.google.com with SMTP id ffacd0b85a97d-47f96c5b722so1798788f8f.0 for ; Mon, 24 Aug 2026 17:15:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787616911; x=1788221711; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=mdmMJSJ8rbCJNULoO8M4OEKgVBhOfOqt451kTS7kBCU=; b=noWgxaLlh1hhnViQNC9Q0ssItIR+dsKEFPnhzZbmW/C7Zlq1QJ/uAOlT8zrAjHk0B8 jkM8al+m99s1exdGbEvXxm4w3LNpRM4ywDiL0Zd0jCdxVqMgvJlHfsEeMBR9qXx/YEzp lhEAUKHzh5biviOCPGCSKbGuHxgziO0o3LcWSr3/WZiAxD41GY+lwaOB7LxLjLDE27ht rLjMzYTwE+ldMkZWLxJ77tqUr/fhT+Z1b+e6Yn1t/RDJQCG436hanNLrYvE819wPB2zv 22AzUWEt7JJjwo3Ts9qz/WrJYjzgHQ9Z8SXYP5ECAWAWPQRtyGRs7G9rxZ5pD2uFSaE0 ohCg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787616911; x=1788221711; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=mdmMJSJ8rbCJNULoO8M4OEKgVBhOfOqt451kTS7kBCU=; b=lz/+TUBm4nf7tM4AjnNXpnotJnoWptyoQLseIGddAtzgPFow3rmAr8c18M8zyn3iNF WsC6vsxVN5Ldhty/dKjGvaVEEKz5zALgWv5CoFXkmguk1npK7zwIDs2LAgnFK6GjpIlc BVTdJWYB/JVsxXimMyxjTaIEcekC/Zb4Hftb2H1KWKb7EPUgBNnhPoC6YhXcG3dFiu/V vSmt6B76zQhU3FbIeOlUUou9YcfBT/qyIizRth/uceRrnToBtFgyU0MKVQd0hw7gGhUL P4dA9HJ/xNv0uw5Es/QRK+RTYRpHuOS0Zsg5tshHEC1mpIiK0WQXLQEjde0xdeVzsKJp obzw== X-Gm-Message-State: AFuF++mxJ8vYUeXNq0PmBQdhA97+M1oh0n8DzvXNVB3rwBE8/lk5wSZ0 V+QrjHGwoIpy/PRygJMC9kxoYo9REWxX9+HCVrYDaYyUvhC0ToXxCqnLm/aSqdzV X-Gm-Gg: AR+sD12NM/+55aRGe/c9rh9TR0igvNJRs7mgrOiWVYdJjHeUuJUvBGV1ODLjGOxk3jJ rCisvjzEhMCKSWgyOzBWcpCjoNfQBqgAdz1WgoRydqq+1mOuodq+KasL26JeL1aX5UKV5MFs+tj FWPWxKM8uTYcIz0C3LkLxG/3OCGw+G734Touci1Fk1YiEWmmp1wArDX9jK+4tTrRFf+bsk2Iuyi RCGq3lFzn4fJmudYRlU1zk4gH1OyvJ7nXxdFpIMJV1W0B14ldRlp424tES7rfq2DBXFLSfb2YIU kCNrqWoafUY/GJ4wEn25Zn5M8Dt5hok3J/Y2WBV21wynGqZMCgVukG0VBLS1QmOlMOakfO6JaIG CQr+M+wlRbDzGLA74Z4r8vP2xNsXc3VZ7az5U8Ij/OZfkRgaWLen/yawkNDbzfkXiozqKGIxpuL FAzNJeX/sdwieGa/CV7EY3LrwBbHdgTbPwt/ij4r9Lv7Cg+ldPLuJ2OJ2elMafM3MQCbU= X-Received: by 2002:a05:6000:2582:b0:47f:80ee:744f with SMTP id ffacd0b85a97d-482c0b99a89mr36897656f8f.16.1787616911031; Mon, 24 Aug 2026 17:15:11 -0700 (PDT) Received: from fedora ([5.31.134.170]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-482c9b78ebfsm9770676f8f.12.2026.08.24.17.15.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Aug 2026 17:15:09 -0700 (PDT) From: Mohamed Ahmed To: linux-kernel@vger.kernel.org Cc: dri-devel@lists.freedesktop.org, Lyude Paul , Danilo Krummrich , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Mary Guillemard , nouveau@lists.freedesktop.org, Mohamed Ahmed , stable@vger.kernel.org Subject: [PATCH v3 05/10] drm/nouveau/disp: fix HDMI GCP AVMute register offsets on GB20x Date: Tue, 25 Aug 2026 04:14:03 +0400 Message-ID: <20260825001408.14219-6-mohamedahmedegypt2001@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260825001408.14219-1-mohamedahmedegypt2001@gmail.com> References: <20260825001408.14219-1-mohamedahmedegypt2001@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The GSP path brackets audio enablement with a General Control Packet AVMute toggle. r535_sor_hdmi_audio() calls the gsp.hdmi_gcp hook, which every chip so far serves with tu102_sor_hdmi_gcp() and the legacy GCP unit at 0x6f00c0/0x6f00cc. On GB20x the SF packet units were compacted and the old generic and VSI units are gone (ACR keeps slot 2) and the GCP unit moved from slot 3 to slot 1 (control 0x6f0040 and subpack 0x6f004c from NVIDIA's published clc971.h. The same offsets are also used by OpenRM's hdmiWriteGeneralCtrlPacketC871() on these chips). The old addresses are reserved on GB20x, so the AVMute writes were silent no-ops and mitigated only by the equivalent GCP r535_sor_hdmi_audio() already sends through the SET_OD_PACKET RM control. Add a GB20x GCP writer using the new offsets and hook it into gb202_gsp_disp, keeping the direct MMIO path in sync with the hardware as on earlier chips. Only SB0 (the AVMute bit) is written. On NVD5.0 the subpack register also carries SB1_CTRL (bit 24), which selects where the deep-color CD/PP fields are generated (hardware or from the driver, with the default being HW). hdmiWriteGeneralCtrlPacketC871() likewise writes only SB0-SB2. Fixes: 6cc6e08d4542 ("drm/nouveau/kms: add support for GB20x") Cc: stable@vger.kernel.org Signed-off-by: Mohamed Ahmed Reviewed-by: Lyude Paul --- .../gpu/drm/nouveau/nvkm/engine/disp/gb202.c | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gb202.c b/drivers/gpu= /drm/nouveau/nvkm/engine/disp/gb202.c index 1e40de83e2bb..face801af080 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gb202.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gb202.c @@ -65,6 +65,24 @@ gb202_sor_hdmi_infoframe_vsi(struct nvkm_ior *ior, int h= ead, void *data, u32 siz nvkm_wr32(device, 0x6f03f8 + hoff, 0x00000002); } =20 +/* General Control Packet AVMute bracket. The GCP unit moved to slot 1 on + * NVD5.0. Only SB0 (the AVMute bit) is ours to write so we must not do a + * full write here: SB1 carries the deep-color CD/PP fields, and SB1_CTRL + * (bit 24, new with clc871.h) controls where their generation happens (HW + * or driver) on these chips, with the default being HW. + */ +static void +gb202_sor_hdmi_gcp(struct nvkm_ior *sor, int head, bool enable) +{ + struct nvkm_device *device =3D sor->disp->engine.subdev.device; + const u32 hdmi =3D head * 0x400; + + nvkm_mask(device, 0x6f0040 + hdmi, 0x00000001, 0x00000000); + nvkm_mask(device, 0x6f004c + hdmi, 0x000000ff, !enable ? 0x00000001 : + 0x00000010); + nvkm_mask(device, 0x6f0040 + hdmi, 0x00000001, 0x00000001); +} + /* GB20x is GSP-only. This table supplies the register programming the * GSP-RM display path needs from the chip. */ @@ -74,7 +92,7 @@ gb202_gsp_disp =3D { .ramht_size =3D 0x2000, .gsp.intr =3D tu102_disp_intr, .gsp.head =3D &tu102_gsp_head, - .gsp.hdmi_gcp =3D tu102_sor_hdmi_gcp, + .gsp.hdmi_gcp =3D gb202_sor_hdmi_gcp, /* The legacy AVI unit is unchanged on GB20x. */ .gsp.hdmi_infoframe_avi =3D gv100_sor_hdmi_infoframe_avi, .gsp.hdmi_infoframe_vsi =3D gb202_sor_hdmi_infoframe_vsi, --=20 2.55.0 From nobody Mon Sep 28 08:12:16 2026 Received: from mail-wr1-f43.google.com (mail-wr1-f43.google.com [209.85.221.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ECE0B224234 for ; Tue, 25 Aug 2026 00:15:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787616923; cv=none; b=UzExo9wGPnS+CGBm3/ogtaUg+LoSFRUFjdasRCSNWlWi/F9WH5AUW+zIFHLbD0OX5TL0Lq5/0+ld1qZ0HFb5iu7IihVqkhBMDksNuTP9JL9qz1qWadmP42/Ksl53hZgfBxEYGePLLt8ynVskQ6cJt2OiV2J9nfRIAe4lznnhdhU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787616923; c=relaxed/simple; bh=rq2ihxtFrd6MrgQlP5DZBfxipmPaNk8pbV5uGfxaBd4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DTFHbZmNHjbAWRcQnZlGgfn+kYnQA2s/7stdGPYqHC5CNGUjcwqwOkw8ft36bDSIAt+GgFwMMr8PC1L9H5eSrpw+lntRdBqXCWE/QYXOigfdvL58xhOxhD4x6Ce8aJOt1bJL1st1QMLPiH4Scx0Hdywk8vIo9rqwoVVt8NCpPDQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=FeGqexny; arc=none smtp.client-ip=209.85.221.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="FeGqexny" Received: by mail-wr1-f43.google.com with SMTP id ffacd0b85a97d-47fd66a094eso1188083f8f.3 for ; Mon, 24 Aug 2026 17:15:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787616920; x=1788221720; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=PE18UOnUU3vtHd95e5x4c1/cDuJ6Y/PBPwnRKByDmzE=; b=FeGqexnyaND6vbToNge1LxY7mxtj3JgzffM9nqzIsJ45TI139AVmvHdQCvaiZUXP76 cJ/E/SVPJuZT3G1wALPamEgedEcQuBu5x4QAHa1RrExMZ1kpb2JcNeIw8+WowwNDs8H3 CYH0KbJDjDMySxGOkd2aOshB1gyCzuPvcFKI9/HwPPs24qss8n0XreLmaMyiM0EKzXDU JADxy+NjUEglu9n5C8wmOYktshPXPwG37uKmsf+kg6szJM14LgIk4eKxiuCmZ7lcYdZA b2ul2NKny5MpxmacrMJcEjFNoJfYJXIeofPkIudOemwOsMQwuOTqTo0TNNu324USXQKT MfSQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787616920; x=1788221720; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=PE18UOnUU3vtHd95e5x4c1/cDuJ6Y/PBPwnRKByDmzE=; b=SWhSyW6vzHkQO+Oj7QbkNBqIseKFf8cPhDU65u9MrzEYm9gW6UCfgWirkcO1oXiiPK QLq3INPLfnkwSdquxnfcXj4SpTxmUcQk9UMyz/QqP56aZ+axlYVowbFhR6//cdjOM/I3 eMj21QDYITYV5V0H9favl6ny5Px2skkinop22N5FlMrtdrVNnin8HATKV/CMlj8a5cS6 6BaxCkVKh32ctxjVlqWWc5G6JFIgudHiErZVkzfDYPSOWoPOMb0MWp/Vw+JWlM2Zj6PI 8LEcb15erfH7GTFecY0y72Mv/utvfQr+/hrD50OKLAHO2fPrK9NcoxOo+qdK0js5l6sQ OFnA== X-Gm-Message-State: AFuF++k/1i9TKiGqqQhxGw6I/cJR3daSVPjEv0RnPKdN2QANbiM9Tk5S xSFdm3FCVfvQHKwKG9fAlEcE1SIwxOQM2UikO6ihMPxRBdU8sgbCHS18di6kXHLo X-Gm-Gg: AR+sD116aFi70OEuVgTE+TPv1tiQZgS1uhlNX4bWJScihipHXA+QlhnUapFdS+8+L6s 67ISzfEfzv6JnJRZEA69Xgpa+tA++huS91gzPRe19nLP04u7f5g84+qP2dEimeZCCTRTOTnrQm3 xfZKFVdFdyHH1Jv6VkSPGCxJZBfEmImqB+PaVhq5qZ0OMcnJ7qvQlkMA4nze6lQPQ2naDj49R+I 7cSHey0Y8EAx2Z7nxOXZshQG6G5id1gAgXbhsAEcVx7HPSCfI3Ar79LWKHFsiDtbeZMFKgWj3AT vJUnJeYAsW+ZGI3y+PnW6Xb/gjZbLDnDwAHacjTwTWULAoy6qQRENqfbWzJDE+SLd8j3Zz7V9oA /VY2H0C+E564SGLlGdjgpthGDz8qdxhp/1DJOG0nEjDc7qfDKfG2h1HtOWzJM/GPEACj8+sFyl9 mHySetpJF6TGtY668D9fAjgThP3MCxBx7AESL44Cc0V2r9i16mtcjQAsL67ZIt3QIZyyc= X-Received: by 2002:a5d:6f09:0:b0:481:5ba5:994c with SMTP id ffacd0b85a97d-482c0baf924mr44313278f8f.20.1787616920113; Mon, 24 Aug 2026 17:15:20 -0700 (PDT) Received: from fedora ([5.31.134.170]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-482c9b78ebfsm9770676f8f.12.2026.08.24.17.15.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Aug 2026 17:15:18 -0700 (PDT) From: Mohamed Ahmed To: linux-kernel@vger.kernel.org Cc: dri-devel@lists.freedesktop.org, Lyude Paul , Danilo Krummrich , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Mary Guillemard , nouveau@lists.freedesktop.org, Mohamed Ahmed , stable@vger.kernel.org Subject: [PATCH v3 06/10] drm/nouveau/gsp: use per-version DP_CONFIG_STREAM params on r570 firmware Date: Tue, 25 Aug 2026 04:14:04 +0400 Message-ID: <20260825001408.14219-7-mohamedahmedegypt2001@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260825001408.14219-1-mohamedahmedegypt2001@gmail.com> References: <20260825001408.14219-1-mohamedahmedegypt2001@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" NVIDIA removed the deprecated actualPclkHz/linkClkFreqHz fields and the whole Legacy{activeCnt, activeFrac, activePolarity, mvidWarEnabled, MvidWarParams} block from the SST sub-struct of NV0073_CTRL_CMD_DP_CONFIG_STREAM_PARAMS between the 535 and 570 releases (compared in OpenRM tags 535.113.01 vs 570.144), shrinking the struct. Everything nouveau writes sits at identical offsets in both layouts except the trailing SST.bEnableAudioOverRightPanel (written as zero), but the size is wrong on r570, which means r535_sor_dp_sst() and r535_sor_dp_vcpi() are sent with an incorrect size. Route the .sst/.vcpi IOR functions through nvkm_rm_api_disp the same way bl_ctrl and dp.get_caps/set_indexed_link_rates already are. Keep the existing implementation for r535 and add an r570 implementation built against the 570.144 layout, which already exists in r570/nvrm/disp.h but was unused until now. Also add the NV0073_CTRL_CMD_DP_CONFIG_STREAM define that was missing from the layout. Other DP controls sent through shared r535 code did not change layout between the tags. Fixes: 6cc6e08d4542 ("drm/nouveau/kms: add support for GB20x") Cc: stable@vger.kernel.org Signed-off-by: Mohamed Ahmed Reviewed-by: Lyude Paul --- .../nouveau/nvkm/subdev/gsp/rm/r535/disp.c | 33 ++++++++-- .../nouveau/nvkm/subdev/gsp/rm/r570/disp.c | 64 +++++++++++++++++++ .../nvkm/subdev/gsp/rm/r570/nvrm/disp.h | 2 + .../gpu/drm/nouveau/nvkm/subdev/gsp/rm/rm.h | 5 ++ 4 files changed, 97 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c b/drive= rs/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c index bf97edcdfc95..7d1d4ee2af79 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c @@ -400,16 +400,16 @@ r535_sor_dp_audio(struct nvkm_ior *sor, int head, boo= l enable) r535_sor_dp_audio_mute(sor, false); } =20 -static void -r535_sor_dp_vcpi(struct nvkm_ior *sor, int head, u8 slot, u8 slot_nr, u16 = pbn, u16 aligned_pbn) +static int +r535_dp_vcpi(struct nvkm_ior *sor, int head, u8 slot, u8 slot_nr, u16 pbn,= u16 aligned_pbn) { struct nvkm_disp *disp =3D sor->disp; struct NV0073_CTRL_CMD_DP_CONFIG_STREAM_PARAMS *ctrl; =20 ctrl =3D nvkm_gsp_rm_ctrl_get(&disp->rm.objcom, NV0073_CTRL_CMD_DP_CONFIG_STREAM, sizeof(*ctrl)); - if (WARN_ON(IS_ERR(ctrl))) - return; + if (IS_ERR(ctrl)) + return PTR_ERR(ctrl); =20 ctrl->subDeviceInstance =3D 0; ctrl->head =3D head; @@ -429,12 +429,20 @@ r535_sor_dp_vcpi(struct nvkm_ior *sor, int head, u8 s= lot, u8 slot_nr, u16 pbn, u ctrl->MST.sendACT =3D 0; ctrl->MST.singleHeadMSTPipeline =3D 0; ctrl->MST.bEnableAudioOverRightPanel =3D 0; - WARN_ON(nvkm_gsp_rm_ctrl_wr(&disp->rm.objcom, ctrl)); + return nvkm_gsp_rm_ctrl_wr(&disp->rm.objcom, ctrl); +} + +static void +r535_sor_dp_vcpi(struct nvkm_ior *sor, int head, u8 slot, u8 slot_nr, u16 = pbn, u16 aligned_pbn) +{ + const struct nvkm_rm_api *rmapi =3D sor->disp->engine.subdev.device->gsp-= >rm->api; + + WARN_ON(rmapi->disp->dp.vcpi(sor, head, slot, slot_nr, pbn, aligned_pbn)); } =20 static int -r535_sor_dp_sst(struct nvkm_ior *sor, int head, bool ef, - u32 watermark, u32 hblanksym, u32 vblanksym) +r535_dp_sst(struct nvkm_ior *sor, int head, bool ef, + u32 watermark, u32 hblanksym, u32 vblanksym) { struct nvkm_disp *disp =3D sor->disp; struct NV0073_CTRL_CMD_DP_CONFIG_STREAM_PARAMS *ctrl; @@ -461,6 +469,15 @@ r535_sor_dp_sst(struct nvkm_ior *sor, int head, bool e= f, return nvkm_gsp_rm_ctrl_wr(&disp->rm.objcom, ctrl); } =20 +static int +r535_sor_dp_sst(struct nvkm_ior *sor, int head, bool ef, + u32 watermark, u32 hblanksym, u32 vblanksym) +{ + const struct nvkm_rm_api *rmapi =3D sor->disp->engine.subdev.device->gsp-= >rm->api; + + return rmapi->disp->dp.sst(sor, head, ef, watermark, hblanksym, vblanksym= ); +} + static const struct nvkm_ior_func_dp r535_sor_dp =3D { .sst =3D r535_sor_dp_sst, @@ -1734,6 +1751,8 @@ r535_disp =3D { .dp =3D { .get_caps =3D r535_dp_get_caps, .set_indexed_link_rates =3D r535_dp_set_indexed_link_rates, + .sst =3D r535_dp_sst, + .vcpi =3D r535_dp_vcpi, }, .chan =3D { .set_pushbuf =3D r535_disp_chan_set_pushbuf, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/disp.c b/drive= rs/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/disp.c index a96e31c2d80b..8a23837f356e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/disp.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/disp.c @@ -5,6 +5,7 @@ #include =20 #include +#include #include =20 #include "nvhw/drf.h" @@ -74,6 +75,67 @@ r570_disp_chan_set_pushbuf(struct nvkm_disp *disp, s32 o= class, int inst, struct return nvkm_gsp_rm_ctrl_wr(&gsp->internal.device.subdevice, ctrl); } =20 +static int +r570_dp_vcpi(struct nvkm_ior *sor, int head, u8 slot, u8 slot_nr, u16 pbn,= u16 aligned_pbn) +{ + struct nvkm_disp *disp =3D sor->disp; + NV0073_CTRL_CMD_DP_CONFIG_STREAM_PARAMS *ctrl; + + ctrl =3D nvkm_gsp_rm_ctrl_get(&disp->rm.objcom, + NV0073_CTRL_CMD_DP_CONFIG_STREAM, sizeof(*ctrl)); + if (IS_ERR(ctrl)) + return PTR_ERR(ctrl); + + ctrl->subDeviceInstance =3D 0; + ctrl->head =3D head; + ctrl->sorIndex =3D sor->id; + ctrl->dpLink =3D sor->asy.link =3D=3D 2; + ctrl->bEnableOverride =3D 1; + ctrl->bMST =3D 1; + ctrl->hBlankSym =3D 0; + ctrl->vBlankSym =3D 0; + ctrl->colorFormat =3D 0; + ctrl->bEnableTwoHeadOneOr =3D 0; + ctrl->singleHeadMultistreamMode =3D 0; + ctrl->MST.slotStart =3D slot; + ctrl->MST.slotEnd =3D slot + slot_nr - 1; + ctrl->MST.PBN =3D pbn; + ctrl->MST.Timeslice =3D aligned_pbn; + ctrl->MST.sendACT =3D 0; + ctrl->MST.singleHeadMSTPipeline =3D 0; + ctrl->MST.bEnableAudioOverRightPanel =3D 0; + return nvkm_gsp_rm_ctrl_wr(&disp->rm.objcom, ctrl); +} + +static int +r570_dp_sst(struct nvkm_ior *sor, int head, bool ef, + u32 watermark, u32 hblanksym, u32 vblanksym) +{ + struct nvkm_disp *disp =3D sor->disp; + NV0073_CTRL_CMD_DP_CONFIG_STREAM_PARAMS *ctrl; + + ctrl =3D nvkm_gsp_rm_ctrl_get(&disp->rm.objcom, + NV0073_CTRL_CMD_DP_CONFIG_STREAM, sizeof(*ctrl)); + if (IS_ERR(ctrl)) + return PTR_ERR(ctrl); + + ctrl->subDeviceInstance =3D 0; + ctrl->head =3D head; + ctrl->sorIndex =3D sor->id; + ctrl->dpLink =3D sor->asy.link =3D=3D 2; + ctrl->bEnableOverride =3D 1; + ctrl->bMST =3D 0; + ctrl->hBlankSym =3D hblanksym; + ctrl->vBlankSym =3D vblanksym; + ctrl->colorFormat =3D 0; + ctrl->bEnableTwoHeadOneOr =3D 0; + ctrl->SST.bEnhancedFraming =3D ef; + ctrl->SST.tuSize =3D 64; + ctrl->SST.waterMark =3D watermark; + ctrl->SST.bEnableAudioOverRightPanel =3D 0; + return nvkm_gsp_rm_ctrl_wr(&disp->rm.objcom, ctrl); +} + static int r570_dp_set_indexed_link_rates(struct nvkm_outp *outp) { @@ -255,6 +317,8 @@ r570_disp =3D { .dp =3D { .get_caps =3D r570_dp_get_caps, .set_indexed_link_rates =3D r570_dp_set_indexed_link_rates, + .sst =3D r570_dp_sst, + .vcpi =3D r570_dp_vcpi, }, .chan =3D { .set_pushbuf =3D r570_disp_chan_set_pushbuf, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/nvrm/disp.h b/= drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/nvrm/disp.h index 06e972835d77..742b25a2a12d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/nvrm/disp.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/nvrm/disp.h @@ -256,6 +256,8 @@ typedef struct NV0073_CTRL_DP_CTRL_PARAMS { NvU32 eightLaneDpcdBaseAddr; } NV0073_CTRL_DP_CTRL_PARAMS; =20 +#define NV0073_CTRL_CMD_DP_CONFIG_STREAM (0x731362U) /* = finn: Evaluated from "(FINN_NV04_DISPLAY_COMMON_DP_INTERFACE_ID << 8) | NV0= 073_CTRL_CMD_DP_CONFIG_STREAM_PARAMS_MESSAGE_ID" */ + typedef struct NV0073_CTRL_CMD_DP_CONFIG_STREAM_PARAMS { NvU32 subDeviceInstance; NvU32 head; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/rm.h b/drivers/gpu/= drm/nouveau/nvkm/subdev/gsp/rm/rm.h index 0fb0e67406c6..e9ac47d86b69 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/rm.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/rm.h @@ -6,6 +6,7 @@ #ifndef __NVKM_RM_H__ #define __NVKM_RM_H__ #include "handles.h" +struct nvkm_ior; struct nvkm_outp; struct r535_gr; =20 @@ -93,6 +94,10 @@ struct nvkm_rm_api { struct { int (*get_caps)(struct nvkm_disp *, int *link_bw, bool *mst, bool *wm); int (*set_indexed_link_rates)(struct nvkm_outp *); + int (*sst)(struct nvkm_ior *, int head, bool ef, + u32 watermark, u32 hblanksym, u32 vblanksym); + int (*vcpi)(struct nvkm_ior *, int head, + u8 slot, u8 slot_nr, u16 pbn, u16 aligned_pbn); } dp; =20 struct { --=20 2.55.0 From nobody Mon Sep 28 08:12:16 2026 Received: from mail-wr1-f52.google.com (mail-wr1-f52.google.com [209.85.221.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 104731DF74F for ; Tue, 25 Aug 2026 00:15:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787616930; cv=none; b=g4c+zeUrOGcVzpotHgQ238FntVbzLOujzK5Yk95jUkr5vud12TKct9JDi0oWD5BIn3BwV1TU2lr3pESWX5aLeJ4/kjUXVAhmROv5H5CMI75Gozy9skYkt3GvYg1ktqHuowN0P7za+ufGbT0cPAzNn/ZQqJ0H3LGbIU2TFZjdn8s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787616930; c=relaxed/simple; bh=DloJqVrrRTqx5pI3JmrxhU/jcdEShwIa0NWx9Pp+Gl0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WL0dbM5X9QQZjd/BlHGtqoctrZcM7KSF0bj7X4tFVlblk2kDZkK5gRyAgiXMrRX7TPQBY6GhU00teObK0rcffixQJi613OM27CLlCTxrsVCxXXcq2AwFjT1TbmnH/0vbBTnf0zj82nKd7ntk0K7m9DnUpKeYGNxOt94sv09PxuY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=tAEt64O+; arc=none smtp.client-ip=209.85.221.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="tAEt64O+" Received: by mail-wr1-f52.google.com with SMTP id ffacd0b85a97d-476a130c138so4014986f8f.0 for ; Mon, 24 Aug 2026 17:15:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787616927; x=1788221727; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=2+P/vDouc9UoeUwar0MlBIfz+YKIXPqdUfu9owZSH9I=; b=tAEt64O+8CMIGKkLevQvDt9MrTOQYoM9dtNU88I7XmL1cSosQZifUa/dgi5+fPDJ7W YAFCoRSkpLmGmQm+WK85yysEr1trHueCK25R2FIEZf1lAFFa2GmtN8BfzC0z2GqjbWwc ZjiBhFjjf65VV/OajmlyA2IPjxs+EZgSEigB306QTBsuSDLB6lUeIwMuuOZ+e6LDX7Iw q+NilrFH3BgpbEgXfnu8OviJVuVeJ0pRK1W3LdV98CiKvthOmOXpqmzRKDo1upadm1DF HnvGnkRY9PS47noF1lyx3LHWcuw61UUYE5NtVKhclVp7PW+d6le7gxWbtmm7YH8YmTtC axmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787616927; x=1788221727; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=2+P/vDouc9UoeUwar0MlBIfz+YKIXPqdUfu9owZSH9I=; b=YD1y4azhB75LBnq9sJ0PGcUQE2EPb1GqOmAoe/JveQqY8vSXmrwrvsYgSizBzG/Q+J TJu5ttZA1coUIbpjS3HhfFZZ1heHD+dd0Zlp490NWqzhM29SFk36qlGd7yMpxV0G5cXC nSL/2Igb0qCA8h0kZYkrF9gtq1DUbwPAldZymVwurP2FzQ4hD+kmRzr6/aspwbRah6qr RePL/FND7/SOinSvUmKePnqtrnVUG67cE0kesW1M4y6P9Xts/7WUDZdg5caIhx9vuaRf 5lPTgioRIIyIIvuL4CbjYwk72M/os930Yb6bywEldlqh+Lposm8j6LtRJGQ6XW/zyEiZ 0oaw== X-Gm-Message-State: AFuF++l6AZlKUzQPpX1dvwWm8w+MoXt7kwPqnuXScmlzWBMd+hvpts20 yPqLN7P1KG0fNy8unGmMMPpA3AbTBkaxr8MAaSnBFKQM490vYWMzyaQRz4euTbtU X-Gm-Gg: AR+sD123S3wJOfQkMaJM54f1l7TcOcUTsd3au0gN/ZzbJUjY8Byc5fDPrkp5VLYvBxf 56eLmzNhgmx6EdW+KKz7V81q19todtaJkLmOqdAQm/U3BD+4mYlKH2g6oEama6KEVqf7RjvqZm0 wbhMkj7qG0bGqeUnXTfK//JMnxZ6A7OdYTXHsX8K6uwofK4dOWY6dRpmqnfGPZtid8si1ujps7z Sx0Dq3zgMm+CK/KMelvTCC7dzg5JvwOzKAhHMahxgeiMRKIQZ7YjTWCi4vFy8qh/nZjxRVFLo6b hIaJm3NtBxHlRklJMcSJDqDOy8i0wBqJphqMWVw4DxfSD7GzH9v2aSic+fj/ZESUPG3n1+Z7lOu 7bW1zFpUAs3O7zC4NzfipEK3vtA20855YjgR/E43a56qKudXnukYOGWgHmYgoPXV3FsqwG0U9Zm 52K6ROmN989QStKF75M2tdhwYb6RnYvX3kOezytvyWfsXb4AvwRLeOoJAbPqn2jCIlyCw= X-Received: by 2002:a05:6000:2204:b0:481:5167:d526 with SMTP id ffacd0b85a97d-482d9ee1e7cmr2945347f8f.6.1787616927138; Mon, 24 Aug 2026 17:15:27 -0700 (PDT) Received: from fedora ([5.31.134.170]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-482c9b78ebfsm9770676f8f.12.2026.08.24.17.15.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Aug 2026 17:15:25 -0700 (PDT) From: Mohamed Ahmed To: linux-kernel@vger.kernel.org Cc: dri-devel@lists.freedesktop.org, Lyude Paul , Danilo Krummrich , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Mary Guillemard , nouveau@lists.freedesktop.org, Mohamed Ahmed , stable@vger.kernel.org Subject: [PATCH v3 07/10] drm/nouveau/disp: fix head state readback on GB20x Date: Tue, 25 Aug 2026 04:14:05 +0400 Message-ID: <20260825001408.14219-8-mohamedahmedegypt2001@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260825001408.14219-1-mohamedahmedegypt2001@gmail.com> References: <20260825001408.14219-1-mohamedahmedegypt2001@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The GSP path reads armed head state and the RG scanout position through gv100_head_state() and gv100_head_rgpos() on every generation. gv100_head_state() reads the core channel's state mirror at a 0x400 per-head stride, which NVD5.0 (GB20x) doubled. Per NVIDIA's published CA7D class header every HEAD_SET method sits at 0x2000 + head * 0x800, while the mirror bases are unchanged (assembly at 0x680000, armed at +0x8000, per OpenRM's v03_00 channel-user-base HAL which is still used on DISPv0502). Add gb202_head_state(), the same readback at the 0x800 stride, and a gb202_gsp_head table to supply it. gv100_head_rgpos() is kept. The RG registers keep their per-head 0x800 stride on NVD5.0, and OpenRM's kdispReadRgLineCountAndFrameCount_v03_00 still reads NV_PDISP_RG_DPCA on DISPv0502. Fixes: 6cc6e08d4542 ("drm/nouveau/kms: add support for GB20x") Cc: stable@vger.kernel.org Signed-off-by: Mohamed Ahmed Reviewed-by: Lyude Paul --- .../gpu/drm/nouveau/nvkm/engine/disp/gb202.c | 51 ++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gb202.c b/drivers/gpu= /drm/nouveau/nvkm/engine/disp/gb202.c index face801af080..765c42039a47 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gb202.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gb202.c @@ -83,6 +83,55 @@ gb202_sor_hdmi_gcp(struct nvkm_ior *sor, int head, bool = enable) nvkm_mask(device, 0x6f0040 + hdmi, 0x00000001, 0x00000001); } =20 +/* Same core-channel state mirror as gv100_head_state() (assembly at 0x680= 000, + * armed at +0x8000, per-head method offsets unchanged), but NVD5.0 spaces + * heads 0x800 apart (see NVCA7D_HEAD_SET_*(a) in clca7d.h). + */ +static void +gb202_head_state(struct nvkm_head *head, struct nvkm_head_state *state) +{ + struct nvkm_device *device =3D head->disp->engine.subdev.device; + const u32 hoff =3D (state =3D=3D &head->arm) * 0x8000 + head->id * 0x800; + u32 data; + + data =3D nvkm_rd32(device, 0x682064 + hoff); + state->vtotal =3D (data & 0xffff0000) >> 16; + state->htotal =3D (data & 0x0000ffff); + data =3D nvkm_rd32(device, 0x682068 + hoff); + state->vsynce =3D (data & 0xffff0000) >> 16; + state->hsynce =3D (data & 0x0000ffff); + data =3D nvkm_rd32(device, 0x68206c + hoff); + state->vblanke =3D (data & 0xffff0000) >> 16; + state->hblanke =3D (data & 0x0000ffff); + data =3D nvkm_rd32(device, 0x682070 + hoff); + state->vblanks =3D (data & 0xffff0000) >> 16; + state->hblanks =3D (data & 0x0000ffff); + /* Bit 31 is ADJ1000DIV1001, not a HERTZ bit. We don't have enough bits + * to add the full clock in hz on Blackwell (35 bits), but state->hz + * is unused and obsolete under GSP so this is fine. + */ + state->hz =3D nvkm_rd32(device, 0x68200c + hoff) & 0x7fffffff; + + data =3D nvkm_rd32(device, 0x682004 + hoff); + switch ((data & 0x000000f0) >> 4) { + case 5: state->or.depth =3D 30; break; + case 4: state->or.depth =3D 24; break; + case 1: state->or.depth =3D 18; break; + default: + state->or.depth =3D 18; + WARN_ON(1); + break; + } +} + +static const struct nvkm_head_func +gb202_gsp_head =3D { + .state =3D gb202_head_state, + .rgpos =3D gv100_head_rgpos, + .vblank_get =3D tu102_head_vblank_get, + .vblank_put =3D tu102_head_vblank_put, +}; + /* GB20x is GSP-only. This table supplies the register programming the * GSP-RM display path needs from the chip. */ @@ -91,7 +140,7 @@ gb202_gsp_disp =3D { .uevent =3D &gv100_disp_chan_uevent, .ramht_size =3D 0x2000, .gsp.intr =3D tu102_disp_intr, - .gsp.head =3D &tu102_gsp_head, + .gsp.head =3D &gb202_gsp_head, .gsp.hdmi_gcp =3D gb202_sor_hdmi_gcp, /* The legacy AVI unit is unchanged on GB20x. */ .gsp.hdmi_infoframe_avi =3D gv100_sor_hdmi_infoframe_avi, --=20 2.55.0 From nobody Mon Sep 28 08:12:16 2026 Received: from mail-wr1-f53.google.com (mail-wr1-f53.google.com [209.85.221.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D731A1DF74F for ; Tue, 25 Aug 2026 00:15:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787616941; cv=none; b=XYmGSVkE1m/azwcLiGqFofr0pdyncqdhYUwbGZajOtHoM4NWMby2ab4OkGM8EmGL10siMpWOPCtc/yQygH1v9mNx1ynJIbghNjlTEUEmJEwP+XtSjNHsTVVF97uFe7c7UmCMvGuEu98Wno3cU87RneO0GuL4aUu2arwmWxWEMMM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787616941; c=relaxed/simple; bh=UJ5NzQN/avXyDqMtAQsiOW+ECU1cubzClqTXY4dYees=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NxlrW011aSKYFrs/ziUfWt2NBvCNKaCxNCAQUA0gXXYABIq9uYMeyNnooEBJYHqv8HLPlyys6Q8eDtrzp1Umo2UAPHTewB00W0MqAWN8vGjwuDuLUcmHgIdLvotFEkffuKH7CK9hXQ0RxOsb4PbyXtAR0HCKIXKeqQ/EzrMoqNs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=qO8rQOjx; arc=none smtp.client-ip=209.85.221.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="qO8rQOjx" Received: by mail-wr1-f53.google.com with SMTP id ffacd0b85a97d-476a130c138so4015072f8f.0 for ; Mon, 24 Aug 2026 17:15:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787616936; x=1788221736; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=QlXM8+B98Oj3ld9axn0pjcyRcs37xmSxRCU/3qFuJS0=; b=qO8rQOjx0zfMxoL2oCnP9waKWRIKvFDLN54nhTUc4wjmFMyyK2jI4BsIgnu8qHYaO6 /pCQfKtEdacneJBUjojPtmg6VRLocBKPcYba++Z51LGIl2SrjBNnK6pIek2Ig6Xi6V5O An72E+2qXo9Dom5lLATDN4N9XZ6TGFcOt3q80xrCgptFAl/52ew+cG/kb4o7cFmWcCOo HNHspa+2nZ+NdRfDVZ1K59rwe7JugQap7ikPTqiYojDMgFjq0nF29VhcvHuHeb9cQGNi yynDIWkUEV8i9Hu8dNy2whzyJihJgrAqKMMWCdaPmv6h4jnR02XeVtWJcjlYpOrp+sE5 K0WQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787616936; x=1788221736; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=QlXM8+B98Oj3ld9axn0pjcyRcs37xmSxRCU/3qFuJS0=; b=A7/1ufTjq2WNsxPAQA9AEHLUIp2bfHMPiWaV1ReToIenXPggL2QKPjpATyDYkvCMV/ 18qEoRY4F5im9mTWVzT+0MUCxvUwcv+cQO/YRhjPq0vzD8HQ33HQMApl+B/a49IMv3mm A31l89NzczEvZS2ig6jI4QBaATkapMnu4t/qliXqOLXGxF2EioMau7uhT3Ux38r8TGGL KKce/Y5zQZwVjj+7VXEP/3Gd/ZSmjIqodXSah5OblNdrM3QdhpTu9ybmMKZPY3CRyx1l +ock7/HhS381FrFgfjO+VcU+YpYr7ZghbgkSLW4IqRM/RLjPvH3LOvvI5/A78moeJeDm ZelQ== X-Gm-Message-State: AFuF++k6/MJaToF1Q07UNo5RoUDHGB/VJvpsdgzDOxDT3zkI523giCmM AOFS0PogR2SDKlBm9GRV+EZq99Wkx4ev/FQ6dqOD77TdVnRBKC5UEcRUy3WzceQw X-Gm-Gg: AR+sD12srsTulFsgPe5PwUv6eSeJzuRxIAi4qBoPijlXOY4s+nHT2Iw91K3BIf0UoVD p+RpWfRGCMBpJjartY4lRwZv/BX3HW9CRALhmCcR6myFglvrI2zPapgIzgLq/nml/Tjja2O2Bf/ Besxt9KIU1Zf4sO5QKeGydTLpdnnGAJ0dCwdWdMGi8Um43O44lSU35KIpAL7LYzHfrCxbDG7IQT +HRsbSg200AL+p4caOfkA1xptoLP0kliOFaxRcY6Xrpy5HT04w0ekxee3iGa0TanbdFuSInOvgA WuYGawyWON/ZJuv1DZ918at0UOCwqDLYA51oN4+ENGH+B5SHn+OZFlB2PmzmAqz7XAYvVehF3wP e0R6EerOAjjObxiUwrgXXBXVG82y9vowsibCsxsMJRjz0iCi/P7c1O3sRsBffHQZsEnvamslHOl gTokayzwDzpJbiNOPhlxYNKSr8inGnXGlIgXzwA9y9kY3EgUoOzNLJdzATVv7Lp0+rWuQNMAjqk dlFDn4= X-Received: by 2002:a05:6000:2dc6:b0:47f:9266:9bde with SMTP id ffacd0b85a97d-482d9ed6576mr2374878f8f.4.1787616936020; Mon, 24 Aug 2026 17:15:36 -0700 (PDT) Received: from fedora ([5.31.134.170]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-482c9b78ebfsm9770676f8f.12.2026.08.24.17.15.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Aug 2026 17:15:34 -0700 (PDT) From: Mohamed Ahmed To: linux-kernel@vger.kernel.org Cc: dri-devel@lists.freedesktop.org, Lyude Paul , Danilo Krummrich , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Mary Guillemard , nouveau@lists.freedesktop.org, Mohamed Ahmed , stable@vger.kernel.org Subject: [PATCH v3 08/10] drm/nouveau/gsp: fix vblank interrupts on GB20x Date: Tue, 25 Aug 2026 04:14:06 +0400 Message-ID: <20260825001408.14219-9-mohamedahmedegypt2001@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260825001408.14219-1-mohamedahmedegypt2001@gmail.com> References: <20260825001408.14219-1-mohamedahmedegypt2001@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The GSP path programs per-head timing (vblank) interrupts the same way on every generation. NVD5.0 (GB20x) reworked the FE interrupt frontend around four message-based kernel vectors (high latency, low latency, PMU, and GSP) and moved RM head-timing interrupts to the dedicated low-latency vector: - The enable is NV_PDISP_FE_RM_INTR_EN1_HEAD_TIMING, 0x611ef0 + head*4 (570.144 kernel_head_0501.c, renamed kernel_head_0502.c from 575.51.02 on, and v05_01 dev_disp.h). - The vector is reported as a separate interrupt table entry, MC_ENGINE_IDX_DISP_LOW (intr_gb202.c, intrCacheDispIntrVectors). - The vector must be re-armed through NV_PDISP_FE_INTR_RETRIGGER(1) at 0x611f34 after servicing (kdispServiceInterrupt -> kdispIntrRetrigger_v05_01). The event latch (0x611800), per-head status (0x611c00), and dispatch summary (0x611ec0) the interrupt handler uses are unchanged on GB20x (kheadReadPendingVblank_v03_00 and kheadResetPendingLastData_v03_00 remain for DISPv0502+). On GB20x the old code enables head timing onto the legacy vector, leaves its handler there, and never re-arms the message-based vectors. Page flips still complete (nv50 sends those events from the commit path), so the desktop looks fine while DRM vblank waits and vblank sequence queries are affected. Supply GB20x vblank enables and an interrupt handler that re-arms the vector after servicing through gb202_gsp_disp, translate the low-latency interrupt table entry as a second NVKM_ENGINE_DISP instance, and add a gsp.intr_low_latency flag so r535_disp_oneinit() attaches the handler to that instance. GB20x was the last cross-file user of the TU1xx vblank enables, so make those static and drop their head.h prototypes. Fixes: 6cc6e08d4542 ("drm/nouveau/kms: add support for GB20x") Cc: stable@vger.kernel.org Signed-off-by: Mohamed Ahmed Reviewed-by: Lyude Paul --- .../gpu/drm/nouveau/nvkm/engine/disp/gb202.c | 42 +++++++++++++++++-- .../gpu/drm/nouveau/nvkm/engine/disp/head.h | 2 - .../gpu/drm/nouveau/nvkm/engine/disp/priv.h | 2 + .../gpu/drm/nouveau/nvkm/engine/disp/tu102.c | 4 +- .../nouveau/nvkm/subdev/gsp/rm/r535/disp.c | 10 ++++- .../drm/nouveau/nvkm/subdev/gsp/rm/r570/gsp.c | 9 ++++ 6 files changed, 61 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gb202.c b/drivers/gpu= /drm/nouveau/nvkm/engine/disp/gb202.c index 765c42039a47..d0360610f9fa 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gb202.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gb202.c @@ -124,12 +124,46 @@ gb202_head_state(struct nvkm_head *head, struct nvkm_= head_state *state) } } =20 +/* NVD5.0 (GB20x and later) moved the RM head-timing interrupt enable to + * the low-latency vector's EN1 block. The event latch is unchanged. + */ +static void +gb202_head_vblank_put(struct nvkm_head *head) +{ + struct nvkm_device *device =3D head->disp->engine.subdev.device; + + nvkm_mask(device, 0x611ef0 + (head->id * 4), 0x00000002, 0x00000000); +} + +static void +gb202_head_vblank_get(struct nvkm_head *head) +{ + struct nvkm_device *device =3D head->disp->engine.subdev.device; + + nvkm_wr32(device, 0x611800 + (head->id * 4), 0x00000002); + nvkm_mask(device, 0x611ef0 + (head->id * 4), 0x00000002, 0x00000002); +} + +static irqreturn_t +gb202_disp_intr(struct nvkm_inth *inth) +{ + struct nvkm_disp *disp =3D container_of(inth, typeof(*disp), engine.subde= v.inth); + irqreturn_t ret =3D tu102_disp_intr(inth); + + /* The FE interrupt vectors are message-based on NVD5.0. Re-arm the + * low-latency vector so it fires again for any event that latched + * while we were servicing. + */ + nvkm_wr32(disp->engine.subdev.device, 0x611f34, 0x00000001); + return ret; +} + static const struct nvkm_head_func gb202_gsp_head =3D { .state =3D gb202_head_state, .rgpos =3D gv100_head_rgpos, - .vblank_get =3D tu102_head_vblank_get, - .vblank_put =3D tu102_head_vblank_put, + .vblank_get =3D gb202_head_vblank_get, + .vblank_put =3D gb202_head_vblank_put, }; =20 /* GB20x is GSP-only. This table supplies the register programming the @@ -139,7 +173,9 @@ static const struct nvkm_disp_func gb202_gsp_disp =3D { .uevent =3D &gv100_disp_chan_uevent, .ramht_size =3D 0x2000, - .gsp.intr =3D tu102_disp_intr, + /* Head timing arrives on the dedicated low-latency vector. */ + .gsp.intr =3D gb202_disp_intr, + .gsp.intr_low_latency =3D true, .gsp.head =3D &gb202_gsp_head, .gsp.hdmi_gcp =3D gb202_sor_hdmi_gcp, /* The legacy AVI unit is unchanged on GB20x. */ diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h b/drivers/gpu/= drm/nouveau/nvkm/engine/disp/head.h index 784521c2aca1..5976498da909 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h @@ -56,8 +56,6 @@ int gv100_head_new(struct nvkm_disp *, int id); void gv100_head_state(struct nvkm_head *head, struct nvkm_head_state *stat= e); void gv100_head_rgpos(struct nvkm_head *head, u16 *hline, u16 *vline); =20 -void tu102_head_vblank_get(struct nvkm_head *); -void tu102_head_vblank_put(struct nvkm_head *); extern const struct nvkm_head_func tu102_gsp_head; =20 #define HEAD_MSG(h,l,f,a...) do { = \ diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h b/drivers/gpu/= drm/nouveau/nvkm/engine/disp/priv.h index a9dbda67a7d4..fde321dbd7c8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h @@ -42,6 +42,8 @@ struct nvkm_disp_func { */ struct { irqreturn_t (*intr)(struct nvkm_inth *); + /* Head-timing interrupts arrive on a second DISP vector. */ + bool intr_low_latency; const struct nvkm_head_func *head; void (*hdmi_gcp)(struct nvkm_ior *, int head, bool enable); void (*hdmi_infoframe_avi)(struct nvkm_ior *, int head, void *data, u32 = size); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c b/drivers/gpu= /drm/nouveau/nvkm/engine/disp/tu102.c index 948b1d2f954c..f6c163072ff6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c @@ -123,7 +123,7 @@ tu102_sor_new(struct nvkm_disp *disp, int id) * enables to us. These program the RM head-timing line (bit 1 of the * per-head enable, not the bit nvkm's own gv100 path uses). */ -void +static void tu102_head_vblank_put(struct nvkm_head *head) { struct nvkm_device *device =3D head->disp->engine.subdev.device; @@ -131,7 +131,7 @@ tu102_head_vblank_put(struct nvkm_head *head) nvkm_mask(device, 0x611d80 + (head->id * 4), 0x00000002, 0x00000000); } =20 -void +static void tu102_head_vblank_get(struct nvkm_head *head) { struct nvkm_device *device =3D head->disp->engine.subdev.device; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c b/drive= rs/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c index 7d1d4ee2af79..f5f22173fc2c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c @@ -1671,7 +1671,15 @@ r535_disp_oneinit(struct nvkm_disp *disp) if (ret) return ret; =20 - ret =3D nvkm_gsp_intr_stall(gsp, disp->engine.subdev.type, disp->engine.s= ubdev.inst); + /* Chips that raise head-timing interrupts on a separate low-latency + * vector report it as a second DISP interrupt table entry, exposed + * as instance 1 by the RM engine-index translation (see + * r570_gsp_xlat_mc_engine_idx()). Their high-latency vector + * (instance 0) is left unhandled as no event nouveau enables is + * routed to it, and without a handler it stays masked. + */ + ret =3D nvkm_gsp_intr_stall(gsp, disp->engine.subdev.type, + disp->func->gsp.intr_low_latency ? 1 : disp->engine.subdev.inst); if (ret < 0) return ret; =20 diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/gsp.c b/driver= s/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/gsp.c index 3e391646d8f7..b45781cd0dfd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/gsp.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/gsp.c @@ -44,6 +44,15 @@ r570_gsp_xlat_mc_engine_idx(u32 mc_engine_idx, enum nvkm= _subdev_type *ptype, int *ptype =3D NVKM_ENGINE_DISP; *pinst =3D 0; return true; + case MC_ENGINE_IDX_DISP_LOW: + /* GB20x+ report a separate low-latency display vector, used + * for head-timing interrupts. Expose it as a second DISP + * interrupt instance. r535_disp_oneinit() attaches the + * handler to it when the chip's gsp.intr_low_latency is set. + */ + *ptype =3D NVKM_ENGINE_DISP; + *pinst =3D 1; + return true; case MC_ENGINE_IDX_CE0 ... MC_ENGINE_IDX_CE19: *ptype =3D NVKM_ENGINE_CE; *pinst =3D mc_engine_idx - MC_ENGINE_IDX_CE0; --=20 2.55.0 From nobody Mon Sep 28 08:12:16 2026 Received: from mail-wr1-f51.google.com (mail-wr1-f51.google.com [209.85.221.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 541F21DF74F for ; Tue, 25 Aug 2026 00:15:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787616950; cv=none; b=AGtjGeQgw9zj9b0xHwR/JwkQw9r/qWKEVTCv7nP6THlIlLC90zrPch4+JvbIf3i4ZwK4e+j8DTCutF3nBOOqtzkjG3+qj4HI9I4qjzumihahDiFXXDynbnEl9ZiU4T5NWAHRSdkUu25DS/FMQOvqSq8u314Esxe/DQtZ01M13yM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787616950; c=relaxed/simple; bh=zsTCX/EOi4jOvhq0P3XQPLNE6q8hWgiUiRC81rgz6b8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=p3X3ucb/lg6glSspyzbqo2itw0YeoVBEux5ou4YkImHN+PtXwnCXNJk51gYuXHdxCXF4jFRFhFVYKaXobtGwiKE1aUtKTf2U5MSCqTXUArCjQpEKJgWYYKqvFQmS/1giCASxyipSSkBN2fV7ziVeFGytcIoXJCLzpLhIPuRsvpY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=iBYhzghX; arc=none smtp.client-ip=209.85.221.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="iBYhzghX" Received: by mail-wr1-f51.google.com with SMTP id ffacd0b85a97d-47f6609c657so1712148f8f.2 for ; Mon, 24 Aug 2026 17:15:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787616946; x=1788221746; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=v+UheZ0Lyv0FjGXFOmgiG2WD4aRSJL9mFA1poG6PJPI=; b=iBYhzghXkiR25MdvDPoExRLUR2W0KgpXd6I6r6jpgL0if+ALIL3u/FdlBrxLNV3a5G Znk34imTJfFMgBASE+SkFFFecuF0Bc2exQIXricjsMX4AXFO5H5QIteQ99/sQWNZAo9H vimKt0vsrUjgqYo3Ns41pkCNGmKOY2HICkxsT0i0QyuUzuL5oLfWrjj4zsaOjBOAz1pA oZrumo6kNA5yXnVV6VoBlZymuE478dHy2fwo/iY/i3uUS17IQudwlRdzqrLJTc1+sqZF t6SATl7mNXEgof7sYdhseSiEYXMJfHUIe9eQxPWF5prn9tSZTB7e+AXHw8T3a1fGn/kE t7pA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787616946; x=1788221746; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=v+UheZ0Lyv0FjGXFOmgiG2WD4aRSJL9mFA1poG6PJPI=; b=XOxNsT9WwNa8fFe5VURT7LTrKTYTixQXLj3Z4HfjrwRvnFZEN7WUBZXGiddiEnpGgE Yga1qq4o2bxXHsKhih9zCkACnRuQON++9dQvjAN157CvhbRwxA61u9F40iAOkP1ksLpA mCiUAyt64dQh8QysuW39HZ3KkrWAU1ElkVp+racZQtM0m0l7g/J0GgVPmSEJH2XO1K7e guQkEChp30mWPHiDhUEr2rWT9S8YPxv5K6HzVtGcsdlHaX3jYr2QHsy3q2TKm/8jfeu5 HFVgk0FGL6hvzF37lAb6LbvBOKAoUFl2Xd90CyXAacyEVXrrYOUr5T/t2KlNqmb+KYQO lThw== X-Gm-Message-State: AFuF++ndIgdZLKCl35NDiuB/wXPWO/T2VV5Iuq7I5FNxTZu7ox/U3Ose 5o4rIlboY3lDMGE4j29NFCUMoTPuxqXAw9z2WLi7Zb/so8iX4aXhcdBkR3Ku+jpN X-Gm-Gg: AR+sD10cbsYKA/DAtz85ahOF/hSORe58dfUe0RO+NFlIiiirz8kyitk1bk+JcDqgax4 xJb/qHjZ/l9jo2VQ41DPJJ0cb/DdYgqAPZNSaHifzvNpK61JgnnvljiYWmWab0Z8kPq2rSujHtj tvriK7+ubCe18+hwq0/gjLK1pPpkywPQYHxmjDcQc0h3vxhpFehp+xcqntarNWvndkCNE80vLcs 1JB1EeEdafP1NrTO3PAiruofg88R5kgIXoZcVMTjP8rWKPDKzjTv/8rjRzNW8O0IkGE+doxilVk 6iv+1AvrSK2Jb00D5sJb1/1LPZ+3zJEOY2WQ1mZzccEvynN5mHFT7obbR/AK4ssC3+X1A5j1+wf 2evpvcvxf+64NNxVq1Lk3LHjekx2a3+UsrotqzLGhlO4i3JROL7T2oiUmu+i7yi93dU+GJEBJns z4ELxHGhIJPZszLNjEpRlrHuMxqOY6ZNDdd7s8Ryl511zpTwz5r/dnibN6qyHX8UJA9Uc= X-Received: by 2002:a05:6000:4008:b0:482:c72e:6af4 with SMTP id ffacd0b85a97d-482d9e97514mr2786420f8f.0.1787616946458; Mon, 24 Aug 2026 17:15:46 -0700 (PDT) Received: from fedora ([5.31.134.170]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-482c9b78ebfsm9770676f8f.12.2026.08.24.17.15.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Aug 2026 17:15:44 -0700 (PDT) From: Mohamed Ahmed To: linux-kernel@vger.kernel.org Cc: dri-devel@lists.freedesktop.org, Lyude Paul , Danilo Krummrich , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Mary Guillemard , nouveau@lists.freedesktop.org, Mohamed Ahmed Subject: [PATCH v3 09/10] drm/nouveau/dispnv50: program pixel clocks above 2.147GHz on GB20x Date: Tue, 25 Aug 2026 04:14:07 +0400 Message-ID: <20260825001408.14219-10-mohamedahmedegypt2001@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260825001408.14219-1-mohamedahmedegypt2001@gmail.com> References: <20260825001408.14219-1-mohamedahmedegypt2001@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The HEAD_SET_PIXEL_CLOCK_FREQUENCY(_MAX) methods carry only 31 HERTZ bits. Starting with C97D the upper bits live in separate HEAD_SET_PIXEL_CLOCK_FREQUENCY_HI(_MAX) methods, which nouveau never programmed and headca7d_mode() computed m->clock * 1000 into the 31-bit field. NVVAL's mask then silently truncates anything past 2^31 Hz, which means that every mode scanned out at pclk modulo 2^31. No mode nouveau can currently commit crosses the boundary (an uncompressed HDMI FRL mode tops out around 1.78GHz at 8bpc), but this is a prerequisite for the upcoming DSC work, which makes 2.147GHz+ modes reachable. Program the full value split across the low and HI methods, exactly as OpenRM's EvoSetRasterParams9() does (nvkms-evo4.c, 31-bit low word plus the 4 HI HERTZ bits, giving 35 bits of range). Signed-off-by: Mohamed Ahmed Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/dispnv50/headca7d.c | 21 ++++++++++++++++--- .../drm/nouveau/include/nvhw/class/clca7d.h | 4 ++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/nouveau/dispnv50/headca7d.c b/drivers/gpu/drm/= nouveau/dispnv50/headca7d.c index eeaeb15aa664..678cbc78ca9f 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/headca7d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/headca7d.c @@ -219,10 +219,11 @@ headca7d_mode(struct nv50_head *head, struct nv50_hea= d_atom *asyh) { struct nvif_push *push =3D &head->disp->core->chan.push; struct nv50_head_mode *m =3D &asyh->mode; + const u64 hz =3D (u64)m->clock * 1000; const int i =3D head->base.index; int ret; =20 - ret =3D PUSH_WAIT(push, 11); + ret =3D PUSH_WAIT(push, 14); if (ret) return ret; =20 @@ -245,11 +246,25 @@ headca7d_mode(struct nv50_head *head, struct nv50_hea= d_atom *asyh) PUSH_MTHD(push, NVCA7D, HEAD_SET_CONTROL(i), NVDEF(NVCA7D, HEAD_SET_CONTROL, STRUCTURE, PROGRESSIVE)); =20 + /* The FREQUENCY methods carry only 31 HERTZ bits; the upper bits + * of anything past 2.147GHz live in the HI methods + * (EvoSetRasterParams9()). Truncating would scan out at pclk modulo 2^31. + */ PUSH_MTHD(push, NVCA7D, HEAD_SET_PIXEL_CLOCK_FREQUENCY(i), - NVVAL(NVCA7D, HEAD_SET_PIXEL_CLOCK_FREQUENCY, HERTZ, m->clock * 1000)); + NVVAL(NVCA7D, HEAD_SET_PIXEL_CLOCK_FREQUENCY, HERTZ, + (u32)(hz & 0x7fffffff))); =20 PUSH_MTHD(push, NVCA7D, HEAD_SET_PIXEL_CLOCK_FREQUENCY_MAX(i), - NVVAL(NVCA7D, HEAD_SET_PIXEL_CLOCK_FREQUENCY_MAX, HERTZ, m->clock * 10= 00)); + NVVAL(NVCA7D, HEAD_SET_PIXEL_CLOCK_FREQUENCY_MAX, HERTZ, + (u32)(hz & 0x7fffffff))); + + PUSH_MTHD(push, NVCA7D, HEAD_SET_PIXEL_CLOCK_FREQUENCY_HI(i), + NVVAL(NVCA7D, HEAD_SET_PIXEL_CLOCK_FREQUENCY_HI, HERTZ, + (u32)(hz >> 31)), + + HEAD_SET_PIXEL_CLOCK_FREQUENCY_HI_MAX(i), + NVVAL(NVCA7D, HEAD_SET_PIXEL_CLOCK_FREQUENCY_HI_MAX, HERTZ, + (u32)(hz >> 31))); =20 return 0; } diff --git a/drivers/gpu/drm/nouveau/include/nvhw/class/clca7d.h b/drivers/= gpu/drm/nouveau/include/nvhw/class/clca7d.h index 0fec6fc21d44..5754878ddc69 100644 --- a/drivers/gpu/drm/nouveau/include/nvhw/class/clca7d.h +++ b/drivers/gpu/drm/nouveau/include/nvhw/class/clca7d.h @@ -734,6 +734,10 @@ #define NVCA7D_HEAD_SET_CONTROL_CURSOR_COMPOSITION_BYPASS = 20:20 #define NVCA7D_HEAD_SET_CONTROL_CURSOR_COMPOSITION_BYPASS_DISABLE = (0x00000000) #define NVCA7D_HEAD_SET_CONTROL_CURSOR_COMPOSITION_BYPASS_ENABLE = (0x00000001) +#define NVCA7D_HEAD_SET_PIXEL_CLOCK_FREQUENCY_HI(a) = (0x000020C0 + (a)*0x00000800) +#define NVCA7D_HEAD_SET_PIXEL_CLOCK_FREQUENCY_HI_HERTZ = 3:0 +#define NVCA7D_HEAD_SET_PIXEL_CLOCK_FREQUENCY_HI_MAX(a) = (0x000020C4 + (a)*0x00000800) +#define NVCA7D_HEAD_SET_PIXEL_CLOCK_FREQUENCY_HI_MAX_HERTZ = 3:0 #define NVCA7D_HEAD_SET_SURFACE_ADDRESS_HI_CRC(a) = (0x00002150 + (a)*0x00000800) #define NVCA7D_HEAD_SET_SURFACE_ADDRESS_HI_CRC_ADDRESS_HI = 31:0 #define NVCA7D_HEAD_SET_SURFACE_ADDRESS_LO_CRC(a) = (0x00002154 + (a)*0x00000800) --=20 2.55.0 From nobody Mon Sep 28 08:12:16 2026 Received: from mail-wr1-f51.google.com (mail-wr1-f51.google.com [209.85.221.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9E0E422A4EE for ; Tue, 25 Aug 2026 00:15:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787616957; cv=none; b=SiBJwufFts6W4UH1xk8xC9L3bmNVpedZIYKXhYLaeDclwOWkIUaWCUrlgQSW6MoeiDi+V5Wa5I8s7hR6/OosZyYrNsAiUnfmvLIer2ZtBm/E6kw5mkKo/lSWBVVGZbfhxodl7PnY6qdjtQQW0czMZEH6kh16KoYhDFj93SIq1iA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787616957; c=relaxed/simple; bh=raLL/sYbe7+cwnq0hHbeN1n3Q/tzY57KhUczCdVbqUU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GUi6OuSMYXMInPE+Otthco7R0BrH4Rfbid/lbnPT2Qw9hdc/m8K2lHMIdL7f2n9Kue081foV3pYO2PqBg7pKxCgk/bertuAJtLiBQym5ttoQJxoyxPqllUS/qXw1HX0CIO5fWp6eOs/FIEzbYRmz+y2P3g4C3wH9QDsF7q2XFm0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Ty1uGmE6; arc=none smtp.client-ip=209.85.221.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Ty1uGmE6" Received: by mail-wr1-f51.google.com with SMTP id ffacd0b85a97d-47f6609c657so1712177f8f.2 for ; Mon, 24 Aug 2026 17:15:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787616954; x=1788221754; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=JixCBqFO+kIVniOqxJ7x/wZ1qVN5j6ydynDyZHBtUY4=; b=Ty1uGmE6Pa20cDgsLkPzy2WHZl3GV6QMFZka8JlVhrrA3f4UAFJgbbL34DP9OPQfEk sgTxMVYjon4ICU0YGsbk2f8lt1mZlPVq44LsC8sJBK2GreOF8hGHY5+DO0ihN+GdQv33 yHstwZGMUabRZi7Ksbum9ecN2tflQhK/CC/GN0Z2kdkzkWBNRVVpWKUjIh60JbQqwgGq Z0Rz0e1zjTgpETD5CQXbOruFYU+yiPsw9V+1bLnyPyNUOTsZKSVCOMJiG+MuIFPCwe0Y DB84DbOggKyIuQy9UW0l+LPPrtRXWAOIJ0UEsiU1fOMzAm0KBG/wwoLcX0U+7HJdOHkV aRKg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787616954; x=1788221754; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=JixCBqFO+kIVniOqxJ7x/wZ1qVN5j6ydynDyZHBtUY4=; b=SVd0uJDFpVVVEcfYojvQ6MhoKiCVhKdwG5omAoHggOwEL53DNTHaDqNd23Vzj5WaSq Mtbjd6jkMiVMlBrOGcymsKepR9bJW+KIclXWyjcMQ5PZJ5Lw8d80wTKJgTl+L9tuEW4G a5Nu3EejLJSTgeBNx71nZ+PkVOx4UPy1TQBpVzSWvfWaxrz4zklk45ktlHN3AvXJtGaW fwXTp/f7puDGmrID+5l3G4UaccLaVEbpwt1SoBqXagf+U4gs8Ji0HYz6+kt+IOfklr+u HGb9sInyB4utOAnDxr9lX57HwYs6r+GuWFjjghfjKmu/WaljCpjGeqqU4YR0ifbQ7fJq 5eKw== X-Gm-Message-State: AFuF++lyd3QJQEk5yV6f+Wet5+fkjqElko39IWmGmRVBJm9NI51bq4OZ zpjQMSEDvrHIdUlK5eMXF7ThzU2q3CEYcxtnBXt6dckp8sOf4VLl9mAijeWS6p5n X-Gm-Gg: AR+sD120a9E+DOLn3B6Hz4y00/Qns24bwga9WO+ySuBdhuZcJNhyU8WyTIrWcixqcsD yoLjAFBZhPG26GKaaS9eCf4wK8WoqLULyjx7ynAj8KZvN4tNTXi7p36/VP2rg/1fi1WW79qkVAE TfFseNw3wNDHwgBRG+0inCW078qDveVelcSxS7yYTQxhQnGRFNE/C6ta2o/1SnVC31tQ7TRFilk +WPYIOQZqrYL6B6w4q4WuX9eo+gXNzu3fhBuIY1yLPvQpog1YYjFWTAW71GgHN72FOUJRtK9d3Q kEuOoY/mVPEWYA1XiLn+ve5//PntPqgS5nFtHfkhIq5eitaSIwQQXwmSRf2/CenexqKtswLqj5Y PA69T09E7iJhH7T3V7tJou8eMYLIVWcAkAgiRc99gi8uW95cxyOgl5hWKqk8paDaYhipOaUPHZv e9DkAloX1mRRqjMbCQbnKvV/Zsx4SSVIkpkziz2D3Jjq6A07D4oqyPWMP7YjmgG+iiNsSCkwLN+ pr3vw== X-Received: by 2002:a05:6000:310f:b0:47f:9662:85fe with SMTP id ffacd0b85a97d-482d9f613b0mr2484359f8f.16.1787616953826; Mon, 24 Aug 2026 17:15:53 -0700 (PDT) Received: from fedora ([5.31.134.170]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-482c9b78ebfsm9770676f8f.12.2026.08.24.17.15.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Aug 2026 17:15:52 -0700 (PDT) From: Mohamed Ahmed To: linux-kernel@vger.kernel.org Cc: dri-devel@lists.freedesktop.org, Lyude Paul , Danilo Krummrich , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Mary Guillemard , nouveau@lists.freedesktop.org, Mohamed Ahmed Subject: [PATCH v3 10/10] drm/nouveau: honor HF-EEODB EDIDs by converting to struct drm_edid Date: Tue, 25 Aug 2026 04:14:08 +0400 Message-ID: <20260825001408.14219-11-mohamedahmedegypt2001@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260825001408.14219-1-mohamedahmedegypt2001@gmail.com> References: <20260825001408.14219-1-mohamedahmedegypt2001@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" HDMI 2.1 sinks ship HF-EEODB EDIDs. Byte 126 deliberately claims one extension block for legacy sources, and the true count lives in the CTA block's first data block. Their high-refresh timings sit in DisplayID extension blocks 2+. The kernel already reads these EDIDs whole, and on GSP boards RM returns the full EDID with its true size. However, nouveau then hands the buffer to the legacy API which sizes the EDID from byte 126 so the DisplayID blocks are not parsed/exposed and the sysfs blob truncates to 256 bytes. The mode list then tops out at the CTA VICs. Convert to the struct drm_edid API, which carries the real size. Read via drm_edid_read_ddc()/drm_edid_read_switcheroo() where an adapter exists, and serve RM's buffer through drm_edid_read_custom() with a block-reading callback where not, which also routes the GSP path through drm's block validation and the debugfs EDID override. A failed RM read now takes the same "no EDID" path as an empty DDC read which stops it from leaking the runtime-PM reference detect() holds. The property, display_info, and mode list go through drm_edid_connector_update()/_add_modes() and every EDID source is funneled through nouveau_connector_set_edid() so all of them reach the property that drm_edid_connector_add_modes() reads from. nouveau_acpi_edid() now returns a drm_edid sized from the EDID's extension count but never past the length _DDC actually returned, so padded buffers pass and truncated ones are rejected, and every firmware-provided EDID (OF, ACPI, VBIOS-embedded) is validated with drm_edid_valid(). An invalid one is treated as no EDID. get_modes() re-syncs the property from the connector's copy when the probe helper has cleared it for a forced-off connector, before adding modes. The few raw EDID readers are converted along with it, so no raw struct edid pointer is kept. Ownership and freeing move to the drm_edid. MST connectors keep their separate legacy path. Signed-off-by: Mohamed Ahmed Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/dispnv04/dfp.c | 5 +- drivers/gpu/drm/nouveau/dispnv50/disp.c | 4 +- drivers/gpu/drm/nouveau/nouveau_acpi.c | 32 ++++- drivers/gpu/drm/nouveau/nouveau_acpi.h | 10 +- drivers/gpu/drm/nouveau/nouveau_connector.c | 148 +++++++++++++++----- drivers/gpu/drm/nouveau/nouveau_connector.h | 12 +- 6 files changed, 163 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/nouveau/dispnv04/dfp.c b/drivers/gpu/drm/nouve= au/dispnv04/dfp.c index c9f96ec8455d..00eb2aacbe93 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/dfp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c @@ -344,9 +344,8 @@ static void nv04_dfp_mode_set(struct drm_encoder *encod= er, regp->fp_control |=3D (2 << 24); if (nv_encoder->dcb->type =3D=3D DCB_OUTPUT_LVDS) { bool duallink =3D false, dummy; - if (nv_connector->edid && - nv_connector->type =3D=3D DCB_CONNECTOR_LVDS_SPWG) { - duallink =3D (((u8 *)nv_connector->edid)[121] =3D=3D 2); + if (nv_connector->spwg_links) { + duallink =3D nv_connector->spwg_links =3D=3D 2; } else { nouveau_bios_parse_lvds_table(dev, output_mode->clock, &duallink, &dummy); diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouv= eau/dispnv50/disp.c index 2c66e480b511..add19d479ebe 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1803,8 +1803,8 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, s= truct drm_atomic_commit *st lvds_dual =3D bios->fp.dual_link; lvds_8bpc =3D bios->fp.if_is_24bit; } else { - if (nv_connector->type =3D=3D DCB_CONNECTOR_LVDS_SPWG) { - if (((u8 *)nv_connector->edid)[121] =3D=3D 2) + if (nv_connector->spwg_links) { + if (nv_connector->spwg_links =3D=3D 2) lvds_dual =3D true; } else if (mode->clock >=3D bios->fp.duallink_transition_clk) { diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouve= au/nouveau_acpi.c index 21b56cc7605c..9e6906490db5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -360,9 +360,10 @@ void nouveau_unregister_dsm_handler(void) {} void nouveau_switcheroo_optimus_dsm(void) {} #endif =20 -void * +const struct drm_edid * nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) { + const struct drm_edid *drm_edid; struct acpi_device *acpidev; int type, ret; void *edid; @@ -384,7 +385,34 @@ nouveau_acpi_edid(struct drm_device *dev, struct drm_c= onnector *connector) if (ret < 0) return NULL; =20 - return edid; + /* Take what _DDC returned as-is first as its length is the only one that + * can describe an HF-EEODB EDID, whose block count is not the byte 126 + * one. Only if that does not validate fall back to trimming the buffer + * to the byte 126 size, which is what the padding some firmware appends + * needs. + */ + drm_edid =3D drm_edid_alloc(edid, ret); + if (drm_edid && !drm_edid_valid(drm_edid)) { + drm_edid_free(drm_edid); + drm_edid =3D NULL; + + if (ret > EDID_LENGTH) { + int trimmed =3D EDID_LENGTH * + (1 + ((const struct edid *)edid)->extensions); + + if (trimmed < ret) + drm_edid =3D drm_edid_alloc(edid, trimmed); + if (drm_edid && !drm_edid_valid(drm_edid)) { + drm_edid_free(drm_edid); + drm_edid =3D NULL; + } + } + } + kfree(edid); + + if (!drm_edid) + drm_dbg_kms(dev, "Invalid EDID from ACPI _DDC\n"); + return drm_edid; } =20 bool nouveau_acpi_video_backlight_use_native(void) diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.h b/drivers/gpu/drm/nouve= au/nouveau_acpi.h index e39dd8b94b8b..bc3ccca7b338 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.h +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.h @@ -4,13 +4,15 @@ =20 #define ROM_BIOS_PAGE 4096 =20 +struct drm_edid; + #if defined(CONFIG_ACPI) && defined(CONFIG_X86) bool nouveau_is_optimus(void); bool nouveau_is_v1_dsm(void); void nouveau_register_dsm_handler(void); void nouveau_unregister_dsm_handler(void); void nouveau_switcheroo_optimus_dsm(void); -void *nouveau_acpi_edid(struct drm_device *, struct drm_connector *); +const struct drm_edid *nouveau_acpi_edid(struct drm_device *, struct drm_c= onnector *); bool nouveau_acpi_video_backlight_use_native(void); void nouveau_acpi_video_register_backlight(void); #else @@ -19,7 +21,11 @@ static inline bool nouveau_is_v1_dsm(void) { return fals= e; }; static inline void nouveau_register_dsm_handler(void) {} static inline void nouveau_unregister_dsm_handler(void) {} static inline void nouveau_switcheroo_optimus_dsm(void) {} -static inline void *nouveau_acpi_edid(struct drm_device *dev, struct drm_c= onnector *connector) { return NULL; } +static inline const struct drm_edid * +nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) +{ + return NULL; +} static inline bool nouveau_acpi_video_backlight_use_native(void) { return = true; } static inline void nouveau_acpi_video_register_backlight(void) {} #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/= nouveau/nouveau_connector.c index b0b0ad9a0c24..3738c23215c5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -397,7 +397,7 @@ nouveau_connector_destroy(struct drm_connector *connect= or) struct nouveau_connector *nv_connector =3D nouveau_connector(connector); nvif_event_dtor(&nv_connector->irq); nvif_event_dtor(&nv_connector->hpd); - kfree(nv_connector->edid); + drm_edid_free(nv_connector->drm_edid); drm_connector_unregister(connector); drm_connector_cleanup(connector); if (nv_connector->aux.transfer) @@ -469,6 +469,36 @@ nouveau_connector_ddc_detect(struct drm_connector *con= nector) return found; } =20 +static void +nouveau_connector_set_edid(struct nouveau_connector *nv_connector, + const struct drm_edid *drm_edid) +{ + if (nv_connector->drm_edid =3D=3D drm_edid) + return; + + /* Updates the EDID property and display_info with HF-EEODB-aware + * sizing. The legacy helpers truncate both to what EDID byte 126 + * admits, hiding the DisplayID extension blocks that carry the + * high-refresh timings. + */ + drm_edid_connector_update(&nv_connector->base, drm_edid); + + drm_edid_free(nv_connector->drm_edid); + nv_connector->drm_edid =3D drm_edid; + + /* The SPWG link-count byte lives in a vendor descriptor drm has no + * accessor for. Peek at it once here so nothing else needs the raw + * EDID. + */ + nv_connector->spwg_links =3D 0; + if (nv_connector->type =3D=3D DCB_CONNECTOR_LVDS_SPWG) { + const u8 *raw =3D (const u8 *)drm_edid_raw(drm_edid); + + if (raw) + nv_connector->spwg_links =3D raw[121] =3D=3D 2 ? 2 : 1; + } +} + static struct nouveau_encoder * nouveau_connector_of_detect(struct drm_connector *connector) { @@ -490,8 +520,17 @@ nouveau_connector_of_detect(struct drm_connector *conn= ector) int idx =3D name ? name[strlen(name) - 1] - 'A' : 0; =20 if (nv_encoder->dcb->i2c_index =3D=3D idx && edid) { - nv_connector->edid =3D - kmemdup(edid, EDID_LENGTH, GFP_KERNEL); + const struct drm_edid *drm_edid =3D + drm_edid_alloc(edid, EDID_LENGTH); + + /* Firmware-provided, so validate it like the DDC + * readers would. + */ + if (drm_edid && !drm_edid_valid(drm_edid)) { + drm_edid_free(drm_edid); + drm_edid =3D NULL; + } + nouveau_connector_set_edid(nv_connector, drm_edid); return nv_encoder; } } @@ -546,17 +585,23 @@ nouveau_connector_set_encoder(struct drm_connector *c= onnector, } } =20 -static void -nouveau_connector_set_edid(struct nouveau_connector *nv_connector, - struct edid *edid) +struct nouveau_rm_edid { + u8 *data; + size_t size; +}; + +static int +nouveau_connector_rm_edid_block(void *context, u8 *buf, unsigned int block, + size_t len) { - if (nv_connector->edid !=3D edid) { - struct edid *old_edid =3D nv_connector->edid; + struct nouveau_rm_edid *rm =3D context; + size_t offset =3D (size_t)block * EDID_LENGTH; =20 - drm_connector_update_edid_property(&nv_connector->base, edid); - kfree(old_edid); - nv_connector->edid =3D edid; - } + if (offset + len > rm->size) + return -EINVAL; + + memcpy(buf, rm->data + offset, len); + return 0; } =20 static enum drm_connector_status @@ -590,22 +635,37 @@ nouveau_connector_detect(struct drm_connector *connec= tor, bool force) =20 nv_encoder =3D nouveau_connector_ddc_detect(connector); if (nv_encoder) { - struct edid *new_edid =3D NULL; + const struct drm_edid *new_edid =3D NULL; =20 if (nv_encoder->i2c) { if ((vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC) && nv_connector->type =3D=3D DCB_CONNECTOR_LVDS) - new_edid =3D drm_get_edid_switcheroo(connector, nv_encoder->i2c); + new_edid =3D drm_edid_read_switcheroo(connector, nv_encoder->i2c); else - new_edid =3D drm_get_edid(connector, nv_encoder->i2c); + new_edid =3D drm_edid_read_ddc(connector, nv_encoder->i2c); } else { - ret =3D nvif_outp_edid_get(&nv_encoder->outp, (u8 **)&new_edid); - if (ret < 0) - return connector_status_disconnected; + struct nouveau_rm_edid rm =3D {}; + + /* RM (which owns the DDC pads on GSP boards) reads the + * EDID whole and returns its true size, which for an + * HF-EEODB EDID exceeds what byte 126 admits. Serve it + * through drm's block reader so EEODB sizing, block + * validation, and the debugfs EDID override all apply. + * A failed read is treated like an empty DDC read, + * which releases the runtime-PM reference. + */ + ret =3D nvif_outp_edid_get(&nv_encoder->outp, &rm.data); + if (ret >=3D 0) { + rm.size =3D ret; + new_edid =3D drm_edid_read_custom(connector, + nouveau_connector_rm_edid_block, + &rm); + kfree(rm.data); + } } =20 nouveau_connector_set_edid(nv_connector, new_edid); - if (!nv_connector->edid) { + if (!nv_connector->drm_edid) { NV_ERROR(drm, "DDC responded, but no EDID for %s\n", connector->name); goto detect_analog; @@ -626,7 +686,7 @@ nouveau_connector_detect(struct drm_connector *connecto= r, bool force) nv_partner->dcb->type =3D=3D DCB_OUTPUT_TMDS) || (nv_encoder->dcb->type =3D=3D DCB_OUTPUT_TMDS && nv_partner->dcb->type =3D=3D DCB_OUTPUT_ANALOG))) { - if (nv_connector->edid->input & DRM_EDID_INPUT_DIGITAL) + if (drm_edid_is_digital(nv_connector->drm_edid)) type =3D DCB_OUTPUT_TMDS; else type =3D DCB_OUTPUT_ANALOG; @@ -638,7 +698,8 @@ nouveau_connector_detect(struct drm_connector *connecto= r, bool force) conn_status =3D connector_status_connected; =20 if (nv_encoder->dcb->type =3D=3D DCB_OUTPUT_DP) - drm_dp_cec_set_edid(&nv_connector->aux, nv_connector->edid); + drm_dp_cec_attach(&nv_connector->aux, + connector->display_info.source_physical_address); =20 goto out; } else { @@ -670,7 +731,7 @@ nouveau_connector_detect(struct drm_connector *connecto= r, bool force) } =20 out: - if (!nv_connector->edid) + if (!nv_connector->drm_edid) drm_dp_cec_unset_edid(&nv_connector->aux); =20 pm_runtime_mark_last_busy(dev->dev); @@ -686,7 +747,7 @@ nouveau_connector_detect_lvds(struct drm_connector *con= nector, bool force) struct nouveau_drm *drm =3D nouveau_drm(dev); struct nouveau_connector *nv_connector =3D nouveau_connector(connector); struct nouveau_encoder *nv_encoder =3D NULL; - struct edid *edid =3D NULL; + const struct drm_edid *edid =3D NULL; enum drm_connector_status status =3D connector_status_disconnected; =20 nv_encoder =3D find_encoder(connector, DCB_OUTPUT_LVDS); @@ -697,7 +758,7 @@ nouveau_connector_detect_lvds(struct drm_connector *con= nector, bool force) if (!drm->vbios.fp_no_ddc) { status =3D nouveau_connector_detect(connector, force); if (status =3D=3D connector_status_connected) { - edid =3D nv_connector->edid; + edid =3D nv_connector->drm_edid; goto out; } } @@ -733,11 +794,20 @@ nouveau_connector_detect_lvds(struct drm_connector *c= onnector, bool force) * stored for the panel stored in them. */ if (!drm->vbios.fp_no_ddc) { - edid =3D (struct edid *)nouveau_bios_embedded_edid(dev); - if (edid) { - edid =3D kmemdup(edid, EDID_LENGTH, GFP_KERNEL); + const void *embedded =3D nouveau_bios_embedded_edid(dev); + + if (embedded) { + edid =3D drm_edid_alloc(embedded, EDID_LENGTH); + /* The panel is there either way, so report it + * connected and let the probe helper fall back to a + * default mode if the EDID itself is unusable. + */ if (edid) status =3D connector_status_connected; + if (edid && !drm_edid_valid(edid)) { + drm_edid_free(edid); + edid =3D NULL; + } } } =20 @@ -886,7 +956,7 @@ nouveau_connector_detect_depth(struct drm_connector *co= nnector) bool duallink; =20 /* if the edid is feeling nice enough to provide this info, use it */ - if (nv_connector->edid && connector->display_info.bpc) + if (nv_connector->drm_edid && connector->display_info.bpc) return; =20 /* EDID 1.4 is *supposed* to be supported on eDP, but, Apple... */ @@ -913,9 +983,8 @@ nouveau_connector_detect_depth(struct drm_connector *co= nnector) /* LVDS: DDC panel, need to first determine the number of links to * know which if_is_24bit flag to check... */ - if (nv_connector->edid && - nv_connector->type =3D=3D DCB_CONNECTOR_LVDS_SPWG) - duallink =3D ((u8 *)nv_connector->edid)[121] =3D=3D 2; + if (nv_connector->spwg_links) + duallink =3D nv_connector->spwg_links =3D=3D 2; else duallink =3D mode->clock >=3D bios->fp.duallink_transition_clk; =20 @@ -973,12 +1042,17 @@ nouveau_connector_get_modes(struct drm_connector *co= nnector) nv_connector->native_mode =3D NULL; } =20 - if (nv_connector->edid) - ret =3D drm_add_edid_modes(connector, nv_connector->edid); - else - if (nv_encoder->dcb->type =3D=3D DCB_OUTPUT_LVDS && - (nv_encoder->dcb->lvdsconf.use_straps_for_mode || - drm->vbios.fp_no_ddc) && nouveau_bios_fp_mode(dev, NULL)) { + if (nv_connector->drm_edid) { + /* The probe helper clears the property and display_info for + * a forced-off connector without calling detect(). Re-sync + * from our copy then, since add_modes() reads the property. + */ + if (!connector->edid_blob_ptr) + drm_edid_connector_update(connector, nv_connector->drm_edid); + ret =3D drm_edid_connector_add_modes(connector); + } else if (nv_encoder->dcb->type =3D=3D DCB_OUTPUT_LVDS && + (nv_encoder->dcb->lvdsconf.use_straps_for_mode || + drm->vbios.fp_no_ddc) && nouveau_bios_fp_mode(dev, NULL)) { struct drm_display_mode mode; =20 nouveau_bios_fp_mode(dev, &mode); diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/= nouveau/nouveau_connector.h index 0608cabed058..eb292d2ba4bc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.h +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h @@ -43,7 +43,7 @@ =20 struct nvkm_i2c_port; struct dcb_output; -struct edid; +struct drm_edid; =20 #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT struct nouveau_backlight { @@ -121,6 +121,13 @@ struct nouveau_connector { struct drm_connector base; enum dcb_connector_type type; u8 index; + /* LVDS_SPWG panels state their link count in EDID descriptor 4 (SPWG + * byte 0x79), cached by nouveau_connector_set_edid() so nothing else + * needs the raw EDID. 0 =3D unknown (not an SPWG panel, or no EDID) and + * callers fall back to their transition-clock/VBIOS heuristics; + * 1 =3D single link; 2 =3D dual link. + */ + u8 spwg_links; =20 struct nvif_conn conn; u64 hpd_pending; @@ -137,7 +144,8 @@ struct nouveau_connector { int scaling_mode; =20 struct nouveau_encoder *detected_encoder; - struct edid *edid; + /* Owner of the sink's EDID, HF-EEODB-complete. */ + const struct drm_edid *drm_edid; struct drm_display_mode *native_mode; #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT struct nouveau_backlight *backlight; --=20 2.55.0