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