1 // SPDX-License-Identifier: GPL-2.0-or-later 2 // Copyright (c) 2024 Hisilicon Limited. 3 4 #include <linux/io.h> 5 6 #include <drm/drm_probe_helper.h> 7 #include <drm/drm_simple_kms_helper.h> 8 #include <drm/drm_atomic_helper.h> 9 #include <drm/drm_modes.h> 10 #include <drm/drm_drv.h> 11 #include <drm/drm_edid.h> 12 13 #include "hibmc_drm_drv.h" 14 #include "dp/dp_hw.h" 15 16 static int hibmc_dp_connector_get_modes(struct drm_connector *connector) 17 { 18 int count; 19 20 count = drm_add_modes_noedid(connector, connector->dev->mode_config.max_width, 21 connector->dev->mode_config.max_height); 22 drm_set_preferred_mode(connector, 1024, 768); // temporary implementation 23 24 return count; 25 } 26 27 static const struct drm_connector_helper_funcs hibmc_dp_conn_helper_funcs = { 28 .get_modes = hibmc_dp_connector_get_modes, 29 }; 30 31 static const struct drm_connector_funcs hibmc_dp_conn_funcs = { 32 .reset = drm_atomic_helper_connector_reset, 33 .fill_modes = drm_helper_probe_single_connector_modes, 34 .destroy = drm_connector_cleanup, 35 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 36 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 37 }; 38 39 static inline int hibmc_dp_prepare(struct hibmc_dp *dp, struct drm_display_mode *mode) 40 { 41 int ret; 42 43 hibmc_dp_display_en(dp, false); 44 45 ret = hibmc_dp_mode_set(dp, mode); 46 if (ret) 47 drm_err(dp->drm_dev, "hibmc dp mode set failed: %d\n", ret); 48 49 return ret; 50 } 51 52 static void hibmc_dp_encoder_enable(struct drm_encoder *drm_encoder, 53 struct drm_atomic_state *state) 54 { 55 struct hibmc_dp *dp = container_of(drm_encoder, struct hibmc_dp, encoder); 56 struct drm_display_mode *mode = &drm_encoder->crtc->state->mode; 57 58 if (hibmc_dp_prepare(dp, mode)) 59 return; 60 61 hibmc_dp_display_en(dp, true); 62 } 63 64 static void hibmc_dp_encoder_disable(struct drm_encoder *drm_encoder, 65 struct drm_atomic_state *state) 66 { 67 struct hibmc_dp *dp = container_of(drm_encoder, struct hibmc_dp, encoder); 68 69 hibmc_dp_display_en(dp, false); 70 } 71 72 static const struct drm_encoder_helper_funcs hibmc_dp_encoder_helper_funcs = { 73 .atomic_enable = hibmc_dp_encoder_enable, 74 .atomic_disable = hibmc_dp_encoder_disable, 75 }; 76 77 int hibmc_dp_init(struct hibmc_drm_private *priv) 78 { 79 struct drm_device *dev = &priv->dev; 80 struct drm_crtc *crtc = &priv->crtc; 81 struct hibmc_dp *dp = &priv->dp; 82 struct drm_connector *connector = &dp->connector; 83 struct drm_encoder *encoder = &dp->encoder; 84 int ret; 85 86 dp->mmio = priv->mmio; 87 dp->drm_dev = dev; 88 89 ret = hibmc_dp_hw_init(&priv->dp); 90 if (ret) { 91 drm_err(dev, "hibmc dp hw init failed: %d\n", ret); 92 return ret; 93 } 94 95 hibmc_dp_display_en(&priv->dp, false); 96 97 encoder->possible_crtcs = drm_crtc_mask(crtc); 98 ret = drmm_encoder_init(dev, encoder, NULL, DRM_MODE_ENCODER_TMDS, NULL); 99 if (ret) { 100 drm_err(dev, "init dp encoder failed: %d\n", ret); 101 return ret; 102 } 103 104 drm_encoder_helper_add(encoder, &hibmc_dp_encoder_helper_funcs); 105 106 ret = drm_connector_init(dev, connector, &hibmc_dp_conn_funcs, 107 DRM_MODE_CONNECTOR_DisplayPort); 108 if (ret) { 109 drm_err(dev, "init dp connector failed: %d\n", ret); 110 return ret; 111 } 112 113 drm_connector_helper_add(connector, &hibmc_dp_conn_helper_funcs); 114 115 drm_connector_attach_encoder(connector, encoder); 116 117 return 0; 118 } 119