u32 send_rtac_asm_apr(void *buf, u32 opcode)
{
	s32	result;
	u32	user_buf_size = 0;
	u32	bytes_returned = 0;
	u32	session_id = 0;
	u32	payload_size;
	u32	data_size = 0;
	struct apr_hdr		asm_params;
	pr_debug("%s\n", __func__);

	if (rtac_cal[ASM_RTAC_CAL].map_data.ion_handle == NULL) {
		result = rtac_allocate_cal_buffer(ASM_RTAC_CAL);
		if (result < 0) {
			pr_err("%s: allocate buffer failed!",
				__func__);
			goto done;
		}
	}

	if (rtac_cal[ASM_RTAC_CAL].map_data.map_handle == 0) {
		result = rtac_map_cal_buffer(ASM_RTAC_CAL);
		if (result < 0) {
			pr_err("%s: map buffer failed!",
				__func__);
			goto done;
		}
	}

	if (copy_from_user(&user_buf_size, (void *)buf,
						sizeof(user_buf_size))) {
		pr_err("%s: Copy from user failed! buf = 0x%x\n",
		       __func__, (unsigned int)buf);
		goto done;
	}
	if (user_buf_size <= 0) {
		pr_err("%s: Invalid buffer size = %d\n",
			__func__, user_buf_size);
		goto done;
	}

	if (copy_from_user(&payload_size, buf + sizeof(u32), sizeof(u32))) {
		pr_err("%s: Could not copy payload size from user buffer\n",
			__func__);
		goto done;
	}

	if (copy_from_user(&session_id, buf + 2 * sizeof(u32), sizeof(u32))) {
		pr_err("%s: Could not copy session id from user buffer\n",
			__func__);
		goto done;
	}
	if (session_id >= (SESSION_MAX + 1)) {
		pr_err("%s: Invalid Session = %d\n", __func__, session_id);
		goto done;
	}

	mutex_lock(&rtac_asm_apr_mutex);
	if (rtac_asm_apr_data[session_id].apr_handle == NULL) {
		pr_err("%s: APR not initialized\n", __func__);
		goto err;
	}

	if (opcode == ASM_STREAM_CMD_SET_PP_PARAMS_V2) {
		
		
		data_size = payload_size - 4 * sizeof(u32);
		if (data_size > rtac_cal[ASM_RTAC_CAL].map_data.map_size) {
			pr_err("%s: Invalid data size = %d\n",
				__func__, data_size);
			goto err; 
		}
		payload_size = 4 * sizeof(u32);

		
		if (copy_from_user((void *)
				rtac_cal[ASM_RTAC_CAL].cal_data.kvaddr,
				buf + 7 * sizeof(u32), data_size)) {
			pr_err("%s: Could not copy payload from user buffer\n",
				__func__);
			goto err;
		}
		
		rtac_asm_buffer[8] = data_size;

	} else {
		if (payload_size > MAX_PAYLOAD_SIZE) {
			pr_err("%s: Invalid payload size = %d\n",
				__func__, payload_size);
			goto err; 
		}

		
		if (copy_from_user(rtac_asm_buffer +
				sizeof(asm_params)/sizeof(u32),
				buf + 3 * sizeof(u32), payload_size)) {
			pr_err("%s: Could not copy payload from user buffer\n",
				__func__);
			goto err;
		}
	}

	
	asm_params.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
		APR_HDR_LEN(20), APR_PKT_VER);
	asm_params.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
		payload_size);
	asm_params.src_svc = q6asm_get_apr_service_id(session_id);
	if (asm_params.src_svc == -EINVAL) {
		pr_err("%s: Could not get service id form session %d", __func__, session_id);
		goto err;
	}

	asm_params.src_domain = APR_DOMAIN_APPS;
	asm_params.src_port = (session_id << 8) | 0x0001;
	asm_params.dest_svc = APR_SVC_ASM;
	asm_params.dest_domain = APR_DOMAIN_ADSP;
	asm_params.dest_port = (session_id << 8) | 0x0001;
	asm_params.token = session_id;
	asm_params.opcode = opcode;

	
	rtac_asm_buffer[5] = rtac_cal[ASM_RTAC_CAL].cal_data.paddr;
	rtac_asm_buffer[6] = 0;
	rtac_asm_buffer[7] = rtac_cal[ASM_RTAC_CAL].map_data.map_handle;

	memcpy(rtac_asm_buffer, &asm_params, sizeof(asm_params));
	atomic_set(&rtac_asm_apr_data[session_id].cmd_state, 1);

	pr_debug("%s: Sending RTAC command ioctl 0x%x, paddr 0x%x\n",
		__func__, opcode,
		rtac_cal[ASM_RTAC_CAL].cal_data.paddr);

	result = apr_send_pkt(rtac_asm_apr_data[session_id].apr_handle,
				(uint32_t *)rtac_asm_buffer);
	if (result < 0) {
		pr_err("%s: Set params failed session = %d\n",
			__func__, session_id);
		goto err;
	}

	
	result = wait_event_timeout(rtac_asm_apr_data[session_id].cmd_wait,
		(atomic_read(&rtac_asm_apr_data[session_id].cmd_state) == 0),
		5 * HZ);
	if (!result) {
		pr_err("%s: Set params timed out session = %d\n",
			__func__, session_id);
		goto err;
	}
	if (atomic_read(&rtac_common.apr_err_code)) {
		pr_err("%s: DSP returned error code = %d, opcode = 0x%x\n",
			__func__, atomic_read(&rtac_common.apr_err_code),
			opcode);
		goto err;
	}

	if (opcode == ASM_STREAM_CMD_GET_PP_PARAMS_V2) {
		bytes_returned = ((u32 *)rtac_cal[ASM_RTAC_CAL].cal_data.
			kvaddr)[2] + 3 * sizeof(u32);

		if (bytes_returned > user_buf_size) {
			pr_err("%s: User buf not big enough, size = 0x%x, returned size = 0x%x\n",
				__func__, user_buf_size, bytes_returned);
			goto err;
		}

		if (copy_to_user(buf, (void *)
				rtac_cal[ASM_RTAC_CAL].cal_data.kvaddr,
				bytes_returned)) {
			pr_err("%s: Could not copy buffer to user,size = %d\n",
				 __func__, bytes_returned);
			goto err;
		}
	} else {
		bytes_returned = data_size;
	}
err:
	mutex_unlock(&rtac_asm_apr_mutex);
done:
	return bytes_returned;
}
Esempio n. 2
0
u32 send_rtac_asm_apr(void *buf, u32 opcode)
{
	s32	result;
	u32	count = 0;
	u32	bytes_returned = 0;
	u32	session_id = 0;
	u32	payload_size;
	struct apr_hdr	asm_params;
	pr_debug("%s\n", __func__);

	if (copy_from_user(&count, (void *)buf, sizeof(count))) {
		pr_err("%s: Copy to user failed! buf = 0x%x\n",
		       __func__, (unsigned int)buf);
		result = -EFAULT;
		goto done;
	}

	if (count <= 0) {
		pr_err("%s: Invalid buffer size = %d\n", __func__, count);
		goto done;
	}

	if (copy_from_user(&payload_size, buf + sizeof(u32), sizeof(u32))) {
		pr_err("%s: Could not copy payload size from user buffer\n",
			__func__);
		goto done;
	}

	if (payload_size > MAX_PAYLOAD_SIZE) {
		pr_err("%s: Invalid payload size = %d\n",
			__func__, payload_size);
		goto done;
	}

	if (copy_from_user(&session_id, buf + 2 * sizeof(u32), sizeof(u32))) {
		pr_err("%s: Could not copy session id from user buffer\n",
			__func__);
		goto done;
	}
	if (session_id > (SESSION_MAX + 1)) {
		pr_err("%s: Invalid Session = %d\n", __func__, session_id);
		goto done;
	}

	mutex_lock(&rtac_asm_apr_mutex);
	if (session_id < SESSION_MAX+1) {
		if (rtac_asm_apr_data[session_id].apr_handle == NULL) {
			pr_err("%s: APR not initialized\n", __func__);
			goto err;
		}
	}

	
	rtac_asm_user_buf_size = count;

	
	if (copy_from_user(rtac_asm_buffer + sizeof(asm_params),
		buf + 3 * sizeof(u32), payload_size)) {
		pr_err("%s: Could not copy payload from user buffer\n",
			__func__);
		goto err;
	}

	
	asm_params.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
		APR_HDR_LEN(20), APR_PKT_VER);
	asm_params.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
		payload_size);
	asm_params.src_svc = q6asm_get_apr_service_id(session_id);
	asm_params.src_domain = APR_DOMAIN_APPS;
	asm_params.src_port = (session_id << 8) | 0x0001;
	asm_params.dest_svc = APR_SVC_ASM;
	asm_params.dest_domain = APR_DOMAIN_ADSP;
	asm_params.dest_port = (session_id << 8) | 0x0001;
	asm_params.token = session_id;
	asm_params.opcode = opcode;

	memcpy(rtac_asm_buffer, &asm_params, sizeof(asm_params));
	if (session_id < SESSION_MAX+1)
		atomic_set(&rtac_asm_apr_data[session_id].cmd_state, 1);

	pr_debug("%s: Sending RTAC command size = %d, session_id=%d\n",
		__func__, asm_params.pkt_size, session_id);

	result = apr_send_pkt(rtac_asm_apr_data[session_id].apr_handle,
				(uint32_t *)rtac_asm_buffer);
	if (result < 0) {
		pr_err("%s: Set params failed session = %d\n",
			__func__, session_id);
		goto err;
	}

	
	result = wait_event_timeout(rtac_asm_apr_data[session_id].cmd_wait,
		(atomic_read(&rtac_asm_apr_data[session_id].cmd_state) == 0),
		5 * HZ);
	mutex_unlock(&rtac_asm_apr_mutex);
	if (!result) {
		pr_err("%s: Set params timed out session = %d\n",
			__func__, session_id);
		goto done;
	}

	if (rtac_asm_payload_size != 0) {
		if (copy_to_user(buf, rtac_asm_buffer,
			rtac_asm_payload_size + sizeof(u32))) {
			pr_err("%s: Could not copy buffer to user,size = %d\n",
				 __func__, payload_size);
			goto done;
		}
	}

	
	if (opcode == ASM_STREAM_CMD_GET_PP_PARAMS)
		bytes_returned = rtac_asm_payload_size;
	else
		bytes_returned = payload_size;
done:
	return bytes_returned;
err:
	mutex_unlock(&rtac_asm_apr_mutex);
	return bytes_returned;
}