void sst_process_mad_ops(struct work_struct *work) { struct mad_ops_wq *mad_ops = container_of(work, struct mad_ops_wq, wq); int retval = 0; switch (mad_ops->control_op) { case SST_SND_PAUSE: retval = sst_pause_stream(mad_ops->stream_id); break; case SST_SND_RESUME: retval = sst_resume_stream(mad_ops->stream_id); break; case SST_SND_DROP: retval = sst_drop_stream(mad_ops->stream_id); break; case SST_SND_START: pr_debug("SST Debug: start stream\n"); retval = sst_start_stream(mad_ops->stream_id); break; case SST_SND_STREAM_PROCESS: pr_debug("play/capt frames...\n"); break; default: pr_err(" wrong control_ops reported\n"); } return; }
static int sst_stream_drop(struct device *dev, int str_id) { struct stream_info *str_info; struct intel_sst_drv *ctx = dev_get_drvdata(dev); if (ctx->sst_state != SST_FW_RUNNING) return 0; str_info = get_stream_info(ctx, str_id); if (!str_info) return -EINVAL; str_info->prev = STREAM_UN_INIT; str_info->status = STREAM_INIT; return sst_drop_stream(ctx, str_id); }
/** * sst_process_message - Processes message from SST * * @work: Pointer to work structure * * This function is scheduled by ISR * It take a msg from process_queue and does action based on msg */ void sst_process_message(struct work_struct *work) { struct sst_ipc_msg_wq *msg = container_of(work, struct sst_ipc_msg_wq, wq); int str_id = msg->header.part.str_id; pr_debug("IPC process for %x\n", msg->header.full); /* based on msg in list call respective handler */ switch (msg->header.part.msg_id) { case IPC_SST_BUF_UNDER_RUN: case IPC_SST_BUF_OVER_RUN: if (sst_validate_strid(str_id)) { pr_err("stream id %d invalid\n", str_id); break; } pr_err("Buffer under/overrun for %d\n", msg->header.part.str_id); pr_err("Got Underrun & not to send data...ignore\n"); break; case IPC_SST_GET_PLAY_FRAMES: if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) { struct stream_info *stream ; if (sst_validate_strid(str_id)) { pr_err("strid %d invalid\n", str_id); break; } /* call sst_play_frame */ stream = &sst_drv_ctx->streams[str_id]; pr_debug("sst_play_frames for %d\n", msg->header.part.str_id); mutex_lock(&sst_drv_ctx->streams[str_id].lock); sst_play_frame(msg->header.part.str_id); mutex_unlock(&sst_drv_ctx->streams[str_id].lock); break; } else pr_err("sst_play_frames for Penwell!!\n"); case IPC_SST_GET_CAPT_FRAMES: if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) { struct stream_info *stream; /* call sst_capture_frame */ if (sst_validate_strid(str_id)) { pr_err("str id %d invalid\n", str_id); break; } stream = &sst_drv_ctx->streams[str_id]; pr_debug("sst_capture_frames for %d\n", msg->header.part.str_id); mutex_lock(&stream->lock); if (stream->mmapped == false && stream->src == SST_DRV) { pr_debug("waking up block for copy.\n"); stream->data_blk.ret_code = 0; stream->data_blk.condition = true; stream->data_blk.on = false; wake_up(&sst_drv_ctx->wait_queue); } else sst_capture_frame(msg->header.part.str_id); mutex_unlock(&stream->lock); } else pr_err("sst_play_frames for Penwell!!\n"); break; case IPC_IA_PRINT_STRING: pr_debug("been asked to print something by fw\n"); /* TBD */ break; case IPC_IA_FW_INIT_CMPLT: { /* send next data to FW */ process_fw_init(msg); break; } case IPC_SST_STREAM_PROCESS_FATAL_ERR: if (sst_validate_strid(str_id)) { pr_err("stream id %d invalid\n", str_id); break; } pr_err("codec fatal error %x stream %d...\n", msg->header.full, msg->header.part.str_id); pr_err("Dropping the stream\n"); sst_drop_stream(msg->header.part.str_id); break; case IPC_IA_LPE_GETTING_STALLED: sst_drv_ctx->lpe_stalled = 1; break; case IPC_IA_LPE_UNSTALLED: sst_drv_ctx->lpe_stalled = 0; break; default: /* Illegal case */ pr_err("Unhandled msg %x header %x\n", msg->header.part.msg_id, msg->header.full); } sst_clear_interrupt(); return; }
static int sst_cdev_stream_drop(struct device *dev, unsigned int str_id) { struct intel_sst_drv *ctx = dev_get_drvdata(dev); return sst_drop_stream(ctx, str_id); }