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
10static void
11komeda_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
19static struct drm_private_state *
20komeda_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
34static void
35komeda_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
43static 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
48static 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
63static struct drm_private_state *
64komeda_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
78static void
79komeda_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
85static 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
90static 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
106static struct drm_private_state *
107komeda_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
121static void
122komeda_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
128static 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
133static 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
149static struct drm_private_state *
150komeda_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
164static void
165komeda_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
171static 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
176static 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
193static struct drm_private_state *
194komeda_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
208static 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
214static 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
219static 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
236static struct drm_private_state *
237komeda_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
251static void
252komeda_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
258static 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
263static 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
279static struct drm_private_state *
280komeda_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
294static void
295komeda_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
301static 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
306static 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
322static struct drm_private_state *
323komeda_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
338static void
339komeda_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
345static 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
350static 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
366int 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
425void 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