File Index
Files and directories
Sign in
FILE

hibmc_drm_vdac.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c C
  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 <linux/io.h>
 15
 16#include <drm/drm_atomic_helper.h>
 17#include <drm/drm_edid.h>
 18#include <drm/drm_probe_helper.h>
 19#include <drm/drm_print.h>
 20#include <drm/drm_simple_kms_helper.h>
 21
 22#include "hibmc_drm_drv.h"
 23#include "hibmc_drm_regs.h"
 24
 25static int hibmc_connector_get_modes(struct drm_connector *connector)
 26{
 27	struct hibmc_vdac *vdac = to_hibmc_vdac(connector);
 28	const struct drm_edid *drm_edid;
 29	int count;
 30
 31	drm_edid = drm_edid_read_ddc(connector, &vdac->adapter);
 32
 33	drm_edid_connector_update(connector, drm_edid);
 34
 35	if (drm_edid) {
 36		count = drm_edid_connector_add_modes(connector);
 37		if (count)
 38			goto out;
 39	}
 40
 41	count = drm_add_modes_noedid(connector,
 42				     connector->dev->mode_config.max_width,
 43				     connector->dev->mode_config.max_height);
 44	drm_set_preferred_mode(connector, 1024, 768);
 45
 46out:
 47	drm_edid_free(drm_edid);
 48
 49	return count;
 50}
 51
 52static void hibmc_connector_destroy(struct drm_connector *connector)
 53{
 54	struct hibmc_vdac *vdac = to_hibmc_vdac(connector);
 55
 56	hibmc_ddc_del(vdac);
 57	drm_connector_cleanup(connector);
 58}
 59
 60static const struct drm_connector_helper_funcs
 61	hibmc_connector_helper_funcs = {
 62	.get_modes = hibmc_connector_get_modes,
 63	.detect_ctx = drm_connector_helper_detect_from_ddc,
 64};
 65
 66static const struct drm_connector_funcs hibmc_connector_funcs = {
 67	.fill_modes = drm_helper_probe_single_connector_modes,
 68	.destroy = hibmc_connector_destroy,
 69	.reset = drm_atomic_helper_connector_reset,
 70	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
 71	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 72};
 73
 74static void hibmc_encoder_mode_set(struct drm_encoder *encoder,
 75				   struct drm_display_mode *mode,
 76				   struct drm_display_mode *adj_mode)
 77{
 78	u32 reg;
 79	struct drm_device *dev = encoder->dev;
 80	struct hibmc_drm_private *priv = to_hibmc_drm_private(dev);
 81
 82	reg = readl(priv->mmio + HIBMC_DISPLAY_CONTROL_HISILE);
 83	reg |= HIBMC_DISPLAY_CONTROL_FPVDDEN(1);
 84	reg |= HIBMC_DISPLAY_CONTROL_PANELDATE(1);
 85	reg |= HIBMC_DISPLAY_CONTROL_FPEN(1);
 86	reg |= HIBMC_DISPLAY_CONTROL_VBIASEN(1);
 87	writel(reg, priv->mmio + HIBMC_DISPLAY_CONTROL_HISILE);
 88}
 89
 90static const struct drm_encoder_helper_funcs hibmc_encoder_helper_funcs = {
 91	.mode_set = hibmc_encoder_mode_set,
 92};
 93
 94int hibmc_vdac_init(struct hibmc_drm_private *priv)
 95{
 96	struct drm_device *dev = &priv->dev;
 97	struct hibmc_vdac *vdac = &priv->vdac;
 98	struct drm_encoder *encoder = &vdac->encoder;
 99	struct drm_crtc *crtc = &priv->crtc;
100	struct drm_connector *connector = &vdac->connector;
101	int ret;
102
103	ret = hibmc_ddc_create(dev, vdac);
104	if (ret) {
105		drm_err(dev, "failed to create ddc: %d\n", ret);
106		return ret;
107	}
108
109	encoder->possible_crtcs = drm_crtc_mask(crtc);
110	ret = drmm_encoder_init(dev, encoder, NULL, DRM_MODE_ENCODER_DAC, NULL);
111	if (ret) {
112		drm_err(dev, "failed to init encoder: %d\n", ret);
113		goto err;
114	}
115
116	drm_encoder_helper_add(encoder, &hibmc_encoder_helper_funcs);
117
118	ret = drm_connector_init_with_ddc(dev, connector,
119					  &hibmc_connector_funcs,
120					  DRM_MODE_CONNECTOR_VGA,
121					  &vdac->adapter);
122	if (ret) {
123		drm_err(dev, "failed to init connector: %d\n", ret);
124		goto err;
125	}
126
127	drm_connector_helper_add(connector, &hibmc_connector_helper_funcs);
128
129	drm_connector_attach_encoder(connector, encoder);
130
131	connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
132
133	return 0;
134
135err:
136	hibmc_ddc_del(vdac);
137
138	return ret;
139}
~/ Read-only file preview.