drm/i915/icl: Allocate DSI encoder/connector
This patch allocates memory for DSI encoder and connector which will be used for various DSI encoder/connector operations and attaching the same to DRM subsystem. This patch also extracts DSI modes info from VBT and save the desired mode info to connector. v2 by Jani: - Drop GEN11 prefix from encoder name - Drop extra parenthesis - Drop extra local variable - Squash encoder power domain here v3 by Jani: - Squash connector and connector helper functions here - Move intel_dsi_vbt_init call here Signed-off-by: Madhav Chauhan <madhav.chauhan@intel.com> Signed-off-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/0197023b92ffa2d59064e30fd4ca22b6a4cff16c.1543500286.git.jani.nikula@intel.com
This commit is contained in:
parent
70a057b7d4
commit
e275804873
|
@ -26,6 +26,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <drm/drm_mipi_dsi.h>
|
#include <drm/drm_mipi_dsi.h>
|
||||||
|
#include <drm/drm_atomic_helper.h>
|
||||||
#include "intel_dsi.h"
|
#include "intel_dsi.h"
|
||||||
|
|
||||||
static inline int header_credits_available(struct drm_i915_private *dev_priv,
|
static inline int header_credits_available(struct drm_i915_private *dev_priv,
|
||||||
|
@ -799,10 +800,9 @@ static void gen11_dsi_powerup_panel(struct intel_encoder *encoder)
|
||||||
wait_for_cmds_dispatched_to_panel(encoder);
|
wait_for_cmds_dispatched_to_panel(encoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __attribute__((unused))
|
static void gen11_dsi_pre_enable(struct intel_encoder *encoder,
|
||||||
gen11_dsi_pre_enable(struct intel_encoder *encoder,
|
const struct intel_crtc_state *pipe_config,
|
||||||
const struct intel_crtc_state *pipe_config,
|
const struct drm_connector_state *conn_state)
|
||||||
const struct drm_connector_state *conn_state)
|
|
||||||
{
|
{
|
||||||
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
|
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
|
||||||
|
|
||||||
|
@ -945,10 +945,9 @@ static void gen11_dsi_disable_io_power(struct intel_encoder *encoder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __attribute__((unused)) gen11_dsi_disable(
|
static void gen11_dsi_disable(struct intel_encoder *encoder,
|
||||||
struct intel_encoder *encoder,
|
const struct intel_crtc_state *old_crtc_state,
|
||||||
const struct intel_crtc_state *old_crtc_state,
|
const struct drm_connector_state *old_conn_state)
|
||||||
const struct drm_connector_state *old_conn_state)
|
|
||||||
{
|
{
|
||||||
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
|
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
|
||||||
|
|
||||||
|
@ -972,10 +971,112 @@ static void __attribute__((unused)) gen11_dsi_disable(
|
||||||
gen11_dsi_disable_io_power(encoder);
|
gen11_dsi_disable_io_power(encoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void gen11_dsi_encoder_destroy(struct drm_encoder *encoder)
|
||||||
|
{
|
||||||
|
intel_encoder_destroy(encoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct drm_encoder_funcs gen11_dsi_encoder_funcs = {
|
||||||
|
.destroy = gen11_dsi_encoder_destroy,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct drm_connector_funcs gen11_dsi_connector_funcs = {
|
||||||
|
.late_register = intel_connector_register,
|
||||||
|
.early_unregister = intel_connector_unregister,
|
||||||
|
.destroy = intel_connector_destroy,
|
||||||
|
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||||
|
.atomic_get_property = intel_digital_connector_atomic_get_property,
|
||||||
|
.atomic_set_property = intel_digital_connector_atomic_set_property,
|
||||||
|
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||||
|
.atomic_duplicate_state = intel_digital_connector_duplicate_state,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct drm_connector_helper_funcs gen11_dsi_connector_helper_funcs = {
|
||||||
|
.get_modes = intel_dsi_get_modes,
|
||||||
|
.mode_valid = intel_dsi_mode_valid,
|
||||||
|
.atomic_check = intel_digital_connector_atomic_check,
|
||||||
|
};
|
||||||
|
|
||||||
void icl_dsi_init(struct drm_i915_private *dev_priv)
|
void icl_dsi_init(struct drm_i915_private *dev_priv)
|
||||||
{
|
{
|
||||||
|
struct drm_device *dev = &dev_priv->drm;
|
||||||
|
struct intel_dsi *intel_dsi;
|
||||||
|
struct intel_encoder *encoder;
|
||||||
|
struct intel_connector *intel_connector;
|
||||||
|
struct drm_connector *connector;
|
||||||
|
struct drm_display_mode *scan, *fixed_mode = NULL;
|
||||||
enum port port;
|
enum port port;
|
||||||
|
|
||||||
if (!intel_bios_is_dsi_present(dev_priv, &port))
|
if (!intel_bios_is_dsi_present(dev_priv, &port))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
intel_dsi = kzalloc(sizeof(*intel_dsi), GFP_KERNEL);
|
||||||
|
if (!intel_dsi)
|
||||||
|
return;
|
||||||
|
|
||||||
|
intel_connector = intel_connector_alloc();
|
||||||
|
if (!intel_connector) {
|
||||||
|
kfree(intel_dsi);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
encoder = &intel_dsi->base;
|
||||||
|
intel_dsi->attached_connector = intel_connector;
|
||||||
|
connector = &intel_connector->base;
|
||||||
|
|
||||||
|
/* register DSI encoder with DRM subsystem */
|
||||||
|
drm_encoder_init(dev, &encoder->base, &gen11_dsi_encoder_funcs,
|
||||||
|
DRM_MODE_ENCODER_DSI, "DSI %c", port_name(port));
|
||||||
|
|
||||||
|
encoder->pre_enable = gen11_dsi_pre_enable;
|
||||||
|
encoder->disable = gen11_dsi_disable;
|
||||||
|
encoder->port = port;
|
||||||
|
encoder->type = INTEL_OUTPUT_DSI;
|
||||||
|
encoder->cloneable = 0;
|
||||||
|
encoder->crtc_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C);
|
||||||
|
encoder->power_domain = POWER_DOMAIN_PORT_DSI;
|
||||||
|
|
||||||
|
/* register DSI connector with DRM subsystem */
|
||||||
|
drm_connector_init(dev, connector, &gen11_dsi_connector_funcs,
|
||||||
|
DRM_MODE_CONNECTOR_DSI);
|
||||||
|
drm_connector_helper_add(connector, &gen11_dsi_connector_helper_funcs);
|
||||||
|
connector->display_info.subpixel_order = SubPixelHorizontalRGB;
|
||||||
|
connector->interlace_allowed = false;
|
||||||
|
connector->doublescan_allowed = false;
|
||||||
|
|
||||||
|
/* attach connector to encoder */
|
||||||
|
intel_connector_attach_encoder(intel_connector, encoder);
|
||||||
|
|
||||||
|
/* fill mode info from VBT */
|
||||||
|
mutex_lock(&dev->mode_config.mutex);
|
||||||
|
intel_dsi_vbt_get_modes(intel_dsi);
|
||||||
|
list_for_each_entry(scan, &connector->probed_modes, head) {
|
||||||
|
if (scan->type & DRM_MODE_TYPE_PREFERRED) {
|
||||||
|
fixed_mode = drm_mode_duplicate(dev, scan);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mutex_unlock(&dev->mode_config.mutex);
|
||||||
|
|
||||||
|
if (!fixed_mode) {
|
||||||
|
DRM_ERROR("DSI fixed mode info missing\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
connector->display_info.width_mm = fixed_mode->width_mm;
|
||||||
|
connector->display_info.height_mm = fixed_mode->height_mm;
|
||||||
|
intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
|
||||||
|
intel_panel_setup_backlight(connector, INVALID_PIPE);
|
||||||
|
|
||||||
|
if (!intel_dsi_vbt_init(intel_dsi, MIPI_DSI_GENERIC_PANEL_ID)) {
|
||||||
|
DRM_DEBUG_KMS("no device found\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
err:
|
||||||
|
drm_encoder_cleanup(&encoder->base);
|
||||||
|
kfree(intel_dsi);
|
||||||
|
kfree(intel_connector);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue