• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 Allwinnertech Co.Ltd
3  * Authors: zhengwanyu
4  *
5  * This program is free software; you can redistribute  it and/or modify it
6  * under  the terms of  the GNU General  Public License as published by the
7  * Free Software Foundation;  either version 2 of the  License, or (at your
8  * option) any later version.
9  *
10  */
11 #include <drm/drm_crtc_helper.h>
12 #include <drm/drm_fb_helper.h>
13 #include <drm/drm_plane_helper.h>
14 #include <drm/drm_atomic_helper.h>
15 #include <drm/drm_atomic.h>
16 #include <drm/drm_print.h>
17 #include <drm/drm_vblank.h>
18 
19 #include "sunxi_drm_drv.h"
20 #include "sunxi_drm_crtc.h"
21 #include "sunxi_drm_plane.h"
22 #include "sunxi_drm_connector.h"
23 
24 static unsigned int sunxi_crtc_cnt;
25 static struct sunxi_drm_crtc *sunxi_crtc;
26 
sunxi_drm_crtc_get_crtc(int id)27 struct sunxi_drm_crtc *sunxi_drm_crtc_get_crtc(int id)
28 {
29 	if (id >= sunxi_crtc_cnt) {
30 		DRM_ERROR("crtc id:%d is too big\n", id);
31 		return NULL;
32 	}
33 
34 	return &sunxi_crtc[id];
35 }
36 
sunxi_drm_get_crtc_count(void)37 unsigned int sunxi_drm_get_crtc_count(void)
38 {
39 	return sunxi_crtc_cnt;
40 }
41 
42 void sunxi_drm_crtc_destroy(struct drm_crtc *drm_crtc);
43 
44 static struct drm_connector *
sunxi_crtc_get_attached_connector(struct drm_crtc * crtc)45 sunxi_crtc_get_attached_connector(struct drm_crtc *crtc)
46 {
47 	bool find = false;
48 	struct drm_encoder *encoder;
49 	struct drm_connector *connector;
50 	struct drm_connector_list_iter conn_iter;
51 	struct drm_device *dev;
52 
53 	drm_for_each_encoder(encoder, crtc->dev) {
54 		if (encoder->crtc == crtc) {
55 			find = true;
56 			break;
57 		}
58 	}
59 
60 	if (!find) {
61 		DRM_ERROR("can NOT find the attached encoder for crtc:%d\n",
62 			crtc->index);
63 		return NULL;
64 	}
65 	dev = encoder->dev;
66 	find = false;
67 	drm_connector_list_iter_begin(dev, &conn_iter);
68 	drm_for_each_connector_iter(connector, &conn_iter) {
69 		if (connector->encoder == encoder) {
70 			drm_connector_list_iter_end(&conn_iter);
71 			find = true;
72 			break;
73 		}
74 	}
75 	drm_connector_list_iter_end(&conn_iter);
76 
77 	if (!find) {
78 		DRM_ERROR("can NOT find the attached connector for encoder:%d\n",
79 			encoder->index);
80 		return NULL;
81 	}
82 
83 	return connector;
84 }
85 
sunxi_crtc_set_enhance(struct drm_crtc * crtc,struct sunxi_drm_crtc_enhance * enhance)86 static int sunxi_crtc_set_enhance(struct drm_crtc *crtc,
87 			struct sunxi_drm_crtc_enhance *enhance)
88 {
89 	int ret;
90 	struct drm_connector *connector;
91 	struct sunxi_drm_connector *sconnector;
92 	struct sunxi_drm_crtc *scrtc = to_sunxi_crtc(crtc);
93 	struct sunxi_de_funcs *de_funcs = scrtc->hw_funcs;
94 
95 	connector = sunxi_crtc_get_attached_connector(crtc);
96 	if (!connector) {
97 		DRM_ERROR("Not find attached connector for crtc:%d\n",
98 			crtc->index);
99 		return -EINVAL;
100 	}
101 
102 	sconnector = to_sunxi_connector(connector);
103 
104 	mutex_lock(&scrtc->update_reg_lock);
105 	ret = de_funcs->set_enhance(crtc->index,
106 			enhance->mode, enhance->enable,
107 			crtc->mode.hdisplay, crtc->mode.vdisplay,
108 			sconnector->type);
109 
110 	atomic_set(&scrtc->update, 1);
111 
112 	mutex_unlock(&scrtc->update_reg_lock);
113 
114 	return ret;
115 }
116 
117 
sunxi_crtc_get_enhance(struct drm_crtc * crtc,struct sunxi_drm_crtc_enhance * enhance)118 static void sunxi_crtc_get_enhance(struct drm_crtc *crtc,
119 			struct sunxi_drm_crtc_enhance *enhance)
120 {
121 	struct sunxi_drm_crtc *scrtc = to_sunxi_crtc(crtc);
122 	struct sunxi_de_funcs *de_funcs = scrtc->hw_funcs;
123 
124 	mutex_lock(&scrtc->update_reg_lock);
125 	de_funcs->get_enhance(crtc->index,
126 	&enhance->mode, &enhance->enable, NULL, NULL);
127 	mutex_unlock(&scrtc->update_reg_lock);
128 }
129 
sunxi_drm_crtc_set_enhance_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)130 int sunxi_drm_crtc_set_enhance_ioctl(struct drm_device *dev,
131 		void *data, struct drm_file *file_priv)
132 {
133 	struct drm_crtc *crtc;
134 	struct sunxi_drm_crtc_enhance *enhance =
135 		(struct sunxi_drm_crtc_enhance *)data;
136 
137 	crtc = drm_crtc_find(dev, file_priv, enhance->crtc_obj_id);
138 	if (!crtc) {
139 		DRM_ERROR("can NOT find crtc for crtc_id:%d\n",
140 			enhance->crtc_obj_id);
141 		return -EINVAL;
142 	}
143 
144 	return sunxi_crtc_set_enhance(crtc, enhance);
145 }
146 
sunxi_drm_crtc_get_enhance_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)147 int sunxi_drm_crtc_get_enhance_ioctl(struct drm_device *dev,
148 		void *data, struct drm_file *file_priv)
149 {
150 	struct drm_crtc *crtc;
151 	struct sunxi_drm_crtc_enhance *enhance =
152 		(struct sunxi_drm_crtc_enhance *)data;
153 
154 	crtc = drm_crtc_find(dev, file_priv, enhance->crtc_obj_id);
155 	if (!crtc) {
156 		DRM_ERROR("can NOT find crtc for crtc_id:%d\n",
157 			enhance->crtc_obj_id);
158 		return -EINVAL;
159 	}
160 
161 	sunxi_crtc_get_enhance(crtc, enhance);
162 
163 	return 0;
164 }
165 
166 /*smbl*/
sunxi_crtc_set_smbl(struct drm_crtc * crtc,struct sunxi_drm_crtc_smbl * smbl)167 static int sunxi_crtc_set_smbl(struct drm_crtc *crtc,
168 			struct sunxi_drm_crtc_smbl *smbl)
169 {
170 	int ret;
171 	struct sunxi_drm_crtc *scrtc = to_sunxi_crtc(crtc);
172 	struct sunxi_de_funcs *de_funcs = scrtc->hw_funcs;
173 
174 	mutex_lock(&scrtc->update_reg_lock);
175 	ret = de_funcs->set_smbl(crtc->index,
176 					smbl->enable, &smbl->window);
177 
178 	atomic_set(&scrtc->update, 1);
179 
180 	mutex_unlock(&scrtc->update_reg_lock);
181 
182 	return ret;
183 }
184 
sunxi_crtc_get_smbl(struct drm_crtc * crtc,struct sunxi_drm_crtc_smbl * smbl)185 static void sunxi_crtc_get_smbl(struct drm_crtc *crtc,
186 			struct sunxi_drm_crtc_smbl *smbl)
187 {
188 	struct sunxi_drm_crtc *scrtc = to_sunxi_crtc(crtc);
189 	struct sunxi_de_funcs *de_funcs = scrtc->hw_funcs;
190 
191 	mutex_lock(&scrtc->update_reg_lock);
192 	de_funcs->get_smbl(crtc->index,
193 		&smbl->enable, &smbl->window);
194 	mutex_unlock(&scrtc->update_reg_lock);
195 }
196 
sunxi_drm_crtc_set_smbl_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)197 int sunxi_drm_crtc_set_smbl_ioctl(struct drm_device *dev,
198 		void *data, struct drm_file *file_priv)
199 {
200 	struct drm_crtc *crtc;
201 	struct sunxi_drm_crtc_smbl *smbl =
202 		(struct sunxi_drm_crtc_smbl *)data;
203 
204 	crtc = drm_crtc_find(dev, file_priv, smbl->crtc_obj_id);
205 	if (!crtc) {
206 		DRM_ERROR("can NOT find crtc for crtc_id:%d\n",
207 			smbl->crtc_obj_id);
208 		return -EINVAL;
209 	}
210 
211 	return sunxi_crtc_set_smbl(crtc, smbl);
212 }
213 
sunxi_drm_crtc_get_smbl_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)214 int sunxi_drm_crtc_get_smbl_ioctl(struct drm_device *dev,
215 		void *data, struct drm_file *file_priv)
216 {
217 	struct drm_crtc *crtc;
218 	struct sunxi_drm_crtc_smbl *smbl =
219 		(struct sunxi_drm_crtc_smbl *)data;
220 
221 	crtc = drm_crtc_find(dev, file_priv, smbl->crtc_obj_id);
222 	if (!crtc) {
223 		DRM_ERROR("can NOT find crtc for crtc_id:%d\n",
224 			smbl->crtc_obj_id);
225 		return -EINVAL;
226 	}
227 
228 	sunxi_crtc_get_smbl(crtc, smbl);
229 
230 	return 0;
231 }
232 
233 
sunxi_crtc_modeinfo_dump(struct drm_mode_modeinfo * mode)234 void sunxi_crtc_modeinfo_dump(struct drm_mode_modeinfo *mode)
235 {
236 	DRM_INFO("MODE INFO:\n");
237 	DRM_INFO("clock:%u\n flag:%u type:%u name:%s\n",
238 		mode->clock, mode->flags, mode->type, mode->name);
239 	DRM_INFO("hdisplay:%u hsync_start:%u hsync_end:%u htotal:%u hskew:%u\n",
240 		mode->hdisplay, mode->hsync_start, mode->hsync_end,
241 		mode->htotal, mode->hskew);
242 		DRM_INFO("vdisplay:%u vsync_start:%u vsync_end:%u "
243 			"vtotal:%u hscan:%u vrefresh:%u\n",
244 		mode->vdisplay, mode->vsync_start, mode->vsync_end,
245 		mode->vtotal, mode->vscan, mode->vrefresh);
246 }
247 
248 /*void sunxi_crtc_state_dump(struct drm_crtc_state *state)
249 {
250 	struct drm_mode_modeinfo modeinfo;
251 
252 	DRM_INFO("drm_crtc_state info:\n");
253 	DRM_INFO("CRTC index: %d\n", drm_crtc_index(state->crtc));
254 	DRM_INFO("enable:%u active:%u\n", state->enable, state->active);
255 	DRM_INFO("Changed: planes:%u mode:%u active:%u connectors:%u "
256 		"zops:%u color_mgmt_changed:%u\n", state->planes_changed,
257 		state->mode_changed, state->active_changed,
258 		state->connectors_changed,
259 		state->zpos_changed, state->color_mgmt_changed);
260 	DRM_INFO("MASK: plane:0x%x connector:0x%x encoder:0x%x\n",
261 		state->plane_mask, state->connector_mask, state->encoder_mask);
262 	DRM_INFO("last_vblank_count:%u\n", state->last_vblank_count);
263 
264 	drm_property_reference_blob(state->mode_blob);
265 	memcpy(&modeinfo, state->mode_blob->data, state->mode_blob->length);
266 	sunxi_crtc_modeinfo_dump(&modeinfo);
267 	drm_property_unreference_blob(state->mode_blob);
268 }*/
269 
sunxi_crtc_modeinfo_show(char * buf,struct drm_mode_modeinfo * mode)270 static ssize_t sunxi_crtc_modeinfo_show(char *buf, struct drm_mode_modeinfo *mode)
271 {
272 	ssize_t n = 0;
273 
274 	n += sprintf(buf + n, "clock:%u flag:%u type:%u name:%s\n",
275 		mode->clock, mode->flags, mode->type, mode->name);
276 	n += sprintf(buf + n, "hdisplay:%u hsync_start:%u hsync_end:%u htotal:%u hskew:%u\n",
277 		mode->hdisplay, mode->hsync_start, mode->hsync_end,
278 		mode->htotal, mode->hskew);
279 	n += sprintf(buf + n, "vdisplay:%u vsync_start:%u vsync_end:%u "
280 			"vtotal:%u hscan:%u vrefresh:%u\n\n",
281 		mode->vdisplay, mode->vsync_start, mode->vsync_end,
282 		mode->vtotal, mode->vscan, mode->vrefresh);
283 
284 	return n;
285 }
286 
287 /*static ssize_t sunxi_crtc_state_show(char *buf, struct drm_crtc_state *state)
288 {
289 	ssize_t n = 0;
290 	struct drm_mode_modeinfo modeinfo;
291 
292 	n += sprintf(buf + n, "enable:%u active:%u\n", state->enable, state->active);
293 	n += sprintf(buf + n, "Changed: planes:%u mode:%u active:%u connectors:%u "
294 		"zops:%u color_mgmt_changed:%u\n", state->planes_changed,
295 		state->mode_changed, state->active_changed,
296 		state->connectors_changed,
297 		state->zpos_changed, state->color_mgmt_changed);
298 	n += sprintf(buf + n, "MASK: plane:0x%x connector:0x%x encoder:0x%x\n",
299 		state->plane_mask, state->connector_mask, state->encoder_mask);
300 	n += sprintf(buf + n, "last_vblank_count:%u\n", state->last_vblank_count);
301 
302 	if (!state->mode_blob) {
303 		n += sprintf(buf + n, "No mode blob\n");
304 		return n;
305 	}
306 
307 	n += sprintf(buf + n, "[crtc state MODE INFO]:\n");
308 	drm_property_reference_blob(state->mode_blob);
309 	memcpy(&modeinfo, state->mode_blob->data, state->mode_blob->length);
310 	n += sunxi_crtc_modeinfo_show(buf + n, &modeinfo);
311 	drm_property_unreference_blob(state->mode_blob);
312 
313 	return n;
314 }
315 
316 
317 ssize_t sunxi_drm_crtc_show(char *buf, struct drm_device *dev)
318 {
319 	ssize_t n = 0;
320 	struct drm_crtc *crtc;
321 
322 	drm_for_each_crtc(crtc, dev) {
323 		struct sunxi_drm_crtc *scrtc = to_sunxi_crtc(crtc);
324 
325 		n += sprintf(buf + n, "crtc id:%d\n\n", scrtc->crtc_id);
326 
327 		n += sprintf(buf + n, "[crtc id:%d  basic info]:\n", scrtc->crtc_id);
328 		n += sprintf(buf + n, "enabled(core):%d  enable(hal):%d\n",
329 				crtc->enabled, scrtc->enabled);
330 		n += sprintf(buf + n, "overlay_plane_num:%d  plane_num:%d\n",
331 			scrtc->overlay_plane_num, scrtc->plane_num);
332 		n += sprintf(buf + n, "crtc name:%s\n", crtc->name);
333 		n += sprintf(buf + n, "drm_mode_object id:%u\n", crtc->base.id);
334 
335 		if (!crtc->enabled || !scrtc->enabled) {
336 			n += sprintf(buf + n, "NOT enabled!!!\n\n");
337 			return n;
338 		}
339 
340 		n += sprintf(buf + n, "x-y:%d-%d\n", crtc->x, crtc->y);
341 		n += sprintf(buf + n, "fence_seqno:%lu\n", crtc->fence_seqno);
342 		n += sprintf(buf + n, "timeline_name:%s\n\n", crtc->timeline_name);
343 
344 		if (crtc->state) {
345 			n += sprintf(buf + n, "[crtc id:%d state info]:\n", scrtc->crtc_id);
346 			n += sunxi_crtc_state_show(buf + n, crtc->state);
347 		}
348 
349 		n += sprintf(buf + n, "[crtc id:%d enabled planes info]:\n", scrtc->crtc_id);
350 		n += sunxi_drm_planes_show(buf + n, crtc->dev, crtc);
351 
352 		n += sprintf(buf + n, "\n");
353 	}
354 
355 	return n;
356 }*/
357 
sunxi_drm_crtc_in_use(struct sunxi_drm_crtc * scrtc)358 bool sunxi_drm_crtc_in_use(struct sunxi_drm_crtc *scrtc)
359 {
360 	struct drm_encoder *encoder;
361 	struct sunxi_drm_encoder *sencoder;
362 	struct drm_crtc *crtc = &scrtc->crtc;
363 	struct drm_device *dev = crtc->dev;
364 
365 	drm_for_each_encoder(encoder, dev) {
366 		sencoder = to_sunxi_encoder(encoder);
367 		if (encoder->crtc == crtc && sencoder->is_in_use(sencoder))
368 			return true;
369 	}
370 
371 	return false;
372 }
373 
sunxi_crtc_finish_page_flip(struct drm_device * dev,struct sunxi_drm_crtc * scrtc)374 static void sunxi_crtc_finish_page_flip(struct drm_device *dev,
375 					struct sunxi_drm_crtc *scrtc)
376 {
377 	unsigned long flags;
378 
379 	/*send the vblank of drm_crtc_state->event*/
380 	spin_lock_irqsave(&dev->event_lock, flags);
381 	if (scrtc->event) {
382 		drm_crtc_send_vblank_event(&scrtc->crtc, scrtc->event);
383 		drm_crtc_vblank_put(&scrtc->crtc);
384 		scrtc->event = NULL;
385 	}
386 	spin_unlock_irqrestore(&dev->event_lock, flags);
387 }
388 
sunxi_crtc_event_proc(int irq,void * parg)389 static irqreturn_t sunxi_crtc_event_proc(int irq, void *parg)
390 {
391 	int ret = 0;
392 	struct drm_crtc *crtc = (struct drm_crtc *)parg;
393 	struct sunxi_drm_crtc *scrtc = to_sunxi_crtc(crtc);
394 	struct sunxi_de_funcs *hw_funcs = scrtc->hw_funcs;
395 
396 	ret = hw_funcs->query_irq(scrtc->crtc_id);
397 	if (ret < 0) {
398 		DRM_ERROR("sunxi_de_query_irq FAILED!\n");
399 		goto out;
400 	}
401 
402 	ret = hw_funcs->event_proc(scrtc->crtc_id,
403 					atomic_read(&scrtc->update));
404 	if (ret < 0) {
405 		DRM_ERROR("sunxi_de_event_proc FAILED!\n");
406 		goto out;
407 	}
408 	atomic_set(&scrtc->update, 0);
409 
410 out:
411 	drm_crtc_handle_vblank(&scrtc->crtc);
412 	sunxi_crtc_finish_page_flip(crtc->dev, scrtc);
413 
414 	return IRQ_HANDLED;
415 }
416 
417 static bool
sunxi_crtc_encoder_is_supported(struct sunxi_drm_crtc * scrtc,struct sunxi_drm_encoder * senc)418 sunxi_crtc_encoder_is_supported(struct sunxi_drm_crtc *scrtc,
419 						struct sunxi_drm_encoder *senc)
420 {
421 	struct sunxi_de_funcs *hw_funcs = scrtc->hw_funcs;
422 
423 	return hw_funcs->is_support_tcon(scrtc->crtc_id, senc->encoder_id);
424 }
425 
426 static char crtc_irq_name[30][4];
sunxi_drm_crtc_irq_register(struct sunxi_drm_crtc * scrtc,unsigned int irq_no)427 static int sunxi_drm_crtc_irq_register(struct sunxi_drm_crtc *scrtc,
428 				unsigned int irq_no)
429 {
430 	int ret;
431 	struct drm_crtc *crtc = &scrtc->crtc;
432 
433 	sprintf(crtc_irq_name[scrtc->crtc_id], "sunxi-crtc%d", scrtc->crtc_id);
434 	DRM_INFO("irq name:%s, irq num:%d\n", crtc_irq_name[scrtc->crtc_id], irq_no);
435 
436 	ret = devm_request_irq(crtc->dev->dev, irq_no,
437 		sunxi_crtc_event_proc, IRQF_TRIGGER_NONE,
438 		crtc_irq_name[scrtc->crtc_id], crtc);
439 	if (ret < 0) {
440 		DRM_ERROR("sunxi crtc request irq failed\n");
441 		return -1;
442 	}
443 
444 	drm_crtc_vblank_on(crtc);
445 
446 	return 0;
447 }
448 
sunxi_drm_crtc_irq_unregister(struct sunxi_drm_crtc * scrtc,unsigned int irq_no)449 static void sunxi_drm_crtc_irq_unregister(struct sunxi_drm_crtc *scrtc,
450 				unsigned int irq_no)
451 {
452 	struct drm_crtc *crtc = &scrtc->crtc;
453 	devm_free_irq(crtc->dev->dev, irq_no, crtc);
454 
455 	if (crtc->state->event && !crtc->state->active) {
456 		spin_lock_irq(&crtc->dev->event_lock);
457 		drm_crtc_send_vblank_event(crtc, crtc->state->event);
458 		spin_unlock_irq(&crtc->dev->event_lock);
459 		crtc->state->event = NULL;
460 	}
461 }
462 
sunxi_crtc_destroy(struct drm_crtc * crtc)463 static void sunxi_crtc_destroy(struct drm_crtc *crtc)
464 {
465 	sunxi_drm_crtc_destroy(crtc);
466 }
467 
sunxi_crtc_reset(struct drm_crtc * crtc)468 static void sunxi_crtc_reset(struct drm_crtc *crtc)
469 {
470        drm_atomic_helper_crtc_reset(crtc);
471 }
472 
sunxi_crtc_atomic_get_property(struct drm_crtc * crtc,const struct drm_crtc_state * state,struct drm_property * property,uint64_t * val)473 int sunxi_crtc_atomic_get_property(struct drm_crtc *crtc,
474 				   const struct drm_crtc_state *state,
475 				   struct drm_property *property,
476 				   uint64_t *val)
477 {
478 	struct sunxi_drm_crtc *scrtc = to_sunxi_crtc(crtc);
479 
480 	if (scrtc->support_smbl == property) {
481 		*val = scrtc->hw_funcs->is_support_smbl(crtc->index);
482 		return 0;
483 	}
484 
485 	return -1;
486 }
487 
sunxi_crtc_atomic_enable(struct drm_crtc * crtc,struct drm_crtc_state * old_state)488 static void sunxi_crtc_atomic_enable(struct drm_crtc *crtc,
489 					struct drm_crtc_state *old_state)
490 {
491 	struct sunxi_drm_crtc *scrtc = to_sunxi_crtc(crtc);
492 	struct drm_crtc_state *new_state = crtc->state;
493 	struct sunxi_drm_connector *sconn;
494 	struct drm_mode_modeinfo modeinfo;
495 	int crtc_id, enc_id = 0, i;
496 
497 	struct disp_manager_data config;
498 	struct disp_manager_info *info = &config.config;
499 	struct sunxi_de_funcs *hw_funcs = scrtc->hw_funcs;
500 
501 #ifdef CONFIG_VIDEO_SUNXI_CAR_REVERSE
502 	if (sunxi_drm_get_force_plane_en())
503 		return;
504 #endif
505 
506 	DRM_DEBUG_DRIVER("[SUNXI-CRTC]%s\n", __func__);
507 	if (scrtc->enabled) {
508 		DRM_INFO("[SUNXI-CRTC]Warn: crtc has been enable,"
509 			"do NOT enable again\n");
510 		return;
511 	}
512 
513 	if ((!new_state->enable) || (!new_state->active)) {
514 		DRM_INFO("Warn: DRM do NOT want to enable or active crtc%d,"
515 			" so can NOT be enabled\n", scrtc->crtc_id);
516 		return;
517 	}
518 
519 	memset(&config, 0, sizeof(struct disp_manager_data));
520 	crtc_id = drm_crtc_index(new_state->crtc);
521 
522 	//sunxi_crtc_state_dump(new_state);
523 
524 	drm_property_blob_get(new_state->mode_blob);
525 	memcpy(&modeinfo, new_state->mode_blob->data,
526 					new_state->mode_blob->length);
527 	drm_property_blob_put(new_state->mode_blob);
528 
529 	config.flag = MANAGER_ALL_DIRTY;
530 	info->size.x = crtc->x;
531 	info->size.y = crtc->y;
532 	info->size.width = modeinfo.hdisplay;
533 	info->size.height = modeinfo.vdisplay;
534 
535 	/*check which connector will be attached to this crtc*/
536 	for (i = 0; i < sunxi_drm_connector_get_count(); i++) {
537 		if ((new_state->connector_mask >> i) & 0x1)
538 			break;
539 	}
540 
541 	sconn = sunxi_drm_connector_get_connector(i);
542 	if (!sconn) {
543 		DRM_ERROR("Get sunxi connector:%d failed!\n", i);
544 		return;
545 	}
546 
547 	for (i = 0; i < sunxi_drm_encoder_get_count(); i++) {
548 		if ((new_state->encoder_mask >> i) & 0x1) {
549 			enc_id = i;
550 			break;
551 		}
552 	}
553 
554 	info->color_space = DISP_BT601_F;
555 
556 	if (sconn->get_work_mode) {
557 		struct sunxi_connector_work_mode conn_work_mode;
558 
559 		sconn->get_work_mode(sconn, &conn_work_mode);
560 		info->cs = conn_work_mode.color_fmt;
561 	} else {
562 		info->cs = DISP_CSC_TYPE_RGB;
563 	}
564 
565 	if (info->cs == DISP_CSC_TYPE_RGB)
566 		info->color_range = DISP_COLOR_RANGE_0_255;
567 	else
568 		info->color_range = DISP_COLOR_RANGE_16_235;
569 
570 	//info->conn_type = sconn->type;
571 
572 	info->enable = true;
573 	info->disp_device = crtc_id;
574 
575 	info->hwdev_index = enc_id;
576 
577 	info->blank = false;
578 	info->de_freq = hw_funcs->get_freq(crtc_id);
579 	info->device_fps = modeinfo.vrefresh;
580 	info->eotf = DISP_EOTF_GAMMA22;
581 	info->data_bits = DISP_DATA_8BITS;
582 
583 	/*DRM_INFO("%s de_freq:%u  fps:%u\n", __func__,
584 		info->de_freq, info->fps);
585 	 */
586 
587 	if (hw_funcs->enable(crtc_id, &config) < 0)
588 		DRM_ERROR("de_al_mgr_apply FAILED\n");
589 	else
590 		DRM_INFO("%s success\n", __func__);
591 
592 	if (hw_funcs->is_use_irq(crtc_id)) {
593 		if (scrtc->irq_register(scrtc,
594 				hw_funcs->get_irq_no(crtc_id)) < 0) {
595 			DRM_ERROR("sunxi_drm_crtc_irq_register failed\n");
596 			return;
597 		}
598 	}
599 	scrtc->enabled = true;
600 	drm_crtc_vblank_on(crtc);
601 }
602 
sunxi_crtc_sw_enable(struct sunxi_drm_crtc * scrtc)603 static void sunxi_crtc_sw_enable(struct sunxi_drm_crtc *scrtc)
604 {
605 	int crtc_id;
606 	struct disp_manager_data config;
607 	struct drm_display_mode *mode;
608 	struct disp_manager_info *info = &config.config;
609 	struct drm_crtc *crtc = &scrtc->crtc;
610 	struct sunxi_drm_connector *sconn;
611 	struct drm_encoder *encoder;
612 	bool find = false;
613 	struct sunxi_de_funcs *hw_funcs = scrtc->hw_funcs;
614 
615 	memset(&config, 0, sizeof(struct disp_manager_data));
616 	crtc_id = drm_crtc_index(crtc);
617 
618 	/*In general, bootlogo is output through connector 0*/
619 	sconn = sunxi_drm_connector_get_connector(0);
620 	if (!sconn) {
621 		DRM_ERROR("Get sunxi connector 0 failed!\n");
622 		return;
623 	}
624 
625 	if (!crtc->state) {
626 		DRM_ERROR("crtc:%d has no state\n", crtc_id);
627 		return;
628 	}
629 	mode = &crtc->state->mode;
630 
631 	config.flag = MANAGER_ALL_DIRTY;
632 	info->size.x = crtc->x;
633 	info->size.y = crtc->y;
634 	info->size.width = mode->hdisplay;
635 	info->size.height = mode->vdisplay;
636 
637 	info->color_space = DISP_BT601_F;
638 
639 	if (sconn->get_work_mode) {
640 		struct sunxi_connector_work_mode conn_work_mode;
641 
642 		sconn->get_work_mode(sconn, &conn_work_mode);
643 		info->cs = conn_work_mode.color_fmt;
644 	} else {
645 		info->cs = DISP_CSC_TYPE_RGB;
646 	}
647 
648 	if (info->cs == DISP_CSC_TYPE_RGB)
649 		info->color_range = DISP_COLOR_RANGE_0_255;
650 	else
651 		info->color_range = DISP_COLOR_RANGE_16_235;
652 
653 	//info->conn_type = sconn->type;
654 
655 	info->enable = true;
656 	info->disp_device = crtc_id;
657 
658 	drm_for_each_encoder(encoder, crtc->dev) {
659 		if (encoder->crtc == crtc) {
660 			find = true;
661 			break;
662 		}
663 	}
664 
665 	if (!find) {
666 		DRM_ERROR("crtc:%d has NO attaching encoder!\n", crtc->index);
667 		return;
668 	}
669 
670 	info->hwdev_index = encoder->index;
671 
672 	info->blank = false;
673 	info->de_freq = hw_funcs->get_freq(crtc_id);
674 	//info->device_fps = mode->vrefresh;
675 	info->eotf = DISP_EOTF_GAMMA22;
676 	info->data_bits = DISP_DATA_8BITS;
677 
678 	if (hw_funcs->enable(crtc_id, &config) < 0)
679 		DRM_ERROR("de_al_mgr_apply FAILED\n");
680 	else
681 		DRM_INFO("%s success\n", __func__);
682 
683 	if (hw_funcs->is_use_irq(crtc_id)) {
684 		if (scrtc->irq_register(scrtc,
685 				hw_funcs->get_irq_no(crtc_id)) < 0) {
686 			DRM_ERROR("sunxi_drm_crtc_irq_register failed\n");
687 			return;
688 		}
689 	}
690 	scrtc->enabled = true;
691 }
692 
sunxi_crtc_atomic_disable(struct drm_crtc * crtc,struct drm_crtc_state * old_state)693 static void sunxi_crtc_atomic_disable(struct drm_crtc *crtc,
694 					struct drm_crtc_state *old_state)
695 
696 {
697 	struct sunxi_drm_crtc *scrtc = to_sunxi_crtc(crtc);
698 	struct drm_crtc_state *new_state = crtc->state;
699 	struct disp_manager_data config;
700 	struct disp_manager_info *info = &config.config;
701 	int crtc_id;
702 	struct sunxi_de_funcs *hw_funcs = scrtc->hw_funcs;
703 
704 	DRM_INFO("[SUNXI-CRTC]%s\n", __func__);
705 	drm_crtc_vblank_off(crtc);
706 	if (!scrtc->enabled) {
707 		DRM_ERROR("%s: crtc has been disable\n", __func__);
708 		return;
709 	}
710 
711 	memset(&config, 0, sizeof(struct disp_manager_data));
712 	crtc_id = drm_crtc_index(new_state->crtc);
713 	scrtc->enabled = false;
714 
715 	if (hw_funcs->is_use_irq(crtc_id))
716 		scrtc->irq_unregister(scrtc, hw_funcs->get_irq_no(crtc_id));
717 
718 	config.flag = MANAGER_ALL_DIRTY;
719 	info->enable = false;
720 	info->blank = true;
721 
722 	hw_funcs->disable(crtc_id, &config);
723 
724 	if (crtc->state->event && !crtc->state->active) {
725 		spin_lock_irq(&crtc->dev->event_lock);
726 		drm_crtc_send_vblank_event(crtc, crtc->state->event);
727 		spin_unlock_irq(&crtc->dev->event_lock);
728 
729 		crtc->state->event = NULL;
730 	}
731 
732 	return;
733 }
734 
sunxi_crtc_atomic_begin(struct drm_crtc * crtc,struct drm_crtc_state * old_crtc_state)735 static void sunxi_crtc_atomic_begin(struct drm_crtc *crtc,
736 			     struct drm_crtc_state *old_crtc_state)
737 {
738 	struct sunxi_drm_crtc *scrtc = to_sunxi_crtc(crtc);
739 	struct drm_device *dev = crtc->dev;
740 	unsigned long flags;
741 
742 	DRM_DEBUG_DRIVER("[SUNXI-CRTC]%s\n", __func__);
743 
744 	atomic_set(&scrtc->update, 0);
745 
746 	if (crtc->state->event) {
747 		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
748 
749 		spin_lock_irqsave(&dev->event_lock, flags);
750 		scrtc->event = crtc->state->event;
751 		spin_unlock_irqrestore(&dev->event_lock, flags);
752 		crtc->state->event = NULL;
753 	}
754 
755 	return;
756 }
757 
sunxi_crtc_atomic_flush(struct drm_crtc * crtc,struct drm_crtc_state * old_crtc_state)758 static void sunxi_crtc_atomic_flush(struct drm_crtc *crtc,
759 			     struct drm_crtc_state *old_crtc_state)
760 {
761 	struct sunxi_drm_crtc *scrtc = to_sunxi_crtc(crtc);
762 	struct drm_pending_vblank_event *event = crtc->state->event;
763 
764 	DRM_DEBUG_DRIVER("[SUNXI-CRTC]%s\n", __func__);
765 	if (event) {
766 		crtc->state->event = NULL;
767 
768 		spin_lock_irq(&crtc->dev->event_lock);
769 		if (drm_crtc_vblank_get(crtc) == 0)
770 			drm_crtc_arm_vblank_event(crtc, event);
771 		else
772 			drm_crtc_send_vblank_event(crtc, event);
773 		spin_unlock_irq(&crtc->dev->event_lock);
774 	}
775 
776 	atomic_set(&scrtc->update, 1);
777 
778 	return;
779 }
780 
sunxi_drm_crtc_enable_vblank(struct drm_crtc * crtc)781 int sunxi_drm_crtc_enable_vblank(struct drm_crtc *crtc)
782 {
783 	return 0;
784 }
785 
786 static const struct drm_crtc_funcs sunxi_crtc_funcs = {
787 	.set_config		= drm_atomic_helper_set_config,
788 	.page_flip		= drm_atomic_helper_page_flip,
789 	.destroy		= sunxi_crtc_destroy,
790 	.reset			= drm_atomic_helper_crtc_reset,
791 	.atomic_get_property	= sunxi_crtc_atomic_get_property,
792 	.atomic_duplicate_state	= drm_atomic_helper_crtc_duplicate_state,
793 	.atomic_destroy_state	= drm_atomic_helper_crtc_destroy_state,
794 	.enable_vblank	= sunxi_drm_crtc_enable_vblank,
795 };
796 
797 static const struct drm_crtc_helper_funcs sunxi_crtc_helper_funcs = {
798 	.atomic_enable	= sunxi_crtc_atomic_enable,
799 	.atomic_disable	= sunxi_crtc_atomic_disable,
800 	//.atomic_begin	= sunxi_crtc_atomic_begin,
801 	.atomic_flush	= sunxi_crtc_atomic_flush,
802 };
803 
804 
805 /*init all of the crtcs*/
sunxi_drm_crtc_init(struct drm_device * dev)806 int sunxi_drm_crtc_init(struct drm_device *dev)
807 {
808 	int i, j, ret, max_crtc, max_plane;
809 
810 	int max_vi_layers;
811 	struct sunxi_de_funcs *hw_funcs;
812 
813 	/*The max counts of crtc is decided by connector counts*/
814 	max_crtc = sunxi_drm_get_connector_count();
815 	if (!max_crtc)
816 		max_crtc = 1; /*There must be at least one crtc*/
817 
818 	sunxi_crtc = kzalloc(
819 			max_crtc * sizeof(struct sunxi_drm_crtc), GFP_KERNEL);
820 	if (!sunxi_crtc) {
821 		DRM_ERROR("can NOT allocate memory for sunxi_crtc\n");
822 		goto crtc_err;
823 	}
824 	sunxi_crtc_cnt = max_crtc;
825 
826 	for (i = 0; i < max_crtc; i++) {
827 		sunxi_crtc[i].crtc_id = i;
828 		mutex_init(&sunxi_crtc[i].update_reg_lock);
829 
830 		hw_funcs = sunxi_de_get_funcs(i);
831 		sunxi_crtc[i].hw_funcs = hw_funcs;
832 
833 /*init planes of crtc*/
834 		max_plane = hw_funcs->get_layer_count(i);
835 		sunxi_crtc[i].plane_num = max_plane;
836 		sunxi_crtc[i].plane = kzalloc(max_plane
837 				* sizeof(struct sunxi_drm_plane),
838 							GFP_KERNEL);
839 		if (!sunxi_crtc[i].plane) {
840 			DRM_ERROR("can NOT allocate mem for planes of "
841 						"crtc:%d\n", i);
842 			goto crtc_err;
843 		}
844 
845 		max_vi_layers = hw_funcs->get_vi_layer_count(i);
846 		sunxi_crtc[i].overlay_plane_num = max_vi_layers;
847 
848 		for (j = 0; j < max_plane; j++) {
849 			/*check if it is the first ui layer*/
850 			if ((j - max_vi_layers) == 0) {
851 				ret = sunxi_drm_plane_init(dev,
852 					&sunxi_crtc[i].plane[j], i, j,
853 					DRM_PLANE_TYPE_PRIMARY);
854 			} else {
855 				ret = sunxi_drm_plane_init(dev,
856 					&sunxi_crtc[i].plane[j],
857 					i, j, DRM_PLANE_TYPE_OVERLAY);
858 			}
859 
860 			if (ret < 0) {
861 				DRM_ERROR("sunxi crtc:%d plane:%d init failed",
862 					i, j);
863 				goto crtc_err;
864 			}
865 			DRM_DEBUG_DRIVER("INIT crtc:%d plane:%d success\n", i, j);
866 		}
867 
868 /*init curtain crtc with a default primary plane*/
869 		ret = drm_crtc_init_with_planes(dev, &sunxi_crtc[i].crtc,
870 				&sunxi_crtc[i].plane[max_vi_layers].plane,
871 				NULL, &sunxi_crtc_funcs, "sunxi-crtc%d", i);
872 		if (ret < 0) {
873 			DRM_ERROR("drm_crtc_init_with_planes failed\n");
874 			goto crtc_err;
875 		}
876 
877 		drm_crtc_helper_add(&sunxi_crtc[i].crtc,
878 				&sunxi_crtc_helper_funcs);
879 
880 		sunxi_crtc_reset(&sunxi_crtc[i].crtc);
881 
882 		sunxi_crtc[i].encoder_is_supported = sunxi_crtc_encoder_is_supported;
883 		sunxi_crtc[i].is_in_use = sunxi_drm_crtc_in_use;
884 		sunxi_crtc[i].sw_enable = sunxi_crtc_sw_enable;
885 		sunxi_crtc[i].irq_register = sunxi_drm_crtc_irq_register;
886 		sunxi_crtc[i].irq_unregister = sunxi_drm_crtc_irq_unregister;
887 
888 		sunxi_crtc[i].support_smbl =
889 			drm_property_create_bool(dev, DRM_MODE_PROP_IMMUTABLE,
890 					"support_smbl");
891 		if (!sunxi_crtc[i].support_smbl)
892 			return -ENOMEM;
893 
894 		DRM_DEBUG_DRIVER("INIT crtc:%d success\n", i);
895 	}
896 
897 	return 0;
898 
899 crtc_err:
900 
901 	if (sunxi_crtc) {
902 		for (i = 0; i < sunxi_crtc_cnt; i++) {
903 			drm_crtc_cleanup(&sunxi_crtc[i].crtc);
904 
905 			max_plane = sunxi_crtc[i].plane_num;
906 			for (j = 0; j < max_plane; j++)
907 				drm_plane_cleanup(&sunxi_crtc[i].plane[j].plane);
908 			kfree(sunxi_crtc[i].plane);
909 		}
910 		kfree(sunxi_crtc);
911 	}
912 	DRM_ERROR("crtc init failed\n");
913 	return -1;
914 }
915 
916 /*destroy all of the crtcs*/
sunxi_drm_crtc_exit(struct drm_device * dev)917 void sunxi_drm_crtc_exit(struct drm_device *dev)
918 {
919 	int i, j, max_plane;
920 
921 	if (sunxi_crtc) {
922 		for (i = 0; i < sunxi_crtc_cnt; i++) {
923 			if (!sunxi_crtc)
924 				break;
925 			drm_crtc_cleanup(&sunxi_crtc[i].crtc);
926 
927 			max_plane = sunxi_crtc[i].plane_num;
928 			for (j = 0; j < max_plane; j++)
929 				drm_plane_cleanup(&sunxi_crtc[i].plane[j].plane);
930 
931 			kfree(sunxi_crtc[i].plane);
932 			sunxi_crtc[i].plane = NULL;
933 		}
934 
935 		kfree(sunxi_crtc);
936 		sunxi_crtc = NULL;
937 	}
938 }
939 
940 /*destroy curtain crtc*/
sunxi_drm_crtc_destroy(struct drm_crtc * drm_crtc)941 void sunxi_drm_crtc_destroy(struct drm_crtc *drm_crtc)
942 {
943 	int j, max_plane;
944 	struct sunxi_drm_crtc *crtc = to_sunxi_crtc(drm_crtc);
945 
946 	drm_crtc_cleanup(drm_crtc);
947 
948 	max_plane = crtc->plane_num;
949 	for (j = 0; j < max_plane; j++)
950 		drm_plane_cleanup(&crtc->plane[j].plane);
951 
952 	kfree(crtc->plane);
953 	crtc->plane = NULL;
954 }
955