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

Commit 5ef08b98 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: debugfs interface for sde connector to transfer cmds"

parents 000169ec b95b9c3d
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -2830,6 +2830,27 @@ static void _dsi_ctrl_cache_misr(struct dsi_ctrl *dsi_ctrl)
		dsi_ctrl->misr_cache);

}
/**
 * dsi_ctrl_get_host_engine_init_state() - Return host init state
 * @dsi_ctrl:          DSI controller handle.
 * @state:             Controller initialization state
 *
 * Return: error code.
 */
int dsi_ctrl_get_host_engine_init_state(struct dsi_ctrl *dsi_ctrl,
		bool *state)
{
	if (!dsi_ctrl || !state) {
		pr_err("Invalid Params\n");
		return -EINVAL;
	}

	mutex_lock(&dsi_ctrl->ctrl_lock);
	*state = dsi_ctrl->current_state.host_initialized;
	mutex_unlock(&dsi_ctrl->ctrl_lock);

	return 0;
}

/**
 * dsi_ctrl_update_host_engine_state_for_cont_splash() -
+7 −0
Original line number Diff line number Diff line
@@ -717,4 +717,11 @@ void dsi_ctrl_isr_configure(struct dsi_ctrl *dsi_ctrl, bool enable);
 * @enable:		   variable to control enable/disable irq line
 */
void dsi_ctrl_irq_update(struct dsi_ctrl *dsi_ctrl, bool enable);

/**
 * dsi_ctrl_get_host_engine_init_state() - Return host init state
 */
int dsi_ctrl_get_host_engine_init_state(struct dsi_ctrl *dsi_ctrl,
		bool *state);

#endif /* _DSI_CTRL_H_ */
+81 −0
Original line number Diff line number Diff line
@@ -564,6 +564,87 @@ int dsi_display_check_status(void *display)
	return rc;
}

static int dsi_display_cmd_prepare(const char *cmd_buf, u32 cmd_buf_len,
		struct dsi_cmd_desc *cmd, u8 *payload, u32 payload_len)
{
	int i;

	memset(cmd, 0x00, sizeof(*cmd));
	cmd->msg.type = cmd_buf[0];
	cmd->last_command = (cmd_buf[1] == 1 ? true : false);
	cmd->msg.channel = cmd_buf[2];
	cmd->msg.flags = cmd_buf[3];
	cmd->msg.ctrl = 0;
	cmd->post_wait_ms = cmd_buf[4];
	cmd->msg.tx_len = ((cmd_buf[5] << 8) | (cmd_buf[6]));

	if (cmd->msg.tx_len > payload_len) {
		pr_err("Incorrect payload length tx_len %ld, payload_len %d\n",
				cmd->msg.tx_len, payload_len);
		return -EINVAL;
	}

	for (i = 0; i < cmd->msg.tx_len; i++)
		payload[i] = cmd_buf[7 + i];

	cmd->msg.tx_buf = payload;
	return 0;
}

static int dsi_display_ctrl_get_host_init_state(struct dsi_display *dsi_display,
		bool *state)
{
	struct dsi_display_ctrl *ctrl;
	int i, rc = -EINVAL;

	for (i = 0 ; i < dsi_display->ctrl_count; i++) {
		ctrl = &dsi_display->ctrl[i];
		rc = dsi_ctrl_get_host_engine_init_state(ctrl->ctrl, state);
		if (rc)
			break;
	}
	return rc;
}

int dsi_display_cmd_transfer(void *display, const char *cmd_buf,
		u32 cmd_buf_len)
{
	struct dsi_display *dsi_display = display;
	struct dsi_cmd_desc cmd;
	u8 cmd_payload[MAX_CMD_PAYLOAD_SIZE];
	int rc = 0;
	bool state = false;

	if (!dsi_display || !cmd_buf) {
		pr_err("[DSI] invalid params\n");
		return -EINVAL;
	}

	pr_debug("[DSI] Display command transfer\n");

	rc = dsi_display_cmd_prepare(cmd_buf, cmd_buf_len,
			&cmd, cmd_payload, MAX_CMD_PAYLOAD_SIZE);
	if (rc) {
		pr_err("[DSI] command prepare failed. rc %d\n", rc);
		return rc;
	}

	mutex_lock(&dsi_display->display_lock);
	rc = dsi_display_ctrl_get_host_init_state(dsi_display, &state);
	if (rc || !state) {
		pr_err("[DSI] Invalid host state %d rc %d\n",
				state, rc);
		rc = -EPERM;
		goto end;
	}

	rc = dsi_display->host.ops->transfer(&dsi_display->host,
			&cmd.msg);
end:
	mutex_unlock(&dsi_display->display_lock);
	return rc;
}

int dsi_display_soft_reset(void *display)
{
	struct dsi_display *dsi_display;
+10 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#define MAX_DSI_CTRLS_PER_DISPLAY             2
#define DSI_CLIENT_NAME_SIZE		20
#define MAX_CMDLINE_PARAM_LEN	 512
#define MAX_CMD_PAYLOAD_SIZE	256
/*
 * DSI Validate Mode modifiers
 * @DSI_VALIDATE_FLAG_ALLOW_ADJUST:	Allow mode validation to also do fixup
@@ -535,6 +536,15 @@ int dsi_display_set_backlight(void *display, u32 bl_lvl);
 */
int dsi_display_check_status(void *display);

/**
 * dsi_display_cmd_transfer() - transfer command to the panel
 * @display:            Handle to display.
 * @cmd_buf:            Command buffer
 * @cmd_buf_len:        Command buffer length in bytes
 */
int dsi_display_cmd_transfer(void *display, const char *cmd_buffer,
		u32 cmd_buf_len);

/**
 * dsi_display_soft_reset() - perform a soft reset on DSI controller
 * @display:         Handle to display
+139 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include "sde_connector.h"
#include "sde_encoder.h"
#include <linux/backlight.h>
#include <linux/string.h>
#include "dsi_drm.h"
#include "dsi_display.h"
#include "sde_crtc.h"
@@ -1357,6 +1358,135 @@ int sde_connector_helper_reset_custom_properties(
	return 0;
}

static int _sde_debugfs_conn_cmd_tx_open(struct inode *inode, struct file *file)
{
	/* non-seekable */
	file->private_data = inode->i_private;
	return nonseekable_open(inode, file);
}

static ssize_t _sde_debugfs_conn_cmd_tx_sts_read(struct file *file,
		char __user *buf, size_t count, loff_t *ppos)
{
	struct drm_connector *connector = file->private_data;
	struct sde_connector *c_conn;
	char buffer[MAX_CMD_PAYLOAD_SIZE];
	int blen = 0;

	if (*ppos)
		return 0;

	if (!connector) {
		SDE_ERROR("invalid argument, conn is NULL\n");
		return 0;
	}

	c_conn = to_sde_connector(connector);

	mutex_lock(&c_conn->lock);
	blen = snprintf(buffer, MAX_CMD_PAYLOAD_SIZE,
		"last_cmd_tx_sts:0x%x",
		c_conn->last_cmd_tx_sts);
	mutex_unlock(&c_conn->lock);

	SDE_DEBUG("output: %s\n", buffer);
	if (blen <= 0) {
		SDE_ERROR("snprintf failed, blen %d\n", blen);
		return 0;
	}

	if (copy_to_user(buf, buffer, blen)) {
		SDE_ERROR("copy to user buffer failed\n");
		return -EFAULT;
	}

	*ppos += blen;
	return blen;
}

static ssize_t _sde_debugfs_conn_cmd_tx_write(struct file *file,
			const char __user *p, size_t count, loff_t *ppos)
{
	struct drm_connector *connector = file->private_data;
	struct sde_connector *c_conn;
	char *input, *token, *input_copy, *input_dup = NULL;
	const char *delim = " ";
	u32 buf_size = 0;
	char buffer[MAX_CMD_PAYLOAD_SIZE];
	int rc = 0, strtoint;

	if (*ppos || !connector) {
		SDE_ERROR("invalid argument(s), conn %d\n", connector != NULL);
		return 0;
	}

	c_conn = to_sde_connector(connector);

	if (!c_conn->ops.cmd_transfer) {
		SDE_ERROR("no cmd transfer support for connector name %s\n",
				c_conn->name);
		return 0;
	}

	input = kmalloc(count + 1, GFP_KERNEL);
	if (!input)
		return -ENOMEM;

	if (copy_from_user(input, p, count)) {
		SDE_ERROR("copy from user failed\n");
		rc = -EFAULT;
		goto end;
	}
	input[count] = '\0';

	SDE_DEBUG("input: %s\n", input);

	input_copy = kstrdup(input, GFP_KERNEL);
	if (!input_copy) {
		rc = -ENOMEM;
		goto end;
	}

	input_dup = input_copy;
	token = strsep(&input_copy, delim);
	while (token) {
		rc = kstrtoint(token, 0, &strtoint);
		if (rc) {
			SDE_ERROR("input buffer conversion failed\n");
			goto end;
		}

		if (buf_size >= MAX_CMD_PAYLOAD_SIZE) {
			SDE_ERROR("buffer size exceeding the limit %d\n",
					MAX_CMD_PAYLOAD_SIZE);
			goto end;
		}
		buffer[buf_size++] = (strtoint & 0xff);
		token = strsep(&input_copy, delim);
	}
	SDE_DEBUG("command packet size in bytes: %u\n", buf_size);
	if (!buf_size)
		goto end;

	mutex_lock(&c_conn->lock);
	rc = c_conn->ops.cmd_transfer(c_conn->display, buffer,
			buf_size);
	c_conn->last_cmd_tx_sts = !rc ? true : false;
	mutex_unlock(&c_conn->lock);

	rc = count;
end:
	kfree(input_dup);
	kfree(input);
	return rc;
}

static const struct file_operations conn_cmd_tx_fops = {
	.open =		_sde_debugfs_conn_cmd_tx_open,
	.read =		_sde_debugfs_conn_cmd_tx_sts_read,
	.write =	_sde_debugfs_conn_cmd_tx_write,
};

#ifdef CONFIG_DEBUG_FS
/**
 * sde_connector_init_debugfs - initialize connector debugfs
@@ -1387,6 +1517,15 @@ static int sde_connector_init_debugfs(struct drm_connector *connector)
		return -ENOMEM;
	}

	if (sde_connector->ops.cmd_transfer) {
		if (!debugfs_create_file("tx_cmd", 0600,
			connector->debugfs_entry,
			connector, &conn_cmd_tx_fops)) {
			SDE_ERROR("failed to create connector cmd_tx\n");
			return -ENOMEM;
		}
	}

	return 0;
}
#else
Loading