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