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