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 <drm/drm_atomic.h>
8 #include <drm/drm_atomic_helper.h>
9 #include <drm/drm_plane_helper.h>
10 #include "komeda_dev.h"
11 #include "komeda_kms.h"
12 
13 static const struct drm_plane_helper_funcs komeda_plane_helper_funcs = {
14 };
15 
16 static void komeda_plane_destroy(struct drm_plane *plane)
17 {
18 	drm_plane_cleanup(plane);
19 
20 	kfree(to_kplane(plane));
21 }
22 
23 static const struct drm_plane_funcs komeda_plane_funcs = {
24 };
25 
26 /* for komeda, which is pipeline can be share between crtcs */
27 static u32 get_possible_crtcs(struct komeda_kms_dev *kms,
28 			      struct komeda_pipeline *pipe)
29 {
30 	struct komeda_crtc *crtc;
31 	u32 possible_crtcs = 0;
32 	int i;
33 
34 	for (i = 0; i < kms->n_crtcs; i++) {
35 		crtc = &kms->crtcs[i];
36 
37 		if ((pipe == crtc->master) || (pipe == crtc->slave))
38 			possible_crtcs |= BIT(i);
39 	}
40 
41 	return possible_crtcs;
42 }
43 
44 /* use Layer0 as primary */
45 static u32 get_plane_type(struct komeda_kms_dev *kms,
46 			  struct komeda_component *c)
47 {
48 	bool is_primary = (c->id == KOMEDA_COMPONENT_LAYER0);
49 
50 	return is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
51 }
52 
53 static int komeda_plane_add(struct komeda_kms_dev *kms,
54 			    struct komeda_layer *layer)
55 {
56 	struct komeda_dev *mdev = kms->base.dev_private;
57 	struct komeda_component *c = &layer->base;
58 	struct komeda_plane *kplane;
59 	struct drm_plane *plane;
60 	u32 *formats, n_formats = 0;
61 	int err;
62 
63 	kplane = kzalloc(sizeof(*kplane), GFP_KERNEL);
64 	if (!kplane)
65 		return -ENOMEM;
66 
67 	plane = &kplane->base;
68 	kplane->layer = layer;
69 
70 	formats = komeda_get_layer_fourcc_list(&mdev->fmt_tbl,
71 					       layer->layer_type, &n_formats);
72 
73 	err = drm_universal_plane_init(&kms->base, plane,
74 			get_possible_crtcs(kms, c->pipeline),
75 			&komeda_plane_funcs,
76 			formats, n_formats, NULL,
77 			get_plane_type(kms, c),
78 			"%s", c->name);
79 
80 	komeda_put_fourcc_list(formats);
81 
82 	if (err)
83 		goto cleanup;
84 
85 	drm_plane_helper_add(plane, &komeda_plane_helper_funcs);
86 
87 	return 0;
88 cleanup:
89 	komeda_plane_destroy(plane);
90 	return err;
91 }
92 
93 int komeda_kms_add_planes(struct komeda_kms_dev *kms, struct komeda_dev *mdev)
94 {
95 	struct komeda_pipeline *pipe;
96 	int i, j, err;
97 
98 	for (i = 0; i < mdev->n_pipelines; i++) {
99 		pipe = mdev->pipelines[i];
100 
101 		for (j = 0; j < pipe->n_layers; j++) {
102 			err = komeda_plane_add(kms, pipe->layers[j]);
103 			if (err)
104 				return err;
105 		}
106 	}
107 
108 	return 0;
109 }
110