1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
4  * Author: James.Qian.Wang <james.qian.wang@arm.com>
5  *
6  */
7 #include "komeda_dev.h"
8 #include "komeda_kms.h"
9 
10 static void
11 komeda_component_state_reset(struct komeda_component_state *st)
12 {
13 	st->binding_user = NULL;
14 	st->affected_inputs = st->active_inputs;
15 	st->active_inputs = 0;
16 	st->changed_active_inputs = 0;
17 }
18 
19 static struct drm_private_state *
20 komeda_layer_atomic_duplicate_state(struct drm_private_obj *obj)
21 {
22 	struct komeda_layer_state *st;
23 
24 	st = kmemdup(obj->state, sizeof(*st), GFP_KERNEL);
25 	if (!st)
26 		return NULL;
27 
28 	komeda_component_state_reset(&st->base);
29 	__drm_atomic_helper_private_obj_duplicate_state(obj, &st->base.obj);
30 
31 	return &st->base.obj;
32 }
33 
34 static void
35 komeda_layer_atomic_destroy_state(struct drm_private_obj *obj,
36 				  struct drm_private_state *state)
37 {
38 	struct komeda_layer_state *st = to_layer_st(priv_to_comp_st(state));
39 
40 	kfree(st);
41 }
42 
43 static const struct drm_private_state_funcs komeda_layer_obj_funcs = {
44 	.atomic_duplicate_state	= komeda_layer_atomic_duplicate_state,
45 	.atomic_destroy_state	= komeda_layer_atomic_destroy_state,
46 };
47 
48 static int komeda_layer_obj_add(struct komeda_kms_dev *kms,
49 				struct komeda_layer *layer)
50 {
51 	struct komeda_layer_state *st;
52 
53 	st = kzalloc(sizeof(*st), GFP_KERNEL);
54 	if (!st)
55 		return -ENOMEM;
56 
57 	st->base.component = &layer->base;
58 	drm_atomic_private_obj_init(&kms->base, &layer->base.obj, &st->base.obj,
59 				    &komeda_layer_obj_funcs);
60 	return 0;
61 }
62 
63 static struct drm_private_state *
64 komeda_compiz_atomic_duplicate_state(struct drm_private_obj *obj)
65 {
66 	struct komeda_compiz_state *st;
67 
68 	st = kmemdup(obj->state, sizeof(*st), GFP_KERNEL);
69 	if (!st)
70 		return NULL;
71 
72 	komeda_component_state_reset(&st->base);
73 	__drm_atomic_helper_private_obj_duplicate_state(obj, &st->base.obj);
74 
75 	return &st->base.obj;
76 }
77 
78 static void
79 komeda_compiz_atomic_destroy_state(struct drm_private_obj *obj,
80 				   struct drm_private_state *state)
81 {
82 	kfree(to_compiz_st(priv_to_comp_st(state)));
83 }
84 
85 static const struct drm_private_state_funcs komeda_compiz_obj_funcs = {
86 	.atomic_duplicate_state	= komeda_compiz_atomic_duplicate_state,
87 	.atomic_destroy_state	= komeda_compiz_atomic_destroy_state,
88 };
89 
90 static int komeda_compiz_obj_add(struct komeda_kms_dev *kms,
91 				 struct komeda_compiz *compiz)
92 {
93 	struct komeda_compiz_state *st;
94 
95 	st = kzalloc(sizeof(*st), GFP_KERNEL);
96 	if (!st)
97 		return -ENOMEM;
98 
99 	st->base.component = &compiz->base;
100 	drm_atomic_private_obj_init(&kms->base, &compiz->base.obj, &st->base.obj,
101 				    &komeda_compiz_obj_funcs);
102 
103 	return 0;
104 }
105 
106 static struct drm_private_state *
107 komeda_improc_atomic_duplicate_state(struct drm_private_obj *obj)
108 {
109 	struct komeda_improc_state *st;
110 
111 	st = kmemdup(obj->state, sizeof(*st), GFP_KERNEL);
112 	if (!st)
113 		return NULL;
114 
115 	komeda_component_state_reset(&st->base);
116 	__drm_atomic_helper_private_obj_duplicate_state(obj, &st->base.obj);
117 
118 	return &st->base.obj;
119 }
120 
121 static void
122 komeda_improc_atomic_destroy_state(struct drm_private_obj *obj,
123 				   struct drm_private_state *state)
124 {
125 	kfree(to_improc_st(priv_to_comp_st(state)));
126 }
127 
128 static const struct drm_private_state_funcs komeda_improc_obj_funcs = {
129 	.atomic_duplicate_state	= komeda_improc_atomic_duplicate_state,
130 	.atomic_destroy_state	= komeda_improc_atomic_destroy_state,
131 };
132 
133 static int komeda_improc_obj_add(struct komeda_kms_dev *kms,
134 				 struct komeda_improc *improc)
135 {
136 	struct komeda_improc_state *st;
137 
138 	st = kzalloc(sizeof(*st), GFP_KERNEL);
139 	if (!st)
140 		return -ENOMEM;
141 
142 	st->base.component = &improc->base;
143 	drm_atomic_private_obj_init(&kms->base, &improc->base.obj, &st->base.obj,
144 				    &komeda_improc_obj_funcs);
145 
146 	return 0;
147 }
148 
149 static struct drm_private_state *
150 komeda_timing_ctrlr_atomic_duplicate_state(struct drm_private_obj *obj)
151 {
152 	struct komeda_timing_ctrlr_state *st;
153 
154 	st = kmemdup(obj->state, sizeof(*st), GFP_KERNEL);
155 	if (!st)
156 		return NULL;
157 
158 	komeda_component_state_reset(&st->base);
159 	__drm_atomic_helper_private_obj_duplicate_state(obj, &st->base.obj);
160 
161 	return &st->base.obj;
162 }
163 
164 static void
165 komeda_timing_ctrlr_atomic_destroy_state(struct drm_private_obj *obj,
166 					 struct drm_private_state *state)
167 {
168 	kfree(to_ctrlr_st(priv_to_comp_st(state)));
169 }
170 
171 static const struct drm_private_state_funcs komeda_timing_ctrlr_obj_funcs = {
172 	.atomic_duplicate_state	= komeda_timing_ctrlr_atomic_duplicate_state,
173 	.atomic_destroy_state	= komeda_timing_ctrlr_atomic_destroy_state,
174 };
175 
176 static int komeda_timing_ctrlr_obj_add(struct komeda_kms_dev *kms,
177 				       struct komeda_timing_ctrlr *ctrlr)
178 {
179 	struct komeda_compiz_state *st;
180 
181 	st = kzalloc(sizeof(*st), GFP_KERNEL);
182 	if (!st)
183 		return -ENOMEM;
184 
185 	st->base.component = &ctrlr->base;
186 	drm_atomic_private_obj_init(&kms->base, &ctrlr->base.obj, &st->base.obj,
187 				    &komeda_timing_ctrlr_obj_funcs);
188 
189 	return 0;
190 }
191 
192 static struct drm_private_state *
193 komeda_pipeline_atomic_duplicate_state(struct drm_private_obj *obj)
194 {
195 	struct komeda_pipeline_state *st;
196 
197 	st = kmemdup(obj->state, sizeof(*st), GFP_KERNEL);
198 	if (!st)
199 		return NULL;
200 
201 	st->active_comps = 0;
202 
203 	__drm_atomic_helper_private_obj_duplicate_state(obj, &st->obj);
204 
205 	return &st->obj;
206 }
207 
208 static void
209 komeda_pipeline_atomic_destroy_state(struct drm_private_obj *obj,
210 				     struct drm_private_state *state)
211 {
212 	kfree(priv_to_pipe_st(state));
213 }
214 
215 static const struct drm_private_state_funcs komeda_pipeline_obj_funcs = {
216 	.atomic_duplicate_state	= komeda_pipeline_atomic_duplicate_state,
217 	.atomic_destroy_state	= komeda_pipeline_atomic_destroy_state,
218 };
219 
220 static int komeda_pipeline_obj_add(struct komeda_kms_dev *kms,
221 				   struct komeda_pipeline *pipe)
222 {
223 	struct komeda_pipeline_state *st;
224 
225 	st = kzalloc(sizeof(*st), GFP_KERNEL);
226 	if (!st)
227 		return -ENOMEM;
228 
229 	st->pipe = pipe;
230 	drm_atomic_private_obj_init(&kms->base, &pipe->obj, &st->obj,
231 				    &komeda_pipeline_obj_funcs);
232 
233 	return 0;
234 }
235 
236 int komeda_kms_add_private_objs(struct komeda_kms_dev *kms,
237 				struct komeda_dev *mdev)
238 {
239 	struct komeda_pipeline *pipe;
240 	int i, j, err;
241 
242 	for (i = 0; i < mdev->n_pipelines; i++) {
243 		pipe = mdev->pipelines[i];
244 
245 		err = komeda_pipeline_obj_add(kms, pipe);
246 		if (err)
247 			return err;
248 
249 		for (j = 0; j < pipe->n_layers; j++) {
250 			err = komeda_layer_obj_add(kms, pipe->layers[j]);
251 			if (err)
252 				return err;
253 		}
254 
255 		err = komeda_compiz_obj_add(kms, pipe->compiz);
256 		if (err)
257 			return err;
258 
259 		err = komeda_improc_obj_add(kms, pipe->improc);
260 		if (err)
261 			return err;
262 
263 		err = komeda_timing_ctrlr_obj_add(kms, pipe->ctrlr);
264 		if (err)
265 			return err;
266 	}
267 
268 	return 0;
269 }
270 
271 void komeda_kms_cleanup_private_objs(struct komeda_kms_dev *kms)
272 {
273 	struct drm_mode_config *config = &kms->base.mode_config;
274 	struct drm_private_obj *obj, *next;
275 
276 	list_for_each_entry_safe(obj, next, &config->privobj_list, head)
277 		drm_atomic_private_obj_fini(obj);
278 }
279