From 047e987980c1ee911570e36f728cbc04efbb676c Mon Sep 17 00:00:00 2001 From: Bang Nguyen Date: Wed, 31 Jul 2019 08:32:50 -0500 Subject: [PATCH] disp: msm: sde: Add motUtil Debugfs framework Adding the motUtil debugfs in /d/dri/0/debug to provide a tool for developer/tester to interface with the Display driver framework Port from: 890aa1c9 Change-Id: I5ca8fbd5f8aa17233683d82a66fe6ed45e722305 Signed-off-by: Bang Nguyen Reviewed-on: https://gerrit.mot.com/1697292 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Guobin Zhang Submit-Approved: Jira Key --- msm/Makefile | 1 + msm/sde/sde_kms.c | 1 + msm/sde/sde_motUtil.c | 271 ++++++++++++++++++++++++++++++++++++++++++ msm/sde/sde_motUtil.h | 38 ++++++ 4 files changed, 311 insertions(+) create mode 100644 msm/sde/sde_motUtil.c create mode 100644 msm/sde/sde_motUtil.h diff --git a/msm/Makefile b/msm/Makefile index 9c7df05e71b3..7e8d5f2a0fdb 100644 --- a/msm/Makefile +++ b/msm/Makefile @@ -42,6 +42,7 @@ msm_drm-$(CONFIG_DRM_MSM_SDE) += sde/sde_crtc.o \ sde/sde_core_perf.o \ sde/sde_rm.o \ sde/sde_kms_utils.o \ + sde/sde_motUtil.o \ sde/sde_kms.o \ sde/sde_plane.o \ sde/sde_connector.o \ diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index 9f7a815c9227..4f1aa7a6d65d 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -152,6 +152,7 @@ static int _sde_debugfs_init(struct sde_kms *sde_kms) (void) sde_debugfs_vbif_init(sde_kms, debugfs_root); (void) sde_debugfs_core_irq_init(sde_kms, debugfs_root); + (void) sde_debugfs_mot_util_init(sde_kms, debugfs_root); rc = sde_core_perf_debugfs_init(&sde_kms->perf, debugfs_root); if (rc) { diff --git a/msm/sde/sde_motUtil.c b/msm/sde/sde_motUtil.c new file mode 100644 index 000000000000..00ae8461658a --- /dev/null +++ b/msm/sde/sde_motUtil.c @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2018-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. + * + */ + +#define pr_fmt(fmt) "motUtil:[%s]" fmt, __func__ + +#include +#include +#include + +#include "sde_connector.h" +#include "sde_encoder.h" +#include "sde_motUtil.h" +#include "dsi_display.h" + + +#define MAIN_DSI_CONN_NAME "DSI-1" +#define CLI_DSI_CONN_NAME "DSI-2" + +struct motUtil motUtil_data; + +static ssize_t _sde_debugfs_motUtil_string2num(const char __user *buf, + size_t count, char buffer[]) +{ + char *input, *input_copy, *token, *input_dup = NULL; + const char *delim =" "; + u32 buf_size = 0; + int rc=0, strtoint; + + /*copy the data from user space*/ + input = kmalloc(count + 1, GFP_KERNEL); + if (!input) + return -ENOMEM; + + if (copy_from_user(input, buf, count)) { + SDE_ERROR("copy from user failed\n"); + rc = -EFAULT; + goto end; + } + input[count]='\0'; + SDE_INFO("input_cmd = %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); + rc = buf_size; +end: + kfree(input_dup); + kfree(input); + + return rc; +} + +static struct sde_connector *_sde_debugfs_motUtil_get_sde_conn( + struct sde_kms *kms, + size_t count, char input[]) +{ + struct drm_device *dev = kms->dev; + struct drm_connector *conn = NULL; + struct sde_connector *sde_conn = NULL; + int found_conn = 0; + enum sde_motUtil_disp_cmd panel_type = input[DISPUTIL_PANEL_TYPE]; + + mutex_lock(&dev->mode_config.mutex); + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(conn, &conn_iter) { + if (panel_type == MOTUTIL_MAIN_DISP) { + if (!strncmp(conn->name, MAIN_DSI_CONN_NAME, 5)) { + SDE_DEBUG("found MAIN disp conn\n"); + found_conn = 1; + break; + } + } else if (panel_type == MOTUTIL_CLI_DISP) { + if (!strncmp(conn->name, CLI_DSI_CONN_NAME, 5)) { + SDE_DEBUG("found CLI disp conn\n"); + found_conn = 1; + break; + } + } + } + + if (found_conn) { + SDE_DEBUG("found SDE Connector for %s\n", + (panel_type == MOTUTIL_MAIN_DISP) ? + "Main Display" : "CLI Display"); + sde_conn = to_sde_connector(conn); + } else { + SDE_ERROR("Can not find SDE Connector for %s\n", + (panel_type == MOTUTIL_MAIN_DISP) ? + "Main Display" : "CLI Display"); + } + + drm_connector_list_iter_end(&conn_iter); + mutex_unlock(&dev->mode_config.mutex); + + return sde_conn; +} + +static int _sde_debugfs_motUtil_transfer(struct sde_kms *kms, + size_t count, char input[]) +{ + struct sde_connector *sde_conn = NULL; + int ret = 0; + enum sde_motUtil_disp_cmd panel_type = input[DISPUTIL_PANEL_TYPE]; + + if (panel_type > MOTUTIL_CLI_DISP) { + SDE_ERROR("Invalid panel number = %d\n", panel_type); + return -EINVAL; + } + + sde_conn = _sde_debugfs_motUtil_get_sde_conn(kms, count, input); + if (!sde_conn) { + ret = -EINVAL; + goto end; + } + + if (sde_conn && !sde_conn->ops.motUtil_transfer) { + SDE_ERROR("no motUtil_transfer support for connector name %s\n", + sde_conn->name); + ret = -ENOENT; + goto end; + } + + if (motUtil_data.rd_buf) { + mutex_lock(&sde_conn->lock); + ret = sde_conn->ops.motUtil_transfer(sde_conn->display, + input, count, &motUtil_data); + motUtil_data.last_cmd_tx_status = !ret ? true : false; + motUtil_data.read_len = ret; + mutex_unlock(&sde_conn->lock); + + ret = count; + } else + ret = -ENOMEM; +end: + return ret; +} + + +static ssize_t _sde_debugfs_motUtil_exe_command(struct sde_kms *kms, + size_t count, char input[]) +{ + int ret = 0; + enum sde_motUtil_type motUtil_type = input[0]; + + motUtil_data.motUtil_type = motUtil_type; + + return ret; +} + +static int _sde_debugfs_motUtil_open(struct inode *inode, + struct file *file) +{ + if (!inode || !file) + return -EINVAL; + + /* non-seekable */ + file->private_data = inode->i_private; + return nonseekable_open(inode, file); +} + +static ssize_t _sde_debugfs_motUtil_write(struct file *file, + const char __user *buf, size_t count, loff_t *ppos) +{ + u32 buf_size = 0; + char buffer[MAX_CMD_PAYLOAD_SIZE]; + struct sde_kms *kms = (struct sde_kms *)file->private_data; + + if (*ppos || !kms) { + SDE_ERROR("invalid argument(s)\n"); + return 0; + } + + buf_size = _sde_debugfs_motUtil_string2num(buf, count, buffer); + if (!buf_size){ + SDE_ERROR("invalid input\n"); + return count; + } + + mutex_lock(&motUtil_data.lock); + _sde_debugfs_motUtil_exe_command(kms, count, buffer); + mutex_unlock(&motUtil_data.lock); + + return count; +} + +static ssize_t _sde_debugfs_motUtil_read(struct file *file, + char __user *buf, size_t count, loff_t *ppos) +{ + int blen = 0; + char buffer[MAX_CMD_PAYLOAD_SIZE]; + + if (*ppos) + return 0; + + mutex_lock(&motUtil_data.lock); + if (!motUtil_data.read_cmd) + blen = snprintf(buffer, MAX_CMD_PAYLOAD_SIZE, + "motUtil_status: 0x%x\n", + motUtil_data.last_cmd_tx_status); + + SDE_INFO("%s\n", buffer); + + if (blen <= 0) { + SDE_ERROR("snprintf failed, blen %d\n", blen); + return 0; + } + + if (copy_to_user(buf, buffer, min(count, (size_t)blen+1))) { + SDE_ERROR("copy to user buffer failed\n"); + return -EFAULT; + } + + *ppos += blen; + mutex_unlock(&motUtil_data.lock); + return blen; +} + +static const struct file_operations sde_debugfs_motUtil_fops = { + .open = _sde_debugfs_motUtil_open, + .read = _sde_debugfs_motUtil_read, + .write = _sde_debugfs_motUtil_write, +}; + +int sde_debugfs_mot_util_init(struct sde_kms *sde_kms, + struct dentry *parent) +{ + debugfs_create_file("motUtil", 0606, parent, + sde_kms, &sde_debugfs_motUtil_fops); + + motUtil_data.rd_buf = kzalloc(SZ_4K, GFP_KERNEL); + if (!motUtil_data.rd_buf) + return -ENOMEM; + + motUtil_data.te_enable = true; + mutex_init(&motUtil_data.lock); + return 0; +} diff --git a/msm/sde/sde_motUtil.h b/msm/sde/sde_motUtil.h new file mode 100644 index 000000000000..0c51d8e486ca --- /dev/null +++ b/msm/sde/sde_motUtil.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018-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 __MOTUTIL_H__ +#define __MOTUTIL_H__ + +#include +#include + +enum sde_motUtil_type { +}; + +struct motUtil { + struct mutex lock; + enum sde_motUtil_type motUtil_type; + bool read_cmd; + bool last_cmd_tx_status; + u16 read_len; + u8 *rd_buf; + int val; + bool te_enable; +}; + +int sde_debugfs_mot_util_init(struct sde_kms *sde_kms, + struct dentry *parent); + +#endif /* __MOTUTIL_H__ */