|
@@ -820,99 +820,6 @@ static int tegra_dc_add_planes(struct drm_device *drm, struct tegra_dc *dc)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y,
|
|
|
- struct drm_framebuffer *fb)
|
|
|
-{
|
|
|
- struct tegra_bo *bo = tegra_fb_get_plane(fb, 0);
|
|
|
- unsigned int h_offset = 0, v_offset = 0;
|
|
|
- struct tegra_bo_tiling tiling;
|
|
|
- unsigned long value, flags;
|
|
|
- unsigned int format, swap;
|
|
|
- int err;
|
|
|
-
|
|
|
- err = tegra_fb_get_tiling(fb, &tiling);
|
|
|
- if (err < 0)
|
|
|
- return err;
|
|
|
-
|
|
|
- spin_lock_irqsave(&dc->lock, flags);
|
|
|
-
|
|
|
- tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER);
|
|
|
-
|
|
|
- value = fb->offsets[0] + y * fb->pitches[0] +
|
|
|
- x * fb->bits_per_pixel / 8;
|
|
|
-
|
|
|
- tegra_dc_writel(dc, bo->paddr + value, DC_WINBUF_START_ADDR);
|
|
|
- tegra_dc_writel(dc, fb->pitches[0], DC_WIN_LINE_STRIDE);
|
|
|
-
|
|
|
- format = tegra_dc_format(fb->pixel_format, &swap);
|
|
|
- tegra_dc_writel(dc, format, DC_WIN_COLOR_DEPTH);
|
|
|
- tegra_dc_writel(dc, swap, DC_WIN_BYTE_SWAP);
|
|
|
-
|
|
|
- if (dc->soc->supports_block_linear) {
|
|
|
- unsigned long height = tiling.value;
|
|
|
-
|
|
|
- switch (tiling.mode) {
|
|
|
- case TEGRA_BO_TILING_MODE_PITCH:
|
|
|
- value = DC_WINBUF_SURFACE_KIND_PITCH;
|
|
|
- break;
|
|
|
-
|
|
|
- case TEGRA_BO_TILING_MODE_TILED:
|
|
|
- value = DC_WINBUF_SURFACE_KIND_TILED;
|
|
|
- break;
|
|
|
-
|
|
|
- case TEGRA_BO_TILING_MODE_BLOCK:
|
|
|
- value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(height) |
|
|
|
- DC_WINBUF_SURFACE_KIND_BLOCK;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- tegra_dc_writel(dc, value, DC_WINBUF_SURFACE_KIND);
|
|
|
- } else {
|
|
|
- switch (tiling.mode) {
|
|
|
- case TEGRA_BO_TILING_MODE_PITCH:
|
|
|
- value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV |
|
|
|
- DC_WIN_BUFFER_ADDR_MODE_LINEAR;
|
|
|
- break;
|
|
|
-
|
|
|
- case TEGRA_BO_TILING_MODE_TILED:
|
|
|
- value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |
|
|
|
- DC_WIN_BUFFER_ADDR_MODE_TILE;
|
|
|
- break;
|
|
|
-
|
|
|
- case TEGRA_BO_TILING_MODE_BLOCK:
|
|
|
- DRM_ERROR("hardware doesn't support block linear mode\n");
|
|
|
- spin_unlock_irqrestore(&dc->lock, flags);
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
-
|
|
|
- tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
|
|
|
- }
|
|
|
-
|
|
|
- /* make sure bottom-up buffers are properly displayed */
|
|
|
- if (tegra_fb_is_bottom_up(fb)) {
|
|
|
- value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS);
|
|
|
- value |= V_DIRECTION;
|
|
|
- tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
|
|
|
-
|
|
|
- v_offset += fb->height - 1;
|
|
|
- } else {
|
|
|
- value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS);
|
|
|
- value &= ~V_DIRECTION;
|
|
|
- tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
|
|
|
- }
|
|
|
-
|
|
|
- tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET);
|
|
|
- tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET);
|
|
|
-
|
|
|
- value = GENERAL_ACT_REQ | WIN_A_ACT_REQ;
|
|
|
- tegra_dc_writel(dc, value << 8, DC_CMD_STATE_CONTROL);
|
|
|
- tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
|
|
|
-
|
|
|
- spin_unlock_irqrestore(&dc->lock, flags);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
void tegra_dc_enable_vblank(struct tegra_dc *dc)
|
|
|
{
|
|
|
unsigned long value, flags;
|
|
@@ -991,30 +898,6 @@ void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file)
|
|
|
spin_unlock_irqrestore(&drm->event_lock, flags);
|
|
|
}
|
|
|
|
|
|
-static int tegra_dc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
|
|
|
- struct drm_pending_vblank_event *event, uint32_t page_flip_flags)
|
|
|
-{
|
|
|
- unsigned int pipe = drm_crtc_index(crtc);
|
|
|
- struct tegra_dc *dc = to_tegra_dc(crtc);
|
|
|
-
|
|
|
- if (dc->event)
|
|
|
- return -EBUSY;
|
|
|
-
|
|
|
- if (event) {
|
|
|
- event->pipe = pipe;
|
|
|
- dc->event = event;
|
|
|
- drm_crtc_vblank_get(crtc);
|
|
|
- }
|
|
|
-
|
|
|
- if (crtc->primary->state)
|
|
|
- drm_atomic_set_fb_for_plane(crtc->primary->state, fb);
|
|
|
-
|
|
|
- tegra_dc_set_base(dc, 0, 0, fb);
|
|
|
- crtc->primary->fb = fb;
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
static void tegra_dc_destroy(struct drm_crtc *crtc)
|
|
|
{
|
|
|
drm_crtc_cleanup(crtc);
|
|
@@ -1056,7 +939,7 @@ static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc,
|
|
|
}
|
|
|
|
|
|
static const struct drm_crtc_funcs tegra_crtc_funcs = {
|
|
|
- .page_flip = tegra_dc_page_flip,
|
|
|
+ .page_flip = drm_atomic_helper_page_flip,
|
|
|
.set_config = drm_atomic_helper_set_config,
|
|
|
.destroy = tegra_dc_destroy,
|
|
|
.reset = tegra_crtc_reset,
|
|
@@ -1326,6 +1209,16 @@ static int tegra_crtc_atomic_check(struct drm_crtc *crtc,
|
|
|
|
|
|
static void tegra_crtc_atomic_begin(struct drm_crtc *crtc)
|
|
|
{
|
|
|
+ struct tegra_dc *dc = to_tegra_dc(crtc);
|
|
|
+
|
|
|
+ if (crtc->state->event) {
|
|
|
+ crtc->state->event->pipe = drm_crtc_index(crtc);
|
|
|
+
|
|
|
+ WARN_ON(drm_crtc_vblank_get(crtc) != 0);
|
|
|
+
|
|
|
+ dc->event = crtc->state->event;
|
|
|
+ crtc->state->event = NULL;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static void tegra_crtc_atomic_flush(struct drm_crtc *crtc)
|