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