xref: /linux/drivers/gpu/drm/loongson/lsdc_crtc.c (revision 9aa99bb1)
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 
lsdc_crtc0_soft_reset(struct lsdc_crtc * lcrtc)22 static 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 
lsdc_crtc1_soft_reset(struct lsdc_crtc * lcrtc)48 static 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 
lsdc_crtc0_enable(struct lsdc_crtc * lcrtc)74 static 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 
lsdc_crtc0_disable(struct lsdc_crtc * lcrtc)94 static 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 
lsdc_crtc1_enable(struct lsdc_crtc * lcrtc)103 static 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 
lsdc_crtc1_disable(struct lsdc_crtc * lcrtc)122 static 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 
lsdc_crtc0_scan_pos(struct lsdc_crtc * lcrtc,int * hpos,int * vpos)133 static 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 
lsdc_crtc1_scan_pos(struct lsdc_crtc * lcrtc,int * hpos,int * vpos)144 static 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 
lsdc_crtc0_enable_vblank(struct lsdc_crtc * lcrtc)155 static 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 
lsdc_crtc0_disable_vblank(struct lsdc_crtc * lcrtc)162 static 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 
lsdc_crtc1_enable_vblank(struct lsdc_crtc * lcrtc)169 static 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 
lsdc_crtc1_disable_vblank(struct lsdc_crtc * lcrtc)176 static 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 
lsdc_crtc0_flip(struct lsdc_crtc * lcrtc)183 static 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 
lsdc_crtc1_flip(struct lsdc_crtc * lcrtc)190 static 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 
lsdc_crtc0_clone(struct lsdc_crtc * lcrtc)204 static 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 
lsdc_crtc1_clone(struct lsdc_crtc * lcrtc)211 static 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 
lsdc_crtc0_set_mode(struct lsdc_crtc * lcrtc,const struct drm_display_mode * mode)218 static 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 
lsdc_crtc1_set_mode(struct lsdc_crtc * lcrtc,const struct drm_display_mode * mode)236 static 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 
lsdc_crtc0_reset(struct lsdc_crtc * lcrtc)265 static 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 
lsdc_crtc1_reset(struct lsdc_crtc * lcrtc)272 static 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 
279 static 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 
lsdc_crtc0_get_vblank_count(struct lsdc_crtc * lcrtc)314 static 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 
lsdc_crtc1_get_vblank_count(struct lsdc_crtc * lcrtc)321 static 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 
lsdc_crtc0_set_dma_step(struct lsdc_crtc * lcrtc,enum lsdc_dma_steps dma_step)335 static 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 
lsdc_crtc1_set_dma_step(struct lsdc_crtc * lcrtc,enum lsdc_dma_steps dma_step)347 static 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 
359 static 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 
lsdc_crtc_reset(struct drm_crtc * crtc)390 static 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 
lsdc_crtc_atomic_destroy_state(struct drm_crtc * crtc,struct drm_crtc_state * state)410 static 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 
420 static struct drm_crtc_state *
lsdc_crtc_atomic_duplicate_state(struct drm_crtc * crtc)421 lsdc_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 
lsdc_crtc_get_vblank_counter(struct drm_crtc * crtc)440 static 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 
lsdc_crtc_enable_vblank(struct drm_crtc * crtc)448 static 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 
lsdc_crtc_disable_vblank(struct drm_crtc * crtc)460 static 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 
481 static 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 
lsdc_crtc_show_regs(struct seq_file * m,void * arg)530 static 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 
lsdc_crtc_show_scan_position(struct seq_file * m,void * arg)548 static 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 
lsdc_crtc_show_vblank_counter(struct seq_file * m,void * arg)560 static 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 
lsdc_pixpll_show_clock(struct seq_file * m,void * arg)572 static 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 
597 static 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 
lsdc_crtc_man_op_show(struct seq_file * m,void * data)614 static 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 
lsdc_crtc_man_op_open(struct inode * inode,struct file * file)625 static 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 
lsdc_crtc_man_op_write(struct file * file,const char __user * ubuf,size_t len,loff_t * offp)632 static 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 
664 static 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 
lsdc_crtc_late_register(struct drm_crtc * crtc)673 static 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 
lsdc_crtc_atomic_print_state(struct drm_printer * p,const struct drm_crtc_state * state)699 static 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 
713 static 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 
727 static 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 
742 static enum drm_mode_status
lsdc_crtc_mode_valid(struct drm_crtc * crtc,const struct drm_display_mode * mode)743 lsdc_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 
lsdc_pixpll_atomic_check(struct drm_crtc * crtc,struct drm_crtc_state * state)774 static 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 
lsdc_crtc_helper_atomic_check(struct drm_crtc * crtc,struct drm_atomic_state * state)794 static 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 
lsdc_crtc_mode_set_nofb(struct drm_crtc * crtc)805 static 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 
lsdc_crtc_send_vblank(struct drm_crtc * crtc)840 static 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 
lsdc_crtc_atomic_enable(struct drm_crtc * crtc,struct drm_atomic_state * state)856 static 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 
lsdc_crtc_atomic_disable(struct drm_crtc * crtc,struct drm_atomic_state * state)867 static 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 
lsdc_crtc_atomic_flush(struct drm_crtc * crtc,struct drm_atomic_state * state)884 static 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 
lsdc_crtc_get_scanout_position(struct drm_crtc * crtc,bool in_vblank_irq,int * vpos,int * hpos,ktime_t * stime,ktime_t * etime,const struct drm_display_mode * mode)898 static 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 
939 static 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 
ls7a1000_crtc_init(struct drm_device * ddev,struct drm_crtc * crtc,struct drm_plane * primary,struct drm_plane * cursor,unsigned int index,bool has_vblank)949 int 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 
ls7a2000_crtc_init(struct drm_device * ddev,struct drm_crtc * crtc,struct drm_plane * primary,struct drm_plane * cursor,unsigned int index,bool has_vblank)988 int 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 }
1026