From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1794338254; b=a5rRwCa2ZasVWhNq/QhzTO1O4B5TJ5EchoJvcyrkwYJ6mSPW9/kHQgA85jVBJA4FqZoK IyUq2JYLGb0j8QZ4CTU+wX8+NOHeHJYqiKgMrMooUDmJ1BChT5+ZVaXxh/pWKSpVPigg9 B/8iGcdK7FDIvexQl2HlnXJpKVVcunvY3897t89cCFRT1C5h522cRYcexAmsxha9e83pK y84CyOpflq6iIzdco/fKZf6OPGkfC9iKhleeyMgHwmdc71FflYn7t114bmGF9TrNcz/zG SAs9bYm4aRhee0YdhgLo5iLebp//w47NDfohTZdbXPzLdoELF/EZrtf7fniV2bHUdIw== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1794338254; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding; bh=Xxbpw+k4P/MZLDzUWxcWXzqg+33+os7zj/R+wyZlXb4=; b=E5WxswwNCybLbVeLP7YhD6dm6m/ILgi5YvzoVgBwugQrNJUQ+msctCSbQ+BEwV5s+qUY b3jH4mmYft60iK6U1VGHR5C4mjr0LYZwCcCXORK9XtsPJRUD7sx6MWqaN9Ko21Nef/Kj1 Rn9cQmpP1mn8OjFDb0JETzWWiRl4tG9hnpCPICtb5gDlvTZ7BZLXxiCtNruN2gt8iJraa Yyi0VjaCHNThaz17PsVyF29WFC2rYFucNFUbvItZA0aPki9ZLxkRh0Zs9dcNYQ9RLAhyp JaEOPo/fC1M0G8H50bkKnvwytSWEC+MnFX4GavvtsRXByJ+/t9aQtsamwyrUHI+QDeQ== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b="Go93aCY/"; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 37C69606A326 for ; Tue, 10 Nov 2026 19:17:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=Go93aCY/ Received: by smtp.kernel.org (Postfix) with ESMTPSA id E89291F008A6; Tue, 10 Nov 2026 19:17:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1794338253; bh=Xxbpw+k4P/MZLDzUWxcWXzqg+33+os7zj/R+wyZlXb4=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Go93aCY/Jo+HyKRCMVa+yDIDLNQ777NXS4wQRrSTJy/cj8TbnidsigQKVdt+wlMqA 9NvNDledlqIitiw46fu6JW1bnkOxRe3WwkEmog9bTT4TTZ4dm32ktd2/2L3/Zp1t80 1MVG+aEM5bPv2+KL1QnfMP7i6HJR6Vnhn4yzQM6KPEvTQxlBuRqbOcajOJsznnuZQo PoBg7FyU3SwLUCR6vLqUnGb6cN+3hnU+3JZNkzsmI5iC0id8w3emVo+nR510YFSJrr q2+CBrN0hVfqgiXB5jNk9BPi5uOrsrtX/559NxCNP4eg3YNZsq2/yaE8Q/ymVBz/7k BKUdz6qNgMyDA== From: Sasha Levin To: stable@vger.kernel.org Cc: Vikash Garodia , Bryan O'Donoghue , Vishnu Reddy , Dikshita Agarwal , Bryan O'Donoghue , Hans Verkuil , Sasha Levin Subject: [PATCH 6.18.y 2/3] media: iris: Move vpu35 specific api to common to use for vpu4 Date: Tue, 10 Nov 2026 14:17:28 -0500 Message-ID: <20261110191435.3457367-2-sashal@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20261110191435.3457367-1-sashal@kernel.org> References: <20261107050739-failed-6.18-9cfae7726a9a@kernel.org> <20261110191435.3457367-1-sashal@kernel.org> X-Mailing-List: stable@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Vikash Garodia [ Upstream commit 82b96a8d8d6ebedcda8ef2d051ddd0f43d8eee14 ] 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 Co-developed-by: Vishnu Reddy Signed-off-by: Vishnu Reddy Signed-off-by: Vikash Garodia Reviewed-by: Dikshita Agarwal Signed-off-by: Bryan O'Donoghue Signed-off-by: Hans Verkuil Stable-dep-of: 9cfae7726a9a ("media: iris: Fix power-off ordering to disable power domain after clocks") Signed-off-by: Sasha Levin --- drivers/media/platform/qcom/iris/iris_vpu3x.c | 157 +----------------- .../platform/qcom/iris/iris_vpu_common.c | 141 ++++++++++++++++ .../platform/qcom/iris/iris_vpu_common.h | 4 + 3 files changed, 151 insertions(+), 151 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_vpu3x.c b/drivers/media/platform/qcom/iris/iris_vpu3x.c index cd53bcda3b3e1..fe4423b951b1e 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_vpu3x.c @@ -16,8 +16,6 @@ #define AON_WRAPPER_MVP_NOC_CORE_CLK_CONTROL (AON_BASE_OFFS + 0x20) #define NOC_HALT BIT(0) #define AON_WRAPPER_SPARE (AON_BASE_OFFS + 0x28) -#define AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL (AON_BASE_OFFS + 0x2C) -#define AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS (AON_BASE_OFFS + 0x30) static bool iris_vpu3x_hw_power_collapsed(struct iris_core *core) { @@ -262,155 +260,12 @@ static void iris_vpu35_power_off_hw(struct iris_core *core) iris_disable_unprepare_clock(core, IRIS_AXI_CLK); } -static int iris_vpu35_power_off_controller(struct iris_core *core) -{ - u32 clk_rst_tbl_size = core->iris_platform_data->clk_rst_tbl_size; - unsigned int count = 0; - u32 val = 0; - bool handshake_done, handshake_busy; - int ret; - - writel(MSK_SIGNAL_FROM_TENSILICA | MSK_CORE_POWER_ON, core->reg_base + CPU_CS_X2RPMH); - - writel(REQ_POWER_DOWN_PREP, core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_CONTROL); - - ret = readl_poll_timeout(core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_STATUS, - val, val & BIT(0), 200, 2000); - if (ret) - goto disable_power; - - writel(0, core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_CONTROL); - - /* Retry up to 1000 times as recommended by hardware documentation */ - do { - /* set MNoC to low power */ - writel(REQ_POWER_DOWN_PREP, core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL); - - udelay(15); - - val = readl(core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS); - - handshake_done = val & NOC_LPI_STATUS_DONE; - handshake_busy = val & (NOC_LPI_STATUS_DENY | NOC_LPI_STATUS_ACTIVE); - - if (handshake_done || !handshake_busy) - break; - - writel(0, core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL); - - udelay(15); - - } while (++count < 1000); - - if (!handshake_done && handshake_busy) - dev_err(core->dev, "LPI handshake timeout\n"); - - ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS, - val, val & BIT(0), 200, 2000); - if (ret) - goto disable_power; - - writel(0, core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL); - - writel(0, core->reg_base + WRAPPER_DEBUG_BRIDGE_LPI_CONTROL); - - ret = readl_poll_timeout(core->reg_base + WRAPPER_DEBUG_BRIDGE_LPI_STATUS, - val, val == 0, 200, 2000); - if (ret) - goto disable_power; - -disable_power: - iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); - iris_disable_unprepare_clock(core, IRIS_CTRL_FREERUN_CLK); - iris_disable_unprepare_clock(core, IRIS_AXI1_CLK); - - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); - - reset_control_bulk_reset(clk_rst_tbl_size, core->resets); - - return 0; -} - -static int iris_vpu35_power_on_controller(struct iris_core *core) -{ - int ret; - - ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); - if (ret) - return ret; - - ret = iris_prepare_enable_clock(core, IRIS_AXI1_CLK); - if (ret) - goto err_disable_power; - - ret = iris_prepare_enable_clock(core, IRIS_CTRL_FREERUN_CLK); - if (ret) - goto err_disable_axi1_clk; - - ret = iris_prepare_enable_clock(core, IRIS_CTRL_CLK); - if (ret) - goto err_disable_ctrl_free_clk; - - return 0; - -err_disable_ctrl_free_clk: - iris_disable_unprepare_clock(core, IRIS_CTRL_FREERUN_CLK); -err_disable_axi1_clk: - iris_disable_unprepare_clock(core, IRIS_AXI1_CLK); -err_disable_power: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); - - return ret; -} - -static void iris_vpu35_program_bootup_registers(struct iris_core *core) -{ - writel(0x1, core->reg_base + WRAPPER_IRIS_VCODEC_VPU_WRAPPER_SPARE_0); -} - -static u64 iris_vpu3x_calculate_frequency(struct iris_inst *inst, size_t data_size) -{ - struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps; - struct v4l2_format *inp_f = inst->fmt_src; - u32 height, width, mbs_per_second, mbpf; - u64 fw_cycles, fw_vpp_cycles; - u64 vsp_cycles, vpp_cycles; - u32 fps = DEFAULT_FPS; - - width = max(inp_f->fmt.pix_mp.width, inst->crop.width); - height = max(inp_f->fmt.pix_mp.height, inst->crop.height); - - mbpf = NUM_MBS_PER_FRAME(height, width); - mbs_per_second = mbpf * fps; - - fw_cycles = fps * caps->mb_cycles_fw; - fw_vpp_cycles = fps * caps->mb_cycles_fw_vpp; - - vpp_cycles = mult_frac(mbs_per_second, caps->mb_cycles_vpp, (u32)inst->fw_caps[PIPE].value); - /* 21 / 20 is minimum overhead factor */ - vpp_cycles += max(div_u64(vpp_cycles, 20), fw_vpp_cycles); - - /* 1.059 is multi-pipe overhead */ - if (inst->fw_caps[PIPE].value > 1) - vpp_cycles += div_u64(vpp_cycles * 59, 1000); - - vsp_cycles = fps * data_size * 8; - vsp_cycles = div_u64(vsp_cycles, 2); - /* VSP FW overhead 1.05 */ - vsp_cycles = div_u64(vsp_cycles * 21, 20); - - if (inst->fw_caps[STAGE].value == STAGE_1) - vsp_cycles = vsp_cycles * 3; - - return max3(vpp_cycles, vsp_cycles, fw_cycles); -} - const struct vpu_ops iris_vpu3_ops = { .power_off_hw = iris_vpu3_power_off_hardware, .power_on_hw = iris_vpu_power_on_hw, .power_off_controller = iris_vpu_power_off_controller, .power_on_controller = iris_vpu_power_on_controller, - .calc_freq = iris_vpu3x_calculate_frequency, + .calc_freq = iris_vpu3x_vpu4x_calculate_frequency, }; const struct vpu_ops iris_vpu33_ops = { @@ -418,14 +273,14 @@ const struct vpu_ops iris_vpu33_ops = { .power_on_hw = iris_vpu_power_on_hw, .power_off_controller = iris_vpu33_power_off_controller, .power_on_controller = iris_vpu_power_on_controller, - .calc_freq = iris_vpu3x_calculate_frequency, + .calc_freq = iris_vpu3x_vpu4x_calculate_frequency, }; const struct vpu_ops iris_vpu35_ops = { .power_off_hw = iris_vpu35_power_off_hw, .power_on_hw = iris_vpu35_power_on_hw, - .power_off_controller = iris_vpu35_power_off_controller, - .power_on_controller = iris_vpu35_power_on_controller, - .program_bootup_registers = iris_vpu35_program_bootup_registers, - .calc_freq = iris_vpu3x_calculate_frequency, + .power_off_controller = iris_vpu35_vpu4x_power_off_controller, + .power_on_controller = iris_vpu35_vpu4x_power_on_controller, + .program_bootup_registers = iris_vpu35_vpu4x_program_bootup_registers, + .calc_freq = iris_vpu3x_vpu4x_calculate_frequency, }; diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c index 38a11002327db..8367540163f2d 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c @@ -8,9 +8,12 @@ #include #include "iris_core.h" +#include "iris_instance.h" #include "iris_vpu_common.h" #include "iris_vpu_register_defines.h" +#define AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL (AON_BASE_OFFS + 0x2C) +#define AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS (AON_BASE_OFFS + 0x30) #define CTRL_INIT (CPU_CS_BASE_OFFS + 0x48) #define CTRL_STATUS (CPU_CS_BASE_OFFS + 0x4C) @@ -289,6 +292,144 @@ int iris_vpu_power_on_hw(struct iris_core *core) return ret; } +int iris_vpu35_vpu4x_power_off_controller(struct iris_core *core) +{ + u32 clk_rst_tbl_size = core->iris_platform_data->clk_rst_tbl_size; + bool handshake_done, handshake_busy; + u32 count = 0, val = 0; + int ret; + + writel(MSK_SIGNAL_FROM_TENSILICA | MSK_CORE_POWER_ON, core->reg_base + CPU_CS_X2RPMH); + + writel(REQ_POWER_DOWN_PREP, core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_CONTROL); + + ret = readl_poll_timeout(core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_STATUS, + val, val & BIT(0), 200, 2000); + if (ret) + goto disable_power; + + writel(0, core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_CONTROL); + + /* Retry up to 1000 times as recommended by hardware documentation */ + do { + /* set MNoC to low power */ + writel(REQ_POWER_DOWN_PREP, core->reg_base + + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL); + usleep_range(10, 20); + val = readl(core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS); + + handshake_done = val & NOC_LPI_STATUS_DONE; + handshake_busy = val & (NOC_LPI_STATUS_DENY | NOC_LPI_STATUS_ACTIVE); + + if (handshake_done || !handshake_busy) + break; + + writel(0, core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL); + usleep_range(10, 20); + + } while (++count < 1000); + + if (!handshake_done && handshake_busy) + dev_err(core->dev, "LPI handshake timeout\n"); + + ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS, + val, val & BIT(0), 200, 2000); + if (ret) + goto disable_power; + + writel(0, core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL); + + writel(0, core->reg_base + WRAPPER_DEBUG_BRIDGE_LPI_CONTROL); + + readl_poll_timeout(core->reg_base + WRAPPER_DEBUG_BRIDGE_LPI_STATUS, + val, val == 0, 200, 2000); + +disable_power: + iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); + iris_disable_unprepare_clock(core, IRIS_CTRL_FREERUN_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI1_CLK); + + iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + + reset_control_bulk_reset(clk_rst_tbl_size, core->resets); + + return 0; +} + +int iris_vpu35_vpu4x_power_on_controller(struct iris_core *core) +{ + int ret; + + ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + if (ret) + return ret; + + ret = iris_prepare_enable_clock(core, IRIS_AXI1_CLK); + if (ret) + goto err_disable_power; + + ret = iris_prepare_enable_clock(core, IRIS_CTRL_FREERUN_CLK); + if (ret) + goto err_disable_axi1_clk; + + ret = iris_prepare_enable_clock(core, IRIS_CTRL_CLK); + if (ret) + goto err_disable_ctrl_free_clk; + + return 0; + +err_disable_ctrl_free_clk: + iris_disable_unprepare_clock(core, IRIS_CTRL_FREERUN_CLK); +err_disable_axi1_clk: + iris_disable_unprepare_clock(core, IRIS_AXI1_CLK); +err_disable_power: + iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + + return ret; +} + +void iris_vpu35_vpu4x_program_bootup_registers(struct iris_core *core) +{ + writel(0x1, core->reg_base + WRAPPER_IRIS_VCODEC_VPU_WRAPPER_SPARE_0); +} + +u64 iris_vpu3x_vpu4x_calculate_frequency(struct iris_inst *inst, size_t data_size) +{ + struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps; + struct v4l2_format *inp_f = inst->fmt_src; + u32 height, width, mbs_per_second, mbpf; + u64 fw_cycles, fw_vpp_cycles; + u64 vsp_cycles, vpp_cycles; + u32 fps = DEFAULT_FPS; + + width = max(inp_f->fmt.pix_mp.width, inst->crop.width); + height = max(inp_f->fmt.pix_mp.height, inst->crop.height); + + mbpf = NUM_MBS_PER_FRAME(height, width); + mbs_per_second = mbpf * fps; + + fw_cycles = fps * caps->mb_cycles_fw; + fw_vpp_cycles = fps * caps->mb_cycles_fw_vpp; + + vpp_cycles = mult_frac(mbs_per_second, caps->mb_cycles_vpp, (u32)inst->fw_caps[PIPE].value); + /* 21 / 20 is minimum overhead factor */ + vpp_cycles += max(div_u64(vpp_cycles, 20), fw_vpp_cycles); + + /* 1.059 is multi-pipe overhead */ + if (inst->fw_caps[PIPE].value > 1) + vpp_cycles += div_u64(vpp_cycles * 59, 1000); + + vsp_cycles = fps * data_size * 8; + vsp_cycles = div_u64(vsp_cycles, 2); + /* VSP FW overhead 1.05 */ + vsp_cycles = div_u64(vsp_cycles * 21, 20); + + if (inst->fw_caps[STAGE].value == STAGE_1) + vsp_cycles = vsp_cycles * 3; + + return max3(vpp_cycles, vsp_cycles, fw_cycles); +} + int iris_vpu_power_on(struct iris_core *core) { u32 freq; diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h index d636e287457ad..7cf4304604cca 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.h @@ -33,5 +33,9 @@ int iris_vpu_power_on(struct iris_core *core); int iris_vpu_power_off_controller(struct iris_core *core); void iris_vpu_power_off_hw(struct iris_core *core); void iris_vpu_power_off(struct iris_core *core); +int iris_vpu35_vpu4x_power_off_controller(struct iris_core *core); +int iris_vpu35_vpu4x_power_on_controller(struct iris_core *core); +void iris_vpu35_vpu4x_program_bootup_registers(struct iris_core *core); +u64 iris_vpu3x_vpu4x_calculate_frequency(struct iris_inst *inst, size_t data_size); #endif -- 2.53.0