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