diff --git a/drivers/gpu/drm/verisilicon/vs_dc.c b/drivers/gpu/drm/verisilicon/vs_dc.c index c72b2e1faf41a..99db76c349cdb 100644 --- a/drivers/gpu/drm/verisilicon/vs_dc.c +++ b/drivers/gpu/drm/verisilicon/vs_dc.c @@ -1242,79 +1242,24 @@ static void update_cursor_size(struct drm_plane_state *state, struct dc_hw_curso cursor->size = size_type; } -static void update_cursor_plane(struct vs_dc *dc, struct vs_plane *plane, struct drm_plane *drm_plane, - struct drm_atomic_state *drm_state) -{ - //struct drm_plane_state *state = plane->base.state; - struct drm_plane_state *state = drm_atomic_get_new_plane_state(drm_state, - drm_plane); - struct drm_framebuffer *drm_fb = state->fb; - struct dc_hw_cursor cursor; - static u32 pre_address = 0; - - cursor.address = plane->dma_addr[0]; - cursor.x = state->crtc_x; - cursor.y = state->crtc_y; - cursor.hot_x = drm_fb->hot_x; - cursor.hot_y = drm_fb->hot_y; - cursor.display_id = to_vs_display_id(dc, state->crtc); - update_cursor_size(state, &cursor); - cursor.enable = true; - - if (cursor.address != pre_address) { - sifive_l2_flush64_range(cursor.address, ((cursor.size == CURSOR_SIZE_32X32) ? - CURSOR_MEM_SIZE_32X32 : CURSOR_MEM_SIZE_64X64)); - pre_address = cursor.address; - } - - dc_hw_update_cursor(&dc->hw, cursor.display_id, &cursor); -} - static void vs_dc_update_plane(struct device *dev, struct vs_plane *plane, struct drm_plane *drm_plane, struct drm_atomic_state *drm_state) { struct vs_dc *dc = dev_get_drvdata(dev); - enum drm_plane_type type = plane->base.type; - switch (type) { - case DRM_PLANE_TYPE_PRIMARY: - case DRM_PLANE_TYPE_OVERLAY: - update_plane(dc, plane, drm_plane, drm_state); - update_qos(dc, plane, drm_plane, drm_state); - break; - case DRM_PLANE_TYPE_CURSOR: - update_cursor_plane(dc, plane, drm_plane, drm_state); - break; - default: - break; - } + update_plane(dc, plane, drm_plane, drm_state); + update_qos(dc, plane, drm_plane, drm_state); + } static void vs_dc_disable_plane(struct device *dev, struct vs_plane *plane, struct drm_plane_state *old_state) { struct vs_dc *dc = dev_get_drvdata(dev); - enum drm_plane_type type = plane->base.type; struct dc_hw_fb fb = {0}; - struct dc_hw_cursor cursor = {0}; - switch (type) { - case DRM_PLANE_TYPE_PRIMARY: - case DRM_PLANE_TYPE_OVERLAY: - fb.enable = false; - dc_hw_update_plane(&dc->hw, plane->id, &fb, NULL, NULL, NULL); -#ifdef CONFIG_VERISILICON_DEC - disable_fbc(dc, plane); -#endif - break; - case DRM_PLANE_TYPE_CURSOR: - cursor.enable = false; - cursor.display_id = to_vs_display_id(dc, old_state->crtc); - dc_hw_update_cursor(&dc->hw, cursor.display_id, &cursor); - break; - default: - break; - } + fb.enable = false; + dc_hw_update_plane(&dc->hw, plane->id, &fb, NULL, NULL, NULL); } static bool vs_dc_mod_supported(const struct vs_plane_info *plane_info, @@ -1372,6 +1317,80 @@ static int vs_dc_check_plane(struct device *dev, struct drm_plane *plane, true, true); } +static void update_cursor_plane(struct vs_dc *dc, struct vs_plane *plane, + struct drm_plane *drm_plane, + struct drm_atomic_state *drm_state) +{ + struct drm_plane_state *state = drm_atomic_get_new_plane_state(drm_state, + drm_plane); + struct drm_framebuffer *drm_fb = state->fb; + struct dc_hw_cursor cursor; + static u32 pre_address = 0; + + cursor.address = plane->dma_addr[0]; + cursor.x = state->crtc_x; + cursor.y = state->crtc_y; + cursor.hot_x = drm_fb->hot_x; + cursor.hot_y = drm_fb->hot_y; + cursor.display_id = to_vs_display_id(dc, state->crtc); + update_cursor_size(state, &cursor); + cursor.enable = true; + + if (cursor.address != pre_address) { + sifive_l2_flush64_range(cursor.address, ((cursor.size == CURSOR_SIZE_32X32) ? + CURSOR_MEM_SIZE_32X32 : CURSOR_MEM_SIZE_64X64)); + pre_address = cursor.address; + } + + dc_hw_update_cursor(&dc->hw, cursor.display_id, &cursor); +} + +void vs_dc_update_cursor_plane(struct vs_dc *dc, struct vs_plane *plane, + struct drm_plane *drm_plane, + struct drm_atomic_state *drm_state) +{ + update_cursor_plane(dc, plane, drm_plane, drm_state); +} + +void vs_dc_disable_cursor_plane(struct vs_dc *dc, struct vs_plane *plane, + struct drm_plane_state *old_state) +{ + struct dc_hw_cursor cursor = {0}; + + cursor.enable = false; + cursor.display_id = to_vs_display_id(dc, old_state->crtc); + dc_hw_update_cursor(&dc->hw, cursor.display_id, &cursor); +} + +int vs_dc_check_cursor_plane(struct vs_dc *dc, struct drm_plane *plane, + struct drm_atomic_state *state) +{ + struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, + plane); + struct drm_framebuffer *fb = new_plane_state->fb; + const struct vs_plane_info *plane_info; + struct drm_crtc *crtc = new_plane_state->crtc; + struct drm_crtc_state *crtc_state; + struct vs_plane *vs_plane = to_vs_plane(plane); + + plane_info = &dc->hw.info->planes[vs_plane->id]; + + if (fb->width < plane_info->min_width || + fb->width > plane_info->max_width || + fb->height < plane_info->min_height || + fb->height > plane_info->max_height) + drm_err_once(plane->dev, "buffer size may not support on plane%d.\n", vs_plane->id); + + crtc_state = drm_atomic_get_existing_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) + return -EINVAL; + + return drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, + plane_info->min_scale, + plane_info->max_scale, + true, true); +} + static irqreturn_t dc_isr(int irq, void *data) { struct vs_dc *dc = data; @@ -1457,20 +1476,6 @@ static int dc_bind(struct device *dev, struct device *master, void *data) return ret; } -#ifdef CONFIG_VERISILICON_MMU - ret = dc_mmu_construct(priv->dma_dev, &priv->mmu); - if (ret) { - dev_err(dev, "failed to construct DC MMU\n"); - goto err_clean_dc; - } - - ret = dc_hw_mmu_init(&dc->hw, priv->mmu); - if (ret) { - dev_err(dev, "failed to init DC MMU\n"); - goto err_clean_dc; - } -#endif - ret = vs_drm_iommu_attach_device(drm_dev, dev); if (ret < 0) { dev_err(dev, "Failed to attached iommu device.\n"); diff --git a/drivers/gpu/drm/verisilicon/vs_dc.h b/drivers/gpu/drm/verisilicon/vs_dc.h index 92ee461d7f7df..d45c3dae4e912 100644 --- a/drivers/gpu/drm/verisilicon/vs_dc.h +++ b/drivers/gpu/drm/verisilicon/vs_dc.h @@ -81,4 +81,13 @@ struct vs_dc { extern struct platform_driver dc_platform_driver; extern void sifive_l2_flush64_range(unsigned long start, unsigned long len); +void vs_dc_update_cursor_plane(struct vs_dc *dc, struct vs_plane *plane, + struct drm_plane *drm_plane, + struct drm_atomic_state *drm_state); +void vs_dc_disable_cursor_plane(struct vs_dc *dc, struct vs_plane *plane, + struct drm_plane_state *old_state); +int vs_dc_check_cursor_plane(struct vs_dc *dc, struct drm_plane *plane, + struct drm_atomic_state *state); + + #endif /* __VS_DC_H__ */ diff --git a/drivers/gpu/drm/verisilicon/vs_plane.c b/drivers/gpu/drm/verisilicon/vs_plane.c index e53b868a908eb..73c2669ba5818 100644 --- a/drivers/gpu/drm/verisilicon/vs_plane.c +++ b/drivers/gpu/drm/verisilicon/vs_plane.c @@ -18,6 +18,7 @@ #include "vs_plane.h" #include "vs_gem.h" #include "vs_fb.h" +#include "vs_dc.h" void vs_plane_destory(struct drm_plane *plane) { @@ -312,12 +313,90 @@ static void vs_plane_atomic_disable(struct drm_plane *plane, vs_plane->funcs->disable(vs_crtc->dev, vs_plane, old_state); } -const struct drm_plane_helper_funcs vs_plane_helper_funcs = { - .atomic_check = vs_plane_atomic_check, - .atomic_update = vs_plane_atomic_update, - .atomic_disable = vs_plane_atomic_disable, +static void vs_cursor_plane_atomic_update(struct drm_plane *plane, + struct drm_atomic_state *state) +{ + struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, + plane); + struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, + plane); + unsigned char i, num_planes; + struct drm_framebuffer *fb; + struct vs_plane *vs_plane = to_vs_plane(plane); + struct vs_crtc *vs_crtc = to_vs_crtc(new_state->crtc); + struct vs_plane_state *plane_state = to_vs_plane_state(new_state); + struct vs_dc *dc = dev_get_drvdata(vs_crtc->dev); + + if (!new_state->fb || !new_state->crtc) + return; + + fb = new_state->fb; + + num_planes = vs_get_plane_number(fb); + + for (i = 0; i < num_planes; i++) { + struct vs_gem_object *vs_obj; + + vs_obj = vs_fb_get_gem_obj(fb, i); + vs_plane->dma_addr[i] = vs_obj->iova + fb->offsets[i]; + } + + plane_state->status.src = drm_plane_state_src(new_state); + plane_state->status.dest = drm_plane_state_dest(new_state); + + vs_dc_update_cursor_plane(dc, vs_plane, plane, state); +} + +static void vs_cursor_plane_atomic_disable(struct drm_plane *plane, + struct drm_atomic_state *state) +{ + struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, + plane); + struct vs_plane *vs_plane = to_vs_plane(plane); + struct vs_crtc *vs_crtc = to_vs_crtc(old_state->crtc); + struct vs_dc *dc = dev_get_drvdata(vs_crtc->dev); + + vs_dc_disable_cursor_plane(dc, vs_plane, old_state); +} + + +static int vs_cursor_plane_atomic_check(struct drm_plane *plane, + struct drm_atomic_state *state) +{ + struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, + plane); + unsigned char i, num_planes; + struct drm_framebuffer *fb = new_plane_state->fb; + struct drm_crtc *crtc = new_plane_state->crtc; + struct vs_crtc *vs_crtc = to_vs_crtc(crtc); + struct vs_dc *dc = dev_get_drvdata(vs_crtc->dev); + struct vs_plane_state *plane_state = to_vs_plane_state(new_plane_state); + + if (!crtc || !fb) + return 0; + + return vs_dc_check_cursor_plane(dc, plane, state); +} + +const struct drm_plane_helper_funcs primary_plane_helpers = { + .atomic_check = vs_plane_atomic_check, + .atomic_update = vs_plane_atomic_update, + .atomic_disable = vs_plane_atomic_disable, +}; + +const struct drm_plane_helper_funcs overlay_plane_helpers = { + .atomic_check = vs_plane_atomic_check, + .atomic_update = vs_plane_atomic_update, + .atomic_disable = vs_plane_atomic_disable, }; +const struct drm_plane_helper_funcs cursor_plane_helpers = { + .atomic_check = vs_cursor_plane_atomic_check, + .atomic_update = vs_cursor_plane_atomic_update, + .atomic_disable = vs_cursor_plane_atomic_disable, +}; + + static const struct drm_prop_enum_list vs_degamma_mode_enum_list[] = { { VS_DEGAMMA_DISABLE, "disabled" }, { VS_DEGAMMA_BT709, "preset degamma for BT709" }, @@ -346,7 +425,12 @@ struct vs_plane *vs_plane_create(struct drm_device *drm_dev, if (ret) goto err_free_plane; - drm_plane_helper_add(&plane->base, &vs_plane_helper_funcs); + if (info->type == DRM_PLANE_TYPE_PRIMARY) + drm_plane_helper_add(&plane->base, &primary_plane_helpers); + else if (info->type == DRM_PLANE_TYPE_CURSOR) + drm_plane_helper_add(&plane->base, &cursor_plane_helpers); + else + drm_plane_helper_add(&plane->base, &overlay_plane_helpers); /* Set up the plane properties */ if (info->degamma_size) { diff --git a/drivers/gpu/drm/verisilicon/vs_plane.h b/drivers/gpu/drm/verisilicon/vs_plane.h index fc46fd7f5c8ef..f613c1b2c3a39 100644 --- a/drivers/gpu/drm/verisilicon/vs_plane.h +++ b/drivers/gpu/drm/verisilicon/vs_plane.h @@ -35,6 +35,7 @@ struct vs_plane_status { struct vs_plane_state { struct drm_plane_state base; struct vs_plane_status status; /* for debugfs */ + dma_addr_t dma_addr[MAX_NUM_PLANES]; struct drm_property_blob *watermark; struct drm_property_blob *color_mgmt;