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