Re: [PATCH v4 4/6] media: qcom: camss: share VFE clock sources by the highest rate

From: Loic Poulain

Date: Wed Oct 28 2026 - 10:42:26 EST


On Wed, Oct 28, 2026 at 2:24 PM Atanas Filipov
<atanas.filipov@xxxxxxxxxxxxxxxx> wrote:
>
> Clocks of different VFEs can be fed by one clock source, and each VFE
> sets such a source to the rate it needs. A VFE started later at a lower
> rate then lowers the source under a VFE that is still running.
>
> For example, on SM8250 the two VFE Lite share one core clock source,
> which the VFE sets to 400 or 480 MHz from the pixel rate. With VFE Lite
> 0 streaming the CSID test pattern at 480 MHz, starting an imx577 stream
> on VFE Lite 1 sets the shared source to 400 MHz under the running VFE
> Lite 0.
>
> Request the VFE clock rates as minimums with clk_set_rate_range(), so
> that a shared clock runs at the highest minimum of its running VFEs.
> On power off the VFE drops its minimum and sets the clock to its lowest
> listed rate within the remaining minimums.
>
> Suggested-by: Bryan O'Donoghue <bryan.odonoghue@xxxxxxxxxx>
> Signed-off-by: Atanas Filipov <atanas.filipov@xxxxxxxxxxxxxxxx>

Reviewed-by: Loic Poulain <loic.poulain@xxxxxxxxxxxxxxxx>

> ---
> Changes in v4:
> - Use clk_set_rate_range() on all SoCs, drop the vfe_clock_ranges flag
> (Loic Poulain, Bryan O'Donoghue)
> - Add Suggested-by (Bryan O'Donoghue)
>
> drivers/media/platform/qcom/camss/camss-vfe.c | 39 +++++++++++++++++--
> 1 file changed, 35 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c
> index bcc2c1929af1..46674bc30e6a 100644
> --- a/drivers/media/platform/qcom/camss/camss-vfe.c
> +++ b/drivers/media/platform/qcom/camss/camss-vfe.c
> @@ -1037,7 +1037,7 @@ static int vfe_set_clock_rates(struct vfe_device *vfe)
> return -EINVAL;
> }
>
> - ret = clk_set_rate(clock->clk, rate);
> + ret = clk_set_rate_range(clock->clk, clock->freq[j], ULONG_MAX);
> if (ret < 0) {
> dev_err(dev, "clk set rate failed: %d\n", ret);
> return ret;
> @@ -1088,6 +1088,34 @@ static int vfe_check_clock_rates(struct vfe_device *vfe)
> return 0;
> }
>
> +/*
> + * vfe_release_clock_rates - Release the minimum clock rates of VFE module
> + * @vfe: VFE device
> + *
> + * Drop the minimum rate requested by the VFE from each of its clocks and set
> + * the clock to its lowest level, or to the highest minimum rate still
> + * requested by the other users of the clock.
> + */
> +static void vfe_release_clock_rates(struct vfe_device *vfe)
> +{
> + int i;
> +
> + for (i = 0; i < vfe->nclocks; i++) {
> + struct camss_clock *clock = &vfe->clock[i];
> + long rate;
> +
> + if (!vfe_match_clock_names(vfe, clock) || !vfe_check_clock_levels(clock))
> + continue;
> +
> + clk_drop_range(clock->clk);
> +
> + /* Round first, so that the rate respects the other users' ranges */
> + rate = clk_round_rate(clock->clk, clock->freq[0]);
> + if (rate > 0)
> + clk_set_rate(clock->clk, rate);
> + }
> +}
> +
> /*
> * vfe_get - Power up and reset VFE module
> * @vfe: VFE Device
> @@ -1111,12 +1139,12 @@ int vfe_get(struct vfe_device *vfe)
>
> ret = vfe_set_clock_rates(vfe);
> if (ret < 0)
> - goto error_pm_runtime_get;
> + goto error_release_rates;
>
> ret = camss_enable_clocks(vfe->nclocks, vfe->clock,
> vfe->camss->dev);
> if (ret < 0)
> - goto error_pm_runtime_get;
> + goto error_release_rates;
>
> ret = vfe_reset(vfe);
> if (ret < 0)
> @@ -1141,7 +1169,9 @@ int vfe_get(struct vfe_device *vfe)
> error_reset:
> camss_disable_clocks(vfe->nclocks, vfe->clock);
>
> -error_pm_runtime_get:
> +error_release_rates:
> + vfe_release_clock_rates(vfe);
> +
> pm_runtime_put_sync(vfe->camss->dev);
> error_domain_off:
> vfe->res->hw_ops->pm_domain_off(vfe);
> @@ -1169,6 +1199,7 @@ void vfe_put(struct vfe_device *vfe)
> vfe->res->hw_ops->vfe_halt(vfe);
> }
> camss_disable_clocks(vfe->nclocks, vfe->clock);
> + vfe_release_clock_rates(vfe);
> pm_runtime_put_sync(vfe->camss->dev);
> vfe->res->hw_ops->pm_domain_off(vfe);
> }
> --
> 2.34.1
>