Skip to content

Commit 72cbe7f

Browse files
Vikash Garodiagouravk-qualcomm
authored andcommitted
BACKPORT: media: iris: Move vpu35 specific api to common to use for vpu4
Some of the sequence and calculations for vpu4 is identical to vpu35, namely power sequence for vpu controller and the clock frequency calculation. Move those to common file that can be shared for both vpu35 and vpu4. This patch prepares for power sequence for vpu4 which is added in subsequent patch. Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Co-developed-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com> Signed-off-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com> Signed-off-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com> Reviewed-by: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com> Signed-off-by: Bryan O'Donoghue <bod@kernel.org> Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org> Link: https://lore.kernel.org/all/20251210-knp_video-v4-5-8d11d840358a@oss.qualcomm.com/ (cherry picked from commit 82b96a8)
1 parent 422f3a6 commit 72cbe7f

3 files changed

Lines changed: 151 additions & 151 deletions

File tree

drivers/media/platform/qcom/iris/iris_vpu3x.c

Lines changed: 6 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
#define AON_WRAPPER_MVP_NOC_CORE_CLK_CONTROL (AON_BASE_OFFS + 0x20)
1717
#define NOC_HALT BIT(0)
1818
#define AON_WRAPPER_SPARE (AON_BASE_OFFS + 0x28)
19-
#define AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL (AON_BASE_OFFS + 0x2C)
20-
#define AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS (AON_BASE_OFFS + 0x30)
2119

2220
static bool iris_vpu3x_hw_power_collapsed(struct iris_core *core)
2321
{
@@ -262,170 +260,27 @@ static void iris_vpu35_power_off_hw(struct iris_core *core)
262260
iris_disable_unprepare_clock(core, IRIS_AXI_CLK);
263261
}
264262

265-
static int iris_vpu35_power_off_controller(struct iris_core *core)
266-
{
267-
u32 clk_rst_tbl_size = core->iris_platform_data->clk_rst_tbl_size;
268-
unsigned int count = 0;
269-
u32 val = 0;
270-
bool handshake_done, handshake_busy;
271-
int ret;
272-
273-
writel(MSK_SIGNAL_FROM_TENSILICA | MSK_CORE_POWER_ON, core->reg_base + CPU_CS_X2RPMH);
274-
275-
writel(REQ_POWER_DOWN_PREP, core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_CONTROL);
276-
277-
ret = readl_poll_timeout(core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_STATUS,
278-
val, val & BIT(0), 200, 2000);
279-
if (ret)
280-
goto disable_power;
281-
282-
writel(0, core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_CONTROL);
283-
284-
/* Retry up to 1000 times as recommended by hardware documentation */
285-
do {
286-
/* set MNoC to low power */
287-
writel(REQ_POWER_DOWN_PREP, core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL);
288-
289-
udelay(15);
290-
291-
val = readl(core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS);
292-
293-
handshake_done = val & NOC_LPI_STATUS_DONE;
294-
handshake_busy = val & (NOC_LPI_STATUS_DENY | NOC_LPI_STATUS_ACTIVE);
295-
296-
if (handshake_done || !handshake_busy)
297-
break;
298-
299-
writel(0, core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL);
300-
301-
udelay(15);
302-
303-
} while (++count < 1000);
304-
305-
if (!handshake_done && handshake_busy)
306-
dev_err(core->dev, "LPI handshake timeout\n");
307-
308-
ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS,
309-
val, val & BIT(0), 200, 2000);
310-
if (ret)
311-
goto disable_power;
312-
313-
writel(0, core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL);
314-
315-
writel(0, core->reg_base + WRAPPER_DEBUG_BRIDGE_LPI_CONTROL);
316-
317-
ret = readl_poll_timeout(core->reg_base + WRAPPER_DEBUG_BRIDGE_LPI_STATUS,
318-
val, val == 0, 200, 2000);
319-
if (ret)
320-
goto disable_power;
321-
322-
disable_power:
323-
iris_disable_unprepare_clock(core, IRIS_CTRL_CLK);
324-
iris_disable_unprepare_clock(core, IRIS_CTRL_FREERUN_CLK);
325-
iris_disable_unprepare_clock(core, IRIS_AXI1_CLK);
326-
327-
iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]);
328-
329-
reset_control_bulk_reset(clk_rst_tbl_size, core->resets);
330-
331-
return 0;
332-
}
333-
334-
static int iris_vpu35_power_on_controller(struct iris_core *core)
335-
{
336-
int ret;
337-
338-
ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]);
339-
if (ret)
340-
return ret;
341-
342-
ret = iris_prepare_enable_clock(core, IRIS_AXI1_CLK);
343-
if (ret)
344-
goto err_disable_power;
345-
346-
ret = iris_prepare_enable_clock(core, IRIS_CTRL_FREERUN_CLK);
347-
if (ret)
348-
goto err_disable_axi1_clk;
349-
350-
ret = iris_prepare_enable_clock(core, IRIS_CTRL_CLK);
351-
if (ret)
352-
goto err_disable_ctrl_free_clk;
353-
354-
return 0;
355-
356-
err_disable_ctrl_free_clk:
357-
iris_disable_unprepare_clock(core, IRIS_CTRL_FREERUN_CLK);
358-
err_disable_axi1_clk:
359-
iris_disable_unprepare_clock(core, IRIS_AXI1_CLK);
360-
err_disable_power:
361-
iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]);
362-
363-
return ret;
364-
}
365-
366-
static void iris_vpu35_program_bootup_registers(struct iris_core *core)
367-
{
368-
writel(0x1, core->reg_base + WRAPPER_IRIS_VCODEC_VPU_WRAPPER_SPARE_0);
369-
}
370-
371-
static u64 iris_vpu3x_calculate_frequency(struct iris_inst *inst, size_t data_size)
372-
{
373-
struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps;
374-
struct v4l2_format *inp_f = inst->fmt_src;
375-
u32 height, width, mbs_per_second, mbpf;
376-
u64 fw_cycles, fw_vpp_cycles;
377-
u64 vsp_cycles, vpp_cycles;
378-
u32 fps = DEFAULT_FPS;
379-
380-
width = max(inp_f->fmt.pix_mp.width, inst->crop.width);
381-
height = max(inp_f->fmt.pix_mp.height, inst->crop.height);
382-
383-
mbpf = NUM_MBS_PER_FRAME(height, width);
384-
mbs_per_second = mbpf * fps;
385-
386-
fw_cycles = fps * caps->mb_cycles_fw;
387-
fw_vpp_cycles = fps * caps->mb_cycles_fw_vpp;
388-
389-
vpp_cycles = mult_frac(mbs_per_second, caps->mb_cycles_vpp, (u32)inst->fw_caps[PIPE].value);
390-
/* 21 / 20 is minimum overhead factor */
391-
vpp_cycles += max(div_u64(vpp_cycles, 20), fw_vpp_cycles);
392-
393-
/* 1.059 is multi-pipe overhead */
394-
if (inst->fw_caps[PIPE].value > 1)
395-
vpp_cycles += div_u64(vpp_cycles * 59, 1000);
396-
397-
vsp_cycles = fps * data_size * 8;
398-
vsp_cycles = div_u64(vsp_cycles, 2);
399-
/* VSP FW overhead 1.05 */
400-
vsp_cycles = div_u64(vsp_cycles * 21, 20);
401-
402-
if (inst->fw_caps[STAGE].value == STAGE_1)
403-
vsp_cycles = vsp_cycles * 3;
404-
405-
return max3(vpp_cycles, vsp_cycles, fw_cycles);
406-
}
407-
408263
const struct vpu_ops iris_vpu3_ops = {
409264
.power_off_hw = iris_vpu3_power_off_hardware,
410265
.power_on_hw = iris_vpu_power_on_hw,
411266
.power_off_controller = iris_vpu_power_off_controller,
412267
.power_on_controller = iris_vpu_power_on_controller,
413-
.calc_freq = iris_vpu3x_calculate_frequency,
268+
.calc_freq = iris_vpu3x_vpu4x_calculate_frequency,
414269
};
415270

416271
const struct vpu_ops iris_vpu33_ops = {
417272
.power_off_hw = iris_vpu33_power_off_hardware,
418273
.power_on_hw = iris_vpu_power_on_hw,
419274
.power_off_controller = iris_vpu33_power_off_controller,
420275
.power_on_controller = iris_vpu_power_on_controller,
421-
.calc_freq = iris_vpu3x_calculate_frequency,
276+
.calc_freq = iris_vpu3x_vpu4x_calculate_frequency,
422277
};
423278

424279
const struct vpu_ops iris_vpu35_ops = {
425280
.power_off_hw = iris_vpu35_power_off_hw,
426281
.power_on_hw = iris_vpu35_power_on_hw,
427-
.power_off_controller = iris_vpu35_power_off_controller,
428-
.power_on_controller = iris_vpu35_power_on_controller,
429-
.program_bootup_registers = iris_vpu35_program_bootup_registers,
430-
.calc_freq = iris_vpu3x_calculate_frequency,
282+
.power_off_controller = iris_vpu35_vpu4x_power_off_controller,
283+
.power_on_controller = iris_vpu35_vpu4x_power_on_controller,
284+
.program_bootup_registers = iris_vpu35_vpu4x_program_bootup_registers,
285+
.calc_freq = iris_vpu3x_vpu4x_calculate_frequency,
431286
};

drivers/media/platform/qcom/iris/iris_vpu_common.c

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@
88
#include <linux/reset.h>
99

1010
#include "iris_core.h"
11+
#include "iris_instance.h"
1112
#include "iris_vpu_common.h"
1213
#include "iris_vpu_register_defines.h"
1314

15+
#define AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL (AON_BASE_OFFS + 0x2C)
16+
#define AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS (AON_BASE_OFFS + 0x30)
1417

1518
#define CTRL_INIT (CPU_CS_BASE_OFFS + 0x48)
1619
#define CTRL_STATUS (CPU_CS_BASE_OFFS + 0x4C)
@@ -305,6 +308,144 @@ int iris_vpu_power_on_hw(struct iris_core *core)
305308
return ret;
306309
}
307310

311+
int iris_vpu35_vpu4x_power_off_controller(struct iris_core *core)
312+
{
313+
u32 clk_rst_tbl_size = core->iris_platform_data->clk_rst_tbl_size;
314+
bool handshake_done, handshake_busy;
315+
u32 count = 0, val = 0;
316+
int ret;
317+
318+
writel(MSK_SIGNAL_FROM_TENSILICA | MSK_CORE_POWER_ON, core->reg_base + CPU_CS_X2RPMH);
319+
320+
writel(REQ_POWER_DOWN_PREP, core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_CONTROL);
321+
322+
ret = readl_poll_timeout(core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_STATUS,
323+
val, val & BIT(0), 200, 2000);
324+
if (ret)
325+
goto disable_power;
326+
327+
writel(0, core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_CONTROL);
328+
329+
/* Retry up to 1000 times as recommended by hardware documentation */
330+
do {
331+
/* set MNoC to low power */
332+
writel(REQ_POWER_DOWN_PREP, core->reg_base +
333+
AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL);
334+
usleep_range(10, 20);
335+
val = readl(core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS);
336+
337+
handshake_done = val & NOC_LPI_STATUS_DONE;
338+
handshake_busy = val & (NOC_LPI_STATUS_DENY | NOC_LPI_STATUS_ACTIVE);
339+
340+
if (handshake_done || !handshake_busy)
341+
break;
342+
343+
writel(0, core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL);
344+
usleep_range(10, 20);
345+
346+
} while (++count < 1000);
347+
348+
if (!handshake_done && handshake_busy)
349+
dev_err(core->dev, "LPI handshake timeout\n");
350+
351+
ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS,
352+
val, val & BIT(0), 200, 2000);
353+
if (ret)
354+
goto disable_power;
355+
356+
writel(0, core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL);
357+
358+
writel(0, core->reg_base + WRAPPER_DEBUG_BRIDGE_LPI_CONTROL);
359+
360+
readl_poll_timeout(core->reg_base + WRAPPER_DEBUG_BRIDGE_LPI_STATUS,
361+
val, val == 0, 200, 2000);
362+
363+
disable_power:
364+
iris_disable_unprepare_clock(core, IRIS_CTRL_CLK);
365+
iris_disable_unprepare_clock(core, IRIS_CTRL_FREERUN_CLK);
366+
iris_disable_unprepare_clock(core, IRIS_AXI1_CLK);
367+
368+
iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]);
369+
370+
reset_control_bulk_reset(clk_rst_tbl_size, core->resets);
371+
372+
return 0;
373+
}
374+
375+
int iris_vpu35_vpu4x_power_on_controller(struct iris_core *core)
376+
{
377+
int ret;
378+
379+
ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]);
380+
if (ret)
381+
return ret;
382+
383+
ret = iris_prepare_enable_clock(core, IRIS_AXI1_CLK);
384+
if (ret)
385+
goto err_disable_power;
386+
387+
ret = iris_prepare_enable_clock(core, IRIS_CTRL_FREERUN_CLK);
388+
if (ret)
389+
goto err_disable_axi1_clk;
390+
391+
ret = iris_prepare_enable_clock(core, IRIS_CTRL_CLK);
392+
if (ret)
393+
goto err_disable_ctrl_free_clk;
394+
395+
return 0;
396+
397+
err_disable_ctrl_free_clk:
398+
iris_disable_unprepare_clock(core, IRIS_CTRL_FREERUN_CLK);
399+
err_disable_axi1_clk:
400+
iris_disable_unprepare_clock(core, IRIS_AXI1_CLK);
401+
err_disable_power:
402+
iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]);
403+
404+
return ret;
405+
}
406+
407+
void iris_vpu35_vpu4x_program_bootup_registers(struct iris_core *core)
408+
{
409+
writel(0x1, core->reg_base + WRAPPER_IRIS_VCODEC_VPU_WRAPPER_SPARE_0);
410+
}
411+
412+
u64 iris_vpu3x_vpu4x_calculate_frequency(struct iris_inst *inst, size_t data_size)
413+
{
414+
struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps;
415+
struct v4l2_format *inp_f = inst->fmt_src;
416+
u32 height, width, mbs_per_second, mbpf;
417+
u64 fw_cycles, fw_vpp_cycles;
418+
u64 vsp_cycles, vpp_cycles;
419+
u32 fps = DEFAULT_FPS;
420+
421+
width = max(inp_f->fmt.pix_mp.width, inst->crop.width);
422+
height = max(inp_f->fmt.pix_mp.height, inst->crop.height);
423+
424+
mbpf = NUM_MBS_PER_FRAME(height, width);
425+
mbs_per_second = mbpf * fps;
426+
427+
fw_cycles = fps * caps->mb_cycles_fw;
428+
fw_vpp_cycles = fps * caps->mb_cycles_fw_vpp;
429+
430+
vpp_cycles = mult_frac(mbs_per_second, caps->mb_cycles_vpp, (u32)inst->fw_caps[PIPE].value);
431+
/* 21 / 20 is minimum overhead factor */
432+
vpp_cycles += max(div_u64(vpp_cycles, 20), fw_vpp_cycles);
433+
434+
/* 1.059 is multi-pipe overhead */
435+
if (inst->fw_caps[PIPE].value > 1)
436+
vpp_cycles += div_u64(vpp_cycles * 59, 1000);
437+
438+
vsp_cycles = fps * data_size * 8;
439+
vsp_cycles = div_u64(vsp_cycles, 2);
440+
/* VSP FW overhead 1.05 */
441+
vsp_cycles = div_u64(vsp_cycles * 21, 20);
442+
443+
if (inst->fw_caps[STAGE].value == STAGE_1)
444+
vsp_cycles = vsp_cycles * 3;
445+
446+
return max3(vpp_cycles, vsp_cycles, fw_cycles);
447+
}
448+
308449
int iris_vpu_power_on(struct iris_core *core)
309450
{
310451
u32 freq;

drivers/media/platform/qcom/iris/iris_vpu_common.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,9 @@ int iris_vpu_power_on(struct iris_core *core);
3333
int iris_vpu_power_off_controller(struct iris_core *core);
3434
void iris_vpu_power_off_hw(struct iris_core *core);
3535
void iris_vpu_power_off(struct iris_core *core);
36+
int iris_vpu35_vpu4x_power_off_controller(struct iris_core *core);
37+
int iris_vpu35_vpu4x_power_on_controller(struct iris_core *core);
38+
void iris_vpu35_vpu4x_program_bootup_registers(struct iris_core *core);
39+
u64 iris_vpu3x_vpu4x_calculate_frequency(struct iris_inst *inst, size_t data_size);
3640

3741
#endif

0 commit comments

Comments
 (0)