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 dc_plane_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 } 50 plane_state->in_shaper_func = dc_create_transfer_func(); 51 if (plane_state->in_shaper_func != NULL) { 52 plane_state->in_shaper_func->type = TF_TYPE_BYPASS; 53 } 54 55 plane_state->lut3d_func = dc_create_3dlut_func(); 56 57 plane_state->blend_tf = dc_create_transfer_func(); 58 if (plane_state->blend_tf != NULL) { 59 plane_state->blend_tf->type = TF_TYPE_BYPASS; 60 } 61 62 plane_state->pre_multiplied_alpha = true; 63 64 } 65 66 static void dc_plane_destruct(struct dc_plane_state *plane_state) 67 { 68 if (plane_state->gamma_correction != NULL) { 69 dc_gamma_release(&plane_state->gamma_correction); 70 } 71 if (plane_state->in_transfer_func != NULL) { 72 dc_transfer_func_release( 73 plane_state->in_transfer_func); 74 plane_state->in_transfer_func = NULL; 75 } 76 if (plane_state->in_shaper_func != NULL) { 77 dc_transfer_func_release( 78 plane_state->in_shaper_func); 79 plane_state->in_shaper_func = NULL; 80 } 81 if (plane_state->lut3d_func != NULL) { 82 dc_3dlut_func_release( 83 plane_state->lut3d_func); 84 plane_state->lut3d_func = NULL; 85 } 86 if (plane_state->blend_tf != NULL) { 87 dc_transfer_func_release( 88 plane_state->blend_tf); 89 plane_state->blend_tf = NULL; 90 } 91 92 } 93 94 /******************************************************************************* 95 * Public functions 96 ******************************************************************************/ 97 void enable_surface_flip_reporting(struct dc_plane_state *plane_state, 98 uint32_t controller_id) 99 { 100 plane_state->irq_source = controller_id + DC_IRQ_SOURCE_PFLIP1 - 1; 101 /*register_flip_interrupt(surface);*/ 102 } 103 104 struct dc_plane_state *dc_create_plane_state(struct 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 dc_plane_construct(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 *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 dc = plane_state->ctx->dc; 145 146 if (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 < dc->res_pool->pipe_count; i++) { 151 struct pipe_ctx *pipe_ctx = 152 &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 < dc->res_pool->pipe_count; i++) { 163 struct pipe_ctx *pipe_ctx = 164 &dc->current_state->res_ctx.pipe_ctx[i]; 165 166 if (pipe_ctx->plane_state != plane_state) 167 continue; 168 169 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 dc_plane_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 static void dc_3dlut_func_free(struct kref *kref) 255 { 256 struct dc_3dlut *lut = container_of(kref, struct dc_3dlut, refcount); 257 258 kvfree(lut); 259 } 260 261 struct dc_3dlut *dc_create_3dlut_func(void) 262 { 263 struct dc_3dlut *lut = kvzalloc(sizeof(*lut), GFP_KERNEL); 264 265 if (lut == NULL) 266 goto alloc_fail; 267 268 kref_init(&lut->refcount); 269 lut->state.raw = 0; 270 271 return lut; 272 273 alloc_fail: 274 return NULL; 275 276 } 277 278 void dc_3dlut_func_release(struct dc_3dlut *lut) 279 { 280 kref_put(&lut->refcount, dc_3dlut_func_free); 281 } 282 283 void dc_3dlut_func_retain(struct dc_3dlut *lut) 284 { 285 kref_get(&lut->refcount); 286 } 287 288 289