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