aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/exynos/exynos_drm_crtc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_crtc.c')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.c89
1 files changed, 70 insertions, 19 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index ee43cc22085..e3861ac4929 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -34,7 +34,6 @@
34#include "exynos_drm_fb.h" 34#include "exynos_drm_fb.h"
35#include "exynos_drm_encoder.h" 35#include "exynos_drm_encoder.h"
36#include "exynos_drm_gem.h" 36#include "exynos_drm_gem.h"
37#include "exynos_drm_buf.h"
38 37
39#define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc,\ 38#define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc,\
40 drm_crtc) 39 drm_crtc)
@@ -52,11 +51,13 @@
52 * drm framework doesn't support multiple irq yet. 51 * drm framework doesn't support multiple irq yet.
53 * we can refer to the crtc to current hardware interrupt occured through 52 * we can refer to the crtc to current hardware interrupt occured through
54 * this pipe value. 53 * this pipe value.
54 * @dpms: store the crtc dpms value
55 */ 55 */
56struct exynos_drm_crtc { 56struct exynos_drm_crtc {
57 struct drm_crtc drm_crtc; 57 struct drm_crtc drm_crtc;
58 struct exynos_drm_overlay overlay; 58 struct exynos_drm_overlay overlay;
59 unsigned int pipe; 59 unsigned int pipe;
60 unsigned int dpms;
60}; 61};
61 62
62static void exynos_drm_crtc_apply(struct drm_crtc *crtc) 63static void exynos_drm_crtc_apply(struct drm_crtc *crtc)
@@ -78,19 +79,23 @@ int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
78 struct exynos_drm_gem_buf *buffer; 79 struct exynos_drm_gem_buf *buffer;
79 unsigned int actual_w; 80 unsigned int actual_w;
80 unsigned int actual_h; 81 unsigned int actual_h;
82 int nr = exynos_drm_format_num_buffers(fb->pixel_format);
83 int i;
84
85 for (i = 0; i < nr; i++) {
86 buffer = exynos_drm_fb_buffer(fb, i);
87 if (!buffer) {
88 DRM_LOG_KMS("buffer is null\n");
89 return -EFAULT;
90 }
81 91
82 buffer = exynos_drm_fb_get_buf(fb); 92 overlay->dma_addr[i] = buffer->dma_addr;
83 if (!buffer) { 93 overlay->vaddr[i] = buffer->kvaddr;
84 DRM_LOG_KMS("buffer is null.\n");
85 return -EFAULT;
86 }
87
88 overlay->dma_addr = buffer->dma_addr;
89 overlay->vaddr = buffer->kvaddr;
90 94
91 DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n", 95 DRM_DEBUG_KMS("buffer: %d, vaddr = 0x%lx, dma_addr = 0x%lx\n",
92 (unsigned long)overlay->vaddr, 96 i, (unsigned long)overlay->vaddr[i],
93 (unsigned long)overlay->dma_addr); 97 (unsigned long)overlay->dma_addr[i]);
98 }
94 99
95 actual_w = min((mode->hdisplay - pos->crtc_x), pos->crtc_w); 100 actual_w = min((mode->hdisplay - pos->crtc_x), pos->crtc_w);
96 actual_h = min((mode->vdisplay - pos->crtc_y), pos->crtc_h); 101 actual_h = min((mode->vdisplay - pos->crtc_y), pos->crtc_h);
@@ -101,7 +106,8 @@ int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
101 overlay->fb_width = fb->width; 106 overlay->fb_width = fb->width;
102 overlay->fb_height = fb->height; 107 overlay->fb_height = fb->height;
103 overlay->bpp = fb->bits_per_pixel; 108 overlay->bpp = fb->bits_per_pixel;
104 overlay->pitch = fb->pitch; 109 overlay->pitch = fb->pitches[0];
110 overlay->pixel_format = fb->pixel_format;
105 111
106 /* set overlay range to be displayed. */ 112 /* set overlay range to be displayed. */
107 overlay->crtc_x = pos->crtc_x; 113 overlay->crtc_x = pos->crtc_x;
@@ -153,26 +159,37 @@ static int exynos_drm_crtc_update(struct drm_crtc *crtc)
153 159
154static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) 160static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
155{ 161{
162 struct drm_device *dev = crtc->dev;
156 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); 163 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
157 164
158 DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode); 165 DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode);
159 166
167 if (exynos_crtc->dpms == mode) {
168 DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n");
169 return;
170 }
171
172 mutex_lock(&dev->struct_mutex);
173
160 switch (mode) { 174 switch (mode) {
161 case DRM_MODE_DPMS_ON: 175 case DRM_MODE_DPMS_ON:
162 exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe, 176 exynos_drm_fn_encoder(crtc, &mode,
163 exynos_drm_encoder_crtc_commit); 177 exynos_drm_encoder_crtc_dpms);
178 exynos_crtc->dpms = mode;
164 break; 179 break;
165 case DRM_MODE_DPMS_STANDBY: 180 case DRM_MODE_DPMS_STANDBY:
166 case DRM_MODE_DPMS_SUSPEND: 181 case DRM_MODE_DPMS_SUSPEND:
167 case DRM_MODE_DPMS_OFF: 182 case DRM_MODE_DPMS_OFF:
168 /* TODO */ 183 exynos_drm_fn_encoder(crtc, &mode,
169 exynos_drm_fn_encoder(crtc, NULL, 184 exynos_drm_encoder_crtc_dpms);
170 exynos_drm_encoder_crtc_disable); 185 exynos_crtc->dpms = mode;
171 break; 186 break;
172 default: 187 default:
173 DRM_DEBUG_KMS("unspecified mode %d\n", mode); 188 DRM_ERROR("unspecified mode %d\n", mode);
174 break; 189 break;
175 } 190 }
191
192 mutex_unlock(&dev->struct_mutex);
176} 193}
177 194
178static void exynos_drm_crtc_prepare(struct drm_crtc *crtc) 195static void exynos_drm_crtc_prepare(struct drm_crtc *crtc)
@@ -188,6 +205,28 @@ static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
188 205
189 DRM_DEBUG_KMS("%s\n", __FILE__); 206 DRM_DEBUG_KMS("%s\n", __FILE__);
190 207
208 /*
209 * when set_crtc is requested from user or at booting time,
210 * crtc->commit would be called without dpms call so if dpms is
211 * no power on then crtc->dpms should be called
212 * with DRM_MODE_DPMS_ON for the hardware power to be on.
213 */
214 if (exynos_crtc->dpms != DRM_MODE_DPMS_ON) {
215 int mode = DRM_MODE_DPMS_ON;
216
217 /*
218 * enable hardware(power on) to all encoders hdmi connected
219 * to current crtc.
220 */
221 exynos_drm_crtc_dpms(crtc, mode);
222 /*
223 * enable dma to all encoders connected to current crtc and
224 * lcd panel.
225 */
226 exynos_drm_fn_encoder(crtc, &mode,
227 exynos_drm_encoder_dpms_from_crtc);
228 }
229
191 exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe, 230 exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe,
192 exynos_drm_encoder_crtc_commit); 231 exynos_drm_encoder_crtc_commit);
193} 232}
@@ -344,6 +383,8 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
344 } 383 }
345 384
346 exynos_crtc->pipe = nr; 385 exynos_crtc->pipe = nr;
386 exynos_crtc->dpms = DRM_MODE_DPMS_OFF;
387 exynos_crtc->overlay.zpos = DEFAULT_ZPOS;
347 crtc = &exynos_crtc->drm_crtc; 388 crtc = &exynos_crtc->drm_crtc;
348 389
349 private->crtc[nr] = crtc; 390 private->crtc[nr] = crtc;
@@ -357,9 +398,14 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
357int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc) 398int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc)
358{ 399{
359 struct exynos_drm_private *private = dev->dev_private; 400 struct exynos_drm_private *private = dev->dev_private;
401 struct exynos_drm_crtc *exynos_crtc =
402 to_exynos_crtc(private->crtc[crtc]);
360 403
361 DRM_DEBUG_KMS("%s\n", __FILE__); 404 DRM_DEBUG_KMS("%s\n", __FILE__);
362 405
406 if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
407 return -EPERM;
408
363 exynos_drm_fn_encoder(private->crtc[crtc], &crtc, 409 exynos_drm_fn_encoder(private->crtc[crtc], &crtc,
364 exynos_drm_enable_vblank); 410 exynos_drm_enable_vblank);
365 411
@@ -369,9 +415,14 @@ int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc)
369void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc) 415void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc)
370{ 416{
371 struct exynos_drm_private *private = dev->dev_private; 417 struct exynos_drm_private *private = dev->dev_private;
418 struct exynos_drm_crtc *exynos_crtc =
419 to_exynos_crtc(private->crtc[crtc]);
372 420
373 DRM_DEBUG_KMS("%s\n", __FILE__); 421 DRM_DEBUG_KMS("%s\n", __FILE__);
374 422
423 if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
424 return;
425
375 exynos_drm_fn_encoder(private->crtc[crtc], &crtc, 426 exynos_drm_fn_encoder(private->crtc[crtc], &crtc,
376 exynos_drm_disable_vblank); 427 exynos_drm_disable_vblank);
377} 428}