linux/drivers/gpu/drm/i915/display/intel_dsi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: MIT
   2/*
   3 * Copyright © 2018 Intel Corporation
   4 */
   5
   6#include <drm/drm_mipi_dsi.h>
   7
   8#include "i915_drv.h"
   9#include "intel_dsi.h"
  10#include "intel_panel.h"
  11
  12int intel_dsi_bitrate(const struct intel_dsi *intel_dsi)
  13{
  14        int bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
  15
  16        if (WARN_ON(bpp < 0))
  17                bpp = 16;
  18
  19        return intel_dsi->pclk * bpp / intel_dsi->lane_count;
  20}
  21
  22int intel_dsi_tlpx_ns(const struct intel_dsi *intel_dsi)
  23{
  24        switch (intel_dsi->escape_clk_div) {
  25        default:
  26        case 0:
  27                return 50;
  28        case 1:
  29                return 100;
  30        case 2:
  31                return 200;
  32        }
  33}
  34
  35int intel_dsi_get_modes(struct drm_connector *connector)
  36{
  37        struct drm_i915_private *i915 = to_i915(connector->dev);
  38        struct intel_connector *intel_connector = to_intel_connector(connector);
  39        struct drm_display_mode *mode;
  40
  41        drm_dbg_kms(&i915->drm, "\n");
  42
  43        if (!intel_connector->panel.fixed_mode) {
  44                drm_dbg_kms(&i915->drm, "no fixed mode\n");
  45                return 0;
  46        }
  47
  48        mode = drm_mode_duplicate(connector->dev,
  49                                  intel_connector->panel.fixed_mode);
  50        if (!mode) {
  51                drm_dbg_kms(&i915->drm, "drm_mode_duplicate failed\n");
  52                return 0;
  53        }
  54
  55        drm_mode_probed_add(connector, mode);
  56        return 1;
  57}
  58
  59enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector,
  60                                          struct drm_display_mode *mode)
  61{
  62        struct drm_i915_private *dev_priv = to_i915(connector->dev);
  63        struct intel_connector *intel_connector = to_intel_connector(connector);
  64        const struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
  65        int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
  66        enum drm_mode_status status;
  67
  68        drm_dbg_kms(&dev_priv->drm, "\n");
  69
  70        if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
  71                return MODE_NO_DBLESCAN;
  72
  73        status = intel_panel_mode_valid(intel_connector, mode);
  74        if (status != MODE_OK)
  75                return status;
  76
  77        if (fixed_mode->clock > max_dotclk)
  78                return MODE_CLOCK_HIGH;
  79
  80        return intel_mode_valid_max_plane_size(dev_priv, mode, false);
  81}
  82
  83struct intel_dsi_host *intel_dsi_host_init(struct intel_dsi *intel_dsi,
  84                                           const struct mipi_dsi_host_ops *funcs,
  85                                           enum port port)
  86{
  87        struct intel_dsi_host *host;
  88        struct mipi_dsi_device *device;
  89
  90        host = kzalloc(sizeof(*host), GFP_KERNEL);
  91        if (!host)
  92                return NULL;
  93
  94        host->base.ops = funcs;
  95        host->intel_dsi = intel_dsi;
  96        host->port = port;
  97
  98        /*
  99         * We should call mipi_dsi_host_register(&host->base) here, but we don't
 100         * have a host->dev, and we don't have OF stuff either. So just use the
 101         * dsi framework as a library and hope for the best. Create the dsi
 102         * devices by ourselves here too. Need to be careful though, because we
 103         * don't initialize any of the driver model devices here.
 104         */
 105        device = kzalloc(sizeof(*device), GFP_KERNEL);
 106        if (!device) {
 107                kfree(host);
 108                return NULL;
 109        }
 110
 111        device->host = &host->base;
 112        host->device = device;
 113
 114        return host;
 115}
 116
 117enum drm_panel_orientation
 118intel_dsi_get_panel_orientation(struct intel_connector *connector)
 119{
 120        struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 121        enum drm_panel_orientation orientation;
 122
 123        orientation = dev_priv->vbt.dsi.orientation;
 124        if (orientation != DRM_MODE_PANEL_ORIENTATION_UNKNOWN)
 125                return orientation;
 126
 127        orientation = dev_priv->vbt.orientation;
 128        if (orientation != DRM_MODE_PANEL_ORIENTATION_UNKNOWN)
 129                return orientation;
 130
 131        return DRM_MODE_PANEL_ORIENTATION_NORMAL;
 132}
 133