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

Commit 8c69d384 authored by Kyle Yan's avatar Kyle Yan Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/msm: add display rsc support" into msm-4.9

parents 9ad8c85c 020f7e12
Loading
Loading
Loading
Loading
+72 −0
Original line number Diff line number Diff line
Qualcomm Technologies, Inc. SDE RSC

Snapdragon Display Engine implements display rsc to driver
display core to different modes for power saving

Required properties
- compatible:			Must be "qcom,sde-rsc"
- reg:				Offset and length of the register set for
				the device.
- reg-names:			Names to refer to register sets related
				to this device

Optional properties:
- clocks:			List of phandles for clock device nodes
				needed by the device.
- clock-names:			List of clock names needed by the device.
- vdd-supply:			phandle for vdd regulator device node.
- qcom,sde-rsc-version:		U32 property represents the rsc version. It helps to
				select correct sequence for sde rsc based on version.
- qcom,sde-dram-channels:	U32 property represents the number of channels in the
				Bus memory controller.
- qcom,sde-num-nrt-paths:	U32 property represents the number of non-realtime
				paths in each Bus Scaling Usecase. This value depends on
				number of AXI ports that are dedicated to non-realtime VBIF
				for particular chipset.
				These paths must be defined after rt-paths in
				"qcom,msm-bus,vectors-KBps" vector request.

Bus Scaling Subnodes:
- qcom,sde-data-bus:		Property to provide Bus scaling for data bus access for
				sde blocks.

Bus Scaling Data:
- qcom,msm-bus,name:		String property describing client name.
- qcom,msm-bus,active-only:	Boolean context flag for requests in active or
				dual (active & sleep) contex
- qcom,msm-bus,num-cases:	This is the number of Bus Scaling use cases
				defined in the vectors property.
- qcom,msm-bus,num-paths:	This represents the number of paths in each
				Bus Scaling Usecase.
- qcom,msm-bus,vectors-KBps:	* A series of 4 cell properties, with a format
				of (src, dst, ab, ib) which is defined at
				Documentation/devicetree/bindings/arm/msm/msm_bus.txt
				* Current values of src & dst are defined at
				include/linux/msm-bus-board.h
Example:
	sde_rscc {
		cell-index = <0>;
		compatible = "qcom,sde-rsc";
		reg = <0xaf20000 0x1c44>,
			<0xaf30000 0x3fd4>;
		reg-names = "drv", "wrapper";
		clocks = <&clock_mmss clk_mdss_ahb_clk>,
			<&clock_mmss clk_mdss_axi_clk>;
		clock-names = "iface_clk", "bus_clk";
		vdd-supply = <&gdsc_mdss>;

		qcom,sde-rsc-version = <1>;
		qcom,sde-dram-channels = <2>;
		qcom,sde-num-nrt-paths = <1>;

		qcom,sde-data-bus {
		      qcom,msm-bus,name = "sde_rsc";
		      qcom,msm-bus,active-only;
		      qcom,msm-bus,num-cases = <3>;
		      qcom,msm-bus,num-paths = <2>;
		      qcom,msm-bus,vectors-KBps =
		          <22 512 0 0>, <23 512 0 0>,
		          <22 512 0 6400000>, <23 512 0 6400000>,
		          <22 512 0 6400000>, <23 512 0 6400000>;
		};
	};
+2 −0
Original line number Diff line number Diff line
@@ -51,6 +51,8 @@ msm_drm-y := \
	sde_io_util.o \
	sde/sde_hw_reg_dma_v1_color_proc.o \
	sde/sde_hw_color_proc_v4.o \
	sde_rsc.o \
	sde_rsc_hw.o \

# use drm gpu driver only if qcom_kgsl driver not available
ifneq ($(CONFIG_QCOM_KGSL),y)
+1 −0
Original line number Diff line number Diff line
@@ -2683,6 +2683,7 @@ int dsi_display_get_info(struct msm_display_info *info, void *disp)
		info->h_tile_instance[i] = display->ctrl[i].ctrl->index;

	info->is_connected = true;
	info->is_primary = true;
	info->width_mm = phy_props.panel_width_mm;
	info->height_mm = phy_props.panel_height_mm;
	info->max_width = 1920;
+2 −0
Original line number Diff line number Diff line
@@ -199,6 +199,7 @@ enum msm_display_caps {
 * @h_tile_instance:    Controller instance used per tile. Number of elements is
 *                      based on num_of_h_tiles
 * @is_connected:       Set to true if display is connected
 * @is_primary:         Set to true if display is primary display
 * @width_mm:           Physical width
 * @height_mm:          Physical height
 * @max_width:          Max width of display. In case of hot pluggable display
@@ -215,6 +216,7 @@ struct msm_display_info {
	uint32_t h_tile_instance[MAX_H_TILES_PER_DISPLAY];

	bool is_connected;
	bool is_primary;

	unsigned int width_mm;
	unsigned int height_mm;
+62 −1
Original line number Diff line number Diff line
@@ -32,6 +32,9 @@
#include "sde_formats.h"
#include "sde_encoder_phys.h"
#include "sde_color_processing.h"
#include "sde_rsc.h"

#include "sde_power_handle.h"

#define SDE_DEBUG_ENC(e, fmt, ...) SDE_DEBUG("enc%d " fmt,\
		(e) ? (e)->base.base.id : -1, ##__VA_ARGS__)
@@ -111,6 +114,9 @@ struct sde_encoder_virt {

	atomic_t frame_done_timeout;
	struct timer_list frame_done_timer;

	struct sde_rsc_client *rsc_client;
	struct msm_display_info disp_info;
};

#define to_sde_encoder_virt(x) container_of(x, struct sde_encoder_virt, base)
@@ -157,6 +163,8 @@ void sde_encoder_destroy(struct drm_encoder *drm_enc)
	SDE_DEBUG_ENC(sde_enc, "\n");

	mutex_lock(&sde_enc->enc_lock);
	sde_rsc_client_destroy(sde_enc->rsc_client);

	for (i = 0; i < sde_enc->num_phys_encs; i++) {
		struct sde_encoder_phys *phys = sde_enc->phys_encs[i];

@@ -367,7 +375,8 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
	struct sde_encoder_virt *sde_enc = NULL;
	struct msm_drm_private *priv;
	struct sde_kms *sde_kms;
	int i = 0;
	int i = 0, ret;
	enum sde_rsc_state rsc_state;

	if (!drm_enc) {
		SDE_ERROR("invalid encoder\n");
@@ -390,6 +399,9 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
	sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);

	sde_enc->cur_master = NULL;
	rsc_state = sde_enc->disp_info.capabilities & MSM_DISPLAY_CAP_CMD_MODE ?
				SDE_RSC_CMD_STATE : SDE_RSC_VID_STATE;

	for (i = 0; i < sde_enc->num_phys_encs; i++) {
		struct sde_encoder_phys *phys = sde_enc->phys_encs[i];

@@ -411,6 +423,19 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
		SDE_ERROR("virt encoder has no master! num_phys %d\n", i);
	else if (sde_enc->cur_master->ops.enable)
		sde_enc->cur_master->ops.enable(sde_enc->cur_master);

	/**
	 * this should be after interface enable because interface enable api
	 * turns on panel, configure the TE for command mode and turns on
	 * timing engine for video mode. The RSC api call is going to wait
	 * for vsync after it switches the mode - that requires te/timing engine
	 * enabled.
	 */
	ret = sde_rsc_client_state_update(sde_enc->rsc_client, rsc_state, NULL,
			drm_enc->crtc ? drm_enc->crtc->index : -1);
	if (ret)
		SDE_ERROR("sde rsc client update failed ret:%d\n", ret);

}

static void sde_encoder_virt_disable(struct drm_encoder *drm_enc)
@@ -462,6 +487,8 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc)

	sde_rm_release(&sde_kms->rm, drm_enc);

	sde_rsc_client_state_update(sde_enc->rsc_client, SDE_RSC_IDLE_STATE,
						NULL, -1);
	sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
}

@@ -821,6 +848,7 @@ void sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc)
	struct sde_encoder_phys *phys;
	bool needs_hw_reset = false;
	unsigned int i;
	int ret;

	if (!drm_enc) {
		SDE_ERROR("invalid encoder\n");
@@ -831,6 +859,15 @@ void sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc)
	SDE_DEBUG_ENC(sde_enc, "\n");
	SDE_EVT32(DRMID(drm_enc));

	if (sde_enc->disp_info.is_primary) {
		ret = sde_rsc_client_vote(sde_enc->rsc_client,
			SDE_POWER_HANDLE_DATA_BUS_IB_QUOTA,
			SDE_POWER_HANDLE_DATA_BUS_AB_QUOTA,
			true);
		if (ret)
			SDE_ERROR("sde rsc client vote failed ret:%d\n", ret);
	}

	/* prepare for next kickoff, may include waiting on previous kickoff */
	for (i = 0; i < sde_enc->num_phys_encs; i++) {
		phys = sde_enc->phys_encs[i];
@@ -1310,6 +1347,7 @@ struct drm_encoder *sde_encoder_init(
	struct drm_encoder *drm_enc = NULL;
	struct sde_encoder_virt *sde_enc = NULL;
	int drm_enc_mode = DRM_MODE_ENCODER_NONE;
	char name[SDE_NAME_SIZE];
	int ret = 0;

	sde_enc = kzalloc(sizeof(*sde_enc), GFP_KERNEL);
@@ -1336,6 +1374,16 @@ struct drm_encoder *sde_encoder_init(

	_sde_encoder_init_debugfs(drm_enc, sde_enc, sde_kms);

	snprintf(name, SDE_NAME_SIZE, "rsc_enc%u", drm_enc->base.id);
	sde_enc->rsc_client = sde_rsc_client_create(SDE_RSC_INDEX, name,
							disp_info->is_primary);
	if (IS_ERR_OR_NULL(sde_enc->rsc_client)) {
		SDE_ERROR("sde rsc client create failed :%ld\n",
						PTR_ERR(sde_enc->rsc_client));
		sde_enc->rsc_client = NULL;
	}
	memcpy(&sde_enc->disp_info, disp_info, sizeof(*disp_info));

	SDE_DEBUG_ENC(sde_enc, "created\n");

	return drm_enc;
@@ -1400,3 +1448,16 @@ enum sde_intf_mode sde_encoder_get_intf_mode(struct drm_encoder *encoder)

	return INTF_MODE_NONE;
}

bool sde_encoder_get_intf_primary(struct drm_encoder *encoder)
{
	struct sde_encoder_virt *sde_enc = NULL;

	if (!encoder) {
		SDE_ERROR("invalid encoder\n");
		return INTF_MODE_NONE;
	}
	sde_enc = to_sde_encoder_virt(encoder);

	return sde_enc->disp_info.is_primary;
}
Loading