18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright 2019 NXP. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <drm/drm_atomic.h> 78c2ecf20Sopenharmony_ci#include <drm/drm_atomic_helper.h> 88c2ecf20Sopenharmony_ci#include <drm/drm_fb_cma_helper.h> 98c2ecf20Sopenharmony_ci#include <drm/drm_gem_framebuffer_helper.h> 108c2ecf20Sopenharmony_ci#include <drm/drm_gem_cma_helper.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include "dcss-dev.h" 138c2ecf20Sopenharmony_ci#include "dcss-kms.h" 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_cistatic const u32 dcss_common_formats[] = { 168c2ecf20Sopenharmony_ci /* RGB */ 178c2ecf20Sopenharmony_ci DRM_FORMAT_ARGB8888, 188c2ecf20Sopenharmony_ci DRM_FORMAT_XRGB8888, 198c2ecf20Sopenharmony_ci DRM_FORMAT_ABGR8888, 208c2ecf20Sopenharmony_ci DRM_FORMAT_XBGR8888, 218c2ecf20Sopenharmony_ci DRM_FORMAT_RGBA8888, 228c2ecf20Sopenharmony_ci DRM_FORMAT_RGBX8888, 238c2ecf20Sopenharmony_ci DRM_FORMAT_BGRA8888, 248c2ecf20Sopenharmony_ci DRM_FORMAT_BGRX8888, 258c2ecf20Sopenharmony_ci DRM_FORMAT_XRGB2101010, 268c2ecf20Sopenharmony_ci DRM_FORMAT_XBGR2101010, 278c2ecf20Sopenharmony_ci DRM_FORMAT_RGBX1010102, 288c2ecf20Sopenharmony_ci DRM_FORMAT_BGRX1010102, 298c2ecf20Sopenharmony_ci DRM_FORMAT_ARGB2101010, 308c2ecf20Sopenharmony_ci DRM_FORMAT_ABGR2101010, 318c2ecf20Sopenharmony_ci DRM_FORMAT_RGBA1010102, 328c2ecf20Sopenharmony_ci DRM_FORMAT_BGRA1010102, 338c2ecf20Sopenharmony_ci}; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistatic const u64 dcss_video_format_modifiers[] = { 368c2ecf20Sopenharmony_ci DRM_FORMAT_MOD_LINEAR, 378c2ecf20Sopenharmony_ci DRM_FORMAT_MOD_INVALID, 388c2ecf20Sopenharmony_ci}; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistatic const u64 dcss_graphics_format_modifiers[] = { 418c2ecf20Sopenharmony_ci DRM_FORMAT_MOD_VIVANTE_TILED, 428c2ecf20Sopenharmony_ci DRM_FORMAT_MOD_VIVANTE_SUPER_TILED, 438c2ecf20Sopenharmony_ci DRM_FORMAT_MOD_LINEAR, 448c2ecf20Sopenharmony_ci DRM_FORMAT_MOD_INVALID, 458c2ecf20Sopenharmony_ci}; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_cistatic inline struct dcss_plane *to_dcss_plane(struct drm_plane *p) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci return container_of(p, struct dcss_plane, base); 508c2ecf20Sopenharmony_ci} 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_cistatic inline bool dcss_plane_fb_is_linear(const struct drm_framebuffer *fb) 538c2ecf20Sopenharmony_ci{ 548c2ecf20Sopenharmony_ci return ((fb->flags & DRM_MODE_FB_MODIFIERS) == 0) || 558c2ecf20Sopenharmony_ci ((fb->flags & DRM_MODE_FB_MODIFIERS) != 0 && 568c2ecf20Sopenharmony_ci fb->modifier == DRM_FORMAT_MOD_LINEAR); 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistatic void dcss_plane_destroy(struct drm_plane *plane) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci struct dcss_plane *dcss_plane = container_of(plane, struct dcss_plane, 628c2ecf20Sopenharmony_ci base); 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci drm_plane_cleanup(plane); 658c2ecf20Sopenharmony_ci kfree(dcss_plane); 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_cistatic bool dcss_plane_format_mod_supported(struct drm_plane *plane, 698c2ecf20Sopenharmony_ci u32 format, 708c2ecf20Sopenharmony_ci u64 modifier) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci switch (plane->type) { 738c2ecf20Sopenharmony_ci case DRM_PLANE_TYPE_PRIMARY: 748c2ecf20Sopenharmony_ci switch (format) { 758c2ecf20Sopenharmony_ci case DRM_FORMAT_ARGB8888: 768c2ecf20Sopenharmony_ci case DRM_FORMAT_XRGB8888: 778c2ecf20Sopenharmony_ci case DRM_FORMAT_ARGB2101010: 788c2ecf20Sopenharmony_ci return modifier == DRM_FORMAT_MOD_LINEAR || 798c2ecf20Sopenharmony_ci modifier == DRM_FORMAT_MOD_VIVANTE_TILED || 808c2ecf20Sopenharmony_ci modifier == DRM_FORMAT_MOD_VIVANTE_SUPER_TILED; 818c2ecf20Sopenharmony_ci default: 828c2ecf20Sopenharmony_ci return modifier == DRM_FORMAT_MOD_LINEAR; 838c2ecf20Sopenharmony_ci } 848c2ecf20Sopenharmony_ci break; 858c2ecf20Sopenharmony_ci case DRM_PLANE_TYPE_OVERLAY: 868c2ecf20Sopenharmony_ci return modifier == DRM_FORMAT_MOD_LINEAR; 878c2ecf20Sopenharmony_ci default: 888c2ecf20Sopenharmony_ci return false; 898c2ecf20Sopenharmony_ci } 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cistatic const struct drm_plane_funcs dcss_plane_funcs = { 938c2ecf20Sopenharmony_ci .update_plane = drm_atomic_helper_update_plane, 948c2ecf20Sopenharmony_ci .disable_plane = drm_atomic_helper_disable_plane, 958c2ecf20Sopenharmony_ci .destroy = dcss_plane_destroy, 968c2ecf20Sopenharmony_ci .reset = drm_atomic_helper_plane_reset, 978c2ecf20Sopenharmony_ci .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, 988c2ecf20Sopenharmony_ci .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, 998c2ecf20Sopenharmony_ci .format_mod_supported = dcss_plane_format_mod_supported, 1008c2ecf20Sopenharmony_ci}; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_cistatic bool dcss_plane_can_rotate(const struct drm_format_info *format, 1038c2ecf20Sopenharmony_ci bool mod_present, u64 modifier, 1048c2ecf20Sopenharmony_ci unsigned int rotation) 1058c2ecf20Sopenharmony_ci{ 1068c2ecf20Sopenharmony_ci bool linear_format = !mod_present || 1078c2ecf20Sopenharmony_ci (mod_present && modifier == DRM_FORMAT_MOD_LINEAR); 1088c2ecf20Sopenharmony_ci u32 supported_rotation = DRM_MODE_ROTATE_0; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci if (!format->is_yuv && linear_format) 1118c2ecf20Sopenharmony_ci supported_rotation = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 | 1128c2ecf20Sopenharmony_ci DRM_MODE_REFLECT_MASK; 1138c2ecf20Sopenharmony_ci else if (!format->is_yuv && 1148c2ecf20Sopenharmony_ci (modifier == DRM_FORMAT_MOD_VIVANTE_TILED || 1158c2ecf20Sopenharmony_ci modifier == DRM_FORMAT_MOD_VIVANTE_SUPER_TILED)) 1168c2ecf20Sopenharmony_ci supported_rotation = DRM_MODE_ROTATE_MASK | 1178c2ecf20Sopenharmony_ci DRM_MODE_REFLECT_MASK; 1188c2ecf20Sopenharmony_ci else if (format->is_yuv && linear_format && 1198c2ecf20Sopenharmony_ci (format->format == DRM_FORMAT_NV12 || 1208c2ecf20Sopenharmony_ci format->format == DRM_FORMAT_NV21)) 1218c2ecf20Sopenharmony_ci supported_rotation = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 | 1228c2ecf20Sopenharmony_ci DRM_MODE_REFLECT_MASK; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci return !!(rotation & supported_rotation); 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cistatic bool dcss_plane_is_source_size_allowed(u16 src_w, u16 src_h, u32 pix_fmt) 1288c2ecf20Sopenharmony_ci{ 1298c2ecf20Sopenharmony_ci if (src_w < 64 && 1308c2ecf20Sopenharmony_ci (pix_fmt == DRM_FORMAT_NV12 || pix_fmt == DRM_FORMAT_NV21)) 1318c2ecf20Sopenharmony_ci return false; 1328c2ecf20Sopenharmony_ci else if (src_w < 32 && 1338c2ecf20Sopenharmony_ci (pix_fmt == DRM_FORMAT_UYVY || pix_fmt == DRM_FORMAT_VYUY || 1348c2ecf20Sopenharmony_ci pix_fmt == DRM_FORMAT_YUYV || pix_fmt == DRM_FORMAT_YVYU)) 1358c2ecf20Sopenharmony_ci return false; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci return src_w >= 16 && src_h >= 8; 1388c2ecf20Sopenharmony_ci} 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_cistatic int dcss_plane_atomic_check(struct drm_plane *plane, 1418c2ecf20Sopenharmony_ci struct drm_plane_state *state) 1428c2ecf20Sopenharmony_ci{ 1438c2ecf20Sopenharmony_ci struct dcss_plane *dcss_plane = to_dcss_plane(plane); 1448c2ecf20Sopenharmony_ci struct dcss_dev *dcss = plane->dev->dev_private; 1458c2ecf20Sopenharmony_ci struct drm_framebuffer *fb = state->fb; 1468c2ecf20Sopenharmony_ci bool is_primary_plane = plane->type == DRM_PLANE_TYPE_PRIMARY; 1478c2ecf20Sopenharmony_ci struct drm_gem_cma_object *cma_obj; 1488c2ecf20Sopenharmony_ci struct drm_crtc_state *crtc_state; 1498c2ecf20Sopenharmony_ci int hdisplay, vdisplay; 1508c2ecf20Sopenharmony_ci int min, max; 1518c2ecf20Sopenharmony_ci int ret; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci if (!fb || !state->crtc) 1548c2ecf20Sopenharmony_ci return 0; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci cma_obj = drm_fb_cma_get_gem_obj(fb, 0); 1578c2ecf20Sopenharmony_ci WARN_ON(!cma_obj); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci crtc_state = drm_atomic_get_existing_crtc_state(state->state, 1608c2ecf20Sopenharmony_ci state->crtc); 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci hdisplay = crtc_state->adjusted_mode.hdisplay; 1638c2ecf20Sopenharmony_ci vdisplay = crtc_state->adjusted_mode.vdisplay; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci if (!dcss_plane_is_source_size_allowed(state->src_w >> 16, 1668c2ecf20Sopenharmony_ci state->src_h >> 16, 1678c2ecf20Sopenharmony_ci fb->format->format)) { 1688c2ecf20Sopenharmony_ci DRM_DEBUG_KMS("Source plane size is not allowed!\n"); 1698c2ecf20Sopenharmony_ci return -EINVAL; 1708c2ecf20Sopenharmony_ci } 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci dcss_scaler_get_min_max_ratios(dcss->scaler, dcss_plane->ch_num, 1738c2ecf20Sopenharmony_ci &min, &max); 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci ret = drm_atomic_helper_check_plane_state(state, crtc_state, 1768c2ecf20Sopenharmony_ci min, max, !is_primary_plane, 1778c2ecf20Sopenharmony_ci false); 1788c2ecf20Sopenharmony_ci if (ret) 1798c2ecf20Sopenharmony_ci return ret; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci if (!state->visible) 1828c2ecf20Sopenharmony_ci return 0; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci if (!dcss_plane_can_rotate(fb->format, 1858c2ecf20Sopenharmony_ci !!(fb->flags & DRM_MODE_FB_MODIFIERS), 1868c2ecf20Sopenharmony_ci fb->modifier, 1878c2ecf20Sopenharmony_ci state->rotation)) { 1888c2ecf20Sopenharmony_ci DRM_DEBUG_KMS("requested rotation is not allowed!\n"); 1898c2ecf20Sopenharmony_ci return -EINVAL; 1908c2ecf20Sopenharmony_ci } 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci if ((state->crtc_x < 0 || state->crtc_y < 0 || 1938c2ecf20Sopenharmony_ci state->crtc_x + state->crtc_w > hdisplay || 1948c2ecf20Sopenharmony_ci state->crtc_y + state->crtc_h > vdisplay) && 1958c2ecf20Sopenharmony_ci !dcss_plane_fb_is_linear(fb)) { 1968c2ecf20Sopenharmony_ci DRM_DEBUG_KMS("requested cropping operation is not allowed!\n"); 1978c2ecf20Sopenharmony_ci return -EINVAL; 1988c2ecf20Sopenharmony_ci } 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci if ((fb->flags & DRM_MODE_FB_MODIFIERS) && 2018c2ecf20Sopenharmony_ci !plane->funcs->format_mod_supported(plane, 2028c2ecf20Sopenharmony_ci fb->format->format, 2038c2ecf20Sopenharmony_ci fb->modifier)) { 2048c2ecf20Sopenharmony_ci DRM_DEBUG_KMS("Invalid modifier: %llx", fb->modifier); 2058c2ecf20Sopenharmony_ci return -EINVAL; 2068c2ecf20Sopenharmony_ci } 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci return 0; 2098c2ecf20Sopenharmony_ci} 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_cistatic void dcss_plane_atomic_set_base(struct dcss_plane *dcss_plane) 2128c2ecf20Sopenharmony_ci{ 2138c2ecf20Sopenharmony_ci struct drm_plane *plane = &dcss_plane->base; 2148c2ecf20Sopenharmony_ci struct drm_plane_state *state = plane->state; 2158c2ecf20Sopenharmony_ci struct dcss_dev *dcss = plane->dev->dev_private; 2168c2ecf20Sopenharmony_ci struct drm_framebuffer *fb = state->fb; 2178c2ecf20Sopenharmony_ci const struct drm_format_info *format = fb->format; 2188c2ecf20Sopenharmony_ci struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); 2198c2ecf20Sopenharmony_ci unsigned long p1_ba = 0, p2_ba = 0; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci if (!format->is_yuv || 2228c2ecf20Sopenharmony_ci format->format == DRM_FORMAT_NV12 || 2238c2ecf20Sopenharmony_ci format->format == DRM_FORMAT_NV21) 2248c2ecf20Sopenharmony_ci p1_ba = cma_obj->paddr + fb->offsets[0] + 2258c2ecf20Sopenharmony_ci fb->pitches[0] * (state->src.y1 >> 16) + 2268c2ecf20Sopenharmony_ci format->char_per_block[0] * (state->src.x1 >> 16); 2278c2ecf20Sopenharmony_ci else if (format->format == DRM_FORMAT_UYVY || 2288c2ecf20Sopenharmony_ci format->format == DRM_FORMAT_VYUY || 2298c2ecf20Sopenharmony_ci format->format == DRM_FORMAT_YUYV || 2308c2ecf20Sopenharmony_ci format->format == DRM_FORMAT_YVYU) 2318c2ecf20Sopenharmony_ci p1_ba = cma_obj->paddr + fb->offsets[0] + 2328c2ecf20Sopenharmony_ci fb->pitches[0] * (state->src.y1 >> 16) + 2338c2ecf20Sopenharmony_ci 2 * format->char_per_block[0] * (state->src.x1 >> 17); 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci if (format->format == DRM_FORMAT_NV12 || 2368c2ecf20Sopenharmony_ci format->format == DRM_FORMAT_NV21) 2378c2ecf20Sopenharmony_ci p2_ba = cma_obj->paddr + fb->offsets[1] + 2388c2ecf20Sopenharmony_ci (((fb->pitches[1] >> 1) * (state->src.y1 >> 17) + 2398c2ecf20Sopenharmony_ci (state->src.x1 >> 17)) << 1); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci dcss_dpr_addr_set(dcss->dpr, dcss_plane->ch_num, p1_ba, p2_ba, 2428c2ecf20Sopenharmony_ci fb->pitches[0]); 2438c2ecf20Sopenharmony_ci} 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_cistatic bool dcss_plane_needs_setup(struct drm_plane_state *state, 2468c2ecf20Sopenharmony_ci struct drm_plane_state *old_state) 2478c2ecf20Sopenharmony_ci{ 2488c2ecf20Sopenharmony_ci struct drm_framebuffer *fb = state->fb; 2498c2ecf20Sopenharmony_ci struct drm_framebuffer *old_fb = old_state->fb; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci return state->crtc_x != old_state->crtc_x || 2528c2ecf20Sopenharmony_ci state->crtc_y != old_state->crtc_y || 2538c2ecf20Sopenharmony_ci state->crtc_w != old_state->crtc_w || 2548c2ecf20Sopenharmony_ci state->crtc_h != old_state->crtc_h || 2558c2ecf20Sopenharmony_ci state->src_x != old_state->src_x || 2568c2ecf20Sopenharmony_ci state->src_y != old_state->src_y || 2578c2ecf20Sopenharmony_ci state->src_w != old_state->src_w || 2588c2ecf20Sopenharmony_ci state->src_h != old_state->src_h || 2598c2ecf20Sopenharmony_ci fb->format->format != old_fb->format->format || 2608c2ecf20Sopenharmony_ci fb->modifier != old_fb->modifier || 2618c2ecf20Sopenharmony_ci state->rotation != old_state->rotation; 2628c2ecf20Sopenharmony_ci} 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_cistatic void dcss_plane_atomic_update(struct drm_plane *plane, 2658c2ecf20Sopenharmony_ci struct drm_plane_state *old_state) 2668c2ecf20Sopenharmony_ci{ 2678c2ecf20Sopenharmony_ci struct drm_plane_state *state = plane->state; 2688c2ecf20Sopenharmony_ci struct dcss_plane *dcss_plane = to_dcss_plane(plane); 2698c2ecf20Sopenharmony_ci struct dcss_dev *dcss = plane->dev->dev_private; 2708c2ecf20Sopenharmony_ci struct drm_framebuffer *fb = state->fb; 2718c2ecf20Sopenharmony_ci struct drm_crtc_state *crtc_state; 2728c2ecf20Sopenharmony_ci bool modifiers_present; 2738c2ecf20Sopenharmony_ci u32 src_w, src_h, dst_w, dst_h; 2748c2ecf20Sopenharmony_ci struct drm_rect src, dst; 2758c2ecf20Sopenharmony_ci bool enable = true; 2768c2ecf20Sopenharmony_ci bool is_rotation_90_or_270; 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci if (!fb || !state->crtc || !state->visible) 2798c2ecf20Sopenharmony_ci return; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci crtc_state = state->crtc->state; 2828c2ecf20Sopenharmony_ci modifiers_present = !!(fb->flags & DRM_MODE_FB_MODIFIERS); 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci if (old_state->fb && !drm_atomic_crtc_needs_modeset(crtc_state) && 2858c2ecf20Sopenharmony_ci !dcss_plane_needs_setup(state, old_state)) { 2868c2ecf20Sopenharmony_ci dcss_plane_atomic_set_base(dcss_plane); 2878c2ecf20Sopenharmony_ci return; 2888c2ecf20Sopenharmony_ci } 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci src = plane->state->src; 2918c2ecf20Sopenharmony_ci dst = plane->state->dst; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci /* 2948c2ecf20Sopenharmony_ci * The width and height after clipping. 2958c2ecf20Sopenharmony_ci */ 2968c2ecf20Sopenharmony_ci src_w = drm_rect_width(&src) >> 16; 2978c2ecf20Sopenharmony_ci src_h = drm_rect_height(&src) >> 16; 2988c2ecf20Sopenharmony_ci dst_w = drm_rect_width(&dst); 2998c2ecf20Sopenharmony_ci dst_h = drm_rect_height(&dst); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci if (plane->type == DRM_PLANE_TYPE_OVERLAY && 3028c2ecf20Sopenharmony_ci modifiers_present && fb->modifier == DRM_FORMAT_MOD_LINEAR) 3038c2ecf20Sopenharmony_ci modifiers_present = false; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci dcss_dpr_format_set(dcss->dpr, dcss_plane->ch_num, state->fb->format, 3068c2ecf20Sopenharmony_ci modifiers_present ? fb->modifier : 3078c2ecf20Sopenharmony_ci DRM_FORMAT_MOD_LINEAR); 3088c2ecf20Sopenharmony_ci dcss_dpr_set_res(dcss->dpr, dcss_plane->ch_num, src_w, src_h); 3098c2ecf20Sopenharmony_ci dcss_dpr_set_rotation(dcss->dpr, dcss_plane->ch_num, 3108c2ecf20Sopenharmony_ci state->rotation); 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci dcss_plane_atomic_set_base(dcss_plane); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci is_rotation_90_or_270 = state->rotation & (DRM_MODE_ROTATE_90 | 3158c2ecf20Sopenharmony_ci DRM_MODE_ROTATE_270); 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci dcss_scaler_setup(dcss->scaler, dcss_plane->ch_num, 3188c2ecf20Sopenharmony_ci state->fb->format, 3198c2ecf20Sopenharmony_ci is_rotation_90_or_270 ? src_h : src_w, 3208c2ecf20Sopenharmony_ci is_rotation_90_or_270 ? src_w : src_h, 3218c2ecf20Sopenharmony_ci dst_w, dst_h, 3228c2ecf20Sopenharmony_ci drm_mode_vrefresh(&crtc_state->mode)); 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci dcss_dtg_plane_pos_set(dcss->dtg, dcss_plane->ch_num, 3258c2ecf20Sopenharmony_ci dst.x1, dst.y1, dst_w, dst_h); 3268c2ecf20Sopenharmony_ci dcss_dtg_plane_alpha_set(dcss->dtg, dcss_plane->ch_num, 3278c2ecf20Sopenharmony_ci fb->format, state->alpha >> 8); 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci if (!dcss_plane->ch_num && (state->alpha >> 8) == 0) 3308c2ecf20Sopenharmony_ci enable = false; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci dcss_dpr_enable(dcss->dpr, dcss_plane->ch_num, enable); 3338c2ecf20Sopenharmony_ci dcss_scaler_ch_enable(dcss->scaler, dcss_plane->ch_num, enable); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci if (!enable) 3368c2ecf20Sopenharmony_ci dcss_dtg_plane_pos_set(dcss->dtg, dcss_plane->ch_num, 3378c2ecf20Sopenharmony_ci 0, 0, 0, 0); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci dcss_dtg_ch_enable(dcss->dtg, dcss_plane->ch_num, enable); 3408c2ecf20Sopenharmony_ci} 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_cistatic void dcss_plane_atomic_disable(struct drm_plane *plane, 3438c2ecf20Sopenharmony_ci struct drm_plane_state *old_state) 3448c2ecf20Sopenharmony_ci{ 3458c2ecf20Sopenharmony_ci struct dcss_plane *dcss_plane = to_dcss_plane(plane); 3468c2ecf20Sopenharmony_ci struct dcss_dev *dcss = plane->dev->dev_private; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci dcss_dpr_enable(dcss->dpr, dcss_plane->ch_num, false); 3498c2ecf20Sopenharmony_ci dcss_scaler_ch_enable(dcss->scaler, dcss_plane->ch_num, false); 3508c2ecf20Sopenharmony_ci dcss_dtg_plane_pos_set(dcss->dtg, dcss_plane->ch_num, 0, 0, 0, 0); 3518c2ecf20Sopenharmony_ci dcss_dtg_ch_enable(dcss->dtg, dcss_plane->ch_num, false); 3528c2ecf20Sopenharmony_ci} 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_cistatic const struct drm_plane_helper_funcs dcss_plane_helper_funcs = { 3558c2ecf20Sopenharmony_ci .prepare_fb = drm_gem_fb_prepare_fb, 3568c2ecf20Sopenharmony_ci .atomic_check = dcss_plane_atomic_check, 3578c2ecf20Sopenharmony_ci .atomic_update = dcss_plane_atomic_update, 3588c2ecf20Sopenharmony_ci .atomic_disable = dcss_plane_atomic_disable, 3598c2ecf20Sopenharmony_ci}; 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_cistruct dcss_plane *dcss_plane_init(struct drm_device *drm, 3628c2ecf20Sopenharmony_ci unsigned int possible_crtcs, 3638c2ecf20Sopenharmony_ci enum drm_plane_type type, 3648c2ecf20Sopenharmony_ci unsigned int zpos) 3658c2ecf20Sopenharmony_ci{ 3668c2ecf20Sopenharmony_ci struct dcss_plane *dcss_plane; 3678c2ecf20Sopenharmony_ci const u64 *format_modifiers = dcss_video_format_modifiers; 3688c2ecf20Sopenharmony_ci int ret; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci if (zpos > 2) 3718c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci dcss_plane = kzalloc(sizeof(*dcss_plane), GFP_KERNEL); 3748c2ecf20Sopenharmony_ci if (!dcss_plane) { 3758c2ecf20Sopenharmony_ci DRM_ERROR("failed to allocate plane\n"); 3768c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 3778c2ecf20Sopenharmony_ci } 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci if (type == DRM_PLANE_TYPE_PRIMARY) 3808c2ecf20Sopenharmony_ci format_modifiers = dcss_graphics_format_modifiers; 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci ret = drm_universal_plane_init(drm, &dcss_plane->base, possible_crtcs, 3838c2ecf20Sopenharmony_ci &dcss_plane_funcs, dcss_common_formats, 3848c2ecf20Sopenharmony_ci ARRAY_SIZE(dcss_common_formats), 3858c2ecf20Sopenharmony_ci format_modifiers, type, NULL); 3868c2ecf20Sopenharmony_ci if (ret) { 3878c2ecf20Sopenharmony_ci DRM_ERROR("failed to initialize plane\n"); 3888c2ecf20Sopenharmony_ci kfree(dcss_plane); 3898c2ecf20Sopenharmony_ci return ERR_PTR(ret); 3908c2ecf20Sopenharmony_ci } 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci drm_plane_helper_add(&dcss_plane->base, &dcss_plane_helper_funcs); 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci ret = drm_plane_create_zpos_immutable_property(&dcss_plane->base, zpos); 3958c2ecf20Sopenharmony_ci if (ret) 3968c2ecf20Sopenharmony_ci return ERR_PTR(ret); 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci drm_plane_create_rotation_property(&dcss_plane->base, 3998c2ecf20Sopenharmony_ci DRM_MODE_ROTATE_0, 4008c2ecf20Sopenharmony_ci DRM_MODE_ROTATE_0 | 4018c2ecf20Sopenharmony_ci DRM_MODE_ROTATE_90 | 4028c2ecf20Sopenharmony_ci DRM_MODE_ROTATE_180 | 4038c2ecf20Sopenharmony_ci DRM_MODE_ROTATE_270 | 4048c2ecf20Sopenharmony_ci DRM_MODE_REFLECT_X | 4058c2ecf20Sopenharmony_ci DRM_MODE_REFLECT_Y); 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci dcss_plane->ch_num = zpos; 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci return dcss_plane; 4108c2ecf20Sopenharmony_ci} 411