From: Sunyoung Kang Date: Thu, 28 Jun 2018 08:56:34 +0000 (+0900) Subject: [COMMON] media: mfc: DRV4.0: replace opr and ctrl to run X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=e588f77631b9ab354beb65b5bf3dc8bca3cbaee6;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git [COMMON] media: mfc: DRV4.0: replace opr and ctrl to run The mfc_opr and mfc_ctrl perform a similar function to operate HW. This merges the both together and changes the name to mfc_run. - apply "mfc_run" prefix to function name in mfc_run - move hwlock code in sleep/wakeup function to caller - remove unnecessary code Change-Id: I23320d6c454c353de30e9c761b3f581e20d28a7b Signed-off-by: Sunyoung Kang --- diff --git a/drivers/media/platform/exynos/mfc/Makefile b/drivers/media/platform/exynos/mfc/Makefile index d13d890ad488..32a248c7afc6 100644 --- a/drivers/media/platform/exynos/mfc/Makefile +++ b/drivers/media/platform/exynos/mfc/Makefile @@ -1,6 +1,6 @@ obj-$(CONFIG_VIDEO_EXYNOS_MFC) := exynos_mfc.o exynos_mfc-y += mfc.o mfc_isr.o mfc_dec_v4l2.o mfc_dec_vb2.o mfc_enc_v4l2.o mfc_enc_vb2.o -exynos_mfc-y += mfc_ctrl.o mfc_hwlock.o mfc_nal_q.o mfc_watchdog.o mfc_opr.o mfc_sync.o +exynos_mfc-y += mfc_hwlock.o mfc_nal_q.o mfc_watchdog.o mfc_run.o mfc_sync.o exynos_mfc-y += mfc_pm.o mfc_cmd.o mfc_hw_reg_api.o mfc_reg_api.o mfc_perf_measure.o exynos_mfc-y += mfc_dec_ctrl.o mfc_enc_ctrl.o mfc_enc_param.o exynos_mfc-y += mfc_queue.o mfc_buf.o mfc_utils.o mfc_qos.o mfc_mem.o diff --git a/drivers/media/platform/exynos/mfc/mfc.c b/drivers/media/platform/exynos/mfc/mfc.c index 9faf35048914..cc5c950b2a35 100644 --- a/drivers/media/platform/exynos/mfc/mfc.c +++ b/drivers/media/platform/exynos/mfc/mfc.c @@ -27,13 +27,12 @@ #include "mfc_dec_v4l2.h" #include "mfc_enc_v4l2.h" -#include "mfc_ctrl.h" +#include "mfc_run.h" #include "mfc_hwlock.h" #include "mfc_nal_q.h" #include "mfc_otf.h" #include "mfc_watchdog.h" #include "mfc_debugfs.h" -#include "mfc_opr.h" #include "mfc_sync.h" #include "mfc_pm.h" @@ -381,7 +380,7 @@ static int __mfc_init_instance(struct mfc_dev *dev, struct mfc_ctx *ctx) dev->preempt_ctx = MFC_NO_INSTANCE_SET; dev->curr_ctx_is_drm = ctx->is_drm; - ret = mfc_init_hw(dev); + ret = mfc_run_init_hw(dev); if (ret) { mfc_err_ctx("Failed to init mfc h/w\n"); goto err_hw_init; @@ -713,7 +712,7 @@ static int mfc_release(struct file *file) dev->num_inst--; if (dev->num_inst == 0) { - mfc_deinit_hw(dev); + mfc_run_deinit_hw(dev); if (perf_boost_mode) mfc_perf_boost_disable(dev); @@ -1469,7 +1468,7 @@ static int mfc_remove(struct platform_device *pdev) mfc_destroy_listable_wq_dev(dev); iovmm_deactivate(&pdev->dev); mfc_debug(2, "Will now deinit HW\n"); - mfc_deinit_hw(dev); + mfc_run_deinit_hw(dev); free_irq(dev->irq, dev); if (dev->has_mmcache) iounmap(dev->mmcache.base); @@ -1515,38 +1514,62 @@ static void mfc_shutdown(struct platform_device *pdev) } #ifdef CONFIG_PM_SLEEP -static int mfc_suspend(struct device *dev) +static int mfc_suspend(struct device *device) { - struct mfc_dev *m_dev = platform_get_drvdata(to_platform_device(dev)); + struct mfc_dev *dev = platform_get_drvdata(to_platform_device(device)); int ret; - if (!m_dev) { + if (!dev) { mfc_err_dev("no mfc device to run\n"); return -EINVAL; } - if (m_dev->num_inst == 0) + if (dev->num_inst == 0) return 0; - ret = mfc_sleep(m_dev); + MFC_TRACE_DEV_HWLOCK("**sleep\n"); + ret = mfc_get_hwlock_dev(dev); + if (ret < 0) { + mfc_err_dev("Failed to get hwlock\n"); + mfc_err_dev("dev:0x%lx, bits:0x%lx, owned:%d, wl:%d, trans:%d\n", + dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq, + dev->hwlock.wl_count, dev->hwlock.transfer_owner); + return -EBUSY; + } + + ret = mfc_run_sleep(dev); + if (ret == 0) + mfc_release_hwlock_dev(dev); return ret; } -static int mfc_resume(struct device *dev) +static int mfc_resume(struct device *device) { - struct mfc_dev *m_dev = platform_get_drvdata(to_platform_device(dev)); + struct mfc_dev *dev = platform_get_drvdata(to_platform_device(device)); int ret; - if (!m_dev) { + if (!dev) { mfc_err_dev("no mfc device to run\n"); return -EINVAL; } - if (m_dev->num_inst == 0) + if (dev->num_inst == 0) return 0; - ret = mfc_wakeup(m_dev); + MFC_TRACE_DEV_HWLOCK("**wakeup\n"); + ret = mfc_get_hwlock_dev(dev); + if (ret < 0) { + mfc_err_dev("Failed to get hwlock\n"); + mfc_err_dev("dev:0x%lx, bits:0x%lx, owned:%d, wl:%d, trans:%d\n", + dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq, + dev->hwlock.wl_count, dev->hwlock.transfer_owner); + return -EBUSY; + } + + ret = mfc_run_wakeup(dev); + if (ret == 0) + mfc_release_hwlock_dev(dev); return ret; } diff --git a/drivers/media/platform/exynos/mfc/mfc_ctrl.c b/drivers/media/platform/exynos/mfc/mfc_ctrl.c deleted file mode 100644 index 9da4eb37d58e..000000000000 --- a/drivers/media/platform/exynos/mfc/mfc_ctrl.c +++ /dev/null @@ -1,367 +0,0 @@ -/* - * drivers/media/platform/exynos/mfc/mfc_ctrl.c - * - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include "mfc_ctrl.h" - -#include "mfc_hwlock.h" -#include "mfc_nal_q.h" -#include "mfc_sync.h" - -#include "mfc_pm.h" -#include "mfc_cmd.h" -#include "mfc_reg_api.h" -#include "mfc_hw_reg_api.h" - -#include "mfc_utils.h" - -/* Initialize hardware */ -static int __mfc_init_hw(struct mfc_dev *dev, enum mfc_buf_usage_type buf_type) -{ - int fw_ver; - int ret = 0; - int curr_ctx_is_drm_backup; - - mfc_debug_enter(); - - if (!dev) { - mfc_err_dev("no mfc device to run\n"); - return -EINVAL; - } - - curr_ctx_is_drm_backup = dev->curr_ctx_is_drm; - - if (!dev->fw_buf.dma_buf) - return -EINVAL; - - /* 0. MFC reset */ - mfc_debug(2, "MFC reset...\n"); - - /* At init time, do not call secure API */ - if (buf_type == MFCBUF_NORMAL) - dev->curr_ctx_is_drm = 0; - else if (buf_type == MFCBUF_DRM) - dev->curr_ctx_is_drm = 1; - - ret = mfc_pm_clock_on(dev); - if (ret) { - mfc_err_dev("Failed to enable clock before reset(%d)\n", ret); - dev->curr_ctx_is_drm = curr_ctx_is_drm_backup; - return ret; - } - - ret = mfc_reset_mfc(dev); - if (ret) { - mfc_err_dev("Failed to reset MFC - timeout\n"); - goto err_init_hw; - } - mfc_debug(2, "Done MFC reset...\n"); - - /* 1. Set DRAM base Addr */ - mfc_set_risc_base_addr(dev, buf_type); - - /* 2. Release reset signal to the RISC */ - mfc_risc_on(dev); - - mfc_debug(2, "Will now wait for completion of firmware transfer\n"); - if (mfc_wait_for_done_dev(dev, MFC_REG_R2H_CMD_FW_STATUS_RET)) { - mfc_err_dev("Failed to RISC_ON\n"); - mfc_clean_dev_int_flags(dev); - ret = -EIO; - goto err_init_hw; - } - - /* 3. Initialize firmware */ - ret = mfc_cmd_sys_init(dev, buf_type); - if (ret) { - mfc_err_dev("Failed to send command to MFC - timeout\n"); - goto err_init_hw; - } - - mfc_debug(2, "Ok, now will write a command to init the system\n"); - if (mfc_wait_for_done_dev(dev, MFC_REG_R2H_CMD_SYS_INIT_RET)) { - mfc_err_dev("Failed to SYS_INIT\n"); - mfc_clean_dev_int_flags(dev); - ret = -EIO; - goto err_init_hw; - } - - dev->int_condition = 0; - if (dev->int_err != 0 || dev->int_reason != MFC_REG_R2H_CMD_SYS_INIT_RET) { - /* Failure. */ - mfc_err_dev("Failed to init firmware - error: %d, int: %d\n", - dev->int_err, dev->int_reason); - ret = -EIO; - goto err_init_hw; - } - - dev->fw.fimv_info = mfc_get_fimv_info(); - if (dev->fw.fimv_info != 'D' && dev->fw.fimv_info != 'E') - dev->fw.fimv_info = 'N'; - - mfc_info_dev("[F/W] MFC v%x.%x, %02xyy %02xmm %02xdd (%c)\n", - MFC_VER_MAJOR(dev), - MFC_VER_MINOR(dev), - mfc_get_fw_ver_year(), - mfc_get_fw_ver_month(), - mfc_get_fw_ver_date(), - dev->fw.fimv_info); - - dev->fw.date = mfc_get_fw_ver_all(); - /* Check MFC version and F/W version */ - fw_ver = mfc_get_mfc_version(); - if (fw_ver != dev->pdata->ip_ver) { - mfc_err_dev("Invalid F/W version(0x%x) for MFC H/W(0x%x)\n", - fw_ver, dev->pdata->ip_ver); - ret = -EIO; - goto err_init_hw; - } - -#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION - /* Cache flush for base address change */ - mfc_cmd_cache_flush(dev); - if (mfc_wait_for_done_dev(dev, MFC_REG_R2H_CMD_CACHE_FLUSH_RET)) { - mfc_err_dev("Failed to CACHE_FLUSH\n"); - mfc_clean_dev_int_flags(dev); - ret = -EIO; - goto err_init_hw; - } - - if (buf_type == MFCBUF_DRM && !curr_ctx_is_drm_backup) { - mfc_pm_clock_off(dev); - dev->curr_ctx_is_drm = curr_ctx_is_drm_backup; - mfc_pm_clock_on_with_base(dev, MFCBUF_NORMAL); - } -#endif - -err_init_hw: - mfc_pm_clock_off(dev); - dev->curr_ctx_is_drm = curr_ctx_is_drm_backup; - mfc_debug_leave(); - - return ret; -} - -/* Wrapper : Initialize hardware */ -int mfc_init_hw(struct mfc_dev *dev) -{ - int ret; - - ret = __mfc_init_hw(dev, MFCBUF_NORMAL); - if (ret) - return ret; - -#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION - if (dev->fw.drm_status) { - ret = __mfc_init_hw(dev, MFCBUF_DRM); - if (ret) - return ret; - } -#endif - - return ret; -} - -/* Deinitialize hardware */ -void mfc_deinit_hw(struct mfc_dev *dev) -{ - int ret; - - mfc_debug(2, "mfc deinit start\n"); - - if (!dev) { - mfc_err_dev("no mfc device to run\n"); - return; - } - - ret = mfc_pm_clock_on(dev); - if (ret) { - mfc_err_dev("Failed to enable clock before reset(%d)\n", ret); - return; - } - - mfc_mfc_off(dev); - - mfc_pm_clock_off(dev); - - mfc_debug(2, "mfc deinit completed\n"); -} - -int mfc_sleep(struct mfc_dev *dev) -{ - struct mfc_ctx *ctx; - int ret; - int old_state, i; - int need_cache_flush = 0; - - mfc_debug_enter(); - - if (!dev) { - mfc_err_dev("no mfc device to run\n"); - return -EINVAL; - } - - ctx = dev->ctx[dev->curr_ctx]; - if (!ctx) { - for (i = 0; i < MFC_NUM_CONTEXTS; i++) { - if (dev->ctx[i]) { - ctx = dev->ctx[i]; - break; - } - } - if (!ctx) { - mfc_err_dev("no mfc context to run\n"); - return -EINVAL; - } else { - mfc_info_dev("ctx is changed %d -> %d\n", - dev->curr_ctx, ctx->num); - dev->curr_ctx = ctx->num; - if (dev->curr_ctx_is_drm != ctx->is_drm) { - need_cache_flush = 1; - mfc_info_dev("DRM attribute is changed %d->%d\n", - dev->curr_ctx_is_drm, ctx->is_drm); - } - } - } - old_state = ctx->state; - mfc_change_state(ctx, MFCINST_ABORT); - MFC_TRACE_DEV_HWLOCK("**sleep (ctx:%d)\n", ctx->num); - ret = mfc_get_hwlock_dev(dev); - if (ret < 0) { - mfc_err_dev("Failed to get hwlock\n"); - mfc_err_dev("dev.hwlock.dev = 0x%lx, bits = 0x%lx, owned_by_irq = %d, wl_count = %d, transfer_owner = %d\n", - dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq, - dev->hwlock.wl_count, dev->hwlock.transfer_owner); - return -EBUSY; - } - - mfc_info_dev("curr_ctx_is_drm:%d, hwlock.bits:%lu, hwlock.dev:%lu\n", - dev->curr_ctx_is_drm, dev->hwlock.bits, dev->hwlock.dev); - - mfc_change_state(ctx, old_state); - mfc_pm_clock_on(dev); - - if (need_cache_flush) - mfc_cache_flush(dev, ctx->is_drm); - - mfc_cmd_sleep(dev); - - if (mfc_wait_for_done_dev(dev, MFC_REG_R2H_CMD_SLEEP_RET)) { - mfc_err_dev("Failed to SLEEP\n"); - dev->logging_data->cause |= (1 << MFC_CAUSE_FAIL_SLEEP); - call_dop(dev, dump_and_stop_always, dev); - return -EIO; - } - - dev->int_condition = 0; - if (dev->int_err != 0 || dev->int_reason != MFC_REG_R2H_CMD_SLEEP_RET) { - /* Failure. */ - mfc_err_dev("Failed to sleep - error: %d, int: %d\n", - dev->int_err, dev->int_reason); - ret = -EIO; - goto err_mfc_sleep; - } - - dev->sleep = 1; - -err_mfc_sleep: - mfc_mfc_off(dev); - mfc_pm_clock_off(dev); - mfc_release_hwlock_dev(dev); - mfc_debug_leave(); - - return ret; -} - -int mfc_wakeup(struct mfc_dev *dev) -{ - enum mfc_buf_usage_type buf_type; - int ret = 0; - - mfc_debug_enter(); - - if (!dev) { - mfc_err_dev("no mfc device to run\n"); - return -EINVAL; - } - mfc_info_dev("curr_ctx_is_drm:%d\n", dev->curr_ctx_is_drm); - - MFC_TRACE_DEV_HWLOCK("**wakeup\n"); - ret = mfc_get_hwlock_dev(dev); - if (ret < 0) { - mfc_err_dev("Failed to get hwlock\n"); - mfc_err_dev("dev.hwlock.dev = 0x%lx, bits = 0x%lx, owned_by_irq = %d, wl_count = %d, transfer_owner = %d\n", - dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq, - dev->hwlock.wl_count, dev->hwlock.transfer_owner); - return -EBUSY; - } - - dev->sleep = 0; - - /* 0. MFC reset */ - mfc_debug(2, "MFC reset...\n"); - - mfc_pm_clock_on(dev); - - ret = mfc_reset_mfc(dev); - if (ret) { - mfc_err_dev("Failed to reset MFC - timeout\n"); - goto err_mfc_wakeup; - } - mfc_debug(2, "Done MFC reset...\n"); - if (dev->curr_ctx_is_drm) - buf_type = MFCBUF_DRM; - else - buf_type = MFCBUF_NORMAL; - - /* 1. Set DRAM base Addr */ - mfc_set_risc_base_addr(dev, buf_type); - - /* 2. Release reset signal to the RISC */ - mfc_risc_on(dev); - - mfc_debug(2, "Will now wait for completion of firmware transfer\n"); - if (mfc_wait_for_done_dev(dev, MFC_REG_R2H_CMD_FW_STATUS_RET)) { - mfc_err_dev("Failed to RISC_ON\n"); - dev->logging_data->cause |= (1 << MFC_CAUSE_FAIL_RISC_ON); - call_dop(dev, dump_and_stop_always, dev); - return -EIO; - } - - mfc_debug(2, "Ok, now will write a command to wakeup the system\n"); - mfc_cmd_wakeup(dev); - - mfc_debug(2, "Will now wait for completion of firmware wake up\n"); - if (mfc_wait_for_done_dev(dev, MFC_REG_R2H_CMD_WAKEUP_RET)) { - mfc_err_dev("Failed to WAKEUP\n"); - dev->logging_data->cause |= (1 << MFC_CAUSE_FAIL_WAKEUP); - call_dop(dev, dump_and_stop_always, dev); - return -EIO; - } - - dev->int_condition = 0; - if (dev->int_err != 0 || dev->int_reason != MFC_REG_R2H_CMD_WAKEUP_RET) { - /* Failure. */ - mfc_err_dev("Failed to wakeup - error: %d, int: %d\n", - dev->int_err, dev->int_reason); - ret = -EIO; - goto err_mfc_wakeup; - } - -err_mfc_wakeup: - mfc_pm_clock_off(dev); - - mfc_release_hwlock_dev(dev); - - mfc_debug_leave(); - - return ret; -} diff --git a/drivers/media/platform/exynos/mfc/mfc_ctrl.h b/drivers/media/platform/exynos/mfc/mfc_ctrl.h deleted file mode 100644 index a8ad7918f6ea..000000000000 --- a/drivers/media/platform/exynos/mfc/mfc_ctrl.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * drivers/media/platform/exynos/mfc/mfc_ctrl.h - * - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#ifndef __MFC_CTRL_H -#define __MFC_CTRL_H __FILE__ - -#include "mfc_common.h" - -int mfc_init_hw(struct mfc_dev *dev); -void mfc_deinit_hw(struct mfc_dev *dev); - -int mfc_sleep(struct mfc_dev *dev); -int mfc_wakeup(struct mfc_dev *dev); - -#endif /* __MFC_CTRL_H */ diff --git a/drivers/media/platform/exynos/mfc/mfc_dec_v4l2.c b/drivers/media/platform/exynos/mfc/mfc_dec_v4l2.c index 27dc71142f67..1e3c13b73088 100644 --- a/drivers/media/platform/exynos/mfc/mfc_dec_v4l2.c +++ b/drivers/media/platform/exynos/mfc/mfc_dec_v4l2.c @@ -14,7 +14,7 @@ #include "mfc_dec_internal.h" #include "mfc_hwlock.h" -#include "mfc_opr.h" +#include "mfc_run.h" #include "mfc_sync.h" #include "mfc_mmcache.h" diff --git a/drivers/media/platform/exynos/mfc/mfc_dec_vb2.c b/drivers/media/platform/exynos/mfc/mfc_dec_vb2.c index a07446e16b59..9d5850ba6c27 100644 --- a/drivers/media/platform/exynos/mfc/mfc_dec_vb2.c +++ b/drivers/media/platform/exynos/mfc/mfc_dec_vb2.c @@ -14,7 +14,7 @@ #include "mfc_hwlock.h" #include "mfc_nal_q.h" -#include "mfc_opr.h" +#include "mfc_run.h" #include "mfc_sync.h" #include "mfc_queue.h" diff --git a/drivers/media/platform/exynos/mfc/mfc_enc_v4l2.c b/drivers/media/platform/exynos/mfc/mfc_enc_v4l2.c index d491a2379eb6..aff1dc8b3abf 100644 --- a/drivers/media/platform/exynos/mfc/mfc_enc_v4l2.c +++ b/drivers/media/platform/exynos/mfc/mfc_enc_v4l2.c @@ -15,7 +15,7 @@ #include "mfc_hwlock.h" #include "mfc_otf.h" -#include "mfc_opr.h" +#include "mfc_run.h" #include "mfc_sync.h" #include "mfc_qos.h" diff --git a/drivers/media/platform/exynos/mfc/mfc_enc_vb2.c b/drivers/media/platform/exynos/mfc/mfc_enc_vb2.c index 6d9ef8f24ca9..b33c1e041287 100644 --- a/drivers/media/platform/exynos/mfc/mfc_enc_vb2.c +++ b/drivers/media/platform/exynos/mfc/mfc_enc_vb2.c @@ -14,7 +14,7 @@ #include "mfc_hwlock.h" #include "mfc_nal_q.h" -#include "mfc_opr.h" +#include "mfc_run.h" #include "mfc_sync.h" #include "mfc_qos.h" diff --git a/drivers/media/platform/exynos/mfc/mfc_hw_reg_api.c b/drivers/media/platform/exynos/mfc/mfc_hw_reg_api.c index 40260069d3ff..2ad7d472a1ef 100644 --- a/drivers/media/platform/exynos/mfc/mfc_hw_reg_api.c +++ b/drivers/media/platform/exynos/mfc/mfc_hw_reg_api.c @@ -16,17 +16,12 @@ #include "mfc_pm.h" /* Reset the device */ -int mfc_reset_mfc(struct mfc_dev *dev) +void mfc_reset_mfc(struct mfc_dev *dev) { int i; mfc_debug_enter(); - if (!dev) { - mfc_err_dev("no mfc device to run\n"); - return -EINVAL; - } - /* Zero Initialization of MFC registers */ MFC_WRITEL(0, MFC_REG_RISC2HOST_CMD); MFC_WRITEL(0, MFC_REG_HOST2RISC_CMD); @@ -39,8 +34,6 @@ int mfc_reset_mfc(struct mfc_dev *dev) MFC_WRITEL(0, MFC_REG_MFC_RESET); mfc_debug_leave(); - - return 0; } void mfc_set_risc_base_addr(struct mfc_dev *dev, diff --git a/drivers/media/platform/exynos/mfc/mfc_hw_reg_api.h b/drivers/media/platform/exynos/mfc/mfc_hw_reg_api.h index 9d1245ddf684..542d47883fff 100644 --- a/drivers/media/platform/exynos/mfc/mfc_hw_reg_api.h +++ b/drivers/media/platform/exynos/mfc/mfc_hw_reg_api.h @@ -102,7 +102,7 @@ static inline void mfc_enable_all_clocks(struct mfc_dev *dev) MFC_WRITEL(0xFFFFFFFF, MFC_REG_MFC_FW_CLOCK); } -int mfc_reset_mfc(struct mfc_dev *dev); +void mfc_reset_mfc(struct mfc_dev *dev); void mfc_set_risc_base_addr(struct mfc_dev *dev, enum mfc_buf_usage_type buf_type); void mfc_cmd_host2risc(struct mfc_dev *dev, int cmd); diff --git a/drivers/media/platform/exynos/mfc/mfc_hwlock.c b/drivers/media/platform/exynos/mfc/mfc_hwlock.c index 4e5cfd548ade..69bb9727d011 100644 --- a/drivers/media/platform/exynos/mfc/mfc_hwlock.c +++ b/drivers/media/platform/exynos/mfc/mfc_hwlock.c @@ -14,7 +14,7 @@ #include "mfc_nal_q.h" #include "mfc_otf.h" -#include "mfc_opr.h" +#include "mfc_run.h" #include "mfc_sync.h" #include "mfc_pm.h" diff --git a/drivers/media/platform/exynos/mfc/mfc_isr.c b/drivers/media/platform/exynos/mfc/mfc_isr.c index d940839dcc13..cbd1cc1d14ee 100644 --- a/drivers/media/platform/exynos/mfc/mfc_isr.c +++ b/drivers/media/platform/exynos/mfc/mfc_isr.c @@ -15,7 +15,6 @@ #include "mfc_hwlock.h" #include "mfc_nal_q.h" #include "mfc_otf.h" -#include "mfc_opr.h" #include "mfc_sync.h" #include "mfc_pm.h" diff --git a/drivers/media/platform/exynos/mfc/mfc_opr.c b/drivers/media/platform/exynos/mfc/mfc_opr.c deleted file mode 100644 index 67a03ab19bb3..000000000000 --- a/drivers/media/platform/exynos/mfc/mfc_opr.c +++ /dev/null @@ -1,342 +0,0 @@ -/* - * drivers/media/platform/exynos/mfc/mfc_opr.c - * - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include "mfc_opr.h" - -#include "mfc_cmd.h" -#include "mfc_reg_api.h" -#include "mfc_enc_param.h" - -#include "mfc_queue.h" -#include "mfc_utils.h" -#include "mfc_mem.h" - -int mfc_run_dec_init(struct mfc_ctx *ctx) -{ - struct mfc_dev *dev; - struct mfc_buf *src_mb; - struct mfc_dec *dec = NULL; - - if (!ctx) { - mfc_err_dev("no mfc context to run\n"); - return -EINVAL; - } - dev = ctx->dev; - if (!dev) { - mfc_err_dev("no mfc device to run\n"); - return -EINVAL; - } - dec = ctx->dec_priv; - /* Initializing decoding - parsing header */ - - /* Get the next source buffer */ - src_mb = mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED); - if (!src_mb) { - mfc_err_dev("no src buffers\n"); - return -EAGAIN; - } - - mfc_debug(2, "Preparing to init decoding\n"); - mfc_debug(2, "Header size: %d, (offset: %lu)\n", - src_mb->vb.vb2_buf.planes[0].bytesused, dec->consumed); - - if (dec->consumed) { - mfc_set_dec_stream_buffer(ctx, src_mb, dec->consumed, dec->remained_size); - } else { - /* decoder src buffer CFW PROT */ - if (ctx->is_drm) { - int index = src_mb->vb.vb2_buf.index; - - mfc_stream_protect(ctx, src_mb, index); - } - - mfc_set_dec_stream_buffer(ctx, src_mb, - 0, src_mb->vb.vb2_buf.planes[0].bytesused); - } - - mfc_debug(2, "Header addr: 0x%08llx\n", src_mb->addr[0][0]); - mfc_clean_ctx_int_flags(ctx); - mfc_cmd_init_decode(ctx); - - return 0; -} - -static int __mfc_check_last_frame(struct mfc_ctx *ctx, struct mfc_buf *mfc_buf) -{ - if (mfc_buf->vb.reserved2 & FLAG_LAST_FRAME) { - mfc_debug(2, "Setting ctx->state to FINISHING\n"); - mfc_change_state(ctx, MFCINST_FINISHING); - return 1; - } - - return 0; -} - -int mfc_run_dec_frame(struct mfc_ctx *ctx) -{ - struct mfc_dev *dev; - struct mfc_buf *src_mb, *dst_mb; - struct mfc_dec *dec; - int last_frame = 0; - unsigned int index; - - if (!ctx) { - mfc_err_dev("no mfc context to run\n"); - return -EINVAL; - } - dec = ctx->dec_priv; - dev = ctx->dev; - if (!dev) { - mfc_err_dev("no mfc device to run\n"); - return -EINVAL; - } - - if (mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->dst_buf_queue, 0) && - mfc_is_queue_count_smaller(&ctx->buf_queue_lock, - &ctx->ref_buf_queue, (ctx->dpb_count + 5))) { - return -EAGAIN; - } - - /* Get the next source buffer */ - src_mb = mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_SET_USED); - if (!src_mb) { - mfc_debug(2, "no src buffers\n"); - return -EAGAIN; - } - - /* decoder src buffer CFW PROT */ - if (ctx->is_drm) { - if (!dec->consumed) { - index = src_mb->vb.vb2_buf.index; - mfc_stream_protect(ctx, src_mb, index); - } - } - - if (src_mb->vb.reserved2 & FLAG_EMPTY_DATA) - src_mb->vb.vb2_buf.planes[0].bytesused = 0; - - if (dec->consumed) - mfc_set_dec_stream_buffer(ctx, src_mb, dec->consumed, dec->remained_size); - else - mfc_set_dec_stream_buffer(ctx, src_mb, 0, src_mb->vb.vb2_buf.planes[0].bytesused); - - /* Try to use the non-referenced DPB on dst-queue */ - dst_mb = mfc_search_for_dpb(ctx, dec->dynamic_used); - if (!dst_mb) { - mfc_debug(2, "[DPB] couldn't find dst buffers\n"); - return -EAGAIN; - } - - index = src_mb->vb.vb2_buf.index; - if (call_cop(ctx, set_buf_ctrls_val, ctx, &ctx->src_ctrls[index]) < 0) - mfc_err_ctx("failed in set_buf_ctrls_val\n"); - - mfc_set_dynamic_dpb(ctx, dst_mb); - - mfc_clean_ctx_int_flags(ctx); - - last_frame = __mfc_check_last_frame(ctx, src_mb); - mfc_cmd_dec_one_frame(ctx, last_frame); - - return 0; -} - -int mfc_run_dec_last_frames(struct mfc_ctx *ctx) -{ - struct mfc_dev *dev; - struct mfc_buf *src_mb, *dst_mb; - struct mfc_dec *dec; - - if (!ctx) { - mfc_err_dev("no mfc context to run\n"); - return -EINVAL; - } - - dec = ctx->dec_priv; - if (!dec) { - mfc_err_dev("no decoder context to run\n"); - return -EINVAL; - } - - dev = ctx->dev; - if (!dev) { - mfc_err_dev("no mfc device to run\n"); - return -EINVAL; - } - - if (mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->dst_buf_queue, 0)) { - mfc_debug(2, "no dst buffer\n"); - return -EAGAIN; - } - - /* Get the next source buffer */ - src_mb = mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_SET_USED); - - /* Frames are being decoded */ - if (!src_mb) { - mfc_debug(2, "no src buffers\n"); - mfc_set_dec_stream_buffer(ctx, 0, 0, 0); - } else { - if (dec->consumed) { - mfc_set_dec_stream_buffer(ctx, src_mb, dec->consumed, dec->remained_size); - } else { - /* decoder src buffer CFW PROT */ - if (ctx->is_drm) { - int index = src_mb->vb.vb2_buf.index; - - mfc_stream_protect(ctx, src_mb, index); - } - - mfc_set_dec_stream_buffer(ctx, src_mb, 0, 0); - } - } - - /* Try to use the non-referenced DPB on dst-queue */ - dst_mb = mfc_search_for_dpb(ctx, dec->dynamic_used); - if (!dst_mb) { - mfc_debug(2, "[DPB] couldn't find dst buffers\n"); - return -EAGAIN; - } - - mfc_set_dynamic_dpb(ctx, dst_mb); - - mfc_clean_ctx_int_flags(ctx); - mfc_cmd_dec_one_frame(ctx, 1); - - return 0; -} - -int mfc_run_enc_init(struct mfc_ctx *ctx) -{ - struct mfc_buf *dst_mb; - int ret; - - dst_mb = mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED); - if (!dst_mb) { - mfc_debug(2, "no dst buffers\n"); - return -EAGAIN; - } - - /* encoder dst buffer CFW PROT */ - if (ctx->is_drm) { - int index = dst_mb->vb.vb2_buf.index; - - mfc_stream_protect(ctx, dst_mb, index); - } - mfc_set_enc_stream_buffer(ctx, dst_mb); - - mfc_set_enc_stride(ctx); - - mfc_debug(2, "Header addr: 0x%08llx\n", dst_mb->addr[0][0]); - mfc_clean_ctx_int_flags(ctx); - - ret = mfc_cmd_init_encode(ctx); - return ret; -} - -int mfc_run_enc_frame(struct mfc_ctx *ctx) -{ - struct mfc_buf *dst_mb; - struct mfc_buf *src_mb; - struct mfc_raw_info *raw; - unsigned int index, i; - int last_frame = 0; - - raw = &ctx->raw_buf; - - /* Get the next source buffer */ - src_mb = mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_SET_USED); - if (!src_mb) { - mfc_debug(2, "no src buffers\n"); - return -EAGAIN; - } - - if (src_mb->num_valid_bufs > 0) { - /* last image in a buffer container */ - if (src_mb->next_index == (src_mb->num_valid_bufs - 1)) { - mfc_debug(4, "[BUFCON] last image in a container\n"); - last_frame = __mfc_check_last_frame(ctx, src_mb); - } - } else { - last_frame = __mfc_check_last_frame(ctx, src_mb); - } - - index = src_mb->vb.vb2_buf.index; - - /* encoder src buffer CFW PROT */ - if (ctx->is_drm) - mfc_raw_protect(ctx, src_mb, index); - - mfc_set_enc_frame_buffer(ctx, src_mb, raw->num_planes); - - dst_mb = mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_SET_USED); - if (!dst_mb) { - mfc_debug(2, "no dst buffers\n"); - return -EAGAIN; - } - - /* encoder dst buffer CFW PROT */ - if (ctx->is_drm) { - i = dst_mb->vb.vb2_buf.index; - mfc_stream_protect(ctx, dst_mb, i); - } - mfc_debug(2, "nal start : src index from src_buf_queue:%d\n", - src_mb->vb.vb2_buf.index); - mfc_debug(2, "nal start : dst index from dst_buf_queue:%d\n", - dst_mb->vb.vb2_buf.index); - - mfc_set_enc_stream_buffer(ctx, dst_mb); - - if (call_cop(ctx, set_buf_ctrls_val, ctx, &ctx->src_ctrls[index]) < 0) - mfc_err_ctx("failed in set_buf_ctrls_val\n"); - - mfc_clean_ctx_int_flags(ctx); - - if (IS_H264_ENC(ctx)) - mfc_set_aso_slice_order_h264(ctx); - mfc_set_slice_mode(ctx); - - mfc_cmd_enc_one_frame(ctx, last_frame); - - return 0; -} - -int mfc_run_enc_last_frames(struct mfc_ctx *ctx) -{ - struct mfc_buf *dst_mb; - struct mfc_raw_info *raw; - - raw = &ctx->raw_buf; - - dst_mb = mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_SET_USED); - if (!dst_mb) { - mfc_debug(2, "no dst buffers\n"); - return -EAGAIN; - } - - mfc_debug(2, "Set address zero for all planes\n"); - mfc_set_enc_frame_buffer(ctx, 0, raw->num_planes); - - /* encoder dst buffer CFW PROT */ - if (ctx->is_drm) { - int index = dst_mb->vb.vb2_buf.index; - - mfc_stream_protect(ctx, dst_mb, index); - } - - mfc_set_enc_stream_buffer(ctx, dst_mb); - - mfc_clean_ctx_int_flags(ctx); - mfc_cmd_enc_one_frame(ctx, 1); - - return 0; -} diff --git a/drivers/media/platform/exynos/mfc/mfc_opr.h b/drivers/media/platform/exynos/mfc/mfc_opr.h deleted file mode 100644 index 75b2984f9c6c..000000000000 --- a/drivers/media/platform/exynos/mfc/mfc_opr.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * drivers/media/platform/exynos/mfc/mfc_opr.h - * - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#ifndef __MFC_OPR_H -#define __MFC_OPR_H __FILE__ - -#include "mfc_common.h" - -int mfc_run_dec_init(struct mfc_ctx *ctx); -int mfc_run_dec_frame(struct mfc_ctx *ctx); -int mfc_run_dec_last_frames(struct mfc_ctx *ctx); -int mfc_run_enc_init(struct mfc_ctx *ctx); -int mfc_run_enc_frame(struct mfc_ctx *ctx); -int mfc_run_enc_last_frames(struct mfc_ctx *ctx); - -#endif /* __MFC_OPR_H */ diff --git a/drivers/media/platform/exynos/mfc/mfc_run.c b/drivers/media/platform/exynos/mfc/mfc_run.c new file mode 100644 index 000000000000..ffc17c1ef524 --- /dev/null +++ b/drivers/media/platform/exynos/mfc/mfc_run.c @@ -0,0 +1,598 @@ +/* + * drivers/media/platform/exynos/mfc/mfc_run.c + * + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include "mfc_run.h" + +#include "mfc_nal_q.h" +#include "mfc_sync.h" +#include "mfc_hwlock.h" + +#include "mfc_pm.h" +#include "mfc_cmd.h" +#include "mfc_reg_api.h" +#include "mfc_hw_reg_api.h" +#include "mfc_enc_param.h" + +#include "mfc_queue.h" +#include "mfc_utils.h" +#include "mfc_mem.h" + +/* Initialize hardware */ +static int __mfc_init_hw(struct mfc_dev *dev, enum mfc_buf_usage_type buf_type) +{ + int fw_ver; + int ret = 0; + int curr_ctx_is_drm_backup; + + mfc_debug_enter(); + + curr_ctx_is_drm_backup = dev->curr_ctx_is_drm; + + if (!dev->fw_buf.dma_buf) + return -EINVAL; + + /* 0. MFC reset */ + mfc_debug(2, "MFC reset...\n"); + + /* At init time, do not call secure API */ + if (buf_type == MFCBUF_NORMAL) + dev->curr_ctx_is_drm = 0; + else if (buf_type == MFCBUF_DRM) + dev->curr_ctx_is_drm = 1; + + ret = mfc_pm_clock_on(dev); + if (ret) { + mfc_err_dev("Failed to enable clock before reset(%d)\n", ret); + dev->curr_ctx_is_drm = curr_ctx_is_drm_backup; + return ret; + } + + mfc_reset_mfc(dev); + mfc_debug(2, "Done MFC reset...\n"); + + /* 1. Set DRAM base Addr */ + mfc_set_risc_base_addr(dev, buf_type); + + /* 2. Release reset signal to the RISC */ + mfc_risc_on(dev); + + mfc_debug(2, "Will now wait for completion of firmware transfer\n"); + if (mfc_wait_for_done_dev(dev, MFC_REG_R2H_CMD_FW_STATUS_RET)) { + mfc_err_dev("Failed to RISC_ON\n"); + mfc_clean_dev_int_flags(dev); + ret = -EIO; + goto err_init_hw; + } + + /* 3. Initialize firmware */ + ret = mfc_cmd_sys_init(dev, buf_type); + if (ret) { + mfc_err_dev("Failed to send command to MFC - timeout\n"); + goto err_init_hw; + } + + mfc_debug(2, "Ok, now will write a command to init the system\n"); + if (mfc_wait_for_done_dev(dev, MFC_REG_R2H_CMD_SYS_INIT_RET)) { + mfc_err_dev("Failed to SYS_INIT\n"); + mfc_clean_dev_int_flags(dev); + ret = -EIO; + goto err_init_hw; + } + + dev->int_condition = 0; + if (dev->int_err != 0 || dev->int_reason != MFC_REG_R2H_CMD_SYS_INIT_RET) { + /* Failure. */ + mfc_err_dev("Failed to init firmware - error: %d, int: %d\n", + dev->int_err, dev->int_reason); + ret = -EIO; + goto err_init_hw; + } + + dev->fw.fimv_info = mfc_get_fimv_info(); + if (dev->fw.fimv_info != 'D' && dev->fw.fimv_info != 'E') + dev->fw.fimv_info = 'N'; + + mfc_info_dev("[F/W] MFC v%x.%x, %02xyy %02xmm %02xdd (%c)\n", + MFC_VER_MAJOR(dev), + MFC_VER_MINOR(dev), + mfc_get_fw_ver_year(), + mfc_get_fw_ver_month(), + mfc_get_fw_ver_date(), + dev->fw.fimv_info); + + dev->fw.date = mfc_get_fw_ver_all(); + /* Check MFC version and F/W version */ + fw_ver = mfc_get_mfc_version(); + if (fw_ver != dev->pdata->ip_ver) { + mfc_err_dev("Invalid F/W version(0x%x) for MFC H/W(0x%x)\n", + fw_ver, dev->pdata->ip_ver); + ret = -EIO; + goto err_init_hw; + } + +#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION + /* Cache flush for base address change */ + mfc_cmd_cache_flush(dev); + if (mfc_wait_for_done_dev(dev, MFC_REG_R2H_CMD_CACHE_FLUSH_RET)) { + mfc_err_dev("Failed to CACHE_FLUSH\n"); + mfc_clean_dev_int_flags(dev); + ret = -EIO; + goto err_init_hw; + } + + if (buf_type == MFCBUF_DRM && !curr_ctx_is_drm_backup) { + mfc_pm_clock_off(dev); + dev->curr_ctx_is_drm = curr_ctx_is_drm_backup; + mfc_pm_clock_on_with_base(dev, MFCBUF_NORMAL); + } +#endif + +err_init_hw: + mfc_pm_clock_off(dev); + dev->curr_ctx_is_drm = curr_ctx_is_drm_backup; + mfc_debug_leave(); + + return ret; +} + +/* Wrapper : Initialize hardware */ +int mfc_run_init_hw(struct mfc_dev *dev) +{ + int ret; + + ret = __mfc_init_hw(dev, MFCBUF_NORMAL); + if (ret) + return ret; + +#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION + if (dev->fw.drm_status) + ret = __mfc_init_hw(dev, MFCBUF_DRM); +#endif + + return ret; +} + +/* Deinitialize hardware */ +void mfc_run_deinit_hw(struct mfc_dev *dev) +{ + int ret; + + mfc_debug(2, "mfc deinit start\n"); + + ret = mfc_pm_clock_on(dev); + if (ret) { + mfc_err_dev("Failed to enable clock before reset(%d)\n", ret); + return; + } + + mfc_mfc_off(dev); + + mfc_pm_clock_off(dev); + + mfc_debug(2, "mfc deinit completed\n"); +} + +int mfc_run_sleep(struct mfc_dev *dev) +{ + struct mfc_ctx *ctx; + int old_state, i; + int need_cache_flush = 0; + + mfc_debug_enter(); + + ctx = dev->ctx[dev->curr_ctx]; + if (!ctx) { + for (i = 0; i < MFC_NUM_CONTEXTS; i++) { + if (dev->ctx[i]) { + ctx = dev->ctx[i]; + break; + } + } + + if (!ctx) { + mfc_err_dev("no mfc context to run\n"); + return -EINVAL; + } + mfc_info_dev("ctx is changed %d -> %d\n", dev->curr_ctx, ctx->num); + + dev->curr_ctx = ctx->num; + if (dev->curr_ctx_is_drm != ctx->is_drm) { + need_cache_flush = 1; + mfc_info_dev("DRM attribute is changed %d->%d\n", + dev->curr_ctx_is_drm, ctx->is_drm); + } + } + mfc_info_dev("curr_ctx_is_drm:%d\n", dev->curr_ctx_is_drm); + + mfc_pm_clock_on(dev); + + if (need_cache_flush) + mfc_cache_flush(dev, ctx->is_drm); + + mfc_cmd_sleep(dev); + + if (mfc_wait_for_done_dev(dev, MFC_REG_R2H_CMD_SLEEP_RET)) { + mfc_err_dev("Failed to SLEEP\n"); + dev->logging_data->cause |= (1 << MFC_CAUSE_FAIL_SLEEP); + call_dop(dev, dump_and_stop_always, dev); + return -EBUSY; + } + + dev->int_condition = 0; + if (dev->int_err != 0 || dev->int_reason != MFC_REG_R2H_CMD_SLEEP_RET) { + /* Failure. */ + mfc_err_dev("Failed to sleep - error: %d, int: %d\n", + dev->int_err, dev->int_reason); + call_dop(dev, dump_and_stop_always, dev); + return -EBUSY; + } + + dev->sleep = 1; + + mfc_mfc_off(dev); + mfc_pm_clock_off(dev); + + mfc_debug_leave(); + + return 0; +} + +int mfc_run_wakeup(struct mfc_dev *dev) +{ + enum mfc_buf_usage_type buf_type; + int ret = 0; + + mfc_debug_enter(); + mfc_info_dev("curr_ctx_is_drm:%d\n", dev->curr_ctx_is_drm); + + /* 0. MFC reset */ + mfc_debug(2, "MFC reset...\n"); + + ret = mfc_pm_clock_on(dev); + if (ret) { + mfc_err_dev("Failed to enable clock before reset(%d)\n", ret); + return ret; + } + + mfc_reset_mfc(dev); + mfc_debug(2, "Done MFC reset...\n"); + + if (dev->curr_ctx_is_drm) + buf_type = MFCBUF_DRM; + else + buf_type = MFCBUF_NORMAL; + + /* 1. Set DRAM base Addr */ + mfc_set_risc_base_addr(dev, buf_type); + + /* 2. Release reset signal to the RISC */ + mfc_risc_on(dev); + + mfc_debug(2, "Will now wait for completion of firmware transfer\n"); + if (mfc_wait_for_done_dev(dev, MFC_REG_R2H_CMD_FW_STATUS_RET)) { + mfc_err_dev("Failed to RISC_ON\n"); + dev->logging_data->cause |= (1 << MFC_CAUSE_FAIL_RISC_ON); + call_dop(dev, dump_and_stop_always, dev); + return -EBUSY; + } + + mfc_debug(2, "Ok, now will write a command to wakeup the system\n"); + mfc_cmd_wakeup(dev); + + mfc_debug(2, "Will now wait for completion of firmware wake up\n"); + if (mfc_wait_for_done_dev(dev, MFC_REG_R2H_CMD_WAKEUP_RET)) { + mfc_err_dev("Failed to WAKEUP\n"); + dev->logging_data->cause |= (1 << MFC_CAUSE_FAIL_WAKEUP); + call_dop(dev, dump_and_stop_always, dev); + return -EBUSY; + } + + dev->int_condition = 0; + if (dev->int_err != 0 || dev->int_reason != MFC_REG_R2H_CMD_WAKEUP_RET) { + /* Failure. */ + mfc_err_dev("Failed to wakeup - error: %d, int: %d\n", + dev->int_err, dev->int_reason); + call_dop(dev, dump_and_stop_always, dev); + return -EBUSY; + } + + dev->sleep = 0; + + mfc_pm_clock_off(dev); + + mfc_debug_leave(); + + return ret; +} + +int mfc_run_dec_init(struct mfc_ctx *ctx) +{ + struct mfc_dev *dev = ctx->dev; + struct mfc_dec *dec = ctx->dec_priv; + struct mfc_buf *src_mb; + + /* Initializing decoding - parsing header */ + + /* Get the next source buffer */ + src_mb = mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED); + if (!src_mb) { + mfc_err_dev("no src buffers\n"); + return -EAGAIN; + } + + mfc_debug(2, "Preparing to init decoding\n"); + mfc_debug(2, "Header size: %d, (offset: %lu)\n", + src_mb->vb.vb2_buf.planes[0].bytesused, dec->consumed); + + if (dec->consumed) { + mfc_set_dec_stream_buffer(ctx, src_mb, dec->consumed, dec->remained_size); + } else { + /* decoder src buffer CFW PROT */ + if (ctx->is_drm) { + int index = src_mb->vb.vb2_buf.index; + + mfc_stream_protect(ctx, src_mb, index); + } + + mfc_set_dec_stream_buffer(ctx, src_mb, + 0, src_mb->vb.vb2_buf.planes[0].bytesused); + } + + mfc_debug(2, "Header addr: 0x%08llx\n", src_mb->addr[0][0]); + mfc_clean_ctx_int_flags(ctx); + mfc_cmd_init_decode(ctx); + + return 0; +} + +static int __mfc_check_last_frame(struct mfc_ctx *ctx, struct mfc_buf *mfc_buf) +{ + if (mfc_buf->vb.reserved2 & FLAG_LAST_FRAME) { + mfc_debug(2, "Setting ctx->state to FINISHING\n"); + mfc_change_state(ctx, MFCINST_FINISHING); + return 1; + } + + return 0; +} + +int mfc_run_dec_frame(struct mfc_ctx *ctx) +{ + struct mfc_dev *dev = ctx->dev; + struct mfc_dec *dec = ctx->dec_priv; + struct mfc_buf *src_mb, *dst_mb; + int last_frame = 0; + unsigned int index; + + if (mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->dst_buf_queue, 0) && + mfc_is_queue_count_smaller(&ctx->buf_queue_lock, + &ctx->ref_buf_queue, (ctx->dpb_count + 5))) { + return -EAGAIN; + } + + /* Get the next source buffer */ + src_mb = mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_SET_USED); + if (!src_mb) { + mfc_debug(2, "no src buffers\n"); + return -EAGAIN; + } + + /* decoder src buffer CFW PROT */ + if (ctx->is_drm) { + if (!dec->consumed) { + index = src_mb->vb.vb2_buf.index; + mfc_stream_protect(ctx, src_mb, index); + } + } + + if (src_mb->vb.reserved2 & FLAG_EMPTY_DATA) + src_mb->vb.vb2_buf.planes[0].bytesused = 0; + + if (dec->consumed) + mfc_set_dec_stream_buffer(ctx, src_mb, dec->consumed, dec->remained_size); + else + mfc_set_dec_stream_buffer(ctx, src_mb, 0, src_mb->vb.vb2_buf.planes[0].bytesused); + + /* Try to use the non-referenced DPB on dst-queue */ + dst_mb = mfc_search_for_dpb(ctx, dec->dynamic_used); + if (!dst_mb) { + mfc_debug(2, "[DPB] couldn't find dst buffers\n"); + return -EAGAIN; + } + + index = src_mb->vb.vb2_buf.index; + if (call_cop(ctx, set_buf_ctrls_val, ctx, &ctx->src_ctrls[index]) < 0) + mfc_err_ctx("failed in set_buf_ctrls_val\n"); + + mfc_set_dynamic_dpb(ctx, dst_mb); + + mfc_clean_ctx_int_flags(ctx); + + last_frame = __mfc_check_last_frame(ctx, src_mb); + mfc_cmd_dec_one_frame(ctx, last_frame); + + return 0; +} + +int mfc_run_dec_last_frames(struct mfc_ctx *ctx) +{ + struct mfc_dev *dev = ctx->dev; + struct mfc_dec *dec = ctx->dec_priv; + struct mfc_buf *src_mb, *dst_mb; + + if (mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->dst_buf_queue, 0)) { + mfc_debug(2, "no dst buffer\n"); + return -EAGAIN; + } + + /* Get the next source buffer */ + src_mb = mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_SET_USED); + + /* Frames are being decoded */ + if (!src_mb) { + mfc_debug(2, "no src buffers\n"); + mfc_set_dec_stream_buffer(ctx, 0, 0, 0); + } else { + if (dec->consumed) { + mfc_set_dec_stream_buffer(ctx, src_mb, dec->consumed, dec->remained_size); + } else { + /* decoder src buffer CFW PROT */ + if (ctx->is_drm) { + int index = src_mb->vb.vb2_buf.index; + + mfc_stream_protect(ctx, src_mb, index); + } + + mfc_set_dec_stream_buffer(ctx, src_mb, 0, 0); + } + } + + /* Try to use the non-referenced DPB on dst-queue */ + dst_mb = mfc_search_for_dpb(ctx, dec->dynamic_used); + if (!dst_mb) { + mfc_debug(2, "[DPB] couldn't find dst buffers\n"); + return -EAGAIN; + } + + mfc_set_dynamic_dpb(ctx, dst_mb); + + mfc_clean_ctx_int_flags(ctx); + mfc_cmd_dec_one_frame(ctx, 1); + + return 0; +} + +int mfc_run_enc_init(struct mfc_ctx *ctx) +{ + struct mfc_buf *dst_mb; + int ret; + + dst_mb = mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED); + if (!dst_mb) { + mfc_debug(2, "no dst buffers\n"); + return -EAGAIN; + } + + /* encoder dst buffer CFW PROT */ + if (ctx->is_drm) { + int index = dst_mb->vb.vb2_buf.index; + + mfc_stream_protect(ctx, dst_mb, index); + } + mfc_set_enc_stream_buffer(ctx, dst_mb); + + mfc_set_enc_stride(ctx); + + mfc_debug(2, "Header addr: 0x%08llx\n", dst_mb->addr[0][0]); + mfc_clean_ctx_int_flags(ctx); + + ret = mfc_cmd_init_encode(ctx); + return ret; +} + +int mfc_run_enc_frame(struct mfc_ctx *ctx) +{ + struct mfc_buf *dst_mb; + struct mfc_buf *src_mb; + struct mfc_raw_info *raw; + unsigned int index, i; + int last_frame = 0; + + raw = &ctx->raw_buf; + + /* Get the next source buffer */ + src_mb = mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_SET_USED); + if (!src_mb) { + mfc_debug(2, "no src buffers\n"); + return -EAGAIN; + } + + if (src_mb->num_valid_bufs > 0) { + /* last image in a buffer container */ + if (src_mb->next_index == (src_mb->num_valid_bufs - 1)) { + mfc_debug(4, "[BUFCON] last image in a container\n"); + last_frame = __mfc_check_last_frame(ctx, src_mb); + } + } else { + last_frame = __mfc_check_last_frame(ctx, src_mb); + } + + index = src_mb->vb.vb2_buf.index; + + /* encoder src buffer CFW PROT */ + if (ctx->is_drm) + mfc_raw_protect(ctx, src_mb, index); + + mfc_set_enc_frame_buffer(ctx, src_mb, raw->num_planes); + + dst_mb = mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_SET_USED); + if (!dst_mb) { + mfc_debug(2, "no dst buffers\n"); + return -EAGAIN; + } + + /* encoder dst buffer CFW PROT */ + if (ctx->is_drm) { + i = dst_mb->vb.vb2_buf.index; + mfc_stream_protect(ctx, dst_mb, i); + } + mfc_debug(2, "nal start : src index from src_buf_queue:%d\n", + src_mb->vb.vb2_buf.index); + mfc_debug(2, "nal start : dst index from dst_buf_queue:%d\n", + dst_mb->vb.vb2_buf.index); + + mfc_set_enc_stream_buffer(ctx, dst_mb); + + if (call_cop(ctx, set_buf_ctrls_val, ctx, &ctx->src_ctrls[index]) < 0) + mfc_err_ctx("failed in set_buf_ctrls_val\n"); + + mfc_clean_ctx_int_flags(ctx); + + if (IS_H264_ENC(ctx)) + mfc_set_aso_slice_order_h264(ctx); + mfc_set_slice_mode(ctx); + + mfc_cmd_enc_one_frame(ctx, last_frame); + + return 0; +} + +int mfc_run_enc_last_frames(struct mfc_ctx *ctx) +{ + struct mfc_buf *dst_mb; + struct mfc_raw_info *raw; + + raw = &ctx->raw_buf; + + dst_mb = mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_SET_USED); + if (!dst_mb) { + mfc_debug(2, "no dst buffers\n"); + return -EAGAIN; + } + + mfc_debug(2, "Set address zero for all planes\n"); + mfc_set_enc_frame_buffer(ctx, 0, raw->num_planes); + + /* encoder dst buffer CFW PROT */ + if (ctx->is_drm) { + int index = dst_mb->vb.vb2_buf.index; + + mfc_stream_protect(ctx, dst_mb, index); + } + + mfc_set_enc_stream_buffer(ctx, dst_mb); + + mfc_clean_ctx_int_flags(ctx); + mfc_cmd_enc_one_frame(ctx, 1); + + return 0; +} diff --git a/drivers/media/platform/exynos/mfc/mfc_run.h b/drivers/media/platform/exynos/mfc/mfc_run.h new file mode 100644 index 000000000000..06970cf16961 --- /dev/null +++ b/drivers/media/platform/exynos/mfc/mfc_run.h @@ -0,0 +1,32 @@ +/* + * drivers/media/platform/exynos/mfc/mfc_run.h + * + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __MFC_RUN_H +#define __MFC_RUN_H __FILE__ + +#include "mfc_common.h" + +int mfc_run_init_hw(struct mfc_dev *dev); +void mfc_run_deinit_hw(struct mfc_dev *dev); + +int mfc_run_sleep(struct mfc_dev *dev); +int mfc_run_wakeup(struct mfc_dev *dev); + +int mfc_run_dec_init(struct mfc_ctx *ctx); +int mfc_run_dec_frame(struct mfc_ctx *ctx); +int mfc_run_dec_last_frames(struct mfc_ctx *ctx); + +int mfc_run_enc_init(struct mfc_ctx *ctx); +int mfc_run_enc_frame(struct mfc_ctx *ctx); +int mfc_run_enc_last_frames(struct mfc_ctx *ctx); + +#endif /* __MFC_RUN_H */