Move the panel specific VBT parsing to happen during the output probing stage. Needs to be done because the VBT parsing will need to look at the EDID to determine the correct panel_type on some machines. We split the parsed VBT data (i915->vbt) along the same boundary. For the moment we just hoist all the panel specific stuff into connector->panel.vbt since that seems like the most convenient place for eg. the backlight code. Note that we simply drop the drrs type check from intel_drrs_frontbuffer_update() since that operates on the whole device rather than a specific connector/encoder. But the check was just a micro optimization so removing it doesn't actually mattter for correctness. TODO: Lot's of cleanup to be done in the future. Eg. most of the DSI stuff could probably be eliminated entirely and just parsed on demand during DSI init. v2: Note the intel_drrs_frontbuffer_update() change Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220510104242.6099-13-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula <jani.nikula@intel.com>
114 lines
2.8 KiB
C
114 lines
2.8 KiB
C
// SPDX-License-Identifier: MIT
|
|
/*
|
|
* Copyright © 2018 Intel Corporation
|
|
*/
|
|
|
|
#include <drm/drm_mipi_dsi.h>
|
|
|
|
#include "i915_drv.h"
|
|
#include "intel_dsi.h"
|
|
#include "intel_panel.h"
|
|
|
|
int intel_dsi_bitrate(const struct intel_dsi *intel_dsi)
|
|
{
|
|
int bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
|
|
|
|
if (WARN_ON(bpp < 0))
|
|
bpp = 16;
|
|
|
|
return intel_dsi->pclk * bpp / intel_dsi->lane_count;
|
|
}
|
|
|
|
int intel_dsi_tlpx_ns(const struct intel_dsi *intel_dsi)
|
|
{
|
|
switch (intel_dsi->escape_clk_div) {
|
|
default:
|
|
case 0:
|
|
return 50;
|
|
case 1:
|
|
return 100;
|
|
case 2:
|
|
return 200;
|
|
}
|
|
}
|
|
|
|
int intel_dsi_get_modes(struct drm_connector *connector)
|
|
{
|
|
return intel_panel_get_modes(to_intel_connector(connector));
|
|
}
|
|
|
|
enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector,
|
|
struct drm_display_mode *mode)
|
|
{
|
|
struct drm_i915_private *dev_priv = to_i915(connector->dev);
|
|
struct intel_connector *intel_connector = to_intel_connector(connector);
|
|
const struct drm_display_mode *fixed_mode =
|
|
intel_panel_fixed_mode(intel_connector, mode);
|
|
int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
|
|
enum drm_mode_status status;
|
|
|
|
drm_dbg_kms(&dev_priv->drm, "\n");
|
|
|
|
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
|
return MODE_NO_DBLESCAN;
|
|
|
|
status = intel_panel_mode_valid(intel_connector, mode);
|
|
if (status != MODE_OK)
|
|
return status;
|
|
|
|
if (fixed_mode->clock > max_dotclk)
|
|
return MODE_CLOCK_HIGH;
|
|
|
|
return intel_mode_valid_max_plane_size(dev_priv, mode, false);
|
|
}
|
|
|
|
struct intel_dsi_host *intel_dsi_host_init(struct intel_dsi *intel_dsi,
|
|
const struct mipi_dsi_host_ops *funcs,
|
|
enum port port)
|
|
{
|
|
struct intel_dsi_host *host;
|
|
struct mipi_dsi_device *device;
|
|
|
|
host = kzalloc(sizeof(*host), GFP_KERNEL);
|
|
if (!host)
|
|
return NULL;
|
|
|
|
host->base.ops = funcs;
|
|
host->intel_dsi = intel_dsi;
|
|
host->port = port;
|
|
|
|
/*
|
|
* We should call mipi_dsi_host_register(&host->base) here, but we don't
|
|
* have a host->dev, and we don't have OF stuff either. So just use the
|
|
* dsi framework as a library and hope for the best. Create the dsi
|
|
* devices by ourselves here too. Need to be careful though, because we
|
|
* don't initialize any of the driver model devices here.
|
|
*/
|
|
device = kzalloc(sizeof(*device), GFP_KERNEL);
|
|
if (!device) {
|
|
kfree(host);
|
|
return NULL;
|
|
}
|
|
|
|
device->host = &host->base;
|
|
host->device = device;
|
|
|
|
return host;
|
|
}
|
|
|
|
enum drm_panel_orientation
|
|
intel_dsi_get_panel_orientation(struct intel_connector *connector)
|
|
{
|
|
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
|
enum drm_panel_orientation orientation;
|
|
|
|
orientation = connector->panel.vbt.dsi.orientation;
|
|
if (orientation != DRM_MODE_PANEL_ORIENTATION_UNKNOWN)
|
|
return orientation;
|
|
|
|
orientation = dev_priv->vbt.orientation;
|
|
if (orientation != DRM_MODE_PANEL_ORIENTATION_UNKNOWN)
|
|
return orientation;
|
|
|
|
return DRM_MODE_PANEL_ORIENTATION_NORMAL;
|
|
}
|