1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2025 Icenowy Zheng <uwu@icenowy.me> 4 */ 5 6 #include <linux/errno.h> 7 #include <linux/printk.h> 8 9 #include <drm/drm_atomic_state_helper.h> 10 #include <drm/drm_fb_dma_helper.h> 11 #include <drm/drm_fourcc.h> 12 #include <drm/drm_gem_dma_helper.h> 13 #include <drm/drm_print.h> 14 15 #include "vs_plane.h" 16 17 int drm_format_to_vs_format(u32 drm_format, struct vs_format *vs_format) 18 { 19 switch (drm_format) { 20 case DRM_FORMAT_XRGB4444: 21 case DRM_FORMAT_RGBX4444: 22 case DRM_FORMAT_XBGR4444: 23 case DRM_FORMAT_BGRX4444: 24 vs_format->color = VSDC_COLOR_FORMAT_X4R4G4B4; 25 break; 26 case DRM_FORMAT_ARGB4444: 27 case DRM_FORMAT_RGBA4444: 28 case DRM_FORMAT_ABGR4444: 29 case DRM_FORMAT_BGRA4444: 30 vs_format->color = VSDC_COLOR_FORMAT_A4R4G4B4; 31 break; 32 case DRM_FORMAT_XRGB1555: 33 case DRM_FORMAT_RGBX5551: 34 case DRM_FORMAT_XBGR1555: 35 case DRM_FORMAT_BGRX5551: 36 vs_format->color = VSDC_COLOR_FORMAT_X1R5G5B5; 37 break; 38 case DRM_FORMAT_ARGB1555: 39 case DRM_FORMAT_RGBA5551: 40 case DRM_FORMAT_ABGR1555: 41 case DRM_FORMAT_BGRA5551: 42 vs_format->color = VSDC_COLOR_FORMAT_A1R5G5B5; 43 break; 44 case DRM_FORMAT_RGB565: 45 case DRM_FORMAT_BGR565: 46 vs_format->color = VSDC_COLOR_FORMAT_R5G6B5; 47 break; 48 case DRM_FORMAT_XRGB8888: 49 case DRM_FORMAT_RGBX8888: 50 case DRM_FORMAT_XBGR8888: 51 case DRM_FORMAT_BGRX8888: 52 vs_format->color = VSDC_COLOR_FORMAT_X8R8G8B8; 53 break; 54 case DRM_FORMAT_ARGB8888: 55 case DRM_FORMAT_RGBA8888: 56 case DRM_FORMAT_ABGR8888: 57 case DRM_FORMAT_BGRA8888: 58 vs_format->color = VSDC_COLOR_FORMAT_A8R8G8B8; 59 break; 60 case DRM_FORMAT_ARGB2101010: 61 case DRM_FORMAT_RGBA1010102: 62 case DRM_FORMAT_ABGR2101010: 63 case DRM_FORMAT_BGRA1010102: 64 vs_format->color = VSDC_COLOR_FORMAT_A2R10G10B10; 65 break; 66 default: 67 return -EINVAL; 68 } 69 70 switch (drm_format) { 71 case DRM_FORMAT_RGBX4444: 72 case DRM_FORMAT_RGBA4444: 73 case DRM_FORMAT_RGBX5551: 74 case DRM_FORMAT_RGBA5551: 75 case DRM_FORMAT_RGBX8888: 76 case DRM_FORMAT_RGBA8888: 77 case DRM_FORMAT_RGBA1010102: 78 vs_format->swizzle = VSDC_SWIZZLE_RGBA; 79 break; 80 case DRM_FORMAT_XBGR4444: 81 case DRM_FORMAT_ABGR4444: 82 case DRM_FORMAT_XBGR1555: 83 case DRM_FORMAT_ABGR1555: 84 case DRM_FORMAT_BGR565: 85 case DRM_FORMAT_XBGR8888: 86 case DRM_FORMAT_ABGR8888: 87 case DRM_FORMAT_ABGR2101010: 88 vs_format->swizzle = VSDC_SWIZZLE_ABGR; 89 break; 90 case DRM_FORMAT_BGRX4444: 91 case DRM_FORMAT_BGRA4444: 92 case DRM_FORMAT_BGRX5551: 93 case DRM_FORMAT_BGRA5551: 94 case DRM_FORMAT_BGRX8888: 95 case DRM_FORMAT_BGRA8888: 96 case DRM_FORMAT_BGRA1010102: 97 vs_format->swizzle = VSDC_SWIZZLE_BGRA; 98 break; 99 default: 100 /* N/A for YUV formats */ 101 vs_format->swizzle = VSDC_SWIZZLE_ARGB; 102 } 103 104 /* N/A for non-YUV formats */ 105 vs_format->uv_swizzle = false; 106 107 return 0; 108 } 109 110 dma_addr_t vs_fb_get_dma_addr(struct drm_framebuffer *fb, 111 const struct drm_rect *src_rect) 112 { 113 struct drm_gem_dma_object *gem; 114 dma_addr_t dma_addr; 115 116 /* Get the physical address of the buffer in memory */ 117 gem = drm_fb_dma_get_gem_obj(fb, 0); 118 119 /* Compute the start of the displayed memory */ 120 dma_addr = gem->dma_addr + fb->offsets[0]; 121 122 /* Fixup framebuffer address for src coordinates */ 123 dma_addr += drm_format_info_min_pitch(fb->format, 0, 124 src_rect->x1 >> 16); 125 dma_addr += (src_rect->y1 >> 16) * fb->pitches[0]; 126 127 return dma_addr; 128 } 129 130 struct drm_plane_state *vs_plane_duplicate_state(struct drm_plane *plane) 131 { 132 struct vs_plane_state *vs_state, *vs_state_old; 133 134 if (drm_WARN_ON(plane->dev, !plane->state)) 135 return NULL; 136 137 vs_state_old = to_vs_plane_state(plane->state); 138 139 vs_state = kzalloc_obj(*vs_state, GFP_KERNEL); 140 if (!vs_state) 141 return NULL; 142 143 __drm_atomic_helper_plane_duplicate_state(plane, &vs_state->base); 144 145 memcpy(&vs_state->format, &vs_state_old->format, 146 sizeof(struct vs_format)); 147 148 return &vs_state->base; 149 } 150 151 void vs_plane_destroy_state(struct drm_plane *plane, 152 struct drm_plane_state *state) 153 { 154 __drm_atomic_helper_plane_destroy_state(state); 155 kfree(state); 156 } 157 158 /* Called during init to allocate the plane's atomic state. */ 159 void vs_plane_reset(struct drm_plane *plane) 160 { 161 struct vs_plane_state *vs_state; 162 163 if (plane->state) { 164 __drm_atomic_helper_plane_destroy_state(plane->state); 165 kfree(plane->state); 166 plane->state = NULL; 167 } 168 169 vs_state = kzalloc_obj(*vs_state, GFP_KERNEL); 170 if (!vs_state) 171 return; 172 173 __drm_atomic_helper_plane_reset(plane, &vs_state->base); 174 } 175