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