[PATCH v3 2/5] fbdev: Give atafb proper parent

Michael Schmitz <[email protected]>
Newsgroups org.kernel.vger.linux-m68k,org.kernel.vger.linux-fbdev
Message-ID <[email protected]>
From: Miro Kropacek <[email protected]>

The atafb fb device registers no parent, causing a missing symlink
(/sys/class/graphics/fb0/device). Xorg fbdevhw driver looks for that
symlink when scanning for devices, so add a parent node for atafb.

The proper way to do that is use of framebuffer_alloc(), which
requries refactoring atafb to move from static fb_info to allocation
of fb_info by framebuffer_alloc().
About the only location where a fb_info pointer cannot be passed
is monspec setup in atafb_setup(). Store static monspecs there
and copy into place after framebuffer_alloc().

Pass fb_info everywhere it's needed (detect, decode_var and
do_fb_set_var functions), and remove the static fb_info struct.

Signed-off-by: Miro Kropacek <[email protected]>
Reviewed-by: Michael Schmitz <[email protected]>
Signed-off-by: Michael Schmitz <[email protected]>
Cc: <[email protected]>
Link: https://lists.debian.org/debian-68k/2026/08/msg00000.html

---

Changes in v3:

- fbdev: refactor atafb fb_info use to allow use of framebuffer_alloc()
  (Thomas Zimmermann)
---
 drivers/video/fbdev/atafb.c | 174 +++++++++++++++++++-----------------
 1 file changed, 92 insertions(+), 82 deletions(-)

diff --git a/drivers/video/fbdev/atafb.c b/drivers/video/fbdev/atafb.c
index b8ed1c537293..a9be06ded5c9 100644
--- a/drivers/video/fbdev/atafb.c
+++ b/drivers/video/fbdev/atafb.c
@@ -158,14 +158,6 @@ static int DontCalcRes = 0;
 #define VMO_PREMASK		0x0c
 #endif
 
-static struct fb_info fb_info = {
-	.fix = {
-		.id	= "Atari ",
-		.visual	= FB_VISUAL_PSEUDOCOLOR,
-		.accel	= FB_ACCEL_NONE,
-	}
-};
-
 static void *screen_base;	/* base address of screen */
 static unsigned long phys_screen_base;	/* (only for Overscan) */
 
@@ -175,6 +167,12 @@ static int current_par_valid;
 
 static int mono_moni;
 
+/* monspecs passed by user */
+
+static __u32 mcap_hmin;		/* hfreq lower limit (Hz) */
+static __u32 mcap_hmax;		/* hfreq upper limit (Hz) */
+static __u16 mcap_vmin;		/* vfreq lower limit (Hz) */
+static __u16 mcap_vmax;		/* vfreq upper limit (Hz) */
 
 #ifdef ATAFB_EXT
 
@@ -299,7 +297,7 @@ static int *MV300_reg = MV300_reg_8bit;
 /* ++roman: This structure abstracts from the underlying hardware (ST(e),
  * TT, or Falcon.
  *
- * int (*detect)(void)
+ * int (*detect)(*fb_info)
  *   This function should detect the current video mode settings and
  *   store them in atafb_predefined[0] for later reference by the
  *   user. Return the index+1 of an equivalent predefined mode or 0
@@ -311,7 +309,7 @@ static int *MV300_reg = MV300_reg_8bit;
  *   values in the 'par' structure.
  * !!! Obsolete, perhaps !!!
  *
- * int (*decode_var)(struct fb_var_screeninfo *var,
+ * int (*decode_var)(struct fb_info *info, struct fb_var_screeninfo *var,
  *                   struct atafb_par *par)
  *   Get the video params out of 'var'. If a value doesn't fit, round
  *   it up, if it's too big, return EINVAL.
@@ -345,10 +343,10 @@ static int *MV300_reg = MV300_reg_8bit;
  */
 
 static struct fb_hwswitch {
-	int (*detect)(void);
+	int (*detect)(struct fb_info *info);
 	int (*encode_fix)(struct fb_fix_screeninfo *fix,
 			  struct atafb_par *par);
-	int (*decode_var)(struct fb_var_screeninfo *var,
+	int (*decode_var)(struct fb_info *info, struct fb_var_screeninfo *var,
 			  struct atafb_par *par);
 	int (*encode_var)(struct fb_var_screeninfo *var,
 			  struct atafb_par *par);
@@ -576,7 +574,7 @@ static int tt_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
 	return 0;
 }
 
-static int tt_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
+static int tt_decode_var(struct fb_info *info, struct fb_var_screeninfo *var, struct atafb_par *par)
 {
 	int xres = var->xres;
 	int yres = var->yres;
@@ -782,7 +780,7 @@ static int tt_setcolreg(unsigned int regno, unsigned int red,
 	return 0;
 }
 
-static int tt_detect(void)
+static int tt_detect(struct fb_info *info)
 {
 	struct atafb_par par;
 
@@ -877,7 +875,7 @@ static int falcon_encode_fix(struct fb_fix_screeninfo *fix,
 	return 0;
 }
 
-static int falcon_decode_var(struct fb_var_screeninfo *var,
+static int falcon_decode_var(struct fb_info *info, struct fb_var_screeninfo *var,
 			     struct atafb_par *par)
 {
 	int bpp = var->bits_per_pixel;
@@ -1069,13 +1067,13 @@ static int falcon_decode_var(struct fb_var_screeninfo *var,
 			/* Choose master pixelclock depending on hor. timing */
 			plen = 1 * xstretch;
 			if ((plen * xres + f25.right + f25.hsync + f25.left) *
-			    fb_info.monspecs.hfmin < f25.f)
+			    info->monspecs.hfmin < f25.f)
 				pclock = &f25;
 			else if ((plen * xres + f32.right + f32.hsync +
-				  f32.left) * fb_info.monspecs.hfmin < f32.f)
+				  f32.left) * info->monspecs.hfmin < f32.f)
 				pclock = &f32;
 			else if ((plen * xres + fext.right + fext.hsync +
-				  fext.left) * fb_info.monspecs.hfmin < fext.f &&
+				  fext.left) * info->monspecs.hfmin < fext.f &&
 			         fext.f)
 				pclock = &fext;
 			else
@@ -1245,14 +1243,14 @@ static int falcon_decode_var(struct fb_var_screeninfo *var,
 
 	/*  check hor. frequency */
 	hfreq = pclock->f / ((par->HHT + 2) * prescale * 2);
-	if (hfreq > fb_info.monspecs.hfmax && mon_type != F_MON_VGA) {
+	if (hfreq > info->monspecs.hfmax && mon_type != F_MON_VGA) {
 		/* ++guenther:   ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
 		/* Too high -> enlarge margin */
 		left_margin += 1;
 		right_margin += 1;
 		goto again;
 	}
-	if (hfreq > fb_info.monspecs.hfmax || hfreq < fb_info.monspecs.hfmin)
+	if (hfreq > info->monspecs.hfmax || hfreq < info->monspecs.hfmin)
 		return -EINVAL;
 
 	/* Vxx-registers */
@@ -1283,50 +1281,50 @@ static int falcon_decode_var(struct fb_var_screeninfo *var,
 	/* V-frequency check, hope I didn't create any loop here. */
 	/* Interlace and doubleline are mutually exclusive. */
 	vfreq = (hfreq * 2) / (par->VFT + 1);
-	if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) {
+	if (vfreq > info->monspecs.vfmax && !doubleline && !interlace) {
 		/* Too high -> try again with doubleline */
 		doubleline = 1;
 		goto again;
-	} else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) {
+	} else if (vfreq < info->monspecs.vfmin && !interlace && !doubleline) {
 		/* Too low -> try again with interlace */
 		interlace = 1;
 		goto again;
-	} else if (vfreq < fb_info.monspecs.vfmin && doubleline) {
+	} else if (vfreq < info->monspecs.vfmin && doubleline) {
 		/* Doubleline too low -> clear doubleline and enlarge margins */
 		int lines;
 		doubleline = 0;
 		for (lines = 0;
 		     (hfreq * 2) / (par->VFT + 1 + 4 * lines - 2 * yres) >
-		     fb_info.monspecs.vfmax;
+		     info->monspecs.vfmax;
 		     lines++)
 			;
 		upper_margin += lines;
 		lower_margin += lines;
 		goto again;
-	} else if (vfreq > fb_info.monspecs.vfmax && doubleline) {
+	} else if (vfreq > info->monspecs.vfmax && doubleline) {
 		/* Doubleline too high -> enlarge margins */
 		int lines;
 		for (lines = 0;
 		     (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
-		     fb_info.monspecs.vfmax;
+		     info->monspecs.vfmax;
 		     lines += 2)
 			;
 		upper_margin += lines;
 		lower_margin += lines;
 		goto again;
-	} else if (vfreq > fb_info.monspecs.vfmax && interlace) {
+	} else if (vfreq > info->monspecs.vfmax && interlace) {
 		/* Interlace, too high -> enlarge margins */
 		int lines;
 		for (lines = 0;
 		     (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
-		     fb_info.monspecs.vfmax;
+		     info->monspecs.vfmax;
 		     lines++)
 			;
 		upper_margin += lines;
 		lower_margin += lines;
 		goto again;
-	} else if (vfreq < fb_info.monspecs.vfmin ||
-		   vfreq > fb_info.monspecs.vfmax)
+	} else if (vfreq < info->monspecs.vfmin ||
+		   vfreq > info->monspecs.vfmax)
 		return -EINVAL;
 
 set_screen_base:
@@ -1720,7 +1718,7 @@ static int falcon_blank(int blank_mode)
 	return 0;
 }
 
-static int falcon_detect(void)
+static int falcon_detect(struct fb_info *info)
 {
 	struct atafb_par par;
 	unsigned char fhw;
@@ -1732,18 +1730,18 @@ static int falcon_detect(void)
 	f030_bus_width = fhw << 6 & 0x80;
 	switch (mon_type) {
 	case F_MON_SM:
-		fb_info.monspecs.vfmin = 70;
-		fb_info.monspecs.vfmax = 72;
-		fb_info.monspecs.hfmin = 35713;
-		fb_info.monspecs.hfmax = 35715;
+		info->monspecs.vfmin = 70;
+		info->monspecs.vfmax = 72;
+		info->monspecs.hfmin = 35713;
+		info->monspecs.hfmax = 35715;
 		break;
 	case F_MON_SC:
 	case F_MON_TV:
 		/* PAL...NTSC */
-		fb_info.monspecs.vfmin = 49;	/* not 50, since TOS defaults to 49.9x Hz */
-		fb_info.monspecs.vfmax = 60;
-		fb_info.monspecs.hfmin = 15620;
-		fb_info.monspecs.hfmax = 15755;
+		info->monspecs.vfmin = 49;	/* not 50, since TOS defaults to 49.9x Hz */
+		info->monspecs.vfmax = 60;
+		info->monspecs.hfmin = 15620;
+		info->monspecs.hfmax = 15755;
 		break;
 	}
 	/* initialize hsync-len */
@@ -1795,7 +1793,7 @@ static int stste_encode_fix(struct fb_fix_screeninfo *fix,
 	return 0;
 }
 
-static int stste_decode_var(struct fb_var_screeninfo *var,
+static int stste_decode_var(struct fb_info *info, struct fb_var_screeninfo *var,
 			    struct atafb_par *par)
 {
 	int xres = var->xres;
@@ -1971,7 +1969,7 @@ static int stste_setcolreg(unsigned int regno, unsigned int red,
 	return 0;
 }
 
-static int stste_detect(void)
+static int stste_detect(struct fb_info *info)
 {
 	struct atafb_par par;
 
@@ -2112,7 +2110,8 @@ static int ext_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
 	return 0;
 }
 
-static int ext_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
+static int ext_decode_var(struct fb_info *info, struct fb_var_screeninfo *var,
+			struct atafb_par *par)
 {
 	struct fb_var_screeninfo *myvar = &atafb_predefined[0];
 
@@ -2226,7 +2225,7 @@ static int ext_setcolreg(unsigned int regno, unsigned int red,
 	}
 }
 
-static int ext_detect(void)
+static int ext_detect(struct fb_info *info)
 {
 	struct fb_var_screeninfo *myvar = &atafb_predefined[0];
 	struct atafb_par dummy_par;
@@ -2344,12 +2343,12 @@ static void ata_set_par(struct atafb_par *par)
 
 /* used for hardware scrolling */
 
-static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
+static int do_fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var, int isactive)
 {
 	int err, activate;
 	struct atafb_par par;
 
-	err = fbhw->decode_var(var, &par);
+	err = fbhw->decode_var(info, var, &par);
 	if (err)
 		return err;
 	activate = var->activate;
@@ -2368,7 +2367,7 @@ static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
 	struct atafb_par par;
 	int err;
 	// Get fix directly (case con == -1 before)??
-	err = fbhw->decode_var(&info->var, &par);
+	err = fbhw->decode_var(info, &info->var, &par);
 	if (err)
 		return err;
 	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
@@ -2635,7 +2634,7 @@ static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 
 	/* Validate wanted screen parameters */
 	// if ((err = ata_decode_var(var, &par)))
-	err = fbhw->decode_var(var, &par);
+	err = fbhw->decode_var(info, var, &par);
 	if (err)
 		return err;
 
@@ -2651,7 +2650,7 @@ static int atafb_set_par(struct fb_info *info)
 	struct atafb_par *par = info->par;
 
 	/* Decode wanted screen parameters */
-	fbhw->decode_var(&info->var, par);
+	fbhw->decode_var(info, &info->var, par);
 	mutex_lock(&info->mm_lock);
 	fbhw->encode_fix(&info->fix, par);
 	mutex_unlock(&info->mm_lock);
@@ -2677,7 +2676,7 @@ static struct fb_ops atafb_ops = {
 	__FB_DEFAULT_IOMEM_OPS_MMAP,
 };
 
-static void check_default_par(int detected_mode)
+static void check_default_par(struct fb_info *info, int detected_mode)
 {
 	char default_name[10];
 	int i;
@@ -2688,14 +2687,14 @@ static void check_default_par(int detected_mode)
 	if (default_par) {
 		var = atafb_predefined[default_par - 1];
 		var.activate = FB_ACTIVATE_TEST;
-		if (do_fb_set_var(&var, 1))
+		if (do_fb_set_var(info, &var, 1))
 			default_par = 0;	/* failed */
 	}
 	/* Next is the autodetected one */
 	if (!default_par) {
 		var = atafb_predefined[detected_mode - 1]; /* autodetect */
 		var.activate = FB_ACTIVATE_TEST;
-		if (!do_fb_set_var(&var, 1))
+		if (!do_fb_set_var(info, &var, 1))
 			default_par = detected_mode;
 	}
 	/* If that also failed, try some default modes... */
@@ -2708,7 +2707,7 @@ static void check_default_par(int detected_mode)
 				panic("can't set default video mode");
 			var = atafb_predefined[default_par - 1];
 			var.activate = FB_ACTIVATE_TEST;
-			if (!do_fb_set_var(&var,1))
+			if (!do_fb_set_var(info, &var, 1))
 				break;	/* ok */
 		}
 	}
@@ -2901,10 +2900,10 @@ static void __init atafb_setup_mcap(char *spec)
 	if (hmax <= 0 || hmax <= hmin)
 		return;
 
-	fb_info.monspecs.vfmin = vmin;
-	fb_info.monspecs.vfmax = vmax;
-	fb_info.monspecs.hfmin = hmin;
-	fb_info.monspecs.hfmax = hmax;
+	mcap_vmin = vmin;
+	mcap_vmax = vmax;
+	mcap_hmin = hmin;
+	mcap_hmax = hmax;
 }
 #endif /* ATAFB_FALCON */
 
@@ -2991,12 +2990,19 @@ static int __init atafb_probe(struct platform_device *pdev)
 	unsigned int defmode = 0;
 	unsigned long mem_req;
 	char *option = NULL;
+	struct fb_info *fb_info;
 
 	if (fb_get_options("atafb", &option))
 		return -ENODEV;
 	atafb_setup(option);
 	dev_dbg(&pdev->dev, "%s: start\n", __func__);
 
+	fb_info =  framebuffer_alloc(sizeof(struct atafb_par), &pdev->dev);
+
+	strscpy(fb_info->fix.id, "Atari ");
+	fb_info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	fb_info->fix.accel = FB_ACCEL_NONE;
+
 	do {
 #ifdef ATAFB_EXT
 		if (external_addr) {
@@ -3052,15 +3058,20 @@ static int __init atafb_probe(struct platform_device *pdev)
 
 	/* Multisync monitor capabilities */
 	/* Atari-TOS defaults if no boot option present */
-	if (fb_info.monspecs.hfmin == 0) {
-		fb_info.monspecs.hfmin = 31000;
-		fb_info.monspecs.hfmax = 32000;
-		fb_info.monspecs.vfmin = 58;
-		fb_info.monspecs.vfmax = 62;
+	if (mcap_hmin == 0) {
+		fb_info->monspecs.hfmin = 31000;
+		fb_info->monspecs.hfmax = 32000;
+		fb_info->monspecs.vfmin = 58;
+		fb_info->monspecs.vfmax = 62;
+	} else {
+		fb_info->monspecs.vfmin = mcap_vmin;
+		fb_info->monspecs.vfmax = mcap_vmax;
+		fb_info->monspecs.hfmin = mcap_hmin;
+		fb_info->monspecs.hfmax = mcap_hmax;
 	}
 
-	detected_mode = fbhw->detect();
-	check_default_par(detected_mode);
+	detected_mode = fbhw->detect(fb_info);
+	check_default_par(fb_info, detected_mode);
 #ifdef ATAFB_EXT
 	if (!external_addr) {
 #endif /* ATAFB_EXT */
@@ -3100,43 +3111,42 @@ static int __init atafb_probe(struct platform_device *pdev)
 	}
 #endif /* ATAFB_EXT */
 
-//	strcpy(fb_info.mode->name, "Atari Builtin ");
-	fb_info.fbops = &atafb_ops;
+//	strcpy(fb_info->mode->name, "Atari Builtin ");
+	fb_info->fbops = &atafb_ops;
 	// try to set default (detected; requested) var
-	do_fb_set_var(&atafb_predefined[default_par - 1], 1);
+	do_fb_set_var(fb_info, &atafb_predefined[default_par - 1], 1);
 	// reads hw state into current par, which may not be sane yet
 	ata_get_par(&current_par);
-	fb_info.par = &current_par;
+	fb_info->par = &current_par;
 	// tries to read from HW which may not be initialized yet
 	// so set sane var first, then call atafb_set_par
-	atafb_get_var(&fb_info.var, &fb_info);
+	atafb_get_var(&(fb_info->var), fb_info);
 
 #ifdef ATAFB_FALCON
-	fb_info.pseudo_palette = current_par.hw.falcon.pseudo_palette;
+	fb_info->pseudo_palette = current_par.hw.falcon.pseudo_palette;
 #endif
 
-	if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, atafb_modedb,
+	if (!fb_find_mode(&(fb_info->var), fb_info, mode_option, atafb_modedb,
 			  NUM_TOTAL_MODES, &atafb_modedb[defmode],
-			  fb_info.var.bits_per_pixel)) {
+			  fb_info->var.bits_per_pixel)) {
 		return -EINVAL;
 	}
 
 	fb_videomode_to_modelist(atafb_modedb, NUM_TOTAL_MODES,
-				 &fb_info.modelist);
-
-	atafb_set_disp(&fb_info);
+				 &(fb_info->modelist));
 
-	fb_alloc_cmap(&(fb_info.cmap), 1 << fb_info.var.bits_per_pixel, 0);
+	atafb_set_disp(fb_info);
 
+	fb_alloc_cmap(&(fb_info->cmap), 1 << fb_info->var.bits_per_pixel, 0);
 
-	dev_info(&pdev->dev, "Determined %dx%d, depth %d\n", fb_info.var.xres,
-		 fb_info.var.yres, fb_info.var.bits_per_pixel);
-	if ((fb_info.var.xres != fb_info.var.xres_virtual) ||
-	    (fb_info.var.yres != fb_info.var.yres_virtual))
+	dev_info(&pdev->dev, "Determined %dx%d, depth %d\n", fb_info->var.xres,
+		 fb_info->var.yres, fb_info->var.bits_per_pixel);
+	if ((fb_info->var.xres != fb_info->var.xres_virtual) ||
+	    (fb_info->var.yres != fb_info->var.yres_virtual))
 		dev_info(&pdev->dev, "   virtual %dx%d\n",
-			 fb_info.var.xres_virtual, fb_info.var.yres_virtual);
+			 fb_info->var.xres_virtual, fb_info->var.yres_virtual);
 
-	if (register_framebuffer(&fb_info) < 0) {
+	if (register_framebuffer(fb_info) < 0) {
 #ifdef ATAFB_EXT
 		if (external_addr) {
 			iounmap(external_screen_base);
@@ -3150,7 +3160,7 @@ static int __init atafb_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	fb_info(&fb_info, "frame buffer device, using %dK of video memory\n",
+	fb_info(fb_info, "frame buffer device, using %dK of video memory\n",
 		screen_len >> 10);
 
 	/* TODO: This driver cannot be unloaded yet */
-- 
2.17.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.