File Index
Files and directories
Sign in
FILE

dc-fu.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/imx/dc/dc-fu.c C
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * Copyright 2024 NXP
  4 */
  5
  6#include <linux/bitfield.h>
  7#include <linux/bitops.h>
  8#include <linux/bits.h>
  9#include <linux/math.h>
 10
 11#include "dc-fu.h"
 12#include "dc-pe.h"
 13
 14/* STATICCONTROL */
 15#define SHDLDREQSTICKY_MASK		GENMASK(31, 24)
 16#define SHDLDREQSTICKY(x)		FIELD_PREP(SHDLDREQSTICKY_MASK, (x))
 17#define BASEADDRESSAUTOUPDATE_MASK	GENMASK(23, 16)
 18#define BASEADDRESSAUTOUPDATE(x)	FIELD_PREP(BASEADDRESSAUTOUPDATE_MASK, (x))
 19
 20/* BURSTBUFFERMANAGEMENT */
 21#define LINEMODE_MASK			BIT(31)
 22#define SETBURSTLENGTH_MASK		GENMASK(12, 8)
 23#define SETBURSTLENGTH(x)		FIELD_PREP(SETBURSTLENGTH_MASK, (x))
 24#define SETNUMBUFFERS_MASK		GENMASK(7, 0)
 25#define SETNUMBUFFERS(x)		FIELD_PREP(SETNUMBUFFERS_MASK, (x))
 26
 27/* SOURCEBUFFERATTRIBUTES */
 28#define BITSPERPIXEL_MASK		GENMASK(21, 16)
 29#define BITSPERPIXEL(x)			FIELD_PREP(BITSPERPIXEL_MASK, (x))
 30#define STRIDE_MASK			GENMASK(15, 0)
 31#define STRIDE(x)			FIELD_PREP(STRIDE_MASK, (x) - 1)
 32
 33/* SOURCEBUFFERDIMENSION */
 34#define LINECOUNT(x)			FIELD_PREP(GENMASK(29, 16), (x))
 35#define LINEWIDTH(x)			FIELD_PREP(GENMASK(13, 0), (x))
 36
 37/* LAYEROFFSET */
 38#define LAYERYOFFSET(x)			FIELD_PREP(GENMASK(30, 16), (x))
 39#define LAYERXOFFSET(x)			FIELD_PREP(GENMASK(14, 0), (x))
 40
 41/* CLIPWINDOWOFFSET */
 42#define CLIPWINDOWYOFFSET(x)		FIELD_PREP(GENMASK(30, 16), (x))
 43#define CLIPWINDOWXOFFSET(x)		FIELD_PREP(GENMASK(14, 0), (x))
 44
 45/* CLIPWINDOWDIMENSIONS */
 46#define CLIPWINDOWHEIGHT(x)		FIELD_PREP(GENMASK(29, 16), (x) - 1)
 47#define CLIPWINDOWWIDTH(x)		FIELD_PREP(GENMASK(13, 0), (x) - 1)
 48
 49enum dc_linemode {
 50	/*
 51	 * Mandatory setting for operation in the Display Controller.
 52	 * Works also for Blit Engine with marginal performance impact.
 53	 */
 54	LINEMODE_DISPLAY = 0,
 55};
 56
 57struct dc_fu_pixel_format {
 58	u32 pixel_format;
 59	u32 bits;
 60	u32 shifts;
 61};
 62
 63static const struct dc_fu_pixel_format pixel_formats[] = {
 64	{
 65		DRM_FORMAT_XRGB8888,
 66		R_BITS(8)   | G_BITS(8)   | B_BITS(8)   | A_BITS(0),
 67		R_SHIFT(16) | G_SHIFT(8)  | B_SHIFT(0)  | A_SHIFT(0),
 68	},
 69};
 70
 71void dc_fu_get_pixel_format_bits(struct dc_fu *fu, u32 format, u32 *bits)
 72{
 73	int i;
 74
 75	for (i = 0; i < ARRAY_SIZE(pixel_formats); i++) {
 76		if (pixel_formats[i].pixel_format == format) {
 77			*bits = pixel_formats[i].bits;
 78			return;
 79		}
 80	}
 81}
 82
 83void
 84dc_fu_get_pixel_format_shifts(struct dc_fu *fu, u32 format, u32 *shifts)
 85{
 86	int i;
 87
 88	for (i = 0; i < ARRAY_SIZE(pixel_formats); i++) {
 89		if (pixel_formats[i].pixel_format == format) {
 90			*shifts = pixel_formats[i].shifts;
 91			return;
 92		}
 93	}
 94}
 95
 96static inline void dc_fu_enable_shden(struct dc_fu *fu)
 97{
 98	regmap_write_bits(fu->reg_cfg, STATICCONTROL, SHDEN, SHDEN);
 99}
100
101static inline void dc_fu_baddr_autoupdate(struct dc_fu *fu, u8 layer_mask)
102{
103	regmap_write_bits(fu->reg_cfg, STATICCONTROL,
104			  BASEADDRESSAUTOUPDATE_MASK,
105			  BASEADDRESSAUTOUPDATE(layer_mask));
106}
107
108void dc_fu_shdldreq_sticky(struct dc_fu *fu, u8 layer_mask)
109{
110	regmap_write_bits(fu->reg_cfg, STATICCONTROL, SHDLDREQSTICKY_MASK,
111			  SHDLDREQSTICKY(layer_mask));
112}
113
114static inline void dc_fu_set_linemode(struct dc_fu *fu, enum dc_linemode mode)
115{
116	regmap_write_bits(fu->reg_cfg, BURSTBUFFERMANAGEMENT, LINEMODE_MASK,
117			  mode);
118}
119
120static inline void dc_fu_set_numbuffers(struct dc_fu *fu, unsigned int num)
121{
122	regmap_write_bits(fu->reg_cfg, BURSTBUFFERMANAGEMENT,
123			  SETNUMBUFFERS_MASK, SETNUMBUFFERS(num));
124}
125
126static void dc_fu_set_burstlength(struct dc_fu *fu, dma_addr_t baddr)
127{
128	unsigned int burst_size, burst_length;
129
130	burst_size = 1 << __ffs(baddr);
131	burst_size = round_up(burst_size, 8);
132	burst_size = min(burst_size, 128U);
133	burst_length = burst_size / 8;
134
135	regmap_write_bits(fu->reg_cfg, BURSTBUFFERMANAGEMENT,
136			  SETBURSTLENGTH_MASK, SETBURSTLENGTH(burst_length));
137}
138
139static void dc_fu_set_baseaddress(struct dc_fu *fu, enum dc_fu_frac frac,
140				  dma_addr_t baddr)
141{
142	regmap_write(fu->reg_cfg, fu->reg_baseaddr[frac], baddr);
143}
144
145void dc_fu_set_src_bpp(struct dc_fu *fu, enum dc_fu_frac frac, unsigned int bpp)
146{
147	regmap_write_bits(fu->reg_cfg, fu->reg_sourcebufferattributes[frac],
148			  BITSPERPIXEL_MASK, BITSPERPIXEL(bpp));
149}
150
151static void dc_fu_set_src_stride(struct dc_fu *fu, enum dc_fu_frac frac,
152				 unsigned int stride)
153{
154	regmap_write_bits(fu->reg_cfg, fu->reg_sourcebufferattributes[frac],
155			  STRIDE_MASK, STRIDE(stride));
156}
157
158static void dc_fu_set_src_buf_dimensions(struct dc_fu *fu, enum dc_fu_frac frac,
159					 int w, int h)
160{
161	regmap_write(fu->reg_cfg, fu->reg_sourcebufferdimension[frac],
162		     LINEWIDTH(w) | LINECOUNT(h));
163}
164
165static inline void dc_fu_layeroffset(struct dc_fu *fu, enum dc_fu_frac frac,
166				     unsigned int x, unsigned int y)
167{
168	regmap_write(fu->reg_cfg, fu->reg_layeroffset[frac],
169		     LAYERXOFFSET(x) | LAYERYOFFSET(y));
170}
171
172static inline void dc_fu_clipoffset(struct dc_fu *fu, enum dc_fu_frac frac,
173				    unsigned int x, unsigned int y)
174{
175	regmap_write(fu->reg_cfg, fu->reg_clipwindowoffset[frac],
176		     CLIPWINDOWXOFFSET(x) | CLIPWINDOWYOFFSET(y));
177}
178
179static inline void dc_fu_clipdimensions(struct dc_fu *fu, enum dc_fu_frac frac,
180					unsigned int w, unsigned int h)
181{
182	regmap_write(fu->reg_cfg, fu->reg_clipwindowdimensions[frac],
183		     CLIPWINDOWWIDTH(w) | CLIPWINDOWHEIGHT(h));
184}
185
186static inline void
187dc_fu_set_pixel_blend_mode(struct dc_fu *fu, enum dc_fu_frac frac)
188{
189	regmap_write(fu->reg_cfg, fu->reg_layerproperty[frac], 0);
190	regmap_write(fu->reg_cfg, fu->reg_constantcolor[frac], 0);
191}
192
193static void dc_fu_enable_src_buf(struct dc_fu *fu, enum dc_fu_frac frac)
194{
195	regmap_write_bits(fu->reg_cfg, fu->reg_layerproperty[frac],
196			  SOURCEBUFFERENABLE, SOURCEBUFFERENABLE);
197}
198
199static void dc_fu_disable_src_buf(struct dc_fu *fu, enum dc_fu_frac frac)
200{
201	regmap_write_bits(fu->reg_cfg, fu->reg_layerproperty[frac],
202			  SOURCEBUFFERENABLE, 0);
203
204	if (fu->lb) {
205		dc_lb_pec_clken(fu->lb, CLKEN_DISABLE);
206		dc_lb_mode(fu->lb, LB_NEUTRAL);
207	}
208}
209
210static void dc_fu_set_layerblend(struct dc_fu *fu, struct dc_lb *lb)
211{
212	fu->lb = lb;
213}
214
215static enum dc_link_id dc_fu_get_link_id(struct dc_fu *fu)
216{
217	return fu->link_id;
218}
219
220static const char *dc_fu_get_name(struct dc_fu *fu)
221{
222	return fu->name;
223}
224
225const struct dc_fu_ops dc_fu_common_ops = {
226	.set_burstlength	= dc_fu_set_burstlength,
227	.set_baseaddress	= dc_fu_set_baseaddress,
228	.set_src_stride		= dc_fu_set_src_stride,
229	.set_src_buf_dimensions = dc_fu_set_src_buf_dimensions,
230	.enable_src_buf		= dc_fu_enable_src_buf,
231	.disable_src_buf	= dc_fu_disable_src_buf,
232	.set_layerblend		= dc_fu_set_layerblend,
233	.get_link_id		= dc_fu_get_link_id,
234	.get_name		= dc_fu_get_name,
235};
236
237const struct dc_fu_ops *dc_fu_get_ops(struct dc_fu *fu)
238{
239	return &fu->ops;
240}
241
242void dc_fu_common_hw_init(struct dc_fu *fu)
243{
244	enum dc_fu_frac i;
245
246	dc_fu_baddr_autoupdate(fu, 0x0);
247	dc_fu_enable_shden(fu);
248	dc_fu_set_linemode(fu, LINEMODE_DISPLAY);
249	dc_fu_set_numbuffers(fu, 16);
250
251	for (i = DC_FETCHUNIT_FRAC0; i < DC_FETCHUNIT_FRAC_NUM; i++) {
252		dc_fu_layeroffset(fu, i, 0, 0);
253		dc_fu_clipoffset(fu, i, 0, 0);
254		dc_fu_clipdimensions(fu, i, 1, 1);
255		dc_fu_disable_src_buf(fu, i);
256		dc_fu_set_pixel_blend_mode(fu, i);
257	}
258}
~/ Read-only file preview.