root/drivers/media/platform/qcom/iris/iris_hfi_common.c
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
 */

#include <linux/pm_runtime.h>

#include "iris_firmware.h"
#include "iris_core.h"
#include "iris_hfi_common.h"
#include "iris_vpu_common.h"

u32 iris_hfi_get_v4l2_color_primaries(u32 hfi_primaries)
{
        switch (hfi_primaries) {
        case HFI_PRIMARIES_RESERVED:
                return V4L2_COLORSPACE_DEFAULT;
        case HFI_PRIMARIES_BT709:
                return V4L2_COLORSPACE_REC709;
        case HFI_PRIMARIES_BT470_SYSTEM_M:
                return V4L2_COLORSPACE_470_SYSTEM_M;
        case HFI_PRIMARIES_BT470_SYSTEM_BG:
                return V4L2_COLORSPACE_470_SYSTEM_BG;
        case HFI_PRIMARIES_BT601_525:
                return V4L2_COLORSPACE_SMPTE170M;
        case HFI_PRIMARIES_SMPTE_ST240M:
                return V4L2_COLORSPACE_SMPTE240M;
        case HFI_PRIMARIES_BT2020:
                return V4L2_COLORSPACE_BT2020;
        case V4L2_COLORSPACE_DCI_P3:
                return HFI_PRIMARIES_SMPTE_RP431_2;
        default:
                return V4L2_COLORSPACE_DEFAULT;
        }
}

u32 iris_hfi_get_v4l2_transfer_char(u32 hfi_characterstics)
{
        switch (hfi_characterstics) {
        case HFI_TRANSFER_RESERVED:
                return V4L2_XFER_FUNC_DEFAULT;
        case HFI_TRANSFER_BT709:
                return V4L2_XFER_FUNC_709;
        case HFI_TRANSFER_SMPTE_ST240M:
                return V4L2_XFER_FUNC_SMPTE240M;
        case HFI_TRANSFER_SRGB_SYCC:
                return V4L2_XFER_FUNC_SRGB;
        case HFI_TRANSFER_SMPTE_ST2084_PQ:
                return V4L2_XFER_FUNC_SMPTE2084;
        default:
                return V4L2_XFER_FUNC_DEFAULT;
        }
}

u32 iris_hfi_get_v4l2_matrix_coefficients(u32 hfi_coefficients)
{
        switch (hfi_coefficients) {
        case HFI_MATRIX_COEFF_RESERVED:
                return V4L2_YCBCR_ENC_DEFAULT;
        case HFI_MATRIX_COEFF_BT709:
                return V4L2_YCBCR_ENC_709;
        case HFI_MATRIX_COEFF_BT470_SYS_BG_OR_BT601_625:
                return V4L2_YCBCR_ENC_XV601;
        case HFI_MATRIX_COEFF_BT601_525_BT1358_525_OR_625:
                return V4L2_YCBCR_ENC_601;
        case HFI_MATRIX_COEFF_SMPTE_ST240:
                return V4L2_YCBCR_ENC_SMPTE240M;
        case HFI_MATRIX_COEFF_BT2020_NON_CONSTANT:
                return V4L2_YCBCR_ENC_BT2020;
        case HFI_MATRIX_COEFF_BT2020_CONSTANT:
                return V4L2_YCBCR_ENC_BT2020_CONST_LUM;
        default:
                return V4L2_YCBCR_ENC_DEFAULT;
        }
}

int iris_hfi_core_init(struct iris_core *core)
{
        const struct iris_hfi_command_ops *hfi_ops = core->hfi_ops;
        int ret;

        ret = hfi_ops->sys_init(core);
        if (ret)
                return ret;

        ret = hfi_ops->sys_image_version(core);
        if (ret)
                return ret;

        return hfi_ops->sys_interframe_powercollapse(core);
}

irqreturn_t iris_hfi_isr(int irq, void *data)
{
        disable_irq_nosync(irq);

        return IRQ_WAKE_THREAD;
}

irqreturn_t iris_hfi_isr_handler(int irq, void *data)
{
        struct iris_core *core = data;

        if (!core)
                return IRQ_NONE;

        mutex_lock(&core->lock);
        pm_runtime_mark_last_busy(core->dev);
        iris_vpu_clear_interrupt(core);
        mutex_unlock(&core->lock);

        core->hfi_response_ops->hfi_response_handler(core);

        if (!iris_vpu_watchdog(core, core->intr_status))
                enable_irq(irq);

        return IRQ_HANDLED;
}

int iris_hfi_pm_suspend(struct iris_core *core)
{
        int ret;

        ret = iris_vpu_prepare_pc(core);
        if (ret) {
                pm_runtime_mark_last_busy(core->dev);
                ret = -EAGAIN;
                goto error;
        }

        ret = iris_set_hw_state(core, false);
        if (ret)
                goto error;

        iris_vpu_power_off(core);

        return 0;

error:
        dev_err(core->dev, "failed to suspend\n");

        return ret;
}

int iris_hfi_pm_resume(struct iris_core *core)
{
        const struct iris_hfi_command_ops *ops = core->hfi_ops;
        int ret;

        ret = iris_vpu_power_on(core);
        if (ret)
                goto error;

        ret = iris_set_hw_state(core, true);
        if (ret)
                goto err_power_off;

        ret = iris_vpu_boot_firmware(core);
        if (ret)
                goto err_suspend_hw;

        ret = ops->sys_interframe_powercollapse(core);
        if (ret)
                goto err_suspend_hw;

        return 0;

err_suspend_hw:
        iris_set_hw_state(core, false);
err_power_off:
        iris_vpu_power_off(core);
error:
        dev_err(core->dev, "failed to resume\n");

        return -EBUSY;
}