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);
}
Exemplo n.º 2
0
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;
}