Hi Thomas,

On Fri Jun 20, 2025 at 1:02 PM CEST, Thomas Zimmermann wrote:
> Hi
>
> Am 20.06.25 um 12:31 schrieb Luca Weiss:
>> Some devices might require keeping an interconnect path alive so that
>> the framebuffer continues working. Add support for that by setting the
>> bandwidth requirements appropriately for all provided interconnect
>> paths.
>>
>> Signed-off-by: Luca Weiss <luca.we...@fairphone.com>
>> ---
>>   drivers/video/fbdev/simplefb.c | 83 
>> ++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 83 insertions(+)
>>
>> diff --git a/drivers/video/fbdev/simplefb.c b/drivers/video/fbdev/simplefb.c
>> index 
>> be95fcddce4c8ca794826b805cd7dad2985bd637..ca73e079fd13550ddc779e84db80f7f9b743d074
>>  100644
>> --- a/drivers/video/fbdev/simplefb.c
>> +++ b/drivers/video/fbdev/simplefb.c
>> @@ -27,6 +27,7 @@
>>   #include <linux/parser.h>
>>   #include <linux/pm_domain.h>
>>   #include <linux/regulator/consumer.h>
>> +#include <linux/interconnect.h>
>
> With alphabetical sorting:
>
> Reviewed-by: Thomas Zimmermann <tzimmerm...@suse.de>

Thanks for the reviews!

For both simpledrm.c and simplefb.c, the includes are not strictly
alphabetically sorted (1 mis-sort in simpledrm, 3 in simplefb), shall I
just try and slot it into the best fitting place, or make them sorted in
my patch? Or I can add a separate commit for each driver before to sort
them.

Let me know!

Regards
Luca


>
> Best regards
> Thomas
>
>
>>   
>>   static const struct fb_fix_screeninfo simplefb_fix = {
>>      .id             = "simple",
>> @@ -89,6 +90,10 @@ struct simplefb_par {
>>      u32 regulator_count;
>>      struct regulator **regulators;
>>   #endif
>> +#if defined CONFIG_OF && defined CONFIG_INTERCONNECT
>> +    unsigned int icc_count;
>> +    struct icc_path **icc_paths;
>> +#endif
>>   };
>>   
>>   static void simplefb_clocks_destroy(struct simplefb_par *par);
>> @@ -525,6 +530,80 @@ static int simplefb_attach_genpds(struct simplefb_par 
>> *par,
>>   }
>>   #endif
>>   
>> +#if defined CONFIG_OF && defined CONFIG_PM_GENERIC_DOMAINS
>> +/*
>> + * Generic interconnect path handling code.
>> + */
>> +static void simplefb_detach_icc(void *res)
>> +{
>> +    struct simplefb_par *par = res;
>> +    int i;
>> +
>> +    for (i = par->icc_count - 1; i >= 0; i--) {
>> +            if (!IS_ERR_OR_NULL(par->icc_paths[i]))
>> +                    icc_put(par->icc_paths[i]);
>> +    }
>> +}
>> +
>> +static int simplefb_attach_icc(struct simplefb_par *par,
>> +                           struct platform_device *pdev)
>> +{
>> +    struct device *dev = &pdev->dev;
>> +    int ret, count, i;
>> +
>> +    count = of_count_phandle_with_args(dev->of_node, "interconnects",
>> +                                                     "#interconnect-cells");
>> +    if (count < 0)
>> +            return 0;
>> +
>> +    /* An interconnect path consists of two elements */
>> +    if (count % 2) {
>> +            dev_err(dev, "invalid interconnects value\n");
>> +            return -EINVAL;
>> +    }
>> +    par->icc_count = count / 2;
>> +
>> +    par->icc_paths = devm_kcalloc(dev, par->icc_count,
>> +                                  sizeof(*par->icc_paths),
>> +                                  GFP_KERNEL);
>> +    if (!par->icc_paths)
>> +            return -ENOMEM;
>> +
>> +    for (i = 0; i < par->icc_count; i++) {
>> +            par->icc_paths[i] = of_icc_get_by_index(dev, i);
>> +            if (IS_ERR_OR_NULL(par->icc_paths[i])) {
>> +                    ret = PTR_ERR(par->icc_paths[i]);
>> +                    if (ret == -EPROBE_DEFER)
>> +                            goto err;
>> +                    dev_err(dev, "failed to get interconnect path %u: 
>> %d\n", i, ret);
>> +                    continue;
>> +            }
>> +
>> +            ret = icc_set_bw(par->icc_paths[i], 0, UINT_MAX);
>> +            if (ret) {
>> +                    dev_err(dev, "failed to set interconnect bandwidth %u: 
>> %d\n", i, ret);
>> +                    continue;
>> +            }
>> +    }
>> +
>> +    return devm_add_action_or_reset(dev, simplefb_detach_icc, par);
>> +
>> +err:
>> +    while (i) {
>> +            --i;
>> +            if (!IS_ERR_OR_NULL(par->icc_paths[i]))
>> +                    icc_put(par->icc_paths[i]);
>> +    }
>> +    return ret;
>> +}
>> +#else
>> +static int simplefb_attach_icc(struct simplefb_par *par,
>> +                           struct platform_device *pdev)
>> +{
>> +    return 0;
>> +}
>> +#endif
>> +
>>   static int simplefb_probe(struct platform_device *pdev)
>>   {
>>      int ret;
>> @@ -615,6 +694,10 @@ static int simplefb_probe(struct platform_device *pdev)
>>      if (ret < 0)
>>              goto error_regulators;
>>   
>> +    ret = simplefb_attach_icc(par, pdev);
>> +    if (ret < 0)
>> +            goto error_regulators;
>> +
>>      simplefb_clocks_enable(par, pdev);
>>      simplefb_regulators_enable(par, pdev);
>>   
>>

Reply via email to