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_probe_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 enum drm_mode_status hibmc_connector_mode_valid(struct drm_connector *connector, 31 struct drm_display_mode *mode) 32 { 33 return MODE_OK; 34 } 35 36 static const struct drm_connector_helper_funcs 37 hibmc_connector_helper_funcs = { 38 .get_modes = hibmc_connector_get_modes, 39 .mode_valid = hibmc_connector_mode_valid, 40 }; 41 42 static const struct drm_connector_funcs hibmc_connector_funcs = { 43 .fill_modes = drm_helper_probe_single_connector_modes, 44 .destroy = drm_connector_cleanup, 45 .reset = drm_atomic_helper_connector_reset, 46 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 47 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 48 }; 49 50 static struct drm_connector * 51 hibmc_connector_init(struct hibmc_drm_private *priv) 52 { 53 struct drm_device *dev = priv->dev; 54 struct drm_connector *connector; 55 int ret; 56 57 connector = devm_kzalloc(dev->dev, sizeof(*connector), GFP_KERNEL); 58 if (!connector) { 59 DRM_ERROR("failed to alloc memory when init connector\n"); 60 return ERR_PTR(-ENOMEM); 61 } 62 63 ret = drm_connector_init(dev, connector, 64 &hibmc_connector_funcs, 65 DRM_MODE_CONNECTOR_VGA); 66 if (ret) { 67 DRM_ERROR("failed to init connector: %d\n", ret); 68 return ERR_PTR(ret); 69 } 70 drm_connector_helper_add(connector, 71 &hibmc_connector_helper_funcs); 72 73 return connector; 74 } 75 76 static void hibmc_encoder_mode_set(struct drm_encoder *encoder, 77 struct drm_display_mode *mode, 78 struct drm_display_mode *adj_mode) 79 { 80 u32 reg; 81 struct drm_device *dev = encoder->dev; 82 struct hibmc_drm_private *priv = dev->dev_private; 83 84 reg = readl(priv->mmio + HIBMC_DISPLAY_CONTROL_HISILE); 85 reg |= HIBMC_DISPLAY_CONTROL_FPVDDEN(1); 86 reg |= HIBMC_DISPLAY_CONTROL_PANELDATE(1); 87 reg |= HIBMC_DISPLAY_CONTROL_FPEN(1); 88 reg |= HIBMC_DISPLAY_CONTROL_VBIASEN(1); 89 writel(reg, priv->mmio + HIBMC_DISPLAY_CONTROL_HISILE); 90 } 91 92 static const struct drm_encoder_helper_funcs hibmc_encoder_helper_funcs = { 93 .mode_set = hibmc_encoder_mode_set, 94 }; 95 96 static const struct drm_encoder_funcs hibmc_encoder_funcs = { 97 .destroy = drm_encoder_cleanup, 98 }; 99 100 int hibmc_vdac_init(struct hibmc_drm_private *priv) 101 { 102 struct drm_device *dev = priv->dev; 103 struct drm_encoder *encoder; 104 struct drm_connector *connector; 105 int ret; 106 107 connector = hibmc_connector_init(priv); 108 if (IS_ERR(connector)) { 109 DRM_ERROR("failed to create connector: %ld\n", 110 PTR_ERR(connector)); 111 return PTR_ERR(connector); 112 } 113 114 encoder = devm_kzalloc(dev->dev, sizeof(*encoder), GFP_KERNEL); 115 if (!encoder) { 116 DRM_ERROR("failed to alloc memory when init encoder\n"); 117 return -ENOMEM; 118 } 119 120 encoder->possible_crtcs = 0x1; 121 ret = drm_encoder_init(dev, encoder, &hibmc_encoder_funcs, 122 DRM_MODE_ENCODER_DAC, NULL); 123 if (ret) { 124 DRM_ERROR("failed to init encoder: %d\n", ret); 125 return ret; 126 } 127 128 drm_encoder_helper_add(encoder, &hibmc_encoder_helper_funcs); 129 drm_connector_attach_encoder(connector, encoder); 130 131 return 0; 132 } 133