aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/exynos/exynos_drm_fimd.c
diff options
context:
space:
mode:
authorMarek Szyprowski <m.szyprowski@samsung.com>2015-06-12 05:07:17 -0400
committerInki Dae <daeinki@gmail.com>2015-06-19 11:32:59 -0400
commitfb88e2141222ad93c594f2babc806d71cfb65e0d (patch)
treef93bdfd5c6b19d3dbcf717a76dd2df5abd7d41b9 /drivers/gpu/drm/exynos/exynos_drm_fimd.c
parentb74f14fd5c98b4cbd0763ea1841478eef5bdb7d8 (diff)
drm/exynos: fimd: ensure proper hw state in fimd_clear_channel()
One should not do any assumptions on the stare of the fimd hardware during driver initialization, so to properly reset fimd before enabling IOMMU, one should ensure that all power domains and clocks are really enabled. This patch adds pm_runtime and clocks management in the fimd_clear_channel() function to ensure that any access to fimd registers will be performed with clocks and power domains enabled. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Tested-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk> Signed-off-by: Inki Dae <inki.dae@samsung.com>
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_fimd.c')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c135
1 files changed, 77 insertions, 58 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 324055f032ec..b5bd16ceaa96 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -196,6 +196,62 @@ static inline struct fimd_driver_data *drm_fimd_get_driver_data(
196 return (struct fimd_driver_data *)of_id->data; 196 return (struct fimd_driver_data *)of_id->data;
197} 197}
198 198
199static int fimd_enable_vblank(struct exynos_drm_crtc *crtc)
200{
201 struct fimd_context *ctx = crtc->ctx;
202 u32 val;
203
204 if (ctx->suspended)
205 return -EPERM;
206
207 if (!test_and_set_bit(0, &ctx->irq_flags)) {
208 val = readl(ctx->regs + VIDINTCON0);
209
210 val |= VIDINTCON0_INT_ENABLE;
211
212 if (ctx->i80_if) {
213 val |= VIDINTCON0_INT_I80IFDONE;
214 val |= VIDINTCON0_INT_SYSMAINCON;
215 val &= ~VIDINTCON0_INT_SYSSUBCON;
216 } else {
217 val |= VIDINTCON0_INT_FRAME;
218
219 val &= ~VIDINTCON0_FRAMESEL0_MASK;
220 val |= VIDINTCON0_FRAMESEL0_VSYNC;
221 val &= ~VIDINTCON0_FRAMESEL1_MASK;
222 val |= VIDINTCON0_FRAMESEL1_NONE;
223 }
224
225 writel(val, ctx->regs + VIDINTCON0);
226 }
227
228 return 0;
229}
230
231static void fimd_disable_vblank(struct exynos_drm_crtc *crtc)
232{
233 struct fimd_context *ctx = crtc->ctx;
234 u32 val;
235
236 if (ctx->suspended)
237 return;
238
239 if (test_and_clear_bit(0, &ctx->irq_flags)) {
240 val = readl(ctx->regs + VIDINTCON0);
241
242 val &= ~VIDINTCON0_INT_ENABLE;
243
244 if (ctx->i80_if) {
245 val &= ~VIDINTCON0_INT_I80IFDONE;
246 val &= ~VIDINTCON0_INT_SYSMAINCON;
247 val &= ~VIDINTCON0_INT_SYSSUBCON;
248 } else
249 val &= ~VIDINTCON0_INT_FRAME;
250
251 writel(val, ctx->regs + VIDINTCON0);
252 }
253}
254
199static void fimd_wait_for_vblank(struct exynos_drm_crtc *crtc) 255static void fimd_wait_for_vblank(struct exynos_drm_crtc *crtc)
200{ 256{
201 struct fimd_context *ctx = crtc->ctx; 257 struct fimd_context *ctx = crtc->ctx;
@@ -248,6 +304,12 @@ static void fimd_clear_channel(struct fimd_context *ctx)
248 304
249 DRM_DEBUG_KMS("%s\n", __FILE__); 305 DRM_DEBUG_KMS("%s\n", __FILE__);
250 306
307 /* Hardware is in unknown state, so ensure it gets enabled properly */
308 pm_runtime_get_sync(ctx->dev);
309
310 clk_prepare_enable(ctx->bus_clk);
311 clk_prepare_enable(ctx->lcd_clk);
312
251 /* Check if any channel is enabled. */ 313 /* Check if any channel is enabled. */
252 for (win = 0; win < WINDOWS_NR; win++) { 314 for (win = 0; win < WINDOWS_NR; win++) {
253 u32 val = readl(ctx->regs + WINCON(win)); 315 u32 val = readl(ctx->regs + WINCON(win));
@@ -265,12 +327,24 @@ static void fimd_clear_channel(struct fimd_context *ctx)
265 327
266 /* Wait for vsync, as disable channel takes effect at next vsync */ 328 /* Wait for vsync, as disable channel takes effect at next vsync */
267 if (ch_enabled) { 329 if (ch_enabled) {
268 unsigned int state = ctx->suspended; 330 int pipe = ctx->pipe;
331
332 /* ensure that vblank interrupt won't be reported to core */
333 ctx->suspended = false;
334 ctx->pipe = -1;
269 335
270 ctx->suspended = 0; 336 fimd_enable_vblank(ctx->crtc);
271 fimd_wait_for_vblank(ctx->crtc); 337 fimd_wait_for_vblank(ctx->crtc);
272 ctx->suspended = state; 338 fimd_disable_vblank(ctx->crtc);
339
340 ctx->suspended = true;
341 ctx->pipe = pipe;
273 } 342 }
343
344 clk_disable_unprepare(ctx->lcd_clk);
345 clk_disable_unprepare(ctx->bus_clk);
346
347 pm_runtime_put(ctx->dev);
274} 348}
275 349
276static int fimd_iommu_attach_devices(struct fimd_context *ctx, 350static int fimd_iommu_attach_devices(struct fimd_context *ctx,
@@ -434,61 +508,6 @@ static void fimd_commit(struct exynos_drm_crtc *crtc)
434 writel(val, ctx->regs + VIDCON0); 508 writel(val, ctx->regs + VIDCON0);
435} 509}
436 510
437static int fimd_enable_vblank(struct exynos_drm_crtc *crtc)
438{
439 struct fimd_context *ctx = crtc->ctx;
440 u32 val;
441
442 if (ctx->suspended)
443 return -EPERM;
444
445 if (!test_and_set_bit(0, &ctx->irq_flags)) {
446 val = readl(ctx->regs + VIDINTCON0);
447
448 val |= VIDINTCON0_INT_ENABLE;
449
450 if (ctx->i80_if) {
451 val |= VIDINTCON0_INT_I80IFDONE;
452 val |= VIDINTCON0_INT_SYSMAINCON;
453 val &= ~VIDINTCON0_INT_SYSSUBCON;
454 } else {
455 val |= VIDINTCON0_INT_FRAME;
456
457 val &= ~VIDINTCON0_FRAMESEL0_MASK;
458 val |= VIDINTCON0_FRAMESEL0_VSYNC;
459 val &= ~VIDINTCON0_FRAMESEL1_MASK;
460 val |= VIDINTCON0_FRAMESEL1_NONE;
461 }
462
463 writel(val, ctx->regs + VIDINTCON0);
464 }
465
466 return 0;
467}
468
469static void fimd_disable_vblank(struct exynos_drm_crtc *crtc)
470{
471 struct fimd_context *ctx = crtc->ctx;
472 u32 val;
473
474 if (ctx->suspended)
475 return;
476
477 if (test_and_clear_bit(0, &ctx->irq_flags)) {
478 val = readl(ctx->regs + VIDINTCON0);
479
480 val &= ~VIDINTCON0_INT_ENABLE;
481
482 if (ctx->i80_if) {
483 val &= ~VIDINTCON0_INT_I80IFDONE;
484 val &= ~VIDINTCON0_INT_SYSMAINCON;
485 val &= ~VIDINTCON0_INT_SYSSUBCON;
486 } else
487 val &= ~VIDINTCON0_INT_FRAME;
488
489 writel(val, ctx->regs + VIDINTCON0);
490 }
491}
492 511
493static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win) 512static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
494{ 513{