static int mfc_release(struct inode *inode, struct file *file) { struct mfc_inst_ctx *mfc_ctx; struct mfc_dev *dev; int ret; mfc_ctx = (struct mfc_inst_ctx *)file->private_data; if (!mfc_ctx) return -EINVAL; dev = mfc_ctx->dev; mutex_lock(&dev->lock); #ifdef CONFIG_CPU_FREQ /* Release MFC & Bus Frequency lock for High resolution */ if (mfc_ctx->busfreq_flag == true){ atomic_dec(&dev->busfreq_lock_cnt); mfc_ctx->busfreq_flag = false; if (atomic_read(&dev->busfreq_lock_cnt) == 0){ /* release Freq lock back to normal */ s5pv310_busfreq_lock_free(DVFS_LOCK_ID_MFC); mfc_dbg("[%s] Bus Freq lock Released Normal !!\n",__func__); } } #endif file->private_data = NULL; printk(KERN_INFO"[%s]Released Instance id %d \n",__func__,mfc_ctx->id); dev->inst_ctx[mfc_ctx->id] = NULL; atomic_dec(&dev->inst_cnt); mfc_destroy_inst(mfc_ctx); if (atomic_read(&dev->inst_cnt) == 0) { ret = mfc_power_off(); if (ret < 0) { mfc_err("power disable failed.\n"); goto err_pwr_disable; } } else { #if defined(SYSMMU_MFC_ON) && !defined(CONFIG_VIDEO_MFC_VCM_UMP) mfc_clock_on(); sysmmu_tlb_invalidate(SYSMMU_MFC_L); sysmmu_tlb_invalidate(SYSMMU_MFC_R); mfc_clock_off(); #endif } ret = 0; err_pwr_disable: mutex_unlock(&dev->lock); return ret; }
static int mfc_open(struct inode *inode, struct file *file) { struct mfc_inst_ctx *mfc_ctx; int ret; enum mfc_ret_code retcode; /* prevent invalid reference */ file->private_data = NULL; mutex_lock(&mfcdev->lock); if (!mfcdev->fw.state) { if (mfcdev->fw.requesting) { printk(KERN_INFO "MFC F/W request is on-going, try again\n"); ret = -ENODEV; goto err_fw_state; } printk(KERN_INFO "MFC F/W is not exist, requesting...\n"); ret = request_firmware(&mfcdev->fw.info, MFC_FW_NAME, mfcdev->device); if (ret < 0) { printk(KERN_INFO "failed to copy MFC F/W during open\n"); goto err_fw_state; } } if (atomic_read(&mfcdev->inst_cnt) == 0) { /* reload F/W for first instance again */ mfcdev->fw.state = mfc_load_firmware(mfcdev->fw.info->data, mfcdev->fw.info->size); if (!mfcdev->fw.state) { printk(KERN_ERR "failed to load MFC F/W, MFC will not working\n"); ret = -ENODEV; goto err_fw_state; } else { printk(KERN_INFO "MFC F/W reloaded successfully (size: %d)\n", mfcdev->fw.info->size); } ret = mfc_power_on(); if (ret < 0) { mfc_err("power enable failed\n"); goto err_pwr_enable; } #ifndef CONFIG_PM_RUNTIME #ifdef SYSMMU_MFC_ON mfc_clock_on(); sysmmu_on(SYSMMU_MFC_L); sysmmu_on(SYSMMU_MFC_R); #ifdef CONFIG_VIDEO_MFC_VCM_UMP vcm_set_pgtable_base(VCM_DEV_MFC); #else /* CONFIG_S5P_VMEM or kernel virtual memory allocator */ sysmmu_set_tablebase_pgd(SYSMMU_MFC_L, __pa(swapper_pg_dir)); sysmmu_set_tablebase_pgd(SYSMMU_MFC_R, __pa(swapper_pg_dir)); /* * RMVME: the power-gating work really (on <-> off), * all TBL entry was invalidated already when the power off */ sysmmu_tlb_invalidate(SYSMMU_MFC_L); sysmmu_tlb_invalidate(SYSMMU_MFC_R); #endif mfc_clock_off(); #endif #endif /* MFC hardware initialization */ retcode = mfc_start(mfcdev); if (retcode != MFC_OK) { mfc_err("MFC H/W init failed: %d\n", retcode); ret = -ENODEV; goto err_start_hw; } /* * Indicate that MFC is running */ mfc_is_running = 1; } mfc_ctx = mfc_create_inst(); if (!mfc_ctx) { mfc_err("failed to create instance context\n"); ret = -ENOMEM; goto err_inst_ctx; } mfc_ctx->id = get_free_inst_id(mfcdev); if (mfc_ctx->id < 0) { mfc_destroy_inst(mfc_ctx); ret = -EINVAL; goto err_inst_ctx; } printk(KERN_INFO "MFC instance [%d] opened", mfc_ctx->id); mfc_ctx->dev = mfcdev; atomic_inc(&mfcdev->inst_cnt); mfcdev->inst_ctx[mfc_ctx->id] = mfc_ctx; file->private_data = (struct mfc_inst_ctx *)mfc_ctx; mutex_unlock(&mfcdev->lock); return 0; err_inst_ctx: err_start_hw: if (atomic_read(&mfcdev->inst_cnt) == 0) { if (mfc_power_off() < 0) mfc_err("power disable failed\n"); } err_pwr_enable: err_fw_state: mutex_unlock(&mfcdev->lock); return ret; }