15474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann/*
25474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann * Backlight code for ATI Radeon based graphic cards
35474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann *
45474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann * Copyright (c) 2000 Ani Joshi <ajoshi@kernel.crashing.org>
55474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann * Copyright (c) 2003 Benjamin Herrenschmidt <benh@kernel.crashing.org>
65474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann * Copyright (c) 2006 Michael Hanselmann <linux-kernel@hansmi.ch>
75474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann *
85474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann * This program is free software; you can redistribute it and/or modify
95474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann * it under the terms of the GNU General Public License version 2 as
105474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann * published by the Free Software Foundation.
115474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann */
125474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
135474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann#include "radeonfb.h"
145474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann#include <linux/backlight.h>
155a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
165474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
175474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann#ifdef CONFIG_PMAC_BACKLIGHT
185474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann#include <asm/backlight.h>
195474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann#endif
205474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
215474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann#define MAX_RADEON_LEVEL 0xFF
225474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
235474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmannstruct radeon_bl_privdata {
245474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	struct radeonfb_info *rinfo;
255474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	uint8_t negative;
265474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann};
275474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
285474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmannstatic int radeon_bl_get_level_brightness(struct radeon_bl_privdata *pdata,
295474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		int level)
305474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann{
315474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	int rlevel;
325474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
335474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	/* Get and convert the value */
3437ce69a57ff217a4ca0871e9ee5aa58c052b7d86Richard Purdie	/* No locking of bl_curve since we read a single value */
355474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	rlevel = pdata->rinfo->info->bl_curve[level] *
365474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		 FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL;
375474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
385474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	if (rlevel < 0)
395474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		rlevel = 0;
405474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	else if (rlevel > MAX_RADEON_LEVEL)
415474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		rlevel = MAX_RADEON_LEVEL;
425474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
43cab267c65f44337974e4f1eae490b21dce0e9811Michael Hanselmann	if (pdata->negative)
44cab267c65f44337974e4f1eae490b21dce0e9811Michael Hanselmann		rlevel = MAX_RADEON_LEVEL - rlevel;
45cab267c65f44337974e4f1eae490b21dce0e9811Michael Hanselmann
465474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	return rlevel;
475474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann}
485474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
495474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmannstatic int radeon_bl_update_status(struct backlight_device *bd)
505474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann{
51655bfd7aebb12481ab9275284d9500bee5ba3e70Richard Purdie	struct radeon_bl_privdata *pdata = bl_get_data(bd);
525474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	struct radeonfb_info *rinfo = pdata->rinfo;
535474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	u32 lvds_gen_cntl, tmpPixclksCntl;
545474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	int level;
555474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
565474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	if (rinfo->mon1_type != MT_LCD)
575474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		return 0;
585474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
595474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	/* We turn off the LCD completely instead of just dimming the
605474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	 * backlight. This provides some greater power saving and the display
615474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	 * is useless without backlight anyway.
625474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	 */
63599a52d12629394236d785615808845823875868Richard Purdie        if (bd->props.power != FB_BLANK_UNBLANK ||
64599a52d12629394236d785615808845823875868Richard Purdie	    bd->props.fb_blank != FB_BLANK_UNBLANK)
655474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		level = 0;
665474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	else
67599a52d12629394236d785615808845823875868Richard Purdie		level = bd->props.brightness;
685474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
695474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	del_timer_sync(&rinfo->lvds_timer);
706c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds	radeon_engine_idle();
715474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
725474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
735474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	if (level > 0) {
745474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		lvds_gen_cntl &= ~LVDS_DISPLAY_DIS;
755474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		if (!(lvds_gen_cntl & LVDS_BLON) || !(lvds_gen_cntl & LVDS_ON)) {
765474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann			lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_DIGON);
775474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann			lvds_gen_cntl |= LVDS_BLON | LVDS_EN;
785474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann			OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
795474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann			lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
805474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann			lvds_gen_cntl |=
815474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann				(radeon_bl_get_level_brightness(pdata, level) <<
825474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann				 LVDS_BL_MOD_LEVEL_SHIFT);
835474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann			lvds_gen_cntl |= LVDS_ON;
845474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann			lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_BL_MOD_EN);
855474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann			rinfo->pending_lvds_gen_cntl = lvds_gen_cntl;
865474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann			mod_timer(&rinfo->lvds_timer,
875474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann				  jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay));
885474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		} else {
895474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann			lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
905474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann			lvds_gen_cntl |=
915474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann				(radeon_bl_get_level_brightness(pdata, level) <<
925474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann				 LVDS_BL_MOD_LEVEL_SHIFT);
935474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann			OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
945474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		}
955474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
965474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		rinfo->init_state.lvds_gen_cntl |= rinfo->pending_lvds_gen_cntl
975474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann			& LVDS_STATE_MASK;
985474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	} else {
995474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		/* Asic bug, when turning off LVDS_ON, we have to make sure
1005474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		   RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
1015474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		*/
1025474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		tmpPixclksCntl = INPLL(PIXCLKS_CNTL);
1035474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		if (rinfo->is_mobility || rinfo->is_IGP)
1045474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann			OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
1055474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		lvds_gen_cntl &= ~(LVDS_BL_MOD_LEVEL_MASK | LVDS_BL_MOD_EN);
1065474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		lvds_gen_cntl |= (radeon_bl_get_level_brightness(pdata, 0) <<
1075474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann				  LVDS_BL_MOD_LEVEL_SHIFT);
1085474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		lvds_gen_cntl |= LVDS_DISPLAY_DIS;
1095474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
1105474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		udelay(100);
1115474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		lvds_gen_cntl &= ~(LVDS_ON | LVDS_EN);
1125474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
1135474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		lvds_gen_cntl &= ~(LVDS_DIGON);
1145474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		rinfo->pending_lvds_gen_cntl = lvds_gen_cntl;
1155474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		mod_timer(&rinfo->lvds_timer,
1165474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann			  jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay));
1175474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		if (rinfo->is_mobility || rinfo->is_IGP)
1185474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann			OUTPLL(PIXCLKS_CNTL, tmpPixclksCntl);
1195474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	}
1205474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
1215474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	rinfo->init_state.lvds_gen_cntl |= (lvds_gen_cntl & LVDS_STATE_MASK);
1225474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
1235474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	return 0;
1245474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann}
1255474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
126acc2472ed33fc5e72482cc3b3b846077d97c2f8bLionel Debrouxstatic const struct backlight_ops radeon_bl_data = {
1275474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	.update_status	= radeon_bl_update_status,
1285474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann};
1295474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
1305474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmannvoid radeonfb_bl_init(struct radeonfb_info *rinfo)
1315474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann{
132a19a6ee6cad2b20292a774c2f56ba8039b0fac9cMatthew Garrett	struct backlight_properties props;
1335474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	struct backlight_device *bd;
1345474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	struct radeon_bl_privdata *pdata;
1355474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	char name[12];
1365474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
1375474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	if (rinfo->mon1_type != MT_LCD)
1385474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		return;
1395474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
1405474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann#ifdef CONFIG_PMAC_BACKLIGHT
1415474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	if (!pmac_has_backlight_type("ati") &&
1425474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	    !pmac_has_backlight_type("mnca"))
1435474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		return;
1445474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann#endif
1455474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
1465474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	pdata = kmalloc(sizeof(struct radeon_bl_privdata), GFP_KERNEL);
1475474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	if (!pdata) {
1485474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		printk("radeonfb: Memory allocation failed\n");
1495474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		goto error;
1505474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	}
1515474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
1525474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	snprintf(name, sizeof(name), "radeonbl%d", rinfo->info->node);
1535474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
154a19a6ee6cad2b20292a774c2f56ba8039b0fac9cMatthew Garrett	memset(&props, 0, sizeof(struct backlight_properties));
155bb7ca747f8d6243b3943c5b133048652020f4a50Matthew Garrett	props.type = BACKLIGHT_RAW;
156a19a6ee6cad2b20292a774c2f56ba8039b0fac9cMatthew Garrett	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
157a19a6ee6cad2b20292a774c2f56ba8039b0fac9cMatthew Garrett	bd = backlight_device_register(name, rinfo->info->dev, pdata,
158a19a6ee6cad2b20292a774c2f56ba8039b0fac9cMatthew Garrett				       &radeon_bl_data, &props);
1595474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	if (IS_ERR(bd)) {
1605474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		rinfo->info->bl_dev = NULL;
1615474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		printk("radeonfb: Backlight registration failed\n");
1625474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		goto error;
1635474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	}
1645474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
1655474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	pdata->rinfo = rinfo;
1665474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
1675474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	/* Pardon me for that hack... maybe some day we can figure out in what
1685474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	 * direction backlight should work on a given panel?
1695474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	 */
1705474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	pdata->negative =
1715474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		(rinfo->family != CHIP_FAMILY_RV200 &&
1725474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		 rinfo->family != CHIP_FAMILY_RV250 &&
1735474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		 rinfo->family != CHIP_FAMILY_RV280 &&
1745474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		 rinfo->family != CHIP_FAMILY_RV350);
1755474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
1765474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann#ifdef CONFIG_PMAC_BACKLIGHT
1775474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	pdata->negative = pdata->negative ||
17871a157e8edca55198e808f8561dd49017a54ee34Grant Likely		of_machine_is_compatible("PowerBook4,3") ||
17971a157e8edca55198e808f8561dd49017a54ee34Grant Likely		of_machine_is_compatible("PowerBook6,3") ||
18071a157e8edca55198e808f8561dd49017a54ee34Grant Likely		of_machine_is_compatible("PowerBook6,5");
1815474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann#endif
1825474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
1835474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	rinfo->info->bl_dev = bd;
1845474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	fb_bl_default_curve(rinfo->info, 0,
1855474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		 63 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL,
1865474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		217 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL);
1875474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
188599a52d12629394236d785615808845823875868Richard Purdie	bd->props.brightness = bd->props.max_brightness;
189599a52d12629394236d785615808845823875868Richard Purdie	bd->props.power = FB_BLANK_UNBLANK;
19028ee086d5b36aab2931f6740e409bb0fb6c65e5fRichard Purdie	backlight_update_status(bd);
1915474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
1925474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	printk("radeonfb: Backlight initialized (%s)\n", name);
1935474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
1945474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	return;
1955474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
1965474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmannerror:
1975474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	kfree(pdata);
1985474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	return;
1995474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann}
2005474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
2015474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmannvoid radeonfb_bl_exit(struct radeonfb_info *rinfo)
2025474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann{
20337ce69a57ff217a4ca0871e9ee5aa58c052b7d86Richard Purdie	struct backlight_device *bd = rinfo->info->bl_dev;
2045474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
20537ce69a57ff217a4ca0871e9ee5aa58c052b7d86Richard Purdie	if (bd) {
2065474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		struct radeon_bl_privdata *pdata;
2075474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
208655bfd7aebb12481ab9275284d9500bee5ba3e70Richard Purdie		pdata = bl_get_data(bd);
20937ce69a57ff217a4ca0871e9ee5aa58c052b7d86Richard Purdie		backlight_device_unregister(bd);
2105474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		kfree(pdata);
2115474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		rinfo->info->bl_dev = NULL;
2125474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann
2135474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann		printk("radeonfb: Backlight unloaded\n");
2145474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann	}
2155474c120aafe78ca54bf272f7a01107c42da2b21Michael Hanselmann}
216