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