typedef struct vpu_service_info {
struct wake_lock wake_lock;
struct delayed_work power_off_work;
- struct mutex lock;
- struct list_head waiting; /* link to link_reg in struct vpu_reg */
- struct list_head running; /* link to link_reg in struct vpu_reg */
+ struct mutex *lock;
+ struct list_head *waiting; /* link to link_reg in struct vpu_reg */
+ struct list_head *running; /* link to link_reg in struct vpu_reg */
struct list_head done; /* link to link_reg in struct vpu_reg */
struct list_head session; /* link to list_session in struct vpu_session */
atomic_t total_running;
bool enabled;
- vpu_reg *reg_codec;
+ vpu_reg **reg_codec;
vpu_reg *reg_pproc;
vpu_reg *reg_resev;
VPUHwDecConfig_t dec_config;
struct vcodec_combo {
struct vpu_service_info *vpu_srv;
struct vpu_service_info *hevc_srv;
+ struct list_head waiting;
+ struct list_head running;
+ struct mutex run_lock;
+ vpu_reg *reg_codec;
+ enum vcodec_device_id current_hw_mode;
};
typedef struct vpu_request
cru_set_soft_reset(SOFT_RST_CPU_VCODEC, false);
pmu_set_idle_request(IDLE_REQ_VIDEO, false);
#endif
-
- pservice->reg_codec = NULL;
+ *pservice->reg_codec = NULL;
pservice->reg_pproc = NULL;
pservice->reg_resev = NULL;
}
running = atomic_read(&pservice->total_running);
printk("total_running %d\n", running);
- printk("reg_codec 0x%.8x\n", (unsigned int)pservice->reg_codec);
+ printk("reg_codec 0x%.8x\n", (unsigned int)(*pservice->reg_codec));
printk("reg_pproc 0x%.8x\n", (unsigned int)pservice->reg_pproc);
printk("reg_resev 0x%.8x\n", (unsigned int)pservice->reg_resev);
udelay(10);
#if defined(CONFIG_VCODEC_MMU)
- if (pservice->mmu_dev) {
+ if (pservice->mmu_dev && !(cpu_is_rk3036() || cpu_is_rk312x())) {
vcodec_enter_mode(pservice->dev_id);
rockchip_iovmm_deactivate(pservice->dev);
vcodec_exit_mode();
struct delayed_work *dlwork = container_of(work_s, struct delayed_work, work);
struct vpu_service_info *pservice = container_of(dlwork, struct vpu_service_info, power_off_work);
- if (mutex_trylock(&pservice->lock)) {
+ if (mutex_trylock(pservice->lock)) {
vpu_service_power_off(pservice);
- mutex_unlock(&pservice->lock);
+ mutex_unlock(pservice->lock);
} else {
/* Come back later if the device is busy... */
vpu_queue_power_off_work(pservice);
vpu_queue_power_off_work(pservice);
last = now;
}
-
if (pservice->enabled)
return ;
pservice->enabled = true;
printk("%s: power on\n", dev_name(pservice->dev));
- if (cpu_is_rk3036() || cpu_is_rk312x()) {
- if (pservice == g_combo.vpu_srv) {
- if (g_combo.hevc_srv != NULL && g_combo.hevc_srv->mmu_dev) {
- u32 config;
- vcodec_enter_mode_nolock(g_combo.hevc_srv->dev_id, &config);
- rockchip_iovmm_deactivate(g_combo.hevc_srv->dev);
- vcodec_exit_mode_nolock(g_combo.hevc_srv->dev_id, config);
- }
- } else if (pservice == g_combo.hevc_srv) {
- if (g_combo.vpu_srv != NULL && g_combo.vpu_srv->mmu_dev) {
- u32 config;
- vcodec_enter_mode_nolock(g_combo.vpu_srv->dev_id, &config);
- rockchip_iovmm_deactivate(g_combo.vpu_srv->dev);
- vcodec_exit_mode_nolock(g_combo.vpu_srv->dev_id, config);
- }
- }
- }
-
#if VCODEC_CLOCK_ENABLE
if (pservice->aclk_vcodec)
clk_prepare_enable(pservice->aclk_vcodec);
wake_lock(&pservice->wake_lock);
#if defined(CONFIG_VCODEC_MMU)
- if (pservice->mmu_dev) {
+ if (pservice->mmu_dev && !(cpu_is_rk3036() || cpu_is_rk312x())) {
vcodec_enter_mode(pservice->dev_id);
rockchip_iovmm_activate(pservice->dev);
vcodec_exit_mode();
}
-#endif
+#endif
}
static inline bool reg_check_rmvb_wmv(vpu_reg *reg)
}
#endif
- mutex_lock(&pservice->lock);
- list_add_tail(®->status_link, &pservice->waiting);
+ mutex_lock(pservice->lock);
+ list_add_tail(®->status_link, pservice->waiting);
list_add_tail(®->session_link, &session->waiting);
- mutex_unlock(&pservice->lock);
+ mutex_unlock(pservice->lock);
if (pservice->auto_freq) {
if (!soc_is_rk2928g()) {
list_del_init(®->session_link);
list_del_init(®->status_link);
- if (reg == pservice->reg_codec)
- pservice->reg_codec = NULL;
+ if (reg == (*pservice->reg_codec))
+ *pservice->reg_codec = NULL;
if (reg == pservice->reg_pproc)
pservice->reg_pproc = NULL;
list_for_each_entry_safe(mem_region, n, ®->mem_region_list, reg_lnk) {
/* do not unmap iommu manually,
unmap will proccess when memory release */
- vcodec_enter_mode(pservice->dev_id);
- /*ion_unmap_iommu(pservice->dev,
+ /*vcodec_enter_mode(pservice->dev_id);
+ ion_unmap_iommu(pservice->dev,
pservice->ion_client,
- mem_region->hdl);*/
- vcodec_exit_mode();
+ mem_region->hdl);
+ vcodec_exit_mode();*/
ion_free(pservice->ion_client, mem_region->hdl);
list_del_init(&mem_region->reg_lnk);
kfree(mem_region);
static void reg_from_wait_to_run(struct vpu_service_info *pservice, vpu_reg *reg)
{
list_del_init(®->status_link);
- list_add_tail(®->status_link, &pservice->running);
+ list_add_tail(®->status_link, pservice->running);
list_del_init(®->session_link);
list_add_tail(®->session_link, ®->session->running);
vcodec_enter_mode(pservice->dev_id);
switch (reg->type) {
case VPU_ENC : {
- pservice->reg_codec = NULL;
+ *pservice->reg_codec = NULL;
reg_copy_from_hw(reg, pservice->enc_dev.hwregs, pservice->hw_info->enc_reg_num);
irq_reg = ENC_INTERRUPT_REGISTER;
break;
}
case VPU_DEC : {
int reg_len = pservice->hw_info->hw_id == HEVC_ID ? REG_NUM_HEVC_DEC : REG_NUM_9190_DEC;
- pservice->reg_codec = NULL;
+ *pservice->reg_codec = NULL;
reg_copy_from_hw(reg, pservice->dec_dev.hwregs, reg_len);
irq_reg = DEC_INTERRUPT_REGISTER;
break;
break;
}
case VPU_DEC_PP : {
- pservice->reg_codec = NULL;
+ *pservice->reg_codec = NULL;
pservice->reg_pproc = NULL;
reg_copy_from_hw(reg, pservice->dec_dev.hwregs, REG_NUM_9190_DEC_PP);
pservice->dec_dev.hwregs[PP_INTERRUPT_REGISTER] = 0;
break;
}
}
+ if (cpu_is_rk3036() || cpu_is_rk312x())
+ rockchip_iovmm_deactivate(pservice->dev);
vcodec_exit_mode();
if (irq_reg != -1) {
vcodec_enter_mode(pservice->dev_id);
+ if (cpu_is_rk3036() || cpu_is_rk312x())
+ rockchip_iovmm_activate(pservice->dev);
+
switch (reg->type) {
case VPU_ENC : {
int enc_count = pservice->hw_info->enc_reg_num;
u32 *dst = (u32 *)pservice->enc_dev.hwregs;
- pservice->reg_codec = reg;
+ *pservice->reg_codec = reg;
dst[VPU_REG_EN_ENC] = src[VPU_REG_EN_ENC] & 0x6;
case VPU_DEC : {
u32 *dst = (u32 *)pservice->dec_dev.hwregs;
- pservice->reg_codec = reg;
+ *pservice->reg_codec = reg;
if (pservice->hw_info->hw_id != HEVC_ID) {
for (i = REG_NUM_9190_DEC - 1; i > VPU_REG_DEC_GATE; i--)
} break;
case VPU_DEC_PP : {
u32 *dst = (u32 *)pservice->dec_dev.hwregs;
- pservice->reg_codec = reg;
+ *pservice->reg_codec = reg;
pservice->reg_pproc = reg;
VDPU_SOFT_RESET(dst);
static void try_set_reg(struct vpu_service_info *pservice)
{
// first get reg from reg list
- if (!list_empty(&pservice->waiting)) {
+ if (!list_empty(pservice->waiting)) {
int can_set = 0;
- vpu_reg *reg = list_entry(pservice->waiting.next, vpu_reg, status_link);
+ vpu_reg *reg = list_entry(pservice->waiting->next, vpu_reg, status_link);
vpu_service_power_on(pservice);
switch (reg->type) {
case VPU_ENC : {
- if ((NULL == pservice->reg_codec) && (NULL == pservice->reg_pproc))
+ if ((NULL == *pservice->reg_codec) && (NULL == pservice->reg_pproc))
can_set = 1;
} break;
case VPU_DEC : {
- if (NULL == pservice->reg_codec)
+ if (NULL == *pservice->reg_codec)
can_set = 1;
if (pservice->auto_freq && (NULL != pservice->reg_pproc)) {
can_set = 0;
}
} break;
case VPU_PP : {
- if (NULL == pservice->reg_codec) {
+ if (NULL == *pservice->reg_codec) {
if (NULL == pservice->reg_pproc)
can_set = 1;
} else {
- if ((VPU_DEC == pservice->reg_codec->type) && (NULL == pservice->reg_pproc))
+ if ((VPU_DEC == (*pservice->reg_codec)->type) && (NULL == pservice->reg_pproc))
can_set = 1;
// can not charge frequency when vpu is working
if (pservice->auto_freq) {
}
} break;
case VPU_DEC_PP : {
- if ((NULL == pservice->reg_codec) && (NULL == pservice->reg_pproc))
+ if ((NULL == *pservice->reg_codec) && (NULL == pservice->reg_pproc))
can_set = 1;
} break;
default : {
if (NULL == reg) {
return -EFAULT;
} else {
- mutex_lock(&pservice->lock);
+ mutex_lock(pservice->lock);
try_set_reg(pservice);
- mutex_unlock(&pservice->lock);
+ mutex_unlock(pservice->lock);
}
break;
}
if (ret < 0) {
int task_running = atomic_read(&session->task_running);
- mutex_lock(&pservice->lock);
+ mutex_lock(pservice->lock);
vpu_service_dump(pservice);
if (task_running) {
atomic_set(&session->task_running, 0);
printk("done\n");
}
vpu_service_session_clear(pservice, session);
- mutex_unlock(&pservice->lock);
+ mutex_unlock(pservice->lock);
return ret;
}
}
- mutex_lock(&pservice->lock);
+ mutex_lock(pservice->lock);
reg = list_entry(session->done.next, vpu_reg, session_link);
return_reg(pservice, reg, (u32 __user *)req.req);
- mutex_unlock(&pservice->lock);
+ mutex_unlock(pservice->lock);
break;
}
case VPU_IOC_PROBE_IOMMU_STATUS: {
INIT_LIST_HEAD(&session->list_session);
init_waitqueue_head(&session->wait);
atomic_set(&session->task_running, 0);
- mutex_lock(&pservice->lock);
+ mutex_lock(pservice->lock);
list_add_tail(&session->list_session, &pservice->session);
filp->private_data = (void *)session;
- mutex_unlock(&pservice->lock);
+ mutex_unlock(pservice->lock);
pr_debug("dev opened\n");
return nonseekable_open(inode, filp);
}
wake_up(&session->wait);
- mutex_lock(&pservice->lock);
+ mutex_lock(pservice->lock);
/* remove this filp from the asynchronusly notified filp's */
list_del_init(&session->list_session);
vpu_service_session_clear(pservice, session);
kfree(session);
filp->private_data = NULL;
- mutex_unlock(&pservice->lock);
+ mutex_unlock(pservice->lock);
pr_debug("dev closed\n");
return 0;
int i = 0;
pr_info("vcodec, fault addr 0x%08x\n", (u32)fault_addr);
list_for_each_entry_safe(mem, n,
- &pservice->reg_codec->mem_region_list,
+ &(*pservice->reg_codec)->mem_region_list,
reg_lnk) {
pr_info("vcodec, mem region [%02d] 0x%08x %ld\n",
i, (u32)mem->iova, mem->len);
}
pr_alert("vcodec, page fault occur, reset hw\n");
- pservice->reg_codec->reg[101] = 1;
+ (*pservice->reg_codec)->reg[101] = 1;
vpu_reset(pservice);
}
vcodec_enter_mode_nolock(pservice->dev_id, &config);
wake_lock_init(&pservice->wake_lock, WAKE_LOCK_SUSPEND, "vpu");
- INIT_LIST_HEAD(&pservice->waiting);
- INIT_LIST_HEAD(&pservice->running);
+ if (cpu_is_rk3036() || cpu_is_rk312x()) {
+ pservice->waiting = &g_combo.waiting;
+ pservice->running = &g_combo.running;
+ pservice->lock = &g_combo.run_lock;
+ pservice->reg_codec = &g_combo.reg_codec;
+ } else {
+ pservice->waiting = kzalloc(sizeof(struct list_head), GFP_KERNEL);
+ pservice->running = kzalloc(sizeof(struct list_head), GFP_KERNEL);
+ pservice->lock = kzalloc(sizeof(struct mutex), GFP_KERNEL);
+ pservice->reg_codec = kzalloc(sizeof(vpu_reg*), GFP_KERNEL);
+ INIT_LIST_HEAD(pservice->waiting);
+ INIT_LIST_HEAD(pservice->running);
+ mutex_init(pservice->lock);
+ }
INIT_LIST_HEAD(&pservice->done);
INIT_LIST_HEAD(&pservice->session);
- mutex_init(&pservice->lock);
- pservice->reg_codec = NULL;
+
pservice->reg_pproc = NULL;
atomic_set(&pservice->total_running, 0);
pservice->enabled = false;
goto err;
}
- ret = devm_request_threaded_irq(pservice->dev, pservice->irq_enc, vepu_irq, vepu_isr, 0, dev_name(pservice->dev), (void *)pservice);
+ ret = devm_request_threaded_irq(pservice->dev, pservice->irq_enc, vepu_irq, vepu_isr, IRQF_DISABLED, dev_name(pservice->dev), (void *)pservice);
if (ret) {
dev_err(pservice->dev, "error: can't request vepu irq %d\n", pservice->irq_enc);
goto err;
if (pservice->mmu_dev) {
platform_set_sysmmu(pservice->mmu_dev, pservice->dev);
- rockchip_iovmm_activate(pservice->dev);
+ /*rockchip_iovmm_activate(pservice->dev);*/
}
rockchip_iovmm_set_fault_handler(pservice->dev, vcodec_sysmmu_fault_handler);
err:
pr_info("init failed\n");
- vcodec_exit_mode();
+ vcodec_exit_mode_nolock(pservice->dev_id, config);
vpu_service_power_off(pservice);
vpu_put_clk(pservice);
wake_lock_destroy(&pservice->wake_lock);
{
struct vpu_service_info *pservice = (struct vpu_service_info*)dev_id;
vpu_device *dev = &pservice->dec_dev;
- mutex_lock(&pservice->lock);
+
+ mutex_lock(pservice->lock);
if (atomic_read(&dev->irq_count_codec)) {
#if VPU_SERVICE_SHOW_TIME
do_gettimeofday(&dec_end);
if (NULL == pservice->reg_codec) {
pr_err("error: dec isr with no task waiting\n");
} else {
- reg_from_run_to_done(pservice, pservice->reg_codec);
+ reg_from_run_to_done(pservice, *pservice->reg_codec);
}
}
}
}
try_set_reg(pservice);
- mutex_unlock(&pservice->lock);
+ mutex_unlock(pservice->lock);
return IRQ_HANDLED;
}
struct vpu_service_info *pservice = (struct vpu_service_info*)dev_id;
vpu_device *dev = &pservice->enc_dev;
- mutex_lock(&pservice->lock);
+ mutex_lock(pservice->lock);
if (atomic_read(&dev->irq_count_codec)) {
atomic_sub(1, &dev->irq_count_codec);
if (NULL == pservice->reg_codec) {
pr_err("error: enc isr with no task waiting\n");
} else {
- reg_from_run_to_done(pservice, pservice->reg_codec);
+ reg_from_run_to_done(pservice, *pservice->reg_codec);
}
}
try_set_reg(pservice);
- mutex_unlock(&pservice->lock);
+ mutex_unlock(pservice->lock);
return IRQ_HANDLED;
}
g_combo.hevc_srv = NULL;
g_combo.vpu_srv = NULL;
+ INIT_LIST_HEAD(&g_combo.waiting);
+ INIT_LIST_HEAD(&g_combo.running);
+ mutex_init(&g_combo.run_lock);
+ g_combo.reg_codec = NULL;
+ g_combo.current_hw_mode = VCODEC_DEVICE_ID_VPU;
if ((ret = platform_driver_register(&vcodec_driver)) != 0) {
pr_err("Platform device register failed (%d).\n", ret);
vpu_reg *reg, *reg_tmp;
vpu_session *session, *session_tmp;
- mutex_lock(&pservice->lock);
+ mutex_lock(pservice->lock);
vpu_service_power_on(pservice);
if (pservice->hw_info->hw_id != HEVC_ID) {
seq_printf(s, "\nENC Registers:\n");
seq_printf(s, "done register set\n");
}
}
- mutex_unlock(&pservice->lock);
+ mutex_unlock(pservice->lock);
return 0;
}
for (i = 10; i <= 24; i++)
reg->reg[i] = phy_yuv;
- mutex_lock(&pservice->lock);
- list_add_tail(®->status_link, &pservice->waiting);
+ mutex_lock(pservice->lock);
+ list_add_tail(®->status_link, pservice->waiting);
list_add_tail(®->session_link, &session.waiting);
- mutex_unlock(&pservice->lock);
+ mutex_unlock(pservice->lock);
printk("%s %d %p\n", __func__, __LINE__, pservice);
if (ret < 0) {
int task_running = atomic_read(&session.task_running);
int n;
- mutex_lock(&pservice->lock);
+ mutex_lock(pservice->lock);
vpu_service_dump(pservice);
if (task_running) {
atomic_set(&session.task_running, 0);
printk("done\n");
}
vpu_service_session_clear(pservice, &session);
- mutex_unlock(&pservice->lock);
+ mutex_unlock(pservice->lock);
printk("\nDEC Registers:\n");
n = pservice->dec_dev.iosize >> 2;