• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* exynos_drm_encoder.c
2  *
3  * Copyright (c) 2011 Samsung Electronics Co., Ltd.
4  * Authors:
5  *	Inki Dae <inki.dae@samsung.com>
6  *	Joonyoung Shim <jy0922.shim@samsung.com>
7  *	Seung-Woo Kim <sw0312.kim@samsung.com>
8  *
9  * This program is free software; you can redistribute  it and/or modify it
10  * under  the terms of  the GNU General  Public License as published by the
11  * Free Software Foundation;  either version 2 of the  License, or (at your
12  * option) any later version.
13  */
14 
15 #include <drm/drmP.h>
16 #include <drm/drm_crtc_helper.h>
17 
18 #include "exynos_drm_drv.h"
19 #include "exynos_drm_encoder.h"
20 #include "exynos_drm_connector.h"
21 
22 #define to_exynos_encoder(x)	container_of(x, struct exynos_drm_encoder,\
23 				drm_encoder)
24 
25 /*
26  * exynos specific encoder structure.
27  *
28  * @drm_encoder: encoder object.
29  * @manager: specific encoder has its own manager to control a hardware
30  *	appropriately and we can access a hardware drawing on this manager.
31  * @dpms: store the encoder dpms value.
32  * @updated: indicate whether overlay data updating is needed or not.
33  */
34 struct exynos_drm_encoder {
35 	struct drm_crtc			*old_crtc;
36 	struct drm_encoder		drm_encoder;
37 	struct exynos_drm_manager	*manager;
38 	int				dpms;
39 	bool				updated;
40 };
41 
exynos_drm_connector_power(struct drm_encoder * encoder,int mode)42 static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode)
43 {
44 	struct drm_device *dev = encoder->dev;
45 	struct drm_connector *connector;
46 
47 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
48 		if (exynos_drm_best_encoder(connector) == encoder) {
49 			DRM_DEBUG_KMS("connector[%d] dpms[%d]\n",
50 					connector->base.id, mode);
51 
52 			exynos_drm_display_power(connector, mode);
53 		}
54 	}
55 }
56 
exynos_drm_encoder_dpms(struct drm_encoder * encoder,int mode)57 static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
58 {
59 	struct drm_device *dev = encoder->dev;
60 	struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
61 	struct exynos_drm_manager_ops *manager_ops = manager->ops;
62 	struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
63 
64 	DRM_DEBUG_KMS("%s, encoder dpms: %d\n", __FILE__, mode);
65 
66 	if (exynos_encoder->dpms == mode) {
67 		DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n");
68 		return;
69 	}
70 
71 	mutex_lock(&dev->struct_mutex);
72 
73 	switch (mode) {
74 	case DRM_MODE_DPMS_ON:
75 		if (manager_ops && manager_ops->apply)
76 			if (!exynos_encoder->updated)
77 				manager_ops->apply(manager->dev);
78 
79 		exynos_drm_connector_power(encoder, mode);
80 		exynos_encoder->dpms = mode;
81 		break;
82 	case DRM_MODE_DPMS_STANDBY:
83 	case DRM_MODE_DPMS_SUSPEND:
84 	case DRM_MODE_DPMS_OFF:
85 		exynos_drm_connector_power(encoder, mode);
86 		exynos_encoder->dpms = mode;
87 		exynos_encoder->updated = false;
88 		break;
89 	default:
90 		DRM_ERROR("unspecified mode %d\n", mode);
91 		break;
92 	}
93 
94 	mutex_unlock(&dev->struct_mutex);
95 }
96 
97 static bool
exynos_drm_encoder_mode_fixup(struct drm_encoder * encoder,const struct drm_display_mode * mode,struct drm_display_mode * adjusted_mode)98 exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder,
99 			       const struct drm_display_mode *mode,
100 			       struct drm_display_mode *adjusted_mode)
101 {
102 	struct drm_device *dev = encoder->dev;
103 	struct drm_connector *connector;
104 	struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
105 	struct exynos_drm_manager_ops *manager_ops = manager->ops;
106 
107 	DRM_DEBUG_KMS("%s\n", __FILE__);
108 
109 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
110 		if (connector->encoder == encoder)
111 			if (manager_ops && manager_ops->mode_fixup)
112 				manager_ops->mode_fixup(manager->dev, connector,
113 							mode, adjusted_mode);
114 	}
115 
116 	return true;
117 }
118 
disable_plane_to_crtc(struct drm_device * dev,struct drm_crtc * old_crtc,struct drm_crtc * new_crtc)119 static void disable_plane_to_crtc(struct drm_device *dev,
120 						struct drm_crtc *old_crtc,
121 						struct drm_crtc *new_crtc)
122 {
123 	struct drm_plane *plane;
124 
125 	/*
126 	 * if old_crtc isn't same as encoder->crtc then it means that
127 	 * user changed crtc id to another one so the plane to old_crtc
128 	 * should be disabled and plane->crtc should be set to new_crtc
129 	 * (encoder->crtc)
130 	 */
131 	list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
132 		if (plane->crtc == old_crtc) {
133 			/*
134 			 * do not change below call order.
135 			 *
136 			 * plane->funcs->disable_plane call checks
137 			 * if encoder->crtc is same as plane->crtc and if same
138 			 * then overlay_ops->disable callback will be called
139 			 * to diasble current hw overlay so plane->crtc should
140 			 * have new_crtc because new_crtc was set to
141 			 * encoder->crtc in advance.
142 			 */
143 			plane->crtc = new_crtc;
144 			plane->funcs->disable_plane(plane);
145 		}
146 	}
147 }
148 
exynos_drm_encoder_mode_set(struct drm_encoder * encoder,struct drm_display_mode * mode,struct drm_display_mode * adjusted_mode)149 static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder,
150 					 struct drm_display_mode *mode,
151 					 struct drm_display_mode *adjusted_mode)
152 {
153 	struct drm_device *dev = encoder->dev;
154 	struct drm_connector *connector;
155 	struct exynos_drm_manager *manager;
156 	struct exynos_drm_manager_ops *manager_ops;
157 
158 	DRM_DEBUG_KMS("%s\n", __FILE__);
159 
160 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
161 		if (connector->encoder == encoder) {
162 			struct exynos_drm_encoder *exynos_encoder;
163 
164 			exynos_encoder = to_exynos_encoder(encoder);
165 
166 			if (exynos_encoder->old_crtc != encoder->crtc &&
167 					exynos_encoder->old_crtc) {
168 
169 				/*
170 				 * disable a plane to old crtc and change
171 				 * crtc of the plane to new one.
172 				 */
173 				disable_plane_to_crtc(dev,
174 						exynos_encoder->old_crtc,
175 						encoder->crtc);
176 			}
177 
178 			manager = exynos_drm_get_manager(encoder);
179 			manager_ops = manager->ops;
180 
181 			if (manager_ops && manager_ops->mode_set)
182 				manager_ops->mode_set(manager->dev,
183 							adjusted_mode);
184 
185 			exynos_encoder->old_crtc = encoder->crtc;
186 		}
187 	}
188 }
189 
exynos_drm_encoder_prepare(struct drm_encoder * encoder)190 static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)
191 {
192 	DRM_DEBUG_KMS("%s\n", __FILE__);
193 
194 	/* drm framework doesn't check NULL. */
195 }
196 
exynos_drm_encoder_commit(struct drm_encoder * encoder)197 static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
198 {
199 	struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
200 	struct exynos_drm_manager *manager = exynos_encoder->manager;
201 	struct exynos_drm_manager_ops *manager_ops = manager->ops;
202 
203 	DRM_DEBUG_KMS("%s\n", __FILE__);
204 
205 	if (manager_ops && manager_ops->commit)
206 		manager_ops->commit(manager->dev);
207 
208 	/*
209 	 * this will avoid one issue that overlay data is updated to
210 	 * real hardware two times.
211 	 * And this variable will be used to check if the data was
212 	 * already updated or not by exynos_drm_encoder_dpms function.
213 	 */
214 	exynos_encoder->updated = true;
215 
216 	/*
217 	 * In case of setcrtc, there is no way to update encoder's dpms
218 	 * so update it here.
219 	 */
220 	exynos_encoder->dpms = DRM_MODE_DPMS_ON;
221 }
222 
exynos_drm_encoder_complete_scanout(struct drm_framebuffer * fb)223 void exynos_drm_encoder_complete_scanout(struct drm_framebuffer *fb)
224 {
225 	struct exynos_drm_encoder *exynos_encoder;
226 	struct exynos_drm_manager_ops *ops;
227 	struct drm_device *dev = fb->dev;
228 	struct drm_encoder *encoder;
229 
230 	/*
231 	 * make sure that overlay data are updated to real hardware
232 	 * for all encoders.
233 	 */
234 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
235 		exynos_encoder = to_exynos_encoder(encoder);
236 		ops = exynos_encoder->manager->ops;
237 
238 		/*
239 		 * wait for vblank interrupt
240 		 * - this makes sure that overlay data are updated to
241 		 *	real hardware.
242 		 */
243 		if (ops->wait_for_vblank)
244 			ops->wait_for_vblank(exynos_encoder->manager->dev);
245 	}
246 }
247 
248 
exynos_drm_encoder_disable(struct drm_encoder * encoder)249 static void exynos_drm_encoder_disable(struct drm_encoder *encoder)
250 {
251 	struct drm_plane *plane;
252 	struct drm_device *dev = encoder->dev;
253 
254 	exynos_drm_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
255 
256 	/* all planes connected to this encoder should be also disabled. */
257 	list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
258 		if (plane->crtc == encoder->crtc)
259 			plane->funcs->disable_plane(plane);
260 	}
261 }
262 
263 static struct drm_encoder_helper_funcs exynos_encoder_helper_funcs = {
264 	.dpms		= exynos_drm_encoder_dpms,
265 	.mode_fixup	= exynos_drm_encoder_mode_fixup,
266 	.mode_set	= exynos_drm_encoder_mode_set,
267 	.prepare	= exynos_drm_encoder_prepare,
268 	.commit		= exynos_drm_encoder_commit,
269 	.disable	= exynos_drm_encoder_disable,
270 };
271 
exynos_drm_encoder_destroy(struct drm_encoder * encoder)272 static void exynos_drm_encoder_destroy(struct drm_encoder *encoder)
273 {
274 	struct exynos_drm_encoder *exynos_encoder =
275 		to_exynos_encoder(encoder);
276 
277 	DRM_DEBUG_KMS("%s\n", __FILE__);
278 
279 	exynos_encoder->manager->pipe = -1;
280 
281 	drm_encoder_cleanup(encoder);
282 	kfree(exynos_encoder);
283 }
284 
285 static struct drm_encoder_funcs exynos_encoder_funcs = {
286 	.destroy = exynos_drm_encoder_destroy,
287 };
288 
exynos_drm_encoder_clones(struct drm_encoder * encoder)289 static unsigned int exynos_drm_encoder_clones(struct drm_encoder *encoder)
290 {
291 	struct drm_encoder *clone;
292 	struct drm_device *dev = encoder->dev;
293 	struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
294 	struct exynos_drm_display_ops *display_ops =
295 				exynos_encoder->manager->display_ops;
296 	unsigned int clone_mask = 0;
297 	int cnt = 0;
298 
299 	list_for_each_entry(clone, &dev->mode_config.encoder_list, head) {
300 		switch (display_ops->type) {
301 		case EXYNOS_DISPLAY_TYPE_LCD:
302 		case EXYNOS_DISPLAY_TYPE_HDMI:
303 		case EXYNOS_DISPLAY_TYPE_VIDI:
304 			clone_mask |= (1 << (cnt++));
305 			break;
306 		default:
307 			continue;
308 		}
309 	}
310 
311 	return clone_mask;
312 }
313 
exynos_drm_encoder_setup(struct drm_device * dev)314 void exynos_drm_encoder_setup(struct drm_device *dev)
315 {
316 	struct drm_encoder *encoder;
317 
318 	DRM_DEBUG_KMS("%s\n", __FILE__);
319 
320 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
321 		encoder->possible_clones = exynos_drm_encoder_clones(encoder);
322 }
323 
324 struct drm_encoder *
exynos_drm_encoder_create(struct drm_device * dev,struct exynos_drm_manager * manager,unsigned int possible_crtcs)325 exynos_drm_encoder_create(struct drm_device *dev,
326 			   struct exynos_drm_manager *manager,
327 			   unsigned int possible_crtcs)
328 {
329 	struct drm_encoder *encoder;
330 	struct exynos_drm_encoder *exynos_encoder;
331 
332 	DRM_DEBUG_KMS("%s\n", __FILE__);
333 
334 	if (!manager || !possible_crtcs)
335 		return NULL;
336 
337 	if (!manager->dev)
338 		return NULL;
339 
340 	exynos_encoder = kzalloc(sizeof(*exynos_encoder), GFP_KERNEL);
341 	if (!exynos_encoder) {
342 		DRM_ERROR("failed to allocate encoder\n");
343 		return NULL;
344 	}
345 
346 	exynos_encoder->dpms = DRM_MODE_DPMS_OFF;
347 	exynos_encoder->manager = manager;
348 	encoder = &exynos_encoder->drm_encoder;
349 	encoder->possible_crtcs = possible_crtcs;
350 
351 	DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
352 
353 	drm_encoder_init(dev, encoder, &exynos_encoder_funcs,
354 			DRM_MODE_ENCODER_TMDS);
355 
356 	drm_encoder_helper_add(encoder, &exynos_encoder_helper_funcs);
357 
358 	DRM_DEBUG_KMS("encoder has been created\n");
359 
360 	return encoder;
361 }
362 
exynos_drm_get_manager(struct drm_encoder * encoder)363 struct exynos_drm_manager *exynos_drm_get_manager(struct drm_encoder *encoder)
364 {
365 	return to_exynos_encoder(encoder)->manager;
366 }
367 
exynos_drm_fn_encoder(struct drm_crtc * crtc,void * data,void (* fn)(struct drm_encoder *,void *))368 void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data,
369 			    void (*fn)(struct drm_encoder *, void *))
370 {
371 	struct drm_device *dev = crtc->dev;
372 	struct drm_encoder *encoder;
373 	struct exynos_drm_private *private = dev->dev_private;
374 	struct exynos_drm_manager *manager;
375 
376 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
377 		/*
378 		 * if crtc is detached from encoder, check pipe,
379 		 * otherwise check crtc attached to encoder
380 		 */
381 		if (!encoder->crtc) {
382 			manager = to_exynos_encoder(encoder)->manager;
383 			if (manager->pipe < 0 ||
384 					private->crtc[manager->pipe] != crtc)
385 				continue;
386 		} else {
387 			if (encoder->crtc != crtc)
388 				continue;
389 		}
390 
391 		fn(encoder, data);
392 	}
393 }
394 
exynos_drm_enable_vblank(struct drm_encoder * encoder,void * data)395 void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data)
396 {
397 	struct exynos_drm_manager *manager =
398 		to_exynos_encoder(encoder)->manager;
399 	struct exynos_drm_manager_ops *manager_ops = manager->ops;
400 	int crtc = *(int *)data;
401 
402 	if (manager->pipe != crtc)
403 		return;
404 
405 	if (manager_ops->enable_vblank)
406 		manager_ops->enable_vblank(manager->dev);
407 }
408 
exynos_drm_disable_vblank(struct drm_encoder * encoder,void * data)409 void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data)
410 {
411 	struct exynos_drm_manager *manager =
412 		to_exynos_encoder(encoder)->manager;
413 	struct exynos_drm_manager_ops *manager_ops = manager->ops;
414 	int crtc = *(int *)data;
415 
416 	if (manager->pipe != crtc)
417 		return;
418 
419 	if (manager_ops->disable_vblank)
420 		manager_ops->disable_vblank(manager->dev);
421 }
422 
exynos_drm_encoder_crtc_dpms(struct drm_encoder * encoder,void * data)423 void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)
424 {
425 	struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
426 	struct exynos_drm_manager *manager = exynos_encoder->manager;
427 	struct exynos_drm_manager_ops *manager_ops = manager->ops;
428 	int mode = *(int *)data;
429 
430 	DRM_DEBUG_KMS("%s\n", __FILE__);
431 
432 	if (manager_ops && manager_ops->dpms)
433 		manager_ops->dpms(manager->dev, mode);
434 
435 	/*
436 	 * if this condition is ok then it means that the crtc is already
437 	 * detached from encoder and last function for detaching is properly
438 	 * done, so clear pipe from manager to prevent repeated call.
439 	 */
440 	if (mode > DRM_MODE_DPMS_ON) {
441 		if (!encoder->crtc)
442 			manager->pipe = -1;
443 	}
444 }
445 
exynos_drm_encoder_crtc_pipe(struct drm_encoder * encoder,void * data)446 void exynos_drm_encoder_crtc_pipe(struct drm_encoder *encoder, void *data)
447 {
448 	struct exynos_drm_manager *manager =
449 		to_exynos_encoder(encoder)->manager;
450 	int pipe = *(int *)data;
451 
452 	DRM_DEBUG_KMS("%s\n", __FILE__);
453 
454 	/*
455 	 * when crtc is detached from encoder, this pipe is used
456 	 * to select manager operation
457 	 */
458 	manager->pipe = pipe;
459 }
460 
exynos_drm_encoder_plane_mode_set(struct drm_encoder * encoder,void * data)461 void exynos_drm_encoder_plane_mode_set(struct drm_encoder *encoder, void *data)
462 {
463 	struct exynos_drm_manager *manager =
464 		to_exynos_encoder(encoder)->manager;
465 	struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
466 	struct exynos_drm_overlay *overlay = data;
467 
468 	DRM_DEBUG_KMS("%s\n", __FILE__);
469 
470 	if (overlay_ops && overlay_ops->mode_set)
471 		overlay_ops->mode_set(manager->dev, overlay);
472 }
473 
exynos_drm_encoder_plane_commit(struct drm_encoder * encoder,void * data)474 void exynos_drm_encoder_plane_commit(struct drm_encoder *encoder, void *data)
475 {
476 	struct exynos_drm_manager *manager =
477 		to_exynos_encoder(encoder)->manager;
478 	struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
479 	int zpos = DEFAULT_ZPOS;
480 
481 	DRM_DEBUG_KMS("%s\n", __FILE__);
482 
483 	if (data)
484 		zpos = *(int *)data;
485 
486 	if (overlay_ops && overlay_ops->commit)
487 		overlay_ops->commit(manager->dev, zpos);
488 }
489 
exynos_drm_encoder_plane_enable(struct drm_encoder * encoder,void * data)490 void exynos_drm_encoder_plane_enable(struct drm_encoder *encoder, void *data)
491 {
492 	struct exynos_drm_manager *manager =
493 		to_exynos_encoder(encoder)->manager;
494 	struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
495 	int zpos = DEFAULT_ZPOS;
496 
497 	DRM_DEBUG_KMS("%s\n", __FILE__);
498 
499 	if (data)
500 		zpos = *(int *)data;
501 
502 	if (overlay_ops && overlay_ops->enable)
503 		overlay_ops->enable(manager->dev, zpos);
504 }
505 
exynos_drm_encoder_plane_disable(struct drm_encoder * encoder,void * data)506 void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data)
507 {
508 	struct exynos_drm_manager *manager =
509 		to_exynos_encoder(encoder)->manager;
510 	struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
511 	int zpos = DEFAULT_ZPOS;
512 
513 	DRM_DEBUG_KMS("%s\n", __FILE__);
514 
515 	if (data)
516 		zpos = *(int *)data;
517 
518 	if (overlay_ops && overlay_ops->disable)
519 		overlay_ops->disable(manager->dev, zpos);
520 }
521