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