xref: /linux/drivers/gpu/drm/imx/dc/dc-kms.c (revision 8d2b0853add1d7534dc0794e3c8e0b9e8c4ec640)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2024 NXP
4  */
5 
6 #include <linux/of.h>
7 #include <linux/of_graph.h>
8 
9 #include <drm/drm_atomic_helper.h>
10 #include <drm/drm_bridge.h>
11 #include <drm/drm_bridge_connector.h>
12 #include <drm/drm_connector.h>
13 #include <drm/drm_crtc.h>
14 #include <drm/drm_device.h>
15 #include <drm/drm_encoder.h>
16 #include <drm/drm_gem_framebuffer_helper.h>
17 #include <drm/drm_mode_config.h>
18 #include <drm/drm_print.h>
19 #include <drm/drm_probe_helper.h>
20 #include <drm/drm_simple_kms_helper.h>
21 #include <drm/drm_vblank.h>
22 
23 #include "dc-de.h"
24 #include "dc-drv.h"
25 #include "dc-kms.h"
26 
27 static const struct drm_mode_config_funcs dc_drm_mode_config_funcs = {
28 	.fb_create = drm_gem_fb_create,
29 	.atomic_check = drm_atomic_helper_check,
30 	.atomic_commit = drm_atomic_helper_commit,
31 };
32 
33 static int dc_kms_init_encoder_per_crtc(struct dc_drm_device *dc_drm,
34 					int crtc_index)
35 {
36 	struct dc_crtc *dc_crtc = &dc_drm->dc_crtc[crtc_index];
37 	struct drm_device *drm = &dc_drm->base;
38 	struct drm_crtc *crtc = &dc_crtc->base;
39 	struct drm_connector *connector;
40 	struct device *dev = drm->dev;
41 	struct drm_encoder *encoder;
42 	struct drm_bridge *bridge;
43 	int ret;
44 
45 	bridge = devm_drm_of_get_bridge(dev, dc_crtc->de->tc->dev->of_node,
46 					0, 0);
47 	if (IS_ERR(bridge)) {
48 		ret = PTR_ERR(bridge);
49 		if (ret == -ENODEV)
50 			return 0;
51 
52 		return dev_err_probe(dev, ret,
53 				     "failed to find bridge for CRTC%u\n",
54 				     crtc->index);
55 	}
56 
57 	encoder = &dc_drm->encoder[crtc_index];
58 	ret = drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_NONE);
59 	if (ret) {
60 		dev_err(dev, "failed to initialize encoder for CRTC%u: %d\n",
61 			crtc->index, ret);
62 		return ret;
63 	}
64 
65 	encoder->possible_crtcs = drm_crtc_mask(crtc);
66 
67 	ret = drm_bridge_attach(encoder, bridge, NULL,
68 				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
69 	if (ret) {
70 		dev_err(dev,
71 			"failed to attach bridge to encoder for CRTC%u: %d\n",
72 			crtc->index, ret);
73 		return ret;
74 	}
75 
76 	connector = drm_bridge_connector_init(drm, encoder);
77 	if (IS_ERR(connector)) {
78 		ret = PTR_ERR(connector);
79 		dev_err(dev, "failed to init bridge connector for CRTC%u: %d\n",
80 			crtc->index, ret);
81 		return ret;
82 	}
83 
84 	ret = drm_connector_attach_encoder(connector, encoder);
85 	if (ret)
86 		dev_err(dev,
87 			"failed to attach encoder to connector for CRTC%u: %d\n",
88 			crtc->index, ret);
89 
90 	return ret;
91 }
92 
93 int dc_kms_init(struct dc_drm_device *dc_drm)
94 {
95 	struct drm_device *drm = &dc_drm->base;
96 	int ret, i;
97 
98 	ret = drmm_mode_config_init(drm);
99 	if (ret)
100 		return ret;
101 
102 	drm->mode_config.min_width = 60;
103 	drm->mode_config.min_height = 60;
104 	drm->mode_config.max_width = 8192;
105 	drm->mode_config.max_height = 8192;
106 	drm->mode_config.funcs = &dc_drm_mode_config_funcs;
107 
108 	drm->vblank_disable_immediate = true;
109 	drm->max_vblank_count = DC_FRAMEGEN_MAX_FRAME_INDEX;
110 
111 	for (i = 0; i < DC_DISPLAYS; i++) {
112 		ret = dc_crtc_init(dc_drm, i);
113 		if (ret)
114 			return ret;
115 
116 		ret = dc_kms_init_encoder_per_crtc(dc_drm, i);
117 		if (ret)
118 			return ret;
119 	}
120 
121 	for (i = 0; i < DC_DISPLAYS; i++) {
122 		ret = dc_crtc_post_init(dc_drm, i);
123 		if (ret)
124 			return ret;
125 	}
126 
127 	ret = drm_vblank_init(drm, DC_DISPLAYS);
128 	if (ret) {
129 		dev_err(drm->dev, "failed to init vblank support: %d\n", ret);
130 		return ret;
131 	}
132 
133 	drm_mode_config_reset(drm);
134 
135 	drm_kms_helper_poll_init(drm);
136 
137 	return 0;
138 }
139 
140 void dc_kms_uninit(struct dc_drm_device *dc_drm)
141 {
142 	drm_kms_helper_poll_fini(&dc_drm->base);
143 }
144