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 41 enum loongson_chip_id { 42 CHIP_LS7A1000 = 0, 43 CHIP_LS7A2000 = 1, 44 CHIP_LS_LAST, 45 }; 46 47 const struct lsdc_desc * 48 lsdc_device_probe(struct pci_dev *pdev, enum loongson_chip_id chip); 49 50 struct lsdc_kms_funcs; 51 52 /* DC specific */ 53 54 struct 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 71 struct 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 92 static inline const struct loongson_gfx_desc * 93 to_loongson_gfx(const struct lsdc_desc *dcp) 94 { 95 return container_of_const(dcp, struct loongson_gfx_desc, dc); 96 }; 97 98 struct lsdc_reg32 { 99 char *name; 100 u32 offset; 101 }; 102 103 /* crtc hardware related ops */ 104 105 struct lsdc_crtc; 106 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); 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 123 struct 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 137 struct lsdc_primary; 138 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); 144 }; 145 146 struct 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 154 struct lsdc_cursor; 155 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); 162 }; 163 164 struct lsdc_cursor { 165 struct drm_plane base; 166 const struct lsdc_cursor_plane_ops *ops; 167 struct lsdc_device *ldev; 168 }; 169 170 struct lsdc_output { 171 struct drm_encoder encoder; 172 struct drm_connector connector; 173 }; 174 175 static inline struct lsdc_output * 176 connector_to_lsdc_output(struct drm_connector *connector) 177 { 178 return container_of(connector, struct lsdc_output, connector); 179 } 180 181 static inline struct lsdc_output * 182 encoder_to_lsdc_output(struct drm_encoder *encoder) 183 { 184 return container_of(encoder, struct lsdc_output, encoder); 185 } 186 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; 193 unsigned int index; 194 }; 195 196 static inline struct lsdc_display_pipe * 197 output_to_display_pipe(struct lsdc_output *output) 198 { 199 return container_of(output, struct lsdc_display_pipe, output); 200 } 201 202 struct 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 230 static inline struct lsdc_crtc * 231 to_lsdc_crtc(struct drm_crtc *crtc) 232 { 233 return container_of(crtc, struct lsdc_crtc, base); 234 } 235 236 static inline struct lsdc_display_pipe * 237 crtc_to_display_pipe(struct drm_crtc *crtc) 238 { 239 return container_of(crtc, struct lsdc_display_pipe, crtc.base); 240 } 241 242 static inline struct lsdc_primary * 243 to_lsdc_primary(struct drm_plane *plane) 244 { 245 return container_of(plane, struct lsdc_primary, base); 246 } 247 248 static inline struct lsdc_cursor * 249 to_lsdc_cursor(struct drm_plane *plane) 250 { 251 return container_of(plane, struct lsdc_cursor, base); 252 } 253 254 struct lsdc_crtc_state { 255 struct drm_crtc_state base; 256 struct lsdc_pixpll_parms pparms; 257 }; 258 259 struct lsdc_gem { 260 /* @mutex: protect objects list */ 261 struct mutex mutex; 262 struct list_head objects; 263 }; 264 265 struct 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 300 static inline struct lsdc_device *tdev_to_ldev(struct ttm_device *bdev) 301 { 302 return container_of(bdev, struct lsdc_device, bdev); 303 } 304 305 static inline struct lsdc_device *to_lsdc(struct drm_device *ddev) 306 { 307 return container_of(ddev, struct lsdc_device, base); 308 } 309 310 static inline struct lsdc_crtc_state * 311 to_lsdc_crtc_state(struct drm_crtc_state *base) 312 { 313 return container_of(base, struct lsdc_crtc_state, base); 314 } 315 316 void lsdc_debugfs_init(struct drm_minor *minor); 317 318 int 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 325 int 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 332 int lsdc_primary_plane_init(struct drm_device *ddev, 333 struct drm_plane *plane, 334 unsigned int index); 335 336 int ls7a1000_cursor_plane_init(struct drm_device *ddev, 337 struct drm_plane *plane, 338 unsigned int index); 339 340 int ls7a2000_cursor_plane_init(struct drm_device *ddev, 341 struct drm_plane *plane, 342 unsigned int index); 343 344 /* Registers access helpers */ 345 346 static inline u32 lsdc_rreg32(struct lsdc_device *ldev, u32 offset) 347 { 348 return readl(ldev->reg_base + offset); 349 } 350 351 static inline void lsdc_wreg32(struct lsdc_device *ldev, u32 offset, u32 val) 352 { 353 writel(val, ldev->reg_base + offset); 354 } 355 356 static 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 366 static 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 376 static 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 382 static 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