diff options
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_crtc.c')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_crtc.c | 89 |
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 | */ |
56 | struct exynos_drm_crtc { | 56 | struct 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 | ||
62 | static void exynos_drm_crtc_apply(struct drm_crtc *crtc) | 63 | static 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 | ||
154 | static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) | 160 | static 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 | ||
178 | static void exynos_drm_crtc_prepare(struct drm_crtc *crtc) | 195 | static 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) | |||
357 | int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc) | 398 | int 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) | |||
369 | void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc) | 415 | void 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 | } |