1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2023 Loongson Technology Corporation Limited
6 #include <linux/delay.h>
8 #include <drm/drm_atomic.h>
9 #include <drm/drm_atomic_helper.h>
10 #include <drm/drm_debugfs.h>
11 #include <drm/drm_vblank.h>
16 * After the CRTC soft reset, the vblank counter would be reset to zero.
17 * But the address and other settings in the CRTC register remain the same
21 static void lsdc_crtc0_soft_reset(struct lsdc_crtc *lcrtc)
23 struct lsdc_device *ldev = lcrtc->ldev;
26 val = lsdc_rreg32(ldev, LSDC_CRTC0_CFG_REG);
28 val &= CFG_VALID_BITS_MASK;
30 /* Soft reset bit, active low */
33 val &= ~CFG_PIX_FMT_MASK;
35 lsdc_wreg32(ldev, LSDC_CRTC0_CFG_REG, val);
39 val |= CFG_RESET_N | LSDC_PF_XRGB8888 | CFG_OUTPUT_ENABLE;
41 lsdc_wreg32(ldev, LSDC_CRTC0_CFG_REG, val);
43 /* Wait about a vblank time */
47 static void lsdc_crtc1_soft_reset(struct lsdc_crtc *lcrtc)
49 struct lsdc_device *ldev = lcrtc->ldev;
52 val = lsdc_rreg32(ldev, LSDC_CRTC1_CFG_REG);
54 val &= CFG_VALID_BITS_MASK;
56 /* Soft reset bit, active low */
59 val &= ~CFG_PIX_FMT_MASK;
61 lsdc_wreg32(ldev, LSDC_CRTC1_CFG_REG, val);
65 val |= CFG_RESET_N | LSDC_PF_XRGB8888 | CFG_OUTPUT_ENABLE;
67 lsdc_wreg32(ldev, LSDC_CRTC1_CFG_REG, val);
69 /* Wait about a vblank time */
73 static void lsdc_crtc0_enable(struct lsdc_crtc *lcrtc)
75 struct lsdc_device *ldev = lcrtc->ldev;
78 val = lsdc_rreg32(ldev, LSDC_CRTC0_CFG_REG);
81 * This may happen in extremely rare cases, but a soft reset can
82 * bring it back to normal. We add a warning here, hoping to catch
83 * something if it happens.
85 if (val & CRTC_ANCHORED) {
86 drm_warn(&ldev->base, "%s stall\n", lcrtc->base.name);
87 return lsdc_crtc0_soft_reset(lcrtc);
90 lsdc_wreg32(ldev, LSDC_CRTC0_CFG_REG, val | CFG_OUTPUT_ENABLE);
93 static void lsdc_crtc0_disable(struct lsdc_crtc *lcrtc)
95 struct lsdc_device *ldev = lcrtc->ldev;
97 lsdc_ureg32_clr(ldev, LSDC_CRTC0_CFG_REG, CFG_OUTPUT_ENABLE);
102 static void lsdc_crtc1_enable(struct lsdc_crtc *lcrtc)
104 struct lsdc_device *ldev = lcrtc->ldev;
108 * This may happen in extremely rare cases, but a soft reset can
109 * bring it back to normal. We add a warning here, hoping to catch
110 * something if it happens.
112 val = lsdc_rreg32(ldev, LSDC_CRTC1_CFG_REG);
113 if (val & CRTC_ANCHORED) {
114 drm_warn(&ldev->base, "%s stall\n", lcrtc->base.name);
115 return lsdc_crtc1_soft_reset(lcrtc);
118 lsdc_wreg32(ldev, LSDC_CRTC1_CFG_REG, val | CFG_OUTPUT_ENABLE);
121 static void lsdc_crtc1_disable(struct lsdc_crtc *lcrtc)
123 struct lsdc_device *ldev = lcrtc->ldev;
125 lsdc_ureg32_clr(ldev, LSDC_CRTC1_CFG_REG, CFG_OUTPUT_ENABLE);
130 /* All Loongson display controllers have hardware scanout position recoders */
132 static void lsdc_crtc0_scan_pos(struct lsdc_crtc *lcrtc, int *hpos, int *vpos)
134 struct lsdc_device *ldev = lcrtc->ldev;
137 val = lsdc_rreg32(ldev, LSDC_CRTC0_SCAN_POS_REG);
140 *vpos = val & 0xffff;
143 static void lsdc_crtc1_scan_pos(struct lsdc_crtc *lcrtc, int *hpos, int *vpos)
145 struct lsdc_device *ldev = lcrtc->ldev;
148 val = lsdc_rreg32(ldev, LSDC_CRTC1_SCAN_POS_REG);
151 *vpos = val & 0xffff;
154 static void lsdc_crtc0_enable_vblank(struct lsdc_crtc *lcrtc)
156 struct lsdc_device *ldev = lcrtc->ldev;
158 lsdc_ureg32_set(ldev, LSDC_INT_REG, INT_CRTC0_VSYNC_EN);
161 static void lsdc_crtc0_disable_vblank(struct lsdc_crtc *lcrtc)
163 struct lsdc_device *ldev = lcrtc->ldev;
165 lsdc_ureg32_clr(ldev, LSDC_INT_REG, INT_CRTC0_VSYNC_EN);
168 static void lsdc_crtc1_enable_vblank(struct lsdc_crtc *lcrtc)
170 struct lsdc_device *ldev = lcrtc->ldev;
172 lsdc_ureg32_set(ldev, LSDC_INT_REG, INT_CRTC1_VSYNC_EN);
175 static void lsdc_crtc1_disable_vblank(struct lsdc_crtc *lcrtc)
177 struct lsdc_device *ldev = lcrtc->ldev;
179 lsdc_ureg32_clr(ldev, LSDC_INT_REG, INT_CRTC1_VSYNC_EN);
182 static void lsdc_crtc0_flip(struct lsdc_crtc *lcrtc)
184 struct lsdc_device *ldev = lcrtc->ldev;
186 lsdc_ureg32_set(ldev, LSDC_CRTC0_CFG_REG, CFG_PAGE_FLIP);
189 static void lsdc_crtc1_flip(struct lsdc_crtc *lcrtc)
191 struct lsdc_device *ldev = lcrtc->ldev;
193 lsdc_ureg32_set(ldev, LSDC_CRTC1_CFG_REG, CFG_PAGE_FLIP);
197 * CRTC0 clone from CRTC1 or CRTC1 clone from CRTC0 using hardware logic
198 * This may be useful for custom cloning (TWIN) applications. Saving the
199 * bandwidth compared with the clone (mirroring) display mode provided by
203 static void lsdc_crtc0_clone(struct lsdc_crtc *lcrtc)
205 struct lsdc_device *ldev = lcrtc->ldev;
207 lsdc_ureg32_set(ldev, LSDC_CRTC0_CFG_REG, CFG_HW_CLONE);
210 static void lsdc_crtc1_clone(struct lsdc_crtc *lcrtc)
212 struct lsdc_device *ldev = lcrtc->ldev;
214 lsdc_ureg32_set(ldev, LSDC_CRTC1_CFG_REG, CFG_HW_CLONE);
217 static void lsdc_crtc0_set_mode(struct lsdc_crtc *lcrtc,
218 const struct drm_display_mode *mode)
220 struct lsdc_device *ldev = lcrtc->ldev;
222 lsdc_wreg32(ldev, LSDC_CRTC0_HDISPLAY_REG,
223 (mode->crtc_htotal << 16) | mode->crtc_hdisplay);
225 lsdc_wreg32(ldev, LSDC_CRTC0_VDISPLAY_REG,
226 (mode->crtc_vtotal << 16) | mode->crtc_vdisplay);
228 lsdc_wreg32(ldev, LSDC_CRTC0_HSYNC_REG,
229 (mode->crtc_hsync_end << 16) | mode->crtc_hsync_start | HSYNC_EN);
231 lsdc_wreg32(ldev, LSDC_CRTC0_VSYNC_REG,
232 (mode->crtc_vsync_end << 16) | mode->crtc_vsync_start | VSYNC_EN);
235 static void lsdc_crtc1_set_mode(struct lsdc_crtc *lcrtc,
236 const struct drm_display_mode *mode)
238 struct lsdc_device *ldev = lcrtc->ldev;
240 lsdc_wreg32(ldev, LSDC_CRTC1_HDISPLAY_REG,
241 (mode->crtc_htotal << 16) | mode->crtc_hdisplay);
243 lsdc_wreg32(ldev, LSDC_CRTC1_VDISPLAY_REG,
244 (mode->crtc_vtotal << 16) | mode->crtc_vdisplay);
246 lsdc_wreg32(ldev, LSDC_CRTC1_HSYNC_REG,
247 (mode->crtc_hsync_end << 16) | mode->crtc_hsync_start | HSYNC_EN);
249 lsdc_wreg32(ldev, LSDC_CRTC1_VSYNC_REG,
250 (mode->crtc_vsync_end << 16) | mode->crtc_vsync_start | VSYNC_EN);
254 * This is required for S3 support.
255 * After resuming from suspend, LSDC_CRTCx_CFG_REG (x = 0 or 1) is filled
256 * with garbage value, which causes the CRTC hang there.
258 * This function provides minimal settings for the affected registers.
259 * This overrides the firmware's settings on startup, making the CRTC work
260 * on our own, similar to the functional of GPU POST (Power On Self Test).
261 * Only touch CRTC hardware-related parts.
264 static void lsdc_crtc0_reset(struct lsdc_crtc *lcrtc)
266 struct lsdc_device *ldev = lcrtc->ldev;
268 lsdc_wreg32(ldev, LSDC_CRTC0_CFG_REG, CFG_RESET_N | LSDC_PF_XRGB8888);
271 static void lsdc_crtc1_reset(struct lsdc_crtc *lcrtc)
273 struct lsdc_device *ldev = lcrtc->ldev;
275 lsdc_wreg32(ldev, LSDC_CRTC1_CFG_REG, CFG_RESET_N | LSDC_PF_XRGB8888);
278 static const struct lsdc_crtc_hw_ops ls7a1000_crtc_hw_ops[2] = {
280 .enable = lsdc_crtc0_enable,
281 .disable = lsdc_crtc0_disable,
282 .enable_vblank = lsdc_crtc0_enable_vblank,
283 .disable_vblank = lsdc_crtc0_disable_vblank,
284 .flip = lsdc_crtc0_flip,
285 .clone = lsdc_crtc0_clone,
286 .set_mode = lsdc_crtc0_set_mode,
287 .get_scan_pos = lsdc_crtc0_scan_pos,
288 .soft_reset = lsdc_crtc0_soft_reset,
289 .reset = lsdc_crtc0_reset,
292 .enable = lsdc_crtc1_enable,
293 .disable = lsdc_crtc1_disable,
294 .enable_vblank = lsdc_crtc1_enable_vblank,
295 .disable_vblank = lsdc_crtc1_disable_vblank,
296 .flip = lsdc_crtc1_flip,
297 .clone = lsdc_crtc1_clone,
298 .set_mode = lsdc_crtc1_set_mode,
299 .get_scan_pos = lsdc_crtc1_scan_pos,
300 .soft_reset = lsdc_crtc1_soft_reset,
301 .reset = lsdc_crtc1_reset,
306 * The 32-bit hardware vblank counter has been available since LS7A2000
307 * and LS2K2000. The counter increases even though the CRTC is disabled,
308 * it will be reset only if the CRTC is being soft reset.
309 * Those registers are also readable for ls7a1000, but its value does not
313 static u32 lsdc_crtc0_get_vblank_count(struct lsdc_crtc *lcrtc)
315 struct lsdc_device *ldev = lcrtc->ldev;
317 return lsdc_rreg32(ldev, LSDC_CRTC0_VSYNC_COUNTER_REG);
320 static u32 lsdc_crtc1_get_vblank_count(struct lsdc_crtc *lcrtc)
322 struct lsdc_device *ldev = lcrtc->ldev;
324 return lsdc_rreg32(ldev, LSDC_CRTC1_VSYNC_COUNTER_REG);
328 * The DMA step bit fields are available since LS7A2000/LS2K2000, for
329 * supporting odd resolutions. But a large DMA step save the bandwidth.
330 * The larger, the better. Behavior of writing those bits on LS7A1000
331 * or LS2K1000 is underfined.
334 static void lsdc_crtc0_set_dma_step(struct lsdc_crtc *lcrtc,
335 enum lsdc_dma_steps dma_step)
337 struct lsdc_device *ldev = lcrtc->ldev;
338 u32 val = lsdc_rreg32(ldev, LSDC_CRTC0_CFG_REG);
340 val &= ~CFG_DMA_STEP_MASK;
341 val |= dma_step << CFG_DMA_STEP_SHIFT;
343 lsdc_wreg32(ldev, LSDC_CRTC0_CFG_REG, val);
346 static void lsdc_crtc1_set_dma_step(struct lsdc_crtc *lcrtc,
347 enum lsdc_dma_steps dma_step)
349 struct lsdc_device *ldev = lcrtc->ldev;
350 u32 val = lsdc_rreg32(ldev, LSDC_CRTC1_CFG_REG);
352 val &= ~CFG_DMA_STEP_MASK;
353 val |= dma_step << CFG_DMA_STEP_SHIFT;
355 lsdc_wreg32(ldev, LSDC_CRTC1_CFG_REG, val);
358 static const struct lsdc_crtc_hw_ops ls7a2000_crtc_hw_ops[2] = {
360 .enable = lsdc_crtc0_enable,
361 .disable = lsdc_crtc0_disable,
362 .enable_vblank = lsdc_crtc0_enable_vblank,
363 .disable_vblank = lsdc_crtc0_disable_vblank,
364 .flip = lsdc_crtc0_flip,
365 .clone = lsdc_crtc0_clone,
366 .set_mode = lsdc_crtc0_set_mode,
367 .soft_reset = lsdc_crtc0_soft_reset,
368 .get_scan_pos = lsdc_crtc0_scan_pos,
369 .set_dma_step = lsdc_crtc0_set_dma_step,
370 .get_vblank_counter = lsdc_crtc0_get_vblank_count,
371 .reset = lsdc_crtc0_reset,
374 .enable = lsdc_crtc1_enable,
375 .disable = lsdc_crtc1_disable,
376 .enable_vblank = lsdc_crtc1_enable_vblank,
377 .disable_vblank = lsdc_crtc1_disable_vblank,
378 .flip = lsdc_crtc1_flip,
379 .clone = lsdc_crtc1_clone,
380 .set_mode = lsdc_crtc1_set_mode,
381 .get_scan_pos = lsdc_crtc1_scan_pos,
382 .soft_reset = lsdc_crtc1_soft_reset,
383 .set_dma_step = lsdc_crtc1_set_dma_step,
384 .get_vblank_counter = lsdc_crtc1_get_vblank_count,
385 .reset = lsdc_crtc1_reset,
389 static void lsdc_crtc_reset(struct drm_crtc *crtc)
391 struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
392 const struct lsdc_crtc_hw_ops *ops = lcrtc->hw_ops;
393 struct lsdc_crtc_state *priv_crtc_state;
396 crtc->funcs->atomic_destroy_state(crtc, crtc->state);
398 priv_crtc_state = kzalloc(sizeof(*priv_crtc_state), GFP_KERNEL);
400 if (!priv_crtc_state)
401 __drm_atomic_helper_crtc_reset(crtc, NULL);
403 __drm_atomic_helper_crtc_reset(crtc, &priv_crtc_state->base);
405 /* Reset the CRTC hardware, this is required for S3 support */
409 static void lsdc_crtc_atomic_destroy_state(struct drm_crtc *crtc,
410 struct drm_crtc_state *state)
412 struct lsdc_crtc_state *priv_state = to_lsdc_crtc_state(state);
414 __drm_atomic_helper_crtc_destroy_state(&priv_state->base);
419 static struct drm_crtc_state *
420 lsdc_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
422 struct lsdc_crtc_state *new_priv_state;
423 struct lsdc_crtc_state *old_priv_state;
425 new_priv_state = kzalloc(sizeof(*new_priv_state), GFP_KERNEL);
429 __drm_atomic_helper_crtc_duplicate_state(crtc, &new_priv_state->base);
431 old_priv_state = to_lsdc_crtc_state(crtc->state);
433 memcpy(&new_priv_state->pparms, &old_priv_state->pparms,
434 sizeof(new_priv_state->pparms));
436 return &new_priv_state->base;
439 static u32 lsdc_crtc_get_vblank_counter(struct drm_crtc *crtc)
441 struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
443 /* 32-bit hardware vblank counter */
444 return lcrtc->hw_ops->get_vblank_counter(lcrtc);
447 static int lsdc_crtc_enable_vblank(struct drm_crtc *crtc)
449 struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
451 if (!lcrtc->has_vblank)
454 lcrtc->hw_ops->enable_vblank(lcrtc);
459 static void lsdc_crtc_disable_vblank(struct drm_crtc *crtc)
461 struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
463 if (!lcrtc->has_vblank)
466 lcrtc->hw_ops->disable_vblank(lcrtc);
470 * CRTC related debugfs
471 * Primary planes and cursor planes belong to the CRTC as well.
472 * For the sake of convenience, plane-related registers are also add here.
475 #define REG_DEF(reg) { \
476 .name = __stringify_1(LSDC_##reg##_REG), \
477 .offset = LSDC_##reg##_REG, \
480 static const struct lsdc_reg32 lsdc_crtc_regs_array[2][21] = {
483 REG_DEF(CRTC0_FB_ORIGIN),
484 REG_DEF(CRTC0_DVO_CONF),
485 REG_DEF(CRTC0_HDISPLAY),
486 REG_DEF(CRTC0_HSYNC),
487 REG_DEF(CRTC0_VDISPLAY),
488 REG_DEF(CRTC0_VSYNC),
489 REG_DEF(CRTC0_GAMMA_INDEX),
490 REG_DEF(CRTC0_GAMMA_DATA),
491 REG_DEF(CRTC0_SYNC_DEVIATION),
492 REG_DEF(CRTC0_VSYNC_COUNTER),
493 REG_DEF(CRTC0_SCAN_POS),
494 REG_DEF(CRTC0_STRIDE),
495 REG_DEF(CRTC0_FB1_ADDR_HI),
496 REG_DEF(CRTC0_FB1_ADDR_LO),
497 REG_DEF(CRTC0_FB0_ADDR_HI),
498 REG_DEF(CRTC0_FB0_ADDR_LO),
499 REG_DEF(CURSOR0_CFG),
500 REG_DEF(CURSOR0_POSITION),
501 REG_DEF(CURSOR0_BG_COLOR),
502 REG_DEF(CURSOR0_FG_COLOR),
506 REG_DEF(CRTC1_FB_ORIGIN),
507 REG_DEF(CRTC1_DVO_CONF),
508 REG_DEF(CRTC1_HDISPLAY),
509 REG_DEF(CRTC1_HSYNC),
510 REG_DEF(CRTC1_VDISPLAY),
511 REG_DEF(CRTC1_VSYNC),
512 REG_DEF(CRTC1_GAMMA_INDEX),
513 REG_DEF(CRTC1_GAMMA_DATA),
514 REG_DEF(CRTC1_SYNC_DEVIATION),
515 REG_DEF(CRTC1_VSYNC_COUNTER),
516 REG_DEF(CRTC1_SCAN_POS),
517 REG_DEF(CRTC1_STRIDE),
518 REG_DEF(CRTC1_FB1_ADDR_HI),
519 REG_DEF(CRTC1_FB1_ADDR_LO),
520 REG_DEF(CRTC1_FB0_ADDR_HI),
521 REG_DEF(CRTC1_FB0_ADDR_LO),
522 REG_DEF(CURSOR1_CFG),
523 REG_DEF(CURSOR1_POSITION),
524 REG_DEF(CURSOR1_BG_COLOR),
525 REG_DEF(CURSOR1_FG_COLOR),
529 static int lsdc_crtc_show_regs(struct seq_file *m, void *arg)
531 struct drm_info_node *node = (struct drm_info_node *)m->private;
532 struct lsdc_crtc *lcrtc = (struct lsdc_crtc *)node->info_ent->data;
533 struct lsdc_device *ldev = lcrtc->ldev;
536 for (i = 0; i < lcrtc->nreg; i++) {
537 const struct lsdc_reg32 *preg = &lcrtc->preg[i];
538 u32 offset = preg->offset;
540 seq_printf(m, "%s (0x%04x): 0x%08x\n",
541 preg->name, offset, lsdc_rreg32(ldev, offset));
547 static int lsdc_crtc_show_scan_position(struct seq_file *m, void *arg)
549 struct drm_info_node *node = (struct drm_info_node *)m->private;
550 struct lsdc_crtc *lcrtc = (struct lsdc_crtc *)node->info_ent->data;
553 lcrtc->hw_ops->get_scan_pos(lcrtc, &x, &y);
554 seq_printf(m, "Scanout position: x: %08u, y: %08u\n", x, y);
559 static int lsdc_crtc_show_vblank_counter(struct seq_file *m, void *arg)
561 struct drm_info_node *node = (struct drm_info_node *)m->private;
562 struct lsdc_crtc *lcrtc = (struct lsdc_crtc *)node->info_ent->data;
564 if (lcrtc->hw_ops->get_vblank_counter)
565 seq_printf(m, "%s vblank counter: %08u\n\n", lcrtc->base.name,
566 lcrtc->hw_ops->get_vblank_counter(lcrtc));
571 static int lsdc_pixpll_show_clock(struct seq_file *m, void *arg)
573 struct drm_info_node *node = (struct drm_info_node *)m->private;
574 struct lsdc_crtc *lcrtc = (struct lsdc_crtc *)node->info_ent->data;
575 struct lsdc_pixpll *pixpll = &lcrtc->pixpll;
576 const struct lsdc_pixpll_funcs *funcs = pixpll->funcs;
577 struct drm_crtc *crtc = &lcrtc->base;
578 struct drm_display_mode *mode = &crtc->state->mode;
579 struct drm_printer printer = drm_seq_file_printer(m);
580 unsigned int out_khz;
582 out_khz = funcs->get_rate(pixpll);
584 seq_printf(m, "%s: %dx%d@%d\n", crtc->name,
585 mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode));
587 seq_printf(m, "Pixel clock required: %d kHz\n", mode->clock);
588 seq_printf(m, "Actual frequency output: %u kHz\n", out_khz);
589 seq_printf(m, "Diff: %d kHz\n", out_khz - mode->clock);
591 funcs->print(pixpll, &printer);
596 static struct drm_info_list lsdc_crtc_debugfs_list[2][4] = {
598 { "regs", lsdc_crtc_show_regs, 0, NULL },
599 { "pixclk", lsdc_pixpll_show_clock, 0, NULL },
600 { "scanpos", lsdc_crtc_show_scan_position, 0, NULL },
601 { "vblanks", lsdc_crtc_show_vblank_counter, 0, NULL },
604 { "regs", lsdc_crtc_show_regs, 0, NULL },
605 { "pixclk", lsdc_pixpll_show_clock, 0, NULL },
606 { "scanpos", lsdc_crtc_show_scan_position, 0, NULL },
607 { "vblanks", lsdc_crtc_show_vblank_counter, 0, NULL },
611 /* operate manually */
613 static int lsdc_crtc_man_op_show(struct seq_file *m, void *data)
615 seq_puts(m, "soft_reset: soft reset this CRTC\n");
616 seq_puts(m, "enable: enable this CRTC\n");
617 seq_puts(m, "disable: disable this CRTC\n");
618 seq_puts(m, "flip: trigger the page flip\n");
619 seq_puts(m, "clone: clone the another crtc with hardware logic\n");
624 static int lsdc_crtc_man_op_open(struct inode *inode, struct file *file)
626 struct drm_crtc *crtc = inode->i_private;
628 return single_open(file, lsdc_crtc_man_op_show, crtc);
631 static ssize_t lsdc_crtc_man_op_write(struct file *file,
632 const char __user *ubuf,
636 struct seq_file *m = file->private_data;
637 struct lsdc_crtc *lcrtc = m->private;
638 const struct lsdc_crtc_hw_ops *ops = lcrtc->hw_ops;
641 if (len > sizeof(buf) - 1)
644 if (copy_from_user(buf, ubuf, len))
649 if (sysfs_streq(buf, "soft_reset"))
650 ops->soft_reset(lcrtc);
651 else if (sysfs_streq(buf, "enable"))
653 else if (sysfs_streq(buf, "disable"))
655 else if (sysfs_streq(buf, "flip"))
657 else if (sysfs_streq(buf, "clone"))
663 static const struct file_operations lsdc_crtc_man_op_fops = {
664 .owner = THIS_MODULE,
665 .open = lsdc_crtc_man_op_open,
668 .release = single_release,
669 .write = lsdc_crtc_man_op_write,
672 static int lsdc_crtc_late_register(struct drm_crtc *crtc)
674 struct lsdc_display_pipe *dispipe = crtc_to_display_pipe(crtc);
675 struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
676 struct drm_minor *minor = crtc->dev->primary;
677 unsigned int index = dispipe->index;
680 lcrtc->preg = lsdc_crtc_regs_array[index];
681 lcrtc->nreg = ARRAY_SIZE(lsdc_crtc_regs_array[index]);
682 lcrtc->p_info_list = lsdc_crtc_debugfs_list[index];
683 lcrtc->n_info_list = ARRAY_SIZE(lsdc_crtc_debugfs_list[index]);
685 for (i = 0; i < lcrtc->n_info_list; ++i)
686 lcrtc->p_info_list[i].data = lcrtc;
688 drm_debugfs_create_files(lcrtc->p_info_list, lcrtc->n_info_list,
689 crtc->debugfs_entry, minor);
691 /* Manual operations supported */
692 debugfs_create_file("ops", 0644, crtc->debugfs_entry, lcrtc,
693 &lsdc_crtc_man_op_fops);
698 static void lsdc_crtc_atomic_print_state(struct drm_printer *p,
699 const struct drm_crtc_state *state)
701 const struct lsdc_crtc_state *priv_state;
702 const struct lsdc_pixpll_parms *pparms;
704 priv_state = container_of_const(state, struct lsdc_crtc_state, base);
705 pparms = &priv_state->pparms;
707 drm_printf(p, "\tInput clock divider = %u\n", pparms->div_ref);
708 drm_printf(p, "\tMedium clock multiplier = %u\n", pparms->loopc);
709 drm_printf(p, "\tOutput clock divider = %u\n", pparms->div_out);
712 static const struct drm_crtc_funcs ls7a1000_crtc_funcs = {
713 .reset = lsdc_crtc_reset,
714 .destroy = drm_crtc_cleanup,
715 .set_config = drm_atomic_helper_set_config,
716 .page_flip = drm_atomic_helper_page_flip,
717 .atomic_duplicate_state = lsdc_crtc_atomic_duplicate_state,
718 .atomic_destroy_state = lsdc_crtc_atomic_destroy_state,
719 .late_register = lsdc_crtc_late_register,
720 .enable_vblank = lsdc_crtc_enable_vblank,
721 .disable_vblank = lsdc_crtc_disable_vblank,
722 .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,
723 .atomic_print_state = lsdc_crtc_atomic_print_state,
726 static const struct drm_crtc_funcs ls7a2000_crtc_funcs = {
727 .reset = lsdc_crtc_reset,
728 .destroy = drm_crtc_cleanup,
729 .set_config = drm_atomic_helper_set_config,
730 .page_flip = drm_atomic_helper_page_flip,
731 .atomic_duplicate_state = lsdc_crtc_atomic_duplicate_state,
732 .atomic_destroy_state = lsdc_crtc_atomic_destroy_state,
733 .late_register = lsdc_crtc_late_register,
734 .get_vblank_counter = lsdc_crtc_get_vblank_counter,
735 .enable_vblank = lsdc_crtc_enable_vblank,
736 .disable_vblank = lsdc_crtc_disable_vblank,
737 .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,
738 .atomic_print_state = lsdc_crtc_atomic_print_state,
741 static enum drm_mode_status
742 lsdc_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
744 struct drm_device *ddev = crtc->dev;
745 struct lsdc_device *ldev = to_lsdc(ddev);
746 const struct lsdc_desc *descp = ldev->descp;
749 if (mode->hdisplay > descp->max_width)
750 return MODE_BAD_HVALUE;
752 if (mode->vdisplay > descp->max_height)
753 return MODE_BAD_VVALUE;
755 if (mode->clock > descp->max_pixel_clk) {
756 drm_dbg_kms(ddev, "mode %dx%d, pixel clock=%d is too high\n",
757 mode->hdisplay, mode->vdisplay, mode->clock);
758 return MODE_CLOCK_HIGH;
761 /* 4 for DRM_FORMAT_XRGB8888 */
762 pitch = mode->hdisplay * 4;
764 if (pitch % descp->pitch_align) {
765 drm_dbg_kms(ddev, "align to %u bytes is required: %u\n",
766 descp->pitch_align, pitch);
767 return MODE_BAD_WIDTH;
773 static int lsdc_pixpll_atomic_check(struct drm_crtc *crtc,
774 struct drm_crtc_state *state)
776 struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
777 struct lsdc_pixpll *pixpll = &lcrtc->pixpll;
778 const struct lsdc_pixpll_funcs *pfuncs = pixpll->funcs;
779 struct lsdc_crtc_state *priv_state = to_lsdc_crtc_state(state);
780 unsigned int clock = state->mode.clock;
783 ret = pfuncs->compute(pixpll, clock, &priv_state->pparms);
785 drm_warn(crtc->dev, "Failed to find PLL params for %ukHz\n",
793 static int lsdc_crtc_helper_atomic_check(struct drm_crtc *crtc,
794 struct drm_atomic_state *state)
796 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
798 if (!crtc_state->enable)
801 return lsdc_pixpll_atomic_check(crtc, crtc_state);
804 static void lsdc_crtc_mode_set_nofb(struct drm_crtc *crtc)
806 struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
807 const struct lsdc_crtc_hw_ops *crtc_hw_ops = lcrtc->hw_ops;
808 struct lsdc_pixpll *pixpll = &lcrtc->pixpll;
809 const struct lsdc_pixpll_funcs *pixpll_funcs = pixpll->funcs;
810 struct drm_crtc_state *state = crtc->state;
811 struct drm_display_mode *mode = &state->mode;
812 struct lsdc_crtc_state *priv_state = to_lsdc_crtc_state(state);
814 pixpll_funcs->update(pixpll, &priv_state->pparms);
816 if (crtc_hw_ops->set_dma_step) {
817 unsigned int width_in_bytes = mode->hdisplay * 4;
818 enum lsdc_dma_steps dma_step;
821 * Using DMA step as large as possible, for improving
822 * hardware DMA efficiency.
824 if (width_in_bytes % 256 == 0)
825 dma_step = LSDC_DMA_STEP_256_BYTES;
826 else if (width_in_bytes % 128 == 0)
827 dma_step = LSDC_DMA_STEP_128_BYTES;
828 else if (width_in_bytes % 64 == 0)
829 dma_step = LSDC_DMA_STEP_64_BYTES;
830 else /* width_in_bytes % 32 == 0 */
831 dma_step = LSDC_DMA_STEP_32_BYTES;
833 crtc_hw_ops->set_dma_step(lcrtc, dma_step);
836 crtc_hw_ops->set_mode(lcrtc, mode);
839 static void lsdc_crtc_send_vblank(struct drm_crtc *crtc)
841 struct drm_device *ddev = crtc->dev;
844 if (!crtc->state || !crtc->state->event)
847 drm_dbg(ddev, "Send vblank manually\n");
849 spin_lock_irqsave(&ddev->event_lock, flags);
850 drm_crtc_send_vblank_event(crtc, crtc->state->event);
851 crtc->state->event = NULL;
852 spin_unlock_irqrestore(&ddev->event_lock, flags);
855 static void lsdc_crtc_atomic_enable(struct drm_crtc *crtc,
856 struct drm_atomic_state *state)
858 struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
860 if (lcrtc->has_vblank)
861 drm_crtc_vblank_on(crtc);
863 lcrtc->hw_ops->enable(lcrtc);
866 static void lsdc_crtc_atomic_disable(struct drm_crtc *crtc,
867 struct drm_atomic_state *state)
869 struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
871 if (lcrtc->has_vblank)
872 drm_crtc_vblank_off(crtc);
874 lcrtc->hw_ops->disable(lcrtc);
877 * Make sure we issue a vblank event after disabling the CRTC if
878 * someone was waiting it.
880 lsdc_crtc_send_vblank(crtc);
883 static void lsdc_crtc_atomic_flush(struct drm_crtc *crtc,
884 struct drm_atomic_state *state)
886 spin_lock_irq(&crtc->dev->event_lock);
887 if (crtc->state->event) {
888 if (drm_crtc_vblank_get(crtc) == 0)
889 drm_crtc_arm_vblank_event(crtc, crtc->state->event);
891 drm_crtc_send_vblank_event(crtc, crtc->state->event);
892 crtc->state->event = NULL;
894 spin_unlock_irq(&crtc->dev->event_lock);
897 static bool lsdc_crtc_get_scanout_position(struct drm_crtc *crtc,
903 const struct drm_display_mode *mode)
905 struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
906 const struct lsdc_crtc_hw_ops *ops = lcrtc->hw_ops;
907 int vsw, vbp, vactive_start, vactive_end, vfp_end;
910 vsw = mode->crtc_vsync_end - mode->crtc_vsync_start;
911 vbp = mode->crtc_vtotal - mode->crtc_vsync_end;
913 vactive_start = vsw + vbp + 1;
914 vactive_end = vactive_start + mode->crtc_vdisplay;
916 /* last scan line before VSYNC */
917 vfp_end = mode->crtc_vtotal;
920 *stime = ktime_get();
922 ops->get_scan_pos(lcrtc, &x, &y);
925 y = y - vfp_end - vactive_start;
933 *etime = ktime_get();
938 static const struct drm_crtc_helper_funcs lsdc_crtc_helper_funcs = {
939 .mode_valid = lsdc_crtc_mode_valid,
940 .mode_set_nofb = lsdc_crtc_mode_set_nofb,
941 .atomic_enable = lsdc_crtc_atomic_enable,
942 .atomic_disable = lsdc_crtc_atomic_disable,
943 .atomic_check = lsdc_crtc_helper_atomic_check,
944 .atomic_flush = lsdc_crtc_atomic_flush,
945 .get_scanout_position = lsdc_crtc_get_scanout_position,
948 int ls7a1000_crtc_init(struct drm_device *ddev,
949 struct drm_crtc *crtc,
950 struct drm_plane *primary,
951 struct drm_plane *cursor,
955 struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
958 ret = lsdc_pixpll_init(&lcrtc->pixpll, ddev, index);
960 drm_err(ddev, "pixel pll init failed: %d\n", ret);
964 lcrtc->ldev = to_lsdc(ddev);
965 lcrtc->has_vblank = has_vblank;
966 lcrtc->hw_ops = &ls7a1000_crtc_hw_ops[index];
968 ret = drm_crtc_init_with_planes(ddev, crtc, primary, cursor,
969 &ls7a1000_crtc_funcs,
970 "LS-CRTC-%d", index);
972 drm_err(ddev, "crtc init with planes failed: %d\n", ret);
976 drm_crtc_helper_add(crtc, &lsdc_crtc_helper_funcs);
978 ret = drm_mode_crtc_set_gamma_size(crtc, 256);
982 drm_crtc_enable_color_mgmt(crtc, 0, false, 256);
987 int ls7a2000_crtc_init(struct drm_device *ddev,
988 struct drm_crtc *crtc,
989 struct drm_plane *primary,
990 struct drm_plane *cursor,
994 struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
997 ret = lsdc_pixpll_init(&lcrtc->pixpll, ddev, index);
999 drm_err(ddev, "crtc init with pll failed: %d\n", ret);
1003 lcrtc->ldev = to_lsdc(ddev);
1004 lcrtc->has_vblank = has_vblank;
1005 lcrtc->hw_ops = &ls7a2000_crtc_hw_ops[index];
1007 ret = drm_crtc_init_with_planes(ddev, crtc, primary, cursor,
1008 &ls7a2000_crtc_funcs,
1009 "LS-CRTC-%u", index);
1011 drm_err(ddev, "crtc init with planes failed: %d\n", ret);
1015 drm_crtc_helper_add(crtc, &lsdc_crtc_helper_funcs);
1017 ret = drm_mode_crtc_set_gamma_size(crtc, 256);
1021 drm_crtc_enable_color_mgmt(crtc, 0, false, 256);