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
hibmc_connector_get_modes(struct drm_connector * connector)21 static int hibmc_connector_get_modes(struct drm_connector *connector)
22 {
23 int count;
24
25 count = drm_add_modes_noedid(connector,
26 connector->dev->mode_config.max_width,
27 connector->dev->mode_config.max_height);
28 drm_set_preferred_mode(connector, 1024, 768);
29
30 return count;
31 }
32
hibmc_connector_mode_valid(struct drm_connector * connector,struct drm_display_mode * mode)33 static enum drm_mode_status hibmc_connector_mode_valid(struct drm_connector *connector,
34 struct drm_display_mode *mode)
35 {
36 return MODE_OK;
37 }
38
39 static const struct drm_connector_helper_funcs
40 hibmc_connector_helper_funcs = {
41 .get_modes = hibmc_connector_get_modes,
42 .mode_valid = hibmc_connector_mode_valid,
43 };
44
45 static const struct drm_connector_funcs hibmc_connector_funcs = {
46 .fill_modes = drm_helper_probe_single_connector_modes,
47 .destroy = drm_connector_cleanup,
48 .reset = drm_atomic_helper_connector_reset,
49 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
50 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
51 };
52
hibmc_encoder_mode_set(struct drm_encoder * encoder,struct drm_display_mode * mode,struct drm_display_mode * adj_mode)53 static void hibmc_encoder_mode_set(struct drm_encoder *encoder,
54 struct drm_display_mode *mode,
55 struct drm_display_mode *adj_mode)
56 {
57 u32 reg;
58 struct drm_device *dev = encoder->dev;
59 struct hibmc_drm_private *priv = dev->dev_private;
60
61 reg = readl(priv->mmio + HIBMC_DISPLAY_CONTROL_HISILE);
62 reg |= HIBMC_DISPLAY_CONTROL_FPVDDEN(1);
63 reg |= HIBMC_DISPLAY_CONTROL_PANELDATE(1);
64 reg |= HIBMC_DISPLAY_CONTROL_FPEN(1);
65 reg |= HIBMC_DISPLAY_CONTROL_VBIASEN(1);
66 writel(reg, priv->mmio + HIBMC_DISPLAY_CONTROL_HISILE);
67 }
68
69 static const struct drm_encoder_helper_funcs hibmc_encoder_helper_funcs = {
70 .mode_set = hibmc_encoder_mode_set,
71 };
72
73 static const struct drm_encoder_funcs hibmc_encoder_funcs = {
74 .destroy = drm_encoder_cleanup,
75 };
76
hibmc_vdac_init(struct hibmc_drm_private * priv)77 int hibmc_vdac_init(struct hibmc_drm_private *priv)
78 {
79 struct drm_device *dev = priv->dev;
80 struct drm_encoder *encoder = &priv->encoder;
81 struct drm_connector *connector = &priv->connector;
82 int ret;
83
84 encoder->possible_crtcs = 0x1;
85 ret = drm_encoder_init(dev, encoder, &hibmc_encoder_funcs,
86 DRM_MODE_ENCODER_DAC, NULL);
87 if (ret) {
88 drm_err(dev, "failed to init encoder: %d\n", ret);
89 return ret;
90 }
91
92 drm_encoder_helper_add(encoder, &hibmc_encoder_helper_funcs);
93
94 ret = drm_connector_init(dev, connector, &hibmc_connector_funcs,
95 DRM_MODE_CONNECTOR_VGA);
96 if (ret) {
97 drm_err(dev, "failed to init connector: %d\n", ret);
98 return ret;
99 }
100 drm_connector_helper_add(connector, &hibmc_connector_helper_funcs);
101
102 drm_connector_attach_encoder(connector, encoder);
103
104 return 0;
105 }
106