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 #include <linux/mm.h> 27 28 /* DC interface (public) */ 29 #include "dm_services.h" 30 #include "dc.h" 31 32 /* DC core (private) */ 33 #include "core_types.h" 34 #include "transform.h" 35 #include "dpp.h" 36 37 /******************************************************************************* 38 * Private functions 39 ******************************************************************************/ 40 static void dc_plane_construct(struct dc_context *ctx, struct dc_plane_state *plane_state) 41 { 42 plane_state->ctx = ctx; 43 44 plane_state->gamma_correction = dc_create_gamma(); 45 if (plane_state->gamma_correction != NULL) 46 plane_state->gamma_correction->is_identity = true; 47 48 plane_state->in_transfer_func = dc_create_transfer_func(); 49 if (plane_state->in_transfer_func != NULL) { 50 plane_state->in_transfer_func->type = TF_TYPE_BYPASS; 51 plane_state->in_transfer_func->ctx = ctx; 52 } 53 plane_state->in_shaper_func = dc_create_transfer_func(); 54 if (plane_state->in_shaper_func != NULL) { 55 plane_state->in_shaper_func->type = TF_TYPE_BYPASS; 56 plane_state->in_shaper_func->ctx = ctx; 57 } 58 59 plane_state->lut3d_func = dc_create_3dlut_func(); 60 if (plane_state->lut3d_func != NULL) { 61 plane_state->lut3d_func->ctx = ctx; 62 } 63 plane_state->blend_tf = dc_create_transfer_func(); 64 if (plane_state->blend_tf != NULL) { 65 plane_state->blend_tf->type = TF_TYPE_BYPASS; 66 plane_state->blend_tf->ctx = ctx; 67 } 68 69 } 70 71 static void dc_plane_destruct(struct dc_plane_state *plane_state) 72 { 73 if (plane_state->gamma_correction != NULL) { 74 dc_gamma_release(&plane_state->gamma_correction); 75 } 76 if (plane_state->in_transfer_func != NULL) { 77 dc_transfer_func_release( 78 plane_state->in_transfer_func); 79 plane_state->in_transfer_func = NULL; 80 } 81 if (plane_state->in_shaper_func != NULL) { 82 dc_transfer_func_release( 83 plane_state->in_shaper_func); 84 plane_state->in_shaper_func = NULL; 85 } 86 if (plane_state->lut3d_func != NULL) { 87 dc_3dlut_func_release( 88 plane_state->lut3d_func); 89 plane_state->lut3d_func = NULL; 90 } 91 if (plane_state->blend_tf != NULL) { 92 dc_transfer_func_release( 93 plane_state->blend_tf); 94 plane_state->blend_tf = NULL; 95 } 96 97 } 98 99 /******************************************************************************* 100 * Public functions 101 ******************************************************************************/ 102 void enable_surface_flip_reporting(struct dc_plane_state *plane_state, 103 uint32_t controller_id) 104 { 105 plane_state->irq_source = controller_id + DC_IRQ_SOURCE_PFLIP1 - 1; 106 /*register_flip_interrupt(surface);*/ 107 } 108 109 struct dc_plane_state *dc_create_plane_state(struct dc *dc) 110 { 111 struct dc_plane_state *plane_state = kvzalloc(sizeof(*plane_state), 112 GFP_KERNEL); 113 114 if (NULL == plane_state) 115 return NULL; 116 117 kref_init(&plane_state->refcount); 118 dc_plane_construct(dc->ctx, plane_state); 119 120 return plane_state; 121 } 122 123 /** 124 ***************************************************************************** 125 * Function: dc_plane_get_status 126 * 127 * @brief 128 * Looks up the pipe context of plane_state and updates the pending status 129 * of the pipe context. Then returns plane_state->status 130 * 131 * @param [in] plane_state: pointer to the plane_state to get the status of 132 ***************************************************************************** 133 */ 134 const struct dc_plane_status *dc_plane_get_status( 135 const struct dc_plane_state *plane_state) 136 { 137 const struct dc_plane_status *plane_status; 138 struct dc *dc; 139 int i; 140 141 if (!plane_state || 142 !plane_state->ctx || 143 !plane_state->ctx->dc) { 144 ASSERT(0); 145 return NULL; /* remove this if above assert never hit */ 146 } 147 148 plane_status = &plane_state->status; 149 dc = plane_state->ctx->dc; 150 151 if (dc->current_state == NULL) 152 return NULL; 153 154 /* Find the current plane state and set its pending bit to false */ 155 for (i = 0; i < dc->res_pool->pipe_count; i++) { 156 struct pipe_ctx *pipe_ctx = 157 &dc->current_state->res_ctx.pipe_ctx[i]; 158 159 if (pipe_ctx->plane_state != plane_state) 160 continue; 161 162 pipe_ctx->plane_state->status.is_flip_pending = false; 163 164 break; 165 } 166 167 for (i = 0; i < dc->res_pool->pipe_count; i++) { 168 struct pipe_ctx *pipe_ctx = 169 &dc->current_state->res_ctx.pipe_ctx[i]; 170 171 if (pipe_ctx->plane_state != plane_state) 172 continue; 173 174 dc->hwss.update_pending_status(pipe_ctx); 175 } 176 177 return plane_status; 178 } 179 180 void dc_plane_state_retain(struct dc_plane_state *plane_state) 181 { 182 kref_get(&plane_state->refcount); 183 } 184 185 static void dc_plane_state_free(struct kref *kref) 186 { 187 struct dc_plane_state *plane_state = container_of(kref, struct dc_plane_state, refcount); 188 dc_plane_destruct(plane_state); 189 kvfree(plane_state); 190 } 191 192 void dc_plane_state_release(struct dc_plane_state *plane_state) 193 { 194 kref_put(&plane_state->refcount, dc_plane_state_free); 195 } 196 197 void dc_gamma_retain(struct dc_gamma *gamma) 198 { 199 kref_get(&gamma->refcount); 200 } 201 202 static void dc_gamma_free(struct kref *kref) 203 { 204 struct dc_gamma *gamma = container_of(kref, struct dc_gamma, refcount); 205 kvfree(gamma); 206 } 207 208 void dc_gamma_release(struct dc_gamma **gamma) 209 { 210 kref_put(&(*gamma)->refcount, dc_gamma_free); 211 *gamma = NULL; 212 } 213 214 struct dc_gamma *dc_create_gamma(void) 215 { 216 struct dc_gamma *gamma = kvzalloc(sizeof(*gamma), GFP_KERNEL); 217 218 if (gamma == NULL) 219 goto alloc_fail; 220 221 kref_init(&gamma->refcount); 222 return gamma; 223 224 alloc_fail: 225 return NULL; 226 } 227 228 void dc_transfer_func_retain(struct dc_transfer_func *tf) 229 { 230 kref_get(&tf->refcount); 231 } 232 233 static void dc_transfer_func_free(struct kref *kref) 234 { 235 struct dc_transfer_func *tf = container_of(kref, struct dc_transfer_func, refcount); 236 kvfree(tf); 237 } 238 239 void dc_transfer_func_release(struct dc_transfer_func *tf) 240 { 241 kref_put(&tf->refcount, dc_transfer_func_free); 242 } 243 244 struct dc_transfer_func *dc_create_transfer_func(void) 245 { 246 struct dc_transfer_func *tf = kvzalloc(sizeof(*tf), GFP_KERNEL); 247 248 if (tf == NULL) 249 goto alloc_fail; 250 251 kref_init(&tf->refcount); 252 253 return tf; 254 255 alloc_fail: 256 return NULL; 257 } 258 259 static void dc_3dlut_func_free(struct kref *kref) 260 { 261 struct dc_3dlut *lut = container_of(kref, struct dc_3dlut, refcount); 262 263 kvfree(lut); 264 } 265 266 struct dc_3dlut *dc_create_3dlut_func(void) 267 { 268 struct dc_3dlut *lut = kvzalloc(sizeof(*lut), GFP_KERNEL); 269 270 if (lut == NULL) 271 goto alloc_fail; 272 273 kref_init(&lut->refcount); 274 lut->state.raw = 0; 275 276 return lut; 277 278 alloc_fail: 279 return NULL; 280 281 } 282 283 void dc_3dlut_func_release(struct dc_3dlut *lut) 284 { 285 kref_put(&lut->refcount, dc_3dlut_func_free); 286 } 287 288 void dc_3dlut_func_retain(struct dc_3dlut *lut) 289 { 290 kref_get(&lut->refcount); 291 } 292 293 294