Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d62b1c14 authored by Camus Wong's avatar Camus Wong
Browse files

drm/msm: Early DRM Driver



Add new DRM node to handle early display service. The early DRM
driver is to workaround Andriod display framework long boot time
problem and DRM single master limitation.  The early DRM node provides
display function for early application that is outside Android
framework.  The early application can use early DRM to draw early
UI and bootloader review camera menu function. Android framework will
not use early DRM node.  It will continue to use the main DRM node.

Early DRM is another KMS driver that designed for bootup application.
Early DRM is not based on SDE framework and it will not initialize
display hardware.  Early DRM rely on bootloader to initialize display
hardware and interfaces.  For power and SMMU, early DRM relies on main
DRM to initialize them.  Early DRM only provide limited display
functionality such as RGB buffer display.  Early DRM only expected to
run during bootup time to work with bootloader/early RVC.  When Android
UI is ready, early DRM will handoff all display resource to main DRM.
After that, no application can open early DRM node.

Early DRM is enabled in device tree.  User must specify which display
to enable early DRM and which display pipes are assigned to eDRM.

Change-Id: Ic9f68726677c5db26507caec79c7da1e6d745f44
Signed-off-by: default avatarCamus Wong <camusw@codeaurora.org>
parent 66843b30
Loading
Loading
Loading
Loading
+57 −0
Original line number Diff line number Diff line
Qualcomm Technologies, Inc. EDRM KMS

EDRM KMS implements Linux DRM/KMS APIs to drive early user interface to
different panel interfaces. EDRM driver provides early service to display
subsystem which manage a subset data paths to specific panel interfaces.
EDRM is expected to provide display service to fill in the gap between
bootloader and main application UI.  Only early application is expected to
use EDRM.  EDRM will be terminated when main application UI is ready.

Required properties
- compatible: Must be "qcom,msm-kms-edrm"

Assigned Display Subnodes:
- qcom,edrm-assigned-display:	List of display that eDRM can use.

Subnode properties:
- qcom,edrm-display-id@x:	a node that contains the display information

- qcom,label:	The string that indicate the label of the display.  The
			label should match with the label used in sde_display.
			For example, SDE display dtsi may defined:
				dsi_adv_7533_2: qcom,dsi-display@8 {...}

			If eDRM wants to use that display, it should set the
			label as:
				qcom,label = "dsi_adv_7533_1";

- qcom,intf-type:  a string that indicate the interface type.  Right now
				it can be "dsi" or "hdmi"

- qcom,assigned_plane :	List of plane that assigned for this display.
				There must be at least one plane in this field.
				The plane that is in this field must also be
				defined in qcom,sde-reserved-plane under sde_kms
				For example, SDE may contains the following
				reserved plane:
				&sde_kms {
					qcom,sde-reserved-plane {
					reserved_plane1: qcom,sde-reserved-plane@1 {
					reg = <0x1>;
					qcom,plane-name = "rgb3";
					lm-stage = <5>;
				}
				Then assigned_plane field can reference to the
				reserved plane like:
				qcom,assigned_plane = <&reserved_plane1>;

Example:
	msm_kms_edrm: qcom,msm_kms_edrm@900000 {
		qcom,edrm-assigned-display {
			qcom,edrm-display-id@0 {
				qcom,label = "dsi_adv_7533_1";
				qcom,intf-type = "dsi";
				qcom,assigned_plane = <&reserved_plane1>;
			}
		}
	}
+10 −0
Original line number Diff line number Diff line
@@ -28,6 +28,16 @@ config DRM_MSM_REGISTER_LOGGING
	  that can be parsed by envytools demsm tool.  If enabled, register
	  logging can be switched on via msm.reglog=y module param.

config DRM_MSM_EARLY_CARD
	bool "Enable Early DRM in MSM DRM driver"
	depends on DRM_MSM
	default y
	help
	  Choose this option if one wants to enable Early DRM driver
	  for MSM/snapdragon.  Early DRM will create one DRI card to
	  support early application.  One should also check device tree
	  to assign proper display resources to early DRM

config DRM_MSM_DSI
	bool "Enable DSI support in MSM DRM driver"
	depends on DRM_MSM
+9 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@ ccflags-$(CONFIG_DRM_MSM_DSI) += -Idrivers/gpu/drm/msm/dsi
ccflags-$(CONFIG_SYNC) += -Idrivers/staging/android
ccflags-$(CONFIG_DRM_MSM_DSI_PLL) += -Idrivers/gpu/drm/msm/dsi
ccflags-y += -Idrivers/gpu/drm/msm/sde
ccflags-$(CONFIG_DRM_MSM_EARLY_CARD) += -Idrivers/gpu/drm/msm/ekms

msm_drm-y := \
	hdmi/hdmi.o \
@@ -57,6 +58,14 @@ msm_drm-y := \
	sde_edid_parser.o \
	sde_hdcp_1x.o

msm_drm-$(CONFIG_DRM_MSM_EARLY_CARD) += ekms/edrm_kms.o \
	ekms/edrm_plane.o \
	ekms/edrm_encoder.o \
	ekms/edrm_connector.o \
	ekms/edrm_crtc.o \
	ekms/edrm_drv.o \
	ekms/edrm_splash.o

# use drm gpu driver only if qcom_kgsl driver not available
ifneq ($(CONFIG_QCOM_KGSL),y)
msm_drm-y += adreno/adreno_device.o \
+123 −0
Original line number Diff line number Diff line
/* Copyright (c) 2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include "edrm_connector.h"

struct edrm_connector {
	struct drm_connector base;
	struct drm_encoder *encoder;
	struct msm_edrm_display *display;
};

#define to_edrm_connector(x) container_of(x, struct edrm_connector, base)

static enum drm_connector_status
edrm_connector_detect(struct drm_connector *conn, bool force)
{
	return connector_status_connected;
}

static int
edrm_connector_get_modes(struct drm_connector *connector)
{
	struct edrm_connector *edrm_conn = to_edrm_connector(connector);
	struct drm_display_mode *m;

	m = drm_mode_duplicate(connector->dev, &edrm_conn->display->mode);
	drm_mode_set_name(m);
	drm_mode_probed_add(connector, m);

	return 1;
}

static enum drm_mode_status
edrm_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode)
{
	return MODE_OK;
}

static struct drm_encoder *
edrm_connector_best_encoder(struct drm_connector *connector)
{
	struct edrm_connector *edrm_conn = to_edrm_connector(connector);

	return edrm_conn->encoder;
}

void edrm_connector_destroy(struct drm_connector *connector)
{
	struct edrm_connector *edrm_conn = to_edrm_connector(connector);

	drm_connector_unregister(connector);
	drm_connector_cleanup(connector);
	kfree(edrm_conn);
}

static const struct drm_connector_helper_funcs edrm_connector_helper_funcs = {
	.get_modes =    edrm_connector_get_modes,
	.mode_valid =   edrm_mode_valid,
	.best_encoder = edrm_connector_best_encoder,
};

static const struct drm_connector_funcs edrm_connector_funcs = {
	.fill_modes = drm_helper_probe_single_connector_modes,
	.detect = edrm_connector_detect,
	.destroy = edrm_connector_destroy,
	.reset = drm_atomic_helper_connector_reset,
	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};

struct drm_connector *edrm_connector_init(struct drm_device *dev,
			struct drm_encoder *encoder,
			struct msm_edrm_display *display)
{
	struct edrm_connector *edrm_conn;
	struct drm_connector *connector;
	int ret;

	edrm_conn = kzalloc(sizeof(*edrm_conn), GFP_KERNEL);
	if (!edrm_conn)
		return ERR_PTR(-ENOMEM);
	connector = &edrm_conn->base;

	ret = drm_connector_init(dev, connector,
			&edrm_connector_funcs,
			display->connector_type);
	if (ret) {
		pr_err("edrm drm_connector_init failed\n");
		goto fail;
	}

	drm_connector_helper_add(connector, &edrm_connector_helper_funcs);

	edrm_conn->display = display;
	edrm_conn->encoder = encoder;

	ret = drm_connector_register(&edrm_conn->base);
	if (ret) {
		pr_err("failed to register drm connector, %d\n", ret);
		goto fail;
	}

	ret = drm_mode_connector_attach_encoder(&edrm_conn->base, encoder);
	if (ret) {
		pr_err("failed to attach encoder to connector, %d\n", ret);
		goto fail;
	}

	return connector;
fail:
	kfree(edrm_conn);
	return ERR_PTR(ret);

}
+28 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#ifndef _EDRM_CONNECTOR_H_
#define _EDRM_CONNECTOR_H_

#include <drm/drmP.h>
#include <drm/drm_crtc.h>
#include "edrm_kms.h"

struct drm_connector *edrm_connector_init(struct drm_device *dev,
			struct drm_encoder *encoder,
			struct msm_edrm_display *display);

void edrm_connector_destroy(struct drm_connector *connector);

#endif /* _EDRM_CONNECTOR_H_ */
Loading