162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright 2019 NXP. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <drm/drm_atomic.h> 762306a36Sopenharmony_ci#include <drm/drm_atomic_helper.h> 862306a36Sopenharmony_ci#include <drm/drm_blend.h> 962306a36Sopenharmony_ci#include <drm/drm_fb_dma_helper.h> 1062306a36Sopenharmony_ci#include <drm/drm_framebuffer.h> 1162306a36Sopenharmony_ci#include <drm/drm_gem_atomic_helper.h> 1262306a36Sopenharmony_ci#include <drm/drm_gem_dma_helper.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include "dcss-dev.h" 1562306a36Sopenharmony_ci#include "dcss-kms.h" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_cistatic const u32 dcss_common_formats[] = { 1862306a36Sopenharmony_ci /* RGB */ 1962306a36Sopenharmony_ci DRM_FORMAT_ARGB8888, 2062306a36Sopenharmony_ci DRM_FORMAT_XRGB8888, 2162306a36Sopenharmony_ci DRM_FORMAT_ABGR8888, 2262306a36Sopenharmony_ci DRM_FORMAT_XBGR8888, 2362306a36Sopenharmony_ci DRM_FORMAT_RGBA8888, 2462306a36Sopenharmony_ci DRM_FORMAT_RGBX8888, 2562306a36Sopenharmony_ci DRM_FORMAT_BGRA8888, 2662306a36Sopenharmony_ci DRM_FORMAT_BGRX8888, 2762306a36Sopenharmony_ci DRM_FORMAT_XRGB2101010, 2862306a36Sopenharmony_ci DRM_FORMAT_XBGR2101010, 2962306a36Sopenharmony_ci DRM_FORMAT_RGBX1010102, 3062306a36Sopenharmony_ci DRM_FORMAT_BGRX1010102, 3162306a36Sopenharmony_ci DRM_FORMAT_ARGB2101010, 3262306a36Sopenharmony_ci DRM_FORMAT_ABGR2101010, 3362306a36Sopenharmony_ci DRM_FORMAT_RGBA1010102, 3462306a36Sopenharmony_ci DRM_FORMAT_BGRA1010102, 3562306a36Sopenharmony_ci}; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistatic const u64 dcss_video_format_modifiers[] = { 3862306a36Sopenharmony_ci DRM_FORMAT_MOD_LINEAR, 3962306a36Sopenharmony_ci DRM_FORMAT_MOD_INVALID, 4062306a36Sopenharmony_ci}; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cistatic const u64 dcss_graphics_format_modifiers[] = { 4362306a36Sopenharmony_ci DRM_FORMAT_MOD_VIVANTE_TILED, 4462306a36Sopenharmony_ci DRM_FORMAT_MOD_VIVANTE_SUPER_TILED, 4562306a36Sopenharmony_ci DRM_FORMAT_MOD_LINEAR, 4662306a36Sopenharmony_ci DRM_FORMAT_MOD_INVALID, 4762306a36Sopenharmony_ci}; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistatic inline struct dcss_plane *to_dcss_plane(struct drm_plane *p) 5062306a36Sopenharmony_ci{ 5162306a36Sopenharmony_ci return container_of(p, struct dcss_plane, base); 5262306a36Sopenharmony_ci} 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_cistatic inline bool dcss_plane_fb_is_linear(const struct drm_framebuffer *fb) 5562306a36Sopenharmony_ci{ 5662306a36Sopenharmony_ci return ((fb->flags & DRM_MODE_FB_MODIFIERS) == 0) || 5762306a36Sopenharmony_ci ((fb->flags & DRM_MODE_FB_MODIFIERS) != 0 && 5862306a36Sopenharmony_ci fb->modifier == DRM_FORMAT_MOD_LINEAR); 5962306a36Sopenharmony_ci} 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cistatic void dcss_plane_destroy(struct drm_plane *plane) 6262306a36Sopenharmony_ci{ 6362306a36Sopenharmony_ci struct dcss_plane *dcss_plane = container_of(plane, struct dcss_plane, 6462306a36Sopenharmony_ci base); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci drm_plane_cleanup(plane); 6762306a36Sopenharmony_ci kfree(dcss_plane); 6862306a36Sopenharmony_ci} 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic bool dcss_plane_format_mod_supported(struct drm_plane *plane, 7162306a36Sopenharmony_ci u32 format, 7262306a36Sopenharmony_ci u64 modifier) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci switch (plane->type) { 7562306a36Sopenharmony_ci case DRM_PLANE_TYPE_PRIMARY: 7662306a36Sopenharmony_ci switch (format) { 7762306a36Sopenharmony_ci case DRM_FORMAT_ARGB8888: 7862306a36Sopenharmony_ci case DRM_FORMAT_XRGB8888: 7962306a36Sopenharmony_ci case DRM_FORMAT_ARGB2101010: 8062306a36Sopenharmony_ci return modifier == DRM_FORMAT_MOD_LINEAR || 8162306a36Sopenharmony_ci modifier == DRM_FORMAT_MOD_VIVANTE_TILED || 8262306a36Sopenharmony_ci modifier == DRM_FORMAT_MOD_VIVANTE_SUPER_TILED; 8362306a36Sopenharmony_ci default: 8462306a36Sopenharmony_ci return modifier == DRM_FORMAT_MOD_LINEAR; 8562306a36Sopenharmony_ci } 8662306a36Sopenharmony_ci break; 8762306a36Sopenharmony_ci case DRM_PLANE_TYPE_OVERLAY: 8862306a36Sopenharmony_ci return modifier == DRM_FORMAT_MOD_LINEAR; 8962306a36Sopenharmony_ci default: 9062306a36Sopenharmony_ci return false; 9162306a36Sopenharmony_ci } 9262306a36Sopenharmony_ci} 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_cistatic const struct drm_plane_funcs dcss_plane_funcs = { 9562306a36Sopenharmony_ci .update_plane = drm_atomic_helper_update_plane, 9662306a36Sopenharmony_ci .disable_plane = drm_atomic_helper_disable_plane, 9762306a36Sopenharmony_ci .destroy = dcss_plane_destroy, 9862306a36Sopenharmony_ci .reset = drm_atomic_helper_plane_reset, 9962306a36Sopenharmony_ci .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, 10062306a36Sopenharmony_ci .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, 10162306a36Sopenharmony_ci .format_mod_supported = dcss_plane_format_mod_supported, 10262306a36Sopenharmony_ci}; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic bool dcss_plane_can_rotate(const struct drm_format_info *format, 10562306a36Sopenharmony_ci bool mod_present, u64 modifier, 10662306a36Sopenharmony_ci unsigned int rotation) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci bool linear_format = !mod_present || modifier == DRM_FORMAT_MOD_LINEAR; 10962306a36Sopenharmony_ci u32 supported_rotation = DRM_MODE_ROTATE_0; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci if (!format->is_yuv && linear_format) 11262306a36Sopenharmony_ci supported_rotation = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 | 11362306a36Sopenharmony_ci DRM_MODE_REFLECT_MASK; 11462306a36Sopenharmony_ci else if (!format->is_yuv && 11562306a36Sopenharmony_ci (modifier == DRM_FORMAT_MOD_VIVANTE_TILED || 11662306a36Sopenharmony_ci modifier == DRM_FORMAT_MOD_VIVANTE_SUPER_TILED)) 11762306a36Sopenharmony_ci supported_rotation = DRM_MODE_ROTATE_MASK | 11862306a36Sopenharmony_ci DRM_MODE_REFLECT_MASK; 11962306a36Sopenharmony_ci else if (format->is_yuv && linear_format && 12062306a36Sopenharmony_ci (format->format == DRM_FORMAT_NV12 || 12162306a36Sopenharmony_ci format->format == DRM_FORMAT_NV21)) 12262306a36Sopenharmony_ci supported_rotation = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 | 12362306a36Sopenharmony_ci DRM_MODE_REFLECT_MASK; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci return !!(rotation & supported_rotation); 12662306a36Sopenharmony_ci} 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_cistatic bool dcss_plane_is_source_size_allowed(u16 src_w, u16 src_h, u32 pix_fmt) 12962306a36Sopenharmony_ci{ 13062306a36Sopenharmony_ci if (src_w < 64 && 13162306a36Sopenharmony_ci (pix_fmt == DRM_FORMAT_NV12 || pix_fmt == DRM_FORMAT_NV21)) 13262306a36Sopenharmony_ci return false; 13362306a36Sopenharmony_ci else if (src_w < 32 && 13462306a36Sopenharmony_ci (pix_fmt == DRM_FORMAT_UYVY || pix_fmt == DRM_FORMAT_VYUY || 13562306a36Sopenharmony_ci pix_fmt == DRM_FORMAT_YUYV || pix_fmt == DRM_FORMAT_YVYU)) 13662306a36Sopenharmony_ci return false; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci return src_w >= 16 && src_h >= 8; 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cistatic int dcss_plane_atomic_check(struct drm_plane *plane, 14262306a36Sopenharmony_ci struct drm_atomic_state *state) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, 14562306a36Sopenharmony_ci plane); 14662306a36Sopenharmony_ci struct dcss_plane *dcss_plane = to_dcss_plane(plane); 14762306a36Sopenharmony_ci struct dcss_dev *dcss = plane->dev->dev_private; 14862306a36Sopenharmony_ci struct drm_framebuffer *fb = new_plane_state->fb; 14962306a36Sopenharmony_ci bool is_primary_plane = plane->type == DRM_PLANE_TYPE_PRIMARY; 15062306a36Sopenharmony_ci struct drm_gem_dma_object *dma_obj; 15162306a36Sopenharmony_ci struct drm_crtc_state *crtc_state; 15262306a36Sopenharmony_ci int hdisplay, vdisplay; 15362306a36Sopenharmony_ci int min, max; 15462306a36Sopenharmony_ci int ret; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci if (!fb || !new_plane_state->crtc) 15762306a36Sopenharmony_ci return 0; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci dma_obj = drm_fb_dma_get_gem_obj(fb, 0); 16062306a36Sopenharmony_ci WARN_ON(!dma_obj); 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci crtc_state = drm_atomic_get_existing_crtc_state(state, 16362306a36Sopenharmony_ci new_plane_state->crtc); 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci hdisplay = crtc_state->adjusted_mode.hdisplay; 16662306a36Sopenharmony_ci vdisplay = crtc_state->adjusted_mode.vdisplay; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci if (!dcss_plane_is_source_size_allowed(new_plane_state->src_w >> 16, 16962306a36Sopenharmony_ci new_plane_state->src_h >> 16, 17062306a36Sopenharmony_ci fb->format->format)) { 17162306a36Sopenharmony_ci DRM_DEBUG_KMS("Source plane size is not allowed!\n"); 17262306a36Sopenharmony_ci return -EINVAL; 17362306a36Sopenharmony_ci } 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci dcss_scaler_get_min_max_ratios(dcss->scaler, dcss_plane->ch_num, 17662306a36Sopenharmony_ci &min, &max); 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, 17962306a36Sopenharmony_ci min, max, !is_primary_plane, 18062306a36Sopenharmony_ci false); 18162306a36Sopenharmony_ci if (ret) 18262306a36Sopenharmony_ci return ret; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci if (!new_plane_state->visible) 18562306a36Sopenharmony_ci return 0; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci if (!dcss_plane_can_rotate(fb->format, 18862306a36Sopenharmony_ci !!(fb->flags & DRM_MODE_FB_MODIFIERS), 18962306a36Sopenharmony_ci fb->modifier, 19062306a36Sopenharmony_ci new_plane_state->rotation)) { 19162306a36Sopenharmony_ci DRM_DEBUG_KMS("requested rotation is not allowed!\n"); 19262306a36Sopenharmony_ci return -EINVAL; 19362306a36Sopenharmony_ci } 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci if ((new_plane_state->crtc_x < 0 || new_plane_state->crtc_y < 0 || 19662306a36Sopenharmony_ci new_plane_state->crtc_x + new_plane_state->crtc_w > hdisplay || 19762306a36Sopenharmony_ci new_plane_state->crtc_y + new_plane_state->crtc_h > vdisplay) && 19862306a36Sopenharmony_ci !dcss_plane_fb_is_linear(fb)) { 19962306a36Sopenharmony_ci DRM_DEBUG_KMS("requested cropping operation is not allowed!\n"); 20062306a36Sopenharmony_ci return -EINVAL; 20162306a36Sopenharmony_ci } 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci if ((fb->flags & DRM_MODE_FB_MODIFIERS) && 20462306a36Sopenharmony_ci !plane->funcs->format_mod_supported(plane, 20562306a36Sopenharmony_ci fb->format->format, 20662306a36Sopenharmony_ci fb->modifier)) { 20762306a36Sopenharmony_ci DRM_DEBUG_KMS("Invalid modifier: %llx", fb->modifier); 20862306a36Sopenharmony_ci return -EINVAL; 20962306a36Sopenharmony_ci } 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci return 0; 21262306a36Sopenharmony_ci} 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_cistatic void dcss_plane_atomic_set_base(struct dcss_plane *dcss_plane) 21562306a36Sopenharmony_ci{ 21662306a36Sopenharmony_ci struct drm_plane *plane = &dcss_plane->base; 21762306a36Sopenharmony_ci struct drm_plane_state *state = plane->state; 21862306a36Sopenharmony_ci struct dcss_dev *dcss = plane->dev->dev_private; 21962306a36Sopenharmony_ci struct drm_framebuffer *fb = state->fb; 22062306a36Sopenharmony_ci const struct drm_format_info *format = fb->format; 22162306a36Sopenharmony_ci struct drm_gem_dma_object *dma_obj = drm_fb_dma_get_gem_obj(fb, 0); 22262306a36Sopenharmony_ci unsigned long p1_ba = 0, p2_ba = 0; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci if (!format->is_yuv || 22562306a36Sopenharmony_ci format->format == DRM_FORMAT_NV12 || 22662306a36Sopenharmony_ci format->format == DRM_FORMAT_NV21) 22762306a36Sopenharmony_ci p1_ba = dma_obj->dma_addr + fb->offsets[0] + 22862306a36Sopenharmony_ci fb->pitches[0] * (state->src.y1 >> 16) + 22962306a36Sopenharmony_ci format->char_per_block[0] * (state->src.x1 >> 16); 23062306a36Sopenharmony_ci else if (format->format == DRM_FORMAT_UYVY || 23162306a36Sopenharmony_ci format->format == DRM_FORMAT_VYUY || 23262306a36Sopenharmony_ci format->format == DRM_FORMAT_YUYV || 23362306a36Sopenharmony_ci format->format == DRM_FORMAT_YVYU) 23462306a36Sopenharmony_ci p1_ba = dma_obj->dma_addr + fb->offsets[0] + 23562306a36Sopenharmony_ci fb->pitches[0] * (state->src.y1 >> 16) + 23662306a36Sopenharmony_ci 2 * format->char_per_block[0] * (state->src.x1 >> 17); 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci if (format->format == DRM_FORMAT_NV12 || 23962306a36Sopenharmony_ci format->format == DRM_FORMAT_NV21) 24062306a36Sopenharmony_ci p2_ba = dma_obj->dma_addr + fb->offsets[1] + 24162306a36Sopenharmony_ci (((fb->pitches[1] >> 1) * (state->src.y1 >> 17) + 24262306a36Sopenharmony_ci (state->src.x1 >> 17)) << 1); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci dcss_dpr_addr_set(dcss->dpr, dcss_plane->ch_num, p1_ba, p2_ba, 24562306a36Sopenharmony_ci fb->pitches[0]); 24662306a36Sopenharmony_ci} 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_cistatic bool dcss_plane_needs_setup(struct drm_plane_state *state, 24962306a36Sopenharmony_ci struct drm_plane_state *old_state) 25062306a36Sopenharmony_ci{ 25162306a36Sopenharmony_ci struct drm_framebuffer *fb = state->fb; 25262306a36Sopenharmony_ci struct drm_framebuffer *old_fb = old_state->fb; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci return state->crtc_x != old_state->crtc_x || 25562306a36Sopenharmony_ci state->crtc_y != old_state->crtc_y || 25662306a36Sopenharmony_ci state->crtc_w != old_state->crtc_w || 25762306a36Sopenharmony_ci state->crtc_h != old_state->crtc_h || 25862306a36Sopenharmony_ci state->src_x != old_state->src_x || 25962306a36Sopenharmony_ci state->src_y != old_state->src_y || 26062306a36Sopenharmony_ci state->src_w != old_state->src_w || 26162306a36Sopenharmony_ci state->src_h != old_state->src_h || 26262306a36Sopenharmony_ci fb->format->format != old_fb->format->format || 26362306a36Sopenharmony_ci fb->modifier != old_fb->modifier || 26462306a36Sopenharmony_ci state->rotation != old_state->rotation || 26562306a36Sopenharmony_ci state->scaling_filter != old_state->scaling_filter; 26662306a36Sopenharmony_ci} 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_cistatic void dcss_plane_atomic_update(struct drm_plane *plane, 26962306a36Sopenharmony_ci struct drm_atomic_state *state) 27062306a36Sopenharmony_ci{ 27162306a36Sopenharmony_ci struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, 27262306a36Sopenharmony_ci plane); 27362306a36Sopenharmony_ci struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, 27462306a36Sopenharmony_ci plane); 27562306a36Sopenharmony_ci struct dcss_plane *dcss_plane = to_dcss_plane(plane); 27662306a36Sopenharmony_ci struct dcss_dev *dcss = plane->dev->dev_private; 27762306a36Sopenharmony_ci struct drm_framebuffer *fb = new_state->fb; 27862306a36Sopenharmony_ci struct drm_crtc_state *crtc_state; 27962306a36Sopenharmony_ci bool modifiers_present; 28062306a36Sopenharmony_ci u32 src_w, src_h, dst_w, dst_h; 28162306a36Sopenharmony_ci struct drm_rect src, dst; 28262306a36Sopenharmony_ci bool enable = true; 28362306a36Sopenharmony_ci bool is_rotation_90_or_270; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci if (!fb || !new_state->crtc || !new_state->visible) 28662306a36Sopenharmony_ci return; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci crtc_state = new_state->crtc->state; 28962306a36Sopenharmony_ci modifiers_present = !!(fb->flags & DRM_MODE_FB_MODIFIERS); 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci if (old_state->fb && !drm_atomic_crtc_needs_modeset(crtc_state) && 29262306a36Sopenharmony_ci !dcss_plane_needs_setup(new_state, old_state)) { 29362306a36Sopenharmony_ci dcss_plane_atomic_set_base(dcss_plane); 29462306a36Sopenharmony_ci return; 29562306a36Sopenharmony_ci } 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci src = plane->state->src; 29862306a36Sopenharmony_ci dst = plane->state->dst; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci /* 30162306a36Sopenharmony_ci * The width and height after clipping. 30262306a36Sopenharmony_ci */ 30362306a36Sopenharmony_ci src_w = drm_rect_width(&src) >> 16; 30462306a36Sopenharmony_ci src_h = drm_rect_height(&src) >> 16; 30562306a36Sopenharmony_ci dst_w = drm_rect_width(&dst); 30662306a36Sopenharmony_ci dst_h = drm_rect_height(&dst); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci if (plane->type == DRM_PLANE_TYPE_OVERLAY && 30962306a36Sopenharmony_ci modifiers_present && fb->modifier == DRM_FORMAT_MOD_LINEAR) 31062306a36Sopenharmony_ci modifiers_present = false; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci dcss_dpr_format_set(dcss->dpr, dcss_plane->ch_num, 31362306a36Sopenharmony_ci new_state->fb->format, 31462306a36Sopenharmony_ci modifiers_present ? fb->modifier : 31562306a36Sopenharmony_ci DRM_FORMAT_MOD_LINEAR); 31662306a36Sopenharmony_ci dcss_dpr_set_res(dcss->dpr, dcss_plane->ch_num, src_w, src_h); 31762306a36Sopenharmony_ci dcss_dpr_set_rotation(dcss->dpr, dcss_plane->ch_num, 31862306a36Sopenharmony_ci new_state->rotation); 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci dcss_plane_atomic_set_base(dcss_plane); 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci is_rotation_90_or_270 = new_state->rotation & (DRM_MODE_ROTATE_90 | 32362306a36Sopenharmony_ci DRM_MODE_ROTATE_270); 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci dcss_scaler_set_filter(dcss->scaler, dcss_plane->ch_num, 32662306a36Sopenharmony_ci new_state->scaling_filter); 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci dcss_scaler_setup(dcss->scaler, dcss_plane->ch_num, 32962306a36Sopenharmony_ci new_state->fb->format, 33062306a36Sopenharmony_ci is_rotation_90_or_270 ? src_h : src_w, 33162306a36Sopenharmony_ci is_rotation_90_or_270 ? src_w : src_h, 33262306a36Sopenharmony_ci dst_w, dst_h, 33362306a36Sopenharmony_ci drm_mode_vrefresh(&crtc_state->mode)); 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci dcss_dtg_plane_pos_set(dcss->dtg, dcss_plane->ch_num, 33662306a36Sopenharmony_ci dst.x1, dst.y1, dst_w, dst_h); 33762306a36Sopenharmony_ci dcss_dtg_plane_alpha_set(dcss->dtg, dcss_plane->ch_num, 33862306a36Sopenharmony_ci fb->format, new_state->alpha >> 8); 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci if (!dcss_plane->ch_num && (new_state->alpha >> 8) == 0) 34162306a36Sopenharmony_ci enable = false; 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci dcss_dpr_enable(dcss->dpr, dcss_plane->ch_num, enable); 34462306a36Sopenharmony_ci dcss_scaler_ch_enable(dcss->scaler, dcss_plane->ch_num, enable); 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci if (!enable) 34762306a36Sopenharmony_ci dcss_dtg_plane_pos_set(dcss->dtg, dcss_plane->ch_num, 34862306a36Sopenharmony_ci 0, 0, 0, 0); 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci dcss_dtg_ch_enable(dcss->dtg, dcss_plane->ch_num, enable); 35162306a36Sopenharmony_ci} 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_cistatic void dcss_plane_atomic_disable(struct drm_plane *plane, 35462306a36Sopenharmony_ci struct drm_atomic_state *state) 35562306a36Sopenharmony_ci{ 35662306a36Sopenharmony_ci struct dcss_plane *dcss_plane = to_dcss_plane(plane); 35762306a36Sopenharmony_ci struct dcss_dev *dcss = plane->dev->dev_private; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci dcss_dpr_enable(dcss->dpr, dcss_plane->ch_num, false); 36062306a36Sopenharmony_ci dcss_scaler_ch_enable(dcss->scaler, dcss_plane->ch_num, false); 36162306a36Sopenharmony_ci dcss_dtg_plane_pos_set(dcss->dtg, dcss_plane->ch_num, 0, 0, 0, 0); 36262306a36Sopenharmony_ci dcss_dtg_ch_enable(dcss->dtg, dcss_plane->ch_num, false); 36362306a36Sopenharmony_ci} 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_cistatic const struct drm_plane_helper_funcs dcss_plane_helper_funcs = { 36662306a36Sopenharmony_ci .atomic_check = dcss_plane_atomic_check, 36762306a36Sopenharmony_ci .atomic_update = dcss_plane_atomic_update, 36862306a36Sopenharmony_ci .atomic_disable = dcss_plane_atomic_disable, 36962306a36Sopenharmony_ci}; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_cistruct dcss_plane *dcss_plane_init(struct drm_device *drm, 37262306a36Sopenharmony_ci unsigned int possible_crtcs, 37362306a36Sopenharmony_ci enum drm_plane_type type, 37462306a36Sopenharmony_ci unsigned int zpos) 37562306a36Sopenharmony_ci{ 37662306a36Sopenharmony_ci struct dcss_plane *dcss_plane; 37762306a36Sopenharmony_ci const u64 *format_modifiers = dcss_video_format_modifiers; 37862306a36Sopenharmony_ci int ret; 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci if (zpos > 2) 38162306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci dcss_plane = kzalloc(sizeof(*dcss_plane), GFP_KERNEL); 38462306a36Sopenharmony_ci if (!dcss_plane) { 38562306a36Sopenharmony_ci DRM_ERROR("failed to allocate plane\n"); 38662306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 38762306a36Sopenharmony_ci } 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci if (type == DRM_PLANE_TYPE_PRIMARY) 39062306a36Sopenharmony_ci format_modifiers = dcss_graphics_format_modifiers; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci ret = drm_universal_plane_init(drm, &dcss_plane->base, possible_crtcs, 39362306a36Sopenharmony_ci &dcss_plane_funcs, dcss_common_formats, 39462306a36Sopenharmony_ci ARRAY_SIZE(dcss_common_formats), 39562306a36Sopenharmony_ci format_modifiers, type, NULL); 39662306a36Sopenharmony_ci if (ret) { 39762306a36Sopenharmony_ci DRM_ERROR("failed to initialize plane\n"); 39862306a36Sopenharmony_ci kfree(dcss_plane); 39962306a36Sopenharmony_ci return ERR_PTR(ret); 40062306a36Sopenharmony_ci } 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci drm_plane_helper_add(&dcss_plane->base, &dcss_plane_helper_funcs); 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci ret = drm_plane_create_zpos_immutable_property(&dcss_plane->base, zpos); 40562306a36Sopenharmony_ci if (ret) 40662306a36Sopenharmony_ci return ERR_PTR(ret); 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci drm_plane_create_scaling_filter_property(&dcss_plane->base, 40962306a36Sopenharmony_ci BIT(DRM_SCALING_FILTER_DEFAULT) | 41062306a36Sopenharmony_ci BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR)); 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci drm_plane_create_rotation_property(&dcss_plane->base, 41362306a36Sopenharmony_ci DRM_MODE_ROTATE_0, 41462306a36Sopenharmony_ci DRM_MODE_ROTATE_0 | 41562306a36Sopenharmony_ci DRM_MODE_ROTATE_90 | 41662306a36Sopenharmony_ci DRM_MODE_ROTATE_180 | 41762306a36Sopenharmony_ci DRM_MODE_ROTATE_270 | 41862306a36Sopenharmony_ci DRM_MODE_REFLECT_X | 41962306a36Sopenharmony_ci DRM_MODE_REFLECT_Y); 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci dcss_plane->ch_num = zpos; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci return dcss_plane; 42462306a36Sopenharmony_ci} 425