Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 37ce69a5 authored by Richard Purdie's avatar Richard Purdie
Browse files

backlight: Rework backlight/fb interaction simplifying, lots



fb_info->bl_mutex is badly thought out and the backlight class doesn't
need it if the framebuffer/backlight register/unregister order is
consistent, particularly after the backlight locking fixes.

Fix the drivers to use the order:

backlight_device_register()
register_framebuffer()
unregister_framebuffer()
backlight_device_unregister()

and turn bl_mutex into a lock for the bl_curve data only.

Signed-off-by: default avatarRichard Purdie <rpurdie@rpsys.net>
parent b5c6916b
Loading
Loading
Loading
Loading
+12 −43
Original line number Diff line number Diff line
@@ -1697,7 +1697,6 @@ static int __devinit aty128fb_setup(char *options)

static struct backlight_properties aty128_bl_data;

/* Call with fb_info->bl_mutex held */
static int aty128_bl_get_level_brightness(struct aty128fb_par *par,
		int level)
{
@@ -1705,6 +1704,7 @@ static int aty128_bl_get_level_brightness(struct aty128fb_par *par,
	int atylevel;

	/* Get and convert the value */
	/* No locking of bl_curve since we read a single value */
	atylevel = MAX_LEVEL -
		(info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL);

@@ -1724,8 +1724,7 @@ static int aty128_bl_get_level_brightness(struct aty128fb_par *par,
/* That one prevents proper CRT output with LCD off */
#undef BACKLIGHT_DAC_OFF

/* Call with fb_info->bl_mutex held */
static int __aty128_bl_update_status(struct backlight_device *bd)
static int aty128_bl_update_status(struct backlight_device *bd)
{
	struct aty128fb_par *par = class_get_devdata(&bd->class_dev);
	unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL);
@@ -1778,19 +1777,6 @@ static int __aty128_bl_update_status(struct backlight_device *bd)
	return 0;
}

static int aty128_bl_update_status(struct backlight_device *bd)
{
	struct aty128fb_par *par = class_get_devdata(&bd->class_dev);
	struct fb_info *info = pci_get_drvdata(par->pdev);
	int ret;

	mutex_lock(&info->bl_mutex);
	ret = __aty128_bl_update_status(bd);
	mutex_unlock(&info->bl_mutex);

	return ret;
}

static int aty128_bl_get_brightness(struct backlight_device *bd)
{
	return bd->props->brightness;
@@ -1804,14 +1790,10 @@ static struct backlight_properties aty128_bl_data = {

static void aty128_bl_set_power(struct fb_info *info, int power)
{
	mutex_lock(&info->bl_mutex);

	if (info->bl_dev) {
		info->bl_dev->props->power = power;
		__aty128_bl_update_status(info->bl_dev);
		backlight_update_status(info->bl_dev);
	}

	mutex_unlock(&info->bl_mutex);
}

static void aty128_bl_init(struct aty128fb_par *par)
@@ -1838,12 +1820,10 @@ static void aty128_bl_init(struct aty128fb_par *par)
		goto error;
	}

	mutex_lock(&info->bl_mutex);
	info->bl_dev = bd;
	fb_bl_default_curve(info, 0,
		 63 * FB_BACKLIGHT_MAX / MAX_LEVEL,
		219 * FB_BACKLIGHT_MAX / MAX_LEVEL);
	mutex_unlock(&info->bl_mutex);

	bd->props->brightness = aty128_bl_data.max_brightness;
	bd->props->power = FB_BLANK_UNBLANK;
@@ -1864,31 +1844,19 @@ static void aty128_bl_init(struct aty128fb_par *par)
	return;
}

static void aty128_bl_exit(struct aty128fb_par *par)
static void aty128_bl_exit(struct backlight_device *bd)
{
	struct fb_info *info = pci_get_drvdata(par->pdev);

	if (bd) {
#ifdef CONFIG_PMAC_BACKLIGHT
		mutex_lock(&pmac_backlight_mutex);
#endif

	mutex_lock(&info->bl_mutex);
	if (info->bl_dev) {
#ifdef CONFIG_PMAC_BACKLIGHT
		if (pmac_backlight == info->bl_dev)
		if (pmac_backlight == bd)
			pmac_backlight = NULL;
		mutex_unlock(&pmac_backlight_mutex);
#endif

		backlight_device_unregister(info->bl_dev);
		info->bl_dev = NULL;
		backlight_device_unregister(bd);

		printk("aty128: Backlight unloaded\n");
	}
	mutex_unlock(&info->bl_mutex);

#ifdef CONFIG_PMAC_BACKLIGHT
	mutex_unlock(&pmac_backlight_mutex);
#endif
}
#endif /* CONFIG_FB_ATY128_BACKLIGHT */

@@ -2175,11 +2143,12 @@ static void __devexit aty128_remove(struct pci_dev *pdev)

	par = info->par;

	unregister_framebuffer(info);

#ifdef CONFIG_FB_ATY128_BACKLIGHT
	aty128_bl_exit(par);
	aty128_bl_exit(info->bl_dev);
#endif

	unregister_framebuffer(info);
#ifdef CONFIG_MTRR
	if (par->mtrr.vram_valid)
		mtrr_del(par->mtrr.vram, info->fix.smem_start,
+11 −38
Original line number Diff line number Diff line
@@ -2116,13 +2116,13 @@ static int atyfb_pci_resume(struct pci_dev *pdev)

static struct backlight_properties aty_bl_data;

/* Call with fb_info->bl_mutex held */
static int aty_bl_get_level_brightness(struct atyfb_par *par, int level)
{
	struct fb_info *info = pci_get_drvdata(par->pdev);
	int atylevel;

	/* Get and convert the value */
	/* No locking of bl_curve since we read a single value */
	atylevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;

	if (atylevel < 0)
@@ -2133,8 +2133,7 @@ static int aty_bl_get_level_brightness(struct atyfb_par *par, int level)
	return atylevel;
}

/* Call with fb_info->bl_mutex held */
static int __aty_bl_update_status(struct backlight_device *bd)
static int aty_bl_update_status(struct backlight_device *bd)
{
	struct atyfb_par *par = class_get_devdata(&bd->class_dev);
	unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par);
@@ -2159,19 +2158,6 @@ static int __aty_bl_update_status(struct backlight_device *bd)
	return 0;
}

static int aty_bl_update_status(struct backlight_device *bd)
{
	struct atyfb_par *par = class_get_devdata(&bd->class_dev);
	struct fb_info *info = pci_get_drvdata(par->pdev);
	int ret;

	mutex_lock(&info->bl_mutex);
	ret = __aty_bl_update_status(bd);
	mutex_unlock(&info->bl_mutex);

	return ret;
}

static int aty_bl_get_brightness(struct backlight_device *bd)
{
	return bd->props->brightness;
@@ -2203,12 +2189,10 @@ static void aty_bl_init(struct atyfb_par *par)
		goto error;
	}

	mutex_lock(&info->bl_mutex);
	info->bl_dev = bd;
	fb_bl_default_curve(info, 0,
		0x3F * FB_BACKLIGHT_MAX / MAX_LEVEL,
		0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL);
	mutex_unlock(&info->bl_mutex);

	bd->props->brightness = aty_bl_data.max_brightness;
	bd->props->power = FB_BLANK_UNBLANK;
@@ -2229,30 +2213,19 @@ static void aty_bl_init(struct atyfb_par *par)
	return;
}

static void aty_bl_exit(struct atyfb_par *par)
static void aty_bl_exit(struct backlight_device *bd)
{
	struct fb_info *info = pci_get_drvdata(par->pdev);

	if (bd) {
#ifdef CONFIG_PMAC_BACKLIGHT
		mutex_lock(&pmac_backlight_mutex);
#endif

	mutex_lock(&info->bl_mutex);
	if (info->bl_dev) {
#ifdef CONFIG_PMAC_BACKLIGHT
		if (pmac_backlight == info->bl_dev)
		if (pmac_backlight == bd)
			pmac_backlight = NULL;
		mutex_unlock(&pmac_backlight_mutex);
#endif

		backlight_device_unregister(info->bl_dev);
		backlight_device_unregister(bd);

		printk("aty: Backlight unloaded\n");
	}
	mutex_unlock(&info->bl_mutex);

#ifdef CONFIG_PMAC_BACKLIGHT
	mutex_unlock(&pmac_backlight_mutex);
#endif
}

#endif /* CONFIG_FB_ATY_BACKLIGHT */
@@ -3705,13 +3678,13 @@ static void __devexit atyfb_remove(struct fb_info *info)
	aty_set_crtc(par, &saved_crtc);
	par->pll_ops->set_pll(info, &saved_pll);

	unregister_framebuffer(info);

#ifdef CONFIG_FB_ATY_BACKLIGHT
	if (M64_HAS(MOBIL_BUS))
		aty_bl_exit(par);
		aty_bl_exit(info->bl_dev);
#endif

	unregister_framebuffer(info);

#ifdef CONFIG_MTRR
	if (par->mtrr_reg >= 0) {
	    mtrr_del(par->mtrr_reg, 0, 0);
+8 −21
Original line number Diff line number Diff line
@@ -29,17 +29,13 @@ struct radeon_bl_privdata {
static int radeon_bl_get_level_brightness(struct radeon_bl_privdata *pdata,
		int level)
{
	struct fb_info *info = pdata->rinfo->info;
	int rlevel;

	mutex_lock(&info->bl_mutex);

	/* Get and convert the value */
	/* No locking of bl_curve since we read a single value */
	rlevel = pdata->rinfo->info->bl_curve[level] *
		 FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL;

	mutex_unlock(&info->bl_mutex);

	if (rlevel < 0)
		rlevel = 0;
	else if (rlevel > MAX_RADEON_LEVEL)
@@ -187,12 +183,10 @@ void radeonfb_bl_init(struct radeonfb_info *rinfo)
		machine_is_compatible("PowerBook6,5");
#endif

	mutex_lock(&rinfo->info->bl_mutex);
	rinfo->info->bl_dev = bd;
	fb_bl_default_curve(rinfo->info, 0,
		 63 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL,
		217 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL);
	mutex_unlock(&rinfo->info->bl_mutex);

	bd->props->brightness = radeon_bl_data.max_brightness;
	bd->props->power = FB_BLANK_UNBLANK;
@@ -216,29 +210,22 @@ void radeonfb_bl_init(struct radeonfb_info *rinfo)

void radeonfb_bl_exit(struct radeonfb_info *rinfo)
{
#ifdef CONFIG_PMAC_BACKLIGHT
	mutex_lock(&pmac_backlight_mutex);
#endif
	struct backlight_device *bd = rinfo->info->bl_dev;

	mutex_lock(&rinfo->info->bl_mutex);
	if (rinfo->info->bl_dev) {
	if (bd) {
		struct radeon_bl_privdata *pdata;

#ifdef CONFIG_PMAC_BACKLIGHT
		if (pmac_backlight == rinfo->info->bl_dev)
		mutex_lock(&pmac_backlight_mutex);
		if (pmac_backlight == bd)
			pmac_backlight = NULL;
		mutex_unlock(&pmac_backlight_mutex);
#endif

		pdata = class_get_devdata(&rinfo->info->bl_dev->class_dev);
		backlight_device_unregister(rinfo->info->bl_dev);
		pdata = class_get_devdata(&bd->class_dev);
		backlight_device_unregister(bd);
		kfree(pdata);
		rinfo->info->bl_dev = NULL;

		printk("radeonfb: Backlight unloaded\n");
	}
	mutex_unlock(&rinfo->info->bl_mutex);

#ifdef CONFIG_PMAC_BACKLIGHT
	mutex_unlock(&pmac_backlight_mutex);
#endif
}
+2 −1
Original line number Diff line number Diff line
@@ -2393,7 +2393,6 @@ static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev)
        if (!rinfo)
                return;

	radeonfb_bl_exit(rinfo);
	radeonfb_pm_exit(rinfo);

	if (rinfo->mon1_EDID)
@@ -2420,6 +2419,8 @@ static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev)

        unregister_framebuffer(info);

        radeonfb_bl_exit(rinfo);

        iounmap(rinfo->mmio_base);
        iounmap(rinfo->fb_base);
 
+9 −5
Original line number Diff line number Diff line
@@ -59,7 +59,7 @@ struct fb_info *framebuffer_alloc(size_t size, struct device *dev)
	info->device = dev;

#ifdef CONFIG_FB_BACKLIGHT
	mutex_init(&info->bl_mutex);
	mutex_init(&info->bl_curve_mutex);
#endif

	return info;
@@ -445,10 +445,10 @@ static ssize_t store_bl_curve(struct device *device,
	/* If there has been an error in the input data, we won't
	 * reach this loop.
	 */
	mutex_lock(&fb_info->bl_mutex);
	mutex_lock(&fb_info->bl_curve_mutex);
	for (i = 0; i < FB_BACKLIGHT_LEVELS; ++i)
		fb_info->bl_curve[i] = tmp_curve[i];
	mutex_unlock(&fb_info->bl_mutex);
	mutex_unlock(&fb_info->bl_curve_mutex);

	return count;
}
@@ -466,7 +466,7 @@ static ssize_t show_bl_curve(struct device *device,
	if (!fb_info || !fb_info->bl_dev)
		return -ENODEV;

	mutex_lock(&fb_info->bl_mutex);
	mutex_lock(&fb_info->bl_curve_mutex);
	for (i = 0; i < FB_BACKLIGHT_LEVELS; i += 8)
		len += snprintf(&buf[len], PAGE_SIZE,
				"%02x %02x %02x %02x %02x %02x %02x %02x\n",
@@ -478,7 +478,7 @@ static ssize_t show_bl_curve(struct device *device,
				fb_info->bl_curve[i + 5],
				fb_info->bl_curve[i + 6],
				fb_info->bl_curve[i + 7]);
	mutex_unlock(&fb_info->bl_mutex);
	mutex_unlock(&fb_info->bl_curve_mutex);

	return len;
}
@@ -552,6 +552,8 @@ void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max)
{
	unsigned int i, flat, count, range = (max - min);

	mutex_lock(&fb_info->bl_curve_mutex);

	fb_info->bl_curve[0] = off;

	for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat)
@@ -560,6 +562,8 @@ void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max)
	count = FB_BACKLIGHT_LEVELS * 15 / 16;
	for (i = 0; i < count; ++i)
		fb_info->bl_curve[flat + i] = min + (range * (i + 1) / count);

	mutex_unlock(&fb_info->bl_curve_mutex);
}
EXPORT_SYMBOL_GPL(fb_bl_default_curve);
#endif
Loading