diff options
Diffstat (limited to 'drivers/gpu/drm/atmel-hlcdc')
-rw-r--r-- | drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 107 | ||||
-rw-r--r-- | drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 135 |
3 files changed, 71 insertions, 178 deletions
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c index 98fb53b75f77..65af56e47129 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c @@ -557,103 +557,10 @@ static irqreturn_t atmel_hlcdc_dc_irq_handler(int irq, void *data) return IRQ_HANDLED; } -struct atmel_hlcdc_dc_commit { - struct work_struct work; - struct drm_device *dev; - struct drm_atomic_state *state; -}; - -static void -atmel_hlcdc_dc_atomic_complete(struct atmel_hlcdc_dc_commit *commit) -{ - struct drm_device *dev = commit->dev; - struct atmel_hlcdc_dc *dc = dev->dev_private; - struct drm_atomic_state *old_state = commit->state; - - /* Apply the atomic update. */ - drm_atomic_helper_commit_modeset_disables(dev, old_state); - drm_atomic_helper_commit_planes(dev, old_state, 0); - drm_atomic_helper_commit_modeset_enables(dev, old_state); - - drm_atomic_helper_wait_for_vblanks(dev, old_state); - - drm_atomic_helper_cleanup_planes(dev, old_state); - - drm_atomic_state_put(old_state); - - /* Complete the commit, wake up any waiter. */ - spin_lock(&dc->commit.wait.lock); - dc->commit.pending = false; - wake_up_all_locked(&dc->commit.wait); - spin_unlock(&dc->commit.wait.lock); - - kfree(commit); -} - -static void atmel_hlcdc_dc_atomic_work(struct work_struct *work) -{ - struct atmel_hlcdc_dc_commit *commit = - container_of(work, struct atmel_hlcdc_dc_commit, work); - - atmel_hlcdc_dc_atomic_complete(commit); -} - -static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev, - struct drm_atomic_state *state, - bool async) -{ - struct atmel_hlcdc_dc *dc = dev->dev_private; - struct atmel_hlcdc_dc_commit *commit; - int ret; - - ret = drm_atomic_helper_prepare_planes(dev, state); - if (ret) - return ret; - - /* Allocate the commit object. */ - commit = kzalloc(sizeof(*commit), GFP_KERNEL); - if (!commit) { - ret = -ENOMEM; - goto error; - } - - INIT_WORK(&commit->work, atmel_hlcdc_dc_atomic_work); - commit->dev = dev; - commit->state = state; - - spin_lock(&dc->commit.wait.lock); - ret = wait_event_interruptible_locked(dc->commit.wait, - !dc->commit.pending); - if (ret == 0) - dc->commit.pending = true; - spin_unlock(&dc->commit.wait.lock); - - if (ret) - goto err_free; - - /* We have our own synchronization through the commit lock. */ - BUG_ON(drm_atomic_helper_swap_state(state, false) < 0); - - /* Swap state succeeded, this is the point of no return. */ - drm_atomic_state_get(state); - if (async) - queue_work(dc->wq, &commit->work); - else - atmel_hlcdc_dc_atomic_complete(commit); - - return 0; - -err_free: - kfree(commit); -error: - drm_atomic_helper_cleanup_planes(dev, state); - return ret; -} - static const struct drm_mode_config_funcs mode_config_funcs = { .fb_create = drm_gem_fb_create, .atomic_check = drm_atomic_helper_check, - .atomic_commit = atmel_hlcdc_dc_atomic_commit, + .atomic_commit = drm_atomic_helper_commit, }; static int atmel_hlcdc_dc_modeset_init(struct drm_device *dev) @@ -712,11 +619,6 @@ static int atmel_hlcdc_dc_load(struct drm_device *dev) if (!dc) return -ENOMEM; - dc->wq = alloc_ordered_workqueue("atmel-hlcdc-dc", 0); - if (!dc->wq) - return -ENOMEM; - - init_waitqueue_head(&dc->commit.wait); dc->desc = match->data; dc->hlcdc = dev_get_drvdata(dev->dev->parent); dev->dev_private = dc; @@ -724,7 +626,7 @@ static int atmel_hlcdc_dc_load(struct drm_device *dev) ret = clk_prepare_enable(dc->hlcdc->periph_clk); if (ret) { dev_err(dev->dev, "failed to enable periph_clk\n"); - goto err_destroy_wq; + return ret; } pm_runtime_enable(dev->dev); @@ -761,9 +663,6 @@ err_periph_clk_disable: pm_runtime_disable(dev->dev); clk_disable_unprepare(dc->hlcdc->periph_clk); -err_destroy_wq: - destroy_workqueue(dc->wq); - return ret; } @@ -771,7 +670,6 @@ static void atmel_hlcdc_dc_unload(struct drm_device *dev) { struct atmel_hlcdc_dc *dc = dev->dev_private; - flush_workqueue(dc->wq); drm_kms_helper_poll_fini(dev); drm_atomic_helper_shutdown(dev); drm_mode_config_cleanup(dev); @@ -784,7 +682,6 @@ static void atmel_hlcdc_dc_unload(struct drm_device *dev) pm_runtime_disable(dev->dev); clk_disable_unprepare(dc->hlcdc->periph_clk); - destroy_workqueue(dc->wq); } static int atmel_hlcdc_dc_irq_postinstall(struct drm_device *dev) diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h index 469d4507e576..5b5c774e0edf 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h @@ -331,9 +331,7 @@ struct atmel_hlcdc_dc_desc { * @crtc: CRTC provided by the display controller * @planes: instantiated planes * @layers: active HLCDC layers - * @wq: display controller workqueue * @suspend: used to store the HLCDC state when entering suspend - * @commit: used for async commit handling */ struct atmel_hlcdc_dc { const struct atmel_hlcdc_dc_desc *desc; @@ -341,15 +339,10 @@ struct atmel_hlcdc_dc { struct atmel_hlcdc *hlcdc; struct drm_crtc *crtc; struct atmel_hlcdc_layer *layers[ATMEL_HLCDC_MAX_LAYERS]; - struct workqueue_struct *wq; struct { u32 imr; struct drm_atomic_state *state; } suspend; - struct { - wait_queue_head_t wait; - bool pending; - } commit; }; extern struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_formats; diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c index 15bc93163833..a077d93c78d7 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c @@ -593,22 +593,23 @@ atmel_hlcdc_plane_update_disc_area(struct atmel_hlcdc_plane *plane, } static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p, - struct drm_plane_state *s) + struct drm_atomic_state *state) { + struct drm_plane_state *s = drm_atomic_get_new_plane_state(state, p); struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p); - struct atmel_hlcdc_plane_state *state = + struct atmel_hlcdc_plane_state *hstate = drm_plane_state_to_atmel_hlcdc_plane_state(s); const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; - struct drm_framebuffer *fb = state->base.fb; + struct drm_framebuffer *fb = hstate->base.fb; const struct drm_display_mode *mode; struct drm_crtc_state *crtc_state; int ret; int i; - if (!state->base.crtc || WARN_ON(!fb)) + if (!hstate->base.crtc || WARN_ON(!fb)) return 0; - crtc_state = drm_atomic_get_existing_crtc_state(s->state, s->crtc); + crtc_state = drm_atomic_get_existing_crtc_state(state, s->crtc); mode = &crtc_state->adjusted_mode; ret = drm_atomic_helper_check_plane_state(s, crtc_state, @@ -617,101 +618,101 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p, if (ret || !s->visible) return ret; - state->src_x = s->src.x1; - state->src_y = s->src.y1; - state->src_w = drm_rect_width(&s->src); - state->src_h = drm_rect_height(&s->src); - state->crtc_x = s->dst.x1; - state->crtc_y = s->dst.y1; - state->crtc_w = drm_rect_width(&s->dst); - state->crtc_h = drm_rect_height(&s->dst); + hstate->src_x = s->src.x1; + hstate->src_y = s->src.y1; + hstate->src_w = drm_rect_width(&s->src); + hstate->src_h = drm_rect_height(&s->src); + hstate->crtc_x = s->dst.x1; + hstate->crtc_y = s->dst.y1; + hstate->crtc_w = drm_rect_width(&s->dst); + hstate->crtc_h = drm_rect_height(&s->dst); - if ((state->src_x | state->src_y | state->src_w | state->src_h) & + if ((hstate->src_x | hstate->src_y | hstate->src_w | hstate->src_h) & SUBPIXEL_MASK) return -EINVAL; - state->src_x >>= 16; - state->src_y >>= 16; - state->src_w >>= 16; - state->src_h >>= 16; + hstate->src_x >>= 16; + hstate->src_y >>= 16; + hstate->src_w >>= 16; + hstate->src_h >>= 16; - state->nplanes = fb->format->num_planes; - if (state->nplanes > ATMEL_HLCDC_LAYER_MAX_PLANES) + hstate->nplanes = fb->format->num_planes; + if (hstate->nplanes > ATMEL_HLCDC_LAYER_MAX_PLANES) return -EINVAL; - for (i = 0; i < state->nplanes; i++) { + for (i = 0; i < hstate->nplanes; i++) { unsigned int offset = 0; int xdiv = i ? fb->format->hsub : 1; int ydiv = i ? fb->format->vsub : 1; - state->bpp[i] = fb->format->cpp[i]; - if (!state->bpp[i]) + hstate->bpp[i] = fb->format->cpp[i]; + if (!hstate->bpp[i]) return -EINVAL; - switch (state->base.rotation & DRM_MODE_ROTATE_MASK) { + switch (hstate->base.rotation & DRM_MODE_ROTATE_MASK) { case DRM_MODE_ROTATE_90: - offset = (state->src_y / ydiv) * + offset = (hstate->src_y / ydiv) * fb->pitches[i]; - offset += ((state->src_x + state->src_w - 1) / - xdiv) * state->bpp[i]; - state->xstride[i] = -(((state->src_h - 1) / ydiv) * + offset += ((hstate->src_x + hstate->src_w - 1) / + xdiv) * hstate->bpp[i]; + hstate->xstride[i] = -(((hstate->src_h - 1) / ydiv) * fb->pitches[i]) - - (2 * state->bpp[i]); - state->pstride[i] = fb->pitches[i] - state->bpp[i]; + (2 * hstate->bpp[i]); + hstate->pstride[i] = fb->pitches[i] - hstate->bpp[i]; break; case DRM_MODE_ROTATE_180: - offset = ((state->src_y + state->src_h - 1) / + offset = ((hstate->src_y + hstate->src_h - 1) / ydiv) * fb->pitches[i]; - offset += ((state->src_x + state->src_w - 1) / - xdiv) * state->bpp[i]; - state->xstride[i] = ((((state->src_w - 1) / xdiv) - 1) * - state->bpp[i]) - fb->pitches[i]; - state->pstride[i] = -2 * state->bpp[i]; + offset += ((hstate->src_x + hstate->src_w - 1) / + xdiv) * hstate->bpp[i]; + hstate->xstride[i] = ((((hstate->src_w - 1) / xdiv) - 1) * + hstate->bpp[i]) - fb->pitches[i]; + hstate->pstride[i] = -2 * hstate->bpp[i]; break; case DRM_MODE_ROTATE_270: - offset = ((state->src_y + state->src_h - 1) / + offset = ((hstate->src_y + hstate->src_h - 1) / ydiv) * fb->pitches[i]; - offset += (state->src_x / xdiv) * state->bpp[i]; - state->xstride[i] = ((state->src_h - 1) / ydiv) * + offset += (hstate->src_x / xdiv) * hstate->bpp[i]; + hstate->xstride[i] = ((hstate->src_h - 1) / ydiv) * fb->pitches[i]; - state->pstride[i] = -fb->pitches[i] - state->bpp[i]; + hstate->pstride[i] = -fb->pitches[i] - hstate->bpp[i]; break; case DRM_MODE_ROTATE_0: default: - offset = (state->src_y / ydiv) * fb->pitches[i]; - offset += (state->src_x / xdiv) * state->bpp[i]; - state->xstride[i] = fb->pitches[i] - - ((state->src_w / xdiv) * - state->bpp[i]); - state->pstride[i] = 0; + offset = (hstate->src_y / ydiv) * fb->pitches[i]; + offset += (hstate->src_x / xdiv) * hstate->bpp[i]; + hstate->xstride[i] = fb->pitches[i] - + ((hstate->src_w / xdiv) * + hstate->bpp[i]); + hstate->pstride[i] = 0; break; } - state->offsets[i] = offset + fb->offsets[i]; + hstate->offsets[i] = offset + fb->offsets[i]; } /* * Swap width and size in case of 90 or 270 degrees rotation */ - if (drm_rotation_90_or_270(state->base.rotation)) { - swap(state->src_w, state->src_h); + if (drm_rotation_90_or_270(hstate->base.rotation)) { + swap(hstate->src_w, hstate->src_h); } if (!desc->layout.size && - (mode->hdisplay != state->crtc_w || - mode->vdisplay != state->crtc_h)) + (mode->hdisplay != hstate->crtc_w || + mode->vdisplay != hstate->crtc_h)) return -EINVAL; - if ((state->crtc_h != state->src_h || state->crtc_w != state->src_w) && + if ((hstate->crtc_h != hstate->src_h || hstate->crtc_w != hstate->src_w) && (!desc->layout.memsize || - state->base.fb->format->has_alpha)) + hstate->base.fb->format->has_alpha)) return -EINVAL; return 0; } static void atmel_hlcdc_plane_atomic_disable(struct drm_plane *p, - struct drm_plane_state *old_state) + struct drm_atomic_state *state) { struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p); @@ -730,27 +731,29 @@ static void atmel_hlcdc_plane_atomic_disable(struct drm_plane *p, } static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p, - struct drm_plane_state *old_s) + struct drm_atomic_state *state) { + struct drm_plane_state *new_s = drm_atomic_get_new_plane_state(state, + p); struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p); - struct atmel_hlcdc_plane_state *state = - drm_plane_state_to_atmel_hlcdc_plane_state(p->state); + struct atmel_hlcdc_plane_state *hstate = + drm_plane_state_to_atmel_hlcdc_plane_state(new_s); u32 sr; - if (!p->state->crtc || !p->state->fb) + if (!new_s->crtc || !new_s->fb) return; - if (!state->base.visible) { - atmel_hlcdc_plane_atomic_disable(p, old_s); + if (!hstate->base.visible) { + atmel_hlcdc_plane_atomic_disable(p, state); return; } - atmel_hlcdc_plane_update_pos_and_size(plane, state); - atmel_hlcdc_plane_update_general_settings(plane, state); - atmel_hlcdc_plane_update_format(plane, state); - atmel_hlcdc_plane_update_clut(plane, state); - atmel_hlcdc_plane_update_buffers(plane, state); - atmel_hlcdc_plane_update_disc_area(plane, state); + atmel_hlcdc_plane_update_pos_and_size(plane, hstate); + atmel_hlcdc_plane_update_general_settings(plane, hstate); + atmel_hlcdc_plane_update_format(plane, hstate); + atmel_hlcdc_plane_update_clut(plane, hstate); + atmel_hlcdc_plane_update_buffers(plane, hstate); + atmel_hlcdc_plane_update_disc_area(plane, hstate); /* Enable the overrun interrupts. */ atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_IER, |