[drm-intel:for-linux-next-gt 1/4] drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c:2680 guc_context_policy_init_v70() warn: variable dereferenced before check 'ce' (see line 2663)

2024-03-10 Thread Dan Carpenter
tree:   git://anongit.freedesktop.org/drm-intel for-linux-next-gt
head:   7ad6a8fae597af7fae5193efc73276609337c360
commit: cec82816d0d018f178b9b7f88fe4bf80d66954e9 [1/4] drm/i915/guc: Use 
context hints for GT frequency
config: i386-randconfig-141-20240309 
(https://download.01.org/0day-ci/archive/20240310/202403101225.7ahejhzj-...@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot 
| Reported-by: Dan Carpenter 
| Closes: https://lore.kernel.org/r/202403101225.7ahejhzj-...@intel.com/

New smatch warnings:
drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c:2680 
guc_context_policy_init_v70() warn: variable dereferenced before check 'ce' 
(see line 2663)

vim +/ce +2680 drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c

774ce1510e6ccb Daniele Ceraolo Spurio 2022-07-18  2661  static int 
guc_context_policy_init_v70(struct intel_context *ce, bool loop)
2584b3549f4c40 John Harrison  2022-04-12  2662  {
2584b3549f4c40 John Harrison  2022-04-12 @2663  struct 
intel_engine_cs *engine = ce->engine;

 ^^
Unchecked dereference

3f2f20da79b208 Andi Shyti 2023-12-29  2664  struct 
intel_guc *guc = gt_to_guc(engine->gt);
2584b3549f4c40 John Harrison  2022-04-12  2665  struct 
context_policy policy;
2584b3549f4c40 John Harrison  2022-04-12  2666  u32 
execution_quantum;
2584b3549f4c40 John Harrison  2022-04-12  2667  u32 
preemption_timeout;
cec82816d0d018 Vinay Belgaumkar   2024-03-05  2668  u32 
slpc_ctx_freq_req = 0;
2584b3549f4c40 John Harrison  2022-04-12  2669  unsigned long 
flags;
2584b3549f4c40 John Harrison  2022-04-12  2670  int ret;
3a4bfa091c46e9 Rahul Kumar Singh  2021-07-26  2671  
7935785240508c John Harrison  2021-07-26  2672  /* NB: For both 
of these, zero means disabled. */
568944af44e753 John Harrison  2022-10-06  2673  
GEM_BUG_ON(overflows_type(engine->props.timeslice_duration_ms * 1000,
568944af44e753 John Harrison  2022-10-06  2674  
  execution_quantum));
568944af44e753 John Harrison  2022-10-06  2675  
GEM_BUG_ON(overflows_type(engine->props.preempt_timeout_ms * 1000,
568944af44e753 John Harrison  2022-10-06  2676  
  preemption_timeout));
2584b3549f4c40 John Harrison  2022-04-12  2677  
execution_quantum = engine->props.timeslice_duration_ms * 1000;
2584b3549f4c40 John Harrison  2022-04-12  2678  
preemption_timeout = engine->props.preempt_timeout_ms * 1000;
2584b3549f4c40 John Harrison  2022-04-12  2679  
cec82816d0d018 Vinay Belgaumkar   2024-03-05 @2680  if (ce && 
(ce->flags & BIT(CONTEXT_LOW_LATENCY)))
^^
NULL check is too late.

cec82816d0d018 Vinay Belgaumkar   2024-03-05  2681  
slpc_ctx_freq_req |= SLPC_CTX_FREQ_REQ_IS_COMPUTE;
cec82816d0d018 Vinay Belgaumkar   2024-03-05  2682  
2584b3549f4c40 John Harrison  2022-04-12  2683  
__guc_context_policy_start_klv(, ce->guc_id.id);
2584b3549f4c40 John Harrison  2022-04-12  2684  
2584b3549f4c40 John Harrison  2022-04-12  2685  
__guc_context_policy_add_priority(, ce->guc_state.prio);
2584b3549f4c40 John Harrison  2022-04-12  2686  
__guc_context_policy_add_execution_quantum(, execution_quantum);
2584b3549f4c40 John Harrison  2022-04-12  2687  
__guc_context_policy_add_preemption_timeout(, preemption_timeout);
cec82816d0d018 Vinay Belgaumkar   2024-03-05  2688  
__guc_context_policy_add_slpc_ctx_freq_req(, slpc_ctx_freq_req);
2584b3549f4c40 John Harrison  2022-04-12  2689  
2584b3549f4c40 John Harrison  2022-04-12  2690  if 
(engine->flags & I915_ENGINE_WANT_FORCED_PREEMPTION)
2584b3549f4c40 John Harrison  2022-04-12  2691  
__guc_context_policy_add_preempt_to_idle(, 1);
2584b3549f4c40 John Harrison  2022-04-12  2692  
2584b3549f4c40 John Harrison  2022-04-12  2693  ret = 
__guc_context_set_context_policies(guc, , loop);
2584b3549f4c40 John Harrison  2022-04-12  2694  
2584b3549f4c40 John Harrison  2022-04-12  2695  
spin_lock_irqsave(>guc_state.lock, flags);
6c82c75230b87d Daniele Ceraolo Spurio 2022-07-27  2696  if (ret != 0)
2584b3549f4c40 John Harrison  2022-04-12  2697  
set_context_policy_required(ce);
2584b3549f4c40 John Harrison  2022-04-12  2698  else
2584b

Re: [RFC PATCH 0/5] Add support for suppressing warning backtraces

2024-03-10 Thread Guenter Roeck
On Tue, Mar 05, 2024 at 10:40:28AM -0800, Guenter Roeck wrote:
> Some unit tests intentionally trigger warning backtraces by passing bad
> parameters to kernel API functions. Such unit tests typically check the
> return value from such calls, not the existence of the warning backtrace.
> 
> Such intentionally generated warning backtraces are neither desirable
> nor useful for a number of reasons.
> - They can result in overlooked real problems.
> - A warning that suddenly starts to show up in unit tests needs to be
>   investigated and has to be marked to be ignored, for example by
>   adjusting filter scripts. Such filters are ad-hoc because there is
>   no real standard format for warnings. On top of that, such filter
>   scripts would require constant maintenance.
> 
> One option to address problem would be to add messages such as "expected
> warning backtraces start / end here" to the kernel log.  However, that
> would again require filter scripts, it might result in missing real
> problematic warning backtraces triggered while the test is running, and
> the irrelevant backtrace(s) would still clog the kernel log.
> 
> Solve the problem by providing a means to identify and suppress specific
> warning backtraces while executing test code. Support suppressing multiple
> backtraces while at the same time limiting changes to generic code to the
> absolute minimum. Architecture specific changes are kept at minimum by
> retaining function names only if both CONFIG_DEBUG_BUGVERBOSE and
> CONFIG_KUNIT are enabled.
> 
> The first patch of the series introduces the necessary infrastructure.
> The second patch marks the warning message in drm_calc_scale() in the DRM
> subsystem as intentional where warranted. This patch is intended to serve
> as an example for the use of the functionality introduced with this series.
> The last three patches in the series introduce the necessary architecture
> specific changes for x86, arm64, and loongarch.
> 
> This series is based on the RFC patch and subsequent discussion at
> https://patchwork.kernel.org/project/linux-kselftest/patch/02546e59-1afe-4b08-ba81-d94f3b691c9a@moroto.mountain/
> and offers a more comprehensive solution of the problem discussed there.
> 
> Checkpatch note:
>   Remaining checkpatch errors and warnings were deliberately ignored.
>   Some are triggered by matching coding style or by comments interpreted
>   as code, others by assembler macros which are disliked by checkpatch.
>   Suggestions for improvements are welcome.
> 
> Some questions:
> 
> - Is the general approach promising ? If not, are there other possible
>   solutions ?
> - Function pointers are only added to the __bug_table section if both
>   CONFIG_KUNIT and CONFIG_DEBUG_BUGVERBOSE are enabled. This avoids image
>   size increases if CONFIG_KUNIT=n. Downside is slightly more complex
>   architecture specific assembler code. If function pointers were always
>   added to the __bug_table section, vmlinux image size would increase by
>   approximately 0.6-0.7%. Is the increased complexity in assembler code
>   worth the reduced image size ? I think so, but I would like to hear
>   other opinions.
> - There are additional possibilities associated with storing the bug
>   function name in the __bug_table section. It could be independent of
>   KUNIT, it could be a configuration flag, and/or it could be used to
>   display the name of the offending function in BUG/WARN messages.
>   Is any of those of interest ?
> 

I am ready to send a full version of this series with support for
all affected architectures. I am undecided if I should send it now,
based on v6.8, and send v2 after rebasing it to v6.9-rc1, or if I
should just wait for v6.9-rc1.

I understand that some maintainers dislike getting new patch series
while the commit window is is open. On the ther side, I tested the
series thoroughly on top of v6.8-rc7, and initial v6.9 release candidates
may have their own problems. Given that, I tend to send the series now.

Any thoughts ? Unless there is strong negative feedback, I'll likely
do that in a day or two.

Thanks,
Guenter


Re: [RFC PATCH net-next v6 01/15] queue_api: define queue api

2024-03-10 Thread David Ahern
On 3/8/24 4:47 PM, David Wei wrote:
> 
> I'm working to port bnxt over to using this API. What are your thoughts
> on maybe pulling this out and use bnxt to drive it?
> 

I would love to see a second nic implementation; this patch set and
overall design is driven by GVE limitations.



Re: [PATCH] drm/sun4i: tcon: Support keeping dclk rate upon ancestor clock changes

2024-03-10 Thread Ondřej Jirman
Hello Frank,

On Sun, Mar 10, 2024 at 02:32:29PM +0100, Frank Oltmanns wrote:
> +static int sun4i_rate_reset_notifier_cb(struct notifier_block *nb,
> +   unsigned long event, void *data)
> +{
> + struct sun4i_rate_reset_nb *rate_reset = to_sun4i_rate_reset_nb(nb);
> +
> + if (event == POST_RATE_CHANGE)
> + schedule_delayed_work(_reset->reset_rate_work, 
> msecs_to_jiffies(100));

If you get multiple reset notifier calls within 100ms of the first one,
the delay from the last one will not be 100ms, so this may violate expectations
you're describing in the commit message.

schedule_delayed_work doesn't re-schedule the work if it's already pending.

Kind regards,
o.


[drm-misc:drm-misc-next 1/1] drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c:843:6: error: variable 'out' set but not used

2024-03-10 Thread kernel test robot
tree:   git://anongit.freedesktop.org/drm/drm-misc drm-misc-next
head:   b219865715e419435ad49dc2300fe3f85c79d3f6
commit: d6eb77731c45caf6ee7b18d907e9bc44be760e8c [1/1] Merge drm/drm-next into 
drm-misc-next
config: x86_64-allyesconfig 
(https://download.01.org/0day-ci/archive/20240311/202403110614.law3uing-...@intel.com/config)
compiler: clang version 17.0.6 (https://github.com/llvm/llvm-project 
6009708b4367171ccdbf4b5905cb6a803753fe18)
reproduce (this is a W=1 build): 
(https://download.01.org/0day-ci/archive/20240311/202403110614.law3uing-...@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot 
| Closes: 
https://lore.kernel.org/oe-kbuild-all/202403110614.law3uing-...@intel.com/

All errors (new ones prefixed by >>):

>> drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c:843:6: error: variable 'out' set 
>> but not used [-Werror,-Wunused-but-set-variable]
 843 | u64 out = dumper->iova + A6XX_CD_DATA_OFFSET;
 | ^
   1 error generated.


vim +/out +843 drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c

64d6255650d4e0 Connor Abbott 2024-01-25  834  
1707add815519d Jordan Crouse 2018-11-02  835  /* Read a shader / debug block 
from the HLSQ aperture with the crashdumper */
1707add815519d Jordan Crouse 2018-11-02  836  static void 
a6xx_get_shader_block(struct msm_gpu *gpu,
d6852b4b2d0140 Jordan Crouse 2018-11-02  837struct a6xx_gpu_state 
*a6xx_state,
1707add815519d Jordan Crouse 2018-11-02  838const struct 
a6xx_shader_block *block,
1707add815519d Jordan Crouse 2018-11-02  839struct 
a6xx_gpu_state_obj *obj,
1707add815519d Jordan Crouse 2018-11-02  840struct a6xx_crashdumper 
*dumper)
1707add815519d Jordan Crouse 2018-11-02  841  {
1707add815519d Jordan Crouse 2018-11-02  842u64 *in = dumper->ptr;
64d6255650d4e0 Connor Abbott 2024-01-25 @843u64 out = dumper->iova + 
A6XX_CD_DATA_OFFSET;
1707add815519d Jordan Crouse 2018-11-02  844size_t datasize = block->size * 
A6XX_NUM_SHADER_BANKS * sizeof(u32);
1707add815519d Jordan Crouse 2018-11-02  845int i;
1707add815519d Jordan Crouse 2018-11-02  846  
1707add815519d Jordan Crouse 2018-11-02  847if (WARN_ON(datasize > 
A6XX_CD_DATA_SIZE))
1707add815519d Jordan Crouse 2018-11-02  848return;
1707add815519d Jordan Crouse 2018-11-02  849  
1707add815519d Jordan Crouse 2018-11-02  850for (i = 0; i < 
A6XX_NUM_SHADER_BANKS; i++) {
1707add815519d Jordan Crouse 2018-11-02  851in += 
CRASHDUMP_WRITE(in, REG_A6XX_HLSQ_DBG_READ_SEL,
1707add815519d Jordan Crouse 2018-11-02  852(block->type << 
8) | i);
1707add815519d Jordan Crouse 2018-11-02  853  
1707add815519d Jordan Crouse 2018-11-02  854in += 
CRASHDUMP_READ(in, REG_A6XX_HLSQ_DBG_AHB_READ_APERTURE,
1707add815519d Jordan Crouse 2018-11-02  855block->size, 
dumper->iova + A6XX_CD_DATA_OFFSET);
64d6255650d4e0 Connor Abbott 2024-01-25  856  
64d6255650d4e0 Connor Abbott 2024-01-25  857out += block->size * 
sizeof(u32);
1707add815519d Jordan Crouse 2018-11-02  858}
1707add815519d Jordan Crouse 2018-11-02  859  
1707add815519d Jordan Crouse 2018-11-02  860CRASHDUMP_FINI(in);
1707add815519d Jordan Crouse 2018-11-02  861  
1707add815519d Jordan Crouse 2018-11-02  862if (a6xx_crashdumper_run(gpu, 
dumper))
1707add815519d Jordan Crouse 2018-11-02  863return;
1707add815519d Jordan Crouse 2018-11-02  864  
1707add815519d Jordan Crouse 2018-11-02  865obj->handle = block;
d6852b4b2d0140 Jordan Crouse 2018-11-02  866obj->data = 
state_kmemdup(a6xx_state, dumper->ptr + A6XX_CD_DATA_OFFSET,
d6852b4b2d0140 Jordan Crouse 2018-11-02  867datasize);
1707add815519d Jordan Crouse 2018-11-02  868  }
1707add815519d Jordan Crouse 2018-11-02  869  

:: The code at line 843 was first introduced by commit
:: 64d6255650d4e0ff816cd303a43685f65c5a0dbb drm/msm: More fully implement 
devcoredump for a7xx

:: TO: Connor Abbott 
:: CC: Rob Clark 

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


[PATCH RESEND] drm: panel-orientation-quirks: Add quirk for Aya Neo KUN

2024-03-10 Thread tjakobi
From: Tobias Jakobi 

Similar to the other Aya Neo devices this one features
again a portrait screen, here with a native resolution
of 1600x2560.

Signed-off-by: Tobias Jakobi 
---
 drivers/gpu/drm/drm_panel_orientation_quirks.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c 
b/drivers/gpu/drm/drm_panel_orientation_quirks.c
index 3d92f66e550c..5d3fb11fd45f 100644
--- a/drivers/gpu/drm/drm_panel_orientation_quirks.c
+++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c
@@ -196,6 +196,12 @@ static const struct dmi_system_id orientation_data[] = {
  DMI_MATCH(DMI_BOARD_NAME, "NEXT"),
},
.driver_data = (void *)_rightside_up,
+   }, {/* AYA NEO KUN */
+   .matches = {
+ DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AYANEO"),
+ DMI_MATCH(DMI_BOARD_NAME, "KUN"),
+   },
+   .driver_data = (void *)_rightside_up,
}, {/* Chuwi HiBook (CWI514) */
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
-- 
2.43.0



[PATCH] drm: Don't return unsupported formats in drm_mode_legacy_fb_format

2024-03-10 Thread Frej Drejhammar
This patch changes drm_mode_legacy_fb_format() to only return formats
which are supported by the current drm-device. The motivation for this
change is to fix a regression introduced by commit
c91acda3a380 ("drm/gem: Check for valid formats") which stops the Xorg
modesetting driver from working on the Beagleboard Black (it uses the
tilcdc kernel driver).

When the Xorg modesetting driver starts up, it tries to determine the
default bpp for the device. It does this by allocating a dumb 32bpp
frame buffer (using DRM_IOCTL_MODE_CREATE_DUMB) and then calling
drmModeAddFB() with that frame buffer asking for a 24-bit depth and 32
bpp. As the modesetting driver uses drmModeAddFB() which doesn't
supply a format, the kernel's drm_mode_legacy_fb_format() is called to
provide a format matching the requested depth and bpp. If the
drmModeAddFB() call fails, it forces both depth and bpp to 24. If
drmModeAddFB() succeeds, depth is assumed to be 24 and bpp 32. The
dummy frame buffer is then removed (using drmModeRmFB()).

If the modesetting driver finds that both the default bpp and depth
are 24, it forces the use of a 32bpp shadow buffer and a 24bpp front
buffer. Following this, the driver reads the user-specified color
depth option and tries to create a framebuffer of that depth, but if
the use of a shadow buffer has been forced, the bpp and depth of it
overrides the user-supplied option.

The Xorg modesetting driver on top of the tilcdc kernel driver used to
work on the Beagleboard Black if a 16 bit color depth was
configured. The hardware in the Beagleboard Black supports the RG16,
BG24, and XB24 formats. When drm_mode_legacy_fb_format() was called to
request a format for a 24-bit depth and 32 bpp, it would return the
unsupported RG24 format which drmModeAddFB() would happily accept (as
there was no check for a valid format). As a shadow buffer wasn't
forced, the modesetting driver would try the user specified 16 bit
color depth and drm_mode_legacy_fb_format() would return RG16 which is
supported by the hardware. Color depths of 24 bits were not supported,
as the unsupported RG24 would be detected when drmModeSetCrtc() was
called.

Following commit c91acda3a380 ("drm/gem: Check for valid formats"),
which adds a check for a valid (supported by the hardware) format to
the code path for the kernel part of drmModeAddFB(), the modesetting
driver fails to configure and add a frame buffer. This is because the
call to create a 24-bit depth and 32 bpp framebuffer during detection
of the default bpp will now fail and a 24-bit depth and 24 bpp front
buffer will be forced. As drm_mode_legacy_fb_format() will return RG24
which isn't supported, the creation of that framebuffer will also
fail.

To fix the regression, this patch extends drm_mode_legacy_fb_format()
to list all formats with a particular bpp and color depth known to the
kernel, and have it probe the current drm-device for a supported
format. This fixes the regression and, as a bonus, a color depth of 24
bits on the Beagleboard Black is now working.

As this patch changes drm_mode_legacy_fb_format() which is used by
other drivers, it has, in addition to the Beagleboard Black, also been
tested with the nouveau and modesetting drivers on a NVIDIA NV96, and
with the intel and modesetting drivers on an intel HD Graphics 4000
chipset.

Signed-off-by: Frej Drejhammar 
Fixes: c91acda3a380 ("drm/gem: Check for valid formats")
Cc: sta...@vger.kernel.org
Cc: Russell King 
Cc: David Airlie 
Cc: Daniel Vetter 
Cc: Maarten Lankhorst 
Cc: Maxime Ripard 
Cc: Thomas Zimmermann 
Cc: Krzysztof Kozlowski 
Cc: Patrik Jakobsson 
Cc: Rob Clark 
Cc: Abhinav Kumar 
Cc: Dmitry Baryshkov 
Cc: Tomi Valkeinen 
Cc: Javier Martinez Canillas 
Cc: "Maíra Canal" 
Cc: "Ville Syrjälä" 
Cc: dri-devel@lists.freedesktop.org
---
 drivers/gpu/drm/armada/armada_fbdev.c |  2 +-
 drivers/gpu/drm/drm_fb_helper.c   |  2 +-
 drivers/gpu/drm/drm_fbdev_dma.c   |  3 +-
 drivers/gpu/drm/drm_fbdev_generic.c   |  3 +-
 drivers/gpu/drm/drm_fourcc.c  | 91 ---
 drivers/gpu/drm/exynos/exynos_drm_fbdev.c |  3 +-
 drivers/gpu/drm/gma500/fbdev.c|  2 +-
 drivers/gpu/drm/i915/display/intel_fbdev_fb.c |  3 +-
 drivers/gpu/drm/msm/msm_fbdev.c   |  3 +-
 drivers/gpu/drm/omapdrm/omap_fbdev.c  |  2 +-
 drivers/gpu/drm/radeon/radeon_fbdev.c |  3 +-
 drivers/gpu/drm/tegra/fbdev.c |  3 +-
 drivers/gpu/drm/tiny/ofdrm.c  |  6 +-
 drivers/gpu/drm/xe/display/intel_fbdev_fb.c   |  3 +-
 include/drm/drm_fourcc.h  |  3 +-
 15 files changed, 104 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_fbdev.c 
b/drivers/gpu/drm/armada/armada_fbdev.c
index d223176912b6..82f312f76980 100644
--- a/drivers/gpu/drm/armada/armada_fbdev.c
+++ b/drivers/gpu/drm/armada/armada_fbdev.c
@@ -54,7 +54,7 @@ static int armada_fbdev_create(struct drm_fb_helper *fbh,

[PATCH v4 2/2] backlight: Add new lm3509 backlight driver

2024-03-10 Thread Patrick Gansterer
This is a general driver for LM3509 backlight chip of TI.
LM3509 is High Efficiency Boost for White LEDs and/or OLED Displays with
Dual Current Sinks. This driver supports OLED/White LED select, brightness
control and sub/main control.
The datasheet can be found at http://www.ti.com/product/lm3509.

Signed-off-by: Patrick Gansterer 
---
 drivers/video/backlight/Kconfig |   7 +
 drivers/video/backlight/Makefile|   1 +
 drivers/video/backlight/lm3509_bl.c | 338 
 3 files changed, 346 insertions(+)
 create mode 100644 drivers/video/backlight/lm3509_bl.c

diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index ea2d0d69bd8c..96ad5dc584b6 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -366,6 +366,13 @@ config BACKLIGHT_AAT2870
  If you have a AnalogicTech AAT2870 say Y to enable the
  backlight driver.
 
+config BACKLIGHT_LM3509
+   tristate "Backlight Driver for LM3509"
+   depends on I2C
+   select REGMAP_I2C
+   help
+ This supports TI LM3509 Backlight Driver
+
 config BACKLIGHT_LM3630A
tristate "Backlight Driver for LM3630A"
depends on I2C && PWM
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 06966cb20459..51a4ac5d0530 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_BACKLIGHT_HP700) += jornada720_bl.o
 obj-$(CONFIG_BACKLIGHT_IPAQ_MICRO) += ipaq_micro_bl.o
 obj-$(CONFIG_BACKLIGHT_KTD253) += ktd253-backlight.o
 obj-$(CONFIG_BACKLIGHT_KTZ8866)+= ktz8866.o
+obj-$(CONFIG_BACKLIGHT_LM3509) += lm3509_bl.o
 obj-$(CONFIG_BACKLIGHT_LM3533) += lm3533_bl.o
 obj-$(CONFIG_BACKLIGHT_LM3630A)+= lm3630a_bl.o
 obj-$(CONFIG_BACKLIGHT_LM3639) += lm3639_bl.o
diff --git a/drivers/video/backlight/lm3509_bl.c 
b/drivers/video/backlight/lm3509_bl.c
new file mode 100644
index ..696ec8aab6aa
--- /dev/null
+++ b/drivers/video/backlight/lm3509_bl.c
@@ -0,0 +1,338 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define LM3509_NAME "lm3509_bl"
+
+#define LM3509_SINK_MAIN 0
+#define LM3509_SINK_SUB 1
+#define LM3509_NUM_SINKS 2
+
+#define LM3509_DEF_BRIGHTNESS 0x12
+#define LM3509_MAX_BRIGHTNESS 0x1F
+
+#define REG_GP 0x10
+#define REG_BMAIN 0xA0
+#define REG_BSUB 0xB0
+#define REG_MAX 0xFF
+
+enum {
+   REG_GP_ENM_BIT = 0,
+   REG_GP_ENS_BIT,
+   REG_GP_UNI_BIT,
+   REG_GP_RMP0_BIT,
+   REG_GP_RMP1_BIT,
+   REG_GP_OLED_BIT,
+};
+
+struct lm3509_bl {
+   struct regmap *regmap;
+   struct backlight_device *bl_main;
+   struct backlight_device *bl_sub;
+   struct gpio_desc *reset_gpio;
+};
+
+struct lm3509_bl_led_pdata {
+   const char *label;
+   int led_sources;
+   u32 brightness;
+   u32 max_brightness;
+};
+
+static void lm3509_reset(struct lm3509_bl *data)
+{
+   if (data->reset_gpio) {
+   gpiod_set_value(data->reset_gpio, 1);
+   udelay(1);
+   gpiod_set_value(data->reset_gpio, 0);
+   udelay(10);
+   }
+}
+
+static int lm3509_update_status(struct backlight_device *bl,
+   unsigned int en_mask, unsigned int br_reg)
+{
+   struct lm3509_bl *data = bl_get_data(bl);
+   int ret;
+   bool en;
+
+   ret = regmap_write(data->regmap, br_reg, backlight_get_brightness(bl));
+   if (ret < 0)
+   return ret;
+
+   en = !backlight_is_blank(bl);
+   return regmap_update_bits(data->regmap, REG_GP, en_mask,
+ en ? en_mask : 0);
+}
+
+static int lm3509_main_update_status(struct backlight_device *bl)
+{
+   return lm3509_update_status(bl, BIT(REG_GP_ENM_BIT), REG_BMAIN);
+}
+
+static const struct backlight_ops lm3509_main_ops = {
+   .options = BL_CORE_SUSPENDRESUME,
+   .update_status = lm3509_main_update_status,
+};
+
+static int lm3509_sub_update_status(struct backlight_device *bl)
+{
+   return lm3509_update_status(bl, BIT(REG_GP_ENS_BIT), REG_BSUB);
+}
+
+static const struct backlight_ops lm3509_sub_ops = {
+   .options = BL_CORE_SUSPENDRESUME,
+   .update_status = lm3509_sub_update_status,
+};
+
+static struct backlight_device *
+lm3509_backlight_register(struct device *dev, const char *name_suffix,
+ struct lm3509_bl *data,
+ const struct backlight_ops *ops,
+ const struct lm3509_bl_led_pdata *pdata)
+
+{
+   struct backlight_device *bd;
+   struct backlight_properties props;
+   const char *label = pdata->label;
+   char name[64];
+
+   memset(, 0, sizeof(props));
+   props.type = BACKLIGHT_RAW;
+   props.brightness = pdata->brightness;
+   props.max_brightness = pdata->max_brightness;
+
+  

[PATCH v4 1/2] dt-bindings: backlight: Add Texas Instruments LM3509

2024-03-10 Thread Patrick Gansterer
Add Device Tree bindings for Texas Instruments LM3509 - a
High Efficiency Boost for White LED's and/or OLED Displays

Signed-off-by: Patrick Gansterer 
Reviewed-by: Krzysztof Kozlowski 
---
Changes in v4:
  Use backlight_*() to access backlight_device
  Do not set backlight_properties.power

v3: https://lore.kernel.org/all/20240309132521.1290173-1-par...@paroga.com/

Changes in v3:
  Improved device tree bindings documentation

v2: https://lore.kernel.org/all/20240308215617.1729664-1-par...@paroga.com/

Changes in v2:
  Add device tree nodes for each output
  Addressed multiple smaller review comments

v1: https://lore.kernel.org/all/20240302212757.1871164-1-par...@paroga.com/

 .../bindings/leds/backlight/ti,lm3509.yaml| 139 ++
 1 file changed, 139 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/leds/backlight/ti,lm3509.yaml

diff --git a/Documentation/devicetree/bindings/leds/backlight/ti,lm3509.yaml 
b/Documentation/devicetree/bindings/leds/backlight/ti,lm3509.yaml
new file mode 100644
index ..b67f67648852
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/backlight/ti,lm3509.yaml
@@ -0,0 +1,139 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/leds/backlight/ti,lm3509.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TI LM3509 High Efficiency Boost for White LED's and/or OLED Displays
+
+maintainers:
+  - Patrick Gansterer 
+
+description:
+  The LM3509 current mode boost converter offers two separate outputs.
+  https://www.ti.com/product/LM3509
+
+properties:
+  compatible:
+const: ti,lm3509
+
+  reg:
+maxItems: 1
+
+  "#address-cells":
+const: 1
+
+  "#size-cells":
+const: 0
+
+  reset-gpios:
+maxItems: 1
+
+  ti,brightness-rate-of-change-us:
+description: Brightness Rate of Change in microseconds.
+enum: [51, 13000, 26000, 52000]
+
+  ti,oled-mode:
+description: Enable OLED mode.
+type: boolean
+
+patternProperties:
+  "^led@[01]$":
+type: object
+description: Properties for a string of connected LEDs.
+
+allOf:
+  - $ref: common.yaml#
+
+properties:
+  reg:
+description:
+  The control register that is used to program the two current sinks.
+  The LM3509 has two registers (BMAIN and BSUB) and are represented
+  as 0 or 1 in this property. The two current sinks can be controlled
+  independently with both registers, or register BMAIN can be
+  configured to control both sinks with the led-sources property.
+minimum: 0
+maximum: 1
+
+  label: true
+
+  led-sources:
+allOf:
+  - minItems: 1
+maxItems: 2
+items:
+  minimum: 0
+  maximum: 1
+
+  default-brightness:
+minimum: 0
+maximum: 31
+default: 18
+
+  max-brightness:
+minimum: 0
+maximum: 31
+default: 31
+
+required:
+  - reg
+
+additionalProperties: false
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+i2c {
+#address-cells = <1>;
+#size-cells = <0>;
+
+backlight@36 {
+compatible = "ti,lm3509";
+reg = <0x36>;
+reset-gpios = < 5 GPIO_ACTIVE_LOW>;
+
+ti,oled-mode;
+ti,brightness-rate-of-change-us = <52000>;
+
+#address-cells = <1>;
+#size-cells = <0>;
+
+led@0 {
+reg = <0>;
+led-sources = <0 1>;
+label = "lcd-backlight";
+default-brightness = <12>;
+max-brightness = <31>;
+};
+};
+};
+  - |
+i2c {
+#address-cells = <1>;
+#size-cells = <0>;
+
+backlight@36 {
+compatible = "ti,lm3509";
+reg = <0x36>;
+
+#address-cells = <1>;
+#size-cells = <0>;
+
+led@0 {
+reg = <0>;
+default-brightness = <12>;
+};
+
+led@1 {
+reg = <1>;
+default-brightness = <15>;
+};
+};
+};
-- 
2.44.0



[PATCH] drm/sun4i: tcon: Support keeping dclk rate upon ancestor clock changes

2024-03-10 Thread Frank Oltmanns
Allow the dclk to reset its rate when a rate change is initiated from an
ancestor clock. This makes it possible to no longer to get an exclusive
lock. As a consequence, it is now possible to set new rates if
necessary, e.g. when an external display is connected.

The first user of this functionality is the A64 because PLL-VIDEO0 is an
ancestor for both HDMI and TCON0. This allows to select an optimal rate
for TCON0 as long as there is no external HDMI connection. Once a change
in PLL-VIDEO0 is performed when an HDMI connection is established, TCON0
can react gracefully and select an optimal rate based on this the new
constraint.

Signed-off-by: Frank Oltmanns 
---
I would like to make the Allwinner A64's data-clock keep its rate
when its ancestor's (pll-video0) rate changes. Keeping data-clock's rate
is required, to let the A64 drive both an LCD and HDMI display at the
same time, because both have pll-video0 as an ancestor.

TCONs that use this flag store the ideal rate for their data-clock and
subscribe to be notified when data-clock changes. When rate setting has
finished (indicated by a POST_RATE_CHANGE event) the call back function
schedules delayed work to set the data-clock's rate to the initial value
after 100 ms. Using delayed work maks sure that the clock setting is
finished.

I've implemented this functionality as a quirk, so that it is possible
to use it only for the A64.

This patch supersedes [1].

This work is inspired by an out-of-tree patchset [2] [3] [4].
Unfortunately, the patchset uses clk_set_rate() directly in a notifier
callback, which the following comment on clk_notifier_register()
forbids: "The callbacks associated with the notifier must not re-enter
into the clk framework by calling any top-level clk APIs." [5]
Furthermore, that out-of-tree patchset no longer works since 6.6,
because setting pll-mipi is now also resetting pll-video0 and therefore
causes a race condition.

Thank you for considering this contribution,
  Frank

[1] 
https://lore.kernel.org/lkml/20230825-pll-mipi_keep_rate-v1-0-35bc43570...@oltmanns.dev/
[2] 
https://codeberg.org/megi/linux/commit/a37cda2fff41a67a2bacf82b1594e10335d0bd8a
[3] 
https://codeberg.org/megi/linux/commit/24dc09128d2c8efc6ddf19249420e9798e967a46
[4] 
https://codeberg.org/megi/linux/commit/728a93d46f99f0eb231ed6fa8971a45f97c7182c
[5] https://elixir.bootlin.com/linux/v6.7.9/source/drivers/clk/clk.c#L4669
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 70 ++
 drivers/gpu/drm/sun4i/sun4i_tcon.h | 12 +++
 2 files changed, 76 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c 
b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index a1a2c845ade0..b880bd44049a 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -108,9 +108,11 @@ static void sun4i_tcon_channel_set_status(struct 
sun4i_tcon *tcon, int channel,
 
if (enabled) {
clk_prepare_enable(clk);
-   clk_rate_exclusive_get(clk);
+   if (!tcon->quirks->restores_rate)
+   clk_rate_exclusive_get(clk);
} else {
-   clk_rate_exclusive_put(clk);
+   if (!tcon->quirks->restores_rate)
+   clk_rate_exclusive_put(clk);
clk_disable_unprepare(clk);
}
 }
@@ -343,6 +345,53 @@ static void sun4i_tcon0_mode_set_dithering(struct 
sun4i_tcon *tcon,
regmap_write(tcon->regs, SUN4I_TCON_FRM_CTL_REG, val);
 }
 
+static void sun4i_rate_reset_notifier_delayed_update(struct work_struct *work)
+{
+   struct sun4i_rate_reset_nb *rate_reset = container_of(work, struct 
sun4i_rate_reset_nb,
+   
reset_rate_work.work);
+
+   clk_set_rate(rate_reset->target_clk, rate_reset->saved_rate);
+}
+
+static int sun4i_rate_reset_notifier_cb(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+   struct sun4i_rate_reset_nb *rate_reset = to_sun4i_rate_reset_nb(nb);
+
+   if (event == POST_RATE_CHANGE)
+   schedule_delayed_work(_reset->reset_rate_work, 
msecs_to_jiffies(100));
+
+   return NOTIFY_DONE;
+}
+
+static void sun4i_rate_reset_notifier_register(struct sun4i_rate_reset_nb 
*rate_reset_nb)
+{
+   if (rate_reset_nb->is_registered)
+   return;
+
+   rate_reset_nb->clk_nb.notifier_call = sun4i_rate_reset_notifier_cb;
+
+   INIT_DELAYED_WORK(_reset_nb->reset_rate_work,
+ sun4i_rate_reset_notifier_delayed_update);
+
+   if (!clk_notifier_register(rate_reset_nb->target_clk,
+  _reset_nb->clk_nb))
+   rate_reset_nb->is_registered = true;
+}
+
+static struct sun4i_rate_reset_nb tcon_rate_reset_tcon0_nb;
+
+static void sun4i_tcon0_set_dclk_rate(struct sun4i_tcon *tcon, unsigned long 
rate)
+{
+   clk_set_rate(tcon->dclk, rate);
+
+   if (tcon->quirks->restores_rate) {

[PATCH v4 5/5] arm64: dts: allwinner: a64: Run GPU at 432 MHz

2024-03-10 Thread Frank Oltmanns
The Allwinner A64's GPU has currently three operating points. However,
the BSP runs the GPU fixed at 432 MHz. In addition, at least one of the
devices using that SoC - the pinephone - shows unstabilities (see link)
that can be circumvented by running the GPU at a fixed rate.

Therefore, remove the other two operating points from the GPU OPP table,
so that the GPU runs at a fixed rate of 432 MHz.

Link: https://gitlab.com/postmarketOS/pmaports/-/issues/805
Acked-by: Erico Nunes 
Signed-off-by: Frank Oltmanns 
---
 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 8 
 1 file changed, 8 deletions(-)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi 
b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index 57ac18738c99..c810380aab6d 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -107,14 +107,6 @@ de: display-engine {
gpu_opp_table: opp-table-gpu {
compatible = "operating-points-v2";
 
-   opp-12000 {
-   opp-hz = /bits/ 64 <12000>;
-   };
-
-   opp-31200 {
-   opp-hz = /bits/ 64 <31200>;
-   };
-
opp-43200 {
opp-hz = /bits/ 64 <43200>;
};

-- 
2.44.0



[PATCH v4 4/5] clk: sunxi-ng: a64: Add constraints on PLL-MIPI's n/m ratio and parent rate

2024-03-10 Thread Frank Oltmanns
The Allwinner A64 manual lists the following constraints for the
PLL-MIPI clock:
 - M/N <= 3
 - (PLL_VIDEO0)/M >= 24MHz

Use these constraints.

Reviewed-by: Jernej Skrabec 
Signed-off-by: Frank Oltmanns 
---
 drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c 
b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index 6a4b2b9ef30a..07796c79a23e 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -171,11 +171,13 @@ static struct ccu_nkm pll_mipi_clk = {
 * user manual, and by experiments the PLL doesn't work without
 * these bits toggled.
 */
-   .enable = BIT(31) | BIT(23) | BIT(22),
-   .lock   = BIT(28),
-   .n  = _SUNXI_CCU_MULT(8, 4),
-   .k  = _SUNXI_CCU_MULT_MIN(4, 2, 2),
-   .m  = _SUNXI_CCU_DIV(0, 4),
+   .enable = BIT(31) | BIT(23) | BIT(22),
+   .lock   = BIT(28),
+   .n  = _SUNXI_CCU_MULT(8, 4),
+   .k  = _SUNXI_CCU_MULT_MIN(4, 2, 2),
+   .m  = _SUNXI_CCU_DIV(0, 4),
+   .max_m_n_ratio  = 3,
+   .min_parent_m_ratio = 2400,
.common = {
.reg= 0x040,
.hw.init= CLK_HW_INIT("pll-mipi", "pll-video0",

-- 
2.44.0



[PATCH v4 2/5] clk: sunxi-ng: a64: Set minimum and maximum rate for PLL-MIPI

2024-03-10 Thread Frank Oltmanns
When the Allwinner A64's TCON0 searches the ideal rate for the connected
panel, it may happen that it requests a rate from its parent PLL-MIPI
which PLL-MIPI does not support.

This happens for example on the Olimex TERES-I laptop where TCON0
requests PLL-MIPI to change to a rate of several GHz which causes the
panel to stay blank. It also happens on the pinephone where a rate of
less than 500 MHz is requested which causes instabilities on some
phones.

Set the minimum and maximum rate of Allwinner A64's PLL-MIPI according
to the Allwinner User Manual.

Fixes: ca1170b69968 ("clk: sunxi-ng: a64: force select PLL_MIPI in TCON0 mux")
Reported-by: Diego Roversi 
Closes: https://groups.google.com/g/linux-sunxi/c/Rh-Uqqa66bw
Tested-by: Diego Roversi 
Cc: sta...@vger.kernel.org
Reviewed-by: Maxime Ripard 
Signed-off-by: Frank Oltmanns 
---
 drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c 
b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index 8951ffc14ff5..6a4b2b9ef30a 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -182,6 +182,8 @@ static struct ccu_nkm pll_mipi_clk = {
  _nkm_ops,
  CLK_SET_RATE_UNGATE | 
CLK_SET_RATE_PARENT),
.features   = CCU_FEATURE_CLOSEST_RATE,
+   .min_rate   = 5,
+   .max_rate   = 14,
},
 };
 

-- 
2.44.0



[PATCH v4 3/5] clk: sunxi-ng: nkm: Support constraints on m/n ratio and parent rate

2024-03-10 Thread Frank Oltmanns
The Allwinner A64 manual lists the following constraints for the
PLL-MIPI clock:
 - M/N <= 3
 - (PLL_VIDEO0)/M >= 24MHz

The PLL-MIPI clock is implemented as ccu_nkm. Therefore, add support for
these constraints.

Reviewed-by: Jernej Skrabec 
Signed-off-by: Frank Oltmanns 
---
 drivers/clk/sunxi-ng/ccu_nkm.c | 21 +
 drivers/clk/sunxi-ng/ccu_nkm.h |  2 ++
 2 files changed, 23 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
index 853f84398e2b..1168d894d636 100644
--- a/drivers/clk/sunxi-ng/ccu_nkm.c
+++ b/drivers/clk/sunxi-ng/ccu_nkm.c
@@ -16,6 +16,20 @@ struct _ccu_nkm {
unsigned long   m, min_m, max_m;
 };
 
+static bool ccu_nkm_is_valid_rate(struct ccu_common *common, unsigned long 
parent,
+ unsigned long n, unsigned long m)
+{
+   struct ccu_nkm *nkm = container_of(common, struct ccu_nkm, common);
+
+   if (nkm->max_m_n_ratio && (m > nkm->max_m_n_ratio * n))
+   return false;
+
+   if (nkm->min_parent_m_ratio && (parent < nkm->min_parent_m_ratio * m))
+   return false;
+
+   return true;
+}
+
 static unsigned long ccu_nkm_find_best_with_parent_adj(struct ccu_common 
*common,
   struct clk_hw *parent_hw,
   unsigned long *parent, 
unsigned long rate,
@@ -31,6 +45,10 @@ static unsigned long 
ccu_nkm_find_best_with_parent_adj(struct ccu_common *common
unsigned long tmp_rate, tmp_parent;
 
tmp_parent = clk_hw_round_rate(parent_hw, rate 
* _m / (_n * _k));
+
+   if (!ccu_nkm_is_valid_rate(common, tmp_parent, 
_n, _m))
+   continue;
+
tmp_rate = tmp_parent * _n * _k / _m;
 
if (ccu_is_better_rate(common, rate, tmp_rate, 
best_rate) ||
@@ -64,6 +82,9 @@ static unsigned long ccu_nkm_find_best(unsigned long parent, 
unsigned long rate,
for (_k = nkm->min_k; _k <= nkm->max_k; _k++) {
for (_n = nkm->min_n; _n <= nkm->max_n; _n++) {
for (_m = nkm->min_m; _m <= nkm->max_m; _m++) {
+   if (!ccu_nkm_is_valid_rate(common, parent, _n, 
_m))
+   continue;
+
unsigned long tmp_rate;
 
tmp_rate = parent * _n * _k / _m;
diff --git a/drivers/clk/sunxi-ng/ccu_nkm.h b/drivers/clk/sunxi-ng/ccu_nkm.h
index 6601defb3f38..c409212ee40e 100644
--- a/drivers/clk/sunxi-ng/ccu_nkm.h
+++ b/drivers/clk/sunxi-ng/ccu_nkm.h
@@ -27,6 +27,8 @@ struct ccu_nkm {
struct ccu_mux_internal mux;
 
unsigned intfixed_post_div;
+   unsigned long   max_m_n_ratio;
+   unsigned long   min_parent_m_ratio;
 
struct ccu_common   common;
 };

-- 
2.44.0



[PATCH v4 1/5] clk: sunxi-ng: common: Support minimum and maximum rate

2024-03-10 Thread Frank Oltmanns
The Allwinner SoC's typically have an upper and lower limit for their
clocks' rates. Up until now, support for that has been implemented
separately for each clock type.

Implement that functionality in the sunxi-ng's common part making use of
the CCF rate liming capabilities, so that it is available for all clock
types.

Suggested-by: Maxime Ripard 
Signed-off-by: Frank Oltmanns 
Cc: sta...@vger.kernel.org
---
 drivers/clk/sunxi-ng/ccu_common.c | 19 +++
 drivers/clk/sunxi-ng/ccu_common.h |  3 +++
 2 files changed, 22 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu_common.c 
b/drivers/clk/sunxi-ng/ccu_common.c
index 8babce55302f..ac0091b4ce24 100644
--- a/drivers/clk/sunxi-ng/ccu_common.c
+++ b/drivers/clk/sunxi-ng/ccu_common.c
@@ -44,6 +44,16 @@ bool ccu_is_better_rate(struct ccu_common *common,
unsigned long current_rate,
unsigned long best_rate)
 {
+   unsigned long min_rate, max_rate;
+
+   clk_hw_get_rate_range(>hw, _rate, _rate);
+
+   if (current_rate > max_rate)
+   return false;
+
+   if (current_rate < min_rate)
+   return false;
+
if (common->features & CCU_FEATURE_CLOSEST_RATE)
return abs(current_rate - target_rate) < abs(best_rate - 
target_rate);
 
@@ -122,6 +132,7 @@ static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct 
device *dev,
 
for (i = 0; i < desc->hw_clks->num ; i++) {
struct clk_hw *hw = desc->hw_clks->hws[i];
+   struct ccu_common *common = hw_to_ccu_common(hw);
const char *name;
 
if (!hw)
@@ -136,6 +147,14 @@ static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct 
device *dev,
pr_err("Couldn't register clock %d - %s\n", i, name);
goto err_clk_unreg;
}
+
+   if (common->max_rate)
+   clk_hw_set_rate_range(hw, common->min_rate,
+ common->max_rate);
+   else
+   WARN(common->min_rate,
+"No max_rate, ignoring min_rate of clock %d - 
%s\n",
+i, name);
}
 
ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get,
diff --git a/drivers/clk/sunxi-ng/ccu_common.h 
b/drivers/clk/sunxi-ng/ccu_common.h
index 942a72c09437..329734f8cf42 100644
--- a/drivers/clk/sunxi-ng/ccu_common.h
+++ b/drivers/clk/sunxi-ng/ccu_common.h
@@ -31,6 +31,9 @@ struct ccu_common {
u16 lock_reg;
u32 prediv;
 
+   unsigned long   min_rate;
+   unsigned long   max_rate;
+
unsigned long   features;
spinlock_t  *lock;
struct clk_hw   hw;

-- 
2.44.0



[PATCH v4 0/5] Pinephone video out fixes (flipping between two frames)

2024-03-10 Thread Frank Oltmanns
On some pinephones the video output sometimes freezes (flips between two
frames) [1]. It seems to be that the reason for this behaviour is that
PLL-MIPI is outside its limits, and the GPU is not running at a fixed
rate.

In this patch series I propose the following changes:
  1. sunxi-ng: Adhere to the following constraints given in the
 Allwinner A64 Manual regarding PLL-MIPI:
  * M/N <= 3
  * (PLL_VIDEO0)/M >= 24MHz
  * 500MHz <= clockrate <= 1400MHz

  2. Remove two operating points from the A64 DTS OPPs, so that the GPU
 runs at a fixed rate of 432 MHz.

Note, that when pinning the GPU to 432 MHz the issue [1] completely
disappears for me. I've searched the BSP and could not find any
indication that supports the idea of having the three OPPs. The only
frequency I found in the BPSs for A64 is 432 MHz, which has also proven
stable for me.

I very much appreciate your feedback!

[1] https://gitlab.com/postmarketOS/pmaports/-/issues/805

Signed-off-by: Frank Oltmanns 
---
Changes in v4:
- sunxi-ng: common: Address review comments.
- Link to v3: 
https://lore.kernel.org/r/20240304-pinephone-pll-fixes-v3-0-94ab828f2...@oltmanns.dev

Changes in v3:
- dts: Pin GPU to 432 MHz.
- nkm and a64: Move minimum and maximum rate handling to the common part
  of the sunxi-ng driver.
- Removed st7703 patch from series.
- Link to v2: 
https://lore.kernel.org/r/20240205-pinephone-pll-fixes-v2-0-96a46a2d8...@oltmanns.dev

Changes in v2:
- dts: Increase minimum GPU frequency to 192 MHz.
- nkm and a64: Add minimum and maximum rate for PLL-MIPI.
- nkm: Use the same approach for skipping invalid rates in
  ccu_nkm_find_best() as in ccu_nkm_find_best_with_parent_adj().
- nkm: Improve names for ratio struct members and hence get rid of
  describing comments.
- nkm and a64: Correct description in the commit messages: M/N <= 3
- Remove patches for nm as they were not needed.
- st7703: Rework the commit message to cover more background for the
  change.
- Link to v1: 
https://lore.kernel.org/r/20231218-pinephone-pll-fixes-v1-0-e238b6ed6...@oltmanns.dev

---
Frank Oltmanns (5):
  clk: sunxi-ng: common: Support minimum and maximum rate
  clk: sunxi-ng: a64: Set minimum and maximum rate for PLL-MIPI
  clk: sunxi-ng: nkm: Support constraints on m/n ratio and parent rate
  clk: sunxi-ng: a64: Add constraints on PLL-MIPI's n/m ratio and parent 
rate
  arm64: dts: allwinner: a64: Run GPU at 432 MHz

 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi |  8 
 drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 14 +-
 drivers/clk/sunxi-ng/ccu_common.c | 19 +++
 drivers/clk/sunxi-ng/ccu_common.h |  3 +++
 drivers/clk/sunxi-ng/ccu_nkm.c| 21 +
 drivers/clk/sunxi-ng/ccu_nkm.h|  2 ++
 6 files changed, 54 insertions(+), 13 deletions(-)
---
base-commit: dcb6c8ee6acc6c347caec1e73fb900c0f4ff9806
change-id: 20231218-pinephone-pll-fixes-0ccdfde273e4

Best regards,
-- 
Frank Oltmanns 



[PATCH v9 6/6] Documentation: iio: Document high-speed DMABUF based API

2024-03-10 Thread Paul Cercueil
Document the new DMABUF based API.

Signed-off-by: Paul Cercueil 
Signed-off-by: Nuno Sa 

---
v2: - Explicitly state that the new interface is optional and is
  not implemented by all drivers.
- The IOCTLs can now only be called on the buffer FD returned by
  IIO_BUFFER_GET_FD_IOCTL.
- Move the page up a bit in the index since it is core stuff and not
  driver-specific.

v3: Update the documentation to reflect the new API.

v5: Use description lists for the documentation of the three new IOCTLs
instead of abusing subsections.

v8: Renamed dmabuf_api.rst -> iio_dmabuf_api.rst, and updated index.rst
whose format changed in iio/togreg.
---
 Documentation/iio/iio_dmabuf_api.rst | 54 
 Documentation/iio/index.rst  |  1 +
 2 files changed, 55 insertions(+)
 create mode 100644 Documentation/iio/iio_dmabuf_api.rst

diff --git a/Documentation/iio/iio_dmabuf_api.rst 
b/Documentation/iio/iio_dmabuf_api.rst
new file mode 100644
index ..1cd6cd51a582
--- /dev/null
+++ b/Documentation/iio/iio_dmabuf_api.rst
@@ -0,0 +1,54 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===
+High-speed DMABUF interface for IIO
+===
+
+1. Overview
+===
+
+The Industrial I/O subsystem supports access to buffers through a
+file-based interface, with read() and write() access calls through the
+IIO device's dev node.
+
+It additionally supports a DMABUF based interface, where the userspace
+can attach DMABUF objects (externally created) to a IIO buffer, and
+subsequently use them for data transfers.
+
+A userspace application can then use this interface to share DMABUF
+objects between several interfaces, allowing it to transfer data in a
+zero-copy fashion, for instance between IIO and the USB stack.
+
+The userspace application can also memory-map the DMABUF objects, and
+access the sample data directly. The advantage of doing this vs. the
+read() interface is that it avoids an extra copy of the data between the
+kernel and userspace. This is particularly useful for high-speed devices
+which produce several megabytes or even gigabytes of data per second.
+It does however increase the userspace-kernelspace synchronization
+overhead, as the DMA_BUF_SYNC_START and DMA_BUF_SYNC_END IOCTLs have to
+be used for data integrity.
+
+2. User API
+===
+
+As part of this interface, three new IOCTLs have been added. These three
+IOCTLs have to be performed on the IIO buffer's file descriptor,
+obtained using the IIO_BUFFER_GET_FD_IOCTL() ioctl.
+
+  ``IIO_BUFFER_DMABUF_ATTACH_IOCTL(int)``
+Attach the DMABUF object, identified by its file descriptor, to the
+IIO buffer. Returns zero on success, and a negative errno value on
+error.
+
+  ``IIO_BUFFER_DMABUF_DETACH_IOCTL(int)``
+Detach the given DMABUF object, identified by its file descriptor,
+from the IIO buffer. Returns zero on success, and a negative errno
+value on error.
+
+Note that closing the IIO buffer's file descriptor will
+automatically detach all previously attached DMABUF objects.
+
+  ``IIO_BUFFER_DMABUF_ENQUEUE_IOCTL(struct iio_dmabuf *iio_dmabuf)``
+Enqueue a previously attached DMABUF object to the buffer queue.
+Enqueued DMABUFs will be read from (if output buffer) or written to
+(if input buffer) as long as the buffer is enabled.
diff --git a/Documentation/iio/index.rst b/Documentation/iio/index.rst
index 30b09eefe75e..feb50b61aac0 100644
--- a/Documentation/iio/index.rst
+++ b/Documentation/iio/index.rst
@@ -9,6 +9,7 @@ Industrial I/O
 
iio_configfs
iio_devbuf
+   iio_dmabuf_api
 
 Industrial I/O Kernel Drivers
 =
-- 
2.43.0



[PATCH v9 5/6] iio: buffer-dmaengine: Support new DMABUF based userspace API

2024-03-10 Thread Paul Cercueil
Use the functions provided by the buffer-dma core to implement the
DMABUF userspace API in the buffer-dmaengine IIO buffer implementation.

Since we want to be able to transfer an arbitrary number of bytes and
not necesarily the full DMABUF, the associated scatterlist is converted
to an array of DMA addresses + lengths, which is then passed to
dmaengine_prep_slave_dma_array().

Signed-off-by: Paul Cercueil 
Signed-off-by: Nuno Sa 

---
v3: Use the new dmaengine_prep_slave_dma_array(), and adapt the code to
work with the new functions introduced in industrialio-buffer-dma.c.

v5: - Use the new dmaengine_prep_slave_dma_vec().
- Restrict to input buffers, since output buffers are not yet
  supported by IIO buffers.

v6: - Populate .lock_queue / .unlock_queue callbacks
- Switch to atomic memory allocations in .submit_queue, because of
  the dma_fence critical section
- Make sure that the size of the scatterlist is enough

v7: Adapted patch for the changes made in patch 1.
---
 .../buffer/industrialio-buffer-dmaengine.c| 59 +--
 1 file changed, 53 insertions(+), 6 deletions(-)

diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c 
b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
index a18c1da292af..3b7b649f0a89 100644
--- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c
+++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
@@ -64,15 +64,55 @@ static int iio_dmaengine_buffer_submit_block(struct 
iio_dma_buffer_queue *queue,
struct dmaengine_buffer *dmaengine_buffer =
iio_buffer_to_dmaengine_buffer(>buffer);
struct dma_async_tx_descriptor *desc;
+   struct scatterlist *sgl;
+   struct dma_vec *vecs;
dma_cookie_t cookie;
+   size_t len_total;
+   size_t max_size;
+   unsigned int i;
+   int nents;
 
-   block->bytes_used = min(block->size, dmaengine_buffer->max_size);
-   block->bytes_used = round_down(block->bytes_used,
-   dmaengine_buffer->align);
+   if (queue->buffer.direction != IIO_BUFFER_DIRECTION_IN) {
+   /* We do not yet support output buffers. */
+   return -EINVAL;
+   }
 
-   desc = dmaengine_prep_slave_single(dmaengine_buffer->chan,
-   block->phys_addr, block->bytes_used, DMA_DEV_TO_MEM,
-   DMA_PREP_INTERRUPT);
+   if (block->sg_table) {
+   sgl = block->sg_table->sgl;
+   nents = sg_nents_for_len(sgl, block->bytes_used);
+   if (nents < 0)
+   return nents;
+
+   vecs = kmalloc_array(nents, sizeof(*vecs), GFP_ATOMIC);
+   if (!vecs)
+   return -ENOMEM;
+
+   len_total = block->bytes_used;
+
+   for (i = 0; i < nents; i++) {
+   vecs[i].addr = sg_dma_address(sgl);
+   vecs[i].len = min(sg_dma_len(sgl), len_total);
+   len_total -= vecs[i].len;
+
+   sgl = sg_next(sgl);
+   }
+
+   desc = dmaengine_prep_peripheral_dma_vec(dmaengine_buffer->chan,
+vecs, nents,
+DMA_DEV_TO_MEM,
+DMA_PREP_INTERRUPT, 0);
+   kfree(vecs);
+   } else {
+   max_size = min(block->size, dmaengine_buffer->max_size);
+   max_size = round_down(max_size, dmaengine_buffer->align);
+   block->bytes_used = max_size;
+
+   desc = dmaengine_prep_slave_single(dmaengine_buffer->chan,
+  block->phys_addr,
+  block->bytes_used,
+  DMA_DEV_TO_MEM,
+  DMA_PREP_INTERRUPT);
+   }
if (!desc)
return -ENOMEM;
 
@@ -120,6 +160,13 @@ static const struct iio_buffer_access_funcs 
iio_dmaengine_buffer_ops = {
.data_available = iio_dma_buffer_data_available,
.release = iio_dmaengine_buffer_release,
 
+   .enqueue_dmabuf = iio_dma_buffer_enqueue_dmabuf,
+   .attach_dmabuf = iio_dma_buffer_attach_dmabuf,
+   .detach_dmabuf = iio_dma_buffer_detach_dmabuf,
+
+   .lock_queue = iio_dma_buffer_lock_queue,
+   .unlock_queue = iio_dma_buffer_unlock_queue,
+
.modes = INDIO_BUFFER_HARDWARE,
.flags = INDIO_BUFFER_FLAG_FIXED_WATERMARK,
 };
-- 
2.43.0



[PATCH v9 4/6] iio: buffer-dma: Enable support for DMABUFs

2024-03-10 Thread Paul Cercueil
Implement iio_dma_buffer_attach_dmabuf(), iio_dma_buffer_detach_dmabuf()
and iio_dma_buffer_transfer_dmabuf(), which can then be used by the IIO
DMA buffer implementations.

Signed-off-by: Paul Cercueil 
Signed-off-by: Nuno Sa 

---
v3: Update code to provide the functions that will be used as callbacks
for the new IOCTLs.

v6: - Update iio_dma_buffer_enqueue_dmabuf() to take a dma_fence pointer
- Pass that dma_fence pointer along to
  iio_buffer_signal_dmabuf_done()
- Add iio_dma_buffer_lock_queue() / iio_dma_buffer_unlock_queue()
- Do not lock the queue in iio_dma_buffer_enqueue_dmabuf().
  The caller will ensure that it has been locked already.
- Replace "int += bool;" by "if (bool) int++;"
- Use dma_fence_begin/end_signalling in the dma_fence critical
  sections
- Use one "num_dmabufs" fields instead of one "num_blocks" and one
  "num_fileio_blocks". Make it an atomic_t, which makes it possible
  to decrement it atomically in iio_buffer_block_release() without
  having to lock the queue mutex; and in turn, it means that we
  don't need to use iio_buffer_block_put_atomic() everywhere to
  avoid locking the queue mutex twice.
- Use cleanup.h guard(mutex) when possible
- Explicitely list all states in the switch in
  iio_dma_can_enqueue_block()
- Rename iio_dma_buffer_fileio_mode() to
  iio_dma_buffer_can_use_fileio(), and add a comment explaining why
  it cannot race vs. DMABUF.
---
 drivers/iio/buffer/industrialio-buffer-dma.c | 181 +--
 include/linux/iio/buffer-dma.h   |  31 
 2 files changed, 201 insertions(+), 11 deletions(-)

diff --git a/drivers/iio/buffer/industrialio-buffer-dma.c 
b/drivers/iio/buffer/industrialio-buffer-dma.c
index 5610ba67925e..c0f539af98f9 100644
--- a/drivers/iio/buffer/industrialio-buffer-dma.c
+++ b/drivers/iio/buffer/industrialio-buffer-dma.c
@@ -4,6 +4,8 @@
  *  Author: Lars-Peter Clausen 
  */
 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -14,6 +16,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 
@@ -94,13 +98,18 @@ static void iio_buffer_block_release(struct kref *kref)
 {
struct iio_dma_buffer_block *block = container_of(kref,
struct iio_dma_buffer_block, kref);
+   struct iio_dma_buffer_queue *queue = block->queue;
 
-   WARN_ON(block->state != IIO_BLOCK_STATE_DEAD);
+   WARN_ON(block->fileio && block->state != IIO_BLOCK_STATE_DEAD);
 
-   dma_free_coherent(block->queue->dev, PAGE_ALIGN(block->size),
-   block->vaddr, block->phys_addr);
+   if (block->fileio) {
+   dma_free_coherent(queue->dev, PAGE_ALIGN(block->size),
+ block->vaddr, block->phys_addr);
+   } else {
+   atomic_dec(>num_dmabufs);
+   }
 
-   iio_buffer_put(>queue->buffer);
+   iio_buffer_put(>buffer);
kfree(block);
 }
 
@@ -163,7 +172,7 @@ static struct iio_dma_buffer_queue 
*iio_buffer_to_queue(struct iio_buffer *buf)
 }
 
 static struct iio_dma_buffer_block *iio_dma_buffer_alloc_block(
-   struct iio_dma_buffer_queue *queue, size_t size)
+   struct iio_dma_buffer_queue *queue, size_t size, bool fileio)
 {
struct iio_dma_buffer_block *block;
 
@@ -171,13 +180,16 @@ static struct iio_dma_buffer_block 
*iio_dma_buffer_alloc_block(
if (!block)
return NULL;
 
-   block->vaddr = dma_alloc_coherent(queue->dev, PAGE_ALIGN(size),
-   >phys_addr, GFP_KERNEL);
-   if (!block->vaddr) {
-   kfree(block);
-   return NULL;
+   if (fileio) {
+   block->vaddr = dma_alloc_coherent(queue->dev, PAGE_ALIGN(size),
+ >phys_addr, 
GFP_KERNEL);
+   if (!block->vaddr) {
+   kfree(block);
+   return NULL;
+   }
}
 
+   block->fileio = fileio;
block->size = size;
block->state = IIO_BLOCK_STATE_DONE;
block->queue = queue;
@@ -186,6 +198,9 @@ static struct iio_dma_buffer_block 
*iio_dma_buffer_alloc_block(
 
iio_buffer_get(>buffer);
 
+   if (!fileio)
+   atomic_inc(>num_dmabufs);
+
return block;
 }
 
@@ -206,13 +221,21 @@ void iio_dma_buffer_block_done(struct 
iio_dma_buffer_block *block)
 {
struct iio_dma_buffer_queue *queue = block->queue;
unsigned long flags;
+   bool cookie;
+
+   cookie = dma_fence_begin_signalling();
 
spin_lock_irqsave(>list_lock, flags);
_iio_dma_buffer_block_done(block);
spin_unlock_irqrestore(>list_lock, flags);
 
+   if (!block->fileio)
+   iio_buffer_signal_dmabuf_done(block->fence, 0);
+
iio_buffer_block_put_atomic(block);
wake_up_interruptible_poll(>buffer.pollq, EPOLLIN | EPOLLRDNORM);
+
+   

[PATCH v9 3/6] iio: core: Add new DMABUF interface infrastructure

2024-03-10 Thread Paul Cercueil
Add the necessary infrastructure to the IIO core to support a new
optional DMABUF based interface.

With this new interface, DMABUF objects (externally created) can be
attached to a IIO buffer, and subsequently used for data transfer.

A userspace application can then use this interface to share DMABUF
objects between several interfaces, allowing it to transfer data in a
zero-copy fashion, for instance between IIO and the USB stack.

The userspace application can also memory-map the DMABUF objects, and
access the sample data directly. The advantage of doing this vs. the
read() interface is that it avoids an extra copy of the data between the
kernel and userspace. This is particularly userful for high-speed
devices which produce several megabytes or even gigabytes of data per
second.

As part of the interface, 3 new IOCTLs have been added:

IIO_BUFFER_DMABUF_ATTACH_IOCTL(int fd):
 Attach the DMABUF object identified by the given file descriptor to the
 buffer.

IIO_BUFFER_DMABUF_DETACH_IOCTL(int fd):
 Detach the DMABUF object identified by the given file descriptor from
 the buffer. Note that closing the IIO buffer's file descriptor will
 automatically detach all previously attached DMABUF objects.

IIO_BUFFER_DMABUF_ENQUEUE_IOCTL(struct iio_dmabuf *):
 Request a data transfer to/from the given DMABUF object. Its file
 descriptor, as well as the transfer size and flags are provided in the
 "iio_dmabuf" structure.

These three IOCTLs have to be performed on the IIO buffer's file
descriptor, obtained using the IIO_BUFFER_GET_FD_IOCTL() ioctl.

Signed-off-by: Paul Cercueil 
Signed-off-by: Nuno Sa 

---
v2: Only allow the new IOCTLs on the buffer FD created with
IIO_BUFFER_GET_FD_IOCTL().

v3: - Get rid of the old IOCTLs. The IIO subsystem does not create or
manage DMABUFs anymore, and only attaches/detaches externally
created DMABUFs.
- Add IIO_BUFFER_DMABUF_CYCLIC to the supported flags.

v5: - Use dev_err() instead of pr_err()
- Inline to_iio_dma_fence()
- Add comment to explain why we unref twice when detaching dmabuf
- Remove TODO comment. It is actually safe to free the file's
  private data even when transfers are still pending because it
  won't be accessed.
- Fix documentation of new fields in struct iio_buffer_access_funcs
- iio_dma_resv_lock() does not need to be exported, make it static

v6: - Remove dead code in iio_dma_resv_lock()
- Fix non-block actually blocking
- Cache dma_buf_attachment instead of mapping/unmapping it for every
  transfer
- Return -EINVAL instead of IIO_IOCTL_UNHANDLED for unknown ioctl
- Make .block_enqueue() callback take a dma_fence pointer, which
  will be passed to iio_buffer_signal_dmabuf_done() instead of the
  dma_buf_attachment; and remove the backpointer from the priv
  structure to the dma_fence.
- Use dma_fence_begin/end_signalling in the dma_fence critical
  sections
- Unref dma_fence and dma_buf_attachment in worker, because they
  might try to lock the dma_resv, which would deadlock.
- Add buffer ops to lock/unlock the queue. This is motivated by the
  fact that once the dma_fence has been installed, we cannot lock
  anything anymore - so the queue must be locked before the
  dma_fence is installed.
- Use 'long retl' variable to handle the return value of
  dma_resv_wait_timeout()
- Protect dmabufs list access with a mutex
- Rework iio_buffer_find_attachment() to use the internal dmabufs
  list, instead of messing with dmabufs private data.
- Add an atomically-increasing sequence number for fences

v8  - Fix swapped fence direction
- Simplify fence wait mechanism
- Remove "Buffer closed with active transfers" print, as it was dead
  code
- Un-export iio_buffer_dmabuf_{get,put}. They are not used anywhere
  else so they can even be static.
- Prevent attaching already-attached DMABUFs

v9: - Select DMA_SHARED_BUFFER in Kconfig
- Remove useless forward declaration of 'iio_dma_fence'
- Import DMA-BUF namespace
- Add missing __user tag to iio_buffer_detach_dmabuf() argument
---
 drivers/iio/Kconfig   |   1 +
 drivers/iio/industrialio-buffer.c | 462 ++
 include/linux/iio/buffer_impl.h   |  30 ++
 include/uapi/linux/iio/buffer.h   |  22 ++
 4 files changed, 515 insertions(+)

diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
index 9c351ffc7bed..661127aed2f9 100644
--- a/drivers/iio/Kconfig
+++ b/drivers/iio/Kconfig
@@ -14,6 +14,7 @@ if IIO
 
 config IIO_BUFFER
bool "Enable buffer support within IIO"
+   select DMA_SHARED_BUFFER
help
  Provide core support for various buffer based data
  acquisition methods.
diff --git a/drivers/iio/industrialio-buffer.c 
b/drivers/iio/industrialio-buffer.c
index b581a7e80566..a987654f82fc 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -9,14 +9,19 

[PATCH v9 2/6] dmaengine: dma-axi-dmac: Implement device_prep_peripheral_dma_vec

2024-03-10 Thread Paul Cercueil
Add implementation of the .device_prep_peripheral_dma_vec() callback.

Signed-off-by: Paul Cercueil 
Signed-off-by: Nuno Sa 

---
v3: New patch

v5: Implement .device_prep_slave_dma_vec() instead of v3's
.device_prep_slave_dma_array().

v6: Use new prototype for axi_dmac_alloc_desc() as it changed upstream.

v7: Adapted patch for the changes made in patch 1.
---
 drivers/dma/dma-axi-dmac.c | 40 ++
 1 file changed, 40 insertions(+)

diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c
index 4e339c04fc1e..d03cbf1d28e8 100644
--- a/drivers/dma/dma-axi-dmac.c
+++ b/drivers/dma/dma-axi-dmac.c
@@ -620,6 +620,45 @@ static struct axi_dmac_sg *axi_dmac_fill_linear_sg(struct 
axi_dmac_chan *chan,
return sg;
 }
 
+static struct dma_async_tx_descriptor *
+axi_dmac_prep_peripheral_dma_vec(struct dma_chan *c, const struct dma_vec 
*vecs,
+size_t nb, enum dma_transfer_direction 
direction,
+unsigned long prep_flags, unsigned long flags)
+{
+   struct axi_dmac_chan *chan = to_axi_dmac_chan(c);
+   struct axi_dmac_desc *desc;
+   unsigned int num_sgs = 0;
+   struct axi_dmac_sg *dsg;
+   size_t i;
+
+   if (direction != chan->direction)
+   return NULL;
+
+   for (i = 0; i < nb; i++)
+   num_sgs += DIV_ROUND_UP(vecs[i].len, chan->max_length);
+
+   desc = axi_dmac_alloc_desc(chan, num_sgs);
+   if (!desc)
+   return NULL;
+
+   dsg = desc->sg;
+
+   for (i = 0; i < nb; i++) {
+   if (!axi_dmac_check_addr(chan, vecs[i].addr) ||
+   !axi_dmac_check_len(chan, vecs[i].len)) {
+   kfree(desc);
+   return NULL;
+   }
+
+   dsg = axi_dmac_fill_linear_sg(chan, direction, vecs[i].addr, 1,
+ vecs[i].len, dsg);
+   }
+
+   desc->cyclic = false;
+
+   return vchan_tx_prep(>vchan, >vdesc, prep_flags);
+}
+
 static struct dma_async_tx_descriptor *axi_dmac_prep_slave_sg(
struct dma_chan *c, struct scatterlist *sgl,
unsigned int sg_len, enum dma_transfer_direction direction,
@@ -1055,6 +1094,7 @@ static int axi_dmac_probe(struct platform_device *pdev)
dma_dev->device_tx_status = dma_cookie_status;
dma_dev->device_issue_pending = axi_dmac_issue_pending;
dma_dev->device_prep_slave_sg = axi_dmac_prep_slave_sg;
+   dma_dev->device_prep_peripheral_dma_vec = 
axi_dmac_prep_peripheral_dma_vec;
dma_dev->device_prep_dma_cyclic = axi_dmac_prep_dma_cyclic;
dma_dev->device_prep_interleaved_dma = axi_dmac_prep_interleaved;
dma_dev->device_terminate_all = axi_dmac_terminate_all;
-- 
2.43.0



[PATCH v9 1/6] dmaengine: Add API function dmaengine_prep_peripheral_dma_vec()

2024-03-10 Thread Paul Cercueil
This function can be used to initiate a scatter-gather DMA transfer,
where the address and size of each segment is located in one entry of
the dma_vec array.

The major difference with dmaengine_prep_slave_sg() is that it supports
specifying the lengths of each DMA transfer; as trying to override the
length of the transfer with dmaengine_prep_slave_sg() is a very tedious
process. The introduction of a new API function is also justified by the
fact that scatterlists are on their way out.

Note that dmaengine_prep_interleaved_dma() is not helpful either in that
case, as it assumes that the address of each segment will be higher than
the one of the previous segment, which we just cannot guarantee in case
of a scatter-gather transfer.

Signed-off-by: Paul Cercueil 
Signed-off-by: Nuno Sa 

---
v3: New patch

v5: Replace with function dmaengine_prep_slave_dma_vec(), and struct
'dma_vec'.
Note that at some point we will need to support cyclic transfers
using dmaengine_prep_slave_dma_vec(). Maybe with a new "flags"
parameter to the function?

v7:
  - Renamed *device_prep_slave_dma_vec() -> device_prep_peripheral_dma_vec();
  - Added a new flag parameter to the function as agreed between Paul
and Vinod. I renamed the first parameter to prep_flags as it's supposed to
be used (I think) with enum dma_ctrl_flags. I'm not really sure how that API
can grow but I was thinking in just having a bool cyclic parameter (as the
first intention of the flags is to support cyclic transfers) but ended up
"respecting" the previously agreed approach.
---
 include/linux/dmaengine.h | 27 +++
 1 file changed, 27 insertions(+)

diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index 752dbde4cec1..856df8cd9a4e 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -160,6 +160,16 @@ struct dma_interleaved_template {
struct data_chunk sgl[];
 };
 
+/**
+ * struct dma_vec - DMA vector
+ * @addr: Bus address of the start of the vector
+ * @len: Length in bytes of the DMA vector
+ */
+struct dma_vec {
+   dma_addr_t addr;
+   size_t len;
+};
+
 /**
  * enum dma_ctrl_flags - DMA flags to augment operation preparation,
  *  control completion, and communicate status.
@@ -910,6 +920,10 @@ struct dma_device {
struct dma_async_tx_descriptor *(*device_prep_dma_interrupt)(
struct dma_chan *chan, unsigned long flags);
 
+   struct dma_async_tx_descriptor *(*device_prep_peripheral_dma_vec)(
+   struct dma_chan *chan, const struct dma_vec *vecs,
+   size_t nents, enum dma_transfer_direction direction,
+   unsigned long prep_flags, unsigned long flags);
struct dma_async_tx_descriptor *(*device_prep_slave_sg)(
struct dma_chan *chan, struct scatterlist *sgl,
unsigned int sg_len, enum dma_transfer_direction direction,
@@ -973,6 +987,19 @@ static inline struct dma_async_tx_descriptor 
*dmaengine_prep_slave_single(
  dir, flags, NULL);
 }
 
+static inline struct dma_async_tx_descriptor 
*dmaengine_prep_peripheral_dma_vec(
+   struct dma_chan *chan, const struct dma_vec *vecs, size_t nents,
+   enum dma_transfer_direction dir, unsigned long prep_flags,
+   unsigned long flags)
+{
+   if (!chan || !chan->device || 
!chan->device->device_prep_peripheral_dma_vec)
+   return NULL;
+
+   return chan->device->device_prep_peripheral_dma_vec(chan, vecs, nents,
+   dir, prep_flags,
+   flags);
+}
+
 static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_sg(
struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len,
enum dma_transfer_direction dir, unsigned long flags)
-- 
2.43.0



[PATCH v9 0/6] iio: new DMABUF based API

2024-03-10 Thread Paul Cercueil
Hi Jonathan,

Here's the final-er version of the IIO DMABUF patchset.

This v9 fixes the few issues reported by the kernel bot.

This was based on next-20240308.

Changelog:

- [3/6]:
- Select DMA_SHARED_BUFFER in Kconfig
- Remove useless forward declaration of 'iio_dma_fence'
- Import DMA-BUF namespace
- Add missing __user tag to iio_buffer_detach_dmabuf() argument

Cheers,
-Paul

Paul Cercueil (6):
  dmaengine: Add API function dmaengine_prep_peripheral_dma_vec()
  dmaengine: dma-axi-dmac: Implement device_prep_peripheral_dma_vec
  iio: core: Add new DMABUF interface infrastructure
  iio: buffer-dma: Enable support for DMABUFs
  iio: buffer-dmaengine: Support new DMABUF based userspace API
  Documentation: iio: Document high-speed DMABUF based API

 Documentation/iio/iio_dmabuf_api.rst  |  54 ++
 Documentation/iio/index.rst   |   1 +
 drivers/dma/dma-axi-dmac.c|  40 ++
 drivers/iio/Kconfig   |   1 +
 drivers/iio/buffer/industrialio-buffer-dma.c  | 181 ++-
 .../buffer/industrialio-buffer-dmaengine.c|  59 ++-
 drivers/iio/industrialio-buffer.c | 462 ++
 include/linux/dmaengine.h |  27 +
 include/linux/iio/buffer-dma.h|  31 ++
 include/linux/iio/buffer_impl.h   |  30 ++
 include/uapi/linux/iio/buffer.h   |  22 +
 11 files changed, 891 insertions(+), 17 deletions(-)
 create mode 100644 Documentation/iio/iio_dmabuf_api.rst

-- 
2.43.0



Re: [PATCH v8 0/6] iio: new DMABUF based API

2024-03-10 Thread Jonathan Cameron
On Fri,  8 Mar 2024 18:00:40 +0100
Paul Cercueil  wrote:

> Hi Jonathan,
> 
> Here's the final(tm) version of the IIO DMABUF patchset.
> 
> This v8 fixes the remaining few issues that Christian reported.
> 
> I also updated the documentation patch as there has been changes to
> index.rst.
> 
> This was based on next-20240308.
> 
> Changelog:
> 
> - [3/6]:
> - Fix swapped fence direction
> - Simplify fence wait mechanism
> - Remove "Buffer closed with active transfers" print, as it was dead
>   code
> - Un-export iio_buffer_dmabuf_{get,put}. They are not used anywhere
>   else so they can even be static.
> - Prevent attaching already-attached DMABUFs
> - [6/6]:
> Renamed dmabuf_api.rst -> iio_dmabuf_api.rst, and updated index.rst
> whose format changed in iio/togreg.
> 
> Cheers,
> -Paul
Given nature of the build bug issues reported, I'm guessing you never
built this as a module :(  Not sure how one instance of a missing 
user marking got through but also easy to fix.

Anyhow, no need to wait before sending a v9 with those sorted.

0-day does it's job again - even better is that it's whilst it's
still your problem and not mine :)

Jonathan

> 
> Paul Cercueil (6):
>   dmaengine: Add API function dmaengine_prep_peripheral_dma_vec()
>   dmaengine: dma-axi-dmac: Implement device_prep_peripheral_dma_vec
>   iio: core: Add new DMABUF interface infrastructure
>   iio: buffer-dma: Enable support for DMABUFs
>   iio: buffer-dmaengine: Support new DMABUF based userspace API
>   Documentation: iio: Document high-speed DMABUF based API
> 
>  Documentation/iio/iio_dmabuf_api.rst  |  54 ++
>  Documentation/iio/index.rst   |   1 +
>  drivers/dma/dma-axi-dmac.c|  40 ++
>  drivers/iio/buffer/industrialio-buffer-dma.c  | 181 ++-
>  .../buffer/industrialio-buffer-dmaengine.c|  59 ++-
>  drivers/iio/industrialio-buffer.c | 462 ++
>  include/linux/dmaengine.h |  27 +
>  include/linux/iio/buffer-dma.h|  31 ++
>  include/linux/iio/buffer_impl.h   |  30 ++
>  include/uapi/linux/iio/buffer.h   |  22 +
>  10 files changed, 890 insertions(+), 17 deletions(-)
>  create mode 100644 Documentation/iio/iio_dmabuf_api.rst
> 



Re: [PATCH v2 14/28] sparc32: Drop unused mmu models

2024-03-10 Thread Sam Ravnborg
Hi kernel test robot et al.

On Sun, Mar 10, 2024 at 06:37:53PM +0800, kernel test robot wrote:
> Hi Sam,
> 
> kernel test robot noticed the following build warnings:
> 
> [auto build test WARNING on 84b76d05828a1909e20d0f66553b876b801f98c8]
> 
> url:
> https://github.com/intel-lab-lkp/linux/commits/Sam-Ravnborg-via-B4-Relay/sparc32-Update-defconfig-to-LEON-SMP/20240310-021717
> base:   84b76d05828a1909e20d0f66553b876b801f98c8
> patch link:
> https://lore.kernel.org/r/20240309-sunset-v2-14-f09912574d2c%40ravnborg.org
> patch subject: [PATCH v2 14/28] sparc32: Drop unused mmu models
> config: sparc-randconfig-r113-20240310 
> (https://download.01.org/0day-ci/archive/20240310/202403101854.z94sau13-...@intel.com/config)
> compiler: sparc-linux-gcc (GCC) 13.2.0
> reproduce: 
> (https://download.01.org/0day-ci/archive/20240310/202403101854.z94sau13-...@intel.com/reproduce)
> 
> If you fix the issue in a separate patch/commit (i.e. not just a new version 
> of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot 
> | Closes: 
> https://lore.kernel.org/oe-kbuild-all/202403101854.z94sau13-...@intel.com/
> 
> sparse warnings: (new ones prefixed by >>)
> >> arch/sparc/mm/srmmu.c:49:5: sparse: sparse: symbol 'vac_line_size' was not 
> >> declared. Should it be static?
> 
> vim +/vac_line_size +49 arch/sparc/mm/srmmu.c
> 
> accf032cfa582e Sam Ravnborg   2012-05-19  46  
> ^1da177e4c3f41 Linus Torvalds 2005-04-16  47  int vac_cache_size;
> 9d262d95114cf2 Guenter Roeck  2017-04-01  48  EXPORT_SYMBOL(vac_cache_size);
> ^1da177e4c3f41 Linus Torvalds 2005-04-16 @49  int vac_line_size;
> ^1da177e4c3f41 Linus Torvalds 2005-04-16  50  

vac_line_size is no longer used and can be deleted.
vac_cache_size is never written to and can be deleted too.

vac_cache_size is used in shmparam_32.h like this:
#define SHMLBA (vac_cache_size ? vac_cache_size : PAGE_SIZE)

The same file has:
#define __ARCH_FORCE_SHMLBA 1

If I understand it right then when SHMLBA equals PAGE_SIZE then there is
no need to define __ARCH_FORCE_SHMLBA and sparc32 can use the asm-generic
variant of shmparam.h

I will do this change in v3.

Sam


Re: [PATCH v8 3/6] iio: core: Add new DMABUF interface infrastructure

2024-03-10 Thread kernel test robot
Hi Paul,

kernel test robot noticed the following build errors:

[auto build test ERROR on jic23-iio/togreg]
[also build test ERROR on vkoul-dmaengine/next lwn/docs-next linus/master 
v6.8-rc7 next-20240308]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:
https://github.com/intel-lab-lkp/linux/commits/Paul-Cercueil/dmaengine-Add-API-function-dmaengine_prep_peripheral_dma_vec/20240309-010421
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git togreg
patch link:
https://lore.kernel.org/r/20240308170046.92899-4-paul%40crapouillou.net
patch subject: [PATCH v8 3/6] iio: core: Add new DMABUF interface infrastructure
config: um-randconfig-002-20240310 
(https://download.01.org/0day-ci/archive/20240310/202403101928.wwsqwfdg-...@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): 
(https://download.01.org/0day-ci/archive/20240310/202403101928.wwsqwfdg-...@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot 
| Closes: 
https://lore.kernel.org/oe-kbuild-all/202403101928.wwsqwfdg-...@intel.com/

All errors (new ones prefixed by >>):

   /usr/bin/ld: drivers/iio/industrialio-buffer.o: in function 
`iio_buffer_dmabuf_release':
>> industrialio-buffer.c:(.text+0xec6): undefined reference to 
>> `dma_buf_unmap_attachment'
>> /usr/bin/ld: industrialio-buffer.c:(.text+0xf96): undefined reference to 
>> `dma_buf_detach'
>> /usr/bin/ld: industrialio-buffer.c:(.text+0xfa5): undefined reference to 
>> `dma_buf_put'
   /usr/bin/ld: drivers/iio/industrialio-buffer.o: in function 
`iio_buffer_signal_dmabuf_done':
>> industrialio-buffer.c:(.text+0x4a56): undefined reference to 
>> `dma_fence_signal'
   /usr/bin/ld: drivers/iio/industrialio-buffer.o: in function 
`iio_buffer_cleanup':
>> industrialio-buffer.c:(.text+0x64f2): undefined reference to 
>> `dma_fence_release'
   /usr/bin/ld: drivers/iio/industrialio-buffer.o: in function 
`iio_buffer_attach_dmabuf.isra.0':
>> industrialio-buffer.c:(.text+0x9dbf): undefined reference to 
>> `dma_fence_context_alloc'
>> /usr/bin/ld: industrialio-buffer.c:(.text+0x9df7): undefined reference to 
>> `dma_buf_get'
>> /usr/bin/ld: industrialio-buffer.c:(.text+0x9e38): undefined reference to 
>> `dma_buf_attach'
>> /usr/bin/ld: industrialio-buffer.c:(.text+0x9efe): undefined reference to 
>> `dma_buf_map_attachment'
   /usr/bin/ld: industrialio-buffer.c:(.text+0xa2c1): undefined reference to 
`dma_buf_detach'
   /usr/bin/ld: industrialio-buffer.c:(.text+0xa2cd): undefined reference to 
`dma_buf_put'
>> /usr/bin/ld: industrialio-buffer.c:(.text+0xa34d): undefined reference to 
>> `dma_buf_unmap_attachment'
   /usr/bin/ld: drivers/iio/industrialio-buffer.o: in function 
`iio_buffer_enqueue_dmabuf':
>> industrialio-buffer.c:(.text+0xa949): undefined reference to `dma_buf_get'
   /usr/bin/ld: industrialio-buffer.c:(.text+0xa997): undefined reference to 
`dma_buf_put'
>> /usr/bin/ld: industrialio-buffer.c:(.text+0xac84): undefined reference to 
>> `dma_fence_init'
>> /usr/bin/ld: industrialio-buffer.c:(.text+0xad4b): undefined reference to 
>> `dma_resv_wait_timeout'
>> /usr/bin/ld: industrialio-buffer.c:(.text+0xadec): undefined reference to 
>> `dma_resv_reserve_fences'
>> /usr/bin/ld: industrialio-buffer.c:(.text+0xae2c): undefined reference to 
>> `dma_resv_add_fence'
>> /usr/bin/ld: industrialio-buffer.c:(.text+0xb0da): undefined reference to 
>> `dma_fence_release'
   /usr/bin/ld: drivers/iio/industrialio-buffer.o: in function 
`iio_buffer_chrdev_ioctl':
   industrialio-buffer.c:(.text+0xb833): undefined reference to `dma_buf_get'
   /usr/bin/ld: industrialio-buffer.c:(.text+0xbad0): undefined reference to 
`dma_buf_put'
   collect2: error: ld returned 1 exit status

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


Re: [PATCH v2 14/28] sparc32: Drop unused mmu models

2024-03-10 Thread kernel test robot
Hi Sam,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 84b76d05828a1909e20d0f66553b876b801f98c8]

url:
https://github.com/intel-lab-lkp/linux/commits/Sam-Ravnborg-via-B4-Relay/sparc32-Update-defconfig-to-LEON-SMP/20240310-021717
base:   84b76d05828a1909e20d0f66553b876b801f98c8
patch link:
https://lore.kernel.org/r/20240309-sunset-v2-14-f09912574d2c%40ravnborg.org
patch subject: [PATCH v2 14/28] sparc32: Drop unused mmu models
config: sparc-randconfig-r113-20240310 
(https://download.01.org/0day-ci/archive/20240310/202403101854.z94sau13-...@intel.com/config)
compiler: sparc-linux-gcc (GCC) 13.2.0
reproduce: 
(https://download.01.org/0day-ci/archive/20240310/202403101854.z94sau13-...@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot 
| Closes: 
https://lore.kernel.org/oe-kbuild-all/202403101854.z94sau13-...@intel.com/

sparse warnings: (new ones prefixed by >>)
>> arch/sparc/mm/srmmu.c:49:5: sparse: sparse: symbol 'vac_line_size' was not 
>> declared. Should it be static?

vim +/vac_line_size +49 arch/sparc/mm/srmmu.c

accf032cfa582e Sam Ravnborg   2012-05-19  46  
^1da177e4c3f41 Linus Torvalds 2005-04-16  47  int vac_cache_size;
9d262d95114cf2 Guenter Roeck  2017-04-01  48  EXPORT_SYMBOL(vac_cache_size);
^1da177e4c3f41 Linus Torvalds 2005-04-16 @49  int vac_line_size;
^1da177e4c3f41 Linus Torvalds 2005-04-16  50  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


Re: [PATCH v3 2/2] backlight: Add new lm3509 backlight driver

2024-03-10 Thread Sam Ravnborg
Hi Patrick,

a few comments in the following.

Sam

On Sat, Mar 09, 2024 at 02:24:56PM +0100, Patrick Gansterer wrote:
> This is a general driver for LM3509 backlight chip of TI.
> LM3509 is High Efficiency Boost for White LEDs and/or OLED Displays with
> Dual Current Sinks. This driver supports OLED/White LED select, brightness
> control and sub/main control.
> The datasheet can be found at http://www.ti.com/product/lm3509.
> 
> Signed-off-by: Patrick Gansterer 
> ---
>  drivers/video/backlight/Kconfig |   7 +
>  drivers/video/backlight/Makefile|   1 +
>  drivers/video/backlight/lm3509_bl.c | 340 
>  3 files changed, 348 insertions(+)
>  create mode 100644 drivers/video/backlight/lm3509_bl.c
> 
> diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
> index ea2d0d69bd8c..96ad5dc584b6 100644
> --- a/drivers/video/backlight/Kconfig
> +++ b/drivers/video/backlight/Kconfig
> @@ -366,6 +366,13 @@ config BACKLIGHT_AAT2870
> If you have a AnalogicTech AAT2870 say Y to enable the
> backlight driver.
>  
> +config BACKLIGHT_LM3509
> + tristate "Backlight Driver for LM3509"
> + depends on I2C
> + select REGMAP_I2C
> + help
> +   This supports TI LM3509 Backlight Driver
> +
>  config BACKLIGHT_LM3630A
>   tristate "Backlight Driver for LM3630A"
>   depends on I2C && PWM
> diff --git a/drivers/video/backlight/Makefile 
> b/drivers/video/backlight/Makefile
> index 06966cb20459..51a4ac5d0530 100644
> --- a/drivers/video/backlight/Makefile
> +++ b/drivers/video/backlight/Makefile
> @@ -35,6 +35,7 @@ obj-$(CONFIG_BACKLIGHT_HP700)   += 
> jornada720_bl.o
>  obj-$(CONFIG_BACKLIGHT_IPAQ_MICRO)   += ipaq_micro_bl.o
>  obj-$(CONFIG_BACKLIGHT_KTD253)   += ktd253-backlight.o
>  obj-$(CONFIG_BACKLIGHT_KTZ8866)  += ktz8866.o
> +obj-$(CONFIG_BACKLIGHT_LM3509)   += lm3509_bl.o
>  obj-$(CONFIG_BACKLIGHT_LM3533)   += lm3533_bl.o
>  obj-$(CONFIG_BACKLIGHT_LM3630A)  += lm3630a_bl.o
>  obj-$(CONFIG_BACKLIGHT_LM3639)   += lm3639_bl.o
> diff --git a/drivers/video/backlight/lm3509_bl.c 
> b/drivers/video/backlight/lm3509_bl.c
> new file mode 100644
> index ..bfad0aaffa0d
> --- /dev/null
> +++ b/drivers/video/backlight/lm3509_bl.c
> @@ -0,0 +1,340 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#define LM3509_NAME "lm3509_bl"
> +
> +#define LM3509_SINK_MAIN 0
> +#define LM3509_SINK_SUB 1
> +#define LM3509_NUM_SINKS 2
> +
> +#define LM3509_DEF_BRIGHTNESS 0x12
> +#define LM3509_MAX_BRIGHTNESS 0x1F
> +
> +#define REG_GP 0x10
> +#define REG_BMAIN 0xA0
> +#define REG_BSUB 0xB0
> +#define REG_MAX 0xFF
> +
> +enum {
> + REG_GP_ENM_BIT = 0,
> + REG_GP_ENS_BIT,
> + REG_GP_UNI_BIT,
> + REG_GP_RMP0_BIT,
> + REG_GP_RMP1_BIT,
> + REG_GP_OLED_BIT,
> +};
> +
> +struct lm3509_bl {
> + struct regmap *regmap;
> + struct backlight_device *bl_main;
> + struct backlight_device *bl_sub;
> + struct gpio_desc *reset_gpio;
> +};
> +
> +struct lm3509_bl_led_pdata {
> + const char *label;
> + int led_sources;
> + u32 brightness;
> + u32 max_brightness;
> +};
> +
> +static void lm3509_reset(struct lm3509_bl *data)
> +{
> + if (data->reset_gpio) {
> + gpiod_set_value(data->reset_gpio, 1);
> + udelay(1);
> + gpiod_set_value(data->reset_gpio, 0);
> + udelay(10);
> + }
> +}
> +
> +static int lm3509_update_status(struct backlight_device *bl,
> + unsigned int en_mask, unsigned int br_reg)
> +{
> + struct lm3509_bl *data = bl_get_data(bl);
> + int ret;
> + bool en;
> +
> + ret = regmap_write(data->regmap, br_reg, bl->props.brightness);

Here you can use backlight_get_brightness() thus avoiding direct access
to backlight internal properties.

> + if (ret < 0)
> + return ret;
> +
> + en = bl->props.power <= FB_BLANK_NORMAL;
Use backlight_is_blank() here.

Sam



> + return regmap_update_bits(data->regmap, REG_GP, en_mask,
> +   en ? en_mask : 0);
> +}
> +
> +static int lm3509_main_update_status(struct backlight_device *bl)
> +{
> + return lm3509_update_status(bl, BIT(REG_GP_ENM_BIT), REG_BMAIN);
> +}
> +
> +static const struct backlight_ops lm3509_main_ops = {
> + .options = BL_CORE_SUSPENDRESUME,
> + .update_status = lm3509_main_update_status,
> +};
> +
> +static int lm3509_sub_update_status(struct backlight_device *bl)
> +{
> + return lm3509_update_status(bl, BIT(REG_GP_ENS_BIT), REG_BSUB);
> +}
> +
> +static const struct backlight_ops lm3509_sub_ops = {
> + .options = BL_CORE_SUSPENDRESUME,
> + .update_status = lm3509_sub_update_status,
> +};
> +
> +static struct backlight_device *
> +lm3509_backlight_register(struct device *dev, const char 

Re: [PATCH v3 1/2] dt-bindings: backlight: Add Texas Instruments LM3509

2024-03-10 Thread Krzysztof Kozlowski
On 09/03/2024 14:24, Patrick Gansterer wrote:
> Add Device Tree bindings for Texas Instruments LM3509 - a
> High Efficiency Boost for White LED's and/or OLED Displays
> 
> Signed-off-by: Patrick Gansterer 
> ---

Reviewed-by: Krzysztof Kozlowski 

Best regards,
Krzysztof



Re: [PATCH v3 1/2] dt-bindings: backlight: Add Texas Instruments LM3509

2024-03-10 Thread Krzysztof Kozlowski
On 09/03/2024 14:24, Patrick Gansterer wrote:
> Add Device Tree bindings for Texas Instruments LM3509 - a
> High Efficiency Boost for White LED's and/or OLED Displays
> 
> Signed-off-by: Patrick Gansterer 
> ---
> Changes in v3:
>   Improved device tree bindings documentation style

That's way too generic. Everything can be called style. If you only
improved style, then my comments regarding real issues like missing
defaults were not implemented?

Best regards,
Krzysztof