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_plane_state *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_plane_state *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_plane_state *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_plane_state *dc_create_surface(const struct dc *dc)
68 {
69 	struct core_dc *core_dc = DC_TO_CORE(dc);
70 
71 	struct dc_plane_state *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_plane_state *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_plane_state *surface)
124 {
125 	ASSERT(surface->ref_count > 0);
126 	++surface->ref_count;
127 }
128 
129 void dc_surface_release(struct dc_plane_state *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(struct dc_gamma *gamma)
141 {
142 	ASSERT(gamma->ref_count > 0);
143 	++gamma->ref_count;
144 }
145 
146 void dc_gamma_release(struct dc_gamma **gamma)
147 {
148 	ASSERT((*gamma)->ref_count > 0);
149 	--(*gamma)->ref_count;
150 
151 	if ((*gamma)->ref_count == 0)
152 		dm_free((*gamma));
153 
154 	*gamma = NULL;
155 }
156 
157 struct dc_gamma *dc_create_gamma()
158 {
159 	struct dc_gamma *gamma = dm_alloc(sizeof(*gamma));
160 
161 	if (gamma == NULL)
162 		goto alloc_fail;
163 
164 	++gamma->ref_count;
165 
166 	return gamma;
167 
168 alloc_fail:
169 	return NULL;
170 }
171 
172 void dc_transfer_func_retain(struct dc_transfer_func *tf)
173 {
174 	ASSERT(tf->ref_count > 0);
175 	++tf->ref_count;
176 }
177 
178 void dc_transfer_func_release(struct dc_transfer_func *tf)
179 {
180 	ASSERT(tf->ref_count > 0);
181 	--tf->ref_count;
182 
183 	if (tf->ref_count == 0)
184 		dm_free(tf);
185 }
186 
187 struct dc_transfer_func *dc_create_transfer_func()
188 {
189 	struct dc_transfer_func *tf = dm_alloc(sizeof(*tf));
190 
191 	if (tf == NULL)
192 		goto alloc_fail;
193 
194 	++tf->ref_count;
195 
196 	return tf;
197 
198 alloc_fail:
199 	return NULL;
200 }
201 
202 
203