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