1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* Hisilicon Hibmc SoC drm driver 3 * 4 * Based on the bochs drm driver. 5 * 6 * Copyright (c) 2016 Huawei Limited. 7 * 8 * Author: 9 * Rongrong Zou <zourongrong@huawei.com> 10 * Rongrong Zou <zourongrong@gmail.com> 11 * Jianhua Li <lijianhua@huawei.com> 12 */ 13 14 #include <drm/drm_atomic_helper.h> 15 #include <drm/drm_probe_helper.h> 16 17 #include "hibmc_drm_drv.h" 18 #include "hibmc_drm_regs.h" 19 20 static int hibmc_connector_get_modes(struct drm_connector *connector) 21 { 22 return drm_add_modes_noedid(connector, 800, 600); 23 } 24 25 static enum drm_mode_status hibmc_connector_mode_valid(struct drm_connector *connector, 26 struct drm_display_mode *mode) 27 { 28 return MODE_OK; 29 } 30 31 static const struct drm_connector_helper_funcs 32 hibmc_connector_helper_funcs = { 33 .get_modes = hibmc_connector_get_modes, 34 .mode_valid = hibmc_connector_mode_valid, 35 }; 36 37 static const struct drm_connector_funcs hibmc_connector_funcs = { 38 .fill_modes = drm_helper_probe_single_connector_modes, 39 .destroy = drm_connector_cleanup, 40 .reset = drm_atomic_helper_connector_reset, 41 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 42 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 43 }; 44 45 static struct drm_connector * 46 hibmc_connector_init(struct hibmc_drm_private *priv) 47 { 48 struct drm_device *dev = priv->dev; 49 struct drm_connector *connector; 50 int ret; 51 52 connector = devm_kzalloc(dev->dev, sizeof(*connector), GFP_KERNEL); 53 if (!connector) { 54 DRM_ERROR("failed to alloc memory when init connector\n"); 55 return ERR_PTR(-ENOMEM); 56 } 57 58 ret = drm_connector_init(dev, connector, 59 &hibmc_connector_funcs, 60 DRM_MODE_CONNECTOR_VGA); 61 if (ret) { 62 DRM_ERROR("failed to init connector: %d\n", ret); 63 return ERR_PTR(ret); 64 } 65 drm_connector_helper_add(connector, 66 &hibmc_connector_helper_funcs); 67 68 return connector; 69 } 70 71 static void hibmc_encoder_mode_set(struct drm_encoder *encoder, 72 struct drm_display_mode *mode, 73 struct drm_display_mode *adj_mode) 74 { 75 u32 reg; 76 struct drm_device *dev = encoder->dev; 77 struct hibmc_drm_private *priv = dev->dev_private; 78 79 reg = readl(priv->mmio + HIBMC_DISPLAY_CONTROL_HISILE); 80 reg |= HIBMC_DISPLAY_CONTROL_FPVDDEN(1); 81 reg |= HIBMC_DISPLAY_CONTROL_PANELDATE(1); 82 reg |= HIBMC_DISPLAY_CONTROL_FPEN(1); 83 reg |= HIBMC_DISPLAY_CONTROL_VBIASEN(1); 84 writel(reg, priv->mmio + HIBMC_DISPLAY_CONTROL_HISILE); 85 } 86 87 static const struct drm_encoder_helper_funcs hibmc_encoder_helper_funcs = { 88 .mode_set = hibmc_encoder_mode_set, 89 }; 90 91 static const struct drm_encoder_funcs hibmc_encoder_funcs = { 92 .destroy = drm_encoder_cleanup, 93 }; 94 95 int hibmc_vdac_init(struct hibmc_drm_private *priv) 96 { 97 struct drm_device *dev = priv->dev; 98 struct drm_encoder *encoder; 99 struct drm_connector *connector; 100 int ret; 101 102 connector = hibmc_connector_init(priv); 103 if (IS_ERR(connector)) { 104 DRM_ERROR("failed to create connector: %ld\n", 105 PTR_ERR(connector)); 106 return PTR_ERR(connector); 107 } 108 109 encoder = devm_kzalloc(dev->dev, sizeof(*encoder), GFP_KERNEL); 110 if (!encoder) { 111 DRM_ERROR("failed to alloc memory when init encoder\n"); 112 return -ENOMEM; 113 } 114 115 encoder->possible_crtcs = 0x1; 116 ret = drm_encoder_init(dev, encoder, &hibmc_encoder_funcs, 117 DRM_MODE_ENCODER_DAC, NULL); 118 if (ret) { 119 DRM_ERROR("failed to init encoder: %d\n", ret); 120 return ret; 121 } 122 123 drm_encoder_helper_add(encoder, &hibmc_encoder_helper_funcs); 124 drm_connector_attach_encoder(connector, encoder); 125 126 return 0; 127 } 128