int sst_alloc_stream_mfld(char *params) { struct ipc_post *msg = NULL; struct snd_sst_alloc_params_mfld alloc_param; struct snd_sst_params *str_params; struct stream_info *str_info; unsigned int stream_ops, device; struct snd_sst_stream_params_mfld *sparams; unsigned int pcm_slot = 0, num_ch, pcm_wd_sz, sfreq; int str_id; u8 codec; u32 rb_size, rb_addr, period_count; unsigned long irq_flags; pr_debug("In %s\n", __func__); BUG_ON(!params); str_params = (struct snd_sst_params *)params; stream_ops = str_params->ops; codec = str_params->codec; device = str_params->device_type; num_ch = sst_get_num_channel(str_params); sfreq = sst_get_sfreq(str_params); pcm_wd_sz = sst_get_wdsize(str_params); rb_size = str_params->aparams.ring_buf_info[0].size; rb_addr = str_params->aparams.ring_buf_info[0].addr; period_count = str_params->aparams.frag_size / 4; pr_debug("period_size = %d\n", period_count); pr_debug("ring_buf_addr = 0x%x\n", rb_addr); pr_debug("ring_buf_size = %d\n", rb_size); pr_debug("device_type=%d\n", device); pr_debug("sfreq =%d\n", sfreq); pr_debug("stream_ops%d codec%d device%d\n", stream_ops, codec, device); sparams = kzalloc(sizeof(*sparams), GFP_KERNEL); if (!sparams) { pr_err("Unable to allocate snd_sst_stream_params\n"); return -ENOMEM; } sparams->uc.pcm_params.codec = codec; sparams->uc.pcm_params.num_chan = num_ch; sparams->uc.pcm_params.pcm_wd_sz = pcm_wd_sz; sparams->uc.pcm_params.reserved = 0; sparams->uc.pcm_params.sfreq = sfreq; sparams->uc.pcm_params.ring_buffer_size = rb_size; sparams->uc.pcm_params.period_count = period_count; sparams->uc.pcm_params.ring_buffer_addr = rb_addr; if (sst_check_device_type(device, num_ch, &pcm_slot)) { kfree(sparams); return -EINVAL; } mutex_lock(&sst_drv_ctx->stream_lock); str_id = device; mutex_unlock(&sst_drv_ctx->stream_lock); pr_debug("slot %x\n", pcm_slot); /*allocate device type context*/ sst_init_stream(&sst_drv_ctx->streams[str_id], codec, str_id, stream_ops, pcm_slot); /* send msg to FW to allocate a stream */ if (sst_create_large_msg(&msg)) { kfree(sparams); return -ENOMEM; } alloc_param.str_type.codec_type = codec; alloc_param.str_type.str_type = SST_STREAM_TYPE_MUSIC; alloc_param.str_type.operation = stream_ops; alloc_param.str_type.protected_str = 0; /* non drm */ alloc_param.str_type.time_slots = pcm_slot; alloc_param.str_type.reserved = 0; alloc_param.str_type.result = 0; sst_fill_header(&msg->header, IPC_IA_ALLOC_STREAM, 1, str_id); msg->header.part.data = sizeof(alloc_param) + sizeof(u32); memcpy(&alloc_param.stream_params, sparams, sizeof(*sparams)); kfree(sparams); memcpy(msg->mailbox_data, &msg->header, sizeof(u32)); memcpy(msg->mailbox_data + sizeof(u32), &alloc_param, sizeof(alloc_param)); str_info = &sst_drv_ctx->streams[str_id]; str_info->ctrl_blk.condition = false; str_info->ctrl_blk.ret_code = 0; str_info->ctrl_blk.on = true; 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); sst_drv_ctx->ops->post_message(&sst_drv_ctx->ipc_post_msg_wq); pr_debug("SST DBG:alloc stream done\n"); return str_id; }
int sst_alloc_stream_mrfld(struct intel_sst_drv *sst_drv_ctx, void *params) { struct snd_sst_alloc_mrfld alloc_param; struct snd_sst_params *str_params; struct snd_sst_tstamp fw_tstamp; struct stream_info *str_info; struct snd_sst_alloc_response *response; unsigned int str_id, pipe_id, task_id; int i, num_ch, ret = 0; void *data = NULL; dev_dbg(sst_drv_ctx->dev, "Enter\n"); BUG_ON(!params); str_params = (struct snd_sst_params *)params; memset(&alloc_param, 0, sizeof(alloc_param)); alloc_param.operation = str_params->ops; alloc_param.codec_type = str_params->codec; alloc_param.sg_count = str_params->aparams.sg_count; alloc_param.ring_buf_info[0].addr = str_params->aparams.ring_buf_info[0].addr; alloc_param.ring_buf_info[0].size = str_params->aparams.ring_buf_info[0].size; alloc_param.frag_size = str_params->aparams.frag_size; memcpy(&alloc_param.codec_params, &str_params->sparams, sizeof(struct snd_sst_stream_params)); /* * fill channel map params for multichannel support. * Ideally channel map should be received from upper layers * for multichannel support. * Currently hardcoding as per FW reqm. */ num_ch = sst_get_num_channel(str_params); for (i = 0; i < 8; i++) { if (i < num_ch) alloc_param.codec_params.uc.pcm_params.channel_map[i] = i; else alloc_param.codec_params.uc.pcm_params.channel_map[i] = 0xFF; } str_id = str_params->stream_id; str_info = get_stream_info(sst_drv_ctx, str_id); if (str_info == NULL) { dev_err(sst_drv_ctx->dev, "get stream info returned null\n"); return -EINVAL; } pipe_id = str_params->device_type; task_id = str_params->task; sst_drv_ctx->streams[str_id].pipe_id = pipe_id; sst_drv_ctx->streams[str_id].task_id = task_id; sst_drv_ctx->streams[str_id].num_ch = num_ch; if (sst_drv_ctx->info.lpe_viewpt_rqd) alloc_param.ts = sst_drv_ctx->info.mailbox_start + sst_drv_ctx->tstamp + (str_id * sizeof(fw_tstamp)); else alloc_param.ts = sst_drv_ctx->mailbox_add + sst_drv_ctx->tstamp + (str_id * sizeof(fw_tstamp)); dev_dbg(sst_drv_ctx->dev, "alloc tstamp location = 0x%x\n", alloc_param.ts); dev_dbg(sst_drv_ctx->dev, "assigned pipe id 0x%x to task %d\n", pipe_id, task_id); /* allocate device type context */ sst_init_stream(&sst_drv_ctx->streams[str_id], alloc_param.codec_type, str_id, alloc_param.operation, 0); dev_info(sst_drv_ctx->dev, "Alloc for str %d pipe %#x\n", str_id, pipe_id); ret = sst_prepare_and_post_msg(sst_drv_ctx, task_id, IPC_CMD, IPC_IA_ALLOC_STREAM_MRFLD, pipe_id, sizeof(alloc_param), &alloc_param, data, true, true, false, true); if (ret < 0) { dev_err(sst_drv_ctx->dev, "FW alloc failed ret %d\n", ret); /* alloc failed, so reset the state to uninit */ str_info->status = STREAM_UN_INIT; str_id = ret; } else if (data) { response = (struct snd_sst_alloc_response *)data; ret = response->str_type.result; if (!ret) goto out; dev_err(sst_drv_ctx->dev, "FW alloc failed ret %d\n", ret); if (ret == SST_ERR_STREAM_IN_USE) { dev_err(sst_drv_ctx->dev, "FW not in clean state, send free for:%d\n", str_id); sst_free_stream(sst_drv_ctx, str_id); } str_id = -ret; } out: kfree(data); return str_id; }
/** * sst_alloc_stream - Send msg for a new stream ID * * @params: stream params * @stream_ops: operation of stream PB/capture * @codec: codec for stream * @device: device stream to be allocated for * * This function is called by any function which wants to start * a new stream. This also check if a stream exists which is idle * it initializes idle stream id to this request */ int sst_alloc_stream_clv(char *params) { struct ipc_post *msg = NULL; struct snd_sst_alloc_params alloc_param; unsigned int pcm_slot = 0x03, num_ch; int str_id; struct snd_sst_params *str_params; struct snd_sst_stream_params *sparams; struct snd_sst_alloc_params_ext *aparams; struct stream_info *str_info; unsigned int stream_ops, device; unsigned long irq_flags; u8 codec; pr_debug("In %s\n", __func__); BUG_ON(!params); str_params = (struct snd_sst_params *)params; stream_ops = str_params->ops; codec = str_params->codec; device = str_params->device_type; sparams = &str_params->sparams; aparams = &str_params->aparams; num_ch = sst_get_num_channel(str_params); pr_debug("period_size = %d\n", aparams->frag_size); pr_debug("ring_buf_addr = 0x%x\n", aparams->ring_buf_info[0].addr); pr_debug("ring_buf_size = %d\n", aparams->ring_buf_info[0].size); pr_debug("In alloc device_type=%d\n", str_params->device_type); pr_debug("In alloc sg_count =%d\n", aparams->sg_count); mutex_lock(&sst_drv_ctx->stream_lock); str_id = get_clv_stream_id(device); mutex_unlock(&sst_drv_ctx->stream_lock); if (str_id <= 0) return -EBUSY; /*allocate device type context*/ sst_init_stream(&sst_drv_ctx->streams[str_id], codec, str_id, stream_ops, pcm_slot); /* send msg to FW to allocate a stream */ if (sst_create_large_msg(&msg)) return -ENOMEM; alloc_param.str_type.codec_type = codec; alloc_param.str_type.str_type = SST_STREAM_TYPE_MUSIC; alloc_param.str_type.operation = stream_ops; alloc_param.str_type.protected_str = 0; /* non drm */ alloc_param.str_type.time_slots = pcm_slot; alloc_param.str_type.reserved = 0; alloc_param.str_type.result = 0; memcpy(&alloc_param.stream_params, sparams, sizeof(struct snd_sst_stream_params)); memcpy(&alloc_param.alloc_params, aparams, sizeof(struct snd_sst_alloc_params_ext)); if (sst_drv_ctx->pci_id == SST_CLV_PCI_ID) { sst_fill_header(&msg->header, IPC_IA_ALLOC_STREAM, 1, str_id); msg->header.part.data = sizeof(alloc_param) + sizeof(u32); memcpy(msg->mailbox_data, &msg->header, sizeof(u32)); memcpy(msg->mailbox_data + sizeof(u32), &alloc_param, sizeof(alloc_param)); } else { sst_fill_header_mrfld(&msg->mrfld_header, IPC_IA_ALLOC_STREAM, 1, str_id); msg->mrfld_header.p.header_low_payload = sizeof(alloc_param) + sizeof(u64); memcpy(msg->mailbox_data, &msg->mrfld_header.p.header_high.full, sizeof(u32)); memcpy(msg->mailbox_data + sizeof(u32), &msg->mrfld_header.p.header_low_payload, sizeof(u32)); memcpy(msg->mailbox_data + sizeof(u64), &alloc_param, sizeof(alloc_param)); } str_info = &sst_drv_ctx->streams[str_id]; str_info->ctrl_blk.condition = false; str_info->ctrl_blk.ret_code = 0; str_info->ctrl_blk.on = true; str_info->num_ch = num_ch; 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); sst_drv_ctx->ops->post_message(&sst_drv_ctx->ipc_post_msg_wq); return str_id; }
int sst_alloc_stream_mrfld(char *params, struct sst_block *block) { struct ipc_post *msg = NULL; struct snd_sst_alloc_mrfld alloc_param; struct ipc_dsp_hdr dsp_hdr; struct snd_sst_params *str_params; struct snd_sst_tstamp fw_tstamp; unsigned int str_id, pipe_id, pvt_id, task_id; u32 len = 0; struct stream_info *str_info; unsigned long irq_flags; int i, num_ch; pr_debug("In %s\n", __func__); BUG_ON(!params); str_params = (struct snd_sst_params *)params; memset(&alloc_param, 0, sizeof(alloc_param)); alloc_param.operation = str_params->ops; alloc_param.codec_type = str_params->codec; alloc_param.sg_count = str_params->aparams.sg_count; alloc_param.ring_buf_info[0].addr = str_params->aparams.ring_buf_info[0].addr; alloc_param.ring_buf_info[0].size = str_params->aparams.ring_buf_info[0].size; alloc_param.frag_size = str_params->aparams.frag_size; memcpy(&alloc_param.codec_params, &str_params->sparams, sizeof(struct snd_sst_stream_params)); /* fill channel map params for multichannel support. * Ideally channel map should be received from upper layers * for multichannel support. * Currently hardcoding as per FW reqm. */ num_ch = sst_get_num_channel(str_params); for (i = 0; i < 8; i++) { if (i < num_ch) alloc_param.codec_params.uc.pcm_params.channel_map[i] = i; else alloc_param.codec_params.uc.pcm_params.channel_map[i] = 0xFF; } str_id = str_params->stream_id; pipe_id = str_params->device_type; task_id = str_params->task; sst_drv_ctx->streams[str_id].pipe_id = pipe_id; sst_drv_ctx->streams[str_id].task_id = task_id; sst_drv_ctx->streams[str_id].num_ch = num_ch; pvt_id = sst_assign_pvt_id(sst_drv_ctx); alloc_param.ts = (struct snd_sst_tstamp *) (sst_drv_ctx->mailbox_add + sst_drv_ctx->tstamp + (str_id * sizeof(fw_tstamp))); pr_debug("alloc tstamp location = 0x%p\n", alloc_param.ts); pr_debug("assigned pipe id 0x%x to task %d\n", pipe_id, task_id); /*allocate device type context*/ sst_init_stream(&sst_drv_ctx->streams[str_id], alloc_param.codec_type, str_id, alloc_param.operation, 0); /* send msg to FW to allocate a stream */ if (sst_create_ipc_msg(&msg, true)) return -ENOMEM; block->drv_id = pvt_id; block->msg_id = IPC_CMD; sst_fill_header_mrfld(&msg->mrfld_header, IPC_CMD, task_id, 1, pvt_id); pr_debug("header:%x\n", msg->mrfld_header.p.header_high.full); msg->mrfld_header.p.header_high.part.res_rqd = 1; len = msg->mrfld_header.p.header_low_payload = sizeof(alloc_param) + sizeof(dsp_hdr); sst_fill_header_dsp(&dsp_hdr, IPC_IA_ALLOC_STREAM_MRFLD, pipe_id, sizeof(alloc_param)); memcpy(msg->mailbox_data, &dsp_hdr, sizeof(dsp_hdr)); memcpy(msg->mailbox_data + sizeof(dsp_hdr), &alloc_param, sizeof(alloc_param)); str_info = &sst_drv_ctx->streams[str_id]; pr_debug("header:%x\n", msg->mrfld_header.p.header_high.full); pr_debug("response rqd: %x", msg->mrfld_header.p.header_high.part.res_rqd); 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); pr_debug("calling post_message\n"); sst_drv_ctx->ops->post_message(&sst_drv_ctx->ipc_post_msg_wq); return str_id; }