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

Commit 29f0d69b authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/msm: propagate mode private data without mode_config mutex"

parents df7a91d9 560785eb
Loading
Loading
Loading
Loading
+88 −11
Original line number Diff line number Diff line
@@ -3982,7 +3982,7 @@ int dsi_display_get_info(struct msm_display_info *info, void *disp)
	return rc;
}

int dsi_display_get_mode_count(struct dsi_display *display,
static int dsi_display_get_mode_count_no_lock(struct dsi_display *display,
			u32 *count)
{
	struct dsi_dfps_capabilities dfps_caps;
@@ -3994,15 +3994,13 @@ int dsi_display_get_mode_count(struct dsi_display *display,
		return -EINVAL;
	}

	mutex_lock(&display->display_lock);

	*count = display->panel->num_timing_nodes;

	rc = dsi_panel_get_dfps_caps(display->panel, &dfps_caps);
	if (rc) {
		pr_err("[%s] failed to get dfps caps from panel\n",
				display->name);
		goto done;
		return rc;
	}

	num_dfps_rates = !dfps_caps.dfps_support ? 1 :
@@ -4012,7 +4010,22 @@ int dsi_display_get_mode_count(struct dsi_display *display,
	/* Inflate num_of_modes by fps in dfps */
	*count = display->panel->num_timing_nodes * num_dfps_rates;

done:
	return 0;
}

int dsi_display_get_mode_count(struct dsi_display *display,
			u32 *count)
{
	int rc;

	if (!display || !display->panel) {
		pr_err("invalid display:%d panel:%d\n", display != NULL,
				display ? display->panel != NULL : 0);
		return -EINVAL;
	}

	mutex_lock(&display->display_lock);
	rc = dsi_display_get_mode_count_no_lock(display, count);
	mutex_unlock(&display->display_lock);

	return 0;
@@ -4025,20 +4038,36 @@ void dsi_display_put_mode(struct dsi_display *display,
}

int dsi_display_get_modes(struct dsi_display *display,
			  struct dsi_display_mode *modes)
			  struct dsi_display_mode **out_modes)
{
	struct dsi_dfps_capabilities dfps_caps;
	u32 num_dfps_rates, panel_mode_count;
	u32 num_dfps_rates, panel_mode_count, total_mode_count;
	u32 mode_idx, array_idx = 0;
	int i, rc = 0;
	int i, rc = -EINVAL;

	if (!display || !modes) {
	if (!display || !out_modes) {
		pr_err("Invalid params\n");
		return -EINVAL;
	}

	*out_modes = NULL;

	mutex_lock(&display->display_lock);

	rc = dsi_display_get_mode_count_no_lock(display, &total_mode_count);
	if (rc)
		goto error;

	/* free any previously probed modes */
	kfree(display->modes);

	display->modes = kcalloc(total_mode_count, sizeof(*display->modes),
			GFP_KERNEL);
	if (!display->modes) {
		rc = -ENOMEM;
		goto error;
	}

	rc = dsi_panel_get_dfps_caps(display->panel, &dfps_caps);
	if (rc) {
		pr_err("[%s] failed to get dfps caps from panel\n",
@@ -4079,12 +4108,14 @@ int dsi_display_get_modes(struct dsi_display *display,
		}

		for (i = 0; i < num_dfps_rates; i++) {
			struct dsi_display_mode *sub_mode = &modes[array_idx];
			struct dsi_display_mode *sub_mode =
					&display->modes[array_idx];
			u32 curr_refresh_rate;

			if (!sub_mode) {
				pr_err("invalid mode data\n");
				return -EFAULT;
				rc = -EFAULT;
				goto error;
			}

			memcpy(sub_mode, &panel_mode, sizeof(panel_mode));
@@ -4108,11 +4139,57 @@ int dsi_display_get_modes(struct dsi_display *display,
		}
	}

	*out_modes = display->modes;
	rc = 0;

error:
	if (rc)
		kfree(display->modes);

	mutex_unlock(&display->display_lock);
	return rc;
}

int dsi_display_find_mode(struct dsi_display *display,
		const struct dsi_display_mode *cmp,
		struct dsi_display_mode **out_mode)
{
	u32 count, i;
	int rc;

	if (!display || !out_mode)
		return -EINVAL;

	*out_mode = NULL;

	rc = dsi_display_get_mode_count(display, &count);
	if (rc)
		return rc;

	mutex_lock(&display->display_lock);
	for (i = 0; i < count; i++) {
		struct dsi_display_mode *m = &display->modes[i];

		if (cmp->timing.v_active == m->timing.v_active &&
			cmp->timing.h_active == m->timing.h_active &&
			cmp->timing.refresh_rate == m->timing.refresh_rate) {
			*out_mode = m;
			rc = 0;
			break;
		}
	}
	mutex_unlock(&display->display_lock);

	if (!*out_mode) {
		pr_err("[%s] failed to find mode for v_active %u h_active %u rate %u\n",
				display->name, cmp->timing.v_active,
				cmp->timing.h_active, cmp->timing.refresh_rate);
		rc = -ENOENT;
	}

	return rc;
}

/**
 * dsi_display_validate_mode_vrr() - Validate if varaible refresh case.
 * @display:     DSI display handle.
+17 −5
Original line number Diff line number Diff line
@@ -135,6 +135,7 @@ struct dsi_display_clk_info {
 * @ctrl:             Controller information for DSI display.
 * @panel:            Handle to DSI panel.
 * @panel_of:         pHandle to DSI panel.
 * @modes:            Array of probed DSI modes
 * @type:             DSI display type.
 * @clk_master_idx:   The master controller for controlling clocks. This is an
 *		      index into the ctrl[MAX_DSI_CTRLS_PER_DISPLAY] array.
@@ -178,6 +179,8 @@ struct dsi_display {
	struct dsi_panel *panel;
	struct device_node *panel_of;

	struct dsi_display_mode *modes;

	enum dsi_display_type type;
	u32 clk_master_idx;
	u32 cmd_master_idx;
@@ -304,15 +307,13 @@ int dsi_display_get_mode_count(struct dsi_display *display, u32 *count);
/**
 * dsi_display_get_modes() - get modes supported by display
 * @display:            Handle to display.
 * @modes;              Pointer to array of modes. Memory allocated should be
 *			big enough to store (count * struct dsi_display_mode)
 *			elements. If modes pointer is NULL, number of modes will
 *			be stored in the memory pointed to by count.
 * @modes;              Output param, list of DSI modes. Number of modes matches
 *                      count returned by dsi_display_get_mode_count
 *
 * Return: error code.
 */
int dsi_display_get_modes(struct dsi_display *display,
			  struct dsi_display_mode *modes);
			  struct dsi_display_mode **modes);

/**
 * dsi_display_put_mode() - free up mode created for the display
@@ -324,6 +325,17 @@ int dsi_display_get_modes(struct dsi_display *display,
void dsi_display_put_mode(struct dsi_display *display,
	struct dsi_display_mode *mode);

/**
 * dsi_display_find_mode() - retrieve cached DSI mode given relevant params
 * @display:            Handle to display.
 * @cmp:                Mode to use as comparison to find original
 * @out_mode:           Output parameter, pointer to retrieved mode
 *
 * Return: error code.
 */
int dsi_display_find_mode(struct dsi_display *display,
		const struct dsi_display_mode *cmp,
		struct dsi_display_mode **out_mode);
/**
 * dsi_display_validate_mode() - validates if mode is supported by display
 * @display:             Handle to display.
+1 −9
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@ static void dsi_display_test_work(struct work_struct *work)
	struct dsi_display *display;
	struct dsi_display_mode *modes;
	u32 count = 0;
	u32 size = 0;
	int rc = 0;

	test = container_of(work, struct dsi_display_test, test_work);
@@ -40,14 +39,7 @@ static void dsi_display_test_work(struct work_struct *work)
		goto test_fail;
	}

	size = count * sizeof(*modes);
	modes = kzalloc(size, GFP_KERNEL);
	if (!modes) {
		rc = -ENOMEM;
		goto test_fail;
	}

	rc = dsi_display_get_modes(display, modes);
	rc = dsi_display_get_modes(display, &modes);
	if (rc) {
		pr_err("failed to get modes, rc=%d\n", rc);
		goto test_fail_free_modes;
+24 −14
Original line number Diff line number Diff line
@@ -268,7 +268,8 @@ static bool dsi_bridge_mode_fixup(struct drm_bridge *bridge,
{
	int rc = 0;
	struct dsi_bridge *c_bridge = to_dsi_bridge(bridge);
	struct dsi_display_mode dsi_mode, cur_dsi_mode;
	struct dsi_display *display;
	struct dsi_display_mode dsi_mode, cur_dsi_mode, *panel_dsi_mode;
	struct drm_display_mode cur_mode;
	struct drm_crtc_state *crtc_state;

@@ -279,8 +280,26 @@ static bool dsi_bridge_mode_fixup(struct drm_bridge *bridge,
		return false;
	}

	display = c_bridge->display;
	if (!display) {
		pr_err("Invalid params\n");
		return false;
	}

	convert_to_dsi_mode(mode, &dsi_mode);

	/*
	 * retrieve dsi mode from dsi driver's cache since not safe to take
	 * the drm mode config mutex in all paths
	 */
	rc = dsi_display_find_mode(display, &dsi_mode, &panel_dsi_mode);
	if (rc)
		return rc;

	/* propagate the private info to the adjusted_mode derived dsi mode */
	dsi_mode.priv_info = panel_dsi_mode->priv_info;
	dsi_mode.dsi_mode_flags = panel_dsi_mode->dsi_mode_flags;

	rc = dsi_display_validate_mode(c_bridge->display, &dsi_mode,
			DSI_VALIDATE_FLAG_ALLOW_ADJUST);
	if (rc) {
@@ -307,6 +326,7 @@ static bool dsi_bridge_mode_fixup(struct drm_bridge *bridge,
			dsi_mode.dsi_mode_flags |= DSI_MODE_FLAG_DMS;
	}

	/* convert back to drm mode, propagating the private info & flags */
	dsi_convert_to_drm_mode(&dsi_mode, adjusted_mode);

	return true;
@@ -540,7 +560,6 @@ int dsi_connector_get_modes(struct drm_connector *connector,
		void *display)
{
	u32 count = 0;
	u32 size = 0;
	struct dsi_display_mode *modes = NULL;
	struct drm_display_mode drm_mode;
	int rc, i;
@@ -556,21 +575,14 @@ int dsi_connector_get_modes(struct drm_connector *connector,
	rc = dsi_display_get_mode_count(display, &count);
	if (rc) {
		pr_err("failed to get num of modes, rc=%d\n", rc);
		goto error;
	}

	size = count * sizeof(*modes);
	modes = kzalloc(size,  GFP_KERNEL);
	if (!modes) {
		count = 0;
		goto end;
	}

	rc = dsi_display_get_modes(display, modes);
	rc = dsi_display_get_modes(display, &modes);
	if (rc) {
		pr_err("failed to get modes, rc=%d\n", rc);
		count = 0;
		goto error;
		goto end;
	}

	for (i = 0; i < count; i++) {
@@ -584,14 +596,12 @@ int dsi_connector_get_modes(struct drm_connector *connector,
			       drm_mode.hdisplay,
			       drm_mode.vdisplay);
			count = -ENOMEM;
			goto error;
			goto end;
		}
		m->width_mm = connector->display_info.width_mm;
		m->height_mm = connector->display_info.height_mm;
		drm_mode_probed_add(connector, m);
	}
error:
	kfree(modes);
end:
	pr_debug("MODE COUNT =%d\n\n", count);
	return count;
+0 −27
Original line number Diff line number Diff line
@@ -780,24 +780,6 @@ void sde_encoder_helper_split_config(
	}
}

static void _sde_encoder_adjust_mode(struct drm_connector *connector,
		struct drm_display_mode *adj_mode)
{
	struct drm_display_mode *cur_mode;

	if (!connector || !adj_mode)
		return;

	list_for_each_entry(cur_mode, &connector->modes, head) {
		if (cur_mode->vdisplay == adj_mode->vdisplay &&
			cur_mode->hdisplay == adj_mode->hdisplay &&
			cur_mode->vrefresh == adj_mode->vrefresh) {
			adj_mode->private = cur_mode->private;
			adj_mode->private_flags |= cur_mode->private_flags;
		}
	}
}

static int sde_encoder_virt_atomic_check(
		struct drm_encoder *drm_enc,
		struct drm_crtc_state *crtc_state,
@@ -833,15 +815,6 @@ static int sde_encoder_virt_atomic_check(

	SDE_EVT32(DRMID(drm_enc), drm_atomic_crtc_needs_modeset(crtc_state));

	/*
	 * display drivers may populate private fields of the drm display mode
	 * structure while registering possible modes of a connector with DRM.
	 * These private fields are not populated back while DRM invokes
	 * the mode_set callbacks. This module retrieves and populates the
	 * private fields of the given mode.
	 */
	_sde_encoder_adjust_mode(conn_state->connector, adj_mode);

	/* perform atomic check on the first physical encoder (master) */
	for (i = 0; i < sde_enc->num_phys_encs; i++) {
		struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
Loading