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