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 #include <drm/drm_print.h> 17 18 #include "hibmc_drm_drv.h" 19 #include "hibmc_drm_regs.h" 20 21 static int hibmc_connector_get_modes(struct drm_connector *connector) 22 { 23 int count; 24 void *edid; 25 struct hibmc_connector *hibmc_connector = to_hibmc_connector(connector); 26 27 edid = drm_get_edid(connector, &hibmc_connector->adapter); 28 if (edid) { 29 drm_connector_update_edid_property(connector, edid); 30 count = drm_add_edid_modes(connector, edid); 31 if (count) 32 goto out; 33 } 34 35 count = drm_add_modes_noedid(connector, 36 connector->dev->mode_config.max_width, 37 connector->dev->mode_config.max_height); 38 drm_set_preferred_mode(connector, 1024, 768); 39 40 out: 41 kfree(edid); 42 return count; 43 } 44 45 static enum drm_mode_status hibmc_connector_mode_valid(struct drm_connector *connector, 46 struct drm_display_mode *mode) 47 { 48 return MODE_OK; 49 } 50 51 static void hibmc_connector_destroy(struct drm_connector *connector) 52 { 53 struct hibmc_connector *hibmc_connector = to_hibmc_connector(connector); 54 55 i2c_del_adapter(&hibmc_connector->adapter); 56 drm_connector_cleanup(connector); 57 } 58 59 static const struct drm_connector_helper_funcs 60 hibmc_connector_helper_funcs = { 61 .get_modes = hibmc_connector_get_modes, 62 .mode_valid = hibmc_connector_mode_valid, 63 }; 64 65 static const struct drm_connector_funcs hibmc_connector_funcs = { 66 .fill_modes = drm_helper_probe_single_connector_modes, 67 .destroy = hibmc_connector_destroy, 68 .reset = drm_atomic_helper_connector_reset, 69 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 70 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 71 }; 72 73 static void hibmc_encoder_mode_set(struct drm_encoder *encoder, 74 struct drm_display_mode *mode, 75 struct drm_display_mode *adj_mode) 76 { 77 u32 reg; 78 struct drm_device *dev = encoder->dev; 79 struct hibmc_drm_private *priv = to_hibmc_drm_private(dev); 80 81 reg = readl(priv->mmio + HIBMC_DISPLAY_CONTROL_HISILE); 82 reg |= HIBMC_DISPLAY_CONTROL_FPVDDEN(1); 83 reg |= HIBMC_DISPLAY_CONTROL_PANELDATE(1); 84 reg |= HIBMC_DISPLAY_CONTROL_FPEN(1); 85 reg |= HIBMC_DISPLAY_CONTROL_VBIASEN(1); 86 writel(reg, priv->mmio + HIBMC_DISPLAY_CONTROL_HISILE); 87 } 88 89 static const struct drm_encoder_helper_funcs hibmc_encoder_helper_funcs = { 90 .mode_set = hibmc_encoder_mode_set, 91 }; 92 93 static const struct drm_encoder_funcs hibmc_encoder_funcs = { 94 .destroy = drm_encoder_cleanup, 95 }; 96 97 int hibmc_vdac_init(struct hibmc_drm_private *priv) 98 { 99 struct drm_device *dev = priv->dev; 100 struct hibmc_connector *hibmc_connector = &priv->connector; 101 struct drm_encoder *encoder = &priv->encoder; 102 struct drm_connector *connector = &hibmc_connector->base; 103 int ret; 104 105 ret = hibmc_ddc_create(dev, hibmc_connector); 106 if (ret) { 107 drm_err(dev, "failed to create ddc: %d\n", ret); 108 return ret; 109 } 110 111 encoder->possible_crtcs = 0x1; 112 ret = drm_encoder_init(dev, encoder, &hibmc_encoder_funcs, 113 DRM_MODE_ENCODER_DAC, NULL); 114 if (ret) { 115 drm_err(dev, "failed to init encoder: %d\n", ret); 116 return ret; 117 } 118 119 drm_encoder_helper_add(encoder, &hibmc_encoder_helper_funcs); 120 121 ret = drm_connector_init_with_ddc(dev, connector, 122 &hibmc_connector_funcs, 123 DRM_MODE_CONNECTOR_VGA, 124 &hibmc_connector->adapter); 125 if (ret) { 126 drm_err(dev, "failed to init connector: %d\n", ret); 127 return ret; 128 } 129 130 drm_connector_helper_add(connector, &hibmc_connector_helper_funcs); 131 132 drm_connector_attach_encoder(connector, encoder); 133 134 return 0; 135 } 136