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 <linux/clk.h>
8 #include <linux/pm_runtime.h>
9 #include <linux/spinlock.h>
10 
11 #include <drm/drm_atomic.h>
12 #include <drm/drm_atomic_helper.h>
13 #include <drm/drm_crtc_helper.h>
14 #include <drm/drm_plane_helper.h>
15 #include <drm/drm_print.h>
16 #include <drm/drm_vblank.h>
17 
18 #include "komeda_dev.h"
19 #include "komeda_kms.h"
20 
21 struct drm_crtc_helper_funcs komeda_crtc_helper_funcs = {
22 };
23 
24 static const struct drm_crtc_funcs komeda_crtc_funcs = {
25 };
26 
27 int komeda_kms_setup_crtcs(struct komeda_kms_dev *kms,
28 			   struct komeda_dev *mdev)
29 {
30 	struct komeda_crtc *crtc;
31 	struct komeda_pipeline *master;
32 	char str[16];
33 	int i;
34 
35 	kms->n_crtcs = 0;
36 
37 	for (i = 0; i < mdev->n_pipelines; i++) {
38 		crtc = &kms->crtcs[kms->n_crtcs];
39 		master = mdev->pipelines[i];
40 
41 		crtc->master = master;
42 		crtc->slave  = NULL;
43 
44 		if (crtc->slave)
45 			sprintf(str, "pipe-%d", crtc->slave->id);
46 		else
47 			sprintf(str, "None");
48 
49 		DRM_INFO("crtc%d: master(pipe-%d) slave(%s) output: %s.\n",
50 			 kms->n_crtcs, master->id, str,
51 			 master->of_output_dev ?
52 			 master->of_output_dev->full_name : "None");
53 
54 		kms->n_crtcs++;
55 	}
56 
57 	return 0;
58 }
59 
60 static struct drm_plane *
61 get_crtc_primary(struct komeda_kms_dev *kms, struct komeda_crtc *crtc)
62 {
63 	struct komeda_plane *kplane;
64 	struct drm_plane *plane;
65 
66 	drm_for_each_plane(plane, &kms->base) {
67 		if (plane->type != DRM_PLANE_TYPE_PRIMARY)
68 			continue;
69 
70 		kplane = to_kplane(plane);
71 		/* only master can be primary */
72 		if (kplane->layer->base.pipeline == crtc->master)
73 			return plane;
74 	}
75 
76 	return NULL;
77 }
78 
79 static int komeda_crtc_add(struct komeda_kms_dev *kms,
80 			   struct komeda_crtc *kcrtc)
81 {
82 	struct drm_crtc *crtc = &kcrtc->base;
83 	int err;
84 
85 	err = drm_crtc_init_with_planes(&kms->base, crtc,
86 					get_crtc_primary(kms, kcrtc), NULL,
87 					&komeda_crtc_funcs, NULL);
88 	if (err)
89 		return err;
90 
91 	drm_crtc_helper_add(crtc, &komeda_crtc_helper_funcs);
92 	drm_crtc_vblank_reset(crtc);
93 
94 	crtc->port = kcrtc->master->of_output_port;
95 
96 	return 0;
97 }
98 
99 int komeda_kms_add_crtcs(struct komeda_kms_dev *kms, struct komeda_dev *mdev)
100 {
101 	int i, err;
102 
103 	for (i = 0; i < kms->n_crtcs; i++) {
104 		err = komeda_crtc_add(kms, &kms->crtcs[i]);
105 		if (err)
106 			return err;
107 	}
108 
109 	return 0;
110 }
111