1 /* SPDX-License-Identifier: GPL-2.0+ */
3 * Copyright (C) 2023 Loongson Technology Corporation Limited
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>
21 #include "lsdc_gfxpll.h"
22 #include "lsdc_output.h"
23 #include "lsdc_pixpll.h"
24 #include "lsdc_regs.h"
26 /* Currently, all Loongson display controllers have two display pipes. */
27 #define LSDC_NUM_CRTC 2
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.
35 * There is only a 1:1 mapping of crtcs, encoders and connectors for the DC
37 * display pipe 0 = crtc0 + dvo0 + encoder0 + connector0 + cursor0 + primary0
38 * display pipe 1 = crtc1 + dvo1 + encoder1 + connectro1 + cursor1 + primary1
41 enum loongson_chip_id {
47 const struct lsdc_desc *
48 lsdc_device_probe(struct pci_dev *pdev, enum loongson_chip_id chip);
50 struct lsdc_kms_funcs;
62 u32 pitch_align; /* CRTC DMA alignment constraint */
63 bool has_vblank_counter; /* 32 bit hw vsync counter */
65 /* device dependent ops, dc side */
66 const struct lsdc_kms_funcs *funcs;
69 /* GFX related resources wrangler */
71 struct loongson_gfx_desc {
76 /* GFXPLL shared by the DC, GMC and GPU */
82 /* Pixel PLL, per display pipe */
86 } pixpll[LSDC_NUM_CRTC];
88 enum loongson_chip_id chip_id;
92 static inline const struct loongson_gfx_desc *
93 to_loongson_gfx(const struct lsdc_desc *dcp)
95 return container_of_const(dcp, struct loongson_gfx_desc, dc);
103 /* crtc hardware related ops */
107 struct 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);
119 u32 (*get_vblank_counter)(struct lsdc_crtc *lcrtc);
120 void (*set_dma_step)(struct lsdc_crtc *lcrtc, enum lsdc_dma_steps step);
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;
130 struct drm_info_list *p_info_list;
131 unsigned int n_info_list;
135 /* primary plane hardware related ops */
139 struct 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);
146 struct lsdc_primary {
147 struct drm_plane base;
148 const struct lsdc_primary_plane_ops *ops;
149 struct lsdc_device *ldev;
152 /* cursor plane hardware related ops */
156 struct 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);
165 struct drm_plane base;
166 const struct lsdc_cursor_plane_ops *ops;
167 struct lsdc_device *ldev;
171 struct drm_encoder encoder;
172 struct drm_connector connector;
175 static inline struct lsdc_output *
176 connector_to_lsdc_output(struct drm_connector *connector)
178 return container_of(connector, struct lsdc_output, connector);
181 static inline struct lsdc_output *
182 encoder_to_lsdc_output(struct drm_encoder *encoder)
184 return container_of(encoder, struct lsdc_output, encoder);
187 struct 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;
196 static inline struct lsdc_display_pipe *
197 output_to_display_pipe(struct lsdc_output *output)
199 return container_of(output, struct lsdc_display_pipe, output);
202 struct lsdc_kms_funcs {
203 irqreturn_t (*irq_handler)(int irq, void *arg);
205 int (*create_i2c)(struct drm_device *ddev,
206 struct lsdc_display_pipe *dispipe,
209 int (*output_init)(struct drm_device *ddev,
210 struct lsdc_display_pipe *dispipe,
211 struct i2c_adapter *ddc,
214 int (*cursor_plane_init)(struct drm_device *ddev,
215 struct drm_plane *plane,
218 int (*primary_plane_init)(struct drm_device *ddev,
219 struct drm_plane *plane,
222 int (*crtc_init)(struct drm_device *ddev,
223 struct drm_crtc *crtc,
224 struct drm_plane *primary,
225 struct drm_plane *cursor,
230 static inline struct lsdc_crtc *
231 to_lsdc_crtc(struct drm_crtc *crtc)
233 return container_of(crtc, struct lsdc_crtc, base);
236 static inline struct lsdc_display_pipe *
237 crtc_to_display_pipe(struct drm_crtc *crtc)
239 return container_of(crtc, struct lsdc_display_pipe, crtc.base);
242 static inline struct lsdc_primary *
243 to_lsdc_primary(struct drm_plane *plane)
245 return container_of(plane, struct lsdc_primary, base);
248 static inline struct lsdc_cursor *
249 to_lsdc_cursor(struct drm_plane *plane)
251 return container_of(plane, struct lsdc_cursor, base);
254 struct lsdc_crtc_state {
255 struct drm_crtc_state base;
256 struct lsdc_pixpll_parms pparms;
260 /* @mutex: protect objects list */
262 struct list_head objects;
266 struct drm_device base;
267 struct ttm_device bdev;
269 /* @descp: features description of the DC variant */
270 const struct lsdc_desc *descp;
274 struct loongson_gfxpll *gfxpll;
276 /* @reglock: protects concurrent access */
279 void __iomem *reg_base;
280 resource_size_t vram_base;
281 resource_size_t vram_size;
283 resource_size_t gtt_base;
284 resource_size_t gtt_size;
286 struct lsdc_display_pipe dispipe[LSDC_NUM_CRTC];
292 /* tracking pinned memory */
293 size_t vram_pinned_size;
294 size_t gtt_pinned_size;
296 /* @num_output: count the number of active display pipe */
297 unsigned int num_output;
300 static inline struct lsdc_device *tdev_to_ldev(struct ttm_device *bdev)
302 return container_of(bdev, struct lsdc_device, bdev);
305 static inline struct lsdc_device *to_lsdc(struct drm_device *ddev)
307 return container_of(ddev, struct lsdc_device, base);
310 static inline struct lsdc_crtc_state *
311 to_lsdc_crtc_state(struct drm_crtc_state *base)
313 return container_of(base, struct lsdc_crtc_state, base);
316 void lsdc_debugfs_init(struct drm_minor *minor);
318 int ls7a1000_crtc_init(struct drm_device *ddev,
319 struct drm_crtc *crtc,
320 struct drm_plane *primary,
321 struct drm_plane *cursor,
325 int ls7a2000_crtc_init(struct drm_device *ddev,
326 struct drm_crtc *crtc,
327 struct drm_plane *primary,
328 struct drm_plane *cursor,
332 int lsdc_primary_plane_init(struct drm_device *ddev,
333 struct drm_plane *plane,
336 int ls7a1000_cursor_plane_init(struct drm_device *ddev,
337 struct drm_plane *plane,
340 int ls7a2000_cursor_plane_init(struct drm_device *ddev,
341 struct drm_plane *plane,
344 /* Registers access helpers */
346 static inline u32 lsdc_rreg32(struct lsdc_device *ldev, u32 offset)
348 return readl(ldev->reg_base + offset);
351 static inline void lsdc_wreg32(struct lsdc_device *ldev, u32 offset, u32 val)
353 writel(val, ldev->reg_base + offset);
356 static inline void lsdc_ureg32_set(struct lsdc_device *ldev,
360 void __iomem *addr = ldev->reg_base + offset;
361 u32 val = readl(addr);
363 writel(val | mask, addr);
366 static inline void lsdc_ureg32_clr(struct lsdc_device *ldev,
370 void __iomem *addr = ldev->reg_base + offset;
371 u32 val = readl(addr);
373 writel(val & ~mask, addr);
376 static inline u32 lsdc_pipe_rreg32(struct lsdc_device *ldev,
377 u32 offset, u32 pipe)
379 return readl(ldev->reg_base + offset + pipe * CRTC_PIPE_OFFSET);
382 static inline void lsdc_pipe_wreg32(struct lsdc_device *ldev,
383 u32 offset, u32 pipe, u32 val)
385 writel(val, ldev->reg_base + offset + pipe * CRTC_PIPE_OFFSET);