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 = DC_SURFACE_TO_CORE(dc_surface);
125 	struct core_dc *core_dc;
126 	int i;
127 
128 	if (!dc_surface ||
129 		!core_surface->ctx ||
130 		!core_surface->ctx->dc) {
131 		ASSERT(0);
132 		return NULL; /* remove this if above assert never hit */
133 	}
134 
135 	surface_status = &core_surface->status;
136 	core_dc = DC_TO_CORE(core_surface->ctx->dc);
137 
138 	if (core_dc->current_context == NULL)
139 		return NULL;
140 
141 	for (i = 0; i < core_dc->current_context->res_ctx.pool->pipe_count;
142 			i++) {
143 		struct pipe_ctx *pipe_ctx =
144 				&core_dc->current_context->res_ctx.pipe_ctx[i];
145 
146 		if (pipe_ctx->surface != core_surface)
147 			continue;
148 
149 		core_dc->hwss.update_pending_status(pipe_ctx);
150 	}
151 
152 	return surface_status;
153 }
154 
155 void dc_surface_retain(const struct dc_surface *dc_surface)
156 {
157 	struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface);
158 
159 	ASSERT(surface->ref_count > 0);
160 	++surface->ref_count;
161 }
162 
163 void dc_surface_release(const struct dc_surface *dc_surface)
164 {
165 	struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface);
166 
167 	ASSERT(surface->ref_count > 0);
168 	--surface->ref_count;
169 
170 	if (surface->ref_count == 0) {
171 		destruct(surface);
172 		dm_free(surface);
173 	}
174 }
175 
176 void dc_gamma_retain(const struct dc_gamma *dc_gamma)
177 {
178 	struct gamma *gamma = DC_GAMMA_TO_GAMMA(dc_gamma);
179 
180 	ASSERT(gamma->ref_count > 0);
181 	++gamma->ref_count;
182 }
183 
184 void dc_gamma_release(const struct dc_gamma **dc_gamma)
185 {
186 	struct gamma *gamma = DC_GAMMA_TO_GAMMA(*dc_gamma);
187 
188 	ASSERT(gamma->ref_count > 0);
189 	--gamma->ref_count;
190 
191 	if (gamma->ref_count == 0)
192 		dm_free(gamma);
193 
194 	*dc_gamma = NULL;
195 }
196 
197 struct dc_gamma *dc_create_gamma()
198 {
199 	struct gamma *gamma = dm_alloc(sizeof(*gamma));
200 
201 	if (gamma == NULL)
202 		goto alloc_fail;
203 
204 	++gamma->ref_count;
205 
206 	return &gamma->protected.public;
207 
208 alloc_fail:
209 	return NULL;
210 }
211 
212 void dc_transfer_func_retain(const struct dc_transfer_func *dc_tf)
213 {
214 	struct transfer_func *tf = DC_TRANSFER_FUNC_TO_TRANSFER_FUNC(dc_tf);
215 
216 	ASSERT(tf->ref_count > 0);
217 	++tf->ref_count;
218 }
219 
220 void dc_transfer_func_release(const struct dc_transfer_func *dc_tf)
221 {
222 	struct transfer_func *tf = DC_TRANSFER_FUNC_TO_TRANSFER_FUNC(dc_tf);
223 
224 	ASSERT(tf->ref_count > 0);
225 	--tf->ref_count;
226 
227 	if (tf->ref_count == 0)
228 		dm_free(tf);
229 }
230 
231 struct dc_transfer_func *dc_create_transfer_func()
232 {
233 	struct transfer_func *tf = dm_alloc(sizeof(*tf));
234 
235 	if (tf == NULL)
236 		goto alloc_fail;
237 
238 	++tf->ref_count;
239 
240 	return &tf->protected.public;
241 
242 alloc_fail:
243 	return NULL;
244 }
245 
246 
247