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

Commit a22aea40 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: cvp: Support DSP to CPU reverse rpmsg"

parents 178e0277 ae9d6bfd
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -2575,6 +2575,9 @@ static void iris_hfi_pm_handler(struct work_struct *work)
	}

	mutex_lock(&device->lock);
	if (gfa_cv.state == DSP_SUSPEND)
		rc = __power_collapse(device, true);
	else
		rc = __power_collapse(device, false);
	mutex_unlock(&device->lock);
	switch (rc) {
@@ -2693,7 +2696,7 @@ static int __power_collapse(struct iris_hfi_device *device, bool force)
	return rc;

skip_power_off:
	dprintk(CVP_WARN, "Skip PC(%#x, %#x, %#x)\n",
	dprintk(CVP_PWR, "Skip PC(%#x, %#x, %#x)\n",
		wfi_status, idle_status, pc_ready);
	__flush_debug_queue(device, device->raw_packet);
	return -EAGAIN;
+132 −21
Original line number Diff line number Diff line
@@ -10,17 +10,7 @@
#include "msm_cvp_dsp.h"
#include "msm_cvp_internal.h"

struct cvp_dsp_apps {
	struct mutex lock;
	struct rpmsg_device *chan;
	uint32_t state;
	bool hyp_assigned;
	uint64_t addr;
	uint32_t size;
	struct completion completions[CVP_DSP_MAX_CMD];
};

static struct cvp_dsp_apps gfa_cv;
struct cvp_dsp_apps gfa_cv;
static int hlosVM[HLOS_VM_NUM] = {VMID_HLOS};
static int dspVM[DSP_VM_NUM] = {VMID_HLOS, VMID_CDSP_Q6};
static int dspVMperm[DSP_VM_NUM] = { PERM_READ | PERM_WRITE | PERM_EXEC,
@@ -71,6 +61,8 @@ static int cvp_dsp_send_cmd_sync(struct cvp_dsp_cmd_msg *cmd, uint32_t len)
		goto exit;
	}

	me->pending_dsp2cpu_rsp.type = CVP_INVALID_RPMSG_TYPE;

exit:
	return rc;
}
@@ -81,7 +73,7 @@ static int cvp_dsp_send_cmd_hfi_queue(phys_addr_t *phys_addr,
	int rc = 0;
	struct cvp_dsp_cmd_msg cmd;

	cmd.type = CVP_DSP_SEND_HFI_QUEUE;
	cmd.type = CPU2DSP_SEND_HFI_QUEUE;
	cmd.msg_ptr = (uint64_t)phys_addr;
	cmd.msg_ptr_len = size_in_bytes;
	cmd.ddr_type = of_fdt_get_ddrtype();
@@ -193,12 +185,34 @@ static int cvp_dsp_rpmsg_callback(struct rpmsg_device *rpdev,
	dprintk(CVP_DSP, "%s: type = 0x%x ret = 0x%x\n",
		__func__, rsp->type, rsp->ret);

	if (rsp->type >= CVP_DSP_MAX_CMD) {
		dprintk(CVP_ERR, "%s: Invalid type: %d\n", __func__, rsp->type);
	if (rsp->type == CPU2DSP_SUSPEND ||
		rsp->type == CPU2DSP_RESUME) {
		me->pending_dsp2cpu_rsp.type = CVP_INVALID_RPMSG_TYPE;
		return 0;
	}

	if (me->pending_dsp2cpu_rsp.type != CVP_INVALID_RPMSG_TYPE ||
		me->pending_dsp2cpu_cmd.type != CVP_INVALID_RPMSG_TYPE)
		goto exit;

	if (rsp->type < CPU2DSP_MAX_CMD) {
		memcpy(&me->pending_dsp2cpu_rsp, rsp,
			sizeof(struct cvp_dsp_rsp_msg));
		complete(&me->completions[rsp->type]);
	} else if (rsp->type < CVP_DSP_MAX_CMD) {
		memcpy(&me->pending_dsp2cpu_cmd, rsp,
			sizeof(struct cvp_dsp2cpu_cmd_msg));
		complete(&me->completions[CPU2DSP_MAX_CMD]);
	} else {
		dprintk(CVP_ERR, "%s: Invalid type: %d\n", __func__, rsp->type);
		return 0;
	}

	return 0;
exit:
	dprintk(CVP_ERR, "concurrent dsp cmd type = %d, rsp type = %d\n",
			me->pending_dsp2cpu_cmd.type,
			me->pending_dsp2cpu_rsp.type);
	return 0;
}

@@ -208,7 +222,7 @@ int cvp_dsp_suspend(uint32_t session_flag)
	struct cvp_dsp_cmd_msg cmd;
	struct cvp_dsp_apps *me = &gfa_cv;

	cmd.type = CVP_DSP_SUSPEND;
	cmd.type = CPU2DSP_SUSPEND;

	mutex_lock(&me->lock);
	if (me->state != DSP_READY)
@@ -237,7 +251,7 @@ int cvp_dsp_resume(uint32_t session_flag)
	struct cvp_dsp_cmd_msg cmd;
	struct cvp_dsp_apps *me = &gfa_cv;

	cmd.type = CVP_DSP_RESUME;
	cmd.type = CPU2DSP_RESUME;

	mutex_lock(&me->lock);
	if (me->state != DSP_SUSPEND)
@@ -266,7 +280,7 @@ int cvp_dsp_shutdown(uint32_t session_flag)
	int rc = 0;
	struct cvp_dsp_cmd_msg cmd;

	cmd.type = CVP_DSP_SHUTDOWN;
	cmd.type = CPU2DSP_SHUTDOWN;

	mutex_lock(&me->lock);
	if (me->state == DSP_INVALID)
@@ -297,7 +311,7 @@ int cvp_dsp_register_buffer(uint32_t session_id, uint32_t buff_fd,
	int rc;
	struct cvp_dsp_apps *me = &gfa_cv;

	cmd.type = CVP_DSP_REGISTER_BUFFER;
	cmd.type = CPU2DSP_REGISTER_BUFFER;
	cmd.session_id = session_id;
	cmd.buff_fd = buff_fd;
	cmd.buff_fd_size = buff_fd_size;
@@ -335,7 +349,7 @@ int cvp_dsp_deregister_buffer(uint32_t session_id, uint32_t buff_fd,
	int rc;
	struct cvp_dsp_apps *me = &gfa_cv;

	cmd.type = CVP_DSP_DEREGISTER_BUFFER;
	cmd.type = CPU2DSP_DEREGISTER_BUFFER;
	cmd.session_id = session_id;
	cmd.buff_fd = buff_fd;
	cmd.buff_fd_size = buff_fd_size;
@@ -439,9 +453,93 @@ void cvp_dsp_send_hfi_queue(void)
	mutex_unlock(&device->lock);
}

static int cvp_dsp_thread(void *data)
{
	int rc = 0, old_state;
	struct cvp_dsp_apps *me = &gfa_cv;
	struct cvp_dsp_cmd_msg cmd;
	struct cvp_hfi_device *hdev;
	struct msm_cvp_core *core;

	core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
	if (!core) {
		dprintk(CVP_ERR, "%s: Failed to find core\n", __func__);
		rc = -EINVAL;
		goto exit;
	}

	hdev = (struct cvp_hfi_device *)core->device;
	if (!hdev) {
		dprintk(CVP_ERR, "%s Invalid device handle\n", __func__);
		rc = -EINVAL;
		goto exit;
	}

wait_dsp:
	rc = wait_for_completion_interruptible(
			&me->completions[CPU2DSP_MAX_CMD]);

	if (me->state == DSP_INVALID)
		goto exit;

	cmd.type = me->pending_dsp2cpu_cmd.type;

	if (rc == -ERESTARTSYS) {
		dprintk(CVP_WARN, "%s received interrupt signal\n", __func__);
	} else {
		mutex_lock(&me->lock);
		switch (me->pending_dsp2cpu_cmd.type) {
		case DSP2CPU_POWERON:
		{
			if (me->state == DSP_READY)
				break;

			mutex_unlock(&me->lock);
			old_state = me->state;
			me->state = DSP_READY;
			rc = call_hfi_op(hdev, resume, hdev->hfi_device_data);
			if (rc) {
				dprintk(CVP_WARN, "%s Failed to resume cvp\n",
						__func__);
				mutex_lock(&me->lock);
				me->state = old_state;
				cmd.ret = 1;
				break;
			}
			mutex_lock(&me->lock);
			cmd.ret = 0;
			break;
		}
		case DSP2CPU_POWEROFF:
		{
			me->state = DSP_SUSPEND;
			cmd.ret = 0;
			break;
		}
		default:
			dprintk(CVP_ERR, "unrecognaized dsp cmds: %d\n",
					me->pending_dsp2cpu_cmd.type);
			break;
		}
		me->pending_dsp2cpu_cmd.type = CVP_INVALID_RPMSG_TYPE;
		mutex_unlock(&me->lock);
	}
	/* Responds to DSP */
	rc = cvp_dsp_send_cmd(&cmd, sizeof(struct cvp_dsp_cmd_msg));
	if (rc)
		dprintk(CVP_ERR,
			"%s: cvp_dsp_send_cmd failed rc = %d cmd type=%d\n",
			__func__, rc, cmd.type);
	goto wait_dsp;
exit:
	dprintk(CVP_DBG, "dsp thread exit\n");
	do_exit(rc);
}

int cvp_dsp_device_init(void)
{
	struct cvp_dsp_apps *me = &gfa_cv;
	char tname[16];
	int rc;
	int i;

@@ -449,9 +547,12 @@ int cvp_dsp_device_init(void)
	me->state = DSP_INVALID;
	me->hyp_assigned = false;

	for (i = 0; i < CVP_DSP_MAX_CMD; i++)
	for (i = 0; i <= CPU2DSP_MAX_CMD; i++)
		init_completion(&me->completions[i]);

	me->pending_dsp2cpu_cmd.type = CVP_INVALID_RPMSG_TYPE;
	me->pending_dsp2cpu_rsp.type = CVP_INVALID_RPMSG_TYPE;

	rc = register_rpmsg_driver(&cvp_dsp_rpmsg_client);
	if (rc) {
		dprintk(CVP_ERR,
@@ -459,7 +560,13 @@ int cvp_dsp_device_init(void)
			__func__, rc);
		goto register_bail;
	}

	snprintf(tname, sizeof(tname), "cvp-dsp-thread");
	me->dsp_thread = kthread_run(cvp_dsp_thread, me, tname);
	if (!me->dsp_thread) {
		dprintk(CVP_ERR, "%s create %s fail", __func__, tname);
		rc = -ECHILD;
		goto register_bail;
	}
	me->state = DSP_UNINIT;
	return 0;

@@ -470,11 +577,15 @@ int cvp_dsp_device_init(void)
void cvp_dsp_device_exit(void)
{
	struct cvp_dsp_apps *me = &gfa_cv;
	int i;

	mutex_lock(&me->lock);
	me->state = DSP_INVALID;
	mutex_unlock(&me->lock);

	for (i = 0; i <= CPU2DSP_MAX_CMD; i++)
		complete_all(&me->completions[i]);

	mutex_destroy(&me->lock);
	unregister_rpmsg_driver(&cvp_dsp_rpmsg_client);
}
+34 −8
Original line number Diff line number Diff line
@@ -17,20 +17,25 @@
#define HLOS_VM_NUM 1
#define DSP_VM_NUM 2
#define CVP_DSP_MAX_RESERVED 5
#define CVP_DSP2CPU_RESERVED 8
#define CVP_DSP_RESPONSE_TIMEOUT 1000
#define CVP_INVALID_RPMSG_TYPE 0xBADDFACE

int cvp_dsp_device_init(void);
void cvp_dsp_device_exit(void);
void cvp_dsp_send_hfi_queue(void);

enum DSP_COMMAND {
	CVP_DSP_SEND_HFI_QUEUE = 0,
	CVP_DSP_SUSPEND = 1,
	CVP_DSP_RESUME = 2,
	CVP_DSP_SHUTDOWN = 3,
	CVP_DSP_REGISTER_BUFFER = 4,
	CVP_DSP_DEREGISTER_BUFFER = 5,
	CVP_DSP_MAX_CMD
enum CVP_DSP_COMMAND {
	CPU2DSP_SEND_HFI_QUEUE = 0,
	CPU2DSP_SUSPEND = 1,
	CPU2DSP_RESUME = 2,
	CPU2DSP_SHUTDOWN = 3,
	CPU2DSP_REGISTER_BUFFER = 4,
	CPU2DSP_DEREGISTER_BUFFER = 5,
	CPU2DSP_MAX_CMD = 6,
	DSP2CPU_POWERON = 6,
	DSP2CPU_POWEROFF = 7,
	CVP_DSP_MAX_CMD = 8,
};

struct cvp_dsp_cmd_msg {
@@ -56,6 +61,27 @@ struct cvp_dsp_rsp_msg {
	uint32_t reserved[CVP_DSP_MAX_RESERVED];
};

struct cvp_dsp2cpu_cmd_msg {
	uint32_t type;
	uint32_t ver;
	uint32_t len;
	uint32_t data[CVP_DSP2CPU_RESERVED];
};

struct cvp_dsp_apps {
	struct mutex lock;
	struct rpmsg_device *chan;
	uint32_t state;
	bool hyp_assigned;
	uint64_t addr;
	uint32_t size;
	struct completion completions[CPU2DSP_MAX_CMD + 1];
	struct cvp_dsp2cpu_cmd_msg pending_dsp2cpu_cmd;
	struct cvp_dsp_rsp_msg pending_dsp2cpu_rsp;
	struct task_struct *dsp_thread;
};

extern struct cvp_dsp_apps gfa_cv;
/*
 * API for CVP driver to suspend CVP session during
 * power collapse