* [PATCH v2 0/4] staging: sm750fb: various code cleanups
From: Ahmet Sezgin Duran @ 2026-05-23 15:34 UTC (permalink / raw)
To: gregkh
Cc: error27, linux-fbdev, linux-staging, linux-kernel,
Ahmet Sezgin Duran
This series performs several cleanups on the sm750fb staging driver
to improve code readability and remove redundancy.
The changes include:
- Removing a block of commented-out forward declarations.
- Removing redundant variable initializations.
- Removing unused struct fields.
- Deduplicating per-index fbinfo handling in suspend/resume using
a loop.
No functional changes are intended.
Changes since v1:
- Dropped "staging: sm750fb: use ARRAY_SIZE macro in fb_find_mode
loop" per Dan Carpenter's review.
Link: <https://lore.kernel.org/linux-staging/ahF8dacOkX0tdxGf@stanley.mountain/>
v1: <https://lore.kernel.org/all/20260523051509.166152-1-ahmet@sezginduran.net>
Ahmet Sezgin Duran (4):
staging: sm750fb: remove commented-out forward declarations
staging: sm750fb: remove unnecessary initializations
staging: sm750fb: remove unused struct fields
staging: sm750fb: deduplicate fbinfo loop in suspend/resume
drivers/staging/sm750fb/sm750.c | 45 ++++++++++-----------------------
drivers/staging/sm750fb/sm750.h | 3 ---
2 files changed, 13 insertions(+), 35 deletions(-)
base-commit: 7cb1c5b32a2bfde961fff8d5204526b609bcb30a
--
2.53.0
^ permalink raw reply
* [PATCH v2 1/4] staging: sm750fb: remove commented-out forward declarations
From: Ahmet Sezgin Duran @ 2026-05-23 15:34 UTC (permalink / raw)
To: gregkh
Cc: error27, linux-fbdev, linux-staging, linux-kernel,
Ahmet Sezgin Duran
In-Reply-To: <20260523153459.177488-1-ahmet@sezginduran.net>
The block at the top of sm750.c declares lynxfb_ops_write() and
lynxfb_ops_read() inside a commented-out #ifdef __BIG_ENDIAN guard.
Neither function is defined anywhere in the driver, so the block
is dead. Remove it.
Signed-off-by: Ahmet Sezgin Duran <ahmet@sezginduran.net>
---
v2: No changes.
drivers/staging/sm750fb/sm750.c | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c
index 89c811e0806c..02db1418476b 100644
--- a/drivers/staging/sm750fb/sm750.c
+++ b/drivers/staging/sm750fb/sm750.c
@@ -8,15 +8,6 @@
#include "sm750_accel.h"
#include "sm750_cursor.h"
-/*
- * #ifdef __BIG_ENDIAN
- * ssize_t lynxfb_ops_write(struct fb_info *info, const char __user *buf,
- * size_t count, loff_t *ppos);
- * ssize_t lynxfb_ops_read(struct fb_info *info, char __user *buf,
- * size_t count, loff_t *ppos);
- * #endif
- */
-
/* common var for all device */
static int g_hwcursor = 1;
static int g_noaccel __ro_after_init;
--
2.53.0
^ permalink raw reply related
* Re: [PATCH 4/5] staging: sm750fb: use ARRAY_SIZE macro in fb_find_mode loop
From: Ahmet Sezgin Duran @ 2026-05-23 15:06 UTC (permalink / raw)
To: Dan Carpenter; +Cc: gregkh, linux-fbdev, linux-staging, linux-kernel
In-Reply-To: <ahF8dacOkX0tdxGf@stanley.mountain>
On 5/23/26 1:07 PM, Dan Carpenter wrote:
> I don't love this. As you mentioned, there are two arrays and they
> both have 3 elements. Why prefer one over the other? This patch
> makes the code look simpler than it really is. I would just leave
> it as 3.
>
> regards,
> dan carpenter
>
Fair. Going to drop that and send v2.
Thanks for the review.
Regards,
Ahmet Sezgin Duran
^ permalink raw reply
* Re: [PATCH 4/5] staging: sm750fb: use ARRAY_SIZE macro in fb_find_mode loop
From: Dan Carpenter @ 2026-05-23 10:07 UTC (permalink / raw)
To: Ahmet Sezgin Duran; +Cc: gregkh, linux-fbdev, linux-staging, linux-kernel
In-Reply-To: <20260523051509.166152-5-ahmet@sezginduran.net>
On Sat, May 23, 2026 at 05:15:08AM +0000, Ahmet Sezgin Duran wrote:
> The loop in lynxfb_set_fbinfo() iterates over pdb[] and cdb[] using
> a hardcoded bound of 3.
>
> Replace it with ARRAY_SIZE(pdb) so the bound tracks the array.
I don't love this. As you mentioned, there are two arrays and they
both have 3 elements. Why prefer one over the other? This patch
makes the code look simpler than it really is. I would just leave
it as 3.
regards,
dan carpenter
^ permalink raw reply
* [PATCH 5/5] staging: sm750fb: deduplicate fbinfo loop in suspend/resume
From: Ahmet Sezgin Duran @ 2026-05-23 5:15 UTC (permalink / raw)
To: gregkh; +Cc: linux-fbdev, linux-staging, linux-kernel, Ahmet Sezgin Duran
In-Reply-To: <20260523051509.166152-1-ahmet@sezginduran.net>
lynxfb_suspend() and lynxfb_resume() both walk sm750_dev->fbinfo[]
via duplicated per-index blocks for fbinfo[0] and fbinfo[1].
Replace each pair of blocks with a for-loop bounded by
sm750_dev->fb_count, the number of successfully registered
framebuffers.
No functional changes intended.
Signed-off-by: Ahmet Sezgin Duran <ahmet@sezginduran.net>
---
drivers/staging/sm750fb/sm750.c | 34 +++++++++++++--------------------
1 file changed, 13 insertions(+), 21 deletions(-)
diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c
index 465615b528fd..279471d6cd14 100644
--- a/drivers/staging/sm750fb/sm750.c
+++ b/drivers/staging/sm750fb/sm750.c
@@ -388,18 +388,18 @@ static int __maybe_unused lynxfb_suspend(struct device *dev)
{
struct fb_info *info;
struct sm750_dev *sm750_dev;
+ int i;
sm750_dev = dev_get_drvdata(dev);
console_lock();
- info = sm750_dev->fbinfo[0];
- if (info)
- /* 1 means do suspend */
- fb_set_suspend(info, 1);
- info = sm750_dev->fbinfo[1];
- if (info)
- /* 1 means do suspend */
- fb_set_suspend(info, 1);
+
+ for (i = 0; i < sm750_dev->fb_count; i++) {
+ info = sm750_dev->fbinfo[i];
+ if (info)
+ /* 1 means do suspend */
+ fb_set_suspend(info, 1);
+ }
console_unlock();
return 0;
@@ -414,6 +414,7 @@ static int __maybe_unused lynxfb_resume(struct device *dev)
struct lynxfb_par *par;
struct lynxfb_crtc *crtc;
struct lynx_cursor *cursor;
+ int i;
sm750_dev = pci_get_drvdata(pdev);
@@ -421,21 +422,12 @@ static int __maybe_unused lynxfb_resume(struct device *dev)
hw_sm750_inithw(sm750_dev, pdev);
- info = sm750_dev->fbinfo[0];
-
- if (info) {
- par = info->par;
- crtc = &par->crtc;
- cursor = &crtc->cursor;
- memset_io(cursor->vstart, 0x0, cursor->size);
- memset_io(crtc->v_screen, 0x0, crtc->vidmem_size);
- lynxfb_ops_set_par(info);
- fb_set_suspend(info, 0);
- }
+ for (i = 0; i < sm750_dev->fb_count; i++) {
+ info = sm750_dev->fbinfo[i];
- info = sm750_dev->fbinfo[1];
+ if (!info)
+ continue;
- if (info) {
par = info->par;
crtc = &par->crtc;
cursor = &crtc->cursor;
--
2.53.0
^ permalink raw reply related
* [PATCH 1/5] staging: sm750fb: remove commented-out forward declarations
From: Ahmet Sezgin Duran @ 2026-05-23 5:15 UTC (permalink / raw)
To: gregkh; +Cc: linux-fbdev, linux-staging, linux-kernel, Ahmet Sezgin Duran
In-Reply-To: <20260523051509.166152-1-ahmet@sezginduran.net>
The block at the top of sm750.c declares lynxfb_ops_write() and
lynxfb_ops_read() inside a commented-out #ifdef __BIG_ENDIAN guard.
Neither function is defined anywhere in the driver, so the block
is dead. Remove it.
Signed-off-by: Ahmet Sezgin Duran <ahmet@sezginduran.net>
---
drivers/staging/sm750fb/sm750.c | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c
index 89c811e0806c..02db1418476b 100644
--- a/drivers/staging/sm750fb/sm750.c
+++ b/drivers/staging/sm750fb/sm750.c
@@ -8,15 +8,6 @@
#include "sm750_accel.h"
#include "sm750_cursor.h"
-/*
- * #ifdef __BIG_ENDIAN
- * ssize_t lynxfb_ops_write(struct fb_info *info, const char __user *buf,
- * size_t count, loff_t *ppos);
- * ssize_t lynxfb_ops_read(struct fb_info *info, char __user *buf,
- * size_t count, loff_t *ppos);
- * #endif
- */
-
/* common var for all device */
static int g_hwcursor = 1;
static int g_noaccel __ro_after_init;
--
2.53.0
^ permalink raw reply related
* [PATCH 4/5] staging: sm750fb: use ARRAY_SIZE macro in fb_find_mode loop
From: Ahmet Sezgin Duran @ 2026-05-23 5:15 UTC (permalink / raw)
To: gregkh; +Cc: linux-fbdev, linux-staging, linux-kernel, Ahmet Sezgin Duran
In-Reply-To: <20260523051509.166152-1-ahmet@sezginduran.net>
The loop in lynxfb_set_fbinfo() iterates over pdb[] and cdb[] using
a hardcoded bound of 3.
Replace it with ARRAY_SIZE(pdb) so the bound tracks the array.
Signed-off-by: Ahmet Sezgin Duran <ahmet@sezginduran.net>
---
drivers/staging/sm750fb/sm750.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c
index fff9c35ee7b0..465615b528fd 100644
--- a/drivers/staging/sm750fb/sm750.c
+++ b/drivers/staging/sm750fb/sm750.c
@@ -764,7 +764,7 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index)
g_fbmode[index] = g_fbmode[0];
}
- for (i = 0; i < 3; i++) {
+ for (i = 0; i < ARRAY_SIZE(pdb); i++) {
ret = fb_find_mode(var, info, g_fbmode[index],
pdb[i], cdb[i], NULL, 8);
--
2.53.0
^ permalink raw reply related
* [PATCH 3/5] staging: sm750fb: remove unused struct fields
From: Ahmet Sezgin Duran @ 2026-05-23 5:15 UTC (permalink / raw)
To: gregkh; +Cc: linux-fbdev, linux-staging, linux-kernel, Ahmet Sezgin Duran
In-Reply-To: <20260523051509.166152-1-ahmet@sezginduran.net>
Remove `void *priv` pointer field in following struct definitions:
- `struct lynxfb_crtc`
- `struct lynxfb_output`
Verified that no other code references them.
No functional changes.
Signed-off-by: Ahmet Sezgin Duran <ahmet@sezginduran.net>
---
drivers/staging/sm750fb/sm750.h | 3 ---
1 file changed, 3 deletions(-)
diff --git a/drivers/staging/sm750fb/sm750.h b/drivers/staging/sm750fb/sm750.h
index d2c522e67f26..56d7e1fa4557 100644
--- a/drivers/staging/sm750fb/sm750.h
+++ b/drivers/staging/sm750fb/sm750.h
@@ -145,8 +145,6 @@ struct lynxfb_crtc {
u16 ypanstep;
u16 ywrapstep;
- void *priv;
-
/* cursor information */
struct lynx_cursor cursor;
};
@@ -168,7 +166,6 @@ struct lynxfb_output {
* *channel=1 means secondary channel
* output->channel ==> &crtc->channel
*/
- void *priv;
};
struct lynxfb_par {
--
2.53.0
^ permalink raw reply related
* [PATCH 2/5] staging: sm750fb: remove unnecessary initializations
From: Ahmet Sezgin Duran @ 2026-05-23 5:15 UTC (permalink / raw)
To: gregkh; +Cc: linux-fbdev, linux-staging, linux-kernel, Ahmet Sezgin Duran
In-Reply-To: <20260523051509.166152-1-ahmet@sezginduran.net>
Remove two instances of `ret = 0` initializations since the
variable is overridden unconditionally before being used.
Signed-off-by: Ahmet Sezgin Duran <ahmet@sezginduran.net>
---
drivers/staging/sm750fb/sm750.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c
index 02db1418476b..fff9c35ee7b0 100644
--- a/drivers/staging/sm750fb/sm750.c
+++ b/drivers/staging/sm750fb/sm750.c
@@ -343,7 +343,6 @@ static int lynxfb_ops_set_par(struct fb_info *info)
if (!info)
return -EINVAL;
- ret = 0;
par = info->par;
crtc = &par->crtc;
output = &par->output;
@@ -463,7 +462,6 @@ static int lynxfb_ops_check_var(struct fb_var_screeninfo *var,
if (!var->pixclock)
return -EINVAL;
- ret = 0;
par = info->par;
crtc = &par->crtc;
--
2.53.0
^ permalink raw reply related
* [PATCH 0/5] staging: sm750fb: various code cleanups
From: Ahmet Sezgin Duran @ 2026-05-23 5:15 UTC (permalink / raw)
To: gregkh; +Cc: linux-fbdev, linux-staging, linux-kernel, Ahmet Sezgin Duran
This series performs several cleanups on the sm750fb staging driver
to improve code readability and remove redundancy.
The changes include:
- Removing a block of commented-out forward declarations.
- Removing redundant variable initializations.
- Removing unused struct fields.
- Replacing a hardcoded loop bound with ARRAY_SIZE().
- Deduplicating per-index fbinfo handling in suspend/resume using
a loop.
No functional changes are intended.
Ahmet Sezgin Duran (5):
staging: sm750fb: remove commented-out forward declarations
staging: sm750fb: remove unnecessary initializations
staging: sm750fb: remove unused struct fields
staging: sm750fb: use ARRAY_SIZE macro in fb_find_mode loop
staging: sm750fb: deduplicate fbinfo loop in suspend/resume
drivers/staging/sm750fb/sm750.c | 47 ++++++++++-----------------------
drivers/staging/sm750fb/sm750.h | 3 ---
2 files changed, 14 insertions(+), 36 deletions(-)
base-commit: 7cb1c5b32a2bfde961fff8d5204526b609bcb30a
--
2.53.0
^ permalink raw reply
* Re: [PATCH] ARM: mach-rpc: fix zImage build after recent font-related changes
From: Helge Deller @ 2026-05-22 22:03 UTC (permalink / raw)
To: Ethan Nelson-Moore, Helge Deller
Cc: linux-arm-kernel, linux-fbdev, Russell King
In-Reply-To: <0aa1e2b5-0700-460c-985f-963c1372c2e1@gmx.de>
On 5/22/26 23:49, Helge Deller wrote:
> Hi Ethan,
>
> On 5/20/26 06:49, Ethan Nelson-Moore wrote:
>> Thanks for investigating this issue.
>>
>> On Tue, May 19, 2026 at 2:11 AM Helge Deller <deller@kernel.org> wrote:
>>> Ethan, does this compile-only-tested patch fix the issue?
>> It almost does - I also had to remove #include <linux/math.h> from
>> include/linux/font.h.
>> This is probably because of the following highly questionable code in
>> arch/arm/boot/compressed/Makefile:
>> CFLAGS_font.o := -Dstatic=
>> which is causing unused static functions to not be optimized out. (The
>> real purpose of it is to make the acorndata_8x8 array non-static so
>> the decompressor can use it.) Really, the decompressor should be fixed
>> to not use this hack.
>
> Would it help to mark acorndata_8x8 with attribute("visible") ?
> That way it should become accessible.
>
>>> Maybe only the first hunk is necessary.
>> You're right. The kernel links successfully with only the #include
>> <linux/math.h> removal and the first hunk applied.
>
> Ok, good.
> How shall we continue?
> Do you want to try the visible trick?
I meant the __visible #define from
include/linux/compiler_attributes.h:# define __visible __attribute__((__externally_visible__))
I understand it might conflict with the "static" keyword (I did not test).
In your patch you #defined OMIT_FONT_DESC:
+# decompressor. OMIT_FONT_DESC is used in lib/fonts/font_acorn_8x8.c to omit the
+# definition of the font's font_desc structure, which requires <linux/font.h>.
+CFLAGS_font.o := -Dstatic= -D_VIDEO_FONT_H -DOMIT_FONT_DESC
On parisc I used a #define BOOTLOADER, which already describes the reason.
For your patch you could also use the "BOOTLOADER" define and then (instead of using __visible):
#ifdef BOOTLOADER
static const struct font_data acorndata_8x8 =
#else
const struct font_data acorndata_8x8 = {
#endif
?
Helge
^ permalink raw reply
* Re: [PATCH] ARM: mach-rpc: fix zImage build after recent font-related changes
From: Helge Deller @ 2026-05-22 21:49 UTC (permalink / raw)
To: Ethan Nelson-Moore, Helge Deller
Cc: linux-arm-kernel, linux-fbdev, Russell King
In-Reply-To: <CADkSEUhhLL6WxUWBChdA=LFrYZQJsCLKOFJoXA_Jsdpab6qx0A@mail.gmail.com>
Hi Ethan,
On 5/20/26 06:49, Ethan Nelson-Moore wrote:
> Thanks for investigating this issue.
>
> On Tue, May 19, 2026 at 2:11 AM Helge Deller <deller@kernel.org> wrote:
>> Ethan, does this compile-only-tested patch fix the issue?
> It almost does - I also had to remove #include <linux/math.h> from
> include/linux/font.h.
> This is probably because of the following highly questionable code in
> arch/arm/boot/compressed/Makefile:
> CFLAGS_font.o := -Dstatic=
> which is causing unused static functions to not be optimized out. (The
> real purpose of it is to make the acorndata_8x8 array non-static so
> the decompressor can use it.) Really, the decompressor should be fixed
> to not use this hack.
Would it help to mark acorndata_8x8 with attribute("visible") ?
That way it should become accessible.
>> Maybe only the first hunk is necessary.
> You're right. The kernel links successfully with only the #include
> <linux/math.h> removal and the first hunk applied.
Ok, good.
How shall we continue?
Do you want to try the visible trick?
Helge
>
> Have a nice day!
>
> Ethan
^ permalink raw reply
* Re: [PATCH v2 0/4] fbdev: Internalize fbcon
From: Helge Deller @ 2026-05-22 13:59 UTC (permalink / raw)
To: Thomas Zimmermann; +Cc: dri-devel, linux-fbdev, linuxppc-dev
In-Reply-To: <20260522123019.211059-1-tzimmermann@suse.de>
On 5/22/26 14:28, Thomas Zimmermann wrote:
> Turn fbcon into an internal client of fbdev. Manage all interactions
> with graphics drivers within fbdev. Add helpers for these tasks and
> convert drivers.
>
> Fbdev's PS3 and SH-Mobile drivers update fbcon as part of user-invoked
> mode changes. Call the new helpers, which also fix inconsistencies
> among the various code paths.
>
> Vga-switcheroo remaps the fbcon terminals when switching physical
> outputs. For now, hide this in another helper. The call will later
> move into DRM's fbdev emulation.
>
> When all refactoring in place, fbdev manages fbcon interactions by
> itself. Remove the public interfaces.
>
> v2:
> - use '#if defined' (Helge)
>
> Thomas Zimmermann (4):
> fbdev: Wrap user-invoked calls to fb_set_var() in helper
> fbdev: Wrap user-invoked calls to fb_blank() in helper
> fbdev: Wrap fbcon updates from vga-switcheroo in helper
> fbdev: Do not export fbcon from fbdev
>
> MAINTAINERS | 1 -
> drivers/gpu/vga/vga_switcheroo.c | 6 +--
> drivers/video/fbdev/core/fb_chrdev.c | 12 ++----
> drivers/video/fbdev/core/fb_internal.h | 1 +
> drivers/video/fbdev/core/fbcon.c | 3 --
> drivers/video/fbdev/core/fbcon.h | 50 +++++++++++++++++++++++
> drivers/video/fbdev/core/fbmem.c | 35 +++++++++++++++-
> drivers/video/fbdev/core/fbsysfs.c | 9 +----
> drivers/video/fbdev/ps3fb.c | 5 +--
> drivers/video/fbdev/sh_mobile_lcdcfb.c | 5 +--
> include/linux/fb.h | 3 ++
> include/linux/fbcon.h | 55 --------------------------
> 12 files changed, 98 insertions(+), 87 deletions(-)
> delete mode 100644 include/linux/fbcon.h
series applied to fbdev git tree.
Thanks!
Helge
^ permalink raw reply
* [PATCH v2 4/4] fbdev: Do not export fbcon from fbdev
From: Thomas Zimmermann @ 2026-05-22 12:28 UTC (permalink / raw)
To: deller, simona, airlied, lukas, maddy, mpe, npiggin, chleroy
Cc: dri-devel, linux-fbdev, linuxppc-dev, Thomas Zimmermann
In-Reply-To: <20260522123019.211059-1-tzimmermann@suse.de>
There are no callers of fbcon outside fbdev. Move the declarations
into the internal header.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
MAINTAINERS | 1 -
drivers/video/fbdev/core/fb_chrdev.c | 2 +-
drivers/video/fbdev/core/fbcon.c | 1 -
drivers/video/fbdev/core/fbcon.h | 50 +++++++++++++++++++++++++
drivers/video/fbdev/core/fbmem.c | 2 +-
include/linux/fbcon.h | 55 ----------------------------
6 files changed, 52 insertions(+), 59 deletions(-)
delete mode 100644 include/linux/fbcon.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 6810710e7a57..0ed3ef0b466a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10147,7 +10147,6 @@ F: drivers/video/fbdev/core/fbcon_rotate.h
F: drivers/video/fbdev/core/fbcon_ud.c
F: drivers/video/fbdev/core/softcursor.c
F: drivers/video/fbdev/core/tileblit.c
-F: include/linux/fbcon.h
F: include/linux/font.h
F: lib/fonts/
diff --git a/drivers/video/fbdev/core/fb_chrdev.c b/drivers/video/fbdev/core/fb_chrdev.c
index 035e67d2c28f..ba1d0bc214c5 100644
--- a/drivers/video/fbdev/core/fb_chrdev.c
+++ b/drivers/video/fbdev/core/fb_chrdev.c
@@ -3,10 +3,10 @@
#include <linux/compat.h>
#include <linux/console.h>
#include <linux/fb.h>
-#include <linux/fbcon.h>
#include <linux/major.h>
#include "fb_internal.h"
+#include "fbcon.h"
/*
* We hold a reference to the fb_info in file->private_data,
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 50b84cd32938..853b52b40d01 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -70,7 +70,6 @@
#include <linux/printk.h>
#include <linux/slab.h>
#include <linux/fb.h>
-#include <linux/fbcon.h>
#include <linux/vt_kern.h>
#include <linux/selection.h>
#include <linux/font.h>
diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h
index 321cc7f44baa..407d207b14f1 100644
--- a/drivers/video/fbdev/core/fbcon.h
+++ b/drivers/video/fbdev/core/fbcon.h
@@ -11,6 +11,7 @@
#ifndef _VIDEO_FBCON_H
#define _VIDEO_FBCON_H
+#include <linux/compiler_types.h>
#include <linux/font.h>
#include <linux/types.h>
#include <linux/vt_buffer.h>
@@ -19,6 +20,11 @@
#include <asm/io.h>
+struct fb_blit_caps;
+struct fb_info;
+struct fb_var_screeninfo;
+struct fb_videomode;
+
/*
* This is the interface between the low-level console driver and the
* low-level frame buffer device
@@ -233,4 +239,48 @@ static inline int get_attribute(struct fb_info *info, u16 c)
(void) (&_r == &_v); \
(i == FB_ROTATE_UR || i == FB_ROTATE_UD) ? _r : _v; })
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE
+void __init fb_console_init(void);
+void __exit fb_console_exit(void);
+int fbcon_fb_registered(struct fb_info *info);
+void fbcon_fb_unregistered(struct fb_info *info);
+void fbcon_fb_unbind(struct fb_info *info);
+void fbcon_suspended(struct fb_info *info);
+void fbcon_resumed(struct fb_info *info);
+int fbcon_mode_deleted(struct fb_info *info,
+ struct fb_videomode *mode);
+void fbcon_delete_modelist(struct list_head *head);
+void fbcon_new_modelist(struct fb_info *info);
+void fbcon_get_requirement(struct fb_info *info,
+ struct fb_blit_caps *caps);
+void fbcon_fb_blanked(struct fb_info *info, int blank);
+int fbcon_modechange_possible(struct fb_info *info,
+ struct fb_var_screeninfo *var);
+void fbcon_update_vcs(struct fb_info *info, bool all);
+void fbcon_remap_all(struct fb_info *info);
+int fbcon_set_con2fb_map_ioctl(void __user *argp);
+int fbcon_get_con2fb_map_ioctl(void __user *argp);
+#else
+static inline void fb_console_init(void) {}
+static inline void fb_console_exit(void) {}
+static inline int fbcon_fb_registered(struct fb_info *info) { return 0; }
+static inline void fbcon_fb_unregistered(struct fb_info *info) {}
+static inline void fbcon_fb_unbind(struct fb_info *info) {}
+static inline void fbcon_suspended(struct fb_info *info) {}
+static inline void fbcon_resumed(struct fb_info *info) {}
+static inline int fbcon_mode_deleted(struct fb_info *info,
+ struct fb_videomode *mode) { return 0; }
+static inline void fbcon_delete_modelist(struct list_head *head) {}
+static inline void fbcon_new_modelist(struct fb_info *info) {}
+static inline void fbcon_get_requirement(struct fb_info *info,
+ struct fb_blit_caps *caps) {}
+static inline void fbcon_fb_blanked(struct fb_info *info, int blank) {}
+static inline int fbcon_modechange_possible(struct fb_info *info,
+ struct fb_var_screeninfo *var) { return 0; }
+static inline void fbcon_update_vcs(struct fb_info *info, bool all) {}
+static inline void fbcon_remap_all(struct fb_info *info) {}
+static inline int fbcon_set_con2fb_map_ioctl(void __user *argp) { return 0; }
+static inline int fbcon_get_con2fb_map_ioctl(void __user *argp) { return 0; }
+#endif
+
#endif /* _VIDEO_FBCON_H */
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index ecadbc58abff..e5221653ec2b 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -14,13 +14,13 @@
#include <linux/console.h>
#include <linux/export.h>
#include <linux/fb.h>
-#include <linux/fbcon.h>
#include <linux/lcd.h>
#include <linux/leds.h>
#include <video/nomodeset.h>
#include "fb_internal.h"
+#include "fbcon.h"
/*
* Frame buffer device initialization and setup routines
diff --git a/include/linux/fbcon.h b/include/linux/fbcon.h
deleted file mode 100644
index f206370060e1..000000000000
--- a/include/linux/fbcon.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef _LINUX_FBCON_H
-#define _LINUX_FBCON_H
-
-#include <linux/compiler_types.h>
-
-struct fb_blit_caps;
-struct fb_info;
-struct fb_var_screeninfo;
-struct fb_videomode;
-
-#ifdef CONFIG_FRAMEBUFFER_CONSOLE
-void __init fb_console_init(void);
-void __exit fb_console_exit(void);
-int fbcon_fb_registered(struct fb_info *info);
-void fbcon_fb_unregistered(struct fb_info *info);
-void fbcon_fb_unbind(struct fb_info *info);
-void fbcon_suspended(struct fb_info *info);
-void fbcon_resumed(struct fb_info *info);
-int fbcon_mode_deleted(struct fb_info *info,
- struct fb_videomode *mode);
-void fbcon_delete_modelist(struct list_head *head);
-void fbcon_new_modelist(struct fb_info *info);
-void fbcon_get_requirement(struct fb_info *info,
- struct fb_blit_caps *caps);
-void fbcon_fb_blanked(struct fb_info *info, int blank);
-int fbcon_modechange_possible(struct fb_info *info,
- struct fb_var_screeninfo *var);
-void fbcon_update_vcs(struct fb_info *info, bool all);
-void fbcon_remap_all(struct fb_info *info);
-int fbcon_set_con2fb_map_ioctl(void __user *argp);
-int fbcon_get_con2fb_map_ioctl(void __user *argp);
-#else
-static inline void fb_console_init(void) {}
-static inline void fb_console_exit(void) {}
-static inline int fbcon_fb_registered(struct fb_info *info) { return 0; }
-static inline void fbcon_fb_unregistered(struct fb_info *info) {}
-static inline void fbcon_fb_unbind(struct fb_info *info) {}
-static inline void fbcon_suspended(struct fb_info *info) {}
-static inline void fbcon_resumed(struct fb_info *info) {}
-static inline int fbcon_mode_deleted(struct fb_info *info,
- struct fb_videomode *mode) { return 0; }
-static inline void fbcon_delete_modelist(struct list_head *head) {}
-static inline void fbcon_new_modelist(struct fb_info *info) {}
-static inline void fbcon_get_requirement(struct fb_info *info,
- struct fb_blit_caps *caps) {}
-static inline void fbcon_fb_blanked(struct fb_info *info, int blank) {}
-static inline int fbcon_modechange_possible(struct fb_info *info,
- struct fb_var_screeninfo *var) { return 0; }
-static inline void fbcon_update_vcs(struct fb_info *info, bool all) {}
-static inline void fbcon_remap_all(struct fb_info *info) {}
-static inline int fbcon_set_con2fb_map_ioctl(void __user *argp) { return 0; }
-static inline int fbcon_get_con2fb_map_ioctl(void __user *argp) { return 0; }
-#endif
-
-#endif /* _LINUX_FBCON_H */
--
2.54.0
^ permalink raw reply related
* [PATCH v2 3/4] fbdev: Wrap fbcon updates from vga-switcheroo in helper
From: Thomas Zimmermann @ 2026-05-22 12:28 UTC (permalink / raw)
To: deller, simona, airlied, lukas, maddy, mpe, npiggin, chleroy
Cc: dri-devel, linux-fbdev, linuxppc-dev, Thomas Zimmermann
In-Reply-To: <20260522123019.211059-1-tzimmermann@suse.de>
Handle console remapping in fbcon in fb_switch_output(). Vga-switcheroo
invokes this functionality before switching physical outputs to a new
graphics device. Open-coding fbcon state in vga-switcheroo exposed fbdev
implementation details.
Vga-switcheroo is used for switching physical outputs among graphics
hardware. This functionality is only supported by DRM drivers. A later
update will further move fb_switch_output() into DRM's fbdev emulation;
thus fully decoupling vga-switcheroo from fbdev.
v2:
- use '#if defined' (Helge)
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/vga/vga_switcheroo.c | 6 +++---
drivers/video/fbdev/core/fbmem.c | 10 ++++++++++
include/linux/fb.h | 1 +
3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index 8fe1ae3c71bb..22cf52b78b75 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -31,11 +31,9 @@
#define pr_fmt(fmt) "vga_switcheroo: " fmt
#include <linux/apple-gmux.h>
-#include <linux/console.h>
#include <linux/debugfs.h>
#include <linux/fb.h>
#include <linux/fs.h>
-#include <linux/fbcon.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/pm_domain.h>
@@ -735,8 +733,10 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
if (!active->driver_power_control)
set_audio_state(active->id, VGA_SWITCHEROO_OFF);
+#if defined(CONFIG_FB)
if (new_client->fb_info)
- fbcon_remap_all(new_client->fb_info);
+ fb_switch_outputs(new_client->fb_info);
+#endif
mutex_lock(&vgasr_priv.mux_hw_lock);
ret = vgasr_priv.handler->switchto(new_client->id);
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 1a6758653b64..ecadbc58abff 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -684,6 +684,16 @@ void fb_set_suspend(struct fb_info *info, int state)
}
EXPORT_SYMBOL(fb_set_suspend);
+/**
+ * fb_switch_outputs - framebuffer got the outputs from vga-switcheroo
+ * @info: framebuffer
+ */
+void fb_switch_outputs(struct fb_info *info)
+{
+ fbcon_remap_all(info);
+}
+EXPORT_SYMBOL(fb_switch_outputs);
+
static int __init fbmem_init(void)
{
int ret;
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 88680a7cabd5..e9a26e82322a 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -608,6 +608,7 @@ void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, const u8 *src, u32 idx, u32 h
u32 shift_high, u32 shift_low, u32 mod);
void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, const u8 *src, u32 s_pitch, u32 height);
extern void fb_set_suspend(struct fb_info *info, int state);
+extern void fb_switch_outputs(struct fb_info *info);
extern int fb_get_color_depth(struct fb_var_screeninfo *var,
struct fb_fix_screeninfo *fix);
extern int fb_get_options(const char *name, char **option);
--
2.54.0
^ permalink raw reply related
* [PATCH v2 2/4] fbdev: Wrap user-invoked calls to fb_blank() in helper
From: Thomas Zimmermann @ 2026-05-22 12:28 UTC (permalink / raw)
To: deller, simona, airlied, lukas, maddy, mpe, npiggin, chleroy
Cc: dri-devel, linux-fbdev, linuxppc-dev, Thomas Zimmermann
In-Reply-To: <20260522123019.211059-1-tzimmermann@suse.de>
Handle fbcon during blanking in fb_blank_from_user(). First blank the
hardware, then blank fbcon. Same for unblanking. Update all callers and
resolve the duplicated logic.
With the new helper, fbdev's sysfb code no longer maintains fbcon state
by itself.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/video/fbdev/core/fb_chrdev.c | 4 +---
drivers/video/fbdev/core/fb_internal.h | 1 +
drivers/video/fbdev/core/fbmem.c | 10 ++++++++++
drivers/video/fbdev/core/fbsysfs.c | 5 +----
4 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/drivers/video/fbdev/core/fb_chrdev.c b/drivers/video/fbdev/core/fb_chrdev.c
index 54f926fb411b..035e67d2c28f 100644
--- a/drivers/video/fbdev/core/fb_chrdev.c
+++ b/drivers/video/fbdev/core/fb_chrdev.c
@@ -138,9 +138,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
return -EINVAL;
console_lock();
lock_fb_info(info);
- ret = fb_blank(info, arg);
- /* might again call into fb_blank */
- fbcon_fb_blanked(info, arg);
+ ret = fb_blank_from_user(info, arg);
unlock_fb_info(info);
console_unlock();
break;
diff --git a/drivers/video/fbdev/core/fb_internal.h b/drivers/video/fbdev/core/fb_internal.h
index 613832d335fe..62e75bf15b9b 100644
--- a/drivers/video/fbdev/core/fb_internal.h
+++ b/drivers/video/fbdev/core/fb_internal.h
@@ -44,6 +44,7 @@ extern struct fb_info *registered_fb[FB_MAX];
extern int num_registered_fb;
struct fb_info *get_fb_info(unsigned int idx);
void put_fb_info(struct fb_info *fb_info);
+int fb_blank_from_user(struct fb_info *info, int blank);
/* fb_procfs.c */
#if defined(CONFIG_FB_DEVICE)
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index d37a1039e221..1a6758653b64 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -422,6 +422,16 @@ int fb_blank(struct fb_info *info, int blank)
}
EXPORT_SYMBOL(fb_blank);
+int fb_blank_from_user(struct fb_info *info, int blank)
+{
+ int ret = fb_blank(info, blank);
+
+ /* might again call into fb_blank */
+ fbcon_fb_blanked(info, blank);
+
+ return ret;
+}
+
static int fb_check_foreignness(struct fb_info *fi)
{
const bool foreign_endian = fi->flags & FBINFO_FOREIGN_ENDIAN;
diff --git a/drivers/video/fbdev/core/fbsysfs.c b/drivers/video/fbdev/core/fbsysfs.c
index 5ece236e6252..d9743ef35355 100644
--- a/drivers/video/fbdev/core/fbsysfs.c
+++ b/drivers/video/fbdev/core/fbsysfs.c
@@ -7,7 +7,6 @@
#include <linux/console.h>
#include <linux/fb.h>
-#include <linux/fbcon.h>
#include <linux/major.h>
#include "fb_internal.h"
@@ -229,9 +228,7 @@ static ssize_t store_blank(struct device *device,
arg = simple_strtoul(buf, &last, 0);
console_lock();
- err = fb_blank(fb_info, arg);
- /* might again call into fb_blank */
- fbcon_fb_blanked(fb_info, arg);
+ err = fb_blank_from_user(fb_info, arg);
console_unlock();
if (err < 0)
return err;
--
2.54.0
^ permalink raw reply related
* [PATCH v2 1/4] fbdev: Wrap user-invoked calls to fb_set_var() in helper
From: Thomas Zimmermann @ 2026-05-22 12:28 UTC (permalink / raw)
To: deller, simona, airlied, lukas, maddy, mpe, npiggin, chleroy
Cc: dri-devel, linux-fbdev, linuxppc-dev, Thomas Zimmermann
In-Reply-To: <20260522123019.211059-1-tzimmermann@suse.de>
Handle fbcon during display updates in fb_set_var_from_user(). Check
with fbcon if the mode change is possible, update hardware state and
finally update fbcon. Update all callers.
Only the FBIOPUT_VSCREENINFO ioctl currently does all steps. Other
mode-changes callers in sysfs and driver code are missing fbcon-related
steps.
With the new helper, ps3fb and sh_mobile_lcdcfb no longer maintain
fbcon state themselves.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/video/fbdev/core/fb_chrdev.c | 6 +-----
drivers/video/fbdev/core/fbcon.c | 2 --
drivers/video/fbdev/core/fbmem.c | 13 +++++++++++++
drivers/video/fbdev/core/fbsysfs.c | 4 +---
drivers/video/fbdev/ps3fb.c | 5 +----
drivers/video/fbdev/sh_mobile_lcdcfb.c | 5 +----
include/linux/fb.h | 2 ++
7 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/drivers/video/fbdev/core/fb_chrdev.c b/drivers/video/fbdev/core/fb_chrdev.c
index 4ebd16b7e3b8..54f926fb411b 100644
--- a/drivers/video/fbdev/core/fb_chrdev.c
+++ b/drivers/video/fbdev/core/fb_chrdev.c
@@ -85,11 +85,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
var.activate &= ~FB_ACTIVATE_KD_TEXT;
console_lock();
lock_fb_info(info);
- ret = fbcon_modechange_possible(info, &var);
- if (!ret)
- ret = fb_set_var(info, &var);
- if (!ret)
- fbcon_update_vcs(info, var.activate & FB_ACTIVATE_ALL);
+ ret = fb_set_var_from_user(info, &var);
unlock_fb_info(info);
console_unlock();
if (!ret && copy_to_user(argp, &var, sizeof(var)))
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index b0e3e765360d..50b84cd32938 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -2699,7 +2699,6 @@ void fbcon_update_vcs(struct fb_info *info, bool all)
else
fbcon_modechanged(info);
}
-EXPORT_SYMBOL(fbcon_update_vcs);
/* let fbcon check if it supports a new screen resolution */
int fbcon_modechange_possible(struct fb_info *info, struct fb_var_screeninfo *var)
@@ -2727,7 +2726,6 @@ int fbcon_modechange_possible(struct fb_info *info, struct fb_var_screeninfo *va
return 0;
}
-EXPORT_SYMBOL_GPL(fbcon_modechange_possible);
int fbcon_mode_deleted(struct fb_info *info,
struct fb_videomode *mode)
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 30f2b59c47bf..d37a1039e221 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -346,6 +346,19 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
}
EXPORT_SYMBOL(fb_set_var);
+int fb_set_var_from_user(struct fb_info *info, struct fb_var_screeninfo *var)
+{
+ int ret = fbcon_modechange_possible(info, var);
+
+ if (!ret)
+ ret = fb_set_var(info, var);
+ if (!ret)
+ fbcon_update_vcs(info, var->activate & FB_ACTIVATE_ALL);
+
+ return ret;
+}
+EXPORT_SYMBOL(fb_set_var_from_user);
+
static void fb_lcd_notify_blank(struct fb_info *info)
{
int power;
diff --git a/drivers/video/fbdev/core/fbsysfs.c b/drivers/video/fbdev/core/fbsysfs.c
index baa2bae0fb5b..5ece236e6252 100644
--- a/drivers/video/fbdev/core/fbsysfs.c
+++ b/drivers/video/fbdev/core/fbsysfs.c
@@ -19,9 +19,7 @@ static int activate(struct fb_info *fb_info, struct fb_var_screeninfo *var)
var->activate |= FB_ACTIVATE_FORCE;
console_lock();
lock_fb_info(fb_info);
- err = fb_set_var(fb_info, var);
- if (!err)
- fbcon_update_vcs(fb_info, var->activate & FB_ACTIVATE_ALL);
+ err = fb_set_var_from_user(fb_info, var);
unlock_fb_info(fb_info);
console_unlock();
if (err)
diff --git a/drivers/video/fbdev/ps3fb.c b/drivers/video/fbdev/ps3fb.c
index dbcda307f6a6..1376d19b19ae 100644
--- a/drivers/video/fbdev/ps3fb.c
+++ b/drivers/video/fbdev/ps3fb.c
@@ -29,7 +29,6 @@
#include <linux/freezer.h>
#include <linux/uaccess.h>
#include <linux/fb.h>
-#include <linux/fbcon.h>
#include <linux/init.h>
#include <asm/cell-regs.h>
@@ -830,9 +829,7 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
/* Force, in case only special bits changed */
var.activate |= FB_ACTIVATE_FORCE;
par->new_mode_id = val;
- retval = fb_set_var(info, &var);
- if (!retval)
- fbcon_update_vcs(info, var.activate & FB_ACTIVATE_ALL);
+ retval = fb_set_var_from_user(info, &var);
console_unlock();
}
break;
diff --git a/drivers/video/fbdev/sh_mobile_lcdcfb.c b/drivers/video/fbdev/sh_mobile_lcdcfb.c
index 72969fe8e513..e8324b01700f 100644
--- a/drivers/video/fbdev/sh_mobile_lcdcfb.c
+++ b/drivers/video/fbdev/sh_mobile_lcdcfb.c
@@ -15,7 +15,6 @@
#include <linux/ctype.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
-#include <linux/fbcon.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/ioctl.h>
@@ -1768,11 +1767,9 @@ static void sh_mobile_fb_reconfig(struct fb_info *info)
var.height = ch->display.height;
var.activate = FB_ACTIVATE_NOW;
- if (fb_set_var(info, &var) < 0)
+ if (fb_set_var_from_user(info, &var) < 0)
/* Couldn't reconfigure, hopefully, can continue as before */
return;
-
- fbcon_update_vcs(info, true);
}
/*
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 5178a33c752c..88680a7cabd5 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -533,6 +533,8 @@ extern int fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var);
extern int fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var);
extern int fb_blank(struct fb_info *info, int blank);
+int fb_set_var_from_user(struct fb_info *info, struct fb_var_screeninfo *var);
+
/*
* Helpers for framebuffers in I/O memory
*/
--
2.54.0
^ permalink raw reply related
* [PATCH v2 0/4] fbdev: Internalize fbcon
From: Thomas Zimmermann @ 2026-05-22 12:28 UTC (permalink / raw)
To: deller, simona, airlied, lukas, maddy, mpe, npiggin, chleroy
Cc: dri-devel, linux-fbdev, linuxppc-dev, Thomas Zimmermann
Turn fbcon into an internal client of fbdev. Manage all interactions
with graphics drivers within fbdev. Add helpers for these tasks and
convert drivers.
Fbdev's PS3 and SH-Mobile drivers update fbcon as part of user-invoked
mode changes. Call the new helpers, which also fix inconsistencies
among the various code paths.
Vga-switcheroo remaps the fbcon terminals when switching physical
outputs. For now, hide this in another helper. The call will later
move into DRM's fbdev emulation.
When all refactoring in place, fbdev manages fbcon interactions by
itself. Remove the public interfaces.
v2:
- use '#if defined' (Helge)
Thomas Zimmermann (4):
fbdev: Wrap user-invoked calls to fb_set_var() in helper
fbdev: Wrap user-invoked calls to fb_blank() in helper
fbdev: Wrap fbcon updates from vga-switcheroo in helper
fbdev: Do not export fbcon from fbdev
MAINTAINERS | 1 -
drivers/gpu/vga/vga_switcheroo.c | 6 +--
drivers/video/fbdev/core/fb_chrdev.c | 12 ++----
drivers/video/fbdev/core/fb_internal.h | 1 +
drivers/video/fbdev/core/fbcon.c | 3 --
drivers/video/fbdev/core/fbcon.h | 50 +++++++++++++++++++++++
drivers/video/fbdev/core/fbmem.c | 35 +++++++++++++++-
drivers/video/fbdev/core/fbsysfs.c | 9 +----
drivers/video/fbdev/ps3fb.c | 5 +--
drivers/video/fbdev/sh_mobile_lcdcfb.c | 5 +--
include/linux/fb.h | 3 ++
include/linux/fbcon.h | 55 --------------------------
12 files changed, 98 insertions(+), 87 deletions(-)
delete mode 100644 include/linux/fbcon.h
base-commit: f103db97c610a41177720b08aa4a2a05f9b42d49
prerequisite-patch-id: c67e5d886a47b7d0266d81100837557fda34cb24
prerequisite-patch-id: a5a973e527c88a5b47053d7a72aefe0b550197cb
prerequisite-patch-id: b9adc9622920a3e70168e672c2c92795b3e3a106
prerequisite-patch-id: 5030de433a01c2e99056cadb676a8e2ba35f055a
--
2.54.0
^ permalink raw reply
* Re: [PATCH 1/4] fbdev: Wrap user-invoked calls to fb_set_var() in helper
From: Thomas Zimmermann @ 2026-05-22 12:14 UTC (permalink / raw)
To: Helge Deller, simona, airlied, lukas, maddy, mpe, npiggin,
chleroy
Cc: dri-devel, linux-fbdev, linuxppc-dev
In-Reply-To: <0ce59eaf-1124-48c5-b812-c8e6b58e01d0@gmx.de>
Hi
Am 20.05.26 um 20:51 schrieb Helge Deller:
> On 5/20/26 18:00, Thomas Zimmermann wrote:
>> Handle fbcon during display updates in fb_set_var_from_user(). Check
>> with fbcon if the mode change is possible, update hardware state and
>> finally update fbcon. Update all callers.
>>
>> Only the FBIOPUT_VSCREENINFO ioctl currently does all steps. Other
>> mode-changes callers in sysfs and driver code are missing fbcon-related
>> steps.
>>
>> With the new helper, ps3fb and sh_mobile_lcdcfb no longer maintain
>> fbcon state themselves.
>>
>> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
>> ---
>> drivers/video/fbdev/core/fb_chrdev.c | 6 +-----
>> drivers/video/fbdev/core/fbcon.c | 2 --
>> drivers/video/fbdev/core/fbmem.c | 13 +++++++++++++
>> drivers/video/fbdev/core/fbsysfs.c | 4 +---
>> drivers/video/fbdev/ps3fb.c | 5 +----
>> drivers/video/fbdev/sh_mobile_lcdcfb.c | 5 +----
>> include/linux/fb.h | 2 ++
>> 7 files changed, 19 insertions(+), 18 deletions(-)
>>
>> ...
>> diff --git a/include/linux/fb.h b/include/linux/fb.h
>> index 5178a33c752c..88680a7cabd5 100644
>> --- a/include/linux/fb.h
>> +++ b/include/linux/fb.h
>> @@ -533,6 +533,8 @@ extern int fb_set_var(struct fb_info *info,
>> struct fb_var_screeninfo *var);
>> extern int fb_pan_display(struct fb_info *info, struct
>> fb_var_screeninfo *var);
>> extern int fb_blank(struct fb_info *info, int blank);
>> +int fb_set_var_from_user(struct fb_info *info, struct
>> fb_var_screeninfo *var);
>> +
>
> "extern" int fb_set_var_from_user(...) ?
As Christophe ointed out, not having extern is correct. I think, if
anything, we should remove the existing externs from the headers.
>
> Other than that the series is a nice cleanup!
Thanks. I'll send you an updated series with the #ifdef fix for patch
3. Sending just fixup patches can confuse the tracker bots and services
(say patchwork), so I'd avoid that.
Best regards
Thomas
>
> Thanks!
> Helge
--
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstr. 146, 90461 Nürnberg, Germany, www.suse.com
GF: Jochen Jaser, Andrew McDonald, Werner Knoblich, (HRB 36809, AG Nürnberg)
^ permalink raw reply
* Re: [PATCH] Staging: sm750fb: Change camelCase to snake_case
From: Dan Carpenter @ 2026-05-22 5:49 UTC (permalink / raw)
To: Michail Tatas
Cc: sudipm.mukherjee, teddy.wang, gregkh, linux-fbdev, linux-staging,
linux-kernel
In-Reply-To: <ag-XlRifxjqXF-Zx@michalis-linux>
On Fri, May 22, 2026 at 02:39:01AM +0300, Michail Tatas wrote:
> Change variable names from camelCase to snake_case
> as per the Linux Kernel standards.
>
> These changes remove 9 CHECK messages from checkpatch.pl
> regarding sm750.c, sm750.h and sm750_hw.c
>
> Tested changes by building the module sm750fb/
Don't put this kind of meta comment in the commit message. Put it
under the --- cur off line.
Please wait a day between resends.
I don't think you're working against the correct staging-next
tree.
regards,
dan carpenter
^ permalink raw reply
* Re: [PATCH] Staging: sm750fb: Change camelCase to snake_case
From: Greg KH @ 2026-05-22 4:43 UTC (permalink / raw)
To: Michail Tatas
Cc: sudipm.mukherjee, teddy.wang, linux-fbdev, linux-staging,
linux-kernel
In-Reply-To: <ag-XlRifxjqXF-Zx@michalis-linux>
On Fri, May 22, 2026 at 02:39:01AM +0300, Michail Tatas wrote:
> Change variable names from camelCase to snake_case
> as per the Linux Kernel standards.
Please do one-change-per-variable, as some of these are fine, but others
are obviously not.
thanks,
greg k-h
^ permalink raw reply
* [PATCH] Staging: sm750fb: Change camelCase to snake_case
From: Michail Tatas @ 2026-05-21 23:39 UTC (permalink / raw)
To: sudipm.mukherjee, teddy.wang, gregkh, linux-fbdev, linux-staging,
linux-kernel
Change variable names from camelCase to snake_case
as per the Linux Kernel standards.
These changes remove 9 CHECK messages from checkpatch.pl
regarding sm750.c, sm750.h and sm750_hw.c
Tested changes by building the module sm750fb/
Signed-off-by: Michail Tatas <michail.tatas@gmail.com>
---
drivers/staging/sm750fb/sm750.c | 32 +++++++++++++++---------------
drivers/staging/sm750fb/sm750.h | 14 ++++++-------
drivers/staging/sm750fb/sm750_hw.c | 20 +++++++++----------
3 files changed, 33 insertions(+), 33 deletions(-)
diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c
index 9f3e3d37e82a..3124380beb81 100644
--- a/drivers/staging/sm750fb/sm750.c
+++ b/drivers/staging/sm750fb/sm750.c
@@ -622,26 +622,26 @@ static int sm750fb_set_drv(struct lynxfb_par *par)
output->paths = sm750_pnc;
crtc->channel = sm750_primary;
crtc->o_screen = 0;
- crtc->v_screen = sm750_dev->pvMem;
+ crtc->v_screen = sm750_dev->pv_mem;
break;
case sm750_simul_sec:
output->paths = sm750_pnc;
crtc->channel = sm750_secondary;
crtc->o_screen = 0;
- crtc->v_screen = sm750_dev->pvMem;
+ crtc->v_screen = sm750_dev->pv_mem;
break;
case sm750_dual_normal:
if (par->index == 0) {
output->paths = sm750_panel;
crtc->channel = sm750_primary;
crtc->o_screen = 0;
- crtc->v_screen = sm750_dev->pvMem;
+ crtc->v_screen = sm750_dev->pv_mem;
} else {
output->paths = sm750_crt;
crtc->channel = sm750_secondary;
/* not consider of padding stuffs for o_screen,need fix */
crtc->o_screen = sm750_dev->vidmem_size >> 1;
- crtc->v_screen = sm750_dev->pvMem + crtc->o_screen;
+ crtc->v_screen = sm750_dev->pv_mem + crtc->o_screen;
}
break;
case sm750_dual_swap:
@@ -649,7 +649,7 @@ static int sm750fb_set_drv(struct lynxfb_par *par)
output->paths = sm750_panel;
crtc->channel = sm750_secondary;
crtc->o_screen = 0;
- crtc->v_screen = sm750_dev->pvMem;
+ crtc->v_screen = sm750_dev->pv_mem;
} else {
output->paths = sm750_crt;
crtc->channel = sm750_primary;
@@ -657,7 +657,7 @@ static int sm750fb_set_drv(struct lynxfb_par *par)
* need fix
*/
crtc->o_screen = sm750_dev->vidmem_size >> 1;
- crtc->v_screen = sm750_dev->pvMem + crtc->o_screen;
+ crtc->v_screen = sm750_dev->pv_mem + crtc->o_screen;
}
break;
default:
@@ -755,13 +755,13 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index)
* must be set after crtc member initialized
*/
crtc->cursor.offset = crtc->o_screen + crtc->vidmem_size - 1024;
- crtc->cursor.mmio = sm750_dev->pvReg +
+ crtc->cursor.mmio = sm750_dev->pv_reg +
0x800f0 + (int)crtc->channel * 0x140;
crtc->cursor.max_h = 64;
crtc->cursor.max_w = 64;
crtc->cursor.size = crtc->cursor.max_h * crtc->cursor.max_w * 2 / 8;
- crtc->cursor.vstart = sm750_dev->pvMem + crtc->cursor.offset;
+ crtc->cursor.vstart = sm750_dev->pv_mem + crtc->cursor.offset;
memset_io(crtc->cursor.vstart, 0, crtc->cursor.size);
if (!g_hwcursor)
@@ -859,9 +859,9 @@ static void sm750fb_setup(struct sm750_dev *sm750_dev, char *src)
sm750_dev->init_parm.chip_clk = 0;
sm750_dev->init_parm.mem_clk = 0;
sm750_dev->init_parm.master_clk = 0;
- sm750_dev->init_parm.powerMode = 0;
- sm750_dev->init_parm.setAllEngOff = 0;
- sm750_dev->init_parm.resetMemory = 1;
+ sm750_dev->init_parm.power_mode = 0;
+ sm750_dev->init_parm.set_all_eng_off = 0;
+ sm750_dev->init_parm.reset_memory = 1;
/* defaultly turn g_hwcursor on for both view */
g_hwcursor = 3;
@@ -880,9 +880,9 @@ static void sm750fb_setup(struct sm750_dev *sm750_dev, char *src)
} else if (!strncmp(opt, "nocrt", strlen("nocrt"))) {
sm750_dev->nocrt = 1;
} else if (!strncmp(opt, "36bit", strlen("36bit"))) {
- sm750_dev->pnltype = sm750_doubleTFT;
+ sm750_dev->pnltype = sm750_double_tft;
} else if (!strncmp(opt, "18bit", strlen("18bit"))) {
- sm750_dev->pnltype = sm750_dualTFT;
+ sm750_dev->pnltype = sm750_dual_tft;
} else if (!strncmp(opt, "24bit", strlen("24bit"))) {
sm750_dev->pnltype = sm750_24TFT;
} else if (!strncmp(opt, "nohwc0", strlen("nohwc0"))) {
@@ -1028,7 +1028,7 @@ static int lynxfb_pci_probe(struct pci_dev *pdev,
sm750_dev->mtrr.vram = arch_phys_wc_add(sm750_dev->vidmem_start,
sm750_dev->vidmem_size);
- memset_io(sm750_dev->pvMem, 0, sm750_dev->vidmem_size);
+ memset_io(sm750_dev->pv_mem, 0, sm750_dev->vidmem_size);
pci_set_drvdata(pdev, sm750_dev);
@@ -1059,8 +1059,8 @@ static void lynxfb_pci_remove(struct pci_dev *pdev)
sm750fb_framebuffer_release(sm750_dev);
arch_phys_wc_del(sm750_dev->mtrr.vram);
- iounmap(sm750_dev->pvReg);
- iounmap(sm750_dev->pvMem);
+ iounmap(sm750_dev->pv_reg);
+ iounmap(sm750_dev->pv_mem);
pci_release_region(pdev, 1);
kfree(g_settings);
}
diff --git a/drivers/staging/sm750fb/sm750.h b/drivers/staging/sm750fb/sm750.h
index 67b9bfa23f41..19dbb91201e3 100644
--- a/drivers/staging/sm750fb/sm750.h
+++ b/drivers/staging/sm750fb/sm750.h
@@ -14,8 +14,8 @@
enum sm750_pnltype {
sm750_24TFT = 0, /* 24bit tft */
- sm750_dualTFT = 2, /* dual 18 bit tft */
- sm750_doubleTFT = 1, /* 36 bit double pixel tft */
+ sm750_dual_tft = 2, /* dual 18 bit tft */
+ sm750_double_tft = 1, /* 36 bit double pixel tft */
};
/* vga channel is not concerned */
@@ -39,13 +39,13 @@ enum sm750_path {
};
struct init_status {
- ushort powerMode;
+ ushort power_mode;
/* below three clocks are in unit of MHZ*/
ushort chip_clk;
ushort mem_clk;
ushort master_clk;
- ushort setAllEngOff;
- ushort resetMemory;
+ ushort set_all_eng_off;
+ ushort reset_memory;
};
struct lynx_accel {
@@ -97,8 +97,8 @@ struct sm750_dev {
unsigned long vidreg_start;
__u32 vidmem_size;
__u32 vidreg_size;
- void __iomem *pvReg;
- unsigned char __iomem *pvMem;
+ void __iomem *pv_reg;
+ unsigned char __iomem *pv_mem;
/* locks*/
spinlock_t slock;
diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c
index a2798d428663..238f3e97fa05 100644
--- a/drivers/staging/sm750fb/sm750_hw.c
+++ b/drivers/staging/sm750fb/sm750_hw.c
@@ -42,18 +42,18 @@ int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev)
}
/* now map mmio and vidmem */
- sm750_dev->pvReg =
+ sm750_dev->pv_reg =
ioremap(sm750_dev->vidreg_start, sm750_dev->vidreg_size);
- if (!sm750_dev->pvReg) {
+ if (!sm750_dev->pv_reg) {
dev_err(&pdev->dev, "mmio failed\n");
ret = -EFAULT;
goto err_release_region;
}
- sm750_dev->accel.dpr_base = sm750_dev->pvReg + DE_BASE_ADDR_TYPE1;
- sm750_dev->accel.dp_port_base = sm750_dev->pvReg + DE_PORT_ADDR_TYPE1;
+ sm750_dev->accel.dpr_base = sm750_dev->pv_reg + DE_BASE_ADDR_TYPE1;
+ sm750_dev->accel.dp_port_base = sm750_dev->pv_reg + DE_PORT_ADDR_TYPE1;
- mmio750 = sm750_dev->pvReg;
+ mmio750 = sm750_dev->pv_reg;
sm750_set_chip_type(sm750_dev->devid, sm750_dev->revid);
sm750_dev->vidmem_start = pci_resource_start(pdev, 0);
@@ -66,9 +66,9 @@ int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev)
sm750_dev->vidmem_size = ddk750_get_vm_size();
/* reserve the vidmem space of smi adaptor */
- sm750_dev->pvMem =
+ sm750_dev->pv_mem =
ioremap_wc(sm750_dev->vidmem_start, sm750_dev->vidmem_size);
- if (!sm750_dev->pvMem) {
+ if (!sm750_dev->pv_mem) {
dev_err(&pdev->dev, "Map video memory failed\n");
ret = -EFAULT;
goto err_unmap_reg;
@@ -77,7 +77,7 @@ int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev)
return 0;
err_unmap_reg:
- iounmap(sm750_dev->pvReg);
+ iounmap(sm750_dev->pv_reg);
err_release_region:
pci_release_region(pdev, 1);
return ret;
@@ -130,10 +130,10 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev)
switch (sm750_dev->pnltype) {
case sm750_24TFT:
break;
- case sm750_doubleTFT:
+ case sm750_double_tft:
val |= PANEL_DISPLAY_CTRL_DOUBLE_PIXEL;
break;
- case sm750_dualTFT:
+ case sm750_dual_tft:
val |= PANEL_DISPLAY_CTRL_DUAL_DISPLAY;
break;
}
--
2.43.0
^ permalink raw reply related
* [PATCH] staging: sm750fb: gate dualview dataflow using g_dualview
From: Ahmet Sezgin Duran @ 2026-05-21 20:44 UTC (permalink / raw)
To: gregkh; +Cc: linux-fbdev, linux-staging, linux-kernel, Ahmet Sezgin Duran
In sm750fb_setup and sm750fb_set_drv functions, the dualview
related code is guarded by `sm750_dev->fb_count > 1` condition.
That value is updated only after each framebuffer is registered,
while both guards are used before any increment.
Current flow:
lynxfb_pci_probe()
sm750fb_setup() // fb_count is 0
for each fb:
sm750fb_framebuffer_alloc()
lynxfb_set_fbinfo()
sm750fb_set_drv() // fb_count is 0 or 1
register_framebuffer()
sm750_dev->fb_count++; // fb_count is incremented
Thus even if `dualview=1` parameter is passed down to the driver,
fb_count is never > 1 at either check, so dualview dataflows are
not selected and crtc->vidmem_size is never halved.
Use `g_dualview` global variable instead of fb_count > 1 to correctly
enable dualview capabilities.
Fixes: a3f92cc94c61 ("staging: sm750fb: replace dual member of sm750_dev with fb_count")
Signed-off-by: Ahmet Sezgin Duran <ahmet@sezginduran.net>
---
Found by code inspection. Not tested on sm750 hardware. This restores
the gate that selects the dual-display dataflow but does not validate
the rest of that path, which has been unreachable since commit a3f92cc94c61.
drivers/staging/sm750fb/sm750.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c
index 89c811e0806c..3a4b9c06f770 100644
--- a/drivers/staging/sm750fb/sm750.c
+++ b/drivers/staging/sm750fb/sm750.c
@@ -591,7 +591,7 @@ static int sm750fb_set_drv(struct lynxfb_par *par)
crtc = &par->crtc;
crtc->vidmem_size = sm750_dev->vidmem_size;
- if (sm750_dev->fb_count > 1)
+ if (g_dualview)
crtc->vidmem_size >>= 1;
/* setup crtc and output member */
@@ -896,7 +896,7 @@ static void sm750fb_setup(struct sm750_dev *sm750_dev, char *src)
NO_PARAM:
if (sm750_dev->revid != SM750LE_REVISION_ID) {
- if (sm750_dev->fb_count > 1) {
+ if (g_dualview) {
if (swap)
sm750_dev->dataflow = sm750_dual_swap;
else
--
2.53.0
^ permalink raw reply related
* [PATCH v4 2/2] backlight: Add SY7758 6-channel High Efficiency LED Driver support
From: Neil Armstrong @ 2026-05-21 8:08 UTC (permalink / raw)
To: Lee Jones, Daniel Thompson, Jingoo Han, Pavel Machek, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Helge Deller
Cc: dri-devel, linux-leds, devicetree, linux-kernel, linux-fbdev,
KancyJoe, Neil Armstrong
In-Reply-To: <20260521-topic-sm8650-ayaneo-pocket-s2-sy7758-v4-0-73c732615e4a@linaro.org>
From: KancyJoe <kancy2333@outlook.com>
Implement support for the Silergy SY7758 6-channel High Efficiency LED
Driver used for backlight brightness control in the Ayaneo Pocket S2
dual-DSI panel.
Signed-off-by: KancyJoe <kancy2333@outlook.com>
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
drivers/video/backlight/Kconfig | 8 ++
drivers/video/backlight/Makefile | 1 +
drivers/video/backlight/sy7758.c | 259 +++++++++++++++++++++++++++++++++++++++
3 files changed, 268 insertions(+)
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index a7a3fbaf7c29..a1f70a2bae99 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -207,6 +207,14 @@ config BACKLIGHT_KTZ8866
Say Y to enable the backlight driver for the Kinetic KTZ8866
found in Xiaomi Mi Pad 5 series.
+config BACKLIGHT_SY7758
+ tristate "Backlight Driver for Silergy SY7758"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ Say Y to enable the backlight driver for the Silergy SY7758
+ backlight controller found in Ayaneo Pocket S2.
+
config BACKLIGHT_LM3533
tristate "Backlight Driver for LM3533"
depends on MFD_LM3533
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 794820a98ed4..39ef588b1cf2 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o
obj-$(CONFIG_BACKLIGHT_QCOM_WLED) += qcom-wled.o
obj-$(CONFIG_BACKLIGHT_RT4831) += rt4831-backlight.o
obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o
+obj-$(CONFIG_BACKLIGHT_SY7758) += sy7758.o
obj-$(CONFIG_BACKLIGHT_SKY81452) += sky81452-backlight.o
obj-$(CONFIG_BACKLIGHT_TPS65217) += tps65217_bl.o
obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o
diff --git a/drivers/video/backlight/sy7758.c b/drivers/video/backlight/sy7758.c
new file mode 100644
index 000000000000..198d55939438
--- /dev/null
+++ b/drivers/video/backlight/sy7758.c
@@ -0,0 +1,259 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Silergy SY7758 6-channel High Efficiency LED Driver
+ *
+ * Copyright (C) 2025 Kancy Joe <kancy2333@outlook.com>
+ * Copyright (C) 2026 Linaro Limited
+ * Author: Neil Armstrong <neil.armstrong@linaro.org>
+ */
+#include <linux/backlight.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/of.h>
+#include <linux/err.h>
+#include <linux/bits.h>
+#include <linux/delay.h>
+#include <linux/regmap.h>
+#include <linux/bitfield.h>
+#include <linux/gpio/consumer.h>
+#include <linux/regulator/consumer.h>
+
+#define DEFAULT_BRIGHTNESS 1024
+#define MAX_BRIGHTNESS 4080
+#define REG_MAX 0xAE
+
+/* Registers */
+#define REG_DEV_CTL 0x01
+#define REG_DEV_ID 0x03
+#define REG_BRT_12BIT_L 0x10
+#define REG_BRT_12BIT_H 0x11
+
+/* OTP memory */
+#define REG_OTP_CFG0 0xA0
+#define REG_OTP_CFG1 0xA1
+#define REG_OTP_CFG2 0xA2
+#define REG_OTP_CFG5 0xA5
+#define REG_OTP_CFG9 0xA9
+
+/* Fields */
+#define BIT_DEV_CTL_FAST BIT(7)
+#define MSK_DEV_CTL_BRT_MODE GENMASK(2, 1)
+#define BIT_DEV_CTL_BL_CTLB BIT(0)
+
+#define MSK_BRT_12BIT_L GENMASK(7, 0)
+#define MSK_BRT_12BIT_H GENMASK(3, 0)
+
+#define MSK_CFG0_CURRENT_LOW GENMASK(7, 0)
+
+#define BIT_CFG1_PDET_STDBY BIT(7)
+#define MSK_CFG1_CURRENT_MAX GENMASK(6, 4)
+#define MSK_CFG1_CURRENT_HIGH GENMASK(3, 0)
+
+#define BIT_CFG2_UVLO_EN BIT(5)
+#define BIT_CFG2_UVLO_TH BIT(4)
+#define BIT_CFG2_BL_ON BIT(3)
+#define BIT_CFG2_ISET_EN BIT(2)
+#define BIT_CFG2_BST_ESET_EN BIT(1)
+
+#define BIT_CFG5_PWM_DIRECT BIT(7)
+#define MSK_CFG5_PS_MODE GENMASK(6, 4)
+#define MSK_CFG5_PWM_FREQ GENMASK(3, 0)
+
+#define MSK_CFG9_VBST_MAX GENMASK(7, 5)
+#define BIT_CFG9_JUMP_EN BIT(4)
+#define MSK_CFG9_JUMP_TH GENMASK(3, 2)
+#define MSK_CFG9_JUMP_VOLTAGE GENMASK(1, 0)
+
+struct sy7758 {
+ struct i2c_client *client;
+ struct regmap *regmap;
+ struct gpio_desc *gpio;
+ struct backlight_device *bl;
+};
+
+static const struct regmap_config sy7758_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = REG_MAX,
+};
+
+static int sy7758_backlight_update_status(struct backlight_device *backlight_dev)
+{
+ struct sy7758 *sydev = bl_get_data(backlight_dev);
+ unsigned int brightness = backlight_get_brightness(backlight_dev);
+ int ret;
+
+ ret = regmap_write(sydev->regmap, REG_BRT_12BIT_L,
+ FIELD_PREP(MSK_BRT_12BIT_L,
+ brightness & 0xff));
+ if (ret)
+ return ret;
+
+ ret = regmap_write(sydev->regmap, REG_BRT_12BIT_H,
+ FIELD_PREP(MSK_BRT_12BIT_H,
+ (brightness >> 8) & 0xf));
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static const struct backlight_ops sy7758_backlight_ops = {
+ .options = BL_CORE_SUSPENDRESUME,
+ .update_status = sy7758_backlight_update_status,
+};
+
+static int sy7758_init(struct sy7758 *sydev)
+{
+ int ret = 0;
+
+ ret = regmap_write(sydev->regmap, REG_DEV_CTL,
+ BIT_DEV_CTL_FAST | BIT_DEV_CTL_BL_CTLB |
+ FIELD_PREP(MSK_DEV_CTL_BRT_MODE, 2));
+ if (ret)
+ return ret;
+
+ ret = regmap_write(sydev->regmap, REG_BRT_12BIT_L,
+ FIELD_PREP(MSK_BRT_12BIT_L,
+ DEFAULT_BRIGHTNESS & 0xff));
+ if (ret)
+ return ret;
+
+ ret = regmap_write(sydev->regmap, REG_BRT_12BIT_H,
+ FIELD_PREP(MSK_BRT_12BIT_H,
+ (DEFAULT_BRIGHTNESS >> 8)));
+ if (ret)
+ return ret;
+
+ ret = regmap_write(sydev->regmap, REG_OTP_CFG5,
+ FIELD_PREP(MSK_CFG5_PS_MODE, 6) |
+ FIELD_PREP(MSK_CFG5_PWM_FREQ, 4));
+ if (ret)
+ return ret;
+
+ ret = regmap_write(sydev->regmap, REG_OTP_CFG0,
+ FIELD_PREP(MSK_CFG0_CURRENT_LOW, 85));
+ if (ret)
+ return ret;
+
+ ret = regmap_write(sydev->regmap, REG_OTP_CFG1,
+ BIT_CFG1_PDET_STDBY |
+ FIELD_PREP(MSK_CFG1_CURRENT_MAX, 1) |
+ FIELD_PREP(MSK_CFG1_CURRENT_HIGH, 10));
+ if (ret)
+ return ret;
+
+ ret = regmap_write(sydev->regmap, REG_OTP_CFG9,
+ FIELD_PREP(MSK_CFG9_VBST_MAX, 4));
+ if (ret)
+ return ret;
+
+ ret = regmap_write(sydev->regmap, REG_OTP_CFG2,
+ BIT_CFG2_BL_ON | BIT_CFG2_UVLO_EN);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int sy7758_probe(struct i2c_client *client)
+{
+ struct backlight_properties props = { };
+ struct device *dev = &client->dev;
+ struct sy7758 *sydev;
+ unsigned int dev_id;
+ int ret;
+
+ sydev = devm_kzalloc(dev, sizeof(*sydev), GFP_KERNEL);
+ if (!sydev)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, sydev);
+
+ /* Initialize regmap */
+ sydev->client = client;
+ sydev->regmap = devm_regmap_init_i2c(client, &sy7758_regmap_config);
+ if (IS_ERR(sydev->regmap))
+ return dev_err_probe(dev, PTR_ERR(sydev->regmap),
+ "failed to init regmap\n");
+
+ /* Get and enable regulators */
+ ret = devm_regulator_get_enable(dev, "vddio");
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to get regulator\n");
+
+ fsleep(100);
+
+ /* Get enable GPIO and set to high */
+ sydev->gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);
+ if (IS_ERR(sydev->gpio))
+ return dev_err_probe(dev, PTR_ERR(sydev->gpio),
+ "failed to get enable GPIO\n");
+
+ /* Let some time for HW to settle */
+ fsleep(10000);
+
+ /* try read and check device id */
+ ret = regmap_read(sydev->regmap, REG_DEV_ID, &dev_id);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to read device id\n");
+ if (dev_id != 0x63) {
+ dev_err(dev, "unexpected device id: 0x%02x\n", dev_id);
+ return -ENODEV;
+ }
+
+ /* Initialize and set default brightness */
+ ret = sy7758_init(sydev);
+ if (ret)
+ return ret;
+
+ props.type = BACKLIGHT_RAW;
+ props.max_brightness = MAX_BRIGHTNESS;
+ props.brightness = DEFAULT_BRIGHTNESS;
+ props.scale = BACKLIGHT_SCALE_LINEAR;
+
+ sydev->bl = devm_backlight_device_register(dev, "sy7758-backlight",
+ dev, sydev, &sy7758_backlight_ops,
+ &props);
+ if (IS_ERR(sydev->bl))
+ return dev_err_probe(dev, PTR_ERR(sydev->bl),
+ "failed to register backlight device\n");
+
+ return backlight_update_status(sydev->bl);
+}
+
+static void sy7758_remove(struct i2c_client *client)
+{
+ struct sy7758 *sydev = i2c_get_clientdata(client);
+
+ backlight_disable(sydev->bl);
+}
+
+static const struct i2c_device_id sy7758_ids[] = {
+ { "sy7758" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, sy7758_ids);
+
+static const struct of_device_id sy7758_match_table[] = {
+ { .compatible = "silergy,sy7758", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, sy7758_match_table);
+
+static struct i2c_driver sy7758_driver = {
+ .driver = {
+ .name = "sy7758",
+ .of_match_table = sy7758_match_table,
+ },
+ .probe = sy7758_probe,
+ .remove = sy7758_remove,
+ .id_table = sy7758_ids,
+};
+
+module_i2c_driver(sy7758_driver);
+
+MODULE_DESCRIPTION("Silergy SY7758 Backlight Driver");
+MODULE_AUTHOR("Kancy Joe <kancy2333@outlook.com>");
+MODULE_AUTHOR("Neil Armstrong <neil.armstrong@linaro.org>");
+MODULE_LICENSE("GPL");
--
2.34.1
^ permalink raw reply related
* [PATCH v4 1/2] dt-bindings: leds: backlight: document the SY7758 6-channel High Efficiency LED Driver
From: Neil Armstrong @ 2026-05-21 8:08 UTC (permalink / raw)
To: Lee Jones, Daniel Thompson, Jingoo Han, Pavel Machek, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Helge Deller
Cc: dri-devel, linux-leds, devicetree, linux-kernel, linux-fbdev,
KancyJoe, Neil Armstrong, Krzysztof Kozlowski
In-Reply-To: <20260521-topic-sm8650-ayaneo-pocket-s2-sy7758-v4-0-73c732615e4a@linaro.org>
Document the Silergy SY7758 6-channel High Efficiency LED Driver
used for backlight brightness control.
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
.../bindings/leds/backlight/silergy,sy7758.yaml | 53 ++++++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/Documentation/devicetree/bindings/leds/backlight/silergy,sy7758.yaml b/Documentation/devicetree/bindings/leds/backlight/silergy,sy7758.yaml
new file mode 100644
index 000000000000..80e978d691c2
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/backlight/silergy,sy7758.yaml
@@ -0,0 +1,53 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/leds/backlight/silergy,sy7758.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Silergy SY7758 6-channel High Efficiency LED Driver
+
+maintainers:
+ - Neil Armstrong <neil.armstrong@linaro.org>
+
+description:
+ Silergy SY7758 is a high efficiency 6-channels LED backlight
+ driver with I2C brightness control.
+
+allOf:
+ - $ref: common.yaml#
+
+properties:
+ compatible:
+ const: silergy,sy7758
+
+ reg:
+ maxItems: 1
+
+ vddio-supply: true
+
+ enable-gpios:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - vddio-supply
+ - enable-gpios
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ backlight@11 {
+ compatible = "silergy,sy7758";
+ reg = <0x11>;
+ vddio-supply = <&bl_vddio>;
+ enable-gpios = <&gpio 16 GPIO_ACTIVE_HIGH>;
+ };
+ };
--
2.34.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox