xref: /netbsd-src/sys/external/bsd/drm2/dist/drm/amd/display/dc/core/amdgpu_dc_surface.c (revision 41ec02673d281bbb3d38e6c78504ce6e30c228c1)
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  ******************************************************************************/
dc_plane_construct(struct dc_context * ctx,struct dc_plane_state * plane_state)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 
dc_plane_destruct(struct dc_plane_state * plane_state)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  ******************************************************************************/
enable_surface_flip_reporting(struct dc_plane_state * plane_state,uint32_t controller_id)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 
dc_create_plane_state(struct dc * dc)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  */
dc_plane_get_status(const struct dc_plane_state * plane_state)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 
dc_plane_state_retain(struct dc_plane_state * plane_state)185 void dc_plane_state_retain(struct dc_plane_state *plane_state)
186 {
187 	kref_get(&plane_state->refcount);
188 }
189 
dc_plane_state_free(struct kref * kref)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 
dc_plane_state_release(struct dc_plane_state * plane_state)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 
dc_gamma_retain(struct dc_gamma * gamma)202 void dc_gamma_retain(struct dc_gamma *gamma)
203 {
204 	kref_get(&gamma->refcount);
205 }
206 
dc_gamma_free(struct kref * kref)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 
dc_gamma_release(struct dc_gamma ** gamma)213 void dc_gamma_release(struct dc_gamma **gamma)
214 {
215 	kref_put(&(*gamma)->refcount, dc_gamma_free);
216 	*gamma = NULL;
217 }
218 
dc_create_gamma(void)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 
dc_transfer_func_retain(struct dc_transfer_func * tf)233 void dc_transfer_func_retain(struct dc_transfer_func *tf)
234 {
235 	kref_get(&tf->refcount);
236 }
237 
dc_transfer_func_free(struct kref * kref)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 
dc_transfer_func_release(struct dc_transfer_func * tf)244 void dc_transfer_func_release(struct dc_transfer_func *tf)
245 {
246 	kref_put(&tf->refcount, dc_transfer_func_free);
247 }
248 
dc_create_transfer_func(void)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 
dc_3dlut_func_free(struct kref * kref)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 
dc_create_3dlut_func(void)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 
dc_3dlut_func_release(struct dc_3dlut * lut)288 void dc_3dlut_func_release(struct dc_3dlut *lut)
289 {
290 	kref_put(&lut->refcount, dc_3dlut_func_free);
291 }
292 
dc_3dlut_func_retain(struct dc_3dlut * lut)293 void dc_3dlut_func_retain(struct dc_3dlut *lut)
294 {
295 	kref_get(&lut->refcount);
296 }
297 
298 
299