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