Home | History | Annotate | Line # | Download | only in core
      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