Loading...
Note: File does not exist in v3.15.
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2023 Loongson Technology Corporation Limited
4 */
5
6#include <linux/debugfs.h>
7#include <linux/delay.h>
8
9#include <drm/drm_atomic.h>
10#include <drm/drm_atomic_helper.h>
11#include <drm/drm_debugfs.h>
12#include <drm/drm_vblank.h>
13
14#include "lsdc_drv.h"
15
16/*
17 * After the CRTC soft reset, the vblank counter would be reset to zero.
18 * But the address and other settings in the CRTC register remain the same
19 * as before.
20 */
21
22static void lsdc_crtc0_soft_reset(struct lsdc_crtc *lcrtc)
23{
24 struct lsdc_device *ldev = lcrtc->ldev;
25 u32 val;
26
27 val = lsdc_rreg32(ldev, LSDC_CRTC0_CFG_REG);
28
29 val &= CFG_VALID_BITS_MASK;
30
31 /* Soft reset bit, active low */
32 val &= ~CFG_RESET_N;
33
34 val &= ~CFG_PIX_FMT_MASK;
35
36 lsdc_wreg32(ldev, LSDC_CRTC0_CFG_REG, val);
37
38 udelay(1);
39
40 val |= CFG_RESET_N | LSDC_PF_XRGB8888 | CFG_OUTPUT_ENABLE;
41
42 lsdc_wreg32(ldev, LSDC_CRTC0_CFG_REG, val);
43
44 /* Wait about a vblank time */
45 mdelay(20);
46}
47
48static void lsdc_crtc1_soft_reset(struct lsdc_crtc *lcrtc)
49{
50 struct lsdc_device *ldev = lcrtc->ldev;
51 u32 val;
52
53 val = lsdc_rreg32(ldev, LSDC_CRTC1_CFG_REG);
54
55 val &= CFG_VALID_BITS_MASK;
56
57 /* Soft reset bit, active low */
58 val &= ~CFG_RESET_N;
59
60 val &= ~CFG_PIX_FMT_MASK;
61
62 lsdc_wreg32(ldev, LSDC_CRTC1_CFG_REG, val);
63
64 udelay(1);
65
66 val |= CFG_RESET_N | LSDC_PF_XRGB8888 | CFG_OUTPUT_ENABLE;
67
68 lsdc_wreg32(ldev, LSDC_CRTC1_CFG_REG, val);
69
70 /* Wait about a vblank time */
71 msleep(20);
72}
73
74static void lsdc_crtc0_enable(struct lsdc_crtc *lcrtc)
75{
76 struct lsdc_device *ldev = lcrtc->ldev;
77 u32 val;
78
79 val = lsdc_rreg32(ldev, LSDC_CRTC0_CFG_REG);
80
81 /*
82 * This may happen in extremely rare cases, but a soft reset can
83 * bring it back to normal. We add a warning here, hoping to catch
84 * something if it happens.
85 */
86 if (val & CRTC_ANCHORED) {
87 drm_warn(&ldev->base, "%s stall\n", lcrtc->base.name);
88 return lsdc_crtc0_soft_reset(lcrtc);
89 }
90
91 lsdc_wreg32(ldev, LSDC_CRTC0_CFG_REG, val | CFG_OUTPUT_ENABLE);
92}
93
94static void lsdc_crtc0_disable(struct lsdc_crtc *lcrtc)
95{
96 struct lsdc_device *ldev = lcrtc->ldev;
97
98 lsdc_ureg32_clr(ldev, LSDC_CRTC0_CFG_REG, CFG_OUTPUT_ENABLE);
99
100 udelay(9);
101}
102
103static void lsdc_crtc1_enable(struct lsdc_crtc *lcrtc)
104{
105 struct lsdc_device *ldev = lcrtc->ldev;
106 u32 val;
107
108 /*
109 * This may happen in extremely rare cases, but a soft reset can
110 * bring it back to normal. We add a warning here, hoping to catch
111 * something if it happens.
112 */
113 val = lsdc_rreg32(ldev, LSDC_CRTC1_CFG_REG);
114 if (val & CRTC_ANCHORED) {
115 drm_warn(&ldev->base, "%s stall\n", lcrtc->base.name);
116 return lsdc_crtc1_soft_reset(lcrtc);
117 }
118
119 lsdc_wreg32(ldev, LSDC_CRTC1_CFG_REG, val | CFG_OUTPUT_ENABLE);
120}
121
122static void lsdc_crtc1_disable(struct lsdc_crtc *lcrtc)
123{
124 struct lsdc_device *ldev = lcrtc->ldev;
125
126 lsdc_ureg32_clr(ldev, LSDC_CRTC1_CFG_REG, CFG_OUTPUT_ENABLE);
127
128 udelay(9);
129}
130
131/* All Loongson display controllers have hardware scanout position recoders */
132
133static void lsdc_crtc0_scan_pos(struct lsdc_crtc *lcrtc, int *hpos, int *vpos)
134{
135 struct lsdc_device *ldev = lcrtc->ldev;
136 u32 val;
137
138 val = lsdc_rreg32(ldev, LSDC_CRTC0_SCAN_POS_REG);
139
140 *hpos = val >> 16;
141 *vpos = val & 0xffff;
142}
143
144static void lsdc_crtc1_scan_pos(struct lsdc_crtc *lcrtc, int *hpos, int *vpos)
145{
146 struct lsdc_device *ldev = lcrtc->ldev;
147 u32 val;
148
149 val = lsdc_rreg32(ldev, LSDC_CRTC1_SCAN_POS_REG);
150
151 *hpos = val >> 16;
152 *vpos = val & 0xffff;
153}
154
155static void lsdc_crtc0_enable_vblank(struct lsdc_crtc *lcrtc)
156{
157 struct lsdc_device *ldev = lcrtc->ldev;
158
159 lsdc_ureg32_set(ldev, LSDC_INT_REG, INT_CRTC0_VSYNC_EN);
160}
161
162static void lsdc_crtc0_disable_vblank(struct lsdc_crtc *lcrtc)
163{
164 struct lsdc_device *ldev = lcrtc->ldev;
165
166 lsdc_ureg32_clr(ldev, LSDC_INT_REG, INT_CRTC0_VSYNC_EN);
167}
168
169static void lsdc_crtc1_enable_vblank(struct lsdc_crtc *lcrtc)
170{
171 struct lsdc_device *ldev = lcrtc->ldev;
172
173 lsdc_ureg32_set(ldev, LSDC_INT_REG, INT_CRTC1_VSYNC_EN);
174}
175
176static void lsdc_crtc1_disable_vblank(struct lsdc_crtc *lcrtc)
177{
178 struct lsdc_device *ldev = lcrtc->ldev;
179
180 lsdc_ureg32_clr(ldev, LSDC_INT_REG, INT_CRTC1_VSYNC_EN);
181}
182
183static void lsdc_crtc0_flip(struct lsdc_crtc *lcrtc)
184{
185 struct lsdc_device *ldev = lcrtc->ldev;
186
187 lsdc_ureg32_set(ldev, LSDC_CRTC0_CFG_REG, CFG_PAGE_FLIP);
188}
189
190static void lsdc_crtc1_flip(struct lsdc_crtc *lcrtc)
191{
192 struct lsdc_device *ldev = lcrtc->ldev;
193
194 lsdc_ureg32_set(ldev, LSDC_CRTC1_CFG_REG, CFG_PAGE_FLIP);
195}
196
197/*
198 * CRTC0 clone from CRTC1 or CRTC1 clone from CRTC0 using hardware logic
199 * This may be useful for custom cloning (TWIN) applications. Saving the
200 * bandwidth compared with the clone (mirroring) display mode provided by
201 * drm core.
202 */
203
204static void lsdc_crtc0_clone(struct lsdc_crtc *lcrtc)
205{
206 struct lsdc_device *ldev = lcrtc->ldev;
207
208 lsdc_ureg32_set(ldev, LSDC_CRTC0_CFG_REG, CFG_HW_CLONE);
209}
210
211static void lsdc_crtc1_clone(struct lsdc_crtc *lcrtc)
212{
213 struct lsdc_device *ldev = lcrtc->ldev;
214
215 lsdc_ureg32_set(ldev, LSDC_CRTC1_CFG_REG, CFG_HW_CLONE);
216}
217
218static void lsdc_crtc0_set_mode(struct lsdc_crtc *lcrtc,
219 const struct drm_display_mode *mode)
220{
221 struct lsdc_device *ldev = lcrtc->ldev;
222
223 lsdc_wreg32(ldev, LSDC_CRTC0_HDISPLAY_REG,
224 (mode->crtc_htotal << 16) | mode->crtc_hdisplay);
225
226 lsdc_wreg32(ldev, LSDC_CRTC0_VDISPLAY_REG,
227 (mode->crtc_vtotal << 16) | mode->crtc_vdisplay);
228
229 lsdc_wreg32(ldev, LSDC_CRTC0_HSYNC_REG,
230 (mode->crtc_hsync_end << 16) | mode->crtc_hsync_start | HSYNC_EN);
231
232 lsdc_wreg32(ldev, LSDC_CRTC0_VSYNC_REG,
233 (mode->crtc_vsync_end << 16) | mode->crtc_vsync_start | VSYNC_EN);
234}
235
236static void lsdc_crtc1_set_mode(struct lsdc_crtc *lcrtc,
237 const struct drm_display_mode *mode)
238{
239 struct lsdc_device *ldev = lcrtc->ldev;
240
241 lsdc_wreg32(ldev, LSDC_CRTC1_HDISPLAY_REG,
242 (mode->crtc_htotal << 16) | mode->crtc_hdisplay);
243
244 lsdc_wreg32(ldev, LSDC_CRTC1_VDISPLAY_REG,
245 (mode->crtc_vtotal << 16) | mode->crtc_vdisplay);
246
247 lsdc_wreg32(ldev, LSDC_CRTC1_HSYNC_REG,
248 (mode->crtc_hsync_end << 16) | mode->crtc_hsync_start | HSYNC_EN);
249
250 lsdc_wreg32(ldev, LSDC_CRTC1_VSYNC_REG,
251 (mode->crtc_vsync_end << 16) | mode->crtc_vsync_start | VSYNC_EN);
252}
253
254/*
255 * This is required for S3 support.
256 * After resuming from suspend, LSDC_CRTCx_CFG_REG (x = 0 or 1) is filled
257 * with garbage value, which causes the CRTC hang there.
258 *
259 * This function provides minimal settings for the affected registers.
260 * This overrides the firmware's settings on startup, making the CRTC work
261 * on our own, similar to the functional of GPU POST (Power On Self Test).
262 * Only touch CRTC hardware-related parts.
263 */
264
265static void lsdc_crtc0_reset(struct lsdc_crtc *lcrtc)
266{
267 struct lsdc_device *ldev = lcrtc->ldev;
268
269 lsdc_wreg32(ldev, LSDC_CRTC0_CFG_REG, CFG_RESET_N | LSDC_PF_XRGB8888);
270}
271
272static void lsdc_crtc1_reset(struct lsdc_crtc *lcrtc)
273{
274 struct lsdc_device *ldev = lcrtc->ldev;
275
276 lsdc_wreg32(ldev, LSDC_CRTC1_CFG_REG, CFG_RESET_N | LSDC_PF_XRGB8888);
277}
278
279static const struct lsdc_crtc_hw_ops ls7a1000_crtc_hw_ops[2] = {
280 {
281 .enable = lsdc_crtc0_enable,
282 .disable = lsdc_crtc0_disable,
283 .enable_vblank = lsdc_crtc0_enable_vblank,
284 .disable_vblank = lsdc_crtc0_disable_vblank,
285 .flip = lsdc_crtc0_flip,
286 .clone = lsdc_crtc0_clone,
287 .set_mode = lsdc_crtc0_set_mode,
288 .get_scan_pos = lsdc_crtc0_scan_pos,
289 .soft_reset = lsdc_crtc0_soft_reset,
290 .reset = lsdc_crtc0_reset,
291 },
292 {
293 .enable = lsdc_crtc1_enable,
294 .disable = lsdc_crtc1_disable,
295 .enable_vblank = lsdc_crtc1_enable_vblank,
296 .disable_vblank = lsdc_crtc1_disable_vblank,
297 .flip = lsdc_crtc1_flip,
298 .clone = lsdc_crtc1_clone,
299 .set_mode = lsdc_crtc1_set_mode,
300 .get_scan_pos = lsdc_crtc1_scan_pos,
301 .soft_reset = lsdc_crtc1_soft_reset,
302 .reset = lsdc_crtc1_reset,
303 },
304};
305
306/*
307 * The 32-bit hardware vblank counter has been available since LS7A2000
308 * and LS2K2000. The counter increases even though the CRTC is disabled,
309 * it will be reset only if the CRTC is being soft reset.
310 * Those registers are also readable for ls7a1000, but its value does not
311 * change.
312 */
313
314static u32 lsdc_crtc0_get_vblank_count(struct lsdc_crtc *lcrtc)
315{
316 struct lsdc_device *ldev = lcrtc->ldev;
317
318 return lsdc_rreg32(ldev, LSDC_CRTC0_VSYNC_COUNTER_REG);
319}
320
321static u32 lsdc_crtc1_get_vblank_count(struct lsdc_crtc *lcrtc)
322{
323 struct lsdc_device *ldev = lcrtc->ldev;
324
325 return lsdc_rreg32(ldev, LSDC_CRTC1_VSYNC_COUNTER_REG);
326}
327
328/*
329 * The DMA step bit fields are available since LS7A2000/LS2K2000, for
330 * supporting odd resolutions. But a large DMA step save the bandwidth.
331 * The larger, the better. Behavior of writing those bits on LS7A1000
332 * or LS2K1000 is underfined.
333 */
334
335static void lsdc_crtc0_set_dma_step(struct lsdc_crtc *lcrtc,
336 enum lsdc_dma_steps dma_step)
337{
338 struct lsdc_device *ldev = lcrtc->ldev;
339 u32 val = lsdc_rreg32(ldev, LSDC_CRTC0_CFG_REG);
340
341 val &= ~CFG_DMA_STEP_MASK;
342 val |= dma_step << CFG_DMA_STEP_SHIFT;
343
344 lsdc_wreg32(ldev, LSDC_CRTC0_CFG_REG, val);
345}
346
347static void lsdc_crtc1_set_dma_step(struct lsdc_crtc *lcrtc,
348 enum lsdc_dma_steps dma_step)
349{
350 struct lsdc_device *ldev = lcrtc->ldev;
351 u32 val = lsdc_rreg32(ldev, LSDC_CRTC1_CFG_REG);
352
353 val &= ~CFG_DMA_STEP_MASK;
354 val |= dma_step << CFG_DMA_STEP_SHIFT;
355
356 lsdc_wreg32(ldev, LSDC_CRTC1_CFG_REG, val);
357}
358
359static const struct lsdc_crtc_hw_ops ls7a2000_crtc_hw_ops[2] = {
360 {
361 .enable = lsdc_crtc0_enable,
362 .disable = lsdc_crtc0_disable,
363 .enable_vblank = lsdc_crtc0_enable_vblank,
364 .disable_vblank = lsdc_crtc0_disable_vblank,
365 .flip = lsdc_crtc0_flip,
366 .clone = lsdc_crtc0_clone,
367 .set_mode = lsdc_crtc0_set_mode,
368 .soft_reset = lsdc_crtc0_soft_reset,
369 .get_scan_pos = lsdc_crtc0_scan_pos,
370 .set_dma_step = lsdc_crtc0_set_dma_step,
371 .get_vblank_counter = lsdc_crtc0_get_vblank_count,
372 .reset = lsdc_crtc0_reset,
373 },
374 {
375 .enable = lsdc_crtc1_enable,
376 .disable = lsdc_crtc1_disable,
377 .enable_vblank = lsdc_crtc1_enable_vblank,
378 .disable_vblank = lsdc_crtc1_disable_vblank,
379 .flip = lsdc_crtc1_flip,
380 .clone = lsdc_crtc1_clone,
381 .set_mode = lsdc_crtc1_set_mode,
382 .get_scan_pos = lsdc_crtc1_scan_pos,
383 .soft_reset = lsdc_crtc1_soft_reset,
384 .set_dma_step = lsdc_crtc1_set_dma_step,
385 .get_vblank_counter = lsdc_crtc1_get_vblank_count,
386 .reset = lsdc_crtc1_reset,
387 },
388};
389
390static void lsdc_crtc_reset(struct drm_crtc *crtc)
391{
392 struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
393 const struct lsdc_crtc_hw_ops *ops = lcrtc->hw_ops;
394 struct lsdc_crtc_state *priv_crtc_state;
395
396 if (crtc->state)
397 crtc->funcs->atomic_destroy_state(crtc, crtc->state);
398
399 priv_crtc_state = kzalloc(sizeof(*priv_crtc_state), GFP_KERNEL);
400
401 if (!priv_crtc_state)
402 __drm_atomic_helper_crtc_reset(crtc, NULL);
403 else
404 __drm_atomic_helper_crtc_reset(crtc, &priv_crtc_state->base);
405
406 /* Reset the CRTC hardware, this is required for S3 support */
407 ops->reset(lcrtc);
408}
409
410static void lsdc_crtc_atomic_destroy_state(struct drm_crtc *crtc,
411 struct drm_crtc_state *state)
412{
413 struct lsdc_crtc_state *priv_state = to_lsdc_crtc_state(state);
414
415 __drm_atomic_helper_crtc_destroy_state(&priv_state->base);
416
417 kfree(priv_state);
418}
419
420static struct drm_crtc_state *
421lsdc_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
422{
423 struct lsdc_crtc_state *new_priv_state;
424 struct lsdc_crtc_state *old_priv_state;
425
426 new_priv_state = kzalloc(sizeof(*new_priv_state), GFP_KERNEL);
427 if (!new_priv_state)
428 return NULL;
429
430 __drm_atomic_helper_crtc_duplicate_state(crtc, &new_priv_state->base);
431
432 old_priv_state = to_lsdc_crtc_state(crtc->state);
433
434 memcpy(&new_priv_state->pparms, &old_priv_state->pparms,
435 sizeof(new_priv_state->pparms));
436
437 return &new_priv_state->base;
438}
439
440static u32 lsdc_crtc_get_vblank_counter(struct drm_crtc *crtc)
441{
442 struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
443
444 /* 32-bit hardware vblank counter */
445 return lcrtc->hw_ops->get_vblank_counter(lcrtc);
446}
447
448static int lsdc_crtc_enable_vblank(struct drm_crtc *crtc)
449{
450 struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
451
452 if (!lcrtc->has_vblank)
453 return -EINVAL;
454
455 lcrtc->hw_ops->enable_vblank(lcrtc);
456
457 return 0;
458}
459
460static void lsdc_crtc_disable_vblank(struct drm_crtc *crtc)
461{
462 struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
463
464 if (!lcrtc->has_vblank)
465 return;
466
467 lcrtc->hw_ops->disable_vblank(lcrtc);
468}
469
470/*
471 * CRTC related debugfs
472 * Primary planes and cursor planes belong to the CRTC as well.
473 * For the sake of convenience, plane-related registers are also add here.
474 */
475
476#define REG_DEF(reg) { \
477 .name = __stringify_1(LSDC_##reg##_REG), \
478 .offset = LSDC_##reg##_REG, \
479}
480
481static const struct lsdc_reg32 lsdc_crtc_regs_array[2][21] = {
482 [0] = {
483 REG_DEF(CRTC0_CFG),
484 REG_DEF(CRTC0_FB_ORIGIN),
485 REG_DEF(CRTC0_DVO_CONF),
486 REG_DEF(CRTC0_HDISPLAY),
487 REG_DEF(CRTC0_HSYNC),
488 REG_DEF(CRTC0_VDISPLAY),
489 REG_DEF(CRTC0_VSYNC),
490 REG_DEF(CRTC0_GAMMA_INDEX),
491 REG_DEF(CRTC0_GAMMA_DATA),
492 REG_DEF(CRTC0_SYNC_DEVIATION),
493 REG_DEF(CRTC0_VSYNC_COUNTER),
494 REG_DEF(CRTC0_SCAN_POS),
495 REG_DEF(CRTC0_STRIDE),
496 REG_DEF(CRTC0_FB1_ADDR_HI),
497 REG_DEF(CRTC0_FB1_ADDR_LO),
498 REG_DEF(CRTC0_FB0_ADDR_HI),
499 REG_DEF(CRTC0_FB0_ADDR_LO),
500 REG_DEF(CURSOR0_CFG),
501 REG_DEF(CURSOR0_POSITION),
502 REG_DEF(CURSOR0_BG_COLOR),
503 REG_DEF(CURSOR0_FG_COLOR),
504 },
505 [1] = {
506 REG_DEF(CRTC1_CFG),
507 REG_DEF(CRTC1_FB_ORIGIN),
508 REG_DEF(CRTC1_DVO_CONF),
509 REG_DEF(CRTC1_HDISPLAY),
510 REG_DEF(CRTC1_HSYNC),
511 REG_DEF(CRTC1_VDISPLAY),
512 REG_DEF(CRTC1_VSYNC),
513 REG_DEF(CRTC1_GAMMA_INDEX),
514 REG_DEF(CRTC1_GAMMA_DATA),
515 REG_DEF(CRTC1_SYNC_DEVIATION),
516 REG_DEF(CRTC1_VSYNC_COUNTER),
517 REG_DEF(CRTC1_SCAN_POS),
518 REG_DEF(CRTC1_STRIDE),
519 REG_DEF(CRTC1_FB1_ADDR_HI),
520 REG_DEF(CRTC1_FB1_ADDR_LO),
521 REG_DEF(CRTC1_FB0_ADDR_HI),
522 REG_DEF(CRTC1_FB0_ADDR_LO),
523 REG_DEF(CURSOR1_CFG),
524 REG_DEF(CURSOR1_POSITION),
525 REG_DEF(CURSOR1_BG_COLOR),
526 REG_DEF(CURSOR1_FG_COLOR),
527 },
528};
529
530static int lsdc_crtc_show_regs(struct seq_file *m, void *arg)
531{
532 struct drm_info_node *node = (struct drm_info_node *)m->private;
533 struct lsdc_crtc *lcrtc = (struct lsdc_crtc *)node->info_ent->data;
534 struct lsdc_device *ldev = lcrtc->ldev;
535 unsigned int i;
536
537 for (i = 0; i < lcrtc->nreg; i++) {
538 const struct lsdc_reg32 *preg = &lcrtc->preg[i];
539 u32 offset = preg->offset;
540
541 seq_printf(m, "%s (0x%04x): 0x%08x\n",
542 preg->name, offset, lsdc_rreg32(ldev, offset));
543 }
544
545 return 0;
546}
547
548static int lsdc_crtc_show_scan_position(struct seq_file *m, void *arg)
549{
550 struct drm_info_node *node = (struct drm_info_node *)m->private;
551 struct lsdc_crtc *lcrtc = (struct lsdc_crtc *)node->info_ent->data;
552 int x, y;
553
554 lcrtc->hw_ops->get_scan_pos(lcrtc, &x, &y);
555 seq_printf(m, "Scanout position: x: %08u, y: %08u\n", x, y);
556
557 return 0;
558}
559
560static int lsdc_crtc_show_vblank_counter(struct seq_file *m, void *arg)
561{
562 struct drm_info_node *node = (struct drm_info_node *)m->private;
563 struct lsdc_crtc *lcrtc = (struct lsdc_crtc *)node->info_ent->data;
564
565 if (lcrtc->hw_ops->get_vblank_counter)
566 seq_printf(m, "%s vblank counter: %08u\n\n", lcrtc->base.name,
567 lcrtc->hw_ops->get_vblank_counter(lcrtc));
568
569 return 0;
570}
571
572static int lsdc_pixpll_show_clock(struct seq_file *m, void *arg)
573{
574 struct drm_info_node *node = (struct drm_info_node *)m->private;
575 struct lsdc_crtc *lcrtc = (struct lsdc_crtc *)node->info_ent->data;
576 struct lsdc_pixpll *pixpll = &lcrtc->pixpll;
577 const struct lsdc_pixpll_funcs *funcs = pixpll->funcs;
578 struct drm_crtc *crtc = &lcrtc->base;
579 struct drm_display_mode *mode = &crtc->state->mode;
580 struct drm_printer printer = drm_seq_file_printer(m);
581 unsigned int out_khz;
582
583 out_khz = funcs->get_rate(pixpll);
584
585 seq_printf(m, "%s: %dx%d@%d\n", crtc->name,
586 mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode));
587
588 seq_printf(m, "Pixel clock required: %d kHz\n", mode->clock);
589 seq_printf(m, "Actual frequency output: %u kHz\n", out_khz);
590 seq_printf(m, "Diff: %d kHz\n", out_khz - mode->clock);
591
592 funcs->print(pixpll, &printer);
593
594 return 0;
595}
596
597static struct drm_info_list lsdc_crtc_debugfs_list[2][4] = {
598 [0] = {
599 { "regs", lsdc_crtc_show_regs, 0, NULL },
600 { "pixclk", lsdc_pixpll_show_clock, 0, NULL },
601 { "scanpos", lsdc_crtc_show_scan_position, 0, NULL },
602 { "vblanks", lsdc_crtc_show_vblank_counter, 0, NULL },
603 },
604 [1] = {
605 { "regs", lsdc_crtc_show_regs, 0, NULL },
606 { "pixclk", lsdc_pixpll_show_clock, 0, NULL },
607 { "scanpos", lsdc_crtc_show_scan_position, 0, NULL },
608 { "vblanks", lsdc_crtc_show_vblank_counter, 0, NULL },
609 },
610};
611
612/* operate manually */
613
614static int lsdc_crtc_man_op_show(struct seq_file *m, void *data)
615{
616 seq_puts(m, "soft_reset: soft reset this CRTC\n");
617 seq_puts(m, "enable: enable this CRTC\n");
618 seq_puts(m, "disable: disable this CRTC\n");
619 seq_puts(m, "flip: trigger the page flip\n");
620 seq_puts(m, "clone: clone the another crtc with hardware logic\n");
621
622 return 0;
623}
624
625static int lsdc_crtc_man_op_open(struct inode *inode, struct file *file)
626{
627 struct drm_crtc *crtc = inode->i_private;
628
629 return single_open(file, lsdc_crtc_man_op_show, crtc);
630}
631
632static ssize_t lsdc_crtc_man_op_write(struct file *file,
633 const char __user *ubuf,
634 size_t len,
635 loff_t *offp)
636{
637 struct seq_file *m = file->private_data;
638 struct lsdc_crtc *lcrtc = m->private;
639 const struct lsdc_crtc_hw_ops *ops = lcrtc->hw_ops;
640 char buf[16];
641
642 if (len > sizeof(buf) - 1)
643 return -EINVAL;
644
645 if (copy_from_user(buf, ubuf, len))
646 return -EFAULT;
647
648 buf[len] = '\0';
649
650 if (sysfs_streq(buf, "soft_reset"))
651 ops->soft_reset(lcrtc);
652 else if (sysfs_streq(buf, "enable"))
653 ops->enable(lcrtc);
654 else if (sysfs_streq(buf, "disable"))
655 ops->disable(lcrtc);
656 else if (sysfs_streq(buf, "flip"))
657 ops->flip(lcrtc);
658 else if (sysfs_streq(buf, "clone"))
659 ops->clone(lcrtc);
660
661 return len;
662}
663
664static const struct file_operations lsdc_crtc_man_op_fops = {
665 .owner = THIS_MODULE,
666 .open = lsdc_crtc_man_op_open,
667 .read = seq_read,
668 .llseek = seq_lseek,
669 .release = single_release,
670 .write = lsdc_crtc_man_op_write,
671};
672
673static int lsdc_crtc_late_register(struct drm_crtc *crtc)
674{
675 struct lsdc_display_pipe *dispipe = crtc_to_display_pipe(crtc);
676 struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
677 struct drm_minor *minor = crtc->dev->primary;
678 unsigned int index = dispipe->index;
679 unsigned int i;
680
681 lcrtc->preg = lsdc_crtc_regs_array[index];
682 lcrtc->nreg = ARRAY_SIZE(lsdc_crtc_regs_array[index]);
683 lcrtc->p_info_list = lsdc_crtc_debugfs_list[index];
684 lcrtc->n_info_list = ARRAY_SIZE(lsdc_crtc_debugfs_list[index]);
685
686 for (i = 0; i < lcrtc->n_info_list; ++i)
687 lcrtc->p_info_list[i].data = lcrtc;
688
689 drm_debugfs_create_files(lcrtc->p_info_list, lcrtc->n_info_list,
690 crtc->debugfs_entry, minor);
691
692 /* Manual operations supported */
693 debugfs_create_file("ops", 0644, crtc->debugfs_entry, lcrtc,
694 &lsdc_crtc_man_op_fops);
695
696 return 0;
697}
698
699static void lsdc_crtc_atomic_print_state(struct drm_printer *p,
700 const struct drm_crtc_state *state)
701{
702 const struct lsdc_crtc_state *priv_state;
703 const struct lsdc_pixpll_parms *pparms;
704
705 priv_state = container_of_const(state, struct lsdc_crtc_state, base);
706 pparms = &priv_state->pparms;
707
708 drm_printf(p, "\tInput clock divider = %u\n", pparms->div_ref);
709 drm_printf(p, "\tMedium clock multiplier = %u\n", pparms->loopc);
710 drm_printf(p, "\tOutput clock divider = %u\n", pparms->div_out);
711}
712
713static const struct drm_crtc_funcs ls7a1000_crtc_funcs = {
714 .reset = lsdc_crtc_reset,
715 .destroy = drm_crtc_cleanup,
716 .set_config = drm_atomic_helper_set_config,
717 .page_flip = drm_atomic_helper_page_flip,
718 .atomic_duplicate_state = lsdc_crtc_atomic_duplicate_state,
719 .atomic_destroy_state = lsdc_crtc_atomic_destroy_state,
720 .late_register = lsdc_crtc_late_register,
721 .enable_vblank = lsdc_crtc_enable_vblank,
722 .disable_vblank = lsdc_crtc_disable_vblank,
723 .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,
724 .atomic_print_state = lsdc_crtc_atomic_print_state,
725};
726
727static const struct drm_crtc_funcs ls7a2000_crtc_funcs = {
728 .reset = lsdc_crtc_reset,
729 .destroy = drm_crtc_cleanup,
730 .set_config = drm_atomic_helper_set_config,
731 .page_flip = drm_atomic_helper_page_flip,
732 .atomic_duplicate_state = lsdc_crtc_atomic_duplicate_state,
733 .atomic_destroy_state = lsdc_crtc_atomic_destroy_state,
734 .late_register = lsdc_crtc_late_register,
735 .get_vblank_counter = lsdc_crtc_get_vblank_counter,
736 .enable_vblank = lsdc_crtc_enable_vblank,
737 .disable_vblank = lsdc_crtc_disable_vblank,
738 .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,
739 .atomic_print_state = lsdc_crtc_atomic_print_state,
740};
741
742static enum drm_mode_status
743lsdc_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
744{
745 struct drm_device *ddev = crtc->dev;
746 struct lsdc_device *ldev = to_lsdc(ddev);
747 const struct lsdc_desc *descp = ldev->descp;
748 unsigned int pitch;
749
750 if (mode->hdisplay > descp->max_width)
751 return MODE_BAD_HVALUE;
752
753 if (mode->vdisplay > descp->max_height)
754 return MODE_BAD_VVALUE;
755
756 if (mode->clock > descp->max_pixel_clk) {
757 drm_dbg_kms(ddev, "mode %dx%d, pixel clock=%d is too high\n",
758 mode->hdisplay, mode->vdisplay, mode->clock);
759 return MODE_CLOCK_HIGH;
760 }
761
762 /* 4 for DRM_FORMAT_XRGB8888 */
763 pitch = mode->hdisplay * 4;
764
765 if (pitch % descp->pitch_align) {
766 drm_dbg_kms(ddev, "align to %u bytes is required: %u\n",
767 descp->pitch_align, pitch);
768 return MODE_BAD_WIDTH;
769 }
770
771 return MODE_OK;
772}
773
774static int lsdc_pixpll_atomic_check(struct drm_crtc *crtc,
775 struct drm_crtc_state *state)
776{
777 struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
778 struct lsdc_pixpll *pixpll = &lcrtc->pixpll;
779 const struct lsdc_pixpll_funcs *pfuncs = pixpll->funcs;
780 struct lsdc_crtc_state *priv_state = to_lsdc_crtc_state(state);
781 unsigned int clock = state->mode.clock;
782 int ret;
783
784 ret = pfuncs->compute(pixpll, clock, &priv_state->pparms);
785 if (ret) {
786 drm_warn(crtc->dev, "Failed to find PLL params for %ukHz\n",
787 clock);
788 return -EINVAL;
789 }
790
791 return 0;
792}
793
794static int lsdc_crtc_helper_atomic_check(struct drm_crtc *crtc,
795 struct drm_atomic_state *state)
796{
797 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
798
799 if (!crtc_state->enable)
800 return 0;
801
802 return lsdc_pixpll_atomic_check(crtc, crtc_state);
803}
804
805static void lsdc_crtc_mode_set_nofb(struct drm_crtc *crtc)
806{
807 struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
808 const struct lsdc_crtc_hw_ops *crtc_hw_ops = lcrtc->hw_ops;
809 struct lsdc_pixpll *pixpll = &lcrtc->pixpll;
810 const struct lsdc_pixpll_funcs *pixpll_funcs = pixpll->funcs;
811 struct drm_crtc_state *state = crtc->state;
812 struct drm_display_mode *mode = &state->mode;
813 struct lsdc_crtc_state *priv_state = to_lsdc_crtc_state(state);
814
815 pixpll_funcs->update(pixpll, &priv_state->pparms);
816
817 if (crtc_hw_ops->set_dma_step) {
818 unsigned int width_in_bytes = mode->hdisplay * 4;
819 enum lsdc_dma_steps dma_step;
820
821 /*
822 * Using DMA step as large as possible, for improving
823 * hardware DMA efficiency.
824 */
825 if (width_in_bytes % 256 == 0)
826 dma_step = LSDC_DMA_STEP_256_BYTES;
827 else if (width_in_bytes % 128 == 0)
828 dma_step = LSDC_DMA_STEP_128_BYTES;
829 else if (width_in_bytes % 64 == 0)
830 dma_step = LSDC_DMA_STEP_64_BYTES;
831 else /* width_in_bytes % 32 == 0 */
832 dma_step = LSDC_DMA_STEP_32_BYTES;
833
834 crtc_hw_ops->set_dma_step(lcrtc, dma_step);
835 }
836
837 crtc_hw_ops->set_mode(lcrtc, mode);
838}
839
840static void lsdc_crtc_send_vblank(struct drm_crtc *crtc)
841{
842 struct drm_device *ddev = crtc->dev;
843 unsigned long flags;
844
845 if (!crtc->state || !crtc->state->event)
846 return;
847
848 drm_dbg(ddev, "Send vblank manually\n");
849
850 spin_lock_irqsave(&ddev->event_lock, flags);
851 drm_crtc_send_vblank_event(crtc, crtc->state->event);
852 crtc->state->event = NULL;
853 spin_unlock_irqrestore(&ddev->event_lock, flags);
854}
855
856static void lsdc_crtc_atomic_enable(struct drm_crtc *crtc,
857 struct drm_atomic_state *state)
858{
859 struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
860
861 if (lcrtc->has_vblank)
862 drm_crtc_vblank_on(crtc);
863
864 lcrtc->hw_ops->enable(lcrtc);
865}
866
867static void lsdc_crtc_atomic_disable(struct drm_crtc *crtc,
868 struct drm_atomic_state *state)
869{
870 struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
871
872 if (lcrtc->has_vblank)
873 drm_crtc_vblank_off(crtc);
874
875 lcrtc->hw_ops->disable(lcrtc);
876
877 /*
878 * Make sure we issue a vblank event after disabling the CRTC if
879 * someone was waiting it.
880 */
881 lsdc_crtc_send_vblank(crtc);
882}
883
884static void lsdc_crtc_atomic_flush(struct drm_crtc *crtc,
885 struct drm_atomic_state *state)
886{
887 spin_lock_irq(&crtc->dev->event_lock);
888 if (crtc->state->event) {
889 if (drm_crtc_vblank_get(crtc) == 0)
890 drm_crtc_arm_vblank_event(crtc, crtc->state->event);
891 else
892 drm_crtc_send_vblank_event(crtc, crtc->state->event);
893 crtc->state->event = NULL;
894 }
895 spin_unlock_irq(&crtc->dev->event_lock);
896}
897
898static bool lsdc_crtc_get_scanout_position(struct drm_crtc *crtc,
899 bool in_vblank_irq,
900 int *vpos,
901 int *hpos,
902 ktime_t *stime,
903 ktime_t *etime,
904 const struct drm_display_mode *mode)
905{
906 struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
907 const struct lsdc_crtc_hw_ops *ops = lcrtc->hw_ops;
908 int vsw, vbp, vactive_start, vactive_end, vfp_end;
909 int x, y;
910
911 vsw = mode->crtc_vsync_end - mode->crtc_vsync_start;
912 vbp = mode->crtc_vtotal - mode->crtc_vsync_end;
913
914 vactive_start = vsw + vbp + 1;
915 vactive_end = vactive_start + mode->crtc_vdisplay;
916
917 /* last scan line before VSYNC */
918 vfp_end = mode->crtc_vtotal;
919
920 if (stime)
921 *stime = ktime_get();
922
923 ops->get_scan_pos(lcrtc, &x, &y);
924
925 if (y > vactive_end)
926 y = y - vfp_end - vactive_start;
927 else
928 y -= vactive_start;
929
930 *vpos = y;
931 *hpos = 0;
932
933 if (etime)
934 *etime = ktime_get();
935
936 return true;
937}
938
939static const struct drm_crtc_helper_funcs lsdc_crtc_helper_funcs = {
940 .mode_valid = lsdc_crtc_mode_valid,
941 .mode_set_nofb = lsdc_crtc_mode_set_nofb,
942 .atomic_enable = lsdc_crtc_atomic_enable,
943 .atomic_disable = lsdc_crtc_atomic_disable,
944 .atomic_check = lsdc_crtc_helper_atomic_check,
945 .atomic_flush = lsdc_crtc_atomic_flush,
946 .get_scanout_position = lsdc_crtc_get_scanout_position,
947};
948
949int ls7a1000_crtc_init(struct drm_device *ddev,
950 struct drm_crtc *crtc,
951 struct drm_plane *primary,
952 struct drm_plane *cursor,
953 unsigned int index,
954 bool has_vblank)
955{
956 struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
957 int ret;
958
959 ret = lsdc_pixpll_init(&lcrtc->pixpll, ddev, index);
960 if (ret) {
961 drm_err(ddev, "pixel pll init failed: %d\n", ret);
962 return ret;
963 }
964
965 lcrtc->ldev = to_lsdc(ddev);
966 lcrtc->has_vblank = has_vblank;
967 lcrtc->hw_ops = &ls7a1000_crtc_hw_ops[index];
968
969 ret = drm_crtc_init_with_planes(ddev, crtc, primary, cursor,
970 &ls7a1000_crtc_funcs,
971 "LS-CRTC-%d", index);
972 if (ret) {
973 drm_err(ddev, "crtc init with planes failed: %d\n", ret);
974 return ret;
975 }
976
977 drm_crtc_helper_add(crtc, &lsdc_crtc_helper_funcs);
978
979 ret = drm_mode_crtc_set_gamma_size(crtc, 256);
980 if (ret)
981 return ret;
982
983 drm_crtc_enable_color_mgmt(crtc, 0, false, 256);
984
985 return 0;
986}
987
988int ls7a2000_crtc_init(struct drm_device *ddev,
989 struct drm_crtc *crtc,
990 struct drm_plane *primary,
991 struct drm_plane *cursor,
992 unsigned int index,
993 bool has_vblank)
994{
995 struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
996 int ret;
997
998 ret = lsdc_pixpll_init(&lcrtc->pixpll, ddev, index);
999 if (ret) {
1000 drm_err(ddev, "crtc init with pll failed: %d\n", ret);
1001 return ret;
1002 }
1003
1004 lcrtc->ldev = to_lsdc(ddev);
1005 lcrtc->has_vblank = has_vblank;
1006 lcrtc->hw_ops = &ls7a2000_crtc_hw_ops[index];
1007
1008 ret = drm_crtc_init_with_planes(ddev, crtc, primary, cursor,
1009 &ls7a2000_crtc_funcs,
1010 "LS-CRTC-%u", index);
1011 if (ret) {
1012 drm_err(ddev, "crtc init with planes failed: %d\n", ret);
1013 return ret;
1014 }
1015
1016 drm_crtc_helper_add(crtc, &lsdc_crtc_helper_funcs);
1017
1018 ret = drm_mode_crtc_set_gamma_size(crtc, 256);
1019 if (ret)
1020 return ret;
1021
1022 drm_crtc_enable_color_mgmt(crtc, 0, false, 256);
1023
1024 return 0;
1025}