media: venus: Add framework support for AR50_LITE video core

The AR50_LITE is a simplified variant of the AR50 video core, designed for
power and cost-efficient platforms.

It supports hardware-accelerated decoding of H.264, HEVC, and VP9 formats,
and provides encoding support for H.264 and HEVC.

This commit prepares the framework to enable the AR50_LITE (it does not
enable it).

Signed-off-by: Jorge Ramirez-Ortiz <jorge.ramirez@oss.qualcomm.com>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Reviewed-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
Signed-off-by: Bryan O'Donoghue <bod@kernel.org>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
This commit is contained in:
Jorge Ramirez-Ortiz
2025-08-14 10:52:43 +02:00
committed by Mauro Carvalho Chehab
parent 85c853b704
commit ba4fdff920
13 changed files with 145 additions and 54 deletions

View File

@@ -254,14 +254,19 @@ static int venus_enumerate_codecs(struct venus_core *core, u32 type)
static void venus_assign_register_offsets(struct venus_core *core)
{
if (IS_IRIS2(core) || IS_IRIS2_1(core)) {
core->vbif_base = core->base + VBIF_BASE;
if (IS_IRIS2(core) || IS_IRIS2_1(core) || IS_AR50_LITE(core)) {
core->cpu_base = core->base + CPU_BASE_V6;
core->cpu_cs_base = core->base + CPU_CS_BASE_V6;
core->cpu_ic_base = core->base + CPU_IC_BASE_V6;
core->wrapper_base = core->base + WRAPPER_BASE_V6;
core->wrapper_tz_base = core->base + WRAPPER_TZ_BASE_V6;
core->aon_base = core->base + AON_BASE_V6;
if (IS_AR50_LITE(core)) {
core->vbif_base = NULL;
core->aon_base = NULL;
} else {
core->vbif_base = core->base + VBIF_BASE;
core->aon_base = core->base + AON_BASE_V6;
}
} else {
core->vbif_base = core->base + VBIF_BASE;
core->cpu_base = core->base + CPU_BASE;
@@ -456,6 +461,10 @@ static int venus_probe(struct platform_device *pdev)
if (ret)
goto err_firmware_deinit;
ret = venus_firmware_cfg(core);
if (ret)
goto err_venus_shutdown;
ret = hfi_core_resume(core, true);
if (ret)
goto err_venus_shutdown;

View File

@@ -533,6 +533,11 @@ struct venus_inst {
#define IS_IRIS2(core) ((core)->res->vpu_version == VPU_VERSION_IRIS2)
#define IS_IRIS2_1(core) ((core)->res->vpu_version == VPU_VERSION_IRIS2_1)
static inline bool is_lite(struct venus_core *core)
{
return IS_AR50_LITE(core);
}
#define ctrl_to_inst(ctrl) \
container_of((ctrl)->handler, struct venus_inst, ctrl_handler)

View File

@@ -207,6 +207,16 @@ static int venus_shutdown_no_tz(struct venus_core *core)
return 0;
}
int venus_firmware_cfg(struct venus_core *core)
{
void __iomem *cpu_cs_base = core->cpu_cs_base;
if (IS_AR50_LITE(core))
writel(CPU_CS_VCICMD_ARP_OFF, cpu_cs_base + CPU_CS_VCICMD);
return 0;
}
int venus_boot(struct venus_core *core)
{
struct device *dev = core->dev;

View File

@@ -10,6 +10,7 @@ struct device;
int venus_firmware_init(struct venus_core *core);
void venus_firmware_deinit(struct venus_core *core);
int venus_firmware_check(struct venus_core *core);
int venus_firmware_cfg(struct venus_core *core);
int venus_boot(struct venus_core *core);
int venus_shutdown(struct venus_core *core);
int venus_set_hw_state(struct venus_core *core, bool suspend);

View File

@@ -1715,11 +1715,17 @@ int venus_helper_session_init(struct venus_inst *inst)
if (ret)
return ret;
inst->clk_data.vpp_freq = hfi_platform_get_codec_vpp_freq(version, codec,
inst->clk_data.vpp_freq = hfi_platform_get_codec_vpp_freq(inst->core,
version,
codec,
session_type);
inst->clk_data.vsp_freq = hfi_platform_get_codec_vsp_freq(version, codec,
inst->clk_data.vsp_freq = hfi_platform_get_codec_vsp_freq(inst->core,
version,
codec,
session_type);
inst->clk_data.low_power_freq = hfi_platform_get_codec_lp_freq(version, codec,
inst->clk_data.low_power_freq = hfi_platform_get_codec_lp_freq(inst->core,
version,
codec,
session_type);
return 0;

View File

@@ -282,7 +282,7 @@ static int hfi_platform_parser(struct venus_core *core, struct venus_inst *inst)
return ret;
if (plat->capabilities)
caps = plat->capabilities(&entries);
caps = plat->capabilities(core, &entries);
if (!caps || !entries || !count)
return -EINVAL;

View File

@@ -21,7 +21,9 @@ const struct hfi_platform *hfi_platform_get(enum hfi_version version)
}
unsigned long
hfi_platform_get_codec_vpp_freq(enum hfi_version version, u32 codec, u32 session_type)
hfi_platform_get_codec_vpp_freq(struct venus_core *core,
enum hfi_version version, u32 codec,
u32 session_type)
{
const struct hfi_platform *plat;
unsigned long freq = 0;
@@ -31,13 +33,15 @@ hfi_platform_get_codec_vpp_freq(enum hfi_version version, u32 codec, u32 session
return 0;
if (plat->codec_vpp_freq)
freq = plat->codec_vpp_freq(session_type, codec);
freq = plat->codec_vpp_freq(core, session_type, codec);
return freq;
}
unsigned long
hfi_platform_get_codec_vsp_freq(enum hfi_version version, u32 codec, u32 session_type)
hfi_platform_get_codec_vsp_freq(struct venus_core *core,
enum hfi_version version, u32 codec,
u32 session_type)
{
const struct hfi_platform *plat;
unsigned long freq = 0;
@@ -47,13 +51,15 @@ hfi_platform_get_codec_vsp_freq(enum hfi_version version, u32 codec, u32 session
return 0;
if (plat->codec_vpp_freq)
freq = plat->codec_vsp_freq(session_type, codec);
freq = plat->codec_vsp_freq(core, session_type, codec);
return freq;
}
unsigned long
hfi_platform_get_codec_lp_freq(enum hfi_version version, u32 codec, u32 session_type)
hfi_platform_get_codec_lp_freq(struct venus_core *core,
enum hfi_version version, u32 codec,
u32 session_type)
{
const struct hfi_platform *plat;
unsigned long freq = 0;
@@ -63,13 +69,14 @@ hfi_platform_get_codec_lp_freq(enum hfi_version version, u32 codec, u32 session_
return 0;
if (plat->codec_lp_freq)
freq = plat->codec_lp_freq(session_type, codec);
freq = plat->codec_lp_freq(core, session_type, codec);
return freq;
}
int
hfi_platform_get_codecs(struct venus_core *core, u32 *enc_codecs, u32 *dec_codecs, u32 *count)
hfi_platform_get_codecs(struct venus_core *core, u32 *enc_codecs,
u32 *dec_codecs, u32 *count)
{
const struct hfi_platform *plat;
@@ -78,7 +85,7 @@ hfi_platform_get_codecs(struct venus_core *core, u32 *enc_codecs, u32 *dec_codec
return -EINVAL;
if (plat->codecs)
plat->codecs(enc_codecs, dec_codecs, count);
plat->codecs(core, enc_codecs, dec_codecs, count);
if (IS_IRIS2_1(core)) {
*enc_codecs &= ~HFI_VIDEO_CODEC_VP8;

View File

@@ -47,11 +47,16 @@ struct hfi_platform_codec_freq_data {
};
struct hfi_platform {
unsigned long (*codec_vpp_freq)(u32 session_type, u32 codec);
unsigned long (*codec_vsp_freq)(u32 session_type, u32 codec);
unsigned long (*codec_lp_freq)(u32 session_type, u32 codec);
void (*codecs)(u32 *enc_codecs, u32 *dec_codecs, u32 *count);
const struct hfi_plat_caps *(*capabilities)(unsigned int *entries);
unsigned long (*codec_vpp_freq)(struct venus_core *core,
u32 session_type, u32 codec);
unsigned long (*codec_vsp_freq)(struct venus_core *core,
u32 session_type, u32 codec);
unsigned long (*codec_lp_freq)(struct venus_core *core,
u32 session_type, u32 codec);
void (*codecs)(struct venus_core *core, u32 *enc_codecs,
u32 *dec_codecs, u32 *count);
const struct hfi_plat_caps *(*capabilities)(struct venus_core *core,
unsigned int *entries);
int (*bufreq)(struct hfi_plat_buffers_params *params, u32 session_type,
u32 buftype, struct hfi_buffer_requirements *bufreq);
};
@@ -60,12 +65,15 @@ extern const struct hfi_platform hfi_plat_v4;
extern const struct hfi_platform hfi_plat_v6;
const struct hfi_platform *hfi_platform_get(enum hfi_version version);
unsigned long hfi_platform_get_codec_vpp_freq(enum hfi_version version, u32 codec,
u32 session_type);
unsigned long hfi_platform_get_codec_vsp_freq(enum hfi_version version, u32 codec,
u32 session_type);
unsigned long hfi_platform_get_codec_lp_freq(enum hfi_version version, u32 codec,
u32 session_type);
int hfi_platform_get_codecs(struct venus_core *core, u32 *enc_codecs, u32 *dec_codecs,
u32 *count);
unsigned long hfi_platform_get_codec_vpp_freq(struct venus_core *core,
enum hfi_version version,
u32 codec, u32 session_type);
unsigned long hfi_platform_get_codec_vsp_freq(struct venus_core *core,
enum hfi_version version,
u32 codec, u32 session_type);
unsigned long hfi_platform_get_codec_lp_freq(struct venus_core *core,
enum hfi_version version,
u32 codec, u32 session_type);
int hfi_platform_get_codecs(struct venus_core *core, u32 *enc_codecs,
u32 *dec_codecs, u32 *count);
#endif

View File

@@ -2,6 +2,7 @@
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*/
#include "core.h"
#include "hfi_platform.h"
static const struct hfi_plat_caps caps[] = {
@@ -245,14 +246,22 @@ static const struct hfi_plat_caps caps[] = {
.num_fmts = 4,
} };
static const struct hfi_plat_caps *get_capabilities(unsigned int *entries)
static const struct hfi_plat_caps *get_capabilities(struct venus_core *core,
unsigned int *entries)
{
if (is_lite(core))
return NULL;
*entries = ARRAY_SIZE(caps);
return caps;
}
static void get_codecs(u32 *enc_codecs, u32 *dec_codecs, u32 *count)
static void get_codecs(struct venus_core *core,
u32 *enc_codecs, u32 *dec_codecs, u32 *count)
{
if (is_lite(core))
return;
*enc_codecs = HFI_VIDEO_CODEC_H264 | HFI_VIDEO_CODEC_HEVC |
HFI_VIDEO_CODEC_VP8;
*dec_codecs = HFI_VIDEO_CODEC_H264 | HFI_VIDEO_CODEC_HEVC |
@@ -273,12 +282,15 @@ static const struct hfi_platform_codec_freq_data codec_freq_data[] = {
};
static const struct hfi_platform_codec_freq_data *
get_codec_freq_data(u32 session_type, u32 pixfmt)
get_codec_freq_data(struct venus_core *core, u32 session_type, u32 pixfmt)
{
const struct hfi_platform_codec_freq_data *data = codec_freq_data;
unsigned int i, data_size = ARRAY_SIZE(codec_freq_data);
const struct hfi_platform_codec_freq_data *found = NULL;
if (is_lite(core))
return NULL;
for (i = 0; i < data_size; i++) {
if (data[i].pixfmt == pixfmt && data[i].session_type == session_type) {
found = &data[i];
@@ -289,33 +301,36 @@ get_codec_freq_data(u32 session_type, u32 pixfmt)
return found;
}
static unsigned long codec_vpp_freq(u32 session_type, u32 codec)
static unsigned long codec_vpp_freq(struct venus_core *core,
u32 session_type, u32 codec)
{
const struct hfi_platform_codec_freq_data *data;
data = get_codec_freq_data(session_type, codec);
data = get_codec_freq_data(core, session_type, codec);
if (data)
return data->vpp_freq;
return 0;
}
static unsigned long codec_vsp_freq(u32 session_type, u32 codec)
static unsigned long codec_vsp_freq(struct venus_core *core,
u32 session_type, u32 codec)
{
const struct hfi_platform_codec_freq_data *data;
data = get_codec_freq_data(session_type, codec);
data = get_codec_freq_data(core, session_type, codec);
if (data)
return data->vsp_freq;
return 0;
}
static unsigned long codec_lp_freq(u32 session_type, u32 codec)
static unsigned long codec_lp_freq(struct venus_core *core,
u32 session_type, u32 codec)
{
const struct hfi_platform_codec_freq_data *data;
data = get_codec_freq_data(session_type, codec);
data = get_codec_freq_data(core, session_type, codec);
if (data)
return data->low_power_freq;

View File

@@ -2,6 +2,7 @@
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*/
#include "core.h"
#include "hfi_platform.h"
static const struct hfi_plat_caps caps[] = {
@@ -245,14 +246,22 @@ static const struct hfi_plat_caps caps[] = {
.num_fmts = 4,
} };
static const struct hfi_plat_caps *get_capabilities(unsigned int *entries)
static const struct hfi_plat_caps *get_capabilities(struct venus_core *core,
unsigned int *entries)
{
if (is_lite(core))
return NULL;
*entries = ARRAY_SIZE(caps);
return caps;
}
static void get_codecs(u32 *enc_codecs, u32 *dec_codecs, u32 *count)
static void get_codecs(struct venus_core *core, u32 *enc_codecs,
u32 *dec_codecs, u32 *count)
{
if (is_lite(core))
return;
*enc_codecs = HFI_VIDEO_CODEC_H264 | HFI_VIDEO_CODEC_HEVC |
HFI_VIDEO_CODEC_VP8;
*dec_codecs = HFI_VIDEO_CODEC_H264 | HFI_VIDEO_CODEC_HEVC |
@@ -273,12 +282,15 @@ static const struct hfi_platform_codec_freq_data codec_freq_data[] = {
};
static const struct hfi_platform_codec_freq_data *
get_codec_freq_data(u32 session_type, u32 pixfmt)
get_codec_freq_data(struct venus_core *core, u32 session_type, u32 pixfmt)
{
const struct hfi_platform_codec_freq_data *data = codec_freq_data;
unsigned int i, data_size = ARRAY_SIZE(codec_freq_data);
const struct hfi_platform_codec_freq_data *found = NULL;
if (is_lite(core))
return NULL;
for (i = 0; i < data_size; i++) {
if (data[i].pixfmt == pixfmt && data[i].session_type == session_type) {
found = &data[i];
@@ -289,33 +301,36 @@ get_codec_freq_data(u32 session_type, u32 pixfmt)
return found;
}
static unsigned long codec_vpp_freq(u32 session_type, u32 codec)
static unsigned long codec_vpp_freq(struct venus_core *core, u32 session_type,
u32 codec)
{
const struct hfi_platform_codec_freq_data *data;
data = get_codec_freq_data(session_type, codec);
data = get_codec_freq_data(core, session_type, codec);
if (data)
return data->vpp_freq;
return 0;
}
static unsigned long codec_vsp_freq(u32 session_type, u32 codec)
static unsigned long codec_vsp_freq(struct venus_core *core, u32 session_type,
u32 codec)
{
const struct hfi_platform_codec_freq_data *data;
data = get_codec_freq_data(session_type, codec);
data = get_codec_freq_data(core, session_type, codec);
if (data)
return data->vsp_freq;
return 0;
}
static unsigned long codec_lp_freq(u32 session_type, u32 codec)
static unsigned long codec_lp_freq(struct venus_core *core, u32 session_type,
u32 codec)
{
const struct hfi_platform_codec_freq_data *data;
data = get_codec_freq_data(session_type, codec);
data = get_codec_freq_data(core, session_type, codec);
if (data)
return data->low_power_freq;

View File

@@ -380,7 +380,7 @@ static void venus_soft_int(struct venus_hfi_device *hdev)
void __iomem *cpu_ic_base = hdev->core->cpu_ic_base;
u32 clear_bit;
if (IS_V6(hdev->core))
if (IS_V6(hdev->core) || (IS_V4(hdev->core) && is_lite(hdev->core)))
clear_bit = BIT(CPU_IC_SOFTINT_H2A_SHIFT_V6);
else
clear_bit = BIT(CPU_IC_SOFTINT_H2A_SHIFT);
@@ -501,9 +501,11 @@ static int venus_boot_core(struct venus_hfi_device *hdev)
if (count >= max_tries)
ret = -ETIMEDOUT;
if (IS_IRIS2(hdev->core) || IS_IRIS2_1(hdev->core)) {
if (IS_IRIS2(hdev->core) || IS_IRIS2_1(hdev->core) || IS_AR50_LITE(hdev->core)) {
writel(0x1, cpu_cs_base + CPU_CS_H2XSOFTINTEN_V6);
writel(0x0, cpu_cs_base + CPU_CS_X2RPMH_V6);
if (!IS_AR50_LITE(hdev->core))
writel(0x0, cpu_cs_base + CPU_CS_X2RPMH_V6);
}
return ret;
@@ -569,6 +571,9 @@ static int venus_halt_axi(struct venus_hfi_device *hdev)
u32 mask_val;
int ret;
if (IS_AR50_LITE(hdev->core))
return 0;
if (IS_IRIS2(hdev->core) || IS_IRIS2_1(hdev->core)) {
writel(0x3, cpu_cs_base + CPU_CS_X2RPMH_V6);
@@ -1138,7 +1143,13 @@ static irqreturn_t venus_isr(struct venus_core *core)
wrapper_base = hdev->core->wrapper_base;
status = readl(wrapper_base + WRAPPER_INTR_STATUS);
if (IS_IRIS2(core) || IS_IRIS2_1(core)) {
if (IS_AR50_LITE(core)) {
if (status & WRAPPER_INTR_STATUS_A2H_MASK ||
status & WRAPPER_INTR_STATUS_A2HWD_MASK_V4_LITE ||
status & CPU_CS_SCIACMDARG0_INIT_IDLE_MSG_MASK)
hdev->irq_status = status;
} else if (IS_IRIS2(core) || IS_IRIS2_1(core)) {
if (status & WRAPPER_INTR_STATUS_A2H_MASK ||
status & WRAPPER_INTR_STATUS_A2HWD_MASK_V6 ||
status & CPU_CS_SCIACMDARG0_INIT_IDLE_MSG_MASK)
@@ -1150,7 +1161,7 @@ static irqreturn_t venus_isr(struct venus_core *core)
hdev->irq_status = status;
}
writel(1, cpu_cs_base + CPU_CS_A2HSOFTINTCLR);
if (!(IS_IRIS2(core) || IS_IRIS2_1(core)))
if (!(IS_IRIS2(core) || IS_IRIS2_1(core) || IS_AR50_LITE(core)))
writel(status, wrapper_base + WRAPPER_INTR_CLEAR);
return IRQ_WAKE_THREAD;
@@ -1535,7 +1546,7 @@ static bool venus_cpu_and_video_core_idle(struct venus_hfi_device *hdev)
void __iomem *cpu_cs_base = hdev->core->cpu_cs_base;
u32 ctrl_status, cpu_status;
if (IS_IRIS2(hdev->core) || IS_IRIS2_1(hdev->core))
if (IS_IRIS2(hdev->core) || IS_IRIS2_1(hdev->core) || IS_AR50_LITE(hdev->core))
cpu_status = readl(wrapper_tz_base + WRAPPER_TZ_CPU_STATUS_V6);
else
cpu_status = readl(wrapper_base + WRAPPER_CPU_STATUS);
@@ -1555,7 +1566,7 @@ static bool venus_cpu_idle_and_pc_ready(struct venus_hfi_device *hdev)
void __iomem *cpu_cs_base = hdev->core->cpu_cs_base;
u32 ctrl_status, cpu_status;
if (IS_IRIS2(hdev->core) || IS_IRIS2_1(hdev->core))
if (IS_IRIS2(hdev->core) || IS_IRIS2_1(hdev->core) || IS_AR50_LITE(hdev->core))
cpu_status = readl(wrapper_tz_base + WRAPPER_TZ_CPU_STATUS_V6);
else
cpu_status = readl(wrapper_base + WRAPPER_CPU_STATUS);

View File

@@ -51,6 +51,9 @@
/* Venus cpu */
#define CPU_CS_SCIACMDARG3 0x58
#define CPU_CS_VCICMD 0x20
#define CPU_CS_VCICMD_ARP_OFF BIT(0)
#define SFR_ADDR 0x5c
#define MMAP_ADDR 0x60
#define UC_REGION_ADDR 0x64
@@ -100,6 +103,7 @@
#define WRAPPER_INTR_MASK_A2HCPU_MASK 0x4
#define WRAPPER_INTR_MASK_A2HCPU_SHIFT 0x2
#define WRAPPER_INTR_STATUS_A2HWD_MASK_V4_LITE 0x10
#define WRAPPER_INTR_STATUS_A2HWD_MASK_V6 0x8
#define WRAPPER_INTR_MASK_A2HWD_BASK_V6 0x8

View File

@@ -52,7 +52,7 @@ static int core_clks_enable(struct venus_core *core)
dev_pm_opp_put(opp);
for (i = 0; i < res->clks_num; i++) {
if (IS_V6(core)) {
if (IS_V6(core) || (IS_V4(core) && is_lite(core))) {
ret = clk_set_rate(core->clks[i], freq);
if (ret)
goto err;