1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * Copyright (C) 2023 Loongson Technology Corporation Limited
4 */
5
6#ifndef __LSDC_DRV_H__
7#define __LSDC_DRV_H__
8
9#include <linux/pci.h>
10
11#include <drm/drm_connector.h>
12#include <drm/drm_crtc.h>
13#include <drm/drm_device.h>
14#include <drm/drm_encoder.h>
15#include <drm/drm_file.h>
16#include <drm/drm_plane.h>
17#include <drm/ttm/ttm_device.h>
18
19#include "lsdc_i2c.h"
20#include "lsdc_irq.h"
21#include "lsdc_gfxpll.h"
22#include "lsdc_output.h"
23#include "lsdc_pixpll.h"
24#include "lsdc_regs.h"
25
26/* Currently, all Loongson display controllers have two display pipes. */
27#define LSDC_NUM_CRTC           2
28
29/*
30 * LS7A1000/LS7A2000 chipsets function as the south & north bridges of the
31 * Loongson 3 series processors, they are equipped with on-board video RAM
32 * typically. While Loongson LS2K series are low cost SoCs which share the
33 * system RAM as video RAM, they don't has a dedicated VRAM.
34 *
35 * There is only a 1:1 mapping of crtcs, encoders and connectors for the DC
36 *
37 * display pipe 0 = crtc0 + dvo0 + encoder0 + connector0 + cursor0 + primary0
38 * display pipe 1 = crtc1 + dvo1 + encoder1 + connectro1 + cursor1 + primary1
39 */
40
41enum loongson_chip_id {
42	CHIP_LS7A1000 = 0,
43	CHIP_LS7A2000 = 1,
44	CHIP_LS_LAST,
45};
46
47const struct lsdc_desc *
48lsdc_device_probe(struct pci_dev *pdev, enum loongson_chip_id chip);
49
50struct lsdc_kms_funcs;
51
52/* DC specific */
53
54struct lsdc_desc {
55	u32 num_of_crtc;
56	u32 max_pixel_clk;
57	u32 max_width;
58	u32 max_height;
59	u32 num_of_hw_cursor;
60	u32 hw_cursor_w;
61	u32 hw_cursor_h;
62	u32 pitch_align;         /* CRTC DMA alignment constraint */
63	bool has_vblank_counter; /* 32 bit hw vsync counter */
64
65	/* device dependent ops, dc side */
66	const struct lsdc_kms_funcs *funcs;
67};
68
69/* GFX related resources wrangler */
70
71struct loongson_gfx_desc {
72	struct lsdc_desc dc;
73
74	u32 conf_reg_base;
75
76	/* GFXPLL shared by the DC, GMC and GPU */
77	struct {
78		u32 reg_offset;
79		u32 reg_size;
80	} gfxpll;
81
82	/* Pixel PLL, per display pipe */
83	struct {
84		u32 reg_offset;
85		u32 reg_size;
86	} pixpll[LSDC_NUM_CRTC];
87
88	enum loongson_chip_id chip_id;
89	char model[64];
90};
91
92static inline const struct loongson_gfx_desc *
93to_loongson_gfx(const struct lsdc_desc *dcp)
94{
95	return container_of_const(dcp, struct loongson_gfx_desc, dc);
96};
97
98struct lsdc_reg32 {
99	char *name;
100	u32 offset;
101};
102
103/* crtc hardware related ops */
104
105struct lsdc_crtc;
106
107struct lsdc_crtc_hw_ops {
108	void (*enable)(struct lsdc_crtc *lcrtc);
109	void (*disable)(struct lsdc_crtc *lcrtc);
110	void (*enable_vblank)(struct lsdc_crtc *lcrtc);
111	void (*disable_vblank)(struct lsdc_crtc *lcrtc);
112	void (*flip)(struct lsdc_crtc *lcrtc);
113	void (*clone)(struct lsdc_crtc *lcrtc);
114	void (*get_scan_pos)(struct lsdc_crtc *lcrtc, int *hpos, int *vpos);
115	void (*set_mode)(struct lsdc_crtc *lcrtc, const struct drm_display_mode *mode);
116	void (*soft_reset)(struct lsdc_crtc *lcrtc);
117	void (*reset)(struct lsdc_crtc *lcrtc);
118
119	u32  (*get_vblank_counter)(struct lsdc_crtc *lcrtc);
120	void (*set_dma_step)(struct lsdc_crtc *lcrtc, enum lsdc_dma_steps step);
121};
122
123struct lsdc_crtc {
124	struct drm_crtc base;
125	struct lsdc_pixpll pixpll;
126	struct lsdc_device *ldev;
127	const struct lsdc_crtc_hw_ops *hw_ops;
128	const struct lsdc_reg32 *preg;
129	unsigned int nreg;
130	struct drm_info_list *p_info_list;
131	unsigned int n_info_list;
132	bool has_vblank;
133};
134
135/* primary plane hardware related ops */
136
137struct lsdc_primary;
138
139struct lsdc_primary_plane_ops {
140	void (*update_fb_addr)(struct lsdc_primary *plane, u64 addr);
141	void (*update_fb_stride)(struct lsdc_primary *plane, u32 stride);
142	void (*update_fb_format)(struct lsdc_primary *plane,
143				 const struct drm_format_info *format);
144};
145
146struct lsdc_primary {
147	struct drm_plane base;
148	const struct lsdc_primary_plane_ops *ops;
149	struct lsdc_device *ldev;
150};
151
152/* cursor plane hardware related ops */
153
154struct lsdc_cursor;
155
156struct lsdc_cursor_plane_ops {
157	void (*update_bo_addr)(struct lsdc_cursor *plane, u64 addr);
158	void (*update_cfg)(struct lsdc_cursor *plane,
159			   enum lsdc_cursor_size cursor_size,
160			   enum lsdc_cursor_format);
161	void (*update_position)(struct lsdc_cursor *plane, int x, int y);
162};
163
164struct lsdc_cursor {
165	struct drm_plane base;
166	const struct lsdc_cursor_plane_ops *ops;
167	struct lsdc_device *ldev;
168};
169
170struct lsdc_output {
171	struct drm_encoder encoder;
172	struct drm_connector connector;
173};
174
175static inline struct lsdc_output *
176connector_to_lsdc_output(struct drm_connector *connector)
177{
178	return container_of(connector, struct lsdc_output, connector);
179}
180
181static inline struct lsdc_output *
182encoder_to_lsdc_output(struct drm_encoder *encoder)
183{
184	return container_of(encoder, struct lsdc_output, encoder);
185}
186
187struct lsdc_display_pipe {
188	struct lsdc_crtc crtc;
189	struct lsdc_primary primary;
190	struct lsdc_cursor cursor;
191	struct lsdc_output output;
192	struct lsdc_i2c *li2c;
193	unsigned int index;
194};
195
196static inline struct lsdc_display_pipe *
197output_to_display_pipe(struct lsdc_output *output)
198{
199	return container_of(output, struct lsdc_display_pipe, output);
200}
201
202struct lsdc_kms_funcs {
203	irqreturn_t (*irq_handler)(int irq, void *arg);
204
205	int (*create_i2c)(struct drm_device *ddev,
206			  struct lsdc_display_pipe *dispipe,
207			  unsigned int index);
208
209	int (*output_init)(struct drm_device *ddev,
210			   struct lsdc_display_pipe *dispipe,
211			   struct i2c_adapter *ddc,
212			   unsigned int index);
213
214	int (*cursor_plane_init)(struct drm_device *ddev,
215				 struct drm_plane *plane,
216				 unsigned int index);
217
218	int (*primary_plane_init)(struct drm_device *ddev,
219				  struct drm_plane *plane,
220				  unsigned int index);
221
222	int (*crtc_init)(struct drm_device *ddev,
223			 struct drm_crtc *crtc,
224			 struct drm_plane *primary,
225			 struct drm_plane *cursor,
226			 unsigned int index,
227			 bool has_vblank);
228};
229
230static inline struct lsdc_crtc *
231to_lsdc_crtc(struct drm_crtc *crtc)
232{
233	return container_of(crtc, struct lsdc_crtc, base);
234}
235
236static inline struct lsdc_display_pipe *
237crtc_to_display_pipe(struct drm_crtc *crtc)
238{
239	return container_of(crtc, struct lsdc_display_pipe, crtc.base);
240}
241
242static inline struct lsdc_primary *
243to_lsdc_primary(struct drm_plane *plane)
244{
245	return container_of(plane, struct lsdc_primary, base);
246}
247
248static inline struct lsdc_cursor *
249to_lsdc_cursor(struct drm_plane *plane)
250{
251	return container_of(plane, struct lsdc_cursor, base);
252}
253
254struct lsdc_crtc_state {
255	struct drm_crtc_state base;
256	struct lsdc_pixpll_parms pparms;
257};
258
259struct lsdc_gem {
260	/* @mutex: protect objects list */
261	struct mutex mutex;
262	struct list_head objects;
263};
264
265struct lsdc_device {
266	struct drm_device base;
267	struct ttm_device bdev;
268
269	/* @descp: features description of the DC variant */
270	const struct lsdc_desc *descp;
271	struct pci_dev *dc;
272	struct pci_dev *gpu;
273
274	struct loongson_gfxpll *gfxpll;
275
276	/* @reglock: protects concurrent access */
277	spinlock_t reglock;
278
279	void __iomem *reg_base;
280	resource_size_t vram_base;
281	resource_size_t vram_size;
282
283	resource_size_t gtt_base;
284	resource_size_t gtt_size;
285
286	struct lsdc_display_pipe dispipe[LSDC_NUM_CRTC];
287
288	struct lsdc_gem gem;
289
290	u32 irq_status;
291
292	/* tracking pinned memory */
293	size_t vram_pinned_size;
294	size_t gtt_pinned_size;
295
296	/* @num_output: count the number of active display pipe */
297	unsigned int num_output;
298};
299
300static inline struct lsdc_device *tdev_to_ldev(struct ttm_device *bdev)
301{
302	return container_of(bdev, struct lsdc_device, bdev);
303}
304
305static inline struct lsdc_device *to_lsdc(struct drm_device *ddev)
306{
307	return container_of(ddev, struct lsdc_device, base);
308}
309
310static inline struct lsdc_crtc_state *
311to_lsdc_crtc_state(struct drm_crtc_state *base)
312{
313	return container_of(base, struct lsdc_crtc_state, base);
314}
315
316void lsdc_debugfs_init(struct drm_minor *minor);
317
318int ls7a1000_crtc_init(struct drm_device *ddev,
319		       struct drm_crtc *crtc,
320		       struct drm_plane *primary,
321		       struct drm_plane *cursor,
322		       unsigned int index,
323		       bool no_vblank);
324
325int ls7a2000_crtc_init(struct drm_device *ddev,
326		       struct drm_crtc *crtc,
327		       struct drm_plane *primary,
328		       struct drm_plane *cursor,
329		       unsigned int index,
330		       bool no_vblank);
331
332int lsdc_primary_plane_init(struct drm_device *ddev,
333			    struct drm_plane *plane,
334			    unsigned int index);
335
336int ls7a1000_cursor_plane_init(struct drm_device *ddev,
337			       struct drm_plane *plane,
338			       unsigned int index);
339
340int ls7a2000_cursor_plane_init(struct drm_device *ddev,
341			       struct drm_plane *plane,
342			       unsigned int index);
343
344/* Registers access helpers */
345
346static inline u32 lsdc_rreg32(struct lsdc_device *ldev, u32 offset)
347{
348	return readl(ldev->reg_base + offset);
349}
350
351static inline void lsdc_wreg32(struct lsdc_device *ldev, u32 offset, u32 val)
352{
353	writel(val, ldev->reg_base + offset);
354}
355
356static inline void lsdc_ureg32_set(struct lsdc_device *ldev,
357				   u32 offset,
358				   u32 mask)
359{
360	void __iomem *addr = ldev->reg_base + offset;
361	u32 val = readl(addr);
362
363	writel(val | mask, addr);
364}
365
366static inline void lsdc_ureg32_clr(struct lsdc_device *ldev,
367				   u32 offset,
368				   u32 mask)
369{
370	void __iomem *addr = ldev->reg_base + offset;
371	u32 val = readl(addr);
372
373	writel(val & ~mask, addr);
374}
375
376static inline u32 lsdc_pipe_rreg32(struct lsdc_device *ldev,
377				   u32 offset, u32 pipe)
378{
379	return readl(ldev->reg_base + offset + pipe * CRTC_PIPE_OFFSET);
380}
381
382static inline void lsdc_pipe_wreg32(struct lsdc_device *ldev,
383				    u32 offset, u32 pipe, u32 val)
384{
385	writel(val, ldev->reg_base + offset + pipe * CRTC_PIPE_OFFSET);
386}
387
388#endif
389