/**
* sst_drain_stream - Send msg for draining stream
* @str_id:		stream ID
*
* This function is called by any function which wants to drain
* a stream.
*/
int sst_drain_stream(int str_id, bool partial_drain)
{
	int retval = 0, pvt_id, len;
	struct ipc_post *msg = NULL;
	struct stream_info *str_info;
	struct intel_sst_ops *ops;
	unsigned long irq_flags;
	struct sst_block *block = NULL;
	struct ipc_dsp_hdr dsp_hdr;

	pr_debug("SST DBG:sst_drain_stream for %d\n", str_id);
	str_info = get_stream_info(str_id);
	if (!str_info)
		return -EINVAL;
	ops = sst_drv_ctx->ops;
	if (str_info->status != STREAM_RUNNING &&
		str_info->status != STREAM_INIT &&
		str_info->status != STREAM_PAUSED) {
			pr_err("SST ERR: BADQRC for stream = %d\n",
				       str_info->status);
			return -EBADRQC;
	}

	if (!sst_drv_ctx->use_32bit_ops) {
		pvt_id = sst_assign_pvt_id(sst_drv_ctx);
		retval = sst_create_block_and_ipc_msg(&msg, true,
				sst_drv_ctx, &block, IPC_CMD, pvt_id);
		if (retval)
			return retval;
		sst_fill_header_mrfld(&msg->mrfld_header, IPC_CMD,
				str_info->task_id, 1, pvt_id);
		pr_debug("header:%x\n",
			(unsigned int)msg->mrfld_header.p.header_high.full);
		msg->mrfld_header.p.header_high.part.res_rqd = 1;

		len = sizeof(u8) + sizeof(dsp_hdr);
		msg->mrfld_header.p.header_low_payload = len;
		sst_fill_header_dsp(&dsp_hdr, IPC_IA_DRAIN_STREAM_MRFLD,
					str_info->pipe_id, sizeof(u8));
		memcpy(msg->mailbox_data, &dsp_hdr, sizeof(dsp_hdr));
		memcpy(msg->mailbox_data + sizeof(dsp_hdr),
				&partial_drain, sizeof(u8));
	} else {
		retval = sst_create_block_and_ipc_msg(&msg, false,
				sst_drv_ctx, &block,
				IPC_IA_DRAIN_STREAM, str_id);
		if (retval)
			return retval;
		sst_fill_header(&msg->header, IPC_IA_DRAIN_STREAM, 0, str_id);
		msg->header.part.data = partial_drain;
	}
	spin_lock_irqsave(&sst_drv_ctx->ipc_spin_lock, irq_flags);
	list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
	spin_unlock_irqrestore(&sst_drv_ctx->ipc_spin_lock, irq_flags);
	ops->post_message(&sst_drv_ctx->ipc_post_msg_wq);
	retval = sst_wait_interruptible(sst_drv_ctx, block);
	sst_free_block(sst_drv_ctx, block);
	return retval;
}
Beispiel #2
0
/**
* sst_drain_stream - Send msg for draining stream
* @str_id:		stream ID
*
* This function is called by any function which wants to drain
* a stream.
*/
int sst_drain_stream(int str_id)
{
	int retval = 0;
	struct ipc_post *msg = NULL;
	struct stream_info *str_info;
	struct intel_sst_ops *ops;
	unsigned long irq_flags;

	pr_debug("SST DBG:sst_drain_stream for %d\n", str_id);
	str_info = get_stream_info(str_id);
	if (!str_info)
		return -EINVAL;
	ops = sst_drv_ctx->ops;
	if (str_info->status != STREAM_RUNNING &&
		str_info->status != STREAM_INIT &&
		str_info->status != STREAM_PAUSED) {
			pr_err("SST ERR: BADQRC for stream = %d\n",
				       str_info->status);
			return -EBADRQC;
	}

	if (str_info->status == STREAM_INIT) {
		if (sst_create_short_msg(&msg)) {
			pr_err("SST ERR: mem allocation failed\n");
			return -ENOMEM;
		}
		sst_fill_header(&msg->header, IPC_IA_DRAIN_STREAM, 0, str_id);
		spin_lock_irqsave(&sst_drv_ctx->ipc_spin_lock, irq_flags);
		list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
		spin_unlock_irqrestore(&sst_drv_ctx->ipc_spin_lock, irq_flags);
		ops->post_message(&sst_drv_ctx->ipc_post_msg_wq);
		str_info->data_blk.condition = false;
		str_info->data_blk.ret_code = 0;
		str_info->data_blk.on = true;
		retval = sst_wait_interruptible(sst_drv_ctx,
						&str_info->data_blk);
	}
	return retval;
}