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