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