1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2023 Loongson Technology Corporation Limited
4 */
5
6#include <linux/delay.h>
7
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>
12
13#include "lsdc_drv.h"
14
15/*
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
18 * as before.
19 */
20
21static void lsdc_crtc0_soft_reset(struct lsdc_crtc *lcrtc)
22{
23	struct lsdc_device *ldev = lcrtc->ldev;
24	u32 val;
25
26	val = lsdc_rreg32(ldev, LSDC_CRTC0_CFG_REG);
27
28	val &= CFG_VALID_BITS_MASK;
29
30	/* Soft reset bit, active low */
31	val &= ~CFG_RESET_N;
32
33	val &= ~CFG_PIX_FMT_MASK;
34
35	lsdc_wreg32(ldev, LSDC_CRTC0_CFG_REG, val);
36
37	udelay(1);
38
39	val |= CFG_RESET_N | LSDC_PF_XRGB8888 | CFG_OUTPUT_ENABLE;
40
41	lsdc_wreg32(ldev, LSDC_CRTC0_CFG_REG, val);
42
43	/* Wait about a vblank time */
44	mdelay(20);
45}
46
47static void lsdc_crtc1_soft_reset(struct lsdc_crtc *lcrtc)
48{
49	struct lsdc_device *ldev = lcrtc->ldev;
50	u32 val;
51
52	val = lsdc_rreg32(ldev, LSDC_CRTC1_CFG_REG);
53
54	val &= CFG_VALID_BITS_MASK;
55
56	/* Soft reset bit, active low */
57	val &= ~CFG_RESET_N;
58
59	val &= ~CFG_PIX_FMT_MASK;
60
61	lsdc_wreg32(ldev, LSDC_CRTC1_CFG_REG, val);
62
63	udelay(1);
64
65	val |= CFG_RESET_N | LSDC_PF_XRGB8888 | CFG_OUTPUT_ENABLE;
66
67	lsdc_wreg32(ldev, LSDC_CRTC1_CFG_REG, val);
68
69	/* Wait about a vblank time */
70	msleep(20);
71}
72
73static void lsdc_crtc0_enable(struct lsdc_crtc *lcrtc)
74{
75	struct lsdc_device *ldev = lcrtc->ldev;
76	u32 val;
77
78	val = lsdc_rreg32(ldev, LSDC_CRTC0_CFG_REG);
79
80	/*
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.
84	 */
85	if (val & CRTC_ANCHORED) {
86		drm_warn(&ldev->base, "%s stall\n", lcrtc->base.name);
87		return lsdc_crtc0_soft_reset(lcrtc);
88	}
89
90	lsdc_wreg32(ldev, LSDC_CRTC0_CFG_REG, val | CFG_OUTPUT_ENABLE);
91}
92
93static void lsdc_crtc0_disable(struct lsdc_crtc *lcrtc)
94{
95	struct lsdc_device *ldev = lcrtc->ldev;
96
97	lsdc_ureg32_clr(ldev, LSDC_CRTC0_CFG_REG, CFG_OUTPUT_ENABLE);
98
99	udelay(9);
100}
101
102static void lsdc_crtc1_enable(struct lsdc_crtc *lcrtc)
103{
104	struct lsdc_device *ldev = lcrtc->ldev;
105	u32 val;
106
107	/*
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.
111	 */
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);
116	}
117
118	lsdc_wreg32(ldev, LSDC_CRTC1_CFG_REG, val | CFG_OUTPUT_ENABLE);
119}
120
121static void lsdc_crtc1_disable(struct lsdc_crtc *lcrtc)
122{
123	struct lsdc_device *ldev = lcrtc->ldev;
124
125	lsdc_ureg32_clr(ldev, LSDC_CRTC1_CFG_REG, CFG_OUTPUT_ENABLE);
126
127	udelay(9);
128}
129
130/* All Loongson display controllers have hardware scanout position recoders */
131
132static void lsdc_crtc0_scan_pos(struct lsdc_crtc *lcrtc, int *hpos, int *vpos)
133{
134	struct lsdc_device *ldev = lcrtc->ldev;
135	u32 val;
136
137	val = lsdc_rreg32(ldev, LSDC_CRTC0_SCAN_POS_REG);
138
139	*hpos = val >> 16;
140	*vpos = val & 0xffff;
141}
142
143static void lsdc_crtc1_scan_pos(struct lsdc_crtc *lcrtc, int *hpos, int *vpos)
144{
145	struct lsdc_device *ldev = lcrtc->ldev;
146	u32 val;
147
148	val = lsdc_rreg32(ldev, LSDC_CRTC1_SCAN_POS_REG);
149
150	*hpos = val >> 16;
151	*vpos = val & 0xffff;
152}
153
154static void lsdc_crtc0_enable_vblank(struct lsdc_crtc *lcrtc)
155{
156	struct lsdc_device *ldev = lcrtc->ldev;
157
158	lsdc_ureg32_set(ldev, LSDC_INT_REG, INT_CRTC0_VSYNC_EN);
159}
160
161static void lsdc_crtc0_disable_vblank(struct lsdc_crtc *lcrtc)
162{
163	struct lsdc_device *ldev = lcrtc->ldev;
164
165	lsdc_ureg32_clr(ldev, LSDC_INT_REG, INT_CRTC0_VSYNC_EN);
166}
167
168static void lsdc_crtc1_enable_vblank(struct lsdc_crtc *lcrtc)
169{
170	struct lsdc_device *ldev = lcrtc->ldev;
171
172	lsdc_ureg32_set(ldev, LSDC_INT_REG, INT_CRTC1_VSYNC_EN);
173}
174
175static void lsdc_crtc1_disable_vblank(struct lsdc_crtc *lcrtc)
176{
177	struct lsdc_device *ldev = lcrtc->ldev;
178
179	lsdc_ureg32_clr(ldev, LSDC_INT_REG, INT_CRTC1_VSYNC_EN);
180}
181
182static void lsdc_crtc0_flip(struct lsdc_crtc *lcrtc)
183{
184	struct lsdc_device *ldev = lcrtc->ldev;
185
186	lsdc_ureg32_set(ldev, LSDC_CRTC0_CFG_REG, CFG_PAGE_FLIP);
187}
188
189static void lsdc_crtc1_flip(struct lsdc_crtc *lcrtc)
190{
191	struct lsdc_device *ldev = lcrtc->ldev;
192
193	lsdc_ureg32_set(ldev, LSDC_CRTC1_CFG_REG, CFG_PAGE_FLIP);
194}
195
196/*
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
200 * drm core.
201 */
202
203static void lsdc_crtc0_clone(struct lsdc_crtc *lcrtc)
204{
205	struct lsdc_device *ldev = lcrtc->ldev;
206
207	lsdc_ureg32_set(ldev, LSDC_CRTC0_CFG_REG, CFG_HW_CLONE);
208}
209
210static void lsdc_crtc1_clone(struct lsdc_crtc *lcrtc)
211{
212	struct lsdc_device *ldev = lcrtc->ldev;
213
214	lsdc_ureg32_set(ldev, LSDC_CRTC1_CFG_REG, CFG_HW_CLONE);
215}
216
217static void lsdc_crtc0_set_mode(struct lsdc_crtc *lcrtc,
218				const struct drm_display_mode *mode)
219{
220	struct lsdc_device *ldev = lcrtc->ldev;
221
222	lsdc_wreg32(ldev, LSDC_CRTC0_HDISPLAY_REG,
223		    (mode->crtc_htotal << 16) | mode->crtc_hdisplay);
224
225	lsdc_wreg32(ldev, LSDC_CRTC0_VDISPLAY_REG,
226		    (mode->crtc_vtotal << 16) | mode->crtc_vdisplay);
227
228	lsdc_wreg32(ldev, LSDC_CRTC0_HSYNC_REG,
229		    (mode->crtc_hsync_end << 16) | mode->crtc_hsync_start | HSYNC_EN);
230
231	lsdc_wreg32(ldev, LSDC_CRTC0_VSYNC_REG,
232		    (mode->crtc_vsync_end << 16) | mode->crtc_vsync_start | VSYNC_EN);
233}
234
235static void lsdc_crtc1_set_mode(struct lsdc_crtc *lcrtc,
236				const struct drm_display_mode *mode)
237{
238	struct lsdc_device *ldev = lcrtc->ldev;
239
240	lsdc_wreg32(ldev, LSDC_CRTC1_HDISPLAY_REG,
241		    (mode->crtc_htotal << 16) | mode->crtc_hdisplay);
242
243	lsdc_wreg32(ldev, LSDC_CRTC1_VDISPLAY_REG,
244		    (mode->crtc_vtotal << 16) | mode->crtc_vdisplay);
245
246	lsdc_wreg32(ldev, LSDC_CRTC1_HSYNC_REG,
247		    (mode->crtc_hsync_end << 16) | mode->crtc_hsync_start | HSYNC_EN);
248
249	lsdc_wreg32(ldev, LSDC_CRTC1_VSYNC_REG,
250		    (mode->crtc_vsync_end << 16) | mode->crtc_vsync_start | VSYNC_EN);
251}
252
253/*
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.
257 *
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.
262 */
263
264static void lsdc_crtc0_reset(struct lsdc_crtc *lcrtc)
265{
266	struct lsdc_device *ldev = lcrtc->ldev;
267
268	lsdc_wreg32(ldev, LSDC_CRTC0_CFG_REG, CFG_RESET_N | LSDC_PF_XRGB8888);
269}
270
271static void lsdc_crtc1_reset(struct lsdc_crtc *lcrtc)
272{
273	struct lsdc_device *ldev = lcrtc->ldev;
274
275	lsdc_wreg32(ldev, LSDC_CRTC1_CFG_REG, CFG_RESET_N | LSDC_PF_XRGB8888);
276}
277
278static const struct lsdc_crtc_hw_ops ls7a1000_crtc_hw_ops[2] = {
279	{
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,
290	},
291	{
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,
302	},
303};
304
305/*
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
310 * change.
311 */
312
313static u32 lsdc_crtc0_get_vblank_count(struct lsdc_crtc *lcrtc)
314{
315	struct lsdc_device *ldev = lcrtc->ldev;
316
317	return lsdc_rreg32(ldev, LSDC_CRTC0_VSYNC_COUNTER_REG);
318}
319
320static u32 lsdc_crtc1_get_vblank_count(struct lsdc_crtc *lcrtc)
321{
322	struct lsdc_device *ldev = lcrtc->ldev;
323
324	return lsdc_rreg32(ldev, LSDC_CRTC1_VSYNC_COUNTER_REG);
325}
326
327/*
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.
332 */
333
334static void lsdc_crtc0_set_dma_step(struct lsdc_crtc *lcrtc,
335				    enum lsdc_dma_steps dma_step)
336{
337	struct lsdc_device *ldev = lcrtc->ldev;
338	u32 val = lsdc_rreg32(ldev, LSDC_CRTC0_CFG_REG);
339
340	val &= ~CFG_DMA_STEP_MASK;
341	val |= dma_step << CFG_DMA_STEP_SHIFT;
342
343	lsdc_wreg32(ldev, LSDC_CRTC0_CFG_REG, val);
344}
345
346static void lsdc_crtc1_set_dma_step(struct lsdc_crtc *lcrtc,
347				    enum lsdc_dma_steps dma_step)
348{
349	struct lsdc_device *ldev = lcrtc->ldev;
350	u32 val = lsdc_rreg32(ldev, LSDC_CRTC1_CFG_REG);
351
352	val &= ~CFG_DMA_STEP_MASK;
353	val |= dma_step << CFG_DMA_STEP_SHIFT;
354
355	lsdc_wreg32(ldev, LSDC_CRTC1_CFG_REG, val);
356}
357
358static const struct lsdc_crtc_hw_ops ls7a2000_crtc_hw_ops[2] = {
359	{
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,
372	},
373	{
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,
386	},
387};
388
389static void lsdc_crtc_reset(struct drm_crtc *crtc)
390{
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;
394
395	if (crtc->state)
396		crtc->funcs->atomic_destroy_state(crtc, crtc->state);
397
398	priv_crtc_state = kzalloc(sizeof(*priv_crtc_state), GFP_KERNEL);
399
400	if (!priv_crtc_state)
401		__drm_atomic_helper_crtc_reset(crtc, NULL);
402	else
403		__drm_atomic_helper_crtc_reset(crtc, &priv_crtc_state->base);
404
405	/* Reset the CRTC hardware, this is required for S3 support */
406	ops->reset(lcrtc);
407}
408
409static void lsdc_crtc_atomic_destroy_state(struct drm_crtc *crtc,
410					   struct drm_crtc_state *state)
411{
412	struct lsdc_crtc_state *priv_state = to_lsdc_crtc_state(state);
413
414	__drm_atomic_helper_crtc_destroy_state(&priv_state->base);
415
416	kfree(priv_state);
417}
418
419static struct drm_crtc_state *
420lsdc_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
421{
422	struct lsdc_crtc_state *new_priv_state;
423	struct lsdc_crtc_state *old_priv_state;
424
425	new_priv_state = kzalloc(sizeof(*new_priv_state), GFP_KERNEL);
426	if (!new_priv_state)
427		return NULL;
428
429	__drm_atomic_helper_crtc_duplicate_state(crtc, &new_priv_state->base);
430
431	old_priv_state = to_lsdc_crtc_state(crtc->state);
432
433	memcpy(&new_priv_state->pparms, &old_priv_state->pparms,
434	       sizeof(new_priv_state->pparms));
435
436	return &new_priv_state->base;
437}
438
439static u32 lsdc_crtc_get_vblank_counter(struct drm_crtc *crtc)
440{
441	struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
442
443	/* 32-bit hardware vblank counter */
444	return lcrtc->hw_ops->get_vblank_counter(lcrtc);
445}
446
447static int lsdc_crtc_enable_vblank(struct drm_crtc *crtc)
448{
449	struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
450
451	if (!lcrtc->has_vblank)
452		return -EINVAL;
453
454	lcrtc->hw_ops->enable_vblank(lcrtc);
455
456	return 0;
457}
458
459static void lsdc_crtc_disable_vblank(struct drm_crtc *crtc)
460{
461	struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
462
463	if (!lcrtc->has_vblank)
464		return;
465
466	lcrtc->hw_ops->disable_vblank(lcrtc);
467}
468
469/*
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.
473 */
474
475#define REG_DEF(reg) { \
476	.name = __stringify_1(LSDC_##reg##_REG), \
477	.offset = LSDC_##reg##_REG, \
478}
479
480static const struct lsdc_reg32 lsdc_crtc_regs_array[2][21] = {
481	[0] = {
482		REG_DEF(CRTC0_CFG),
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),
503	},
504	[1] = {
505		REG_DEF(CRTC1_CFG),
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),
526	},
527};
528
529static int lsdc_crtc_show_regs(struct seq_file *m, void *arg)
530{
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;
534	unsigned int i;
535
536	for (i = 0; i < lcrtc->nreg; i++) {
537		const struct lsdc_reg32 *preg = &lcrtc->preg[i];
538		u32 offset = preg->offset;
539
540		seq_printf(m, "%s (0x%04x): 0x%08x\n",
541			   preg->name, offset, lsdc_rreg32(ldev, offset));
542	}
543
544	return 0;
545}
546
547static int lsdc_crtc_show_scan_position(struct seq_file *m, void *arg)
548{
549	struct drm_info_node *node = (struct drm_info_node *)m->private;
550	struct lsdc_crtc *lcrtc = (struct lsdc_crtc *)node->info_ent->data;
551	int x, y;
552
553	lcrtc->hw_ops->get_scan_pos(lcrtc, &x, &y);
554	seq_printf(m, "Scanout position: x: %08u, y: %08u\n", x, y);
555
556	return 0;
557}
558
559static int lsdc_crtc_show_vblank_counter(struct seq_file *m, void *arg)
560{
561	struct drm_info_node *node = (struct drm_info_node *)m->private;
562	struct lsdc_crtc *lcrtc = (struct lsdc_crtc *)node->info_ent->data;
563
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));
567
568	return 0;
569}
570
571static int lsdc_pixpll_show_clock(struct seq_file *m, void *arg)
572{
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;
581
582	out_khz = funcs->get_rate(pixpll);
583
584	seq_printf(m, "%s: %dx%d@%d\n", crtc->name,
585		   mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode));
586
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);
590
591	funcs->print(pixpll, &printer);
592
593	return 0;
594}
595
596static struct drm_info_list lsdc_crtc_debugfs_list[2][4] = {
597	[0] = {
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 },
602	},
603	[1] = {
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 },
608	},
609};
610
611/* operate manually */
612
613static int lsdc_crtc_man_op_show(struct seq_file *m, void *data)
614{
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");
620
621	return 0;
622}
623
624static int lsdc_crtc_man_op_open(struct inode *inode, struct file *file)
625{
626	struct drm_crtc *crtc = inode->i_private;
627
628	return single_open(file, lsdc_crtc_man_op_show, crtc);
629}
630
631static ssize_t lsdc_crtc_man_op_write(struct file *file,
632				      const char __user *ubuf,
633				      size_t len,
634				      loff_t *offp)
635{
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;
639	char buf[16];
640
641	if (len > sizeof(buf) - 1)
642		return -EINVAL;
643
644	if (copy_from_user(buf, ubuf, len))
645		return -EFAULT;
646
647	buf[len] = '\0';
648
649	if (sysfs_streq(buf, "soft_reset"))
650		ops->soft_reset(lcrtc);
651	else if (sysfs_streq(buf, "enable"))
652		ops->enable(lcrtc);
653	else if (sysfs_streq(buf, "disable"))
654		ops->disable(lcrtc);
655	else if (sysfs_streq(buf, "flip"))
656		ops->flip(lcrtc);
657	else if (sysfs_streq(buf, "clone"))
658		ops->clone(lcrtc);
659
660	return len;
661}
662
663static const struct file_operations lsdc_crtc_man_op_fops = {
664	.owner = THIS_MODULE,
665	.open = lsdc_crtc_man_op_open,
666	.read = seq_read,
667	.llseek = seq_lseek,
668	.release = single_release,
669	.write = lsdc_crtc_man_op_write,
670};
671
672static int lsdc_crtc_late_register(struct drm_crtc *crtc)
673{
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;
678	unsigned int i;
679
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]);
684
685	for (i = 0; i < lcrtc->n_info_list; ++i)
686		lcrtc->p_info_list[i].data = lcrtc;
687
688	drm_debugfs_create_files(lcrtc->p_info_list, lcrtc->n_info_list,
689				 crtc->debugfs_entry, minor);
690
691	/* Manual operations supported */
692	debugfs_create_file("ops", 0644, crtc->debugfs_entry, lcrtc,
693			    &lsdc_crtc_man_op_fops);
694
695	return 0;
696}
697
698static void lsdc_crtc_atomic_print_state(struct drm_printer *p,
699					 const struct drm_crtc_state *state)
700{
701	const struct lsdc_crtc_state *priv_state;
702	const struct lsdc_pixpll_parms *pparms;
703
704	priv_state = container_of_const(state, struct lsdc_crtc_state, base);
705	pparms = &priv_state->pparms;
706
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);
710}
711
712static 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,
724};
725
726static 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,
739};
740
741static enum drm_mode_status
742lsdc_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
743{
744	struct drm_device *ddev = crtc->dev;
745	struct lsdc_device *ldev = to_lsdc(ddev);
746	const struct lsdc_desc *descp = ldev->descp;
747	unsigned int pitch;
748
749	if (mode->hdisplay > descp->max_width)
750		return MODE_BAD_HVALUE;
751
752	if (mode->vdisplay > descp->max_height)
753		return MODE_BAD_VVALUE;
754
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;
759	}
760
761	/* 4 for DRM_FORMAT_XRGB8888 */
762	pitch = mode->hdisplay * 4;
763
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;
768	}
769
770	return MODE_OK;
771}
772
773static int lsdc_pixpll_atomic_check(struct drm_crtc *crtc,
774				    struct drm_crtc_state *state)
775{
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;
781	int ret;
782
783	ret = pfuncs->compute(pixpll, clock, &priv_state->pparms);
784	if (ret) {
785		drm_warn(crtc->dev, "Failed to find PLL params for %ukHz\n",
786			 clock);
787		return -EINVAL;
788	}
789
790	return 0;
791}
792
793static int lsdc_crtc_helper_atomic_check(struct drm_crtc *crtc,
794					 struct drm_atomic_state *state)
795{
796	struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
797
798	if (!crtc_state->enable)
799		return 0;
800
801	return lsdc_pixpll_atomic_check(crtc, crtc_state);
802}
803
804static void lsdc_crtc_mode_set_nofb(struct drm_crtc *crtc)
805{
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);
813
814	pixpll_funcs->update(pixpll, &priv_state->pparms);
815
816	if (crtc_hw_ops->set_dma_step) {
817		unsigned int width_in_bytes = mode->hdisplay * 4;
818		enum lsdc_dma_steps dma_step;
819
820		/*
821		 * Using DMA step as large as possible, for improving
822		 * hardware DMA efficiency.
823		 */
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;
832
833		crtc_hw_ops->set_dma_step(lcrtc, dma_step);
834	}
835
836	crtc_hw_ops->set_mode(lcrtc, mode);
837}
838
839static void lsdc_crtc_send_vblank(struct drm_crtc *crtc)
840{
841	struct drm_device *ddev = crtc->dev;
842	unsigned long flags;
843
844	if (!crtc->state || !crtc->state->event)
845		return;
846
847	drm_dbg(ddev, "Send vblank manually\n");
848
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);
853}
854
855static void lsdc_crtc_atomic_enable(struct drm_crtc *crtc,
856				    struct drm_atomic_state *state)
857{
858	struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
859
860	if (lcrtc->has_vblank)
861		drm_crtc_vblank_on(crtc);
862
863	lcrtc->hw_ops->enable(lcrtc);
864}
865
866static void lsdc_crtc_atomic_disable(struct drm_crtc *crtc,
867				     struct drm_atomic_state *state)
868{
869	struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
870
871	if (lcrtc->has_vblank)
872		drm_crtc_vblank_off(crtc);
873
874	lcrtc->hw_ops->disable(lcrtc);
875
876	/*
877	 * Make sure we issue a vblank event after disabling the CRTC if
878	 * someone was waiting it.
879	 */
880	lsdc_crtc_send_vblank(crtc);
881}
882
883static void lsdc_crtc_atomic_flush(struct drm_crtc *crtc,
884				   struct drm_atomic_state *state)
885{
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);
890		else
891			drm_crtc_send_vblank_event(crtc, crtc->state->event);
892		crtc->state->event = NULL;
893	}
894	spin_unlock_irq(&crtc->dev->event_lock);
895}
896
897static bool lsdc_crtc_get_scanout_position(struct drm_crtc *crtc,
898					   bool in_vblank_irq,
899					   int *vpos,
900					   int *hpos,
901					   ktime_t *stime,
902					   ktime_t *etime,
903					   const struct drm_display_mode *mode)
904{
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;
908	int x, y;
909
910	vsw = mode->crtc_vsync_end - mode->crtc_vsync_start;
911	vbp = mode->crtc_vtotal - mode->crtc_vsync_end;
912
913	vactive_start = vsw + vbp + 1;
914	vactive_end = vactive_start + mode->crtc_vdisplay;
915
916	/* last scan line before VSYNC */
917	vfp_end = mode->crtc_vtotal;
918
919	if (stime)
920		*stime = ktime_get();
921
922	ops->get_scan_pos(lcrtc, &x, &y);
923
924	if (y > vactive_end)
925		y = y - vfp_end - vactive_start;
926	else
927		y -= vactive_start;
928
929	*vpos = y;
930	*hpos = 0;
931
932	if (etime)
933		*etime = ktime_get();
934
935	return true;
936}
937
938static 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,
946};
947
948int ls7a1000_crtc_init(struct drm_device *ddev,
949		       struct drm_crtc *crtc,
950		       struct drm_plane *primary,
951		       struct drm_plane *cursor,
952		       unsigned int index,
953		       bool has_vblank)
954{
955	struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
956	int ret;
957
958	ret = lsdc_pixpll_init(&lcrtc->pixpll, ddev, index);
959	if (ret) {
960		drm_err(ddev, "pixel pll init failed: %d\n", ret);
961		return ret;
962	}
963
964	lcrtc->ldev = to_lsdc(ddev);
965	lcrtc->has_vblank = has_vblank;
966	lcrtc->hw_ops = &ls7a1000_crtc_hw_ops[index];
967
968	ret = drm_crtc_init_with_planes(ddev, crtc, primary, cursor,
969					&ls7a1000_crtc_funcs,
970					"LS-CRTC-%d", index);
971	if (ret) {
972		drm_err(ddev, "crtc init with planes failed: %d\n", ret);
973		return ret;
974	}
975
976	drm_crtc_helper_add(crtc, &lsdc_crtc_helper_funcs);
977
978	ret = drm_mode_crtc_set_gamma_size(crtc, 256);
979	if (ret)
980		return ret;
981
982	drm_crtc_enable_color_mgmt(crtc, 0, false, 256);
983
984	return 0;
985}
986
987int ls7a2000_crtc_init(struct drm_device *ddev,
988		       struct drm_crtc *crtc,
989		       struct drm_plane *primary,
990		       struct drm_plane *cursor,
991		       unsigned int index,
992		       bool has_vblank)
993{
994	struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
995	int ret;
996
997	ret = lsdc_pixpll_init(&lcrtc->pixpll, ddev, index);
998	if (ret) {
999		drm_err(ddev, "crtc init with pll failed: %d\n", ret);
1000		return ret;
1001	}
1002
1003	lcrtc->ldev = to_lsdc(ddev);
1004	lcrtc->has_vblank = has_vblank;
1005	lcrtc->hw_ops = &ls7a2000_crtc_hw_ops[index];
1006
1007	ret = drm_crtc_init_with_planes(ddev, crtc, primary, cursor,
1008					&ls7a2000_crtc_funcs,
1009					"LS-CRTC-%u", index);
1010	if (ret) {
1011		drm_err(ddev, "crtc init with planes failed: %d\n", ret);
1012		return ret;
1013	}
1014
1015	drm_crtc_helper_add(crtc, &lsdc_crtc_helper_funcs);
1016
1017	ret = drm_mode_crtc_set_gamma_size(crtc, 256);
1018	if (ret)
1019		return ret;
1020
1021	drm_crtc_enable_color_mgmt(crtc, 0, false, 256);
1022
1023	return 0;
1024}
1025