From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.223.131]) (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 118EE47AF6D for ; Mon, 14 Sep 2026 14:11:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.131 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789395073; cv=none; b=X/eebCk3d4kK5g5r5X1cBB3KD2Aue9xPa65vKsoQuzwUPQkSWOF/pLknYZV5U7wcFchweMauBO8RGFp7xbSQMb/Yeg+iWU8juwDe7/fG/Ly9jspKGWcgkTaGcYcDyAHYEOT3hNDUAw6z90zcPejx6SmR155Btsn9epO37ADvub8= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789395073; c=relaxed/simple; bh=+lwZydvY2Vbef6JTQmBdSFQEQB9Px5uUFLtxJvN5Iqg=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=JzdQwO3zsEM9awvGUs5eA7zEC9Zs4VHjsF+sboDgKoBrmtgiwoeuVOFUrjuefJaHwPAgAGowpcjQtEs1btwY/vWcJ4cLVDJyR6wbWfNz95ZsnMr9XuaMY71Pd+J4DwKaQdjnarP5maihSq+TisJOp14aO6mJlsN01gLbRM1BpVQ= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de; spf=pass smtp.mailfrom=suse.de; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=RJN+Apn6; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=8l7yOgeZ; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=OCTLjWk0; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=QXJ1c/8z; arc=none smtp.client-ip=195.135.223.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="RJN+Apn6"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="8l7yOgeZ"; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="OCTLjWk0"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="QXJ1c/8z" Received: from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org [IPv6:2a07:de40:b281:104:10:150:64:97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 54A601F7D7; Mon, 14 Sep 2026 14:10:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1789395031; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:autocrypt:autocrypt; bh=VSrt92bw9g8iah1NebfN0cFbUIAoXSrwEgpbBbQbj28=; b=RJN+Apn6THMVTpO8IWmAFqhKgyv3MsP1smdwmjNL4NhRE9CVA8T4RMcfH3EFFk+QFAAFSc O0uHtqNHWdOd/Ld+4E2EoPs/1jG49J6BX4+ptjbXhPFZEamS+8de9eXGPQs3n64m4ZRnLM 6EvjEQt58TcTSopgoFx7z0B5RafriMA= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1789395031; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:autocrypt:autocrypt; bh=VSrt92bw9g8iah1NebfN0cFbUIAoXSrwEgpbBbQbj28=; b=8l7yOgeZwVWsLIt/9b7OU1gkI4FywyQXMU7ehH9c8iAHGkYovP/+QlbvEDsFy3TzWrWezq uNWbDPVKeWisNeBw== Authentication-Results: smtp-out2.suse.de; dkim=pass header.d=suse.de header.s=susede2_rsa header.b=OCTLjWk0; dkim=pass header.d=suse.de header.s=susede2_ed25519 header.b="QXJ1c/8z" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1789395027; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:autocrypt:autocrypt; bh=VSrt92bw9g8iah1NebfN0cFbUIAoXSrwEgpbBbQbj28=; b=OCTLjWk0VppYFK76+0E6N10M4YVdBPJrBTYZfYjkOy4Nk93wVcydNUUXG5r6DFbT30+vx/ ZwoIAQRs/iMvbpwEyfV13JHVec1T2dYPnIIvFx9LhrPenM3uQPJk65q31NSUch2EPZsq4G Vq/XMk15C9DalBjRHIG5A9Co1/b+9L0= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1789395027; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:autocrypt:autocrypt; bh=VSrt92bw9g8iah1NebfN0cFbUIAoXSrwEgpbBbQbj28=; b=QXJ1c/8zqcPYnsNuaC38zOnO5wfiz4RZxxyg6J26hfNbhVTKLmkIfeWuumyKy/KcNSqK6W K2vR0oHf1k349MCg== Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 32A0B13693; Mon, 14 Sep 2026 14:10:26 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id DPfBA1IAqGqaDgAAD6G6ig (envelope-from ); Mon, 14 Sep 2026 14:10:26 +0000 Message-ID: <0dc12950-68e7-4c30-9138-23539e676e1a@suse.de> Date: Mon, 14 Sep 2026 16:10:25 +0200 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH v2 08/17] drm/spacemit: add Saturn DPU core types, cmdlist and display MMU To: codykang.hk@gmail.com, David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Yixun Lan , Vinod Koul , Neil Armstrong , Haylen Chu , Michael Turquette , Stephen Boyd , Brian Masney , Philipp Zabel , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Yao Zi , =?UTF-8?Q?Uwe_Kleine-K=C3=B6nig?= , Guodong Xu Cc: dri-devel@lists.freedesktop.org, linux-riscv@lists.infradead.org, devicetree@vger.kernel.org, spacemit@lists.linux.dev, linux-kernel@vger.kernel.org, linux-phy@lists.infradead.org, linux-clk@vger.kernel.org References: <20260809-k3-display-v2-0-327d7910bf71@gmail.com> <20260809-k3-display-v2-8-327d7910bf71@gmail.com> Content-Language: en-US From: Thomas Zimmermann Autocrypt: addr=tzimmermann@suse.de; keydata= xsBNBFs50uABCADEHPidWt974CaxBVbrIBwqcq/WURinJ3+2WlIrKWspiP83vfZKaXhFYsdg XH47fDVbPPj+d6tQrw5lPQCyqjwrCPYnq3WlIBnGPJ4/jreTL6V+qfKRDlGLWFjZcsrPJGE0 BeB5BbqP5erN1qylK9i3gPoQjXGhpBpQYwRrEyQyjuvk+Ev0K1Jc5tVDeJAuau3TGNgah4Yc hdHm3bkPjz9EErV85RwvImQ1dptvx6s7xzwXTgGAsaYZsL8WCwDaTuqFa1d1jjlaxg6+tZsB 9GluwvIhSezPgnEmimZDkGnZRRSFiGP8yjqTjjWuf0bSj5rUnTGiyLyRZRNGcXmu6hjlABEB AAHNJ1Rob21hcyBaaW1tZXJtYW5uIDx0emltbWVybWFubkBzdXNlLmRlPsLAjgQTAQgAOAIb AwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgBYhBHIX+6yM6c9jRKFo5WgNwR1TC3ojBQJftODH AAoJEGgNwR1TC3ojx1wH/0hKGWugiqDgLNXLRD/4TfHBEKmxIrmfu9Z5t7vwUKfwhFL6hqvo lXPJJKQpQ2z8+X2vZm/slsLn7J1yjrOsoJhKABDi+3QWWSGkaGwRJAdPVVyJMfJRNNNIKwVb U6B1BkX2XDKDGffF4TxlOpSQzdtNI/9gleOoUA8+jy8knnDYzjBNOZqLG2FuTdicBXblz0Mf vg41gd9kCwYXDnD91rJU8tzylXv03E75NCaTxTM+FBXPmsAVYQ4GYhhgFt8S2UWMoaaABLDe 7l5FdnLdDEcbmd8uLU2CaG4W2cLrUaI4jz2XbkcPQkqTQ3EB67hYkjiEE6Zy3ggOitiQGcqp j//OwE0EWznS4AEIAMYmP4M/V+T5RY5at/g7rUdNsLhWv1APYrh9RQefODYHrNRHUE9eosYb T6XMryR9hT8XlGOYRwKWwiQBoWSDiTMo/Xi29jUnn4BXfI2px2DTXwc22LKtLAgTRjP+qbU6 3Y0xnQN29UGDbYgyyK51DW3H0If2a3JNsheAAK+Xc9baj0LGIc8T9uiEWHBnCH+RdhgATnWW GKdDegUR5BkDfDg5O/FISymJBHx2Dyoklv5g4BzkgqTqwmaYzsl8UxZKvbaxq0zbehDda8lv hFXodNFMAgTLJlLuDYOGLK2AwbrS3Sp0AEbkpdJBb44qVlGm5bApZouHeJ/+n+7r12+lqdsA EQEAAcLAdgQYAQgAIAIbDBYhBHIX+6yM6c9jRKFo5WgNwR1TC3ojBQJftOH6AAoJEGgNwR1T C3ojVSkIALpAPkIJPQoURPb1VWjh34l0HlglmYHvZszJWTXYwavHR8+k6Baa6H7ufXNQtThR yIxJrQLW6rV5lm7TjhffEhxVCn37+cg0zZ3j7zIsSS0rx/aMwi6VhFJA5hfn3T0TtrijKP4A SAQO9xD1Zk9/61JWk8OysuIh7MXkl0fxbRKWE93XeQBhIJHQfnc+YBLprdnxR446Sh8Wn/2D Ya8cavuWf2zrB6cZurs048xe0UbSW5AOSo4V9M0jzYI4nZqTmPxYyXbm30Kvmz0rYVRaitYJ 4kyYYMhuULvrJDMjZRvaNe52tkKAvMevcGdt38H4KSVXAylqyQOW5zvPc4/sq9c= In-Reply-To: <20260809-k3-display-v2-8-327d7910bf71@gmail.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit X-Spam-Score: -3.01 X-Rspamd-Queue-Id: 54A601F7D7 X-Rspamd-Server: rspamd1.dmz-prg2.suse.org X-Spam-Level: X-Rspamd-Action: no action X-Spamd-Result: default: False [-3.01 / 50.00]; BAYES_HAM(-3.00)[100.00%]; SUSPICIOUS_RECIPS(1.50)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_DKIM_ALLOW(-0.20)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; MX_GOOD(-0.01)[]; TO_MATCH_ENVRCPT_ALL(0.00)[]; DKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; FREEMAIL_TO(0.00)[gmail.com,ffwll.ch,linux.intel.com,kernel.org,linaro.org,4d2.org,baylibre.com,redhat.com,pengutronix.de,dabbelt.com,eecs.berkeley.edu,ghiti.fr,ziyao.cc]; SPAMHAUS_XBL(0.00)[2a07:de40:b281:104:10:150:64:97:from]; ARC_NA(0.00)[]; RCPT_COUNT_TWELVE(0.00)[30]; MIME_TRACE(0.00)[0:+]; FREEMAIL_ENVRCPT(0.00)[gmail.com]; RCVD_TLS_ALL(0.00)[]; DKIM_TRACE(0.00)[suse.de:+]; RCVD_COUNT_TWO(0.00)[2]; FROM_EQ_ENVFROM(0.00)[]; FROM_HAS_DN(0.00)[]; TO_DN_SOME(0.00)[]; MID_RHS_MATCH_FROM(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; TAGGED_RCPT(0.00)[dt]; R_RATELIMIT(0.00)[to_ip_from(RLkaw45m9fyyou58pkcdpg1rmb)]; DBL_BLOCKED_OPENRESOLVER(0.00)[suse.de:dkim,suse.de:mid,suse.com:url,imap1.dmz-prg2.suse.org:helo,imap1.dmz-prg2.suse.org:rdns] X-Spam-Flag: NO Hi Am 09.08.26 um 15:14 schrieb Cody Kang via B4 Relay: > From: Cody Kang > > Register programming of the Saturn DPU is batched: the driver builds > per-module register lists in memory and the hardware command-list > engine replays them at frame boundaries, while scanout buffers are > mapped through the DPU's private address translation unit (DMMU) > rather than scanned out by physical address. I've looked through the code in patch 10. How does a plane interact with the hardware? It apparently has its own command list, but there's mostly code for the CRTC update. Best regards Thomas > > Add the shared driver types, the MMIO field accessors, the trace > events, the command-list builder and the DMMU table code. Some DPU > configuration registers are write-only, so a read-modify-write would > corrupt neighbouring fields; byte- and halfword-aligned fields are > therefore written at their native width instead. > > Signed-off-by: Cody Kang > > --- > v2: > - hold the DPU reset lines as one reset_control_bulk_data > pipe_resets[5] array in spacemit_drm_private and drop the pointers > duplicated into struct spacemit_crtc (Philipp Zabel) > - drop the INT_VSYNC_UPDATE enum member; it never had an irq_list[] > mapping and the register model has no such status bit (Sashiko) > - drop the unreachable multi-planar arms in spacemit_dmmu_map(); every > advertised format is single-planar (Sashiko) > - drop the unused cmdlist parameter from the crtc_cmdlist op (Sashiko) > --- > drivers/gpu/drm/spacemit/dpu/dpu_saturn.h | 35 +++ > drivers/gpu/drm/spacemit/dpu/dpu_trace.h | 350 ++++++++++++++++++++++++++++ > drivers/gpu/drm/spacemit/spacemit_cmdlist.c | 304 ++++++++++++++++++++++++ > drivers/gpu/drm/spacemit/spacemit_cmdlist.h | 146 ++++++++++++ > drivers/gpu/drm/spacemit/spacemit_crtc.h | 246 +++++++++++++++++++ > drivers/gpu/drm/spacemit/spacemit_dmmu.c | 80 +++++++ > drivers/gpu/drm/spacemit/spacemit_dmmu.h | 40 ++++ > drivers/gpu/drm/spacemit/spacemit_dpu_reg.h | 108 +++++++++ > drivers/gpu/drm/spacemit/spacemit_drm.h | 61 +++++ > 9 files changed, 1370 insertions(+) > > diff --git a/drivers/gpu/drm/spacemit/dpu/dpu_saturn.h b/drivers/gpu/drm/spacemit/dpu/dpu_saturn.h > new file mode 100644 > index 0000000000000..22d77d56eca1a > --- /dev/null > +++ b/drivers/gpu/drm/spacemit/dpu/dpu_saturn.h > @@ -0,0 +1,35 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright (C) 2025-2026 SpacemiT Co., Ltd. > + * > + */ > + > +#ifndef _DPU_SATURN_H_ > +#define _DPU_SATURN_H_ > + > +#include "../spacemit_crtc.h" > + > +struct dpu_format_id { > + u32 format; /* DRM fourcc */ > + u8 id; > + u8 bpp; /* bits per pixel */ > +}; > + > +#define SPACEMIT_DPU_INVALID_FORMAT_ID 0xff > + > +enum format_features { > + FORMAT_RGB = BIT(0), > +}; > + > +struct spacemit_hw_rdma { > + u16 formats; > +}; > + > +int dpu_parse_clocks(struct device *dev, struct dpu_clk_context *clk_ctx); > +u8 spacemit_plane_hw_get_format_id(u32 format); > +u32 saturn_conf_dpuctrl_rdma(struct spacemit_crtc *a_crtc); > +extern const struct spacemit_hw_device k3_saturn_dpu; > +void saturn_enable_irq_mask(struct spacemit_crtc *a_crtc, bool enable, > + u32 offset, u32 mask); > +void spacemit_cfg_rdy_timer_handler(struct timer_list *t); > +#endif > diff --git a/drivers/gpu/drm/spacemit/dpu/dpu_trace.h b/drivers/gpu/drm/spacemit/dpu/dpu_trace.h > new file mode 100644 > index 0000000000000..abfe34a67a4bd > --- /dev/null > +++ b/drivers/gpu/drm/spacemit/dpu/dpu_trace.h > @@ -0,0 +1,350 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright (C) 2025-2026 SpacemiT Co., Ltd. > + * > + */ > + > +#undef TRACE_SYSTEM > +#define TRACE_SYSTEM spacemit_dpu > + > +#if !defined(_DPU_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ) > +#define _DPU_TRACE_H_ > + > +#include > +#include > +#include > + > +#include "dpu_saturn.h" > + > +TRACE_EVENT(drm_display_mode_info, > + TP_PROTO(struct drm_display_mode *mode), > + TP_ARGS(mode), > + TP_STRUCT__entry( > + __field(u16, hdisplay) > + __field(u16, hbp) > + __field(u16, hfp) > + __field(u16, hsync) > + __field(u16, vdisplay) > + __field(u16, vbp) > + __field(u16, vfp) > + __field(u16, vsync) > + ), > + TP_fast_assign( > + __entry->hdisplay = mode->hdisplay; > + __entry->hbp = mode->htotal - mode->hsync_end; > + __entry->hfp = mode->hsync_start - mode->hdisplay; > + __entry->hsync = mode->hsync_end - mode->hsync_start; > + __entry->vdisplay = mode->vdisplay; > + __entry->vbp = mode->vtotal - mode->vsync_end; > + __entry->vfp = mode->vsync_start - mode->vdisplay; > + __entry->vsync = mode->vsync_end - mode->vsync_start; > + ), > + TP_printk("drm_display_mode: hdisplay=%d vdisplay=%d hsync=%d vsync=%d hbp=%d hfp=%d vbp=%d vfp=%d", > + __entry->hdisplay, __entry->vdisplay, __entry->hsync, __entry->vsync, > + __entry->hbp, __entry->hfp, __entry->vbp, __entry->vfp > + ) > +); > + > +TRACE_EVENT(dpu_plane_info, > + TP_PROTO(struct drm_plane_state *state, struct drm_framebuffer *fb, > + u32 rdma_id, u32 alpha, u32 rotation), > + TP_ARGS(state, fb, rdma_id, alpha, rotation), > + TP_STRUCT__entry( > + __field(u32, rdma_id) > + __field(u32, src_w) > + __field(u32, src_h) > + __field(u32, src_x) > + __field(u32, src_y) > + __field(u32, crtc_w) > + __field(u32, crtc_h) > + __field(u32, crtc_x) > + __field(u32, crtc_y) > + __field(u32, width) > + __field(u32, height) > + __field(u32, format) > + __field(u32, blend_mode) > + __field(u32, alpha) > + __field(u32, zpos) > + __field(u32, rotation) > + ), > + TP_fast_assign( > + __entry->rdma_id = rdma_id; > + __entry->src_w = state->src_w >> 16; > + __entry->src_h = state->src_h >> 16; > + __entry->src_x = state->src_x >> 16; > + __entry->src_y = state->src_y >> 16; > + __entry->crtc_w = state->crtc_w; > + __entry->crtc_h = state->crtc_h; > + __entry->crtc_x = state->crtc_x; > + __entry->crtc_y = state->crtc_y; > + __entry->width = fb->width; > + __entry->height = fb->height; > + __entry->format = fb->format->format; > + __entry->blend_mode = state->pixel_blend_mode; > + __entry->alpha = alpha; > + __entry->zpos = state->zpos; > + __entry->rotation = rotation; > + ), > + TP_printk("rdma_id=%d src: w=%d h=%d x=%d y=%d crtc: w=%d h=%d x=%d y=%d width=%d height=%d fmt=0x%x blend=%d alpha=%d zpos=%d rot=%d", > + __entry->rdma_id, __entry->src_w, > + __entry->src_h, __entry->src_x, > + __entry->src_y, __entry->crtc_w, > + __entry->crtc_h, __entry->crtc_x, > + __entry->crtc_y, __entry->width, > + __entry->height, __entry->format, > + __entry->blend_mode, __entry->alpha, > + __entry->zpos, __entry->rotation) > +); > + > +DECLARE_EVENT_CLASS(dpu_status_template, > + TP_PROTO(const char *name, int status), > + TP_ARGS(name, status), > + TP_STRUCT__entry( > + __string(name_str, name) > + __field(int, status) > + ), > + TP_fast_assign( > + __assign_str(name_str); > + __entry->status = status; > + ), > + TP_printk("%s: 0x%x", > + __get_str(name_str), __entry->status) > +); > + > +DEFINE_EVENT(dpu_status_template, dpuctrl, > + TP_PROTO(const char *name, int status), > + TP_ARGS(name, status) > +); > +DEFINE_EVENT(dpu_status_template, spacemit_plane_update_hw_channel, > + TP_PROTO(const char *name, int status), > + TP_ARGS(name, status) > +); > +DEFINE_EVENT(dpu_status_template, saturn_irq_enable, > + TP_PROTO(const char *name, int status), > + TP_ARGS(name, status) > +); > +DEFINE_EVENT(dpu_status_template, saturn_enable_vsync, > + TP_PROTO(const char *name, int status), > + TP_ARGS(name, status) > +); > +DEFINE_EVENT(dpu_status_template, dpu_isr_status, > + TP_PROTO(const char *name, int status), > + TP_ARGS(name, status) > +); > + > +DECLARE_EVENT_CLASS(dpu_uint64_t_data_template, > + TP_PROTO(const char *name, u64 data), > + TP_ARGS(name, data), > + TP_STRUCT__entry( > + __string(name_str, name) > + __field(u64, data) > + ), > + TP_fast_assign( > + __assign_str(name_str); > + __entry->data = data; > + ), > + TP_printk("%s: %lld", > + __get_str(name_str), __entry->data) > +); > + > +DEFINE_EVENT(dpu_uint64_t_data_template, u64_data, > + TP_PROTO(const char *name, u64 data), > + TP_ARGS(name, data) > +); > + > +TRACE_EVENT(spacemit_dpu_reg_write, > + TP_PROTO(u32 data, u32 base, const char *name), > + TP_ARGS(data, base, name), > + TP_STRUCT__entry( > + __field(u32, data) > + __field(u32, base) > + __string(name_str, name) > + ), > + TP_fast_assign( > + __entry->data = data; > + __entry->base = base; > + __assign_str(name_str); > + ), > + TP_printk("dpu write 0x%x to addr 0x%x field %s", > + __entry->data, __entry->base, __get_str(name_str)) > +); > + > +TRACE_EVENT(spacemit_plane_disable_hw_channel, > + TP_PROTO(u32 layer_id, u32 rdma_id), > + TP_ARGS(layer_id, rdma_id), > + TP_STRUCT__entry( > + __field(u32, layer_id) > + __field(u32, rdma_id) > + ), > + TP_fast_assign( > + __entry->layer_id = layer_id; > + __entry->rdma_id = rdma_id; > + ), > + TP_printk("layer_id:%d rdma_id:%d", > + __entry->layer_id, __entry->rdma_id) > +); > + > +DECLARE_EVENT_CLASS(dpu_func_template, > + TP_PROTO(u32 dev_id), > + TP_ARGS(dev_id), > + TP_STRUCT__entry( > + __field(u32, dev_id) > + ), > + TP_fast_assign( > + __entry->dev_id = dev_id; > + ), > + TP_printk("dev_id=%d", __entry->dev_id) > +); > +DEFINE_EVENT(dpu_func_template, spacemit_plane_atomic_check, > + TP_PROTO(u32 dev_id), > + TP_ARGS(dev_id) > +); > +DEFINE_EVENT(dpu_func_template, spacemit_plane_atomic_update, > + TP_PROTO(u32 dev_id), > + TP_ARGS(dev_id) > +); > +DEFINE_EVENT(dpu_func_template, spacemit_plane_atomic_duplicate_state, > + TP_PROTO(u32 dev_id), > + TP_ARGS(dev_id) > +); > +DEFINE_EVENT(dpu_func_template, spacemit_plane_atomic_destroy_state, > + TP_PROTO(u32 dev_id), > + TP_ARGS(dev_id) > +); > +DEFINE_EVENT(dpu_func_template, spacemit_plane_init, > + TP_PROTO(u32 dev_id), > + TP_ARGS(dev_id) > +); > +DEFINE_EVENT(dpu_func_template, dpu_enable_clocks, > + TP_PROTO(u32 dev_id), > + TP_ARGS(dev_id) > +); > +DEFINE_EVENT(dpu_func_template, dpu_disable_clocks, > + TP_PROTO(u32 dev_id), > + TP_ARGS(dev_id) > +); > +DEFINE_EVENT(dpu_func_template, dpu_uninit, > + TP_PROTO(u32 dev_id), > + TP_ARGS(dev_id) > +); > +DEFINE_EVENT(dpu_func_template, dpu_isr, > + TP_PROTO(u32 dev_id), > + TP_ARGS(dev_id) > +); > +DEFINE_EVENT(dpu_func_template, dpu_run, > + TP_PROTO(u32 dev_id), > + TP_ARGS(dev_id) > +); > +DEFINE_EVENT(dpu_func_template, spacemit_crtc_atomic_enable, > + TP_PROTO(u32 dev_id), > + TP_ARGS(dev_id) > +); > +DEFINE_EVENT(dpu_func_template, spacemit_crtc_atomic_disable, > + TP_PROTO(u32 dev_id), > + TP_ARGS(dev_id) > +); > +DEFINE_EVENT(dpu_func_template, spacemit_crtc_atomic_check, > + TP_PROTO(u32 dev_id), > + TP_ARGS(dev_id) > +); > +DEFINE_EVENT(dpu_func_template, spacemit_crtc_atomic_begin, > + TP_PROTO(u32 dev_id), > + TP_ARGS(dev_id) > +); > +DEFINE_EVENT(dpu_func_template, spacemit_crtc_atomic_flush, > + TP_PROTO(u32 dev_id), > + TP_ARGS(dev_id) > +); > +DEFINE_EVENT(dpu_func_template, spacemit_crtc_enable_vblank, > + TP_PROTO(u32 dev_id), > + TP_ARGS(dev_id) > +); > +DEFINE_EVENT(dpu_func_template, spacemit_crtc_disable_vblank, > + TP_PROTO(u32 dev_id), > + TP_ARGS(dev_id) > +); > +DEFINE_EVENT(dpu_func_template, spacemit_crtc_run, > + TP_PROTO(u32 dev_id), > + TP_ARGS(dev_id) > +); > +DEFINE_EVENT(dpu_func_template, spacemit_crtc_init, > + TP_PROTO(u32 dev_id), > + TP_ARGS(dev_id) > +); > +DEFINE_EVENT(dpu_func_template, spacemit_crtc_uninit, > + TP_PROTO(u32 dev_id), > + TP_ARGS(dev_id) > +); > +DEFINE_EVENT(dpu_func_template, saturn_ctrl_cfg_ready_timer, > + TP_PROTO(u32 dev_id), > + TP_ARGS(dev_id) > +); > +DECLARE_EVENT_CLASS(dpu_ctrl_template, > + TP_PROTO(int id, int enable), > + TP_ARGS(id, enable), > + TP_STRUCT__entry( > + __field(u32, id) > + __field(u32, enable) > + ), > + TP_fast_assign( > + __entry->id = id; > + __entry->enable = enable; > + ), > + TP_printk("id=%d enable:%d", > + __entry->id, __entry->enable) > +); > +DEFINE_EVENT(dpu_ctrl_template, saturn_ctrl_cfg_ready, > + TP_PROTO(int id, int enable), > + TP_ARGS(id, enable) > +); > + > +DEFINE_EVENT(dpu_ctrl_template, saturn_ctrl_sw_start, > + TP_PROTO(int id, int enable), > + TP_ARGS(id, enable) > +); > + > +TRACE_EVENT(plat_cmdlist_dump_node, > + TP_PROTO(char *dump), > + TP_ARGS(dump), > + TP_STRUCT__entry( > + __string(dump_str, dump) > + ), > + TP_fast_assign( > + __assign_str(dump_str); > + ), > + TP_printk("%s", __get_str(dump_str)) > +); > + > +TRACE_EVENT(cmdlist_dump_node, > + TP_PROTO(char *type, int rdma_id, u8 dev_id, int zpos, u16 nod_len), > + TP_ARGS(type, rdma_id, dev_id, zpos, nod_len), > + TP_STRUCT__entry( > + __string(type_str, type) > + __field(int, rdma_id) > + __field(u8, dev_id) > + __field(int, zpos) > + __field(u16, nod_len) > + ), > + TP_fast_assign( > + __assign_str(type_str); > + __entry->rdma_id = rdma_id; > + __entry->dev_id = dev_id; > + __entry->zpos = zpos; > + __entry->nod_len = nod_len; > + ), > + TP_printk("cmdlist[%s]: rdma_id:%d crtc:%d zpos:%d rows:%d", > + __get_str(type_str), > + __entry->rdma_id, > + __entry->dev_id, > + __entry->zpos, > + __entry->nod_len) > +); > +#endif /* _DPU_TRACE_H_ */ > + > +/* This part must be outside protection */ > +#undef TRACE_INCLUDE_FILE > +#undef TRACE_INCLUDE_PATH > +#define TRACE_INCLUDE_PATH ../../drivers/gpu/drm/spacemit/dpu/ > + > +#define TRACE_INCLUDE_FILE dpu_trace > +#include > diff --git a/drivers/gpu/drm/spacemit/spacemit_cmdlist.c b/drivers/gpu/drm/spacemit/spacemit_cmdlist.c > new file mode 100644 > index 0000000000000..f4f14eaa12a0f > --- /dev/null > +++ b/drivers/gpu/drm/spacemit/spacemit_cmdlist.c > @@ -0,0 +1,304 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (C) 2025-2026 SpacemiT Co., Ltd. > + * > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include "spacemit_cmdlist.h" > +#include "spacemit_crtc.h" > +#include "spacemit_dpu_reg.h" > +#include "spacemit_drm.h" > +#include "dpu/dpu_saturn.h" > +#include "dpu/dpu_trace.h" > + > +struct spacemit_plane_state *cl_to_spacemit_pstate(const struct cmdlist *cl) > +{ > + return container_of(cl, struct spacemit_plane_state, cl); > +} > + > +struct spacemit_crtc_state *cl_to_spacemit_cstate(const struct cmdlist *cl) > +{ > + return container_of(cl, struct spacemit_crtc_state, cl); > +} > + > +struct cmdlist *plane_to_cl(struct drm_plane *plane) > +{ > + struct spacemit_plane_state *spacemit_pstate = > + to_spacemit_plane_state(plane->state); > + > + return &spacemit_pstate->cl; > +} > + > +struct cmdlist *crtc_to_cl(struct drm_crtc *crtc) > +{ > + struct spacemit_crtc_state *spacemit_cstate = > + to_spacemit_crtc_state(crtc->state); > + > + return &spacemit_cstate->cl; > +} > + > +static void cmdlist_dump_node(struct cmdlist *cl) > +{ > + struct spacemit_drm_private *priv; > + struct spacemit_hw_device *hwdev; > + struct spacemit_crtc *a_crtc; > + char *type; > + int zpos = -1, rdma_id = -1; > + > + if (!cl) > + return; > + > + if (cl->type == CMDLIST_PLANE) { > + struct spacemit_plane_state *spacemit_pstate = > + cl_to_spacemit_pstate(cl); > + > + a_crtc = to_spacemit_crtc(spacemit_pstate->state.crtc); > + rdma_id = spacemit_pstate->rdma_id; > + zpos = (int)(spacemit_pstate->state.zpos); > + type = "RDMA"; > + } else if (cl->type == CMDLIST_CRTC) { > + struct spacemit_crtc_state *spacemit_cstate = > + cl_to_spacemit_cstate(cl); > + > + a_crtc = to_spacemit_crtc(spacemit_cstate->base.crtc); > + type = "CRTC"; > + } else { > + return; > + } > + > + trace_cmdlist_dump_node(type, rdma_id, a_crtc->dev_id, zpos, > + cl->nod_len); > + > + priv = a_crtc->crtc.dev->dev_private; > + hwdev = priv->hwdev; > + hwdev->cmdlist_dump_node(cl); > +} > + > +void cmdlist_regs_packing(struct cmdlist *cl, enum cmdlist_mode_type mod, > + struct cmdlist_regs *cl_regs) > +{ > + struct spacemit_crtc *a_crtc; > + struct spacemit_drm_private *priv; > + struct spacemit_hw_device *hwdev; > + u32 *reg_base; > + int i; > + u32 index; > + > + if (!cl_regs) > + return; > + > + if (cl->type == CMDLIST_PLANE) { > + struct spacemit_plane_state *spacemit_pstate = > + cl_to_spacemit_pstate(cl); > + > + a_crtc = to_spacemit_crtc(spacemit_pstate->state.crtc); > + > + drm_dbg(a_crtc->crtc.dev, "rch_id = %d, ch_y = %u\n", > + spacemit_pstate->rdma_id, > + spacemit_pstate->state.crtc_y); > + } else if (cl->type == CMDLIST_CRTC) { > + struct spacemit_crtc_state *spacemit_cstate = > + cl_to_spacemit_cstate(cl); > + > + a_crtc = to_spacemit_crtc(spacemit_cstate->base.crtc); > + } else { > + WARN_ONCE(1, "unsupported cmdlist type %d\n", cl->type); > + return; > + } > + > + priv = a_crtc->crtc.dev->dev_private; > + hwdev = priv->hwdev; > + reg_base = cl_regs->module; > + > + cl->mode_mask |= mod; > + > + /* > + * Without the atomic_check() buffer the staged register writes vanish. > + */ > + if (drm_WARN_ON(a_crtc->crtc.dev, !cl->va)) > + return; > + > + for (i = 0; i < cl_regs->size;) { > + u32 value[CMDLIST_ROW_REGS] = {0x0}; > + u32 offset, strobe = 0; > + u8 regs_in_row = 0; > + > + if (cl_regs->flags[i]) { > + offset = cl_regs->base + i * sizeof(u32); > + for (u8 j = 0; j < CMDLIST_ROW_REGS; j++) { > + index = i + j; > + if (likely(index < cl_regs->size)) { > + if (cl_regs->flags[index]) { > + value[j] = reg_base[index]; > + regs_in_row++; > + strobe |= CMDLIST_REG_STROBE(j); > + } > + } else { > + break; > + } > + } > + hwdev->cmdlist_fill_data_row(cl, strobe, offset, value); > + /* > + * the row covers the whole window; a shorter stride > + * would revisit covered words as duplicate rows > + */ > + i += CMDLIST_ROW_REGS; > + cl->nod_len++; > + } else { > + i++; > + } > + } > + > + drm_dbg(a_crtc->crtc.dev, "row_num = %d\n", cl->nod_len); > +} > + > +void cmdlist_sort_by_group(struct drm_crtc *crtc) > +{ > + struct cmdlist *first_cl; > + struct cmdlist *last_cl; > + struct cmdlist *p; > + struct cmdlist *prev; > + struct drm_plane *plane; > + struct spacemit_crtc_rdma *rdmas = > + to_spacemit_crtc_state(crtc->state)->rdmas; > + struct spacemit_drm_private *priv = crtc->dev->dev_private; > + > + drm_atomic_crtc_for_each_plane(plane, crtc) { > + struct spacemit_plane_state *spacemit_pstate = > + to_spacemit_plane_state(plane->state); > + u32 rdma_id = spacemit_pstate->rdma_id; > + > + first_cl = &spacemit_pstate->cl; > + if (!first_cl->va) > + continue; > + > + last_cl = first_cl; > + last_cl->next = NULL; > + > + rdmas[rdma_id].in_use = true; > + if (priv->cmdlist_groups[rdma_id]) { > + p = priv->cmdlist_groups[rdma_id]; > + prev = NULL; > + while (p) { > + if (cl_to_spacemit_pstate(p)->state.crtc_y < > + spacemit_pstate->state.crtc_y) { > + prev = p; > + p = p->next; > + } else { > + break; > + } > + } > + if (!prev) { > + priv->cmdlist_groups[rdma_id] = first_cl; > + last_cl->next = p; > + } else { > + prev->next = first_cl; > + last_cl->next = p; > + } > + } else { > + priv->cmdlist_groups[rdma_id] = first_cl; > + } > + } > +} > + > +void cmdlist_atomic_commit(struct drm_crtc *crtc, > + struct drm_crtc_state *old_state) > +{ > + int i; > + struct cmdlist *cur_cl, *first_cl; > + struct spacemit_crtc *a_crtc = NULL; > + u32 chy, addrl, addrh; > + struct spacemit_drm_private *priv = crtc->dev->dev_private; > + struct spacemit_hw_device *hwdev = priv->hwdev; > + struct spacemit_crtc_rdma *cur_rdmas = > + to_spacemit_crtc_state(crtc->state)->rdmas; > + struct spacemit_crtc_rdma *old_rdmas = > + to_spacemit_crtc_state(old_state)->rdmas; > + > + a_crtc = to_spacemit_crtc(crtc); > + > + for (i = 0; i < hwdev->rdma_nums; i++) { > + if (old_rdmas[i].in_use) > + hwdev->enable_cmdlist(a_crtc, hwdev, i, false); > + > + if (cur_rdmas[i].in_use) { > + drm_dbg(crtc->dev, "cmdlist group = %d\n", i); > + cur_cl = priv->cmdlist_groups[i]; > + first_cl = cur_cl; > + while (cur_cl) { > + hwdev->cmdlist_fill_conf_row(cur_cl, hwdev, > + CMDLIST_CMP_INVALID); > + cmdlist_dump_node(cur_cl); > + cur_cl = cur_cl->next; > + } > + chy = cl_to_spacemit_pstate(first_cl)->state.crtc_y; > + addrl = (lower_32_bits(priv->cmdlist_groups[i]->pa) & > + CMDLIST_ADDRL_ALIGN_MASK) >> CMDLIST_ADDRL_ALIGN_BITS; > + > + addrh = upper_32_bits(priv->cmdlist_groups[i]->pa); > + hwdev->cfg_cmdlist(hwdev, i, chy, addrl, addrh); > + hwdev->enable_cmdlist(a_crtc, hwdev, i, true); > + priv->cmdlist_groups[i] = NULL; > + } > + } > +} > + > +void crtc_cmdlist_sort_by_group(struct spacemit_crtc *a_crtc) > +{ > + struct cmdlist *first_cl; > + struct cmdlist *last_cl; > + struct drm_crtc *crtc = &a_crtc->crtc; > + struct spacemit_drm_private *priv = crtc->dev->dev_private; > + struct spacemit_hw_device *hwdev = priv->hwdev; > + struct drm_crtc_state *crtc_state = a_crtc->crtc.state; > + struct spacemit_crtc_state *spacemit_crtc_state = > + to_spacemit_crtc_state(crtc_state); > + u8 crtc_id = drm_crtc_index(crtc); > + > + first_cl = &spacemit_crtc_state->cl; > + last_cl = first_cl; > + last_cl->next = NULL; > + priv->cmdlist_groups[hwdev->rdma_nums + crtc_id] = first_cl; > +} > + > +void crtc_cmdlist_atomic_commit(struct spacemit_crtc *a_crtc) > +{ > + struct cmdlist *cur_cl; > + struct drm_crtc *crtc = &a_crtc->crtc; > + struct spacemit_drm_private *priv = crtc->dev->dev_private; > + struct spacemit_hw_device *hwdev = priv->hwdev; > + u8 crtc_id = drm_crtc_index(crtc); > + u8 dev_id = a_crtc->dev_id; > + > + drm_dbg(crtc->dev, "cmdlist group = %d\n", > + hwdev->rdma_nums + crtc_id); > + cur_cl = priv->cmdlist_groups[hwdev->rdma_nums + crtc_id]; > + while (cur_cl) { > + hwdev->cmdlist_fill_conf_row(cur_cl, hwdev, dev_id); > + cmdlist_dump_node(cur_cl); > + cur_cl = cur_cl->next; > + } > + hwdev->crtc_cmdlist(hwdev, priv, crtc_id, dev_id); > +} > + > +/* Called from atomic_check(), where -ENOMEM is still an answer. */ > +int spacemit_cmdlist_alloc(struct device *dev, struct cmdlist *cl) > +{ > + if (cl->va) > + return 0; > + > + cl->size = PER_CMDLIST_SIZE; > + cl->va = dma_alloc_coherent(dev, cl->size, &cl->pa, > + GFP_KERNEL | __GFP_ZERO); > + if (!cl->va) > + return -ENOMEM; > + > + return 0; > +} > diff --git a/drivers/gpu/drm/spacemit/spacemit_cmdlist.h b/drivers/gpu/drm/spacemit/spacemit_cmdlist.h > new file mode 100644 > index 0000000000000..d5acdbeb3b0e7 > --- /dev/null > +++ b/drivers/gpu/drm/spacemit/spacemit_cmdlist.h > @@ -0,0 +1,146 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright (C) 2025-2026 SpacemiT Co., Ltd. > + * > + */ > + > +#ifndef _SATURN_FW_CMDLIST_H_ > +#define _SATURN_FW_CMDLIST_H_ > + > +#include > +#include > +#include > +#include > + > +struct spacemit_crtc; > +struct spacemit_plane_state; > + > +#define PER_CMDLIST_SIZE 4096 > +#define CMDLIST_ROW_REGS (3) > +#define CMDLIST_CMP_INVALID (0xff) > +/* poison for the per-cmdlist compose sentinels, never written to hw */ > +#define CMDLIST_SENTINEL_POISON 0xDEADBEEF > + > +/** > + * enum cmdlist_type - what surface owns a cmdlist instance > + * @CMDLIST_PLANE: Per-plane RDMA register batches. > + * @CMDLIST_CRTC: Compose-side batches submitted on every flush. > + */ > +enum cmdlist_type { > + CMDLIST_PLANE = 1, > + CMDLIST_CRTC, > +}; > + > +/** > + * struct cmdlist - A DMA-backed batch of register writes replayed at CFG_RDY > + * @nod_len: Number of register-write rows currently filled. > + * @size: Capacity of the DMA buffer in bytes. > + * @mode_mask: cmdlist_mode_type sources; gates which rows are pulled. > + * @va: Kernel virtual address of the DMA buffer. > + * @pa: DMA address programmed into the cmdlist base register. > + * @next: Cmdlists in submission order; the CRTC-level one comes last. > + * @type: Originating surface; see &enum cmdlist_type. > + * @rch_start_cmps_y: Compositor-Y start sentinel. > + * @cmdlist_ch_y_other: Companion sentinel to @rch_start_cmps_y. > + */ > +struct cmdlist { > + u16 nod_len; > + u32 size; > + u32 mode_mask; > + void *va; > + dma_addr_t pa; > + struct cmdlist *next; > + u8 type; > + u32 rch_start_cmps_y; > + u32 cmdlist_ch_y_other; > +}; > + > +enum cmdlist_mode_type { > + CMDLIST_MOD_RDMA = BIT(0), > + CMDLIST_MOD_COMP = BIT(3), > + CMDLIST_MOD_DMMU = BIT(6), > +}; > + > +#define CMDLIST_REG_STROBE(index) (0xf << ((index) * 4)) > + > +#define CMDLIST_ADDRL_ALIGN_BITS (4) /* From cmdlist_reg_0[] in CMDLIST_REG */ > +#define CMDLIST_ADDRL_ALIGN_MASK \ > + ((u32)(~(BIT(CMDLIST_ADDRL_ALIGN_BITS) - 1))) > +/* NULL on failure is safe: every consumer falls back to direct MMIO. */ > +#define alloc_cmdlist_regs(module_name) \ > +({ \ > + struct cmdlist_regs *cl = kzalloc(sizeof(*cl), GFP_KERNEL); \ > + if (cl) { \ > + cl->size = module_name##__NWORDS; \ > + cl->module = kzalloc(4 * module_name##__NWORDS, GFP_KERNEL); \ > + cl->flags = kzalloc(module_name##__NWORDS, GFP_KERNEL); \ > + if (!cl->module || !cl->flags) { \ > + kfree(cl->module); \ > + kfree(cl->flags); \ > + kfree(cl); \ > + cl = NULL; \ > + } \ > + } \ > + cl; \ > +}) > + > +#define free_cmdlist_regs(cl_p) \ > +do { \ > + struct cmdlist_regs *cl = (cl_p); \ > + if (cl) { \ > + kfree(cl->module); \ > + kfree(cl->flags); \ > + kfree(cl); \ > + } \ > +} while (0) > + > +/* > + * First touch seeds the word from a live MMIO read: only register blocks that > + * read back what was written may be routed through cmdlist. > + */ > +#define cmdlist_write_reg(hwdev, module_name, module_base, field, data, cl_regs) \ > +do { \ > + struct cmdlist_regs *cl_p = (cl_regs); \ > + u32 *__words = cl_p->module; \ > + const unsigned int __w = dpu_field_word(module_name, field); \ > + if (cl_p->flags[__w] == 0) { \ > + __words[__w] = readl((hwdev)->base + (module_base) + 4 * __w); \ > + cl_p->base = (module_base); \ > + cl_p->flags[__w] = 1; \ > + } \ > + __words[__w] &= ~dpu_field_mask(module_name, field); \ > + __words[__w] |= FIELD_PREP(dpu_field_mask(module_name, field), \ > + (u32)(data)); \ > +} while (0) > + > +/* Raw whole-word variant (the value32[] call sites); no seeding needed. */ > +#define cmdlist_write_word(module_base, word, data, cl_regs) \ > +do { \ > + struct cmdlist_regs *cl_p = (cl_regs); \ > + u32 *__words = cl_p->module; \ > + cl_p->base = (module_base); \ > + cl_p->flags[(word)] = 1; \ > + __words[(word)] = (u32)(data); \ > +} while (0) > + > +struct cmdlist_regs { > + u32 base; > + u16 size; > + u32 *module; > + u8 *flags; > +}; > + > +void cmdlist_regs_packing(struct cmdlist *cl, enum cmdlist_mode_type mod, > + struct cmdlist_regs *cl_regs); > +void cmdlist_sort_by_group(struct drm_crtc *crtc); > +void cmdlist_atomic_commit(struct drm_crtc *crtc, > + struct drm_crtc_state *old_state); > +struct spacemit_plane_state *cl_to_spacemit_pstate(const struct cmdlist *cl); > +void crtc_cmdlist_sort_by_group(struct spacemit_crtc *a_crtc); > +void crtc_cmdlist_atomic_commit(struct spacemit_crtc *a_crtc); > +struct spacemit_crtc_state *cl_to_spacemit_cstate(const struct cmdlist *cl); > +int spacemit_cmdlist_alloc(struct device *dev, struct cmdlist *cl); > +struct cmdlist *plane_to_cl(struct drm_plane *plane); > +struct cmdlist *crtc_to_cl(struct drm_crtc *crtc); > + > +#endif /* _SATURN_FW_CMDLIST_H_ */ > diff --git a/drivers/gpu/drm/spacemit/spacemit_crtc.h b/drivers/gpu/drm/spacemit/spacemit_crtc.h > new file mode 100644 > index 0000000000000..7c03102414d00 > --- /dev/null > +++ b/drivers/gpu/drm/spacemit/spacemit_crtc.h > @@ -0,0 +1,246 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright (C) 2025-2026 SpacemiT Co., Ltd. > + * > + */ > + > +#ifndef _SPACEMIT_CRTC_H_ > +#define _SPACEMIT_CRTC_H_ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include