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
komeda_component_state_reset(struct komeda_component_state * st)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 *
komeda_layer_atomic_duplicate_state(struct drm_private_obj * obj)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
komeda_layer_atomic_destroy_state(struct drm_private_obj * obj,struct drm_private_state * state)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 
komeda_layer_obj_add(struct komeda_kms_dev * kms,struct komeda_layer * layer)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 *
komeda_scaler_atomic_duplicate_state(struct drm_private_obj * obj)64 komeda_scaler_atomic_duplicate_state(struct drm_private_obj *obj)
65 {
66 	struct komeda_scaler_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
komeda_scaler_atomic_destroy_state(struct drm_private_obj * obj,struct drm_private_state * state)79 komeda_scaler_atomic_destroy_state(struct drm_private_obj *obj,
80 				   struct drm_private_state *state)
81 {
82 	kfree(to_scaler_st(priv_to_comp_st(state)));
83 }
84 
85 static const struct drm_private_state_funcs komeda_scaler_obj_funcs = {
86 	.atomic_duplicate_state	= komeda_scaler_atomic_duplicate_state,
87 	.atomic_destroy_state	= komeda_scaler_atomic_destroy_state,
88 };
89 
komeda_scaler_obj_add(struct komeda_kms_dev * kms,struct komeda_scaler * scaler)90 static int komeda_scaler_obj_add(struct komeda_kms_dev *kms,
91 				 struct komeda_scaler *scaler)
92 {
93 	struct komeda_scaler_state *st;
94 
95 	st = kzalloc(sizeof(*st), GFP_KERNEL);
96 	if (!st)
97 		return -ENOMEM;
98 
99 	st->base.component = &scaler->base;
100 	drm_atomic_private_obj_init(&kms->base,
101 				    &scaler->base.obj, &st->base.obj,
102 				    &komeda_scaler_obj_funcs);
103 	return 0;
104 }
105 
106 static struct drm_private_state *
komeda_compiz_atomic_duplicate_state(struct drm_private_obj * obj)107 komeda_compiz_atomic_duplicate_state(struct drm_private_obj *obj)
108 {
109 	struct komeda_compiz_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
komeda_compiz_atomic_destroy_state(struct drm_private_obj * obj,struct drm_private_state * state)122 komeda_compiz_atomic_destroy_state(struct drm_private_obj *obj,
123 				   struct drm_private_state *state)
124 {
125 	kfree(to_compiz_st(priv_to_comp_st(state)));
126 }
127 
128 static const struct drm_private_state_funcs komeda_compiz_obj_funcs = {
129 	.atomic_duplicate_state	= komeda_compiz_atomic_duplicate_state,
130 	.atomic_destroy_state	= komeda_compiz_atomic_destroy_state,
131 };
132 
komeda_compiz_obj_add(struct komeda_kms_dev * kms,struct komeda_compiz * compiz)133 static int komeda_compiz_obj_add(struct komeda_kms_dev *kms,
134 				 struct komeda_compiz *compiz)
135 {
136 	struct komeda_compiz_state *st;
137 
138 	st = kzalloc(sizeof(*st), GFP_KERNEL);
139 	if (!st)
140 		return -ENOMEM;
141 
142 	st->base.component = &compiz->base;
143 	drm_atomic_private_obj_init(&kms->base, &compiz->base.obj, &st->base.obj,
144 				    &komeda_compiz_obj_funcs);
145 
146 	return 0;
147 }
148 
149 static struct drm_private_state *
komeda_splitter_atomic_duplicate_state(struct drm_private_obj * obj)150 komeda_splitter_atomic_duplicate_state(struct drm_private_obj *obj)
151 {
152 	struct komeda_splitter_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
komeda_splitter_atomic_destroy_state(struct drm_private_obj * obj,struct drm_private_state * state)165 komeda_splitter_atomic_destroy_state(struct drm_private_obj *obj,
166 				     struct drm_private_state *state)
167 {
168 	kfree(to_splitter_st(priv_to_comp_st(state)));
169 }
170 
171 static const struct drm_private_state_funcs komeda_splitter_obj_funcs = {
172 	.atomic_duplicate_state	= komeda_splitter_atomic_duplicate_state,
173 	.atomic_destroy_state	= komeda_splitter_atomic_destroy_state,
174 };
175 
komeda_splitter_obj_add(struct komeda_kms_dev * kms,struct komeda_splitter * splitter)176 static int komeda_splitter_obj_add(struct komeda_kms_dev *kms,
177 				   struct komeda_splitter *splitter)
178 {
179 	struct komeda_splitter_state *st;
180 
181 	st = kzalloc(sizeof(*st), GFP_KERNEL);
182 	if (!st)
183 		return -ENOMEM;
184 
185 	st->base.component = &splitter->base;
186 	drm_atomic_private_obj_init(&kms->base,
187 				    &splitter->base.obj, &st->base.obj,
188 				    &komeda_splitter_obj_funcs);
189 
190 	return 0;
191 }
192 
193 static struct drm_private_state *
komeda_merger_atomic_duplicate_state(struct drm_private_obj * obj)194 komeda_merger_atomic_duplicate_state(struct drm_private_obj *obj)
195 {
196 	struct komeda_merger_state *st;
197 
198 	st = kmemdup(obj->state, sizeof(*st), GFP_KERNEL);
199 	if (!st)
200 		return NULL;
201 
202 	komeda_component_state_reset(&st->base);
203 	__drm_atomic_helper_private_obj_duplicate_state(obj, &st->base.obj);
204 
205 	return &st->base.obj;
206 }
207 
komeda_merger_atomic_destroy_state(struct drm_private_obj * obj,struct drm_private_state * state)208 static void komeda_merger_atomic_destroy_state(struct drm_private_obj *obj,
209 					       struct drm_private_state *state)
210 {
211 	kfree(to_merger_st(priv_to_comp_st(state)));
212 }
213 
214 static const struct drm_private_state_funcs komeda_merger_obj_funcs = {
215 	.atomic_duplicate_state	= komeda_merger_atomic_duplicate_state,
216 	.atomic_destroy_state	= komeda_merger_atomic_destroy_state,
217 };
218 
komeda_merger_obj_add(struct komeda_kms_dev * kms,struct komeda_merger * merger)219 static int komeda_merger_obj_add(struct komeda_kms_dev *kms,
220 				 struct komeda_merger *merger)
221 {
222 	struct komeda_merger_state *st;
223 
224 	st = kzalloc(sizeof(*st), GFP_KERNEL);
225 	if (!st)
226 		return -ENOMEM;
227 
228 	st->base.component = &merger->base;
229 	drm_atomic_private_obj_init(&kms->base,
230 				    &merger->base.obj, &st->base.obj,
231 				    &komeda_merger_obj_funcs);
232 
233 	return 0;
234 }
235 
236 static struct drm_private_state *
komeda_improc_atomic_duplicate_state(struct drm_private_obj * obj)237 komeda_improc_atomic_duplicate_state(struct drm_private_obj *obj)
238 {
239 	struct komeda_improc_state *st;
240 
241 	st = kmemdup(obj->state, sizeof(*st), GFP_KERNEL);
242 	if (!st)
243 		return NULL;
244 
245 	komeda_component_state_reset(&st->base);
246 	__drm_atomic_helper_private_obj_duplicate_state(obj, &st->base.obj);
247 
248 	return &st->base.obj;
249 }
250 
251 static void
komeda_improc_atomic_destroy_state(struct drm_private_obj * obj,struct drm_private_state * state)252 komeda_improc_atomic_destroy_state(struct drm_private_obj *obj,
253 				   struct drm_private_state *state)
254 {
255 	kfree(to_improc_st(priv_to_comp_st(state)));
256 }
257 
258 static const struct drm_private_state_funcs komeda_improc_obj_funcs = {
259 	.atomic_duplicate_state	= komeda_improc_atomic_duplicate_state,
260 	.atomic_destroy_state	= komeda_improc_atomic_destroy_state,
261 };
262 
komeda_improc_obj_add(struct komeda_kms_dev * kms,struct komeda_improc * improc)263 static int komeda_improc_obj_add(struct komeda_kms_dev *kms,
264 				 struct komeda_improc *improc)
265 {
266 	struct komeda_improc_state *st;
267 
268 	st = kzalloc(sizeof(*st), GFP_KERNEL);
269 	if (!st)
270 		return -ENOMEM;
271 
272 	st->base.component = &improc->base;
273 	drm_atomic_private_obj_init(&kms->base, &improc->base.obj, &st->base.obj,
274 				    &komeda_improc_obj_funcs);
275 
276 	return 0;
277 }
278 
279 static struct drm_private_state *
komeda_timing_ctrlr_atomic_duplicate_state(struct drm_private_obj * obj)280 komeda_timing_ctrlr_atomic_duplicate_state(struct drm_private_obj *obj)
281 {
282 	struct komeda_timing_ctrlr_state *st;
283 
284 	st = kmemdup(obj->state, sizeof(*st), GFP_KERNEL);
285 	if (!st)
286 		return NULL;
287 
288 	komeda_component_state_reset(&st->base);
289 	__drm_atomic_helper_private_obj_duplicate_state(obj, &st->base.obj);
290 
291 	return &st->base.obj;
292 }
293 
294 static void
komeda_timing_ctrlr_atomic_destroy_state(struct drm_private_obj * obj,struct drm_private_state * state)295 komeda_timing_ctrlr_atomic_destroy_state(struct drm_private_obj *obj,
296 					 struct drm_private_state *state)
297 {
298 	kfree(to_ctrlr_st(priv_to_comp_st(state)));
299 }
300 
301 static const struct drm_private_state_funcs komeda_timing_ctrlr_obj_funcs = {
302 	.atomic_duplicate_state	= komeda_timing_ctrlr_atomic_duplicate_state,
303 	.atomic_destroy_state	= komeda_timing_ctrlr_atomic_destroy_state,
304 };
305 
komeda_timing_ctrlr_obj_add(struct komeda_kms_dev * kms,struct komeda_timing_ctrlr * ctrlr)306 static int komeda_timing_ctrlr_obj_add(struct komeda_kms_dev *kms,
307 				       struct komeda_timing_ctrlr *ctrlr)
308 {
309 	struct komeda_compiz_state *st;
310 
311 	st = kzalloc(sizeof(*st), GFP_KERNEL);
312 	if (!st)
313 		return -ENOMEM;
314 
315 	st->base.component = &ctrlr->base;
316 	drm_atomic_private_obj_init(&kms->base, &ctrlr->base.obj, &st->base.obj,
317 				    &komeda_timing_ctrlr_obj_funcs);
318 
319 	return 0;
320 }
321 
322 static struct drm_private_state *
komeda_pipeline_atomic_duplicate_state(struct drm_private_obj * obj)323 komeda_pipeline_atomic_duplicate_state(struct drm_private_obj *obj)
324 {
325 	struct komeda_pipeline_state *st;
326 
327 	st = kmemdup(obj->state, sizeof(*st), GFP_KERNEL);
328 	if (!st)
329 		return NULL;
330 
331 	st->active_comps = 0;
332 
333 	__drm_atomic_helper_private_obj_duplicate_state(obj, &st->obj);
334 
335 	return &st->obj;
336 }
337 
338 static void
komeda_pipeline_atomic_destroy_state(struct drm_private_obj * obj,struct drm_private_state * state)339 komeda_pipeline_atomic_destroy_state(struct drm_private_obj *obj,
340 				     struct drm_private_state *state)
341 {
342 	kfree(priv_to_pipe_st(state));
343 }
344 
345 static const struct drm_private_state_funcs komeda_pipeline_obj_funcs = {
346 	.atomic_duplicate_state	= komeda_pipeline_atomic_duplicate_state,
347 	.atomic_destroy_state	= komeda_pipeline_atomic_destroy_state,
348 };
349 
komeda_pipeline_obj_add(struct komeda_kms_dev * kms,struct komeda_pipeline * pipe)350 static int komeda_pipeline_obj_add(struct komeda_kms_dev *kms,
351 				   struct komeda_pipeline *pipe)
352 {
353 	struct komeda_pipeline_state *st;
354 
355 	st = kzalloc(sizeof(*st), GFP_KERNEL);
356 	if (!st)
357 		return -ENOMEM;
358 
359 	st->pipe = pipe;
360 	drm_atomic_private_obj_init(&kms->base, &pipe->obj, &st->obj,
361 				    &komeda_pipeline_obj_funcs);
362 
363 	return 0;
364 }
365 
komeda_kms_add_private_objs(struct komeda_kms_dev * kms,struct komeda_dev * mdev)366 int komeda_kms_add_private_objs(struct komeda_kms_dev *kms,
367 				struct komeda_dev *mdev)
368 {
369 	struct komeda_pipeline *pipe;
370 	int i, j, err;
371 
372 	for (i = 0; i < mdev->n_pipelines; i++) {
373 		pipe = mdev->pipelines[i];
374 
375 		err = komeda_pipeline_obj_add(kms, pipe);
376 		if (err)
377 			return err;
378 
379 		for (j = 0; j < pipe->n_layers; j++) {
380 			err = komeda_layer_obj_add(kms, pipe->layers[j]);
381 			if (err)
382 				return err;
383 		}
384 
385 		if (pipe->wb_layer) {
386 			err = komeda_layer_obj_add(kms, pipe->wb_layer);
387 			if (err)
388 				return err;
389 		}
390 
391 		for (j = 0; j < pipe->n_scalers; j++) {
392 			err = komeda_scaler_obj_add(kms, pipe->scalers[j]);
393 			if (err)
394 				return err;
395 		}
396 
397 		err = komeda_compiz_obj_add(kms, pipe->compiz);
398 		if (err)
399 			return err;
400 
401 		if (pipe->splitter) {
402 			err = komeda_splitter_obj_add(kms, pipe->splitter);
403 			if (err)
404 				return err;
405 		}
406 
407 		if (pipe->merger) {
408 			err = komeda_merger_obj_add(kms, pipe->merger);
409 			if (err)
410 				return err;
411 		}
412 
413 		err = komeda_improc_obj_add(kms, pipe->improc);
414 		if (err)
415 			return err;
416 
417 		err = komeda_timing_ctrlr_obj_add(kms, pipe->ctrlr);
418 		if (err)
419 			return err;
420 	}
421 
422 	return 0;
423 }
424 
komeda_kms_cleanup_private_objs(struct komeda_kms_dev * kms)425 void komeda_kms_cleanup_private_objs(struct komeda_kms_dev *kms)
426 {
427 	struct drm_mode_config *config = &kms->base.mode_config;
428 	struct drm_private_obj *obj, *next;
429 
430 	list_for_each_entry_safe(obj, next, &config->privobj_list, head)
431 		drm_atomic_private_obj_fini(obj);
432 }
433