static enum BC_STATUS bc_cproc_flush_cap_buffs(struct crystalhd_cmd *ctx, struct crystalhd_ioctl_data *idata) { struct crystalhd_dio_req *dio = NULL; enum BC_STATUS sts = BC_STS_SUCCESS; struct BC_DEC_OUT_BUFF *frame; uint32_t count; if (!ctx || !idata) { BCMLOG_ERR("Invalid Arg!!\n"); return BC_STS_INV_ARG; } if (!(ctx->state & BC_LINK_CAP_EN)) return BC_STS_ERR_USAGE; /* We should ack flush even when we are in paused/suspend state */ if (!(ctx->state & BC_LINK_READY)) return crystalhd_hw_stop_capture(&ctx->hw_ctx); ctx->state &= ~(BC_LINK_CAP_EN|BC_LINK_FMT_CHG); frame = &idata->udata.u.DecOutData; for (count = 0; count < BC_RX_LIST_CNT; count++) { sts = crystalhd_hw_get_cap_buffer(&ctx->hw_ctx, &frame->PibInfo, &dio); if (sts != BC_STS_SUCCESS) break; crystalhd_unmap_dio(ctx->adp, dio); } return crystalhd_hw_stop_capture(&ctx->hw_ctx); }
static int chd_dec_close(struct inode *in, struct file *fd) { struct crystalhd_adp *adp = chd_get_adp(); struct device *dev = &adp->pdev->dev; struct crystalhd_cmd *ctx = &adp->cmds; struct crystalhd_user *uc; uint32_t mode; dev_dbg(dev, "Entering %s\n", __func__); if (!adp) { dev_err(dev, "Invalid adp\n"); return -EINVAL; } uc = fd->private_data; if (!uc) { dev_err(dev, "Failed to get uc\n"); return -ENODATA; } /* Check and close only if we have not flush/closed before */ /* This is needed because release is not guarenteed to be called immediately on close, * if duplicate file handles exist due to fork etc. This causes problems with close and re-open of the device immediately */ if(uc->in_use) { mode = uc->mode; ctx->user[uc->uid].mode = DTS_MODE_INV; ctx->user[uc->uid].in_use = 0; dev_info(chddev(), "Closing user[%x] handle with mode %x\n", uc->uid, mode); if (((mode & 0xFF) == DTS_DIAG_MODE) || ((mode & 0xFF) == DTS_PLAYBACK_MODE) || ((bc_get_userhandle_count(ctx) == 0) && (ctx->hw_ctx != NULL))) { ctx->cin_wait_exit = 1; ctx->pwr_state_change = BC_HW_RUNNING; /* Stop the HW Capture just in case flush did not get called before stop */ /* And only if we had actually started it */ if(ctx->hw_ctx->rx_freeq != NULL) { crystalhd_hw_stop_capture(ctx->hw_ctx, true); crystalhd_hw_free_dma_rings(ctx->hw_ctx); } if(ctx->adp->fill_byte_pool) crystalhd_destroy_dio_pool(ctx->adp); if(ctx->adp->elem_pool_head) crystalhd_delete_elem_pool(ctx->adp); ctx->state = BC_LINK_INVALID; crystalhd_hw_close(ctx->hw_ctx, ctx->adp); kfree(ctx->hw_ctx); ctx->hw_ctx = NULL; } uc->in_use = 0; if(adp->cfg_users > 0) adp->cfg_users--; } return 0; }