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_dc.h"
32 #include "transform.h"
33 
34 /*******************************************************************************
35  * Private structures
36  ******************************************************************************/
37 struct surface {
38 	struct core_surface protected;
39 	enum dc_irq_source irq_source;
40 	int ref_count;
41 };
42 
43 struct gamma {
44 	struct core_gamma protected;
45 	int ref_count;
46 };
47 
48 struct transfer_func {
49 	struct core_transfer_func protected;
50 	int ref_count;
51 };
52 
53 #define DC_SURFACE_TO_SURFACE(dc_surface) container_of(dc_surface, struct surface, protected.public)
54 #define CORE_SURFACE_TO_SURFACE(core_surface) container_of(core_surface, struct surface, protected)
55 
56 #define DC_GAMMA_TO_GAMMA(dc_gamma) \
57 	container_of(dc_gamma, struct gamma, protected.public)
58 #define DC_TRANSFER_FUNC_TO_TRANSFER_FUNC(dc_tf) \
59 	container_of(dc_tf, struct transfer_func, protected.public)
60 #define CORE_GAMMA_TO_GAMMA(core_gamma) \
61 	container_of(core_gamma, struct gamma, protected)
62 
63 /*******************************************************************************
64  * Private functions
65  ******************************************************************************/
66 static bool construct(struct dc_context *ctx, struct surface *surface)
67 {
68 	surface->protected.ctx = ctx;
69 	memset(&surface->protected.public.hdr_static_ctx,
70 			0, sizeof(struct dc_hdr_static_metadata));
71 	return true;
72 }
73 
74 static void destruct(struct surface *surface)
75 {
76 	if (surface->protected.public.gamma_correction != NULL) {
77 		dc_gamma_release(&surface->protected.public.gamma_correction);
78 	}
79 	if (surface->protected.public.in_transfer_func != NULL) {
80 		dc_transfer_func_release(
81 				surface->protected.public.in_transfer_func);
82 		surface->protected.public.in_transfer_func = NULL;
83 	}
84 }
85 
86 /*******************************************************************************
87  * Public functions
88  ******************************************************************************/
89 void enable_surface_flip_reporting(struct dc_surface *dc_surface,
90 		uint32_t controller_id)
91 {
92 	struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface);
93 	surface->irq_source = controller_id + DC_IRQ_SOURCE_PFLIP1 - 1;
94 	/*register_flip_interrupt(surface);*/
95 }
96 
97 struct dc_surface *dc_create_surface(const struct dc *dc)
98 {
99 	struct core_dc *core_dc = DC_TO_CORE(dc);
100 
101 	struct surface *surface = dm_alloc(sizeof(*surface));
102 
103 	if (NULL == surface)
104 		goto alloc_fail;
105 
106 	if (false == construct(core_dc->ctx, surface))
107 		goto construct_fail;
108 
109 	++surface->ref_count;
110 
111 	return &surface->protected.public;
112 
113 construct_fail:
114 	dm_free(surface);
115 
116 alloc_fail:
117 	return NULL;
118 }
119 
120 const struct dc_surface_status *dc_surface_get_status(
121 		const struct dc_surface *dc_surface)
122 {
123 	struct dc_surface_status *surface_status;
124 	struct core_surface *core_surface;
125 	struct core_dc *core_dc;
126 	int i;
127 
128 	if (dc_surface == NULL)
129 		return NULL;
130 
131 	core_surface = DC_SURFACE_TO_CORE(dc_surface);
132 
133 	if (core_surface == NULL || core_surface->ctx == NULL)
134 		return NULL;
135 
136 	surface_status = &core_surface->status;
137 
138 	if (core_surface->ctx == NULL || core_surface->ctx->dc == NULL)
139 		return NULL;
140 
141 	core_dc = DC_TO_CORE(core_surface->ctx->dc);
142 
143 
144 	if (core_dc->current_context == NULL)
145 		return NULL;
146 
147 	for (i = 0; i < core_dc->current_context->res_ctx.pool->pipe_count;
148 			i++) {
149 		struct pipe_ctx *pipe_ctx =
150 				&core_dc->current_context->res_ctx.pipe_ctx[i];
151 
152 		if (pipe_ctx->surface !=
153 				DC_SURFACE_TO_CORE(dc_surface))
154 			continue;
155 
156 		core_dc->hwss.update_pending_status(pipe_ctx);
157 	}
158 
159 	return surface_status;
160 }
161 
162 void dc_surface_retain(const struct dc_surface *dc_surface)
163 {
164 	struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface);
165 
166 	ASSERT(surface->ref_count > 0);
167 	++surface->ref_count;
168 }
169 
170 void dc_surface_release(const struct dc_surface *dc_surface)
171 {
172 	struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface);
173 
174 	ASSERT(surface->ref_count > 0);
175 	--surface->ref_count;
176 
177 	if (surface->ref_count == 0) {
178 		destruct(surface);
179 		dm_free(surface);
180 	}
181 }
182 
183 void dc_gamma_retain(const struct dc_gamma *dc_gamma)
184 {
185 	struct gamma *gamma = DC_GAMMA_TO_GAMMA(dc_gamma);
186 
187 	ASSERT(gamma->ref_count > 0);
188 	++gamma->ref_count;
189 }
190 
191 void dc_gamma_release(const struct dc_gamma **dc_gamma)
192 {
193 	struct gamma *gamma = DC_GAMMA_TO_GAMMA(*dc_gamma);
194 
195 	ASSERT(gamma->ref_count > 0);
196 	--gamma->ref_count;
197 
198 	if (gamma->ref_count == 0)
199 		dm_free(gamma);
200 
201 	*dc_gamma = NULL;
202 }
203 
204 struct dc_gamma *dc_create_gamma()
205 {
206 	struct gamma *gamma = dm_alloc(sizeof(*gamma));
207 
208 	if (gamma == NULL)
209 		goto alloc_fail;
210 
211 	++gamma->ref_count;
212 
213 	return &gamma->protected.public;
214 
215 alloc_fail:
216 	return NULL;
217 }
218 
219 void dc_transfer_func_retain(const struct dc_transfer_func *dc_tf)
220 {
221 	struct transfer_func *tf = DC_TRANSFER_FUNC_TO_TRANSFER_FUNC(dc_tf);
222 
223 	ASSERT(tf->ref_count > 0);
224 	++tf->ref_count;
225 }
226 
227 void dc_transfer_func_release(const struct dc_transfer_func *dc_tf)
228 {
229 	struct transfer_func *tf = DC_TRANSFER_FUNC_TO_TRANSFER_FUNC(dc_tf);
230 
231 	ASSERT(tf->ref_count > 0);
232 	--tf->ref_count;
233 
234 	if (tf->ref_count == 0)
235 		dm_free(tf);
236 }
237 
238 struct dc_transfer_func *dc_create_transfer_func()
239 {
240 	struct transfer_func *tf = dm_alloc(sizeof(*tf));
241 
242 	if (tf == NULL)
243 		goto alloc_fail;
244 
245 	++tf->ref_count;
246 
247 	return &tf->protected.public;
248 
249 alloc_fail:
250 	return NULL;
251 }
252 
253 
254