1 /* $NetBSD: amdgpu_dc_surface.c,v 1.2 2021/12/18 23:45:02 riastradh Exp $ */ 2 3 /* 4 * Copyright 2015 Advanced Micro Devices, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: AMD 25 * 26 */ 27 28 #include <sys/cdefs.h> 29 __KERNEL_RCSID(0, "$NetBSD: amdgpu_dc_surface.c,v 1.2 2021/12/18 23:45:02 riastradh Exp $"); 30 31 #include <linux/mm.h> 32 33 /* DC interface (public) */ 34 #include "dm_services.h" 35 #include "dc.h" 36 37 /* DC core (private) */ 38 #include "core_types.h" 39 #include "transform.h" 40 #include "dpp.h" 41 42 /******************************************************************************* 43 * Private functions 44 ******************************************************************************/ 45 static void dc_plane_construct(struct dc_context *ctx, struct dc_plane_state *plane_state) 46 { 47 plane_state->ctx = ctx; 48 49 plane_state->gamma_correction = dc_create_gamma(); 50 if (plane_state->gamma_correction != NULL) 51 plane_state->gamma_correction->is_identity = true; 52 53 plane_state->in_transfer_func = dc_create_transfer_func(); 54 if (plane_state->in_transfer_func != NULL) { 55 plane_state->in_transfer_func->type = TF_TYPE_BYPASS; 56 plane_state->in_transfer_func->ctx = ctx; 57 } 58 plane_state->in_shaper_func = dc_create_transfer_func(); 59 if (plane_state->in_shaper_func != NULL) { 60 plane_state->in_shaper_func->type = TF_TYPE_BYPASS; 61 plane_state->in_shaper_func->ctx = ctx; 62 } 63 64 plane_state->lut3d_func = dc_create_3dlut_func(); 65 if (plane_state->lut3d_func != NULL) { 66 plane_state->lut3d_func->ctx = ctx; 67 } 68 plane_state->blend_tf = dc_create_transfer_func(); 69 if (plane_state->blend_tf != NULL) { 70 plane_state->blend_tf->type = TF_TYPE_BYPASS; 71 plane_state->blend_tf->ctx = ctx; 72 } 73 74 } 75 76 static void dc_plane_destruct(struct dc_plane_state *plane_state) 77 { 78 if (plane_state->gamma_correction != NULL) { 79 dc_gamma_release(&plane_state->gamma_correction); 80 } 81 if (plane_state->in_transfer_func != NULL) { 82 dc_transfer_func_release( 83 plane_state->in_transfer_func); 84 plane_state->in_transfer_func = NULL; 85 } 86 if (plane_state->in_shaper_func != NULL) { 87 dc_transfer_func_release( 88 plane_state->in_shaper_func); 89 plane_state->in_shaper_func = NULL; 90 } 91 if (plane_state->lut3d_func != NULL) { 92 dc_3dlut_func_release( 93 plane_state->lut3d_func); 94 plane_state->lut3d_func = NULL; 95 } 96 if (plane_state->blend_tf != NULL) { 97 dc_transfer_func_release( 98 plane_state->blend_tf); 99 plane_state->blend_tf = NULL; 100 } 101 102 } 103 104 /******************************************************************************* 105 * Public functions 106 ******************************************************************************/ 107 void enable_surface_flip_reporting(struct dc_plane_state *plane_state, 108 uint32_t controller_id) 109 { 110 plane_state->irq_source = controller_id + DC_IRQ_SOURCE_PFLIP1 - 1; 111 /*register_flip_interrupt(surface);*/ 112 } 113 114 struct dc_plane_state *dc_create_plane_state(struct dc *dc) 115 { 116 struct dc_plane_state *plane_state = kvzalloc(sizeof(*plane_state), 117 GFP_KERNEL); 118 119 if (NULL == plane_state) 120 return NULL; 121 122 kref_init(&plane_state->refcount); 123 dc_plane_construct(dc->ctx, plane_state); 124 125 return plane_state; 126 } 127 128 /** 129 ***************************************************************************** 130 * Function: dc_plane_get_status 131 * 132 * @brief 133 * Looks up the pipe context of plane_state and updates the pending status 134 * of the pipe context. Then returns plane_state->status 135 * 136 * @param [in] plane_state: pointer to the plane_state to get the status of 137 ***************************************************************************** 138 */ 139 const struct dc_plane_status *dc_plane_get_status( 140 const struct dc_plane_state *plane_state) 141 { 142 const struct dc_plane_status *plane_status; 143 struct dc *dc; 144 int i; 145 146 if (!plane_state || 147 !plane_state->ctx || 148 !plane_state->ctx->dc) { 149 ASSERT(0); 150 return NULL; /* remove this if above assert never hit */ 151 } 152 153 plane_status = &plane_state->status; 154 dc = plane_state->ctx->dc; 155 156 if (dc->current_state == NULL) 157 return NULL; 158 159 /* Find the current plane state and set its pending bit to false */ 160 for (i = 0; i < dc->res_pool->pipe_count; i++) { 161 struct pipe_ctx *pipe_ctx = 162 &dc->current_state->res_ctx.pipe_ctx[i]; 163 164 if (pipe_ctx->plane_state != plane_state) 165 continue; 166 167 pipe_ctx->plane_state->status.is_flip_pending = false; 168 169 break; 170 } 171 172 for (i = 0; i < dc->res_pool->pipe_count; i++) { 173 struct pipe_ctx *pipe_ctx = 174 &dc->current_state->res_ctx.pipe_ctx[i]; 175 176 if (pipe_ctx->plane_state != plane_state) 177 continue; 178 179 dc->hwss.update_pending_status(pipe_ctx); 180 } 181 182 return plane_status; 183 } 184 185 void dc_plane_state_retain(struct dc_plane_state *plane_state) 186 { 187 kref_get(&plane_state->refcount); 188 } 189 190 static void dc_plane_state_free(struct kref *kref) 191 { 192 struct dc_plane_state *plane_state = container_of(kref, struct dc_plane_state, refcount); 193 dc_plane_destruct(plane_state); 194 kvfree(plane_state); 195 } 196 197 void dc_plane_state_release(struct dc_plane_state *plane_state) 198 { 199 kref_put(&plane_state->refcount, dc_plane_state_free); 200 } 201 202 void dc_gamma_retain(struct dc_gamma *gamma) 203 { 204 kref_get(&gamma->refcount); 205 } 206 207 static void dc_gamma_free(struct kref *kref) 208 { 209 struct dc_gamma *gamma = container_of(kref, struct dc_gamma, refcount); 210 kvfree(gamma); 211 } 212 213 void dc_gamma_release(struct dc_gamma **gamma) 214 { 215 kref_put(&(*gamma)->refcount, dc_gamma_free); 216 *gamma = NULL; 217 } 218 219 struct dc_gamma *dc_create_gamma(void) 220 { 221 struct dc_gamma *gamma = kvzalloc(sizeof(*gamma), GFP_KERNEL); 222 223 if (gamma == NULL) 224 goto alloc_fail; 225 226 kref_init(&gamma->refcount); 227 return gamma; 228 229 alloc_fail: 230 return NULL; 231 } 232 233 void dc_transfer_func_retain(struct dc_transfer_func *tf) 234 { 235 kref_get(&tf->refcount); 236 } 237 238 static void dc_transfer_func_free(struct kref *kref) 239 { 240 struct dc_transfer_func *tf = container_of(kref, struct dc_transfer_func, refcount); 241 kvfree(tf); 242 } 243 244 void dc_transfer_func_release(struct dc_transfer_func *tf) 245 { 246 kref_put(&tf->refcount, dc_transfer_func_free); 247 } 248 249 struct dc_transfer_func *dc_create_transfer_func(void) 250 { 251 struct dc_transfer_func *tf = kvzalloc(sizeof(*tf), GFP_KERNEL); 252 253 if (tf == NULL) 254 goto alloc_fail; 255 256 kref_init(&tf->refcount); 257 258 return tf; 259 260 alloc_fail: 261 return NULL; 262 } 263 264 static void dc_3dlut_func_free(struct kref *kref) 265 { 266 struct dc_3dlut *lut = container_of(kref, struct dc_3dlut, refcount); 267 268 kvfree(lut); 269 } 270 271 struct dc_3dlut *dc_create_3dlut_func(void) 272 { 273 struct dc_3dlut *lut = kvzalloc(sizeof(*lut), GFP_KERNEL); 274 275 if (lut == NULL) 276 goto alloc_fail; 277 278 kref_init(&lut->refcount); 279 lut->state.raw = 0; 280 281 return lut; 282 283 alloc_fail: 284 return NULL; 285 286 } 287 288 void dc_3dlut_func_release(struct dc_3dlut *lut) 289 { 290 kref_put(&lut->refcount, dc_3dlut_func_free); 291 } 292 293 void dc_3dlut_func_retain(struct dc_3dlut *lut) 294 { 295 kref_get(&lut->refcount); 296 } 297 298 299