static int chd_dec_open(struct inode *in, struct file *fd) { struct crystalhd_adp *adp = chd_get_adp(); int rc = 0; enum BC_STATUS sts = BC_STS_SUCCESS; struct crystalhd_user *uc = NULL; BCMLOG_ENTER; if (!adp) { BCMLOG_ERR("Invalid adp\n"); return -EINVAL; } if (adp->cfg_users >= BC_LINK_MAX_OPENS) { BCMLOG(BCMLOG_INFO, "Already in use.%d\n", adp->cfg_users); return -EBUSY; } sts = crystalhd_user_open(&adp->cmds, &uc); if (sts != BC_STS_SUCCESS) { BCMLOG_ERR("cmd_user_open - %d\n", sts); rc = -EBUSY; } adp->cfg_users++; fd->private_data = uc; return rc; }
/* API interfaces */ static long chd_dec_ioctl(struct file *fd, unsigned int cmd, unsigned long ua) { struct crystalhd_adp *adp = chd_get_adp(); crystalhd_cmd_proc cproc; struct crystalhd_user *uc; int ret; if (!adp || !fd) { BCMLOG_ERR("Invalid adp\n"); return -EINVAL; } uc = (struct crystalhd_user *)fd->private_data; if (!uc) { BCMLOG_ERR("Failed to get uc\n"); return -ENODATA; } lock_kernel(); cproc = crystalhd_get_cmd_proc(&adp->cmds, cmd, uc); if (!cproc) { BCMLOG_ERR("Unhandled command: %d\n", cmd); unlock_kernel(); return -EINVAL; } ret = chd_dec_api_cmd(adp, ua, uc->uid, cmd, cproc); unlock_kernel(); return ret; }
static int chd_dec_open(struct inode *in, struct file *fd) { struct crystalhd_adp *adp = chd_get_adp(); struct device *dev = &adp->pdev->dev; int rc = 0; BC_STATUS sts = BC_STS_SUCCESS; struct crystalhd_user *uc = NULL; dev_dbg(dev, "Entering %s\n", __func__); if (!adp) { dev_err(dev, "Invalid adp\n"); return -EINVAL; } if (adp->cfg_users >= BC_LINK_MAX_OPENS) { dev_info(dev, "Already in use.%d\n", adp->cfg_users); return -EBUSY; } sts = crystalhd_user_open(&adp->cmds, &uc); if (sts != BC_STS_SUCCESS) { dev_err(dev, "cmd_user_open - %d\n", sts); rc = -EBUSY; } else { adp->cfg_users++; fd->private_data = uc; } return rc; }
static long chd_dec_ioctl(struct file *fd, unsigned int cmd, unsigned long ua) #endif { struct crystalhd_adp *adp = chd_get_adp(); struct device *dev = &adp->pdev->dev; crystalhd_cmd_proc cproc; struct crystalhd_user *uc; dev_dbg(dev, "Entering %s\n", __func__); if (!adp || !fd) { dev_err(chddev(), "Invalid adp\n"); return -EINVAL; } uc = fd->private_data; if (!uc) { dev_err(chddev(), "Failed to get uc\n"); return -ENODATA; } cproc = crystalhd_get_cmd_proc(&adp->cmds, cmd, uc); if (!cproc && !(adp->cmds.state & BC_LINK_SUSPEND)) { dev_err(chddev(), "Unhandled command: %d\n", cmd); return -EINVAL; } return chd_dec_api_cmd(adp, ua, uc->uid, cmd, cproc); }
static int chd_dec_close(struct inode *in, struct file *fd) { struct crystalhd_adp *adp = chd_get_adp(); struct crystalhd_user *uc; if (!adp) { BCMLOG_ERR("Invalid adp\n"); return -EINVAL; } uc = fd->private_data; if (!uc) { BCMLOG_ERR("Failed to get uc\n"); return -ENODATA; } crystalhd_user_close(&adp->cmds, uc); adp->cfg_users--; return 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; }