All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/5] Backlight: Add backlight type
@ 2011-01-14 19:24 Matthew Garrett
  2011-01-14 19:24   ` Matthew Garrett
                   ` (3 more replies)
  0 siblings, 4 replies; 40+ messages in thread
From: Matthew Garrett @ 2011-01-14 19:24 UTC (permalink / raw)
  To: akpm
  Cc: intel-gfx, dri-devel, linux-acpi, linux-kernel, rpurdie, Matthew Garrett

There may be multiple ways of controlling the backlight on a given machine.
Allow drivers to expose the type of interface they are providing, making
it possible for userspace to make appropriate policy decisions.

Signed-off-by: Matthew Garrett <mjg@redhat.com>
Cc: Richard Purdie <rpurdie@rpsys.net>
Cc: intel-gfx@lists.freedesktop.org
Cc: dri-devel@lists.freedesktop.org
---
 Documentation/ABI/stable/sysfs-class-backlight     |   20 ++++++++++++++++
 drivers/acpi/video.c                               |    1 +
 drivers/gpu/drm/nouveau/nouveau_backlight.c        |    2 +
 drivers/hid/hid-picolcd.c                          |    1 +
 drivers/macintosh/via-pmu-backlight.c              |    1 +
 drivers/platform/x86/acer-wmi.c                    |    1 +
 drivers/platform/x86/asus-laptop.c                 |    1 +
 drivers/platform/x86/asus_acpi.c                   |    1 +
 drivers/platform/x86/classmate-laptop.c            |    1 +
 drivers/platform/x86/compal-laptop.c               |    1 +
 drivers/platform/x86/dell-laptop.c                 |    1 +
 drivers/platform/x86/eeepc-laptop.c                |    1 +
 drivers/platform/x86/eeepc-wmi.c                   |    1 +
 drivers/platform/x86/fujitsu-laptop.c              |    1 +
 drivers/platform/x86/msi-laptop.c                  |    1 +
 drivers/platform/x86/msi-wmi.c                     |    1 +
 drivers/platform/x86/panasonic-laptop.c            |    1 +
 drivers/platform/x86/sony-laptop.c                 |    1 +
 drivers/platform/x86/thinkpad_acpi.c               |    1 +
 drivers/platform/x86/toshiba_acpi.c                |    1 +
 drivers/staging/olpc_dcon/olpc_dcon.c              |    1 +
 drivers/staging/samsung-laptop/samsung-laptop.c    |    1 +
 drivers/usb/misc/appledisplay.c                    |    1 +
 drivers/video/atmel_lcdfb.c                        |    1 +
 drivers/video/aty/aty128fb.c                       |    1 +
 drivers/video/aty/atyfb_base.c                     |    1 +
 drivers/video/aty/radeon_backlight.c               |    1 +
 drivers/video/backlight/88pm860x_bl.c              |    1 +
 drivers/video/backlight/adp5520_bl.c               |    1 +
 drivers/video/backlight/adp8860_bl.c               |    1 +
 drivers/video/backlight/adx_bl.c                   |    1 +
 drivers/video/backlight/atmel-pwm-bl.c             |    1 +
 drivers/video/backlight/backlight.c                |   24 +++++++++++++++++++-
 drivers/video/backlight/corgi_lcd.c                |    1 +
 drivers/video/backlight/cr_bllcd.c                 |    1 +
 drivers/video/backlight/da903x_bl.c                |    1 +
 drivers/video/backlight/ep93xx_bl.c                |    1 +
 drivers/video/backlight/generic_bl.c               |    1 +
 drivers/video/backlight/hp680_bl.c                 |    1 +
 drivers/video/backlight/jornada720_bl.c            |    1 +
 drivers/video/backlight/kb3886_bl.c                |    1 +
 drivers/video/backlight/locomolcd.c                |    1 +
 drivers/video/backlight/max8925_bl.c               |    1 +
 drivers/video/backlight/mbp_nvidia_bl.c            |    1 +
 drivers/video/backlight/omap1_bl.c                 |    1 +
 drivers/video/backlight/pcf50633-backlight.c       |    1 +
 drivers/video/backlight/progear_bl.c               |    1 +
 drivers/video/backlight/pwm_bl.c                   |    1 +
 drivers/video/backlight/s6e63m0.c                  |    1 +
 drivers/video/backlight/tosa_bl.c                  |    1 +
 drivers/video/backlight/wm831x_bl.c                |    1 +
 drivers/video/bf54x-lq043fb.c                      |    1 +
 drivers/video/bfin-t350mcqb-fb.c                   |    1 +
 drivers/video/imxfb.c                              |    1 +
 drivers/video/nvidia/nv_backlight.c                |    1 +
 drivers/video/omap2/displays/panel-acx565akm.c     |    1 +
 .../video/omap2/displays/panel-sharp-ls037v7dw01.c |    1 +
 drivers/video/omap2/displays/panel-taal.c          |    2 +
 drivers/video/riva/fbdev.c                         |    1 +
 include/linux/backlight.h                          |    9 +++++++
 60 files changed, 111 insertions(+), 1 deletions(-)

diff --git a/Documentation/ABI/stable/sysfs-class-backlight b/Documentation/ABI/stable/sysfs-class-backlight
index 4d637e1..70302f3 100644
--- a/Documentation/ABI/stable/sysfs-class-backlight
+++ b/Documentation/ABI/stable/sysfs-class-backlight
@@ -34,3 +34,23 @@ Contact:	Richard Purdie <rpurdie@rpsys.net>
 Description:
 		Maximum brightness for <backlight>.
 Users:		HAL
+
+What:		/sys/class/backlight/<backlight>/type
+Date:		September 2010
+KernelVersion:	2.6.37
+Contact:	Matthew Garrett <mjg@redhat.com>
+Description:
+		The type of interface controlled by <backlight>.
+		"firmware": The driver uses a standard firmware interface
+		"platform": The driver uses a platform-specific interface
+		"raw": The driver controls hardware registers directly
+
+		In the general case, when multiple backlight
+		interfaces are available for a single device, firmware
+		control should be preferred to platform control should
+		be preferred to raw control. Using a firmware
+		interface reduces the probability of confusion with
+		the hardware and the OS independently updating the
+		backlight state. Platform interfaces are mostly a
+		holdover from pre-standardisation of firmware
+		interfaces.
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 90f8f76..a9eec8c 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -795,6 +795,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
 		count++;
 
 		memset(&props, 0, sizeof(struct backlight_properties));
+		props.type = BACKLIGHT_FIRMWARE;
 		props.max_brightness = device->brightness->count - 3;
 		device->backlight = backlight_device_register(name, NULL, device,
 							      &acpi_backlight_ops,
diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
index d3a9c6e..18d7bcc 100644
--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
+++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
@@ -98,6 +98,7 @@ static int nouveau_nv40_backlight_init(struct drm_device *dev)
 		return 0;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 31;
 	bd = backlight_device_register("nv_backlight", &dev->pdev->dev, dev,
 				       &nv40_bl_ops, &props);
@@ -121,6 +122,7 @@ static int nouveau_nv50_backlight_init(struct drm_device *dev)
 		return 0;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 1025;
 	bd = backlight_device_register("nv_backlight", &dev->pdev->dev, dev,
 				       &nv50_bl_ops, &props);
diff --git a/drivers/hid/hid-picolcd.c b/drivers/hid/hid-picolcd.c
index de9cf21b..657da5a 100644
--- a/drivers/hid/hid-picolcd.c
+++ b/drivers/hid/hid-picolcd.c
@@ -944,6 +944,7 @@ static int picolcd_init_backlight(struct picolcd_data *data, struct hid_report *
 	}
 
 	memset(&props, 0, sizeof(props));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 0xff;
 	bdev = backlight_device_register(dev_name(dev), dev, data,
 			&picolcd_blops, &props);
diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c
index ade1e65..b1d9117 100644
--- a/drivers/macintosh/via-pmu-backlight.c
+++ b/drivers/macintosh/via-pmu-backlight.c
@@ -163,6 +163,7 @@ void __init pmu_backlight_init()
 	snprintf(name, sizeof(name), "pmubl");
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
 	bd = backlight_device_register(name, NULL, NULL, &pmu_backlight_data,
 				       &props);
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index c5c4b8c..3644c49 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -1032,6 +1032,7 @@ static int __devinit acer_backlight_init(struct device *dev)
 	struct backlight_device *bd;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = max_brightness;
 	bd = backlight_device_register("acer-wmi", dev, NULL, &acer_bl_ops,
 				       &props);
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index f3aa6a7..5a6f7d7 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -667,6 +667,7 @@ static int asus_backlight_init(struct asus_laptop *asus)
 
 	memset(&props, 0, sizeof(struct backlight_properties));
 	props.max_brightness = 15;
+	props.type = BACKLIGHT_PLATFORM;
 
 	bd = backlight_device_register(ASUS_LAPTOP_FILE,
 				       &asus->platform_device->dev, asus,
diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c
index 4633fd8..3be3380 100644
--- a/drivers/platform/x86/asus_acpi.c
+++ b/drivers/platform/x86/asus_acpi.c
@@ -1513,6 +1513,7 @@ static int __init asus_acpi_init(void)
 	}
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = 15;
 	asus_backlight_device = backlight_device_register("asus", NULL, NULL,
 							  &asus_backlight_data,
diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c
index 9111354..94f93b6 100644
--- a/drivers/platform/x86/classmate-laptop.c
+++ b/drivers/platform/x86/classmate-laptop.c
@@ -564,6 +564,7 @@ static int cmpc_ipml_add(struct acpi_device *acpi)
 		return -ENOMEM;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = 7;
 	ipml->bd = backlight_device_register("cmpc_bl", &acpi->dev,
 					     acpi->handle, &cmpc_bl_ops,
diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c
index 034572b..eb95878 100644
--- a/drivers/platform/x86/compal-laptop.c
+++ b/drivers/platform/x86/compal-laptop.c
@@ -970,6 +970,7 @@ static int __init compal_init(void)
 	if (!acpi_video_backlight_support()) {
 		struct backlight_properties props;
 		memset(&props, 0, sizeof(struct backlight_properties));
+		props.type = BACKLIGHT_PLATFORM;
 		props.max_brightness = BACKLIGHT_LEVEL_MAX;
 		compalbl_device = backlight_device_register(DRIVER_NAME,
 							    NULL, NULL,
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index 34657f9..fdfb9e7 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -651,6 +651,7 @@ static int __init dell_init(void)
 	if (max_intensity) {
 		struct backlight_properties props;
 		memset(&props, 0, sizeof(struct backlight_properties));
+		props.type = BACKLIGHT_PLATFORM;
 		props.max_brightness = max_intensity;
 		dell_backlight_device = backlight_device_register("dell_backlight",
 								  &platform_device->dev,
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index 49d9ad7..6605bea 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -1147,6 +1147,7 @@ static int eeepc_backlight_init(struct eeepc_laptop *eeepc)
 	struct backlight_device *bd;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = 15;
 	bd = backlight_device_register(EEEPC_LAPTOP_FILE,
 				       &eeepc->platform_device->dev, eeepc,
diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index 4d38f98..a304e5a 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -518,6 +518,7 @@ static int eeepc_wmi_backlight_init(struct eeepc_wmi *eeepc)
 
 	memset(&props, 0, sizeof(struct backlight_properties));
 	props.max_brightness = 15;
+	props.type = BACKLIGHT_PLATFORM;
 	bd = backlight_device_register(EEEPC_WMI_FILE,
 				       &eeepc->platform_device->dev, eeepc,
 				       &eeepc_wmi_bl_ops, &props);
diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c
index 95e3b09..493054c 100644
--- a/drivers/platform/x86/fujitsu-laptop.c
+++ b/drivers/platform/x86/fujitsu-laptop.c
@@ -1128,6 +1128,7 @@ static int __init fujitsu_init(void)
 
 		memset(&props, 0, sizeof(struct backlight_properties));
 		max_brightness = fujitsu->max_brightness;
+		props.type = BACKLIGHT_PLATFORM;
 		props.max_brightness = max_brightness - 1;
 		fujitsu->bl_device = backlight_device_register("fujitsu-laptop",
 							       NULL, NULL,
diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c
index 7e9bb6d..142d385 100644
--- a/drivers/platform/x86/msi-laptop.c
+++ b/drivers/platform/x86/msi-laptop.c
@@ -804,6 +804,7 @@ static int __init msi_init(void)
 	} else {
 		struct backlight_properties props;
 		memset(&props, 0, sizeof(struct backlight_properties));
+		props.type = BACKLIGHT_PLATFORM;
 		props.max_brightness = MSI_LCD_LEVEL_MAX - 1;
 		msibl_device = backlight_device_register("msi-laptop-bl", NULL,
 							 NULL, &msibl_ops,
diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c
index 35278ad..d5419c9 100644
--- a/drivers/platform/x86/msi-wmi.c
+++ b/drivers/platform/x86/msi-wmi.c
@@ -254,6 +254,7 @@ static int __init msi_wmi_init(void)
 	if (!acpi_video_backlight_support()) {
 		struct backlight_properties props;
 		memset(&props, 0, sizeof(struct backlight_properties));
+		props.type = BACKLIGHT_PLATFORM;
 		props.max_brightness = ARRAY_SIZE(backlight_map) - 1;
 		backlight = backlight_device_register(DRV_NAME, NULL, NULL,
 						      &msi_backlight_ops,
diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c
index cc1e0ba..05be30e 100644
--- a/drivers/platform/x86/panasonic-laptop.c
+++ b/drivers/platform/x86/panasonic-laptop.c
@@ -602,6 +602,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
 	}
 	/* initialize backlight */
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = pcc->sinf[SINF_AC_MAX_BRIGHT];
 	pcc->backlight = backlight_device_register("panasonic", NULL, pcc,
 						   &pcc_backlight_ops, &props);
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index 5e83370..75a1de3 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -1307,6 +1307,7 @@ static int sony_nc_add(struct acpi_device *device)
 						&handle))) {
 							struct backlight_properties props;
 		memset(&props, 0, sizeof(struct backlight_properties));
+		props.type = BACKLIGHT_PLATFORM;
 		props.max_brightness = SONY_MAX_BRIGHTNESS - 1;
 		sony_backlight_device = backlight_device_register("sony", NULL,
 								  NULL,
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index dd59958..d5e6969 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -6311,6 +6311,7 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
 		return 1;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = bright_maxlvl;
 	props.brightness = b & TP_EC_BACKLIGHT_LVLMSK;
 	ibm_backlight_device = backlight_device_register(TPACPI_BACKLIGHT_DEV_NAME,
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 209cced..63f42a2 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -1018,6 +1018,7 @@ static int __init toshiba_acpi_init(void)
 		create_toshiba_proc_entries();
 	}
 
+	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
 	toshiba_backlight_device = backlight_device_register("toshiba",
 							     &toshiba_acpi.p_dev->dev,
diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c
index 9f26dc9..fd9f24b 100644
--- a/drivers/staging/olpc_dcon/olpc_dcon.c
+++ b/drivers/staging/olpc_dcon/olpc_dcon.c
@@ -716,6 +716,7 @@ static int dcon_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	}
 	else {
 		dcon_bl_dev->props.max_brightness = 15;
+		dcon_bl_dev->props.type = BACKLIGHT_RAW;
 		dcon_bl_dev->props.power = FB_BLANK_UNBLANK;
 		dcon_bl_dev->props.brightness = dcon_get_backlight();
 
diff --git a/drivers/staging/samsung-laptop/samsung-laptop.c b/drivers/staging/samsung-laptop/samsung-laptop.c
index 701e8d5..532a48f 100644
--- a/drivers/staging/samsung-laptop/samsung-laptop.c
+++ b/drivers/staging/samsung-laptop/samsung-laptop.c
@@ -488,6 +488,7 @@ static int __init samsung_init(void)
 
 	/* create a backlight device to talk to this one */
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = MAX_BRIGHT;
 	backlight_device = backlight_device_register("samsung", &sdev->dev,
 						     NULL, &backlight_ops,
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
index 1fa6ce3..68ab460 100644
--- a/drivers/usb/misc/appledisplay.c
+++ b/drivers/usb/misc/appledisplay.c
@@ -282,6 +282,7 @@ static int appledisplay_probe(struct usb_interface *iface,
 	snprintf(bl_name, sizeof(bl_name), "appledisplay%d",
 		atomic_inc_return(&count_displays) - 1);
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 0xff;
 	pdata->bd = backlight_device_register(bl_name, NULL, pdata,
 					      &appledisplay_bl_data, &props);
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index bac16345..4b4e8da 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -127,6 +127,7 @@ static void init_backlight(struct atmel_lcdfb_info *sinfo)
 		return;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 0xff;
 	bl = backlight_device_register("backlight", &sinfo->pdev->dev, sinfo,
 				       &atmel_lcdc_bl_ops, &props);
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index dd9de2e..3813c7a 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -1818,6 +1818,7 @@ static void aty128_bl_init(struct aty128fb_par *par)
 	snprintf(name, sizeof(name), "aty128bl%d", info->node);
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
 	bd = backlight_device_register(name, info->dev, par, &aty128_bl_data,
 				       &props);
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 767ab4f..58deaeb 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -2241,6 +2241,7 @@ static void aty_bl_init(struct atyfb_par *par)
 	snprintf(name, sizeof(name), "atybl%d", info->node);
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
 	bd = backlight_device_register(name, info->dev, par, &aty_bl_data,
 				       &props);
diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c
index 9b811dd..db572df 100644
--- a/drivers/video/aty/radeon_backlight.c
+++ b/drivers/video/aty/radeon_backlight.c
@@ -158,6 +158,7 @@ void radeonfb_bl_init(struct radeonfb_info *rinfo)
 	snprintf(name, sizeof(name), "radeonbl%d", rinfo->info->node);
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
 	bd = backlight_device_register(name, rinfo->info->dev, pdata,
 				       &radeon_bl_data, &props);
diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c
index c789c46..a2da3a6 100644
--- a/drivers/video/backlight/88pm860x_bl.c
+++ b/drivers/video/backlight/88pm860x_bl.c
@@ -227,6 +227,7 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
 	}
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = MAX_BRIGHTNESS;
 	bl = backlight_device_register(name, &pdev->dev, data,
 					&pm860x_backlight_ops, &props);
diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c
index 9f436e0..af31197 100644
--- a/drivers/video/backlight/adp5520_bl.c
+++ b/drivers/video/backlight/adp5520_bl.c
@@ -303,6 +303,7 @@ static int __devinit adp5520_bl_probe(struct platform_device *pdev)
 	mutex_init(&data->lock);
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = ADP5020_MAX_BRIGHTNESS;
 	bl = backlight_device_register(pdev->name, data->master, data,
 				       &adp5520_bl_ops, &props);
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c
index 734c650..d2a96a4 100644
--- a/drivers/video/backlight/adp8860_bl.c
+++ b/drivers/video/backlight/adp8860_bl.c
@@ -709,6 +709,7 @@ static int __devinit adp8860_probe(struct i2c_client *client,
 	i2c_set_clientdata(client, data);
 
 	memset(&props, 0, sizeof(props));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = ADP8860_MAX_BRIGHTNESS;
 
 	mutex_init(&data->lock);
diff --git a/drivers/video/backlight/adx_bl.c b/drivers/video/backlight/adx_bl.c
index fe9af12..c861c41 100644
--- a/drivers/video/backlight/adx_bl.c
+++ b/drivers/video/backlight/adx_bl.c
@@ -104,6 +104,7 @@ static int __devinit adx_backlight_probe(struct platform_device *pdev)
 	}
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 0xff;
 	bldev = backlight_device_register(dev_name(&pdev->dev), &pdev->dev,
 					  bl, &adx_backlight_ops, &props);
diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c
index e6a66da..0443a4f 100644
--- a/drivers/video/backlight/atmel-pwm-bl.c
+++ b/drivers/video/backlight/atmel-pwm-bl.c
@@ -168,6 +168,7 @@ static int atmel_pwm_bl_probe(struct platform_device *pdev)
 	}
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = pdata->pwm_duty_max - pdata->pwm_duty_min;
 	bldev = backlight_device_register("atmel-pwm-bl", &pdev->dev, pwmbl,
 					  &atmel_pwm_bl_ops, &props);
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 0870329..80d292f 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -19,6 +19,12 @@
 #include <asm/backlight.h>
 #endif
 
+static const char const *backlight_types[] = {
+	[BACKLIGHT_RAW] = "raw",
+	[BACKLIGHT_PLATFORM] = "platform",
+	[BACKLIGHT_FIRMWARE] = "firmware",
+};
+
 #if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \
 			   defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE))
 /* This callback gets called when something important happens inside a
@@ -169,6 +175,14 @@ static ssize_t backlight_store_brightness(struct device *dev,
 	return rc;
 }
 
+static ssize_t backlight_show_type(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct backlight_device *bd = to_backlight_device(dev);
+
+	return sprintf(buf, "%s\n", backlight_types[bd->props.type]);
+}
+
 static ssize_t backlight_show_max_brightness(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -234,6 +248,7 @@ static struct device_attribute bl_device_attributes[] = {
 	__ATTR(actual_brightness, 0444, backlight_show_actual_brightness,
 		     NULL),
 	__ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL),
+	__ATTR(type, 0444, backlight_show_type, NULL),
 	__ATTR_NULL,
 };
 
@@ -292,9 +307,16 @@ struct backlight_device *backlight_device_register(const char *name,
 	dev_set_drvdata(&new_bd->dev, devdata);
 
 	/* Set default properties */
-	if (props)
+	if (props) {
 		memcpy(&new_bd->props, props,
 		       sizeof(struct backlight_properties));
+		if (props->type <= 0 || props->type >= BACKLIGHT_TYPE_MAX) {
+			WARN(1, "%s: invalid backlight type", name);
+			new_bd->props.type = BACKLIGHT_RAW;
+		}
+	} else {
+		new_bd->props.type = BACKLIGHT_RAW;
+	}
 
 	rc = device_register(&new_bd->dev);
 	if (rc) {
diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c
index 1e71c35..af60983 100644
--- a/drivers/video/backlight/corgi_lcd.c
+++ b/drivers/video/backlight/corgi_lcd.c
@@ -562,6 +562,7 @@ static int __devinit corgi_lcd_probe(struct spi_device *spi)
 	lcd->mode = (pdata) ? pdata->init_mode : CORGI_LCD_MODE_VGA;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = pdata->max_intensity;
 	lcd->bl_dev = backlight_device_register("corgi_bl", &spi->dev, lcd,
 						&corgi_bl_ops, &props);
diff --git a/drivers/video/backlight/cr_bllcd.c b/drivers/video/backlight/cr_bllcd.c
index 397d15e..6c8c540 100644
--- a/drivers/video/backlight/cr_bllcd.c
+++ b/drivers/video/backlight/cr_bllcd.c
@@ -193,6 +193,7 @@ static int cr_backlight_probe(struct platform_device *pdev)
 	}
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	bdp = backlight_device_register("cr-backlight", &pdev->dev, NULL,
 					&cr_backlight_ops, &props);
 	if (IS_ERR(bdp)) {
diff --git a/drivers/video/backlight/da903x_bl.c b/drivers/video/backlight/da903x_bl.c
index 87659ed..62043f1 100644
--- a/drivers/video/backlight/da903x_bl.c
+++ b/drivers/video/backlight/da903x_bl.c
@@ -136,6 +136,7 @@ static int da903x_backlight_probe(struct platform_device *pdev)
 		da903x_write(data->da903x_dev, DA9034_WLED_CONTROL2,
 				DA9034_WLED_ISET(pdata->output_current));
 
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = max_brightness;
 	bl = backlight_device_register(pdev->name, data->da903x_dev, data,
 				       &da903x_backlight_ops, &props);
diff --git a/drivers/video/backlight/ep93xx_bl.c b/drivers/video/backlight/ep93xx_bl.c
index b0cc491..9f1e389 100644
--- a/drivers/video/backlight/ep93xx_bl.c
+++ b/drivers/video/backlight/ep93xx_bl.c
@@ -87,6 +87,7 @@ static int __init ep93xxbl_probe(struct platform_device *dev)
 	ep93xxbl->mmio = EP93XX_RASTER_BRIGHTNESS;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = EP93XX_MAX_BRIGHT;
 	bl = backlight_device_register(dev->name, &dev->dev, ep93xxbl,
 				       &ep93xxbl_ops, &props);
diff --git a/drivers/video/backlight/generic_bl.c b/drivers/video/backlight/generic_bl.c
index 312ca61..8c6befd 100644
--- a/drivers/video/backlight/generic_bl.c
+++ b/drivers/video/backlight/generic_bl.c
@@ -91,6 +91,7 @@ static int genericbl_probe(struct platform_device *pdev)
 		name = machinfo->name;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = machinfo->max_intensity;
 	bd = backlight_device_register(name, &pdev->dev, NULL, &genericbl_ops,
 				       &props);
diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c
index 267d23f..38aa002 100644
--- a/drivers/video/backlight/hp680_bl.c
+++ b/drivers/video/backlight/hp680_bl.c
@@ -109,6 +109,7 @@ static int __devinit hp680bl_probe(struct platform_device *pdev)
 	struct backlight_device *bd;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = HP680_MAX_INTENSITY;
 	bd = backlight_device_register("hp680-bl", &pdev->dev, NULL,
 				       &hp680bl_ops, &props);
diff --git a/drivers/video/backlight/jornada720_bl.c b/drivers/video/backlight/jornada720_bl.c
index 2f177b3..40e4fa8 100644
--- a/drivers/video/backlight/jornada720_bl.c
+++ b/drivers/video/backlight/jornada720_bl.c
@@ -106,6 +106,7 @@ static int jornada_bl_probe(struct platform_device *pdev)
 	struct backlight_device *bd;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = BL_MAX_BRIGHT;
 	bd = backlight_device_register(S1D_DEVICENAME, &pdev->dev, NULL,
 				       &jornada_bl_ops, &props);
diff --git a/drivers/video/backlight/kb3886_bl.c b/drivers/video/backlight/kb3886_bl.c
index f439a86..72dd555 100644
--- a/drivers/video/backlight/kb3886_bl.c
+++ b/drivers/video/backlight/kb3886_bl.c
@@ -149,6 +149,7 @@ static int kb3886bl_probe(struct platform_device *pdev)
 		machinfo->limit_mask = -1;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = machinfo->max_intensity;
 	kb3886_backlight_device = backlight_device_register("kb3886-bl",
 							    &pdev->dev, NULL,
diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c
index d2f5901..bbca312 100644
--- a/drivers/video/backlight/locomolcd.c
+++ b/drivers/video/backlight/locomolcd.c
@@ -184,6 +184,7 @@ static int locomolcd_probe(struct locomo_dev *ldev)
 	local_irq_restore(flags);
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 4;
 	locomolcd_bl_device = backlight_device_register("locomo-bl",
 							&ldev->dev, NULL,
diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c
index 209acc1..07e8e27 100644
--- a/drivers/video/backlight/max8925_bl.c
+++ b/drivers/video/backlight/max8925_bl.c
@@ -136,6 +136,7 @@ static int __devinit max8925_backlight_probe(struct platform_device *pdev)
 	data->current_brightness = 0;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = MAX_BRIGHTNESS;
 	bl = backlight_device_register(name, &pdev->dev, data,
 					&max8925_backlight_ops, &props);
diff --git a/drivers/video/backlight/mbp_nvidia_bl.c b/drivers/video/backlight/mbp_nvidia_bl.c
index 1485f73..74c3394 100644
--- a/drivers/video/backlight/mbp_nvidia_bl.c
+++ b/drivers/video/backlight/mbp_nvidia_bl.c
@@ -367,6 +367,7 @@ static int __init mbp_init(void)
 		return -ENXIO;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = 15;
 	mbp_backlight_device = backlight_device_register("mbp_backlight", NULL,
 							 NULL,
diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c
index d3bc562..08d26a7 100644
--- a/drivers/video/backlight/omap1_bl.c
+++ b/drivers/video/backlight/omap1_bl.c
@@ -146,6 +146,7 @@ static int omapbl_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = OMAPBL_MAX_INTENSITY;
 	dev = backlight_device_register("omap-bl", &pdev->dev, bl, &omapbl_ops,
 					&props);
diff --git a/drivers/video/backlight/pcf50633-backlight.c b/drivers/video/backlight/pcf50633-backlight.c
index 3c424f7..ef5628d 100644
--- a/drivers/video/backlight/pcf50633-backlight.c
+++ b/drivers/video/backlight/pcf50633-backlight.c
@@ -112,6 +112,7 @@ static int __devinit pcf50633_bl_probe(struct platform_device *pdev)
 	if (!pcf_bl)
 		return -ENOMEM;
 
+	bl_props.type = BACKLIGHT_RAW;
 	bl_props.max_brightness = 0x3f;
 	bl_props.power = FB_BLANK_UNBLANK;
 
diff --git a/drivers/video/backlight/progear_bl.c b/drivers/video/backlight/progear_bl.c
index 809278c..6af183d 100644
--- a/drivers/video/backlight/progear_bl.c
+++ b/drivers/video/backlight/progear_bl.c
@@ -84,6 +84,7 @@ static int progearbl_probe(struct platform_device *pdev)
 	pci_write_config_byte(sb_dev, SB_MPS1, temp | 0x20);
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = HW_LEVEL_MAX - HW_LEVEL_MIN;
 	progear_backlight_device = backlight_device_register("progear-bl",
 							     &pdev->dev, NULL,
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index 21866ec..2c2a2c7 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -108,6 +108,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
 		dev_dbg(&pdev->dev, "got pwm for backlight\n");
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = data->max_brightness;
 	bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, pb,
 				       &pwm_backlight_ops, &props);
diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c
index 5927db0..322040f 100644
--- a/drivers/video/backlight/s6e63m0.c
+++ b/drivers/video/backlight/s6e63m0.c
@@ -778,6 +778,7 @@ static int __devinit s6e63m0_probe(struct spi_device *spi)
 
 	bd->props.max_brightness = MAX_BRIGHTNESS;
 	bd->props.brightness = MAX_BRIGHTNESS;
+	bd->props.type = BACKLIGHT_RAW;
 	lcd->bd = bd;
 
 	/*
diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c
index 2a04b38..425a736 100644
--- a/drivers/video/backlight/tosa_bl.c
+++ b/drivers/video/backlight/tosa_bl.c
@@ -102,6 +102,7 @@ static int __devinit tosa_bl_probe(struct i2c_client *client,
 	data->i2c = client;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 512 - 1;
 	data->bl = backlight_device_register("tosa-bl", &client->dev, data,
 					     &bl_ops, &props);
diff --git a/drivers/video/backlight/wm831x_bl.c b/drivers/video/backlight/wm831x_bl.c
index 08fd87f..d4c6eb2 100644
--- a/drivers/video/backlight/wm831x_bl.c
+++ b/drivers/video/backlight/wm831x_bl.c
@@ -193,6 +193,7 @@ static int wm831x_backlight_probe(struct platform_device *pdev)
 	data->current_brightness = 0;
 	data->isink_reg = isink_reg;
 
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = max_isel;
 	bl = backlight_device_register("wm831x", &pdev->dev, data,
 				       &wm831x_backlight_ops, &props);
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c
index e7d0f52..2464b91 100644
--- a/drivers/video/bf54x-lq043fb.c
+++ b/drivers/video/bf54x-lq043fb.c
@@ -649,6 +649,7 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev)
 	}
 #ifndef NO_BL_SUPPORT
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 255;
 	bl_dev = backlight_device_register("bf54x-bl", NULL, NULL,
 					   &bfin_lq043fb_bl_ops, &props);
diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c
index 3cf7767..d8de29f 100644
--- a/drivers/video/bfin-t350mcqb-fb.c
+++ b/drivers/video/bfin-t350mcqb-fb.c
@@ -545,6 +545,7 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev)
 	}
 #ifndef NO_BL_SUPPORT
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 255;
 	bl_dev = backlight_device_register("bf52x-bl", NULL, NULL,
 					   &bfin_lq043fb_bl_ops, &props);
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index 69bd4a5..ef72cb4 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -499,6 +499,7 @@ static void imxfb_init_backlight(struct imxfb_info *fbi)
 
 	memset(&props, 0, sizeof(struct backlight_properties));
 	props.max_brightness = 0xff;
+	props.type = BACKLIGHT_RAW;
 	writel(fbi->pwmr, fbi->regs + LCDC_PWMR);
 
 	bl = backlight_device_register("imxfb-bl", &fbi->pdev->dev, fbi,
diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/nvidia/nv_backlight.c
index 6aac6d1..8471008 100644
--- a/drivers/video/nvidia/nv_backlight.c
+++ b/drivers/video/nvidia/nv_backlight.c
@@ -111,6 +111,7 @@ void nvidia_bl_init(struct nvidia_par *par)
 	snprintf(name, sizeof(name), "nvidiabl%d", info->node);
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
 	bd = backlight_device_register(name, info->dev, par, &nvidia_bl_ops,
 				       &props);
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
index e773106..7e04c92 100644
--- a/drivers/video/omap2/displays/panel-acx565akm.c
+++ b/drivers/video/omap2/displays/panel-acx565akm.c
@@ -534,6 +534,7 @@ static int acx_panel_probe(struct omap_dss_device *dssdev)
 
 	props.fb_blank = FB_BLANK_UNBLANK;
 	props.power = FB_BLANK_UNBLANK;
+	props.type = BACKLIGHT_RAW;
 
 	bldev = backlight_device_register("acx565akm", &md->spi->dev,
 			md, &acx565akm_bl_ops, &props);
diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
index 9a138f6..d2b35d2 100644
--- a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
@@ -99,6 +99,7 @@ static int sharp_ls_panel_probe(struct omap_dss_device *dssdev)
 
 	memset(&props, 0, sizeof(struct backlight_properties));
 	props.max_brightness = dssdev->max_backlight_level;
+	props.type = BACKLIGHT_RAW;
 
 	bl = backlight_device_register("sharp-ls", &dssdev->dev, dssdev,
 			&sharp_ls_bl_ops, &props);
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index 61026f9..c74e8b7 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -729,6 +729,8 @@ static int taal_probe(struct omap_dss_device *dssdev)
 		props.max_brightness = 255;
 	else
 		props.max_brightness = 127;
+
+	props.type = BACKLIGHT_RAW;
 	bldev = backlight_device_register("taal", &dssdev->dev, dssdev,
 					  &taal_bl_ops, &props);
 	if (IS_ERR(bldev)) {
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index da38818..d8ab7be 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -355,6 +355,7 @@ static void riva_bl_init(struct riva_par *par)
 	snprintf(name, sizeof(name), "rivabl%d", info->node);
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
 	bd = backlight_device_register(name, info->dev, par, &riva_bl_ops,
 				       &props);
diff --git a/include/linux/backlight.h b/include/linux/backlight.h
index 4a3d52e..5ffc6dd 100644
--- a/include/linux/backlight.h
+++ b/include/linux/backlight.h
@@ -32,6 +32,13 @@ enum backlight_update_reason {
 	BACKLIGHT_UPDATE_SYSFS,
 };
 
+enum backlight_type {
+	BACKLIGHT_RAW = 1,
+	BACKLIGHT_PLATFORM,
+	BACKLIGHT_FIRMWARE,
+	BACKLIGHT_TYPE_MAX,
+};
+
 struct backlight_device;
 struct fb_info;
 
@@ -62,6 +69,8 @@ struct backlight_properties {
 	/* FB Blanking active? (values as for power) */
 	/* Due to be removed, please use (state & BL_CORE_FBBLANK) */
 	int fb_blank;
+	/* Backlight type */
+	enum backlight_type type;
 	/* Flags used to signal drivers of state changes */
 	/* Upper 4 bits are reserved for driver internal use */
 	unsigned int state;
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 2/5] i915: Add native backlight control
  2011-01-14 19:24 [PATCH 1/5] Backlight: Add backlight type Matthew Garrett
@ 2011-01-14 19:24   ` Matthew Garrett
  2011-01-14 19:24 ` [PATCH 3/5] radeon: Expose backlight class device for legacy LVDS encoder Matthew Garrett
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 40+ messages in thread
From: Matthew Garrett @ 2011-01-14 19:24 UTC (permalink / raw)
  To: akpm
  Cc: intel-gfx, linux-kernel, dri-devel, linux-acpi, rpurdie, Matthew Garrett

Not all systems expose a firmware or platform mechanism for changing the
backlight intensity on i915, so add native driver support.

Signed-off-by: Matthew Garrett <mjg@redhat.com>
Cc: intel-gfx <intel-gfx@lists.freedesktop.org>
---
 drivers/gpu/drm/i915/i915_drv.h       |    4 ++
 drivers/gpu/drm/i915/intel_dp.c       |    7 +++
 drivers/gpu/drm/i915/intel_drv.h      |    3 +-
 drivers/gpu/drm/i915/intel_lvds.c     |    5 ++
 drivers/gpu/drm/i915/intel_opregion.c |    1 -
 drivers/gpu/drm/i915/intel_panel.c    |   72 ++++++++++++++++++++++++++++++++-
 6 files changed, 89 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 5969f46..2d6ef13 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -36,6 +36,7 @@
 #include <linux/io-mapping.h>
 #include <linux/i2c.h>
 #include <drm/intel-gtt.h>
+#include <linux/backlight.h>
 
 /* General customization:
  */
@@ -667,6 +668,7 @@ typedef struct drm_i915_private {
 	int child_dev_num;
 	struct child_device_config *child_dev;
 	struct drm_connector *int_lvds_connector;
+	struct drm_connector *int_edp_connector;
 
 	bool mchbar_need_disable;
 
@@ -695,6 +697,8 @@ typedef struct drm_i915_private {
 
 	/* list of fbdev register on this device */
 	struct intel_fbdev *fbdev;
+
+	struct backlight_device *backlight;
 } drm_i915_private_t;
 
 struct drm_i915_gem_object {
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 1f4242b..54e89e9 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1682,6 +1682,11 @@ done:
 static void
 intel_dp_destroy (struct drm_connector *connector)
 {
+	struct drm_device *dev = connector->dev;
+
+	if (intel_dpd_is_edp(dev))
+		intel_panel_destroy_backlight(dev);
+
 	drm_sysfs_connector_remove(connector);
 	drm_connector_cleanup(connector);
 	kfree(connector);
@@ -1911,6 +1916,8 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 					DRM_MODE_TYPE_PREFERRED;
 			}
 		}
+		dev_priv->int_edp_connector = connector;
+		intel_panel_setup_backlight(dev);
 	}
 
 	intel_dp_add_properties(intel_dp, connector);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 74db255..074d41a 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -257,9 +257,10 @@ extern void intel_pch_panel_fitting(struct drm_device *dev,
 extern u32 intel_panel_get_max_backlight(struct drm_device *dev);
 extern u32 intel_panel_get_backlight(struct drm_device *dev);
 extern void intel_panel_set_backlight(struct drm_device *dev, u32 level);
-extern void intel_panel_setup_backlight(struct drm_device *dev);
+extern int intel_panel_setup_backlight(struct drm_device *dev);
 extern void intel_panel_enable_backlight(struct drm_device *dev);
 extern void intel_panel_disable_backlight(struct drm_device *dev);
+extern void intel_panel_destroy_backlight(struct drm_device *dev);
 
 extern void intel_crtc_load_lut(struct drm_crtc *crtc);
 extern void intel_encoder_prepare (struct drm_encoder *encoder);
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index ace8d5d..75f38c0 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -580,6 +580,8 @@ static void intel_lvds_destroy(struct drm_connector *connector)
 	struct drm_device *dev = connector->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
+	intel_panel_destroy_backlight(dev);
+
 	if (dev_priv->lid_notifier.notifier_call)
 		acpi_lid_notifier_unregister(&dev_priv->lid_notifier);
 	drm_sysfs_connector_remove(connector);
@@ -1055,6 +1057,9 @@ out:
 	/* keep the LVDS connector */
 	dev_priv->int_lvds_connector = connector;
 	drm_sysfs_connector_add(connector);
+
+	intel_panel_setup_backlight(dev);
+
 	return true;
 
 failed:
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
index f295a7a..5df3d38 100644
--- a/drivers/gpu/drm/i915/intel_opregion.c
+++ b/drivers/gpu/drm/i915/intel_opregion.c
@@ -224,7 +224,6 @@ void intel_opregion_asle_intr(struct drm_device *dev)
 	asle->aslc = asle_stat;
 }
 
-/* Only present on Ironlake+ */
 void intel_opregion_gse_intr(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index c65992d..4ab4239 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -274,10 +274,80 @@ void intel_panel_enable_backlight(struct drm_device *dev)
 	dev_priv->backlight_enabled = true;
 }
 
-void intel_panel_setup_backlight(struct drm_device *dev)
+void intel_panel_init_backlight(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	dev_priv->backlight_level = intel_panel_get_backlight(dev);
 	dev_priv->backlight_enabled = dev_priv->backlight_level != 0;
 }
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+static int intel_panel_update_status(struct backlight_device *bd)
+{
+	struct drm_device *dev = bl_get_data(bd);
+	intel_panel_set_backlight(dev, bd->props.brightness);
+	return 0;
+}
+
+static int intel_panel_get_brightness(struct backlight_device *bd)
+{
+	struct drm_device *dev = bl_get_data(bd);
+	return intel_panel_get_backlight(dev);
+}
+
+static const struct backlight_ops intel_panel_bl_ops = {
+	.update_status = intel_panel_update_status,
+	.get_brightness = intel_panel_get_brightness,
+};
+
+int intel_panel_setup_backlight(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct backlight_properties props;
+	struct drm_connector *connector;
+
+	intel_panel_init_backlight(dev);
+
+	if (dev_priv->int_lvds_connector)
+		connector = dev_priv->int_lvds_connector;
+	else if (dev_priv->int_edp_connector)
+		connector = dev_priv->int_edp_connector;
+	else
+		return -ENODEV;
+
+	props.type = BACKLIGHT_RAW;
+	props.max_brightness = intel_panel_get_max_backlight(dev);
+	dev_priv->backlight =
+		backlight_device_register("intel_backlight",
+					  &connector->kdev, dev,
+					  &intel_panel_bl_ops, &props);
+
+	if (IS_ERR(dev_priv->backlight)) {
+		DRM_ERROR("Failed to register backlight: %ld\n",
+			  PTR_ERR(dev_priv->backlight));
+		dev_priv->backlight = NULL;
+		return -ENODEV;
+	}
+	dev_priv->backlight->props.brightness = intel_panel_get_backlight(dev);
+	return 0;
+}
+
+void intel_panel_destroy_backlight(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	if (dev_priv->backlight)
+		backlight_device_unregister(dev_priv->backlight);
+}
+#else
+int intel_panel_setup_backlight(struct drm_device *dev)
+{
+	intel_panel_init_backlight(dev);
+	return 0;
+}
+
+void intel_panel_destroy_backlight(struct drm_device *dev)
+{
+	return;
+}
+#endif
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 2/5] i915: Add native backlight control
@ 2011-01-14 19:24   ` Matthew Garrett
  0 siblings, 0 replies; 40+ messages in thread
From: Matthew Garrett @ 2011-01-14 19:24 UTC (permalink / raw)
  To: akpm
  Cc: intel-gfx, dri-devel, linux-acpi, linux-kernel, rpurdie, Matthew Garrett

Not all systems expose a firmware or platform mechanism for changing the
backlight intensity on i915, so add native driver support.

Signed-off-by: Matthew Garrett <mjg@redhat.com>
Cc: intel-gfx <intel-gfx@lists.freedesktop.org>
---
 drivers/gpu/drm/i915/i915_drv.h       |    4 ++
 drivers/gpu/drm/i915/intel_dp.c       |    7 +++
 drivers/gpu/drm/i915/intel_drv.h      |    3 +-
 drivers/gpu/drm/i915/intel_lvds.c     |    5 ++
 drivers/gpu/drm/i915/intel_opregion.c |    1 -
 drivers/gpu/drm/i915/intel_panel.c    |   72 ++++++++++++++++++++++++++++++++-
 6 files changed, 89 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 5969f46..2d6ef13 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -36,6 +36,7 @@
 #include <linux/io-mapping.h>
 #include <linux/i2c.h>
 #include <drm/intel-gtt.h>
+#include <linux/backlight.h>
 
 /* General customization:
  */
@@ -667,6 +668,7 @@ typedef struct drm_i915_private {
 	int child_dev_num;
 	struct child_device_config *child_dev;
 	struct drm_connector *int_lvds_connector;
+	struct drm_connector *int_edp_connector;
 
 	bool mchbar_need_disable;
 
@@ -695,6 +697,8 @@ typedef struct drm_i915_private {
 
 	/* list of fbdev register on this device */
 	struct intel_fbdev *fbdev;
+
+	struct backlight_device *backlight;
 } drm_i915_private_t;
 
 struct drm_i915_gem_object {
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 1f4242b..54e89e9 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1682,6 +1682,11 @@ done:
 static void
 intel_dp_destroy (struct drm_connector *connector)
 {
+	struct drm_device *dev = connector->dev;
+
+	if (intel_dpd_is_edp(dev))
+		intel_panel_destroy_backlight(dev);
+
 	drm_sysfs_connector_remove(connector);
 	drm_connector_cleanup(connector);
 	kfree(connector);
@@ -1911,6 +1916,8 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 					DRM_MODE_TYPE_PREFERRED;
 			}
 		}
+		dev_priv->int_edp_connector = connector;
+		intel_panel_setup_backlight(dev);
 	}
 
 	intel_dp_add_properties(intel_dp, connector);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 74db255..074d41a 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -257,9 +257,10 @@ extern void intel_pch_panel_fitting(struct drm_device *dev,
 extern u32 intel_panel_get_max_backlight(struct drm_device *dev);
 extern u32 intel_panel_get_backlight(struct drm_device *dev);
 extern void intel_panel_set_backlight(struct drm_device *dev, u32 level);
-extern void intel_panel_setup_backlight(struct drm_device *dev);
+extern int intel_panel_setup_backlight(struct drm_device *dev);
 extern void intel_panel_enable_backlight(struct drm_device *dev);
 extern void intel_panel_disable_backlight(struct drm_device *dev);
+extern void intel_panel_destroy_backlight(struct drm_device *dev);
 
 extern void intel_crtc_load_lut(struct drm_crtc *crtc);
 extern void intel_encoder_prepare (struct drm_encoder *encoder);
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index ace8d5d..75f38c0 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -580,6 +580,8 @@ static void intel_lvds_destroy(struct drm_connector *connector)
 	struct drm_device *dev = connector->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
+	intel_panel_destroy_backlight(dev);
+
 	if (dev_priv->lid_notifier.notifier_call)
 		acpi_lid_notifier_unregister(&dev_priv->lid_notifier);
 	drm_sysfs_connector_remove(connector);
@@ -1055,6 +1057,9 @@ out:
 	/* keep the LVDS connector */
 	dev_priv->int_lvds_connector = connector;
 	drm_sysfs_connector_add(connector);
+
+	intel_panel_setup_backlight(dev);
+
 	return true;
 
 failed:
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
index f295a7a..5df3d38 100644
--- a/drivers/gpu/drm/i915/intel_opregion.c
+++ b/drivers/gpu/drm/i915/intel_opregion.c
@@ -224,7 +224,6 @@ void intel_opregion_asle_intr(struct drm_device *dev)
 	asle->aslc = asle_stat;
 }
 
-/* Only present on Ironlake+ */
 void intel_opregion_gse_intr(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index c65992d..4ab4239 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -274,10 +274,80 @@ void intel_panel_enable_backlight(struct drm_device *dev)
 	dev_priv->backlight_enabled = true;
 }
 
-void intel_panel_setup_backlight(struct drm_device *dev)
+void intel_panel_init_backlight(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	dev_priv->backlight_level = intel_panel_get_backlight(dev);
 	dev_priv->backlight_enabled = dev_priv->backlight_level != 0;
 }
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+static int intel_panel_update_status(struct backlight_device *bd)
+{
+	struct drm_device *dev = bl_get_data(bd);
+	intel_panel_set_backlight(dev, bd->props.brightness);
+	return 0;
+}
+
+static int intel_panel_get_brightness(struct backlight_device *bd)
+{
+	struct drm_device *dev = bl_get_data(bd);
+	return intel_panel_get_backlight(dev);
+}
+
+static const struct backlight_ops intel_panel_bl_ops = {
+	.update_status = intel_panel_update_status,
+	.get_brightness = intel_panel_get_brightness,
+};
+
+int intel_panel_setup_backlight(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct backlight_properties props;
+	struct drm_connector *connector;
+
+	intel_panel_init_backlight(dev);
+
+	if (dev_priv->int_lvds_connector)
+		connector = dev_priv->int_lvds_connector;
+	else if (dev_priv->int_edp_connector)
+		connector = dev_priv->int_edp_connector;
+	else
+		return -ENODEV;
+
+	props.type = BACKLIGHT_RAW;
+	props.max_brightness = intel_panel_get_max_backlight(dev);
+	dev_priv->backlight =
+		backlight_device_register("intel_backlight",
+					  &connector->kdev, dev,
+					  &intel_panel_bl_ops, &props);
+
+	if (IS_ERR(dev_priv->backlight)) {
+		DRM_ERROR("Failed to register backlight: %ld\n",
+			  PTR_ERR(dev_priv->backlight));
+		dev_priv->backlight = NULL;
+		return -ENODEV;
+	}
+	dev_priv->backlight->props.brightness = intel_panel_get_backlight(dev);
+	return 0;
+}
+
+void intel_panel_destroy_backlight(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	if (dev_priv->backlight)
+		backlight_device_unregister(dev_priv->backlight);
+}
+#else
+int intel_panel_setup_backlight(struct drm_device *dev)
+{
+	intel_panel_init_backlight(dev);
+	return 0;
+}
+
+void intel_panel_destroy_backlight(struct drm_device *dev)
+{
+	return;
+}
+#endif
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 3/5] radeon: Expose backlight class device for legacy LVDS encoder
  2011-01-14 19:24 [PATCH 1/5] Backlight: Add backlight type Matthew Garrett
  2011-01-14 19:24   ` Matthew Garrett
@ 2011-01-14 19:24 ` Matthew Garrett
  2011-01-15 17:34     ` Alex Deucher
  2011-01-20  2:12     ` Andrew Morton
  2011-01-14 19:24 ` [PATCH 4/5] nouveau: Change the backlight parent device to the connector, not the PCI dev Matthew Garrett
  2011-01-14 19:24 ` [PATCH 5/5] ACPI: Tie ACPI backlight devices to PCI devices if possible Matthew Garrett
  3 siblings, 2 replies; 40+ messages in thread
From: Matthew Garrett @ 2011-01-14 19:24 UTC (permalink / raw)
  To: akpm
  Cc: intel-gfx, dri-devel, linux-acpi, linux-kernel, rpurdie,
	Michel Dänzer, Michel Dänzer, Matthew Garrett

From: Michel Dänzer <michel@daenzer.net>

Allows e.g. power management daemons to control the backlight level. Inspired
by the corresponding code in radeonfb.

(Updated to add backlight type and make the connector the parent device - mjg)

Signed-off-by: Michel Dänzer <daenzer@vmware.com>
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Cc: dri-devel@lists.freedesktop.org
---
 drivers/gpu/drm/radeon/Kconfig                  |    1 +
 drivers/gpu/drm/radeon/radeon_connectors.c      |   15 ++
 drivers/gpu/drm/radeon/radeon_legacy_encoders.c |  257 ++++++++++++++++++++++-
 drivers/gpu/drm/radeon/radeon_mode.h            |   10 +
 4 files changed, 277 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/radeon/Kconfig b/drivers/gpu/drm/radeon/Kconfig
index 1c02d23..9746fee 100644
--- a/drivers/gpu/drm/radeon/Kconfig
+++ b/drivers/gpu/drm/radeon/Kconfig
@@ -1,6 +1,7 @@
 config DRM_RADEON_KMS
 	bool "Enable modesetting on radeon by default - NEW DRIVER"
 	depends on DRM_RADEON
+	select BACKLIGHT_CLASS_DEVICE
 	help
 	  Choose this option if you want kernel modesetting enabled by default.
 
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 22b7e3d..e842fb5 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -40,6 +40,10 @@ radeon_atombios_connected_scratch_regs(struct drm_connector *connector,
 				       struct drm_encoder *encoder,
 				       bool connected);
 
+extern void
+radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
+			     struct drm_connector *drm_connector);
+
 void radeon_connector_hotplug(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
@@ -1517,6 +1521,17 @@ radeon_add_legacy_connector(struct drm_device *dev,
 		connector->polled = DRM_CONNECTOR_POLL_HPD;
 	connector->display_info.subpixel_order = subpixel_order;
 	drm_sysfs_connector_add(connector);
+	if (connector_type == DRM_MODE_CONNECTOR_LVDS) {
+		struct drm_encoder *drm_encoder;
+
+		list_for_each_entry(drm_encoder, &dev->mode_config.encoder_list, head) {
+			struct radeon_encoder *radeon_encoder;
+
+			radeon_encoder = to_radeon_encoder(drm_encoder);
+			if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_LVDS)
+				radeon_legacy_backlight_init(radeon_encoder, connector);
+		}
+	}
 	return;
 
 failed:
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
index 59f834b..ba7dcc6 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
@@ -28,6 +28,10 @@
 #include "radeon_drm.h"
 #include "radeon.h"
 #include "atom.h"
+#include <linux/backlight.h>
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
 
 static void radeon_legacy_encoder_disable(struct drm_encoder *encoder)
 {
@@ -39,7 +43,7 @@ static void radeon_legacy_encoder_disable(struct drm_encoder *encoder)
 	radeon_encoder->active_device = 0;
 }
 
-static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
+static void radeon_legacy_lvds_update(struct drm_encoder *encoder, int mode)
 {
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
@@ -47,15 +51,23 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
 	uint32_t lvds_gen_cntl, lvds_pll_cntl, pixclks_cntl, disp_pwr_man;
 	int panel_pwr_delay = 2000;
 	bool is_mac = false;
+	uint8_t backlight_level;
 	DRM_DEBUG_KMS("\n");
 
+	lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
+	backlight_level = (lvds_gen_cntl >> RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
+
 	if (radeon_encoder->enc_priv) {
 		if (rdev->is_atom_bios) {
 			struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
 			panel_pwr_delay = lvds->panel_pwr_delay;
+			if (lvds->bl_dev)
+				backlight_level = lvds->backlight_level;
 		} else {
 			struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
 			panel_pwr_delay = lvds->panel_pwr_delay;
+			if (lvds->bl_dev)
+				backlight_level = lvds->backlight_level;
 		}
 	}
 
@@ -82,11 +94,13 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
 		lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET;
 		WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
 
-		lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
-		lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN | RADEON_LVDS_DIGON | RADEON_LVDS_BLON);
+		lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS |
+				   RADEON_LVDS_BL_MOD_LEVEL_MASK);
+		lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN |
+				  RADEON_LVDS_DIGON | RADEON_LVDS_BLON |
+				  (backlight_level << RADEON_LVDS_BL_MOD_LEVEL_SHIFT));
 		if (is_mac)
 			lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN;
-		lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS);
 		udelay(panel_pwr_delay * 1000);
 		WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
 		break;
@@ -95,7 +109,6 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
 	case DRM_MODE_DPMS_OFF:
 		pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
 		WREG32_PLL_P(RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb);
-		lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
 		lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
 		if (is_mac) {
 			lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_EN;
@@ -119,6 +132,25 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
 
 }
 
+static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct radeon_device *rdev = encoder->dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	DRM_DEBUG("\n");
+
+	if (radeon_encoder->enc_priv) {
+		if (rdev->is_atom_bios) {
+			struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
+			lvds->dpms_mode = mode;
+		} else {
+			struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
+			lvds->dpms_mode = mode;
+		}
+	}
+
+	radeon_legacy_lvds_update(encoder, mode);
+}
+
 static void radeon_legacy_lvds_prepare(struct drm_encoder *encoder)
 {
 	struct radeon_device *rdev = encoder->dev->dev_private;
@@ -237,9 +269,222 @@ static const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = {
 	.disable = radeon_legacy_encoder_disable,
 };
 
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+
+#define MAX_RADEON_LEVEL 0xFF
+
+struct radeon_backlight_privdata {
+	struct radeon_encoder *encoder;
+	uint8_t negative;
+};
+
+static uint8_t radeon_legacy_lvds_level(struct backlight_device *bd)
+{
+	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
+	uint8_t level;
+
+	/* Convert brightness to hardware level */
+	if (bd->props.brightness < 0)
+		level = 0;
+	else if (bd->props.brightness > MAX_RADEON_LEVEL)
+		level = MAX_RADEON_LEVEL;
+	else
+		level = bd->props.brightness;
+
+	if (pdata->negative)
+		level = MAX_RADEON_LEVEL - level;
+
+	return level;
+}
+
+static int radeon_legacy_backlight_update_status(struct backlight_device *bd)
+{
+	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
+	struct radeon_encoder *radeon_encoder = pdata->encoder;
+	struct drm_device *dev = radeon_encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	int dpms_mode = DRM_MODE_DPMS_ON;
+
+	if (radeon_encoder->enc_priv) {
+		if (rdev->is_atom_bios) {
+			struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
+			dpms_mode = lvds->dpms_mode;
+			lvds->backlight_level = radeon_legacy_lvds_level(bd);
+		} else {
+			struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
+			dpms_mode = lvds->dpms_mode;
+			lvds->backlight_level = radeon_legacy_lvds_level(bd);
+		}
+	}
+
+	if (bd->props.brightness > 0)
+		radeon_legacy_lvds_update(&radeon_encoder->base, dpms_mode);
+	else
+		radeon_legacy_lvds_update(&radeon_encoder->base, DRM_MODE_DPMS_OFF);
+
+	return 0;
+}
+
+static int radeon_legacy_backlight_get_brightness(struct backlight_device *bd)
+{
+	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
+	struct radeon_encoder *radeon_encoder = pdata->encoder;
+	struct drm_device *dev = radeon_encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint8_t backlight_level;
+
+	backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >>
+			   RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
+
+	return pdata->negative ? MAX_RADEON_LEVEL - backlight_level : backlight_level;
+}
+
+static const struct backlight_ops radeon_backlight_ops = {
+	.get_brightness = radeon_legacy_backlight_get_brightness,
+	.update_status	= radeon_legacy_backlight_update_status,
+};
+
+void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
+				  struct drm_connector *drm_connector)
+{
+	struct drm_device *dev = radeon_encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct backlight_device *bd;
+	struct backlight_properties props;
+	struct radeon_backlight_privdata *pdata;
+	uint8_t backlight_level;
+
+	if (!radeon_encoder->enc_priv)
+		return;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	if (!pmac_has_backlight_type("ati") &&
+	    !pmac_has_backlight_type("mnca"))
+		return;
+#endif
+
+	pdata = kmalloc(sizeof(struct radeon_backlight_privdata), GFP_KERNEL);
+	if (!pdata) {
+		DRM_ERROR("Memory allocation failed\n");
+		goto error;
+	}
+
+	props.max_brightness = MAX_RADEON_LEVEL;
+	props.type = BACKLIGHT_RAW;
+	bd = backlight_device_register("radeon_bl", &drm_connector->kdev,
+				       pdata, &radeon_backlight_ops, &props);
+	if (IS_ERR(bd)) {
+		DRM_ERROR("Backlight registration failed\n");
+		goto error;
+	}
+
+	pdata->encoder = radeon_encoder;
+
+	backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >>
+			   RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
+
+	/* First, try to detect backlight level sense based on the assumption
+	 * that firmware set it up at full brightness
+	 */
+	if (backlight_level == 0)
+		pdata->negative = true;
+	else if (backlight_level == 0xff)
+		pdata->negative = false;
+	else {
+		/* XXX hack... maybe some day we can figure out in what direction
+		 * backlight should work on a given panel?
+		 */
+		pdata->negative = (rdev->family != CHIP_RV200 &&
+				   rdev->family != CHIP_RV250 &&
+				   rdev->family != CHIP_RV280 &&
+				   rdev->family != CHIP_RV350);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+		pdata->negative = (pdata->negative ||
+				   of_machine_is_compatible("PowerBook4,3") ||
+				   of_machine_is_compatible("PowerBook6,3") ||
+				   of_machine_is_compatible("PowerBook6,5"));
+#endif
+	}
+
+	if (rdev->is_atom_bios) {
+		struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
+		lvds->bl_dev = bd;
+	} else {
+		struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
+		lvds->bl_dev = bd;
+	}
+
+	bd->props.brightness = radeon_legacy_backlight_get_brightness(bd);
+	bd->props.power = FB_BLANK_UNBLANK;
+	backlight_update_status(bd);
+
+	DRM_INFO("radeon legacy LVDS backlight initialized\n");
+
+	return;
+
+error:
+	kfree(pdata);
+	return;
+}
+
+static void radeon_legacy_backlight_exit(struct radeon_encoder *radeon_encoder)
+{
+	struct drm_device *dev = radeon_encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct backlight_device *bd = NULL;
+
+	if (!radeon_encoder->enc_priv)
+		return;
+
+	if (rdev->is_atom_bios) {
+		struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
+		bd = lvds->bl_dev;
+		lvds->bl_dev = NULL;
+	} else {
+		struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
+		bd = lvds->bl_dev;
+		lvds->bl_dev = NULL;
+	}
+
+	if (bd) {
+		struct radeon_legacy_backlight_privdata *pdata;
+
+		pdata = bl_get_data(bd);
+		backlight_device_unregister(bd);
+		kfree(pdata);
+
+		DRM_INFO("radeon legacy LVDS backlight unloaded\n");
+	}
+}
+
+#else /* !CONFIG_BACKLIGHT_CLASS_DEVICE */
+
+static void radeon_legacy_backlight_init(struct radeon_encoder *encoder)
+{
+}
+
+static void radeon_legacy_backlight_exit(struct radeon_encoder *encoder)
+{
+}
+
+#endif
+
+
+static void radeon_lvds_enc_destroy(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+
+	if (radeon_encoder->enc_priv) {
+		radeon_legacy_backlight_exit(radeon_encoder);
+		kfree(radeon_encoder->enc_priv);
+	}
+	drm_encoder_cleanup(encoder);
+	kfree(radeon_encoder);
+}
 
 static const struct drm_encoder_funcs radeon_legacy_lvds_enc_funcs = {
-	.destroy = radeon_enc_destroy,
+	.destroy = radeon_lvds_enc_destroy,
 };
 
 static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode)
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 12bdeab..32c6257 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -300,6 +300,11 @@ struct radeon_encoder_lvds {
 	uint32_t lvds_gen_cntl;
 	/* panel mode */
 	struct drm_display_mode native_mode;
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	struct backlight_device *bl_dev;
+	int      dpms_mode;
+	uint8_t  backlight_level;
+#endif
 };
 
 struct radeon_encoder_tv_dac {
@@ -353,6 +358,11 @@ struct radeon_encoder_atom_dig {
 	uint32_t lcd_ss_id;
 	/* panel mode */
 	struct drm_display_mode native_mode;
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	struct backlight_device *bl_dev;
+	int dpms_mode;
+	uint8_t backlight_level;
+#endif
 };
 
 struct radeon_encoder_atom_dac {
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 4/5] nouveau: Change the backlight parent device to the connector, not the PCI dev
  2011-01-14 19:24 [PATCH 1/5] Backlight: Add backlight type Matthew Garrett
  2011-01-14 19:24   ` Matthew Garrett
  2011-01-14 19:24 ` [PATCH 3/5] radeon: Expose backlight class device for legacy LVDS encoder Matthew Garrett
@ 2011-01-14 19:24 ` Matthew Garrett
  2011-01-14 19:30     ` Anca Emanuel
  2011-01-15  9:49   ` Ben Skeggs
  2011-01-14 19:24 ` [PATCH 5/5] ACPI: Tie ACPI backlight devices to PCI devices if possible Matthew Garrett
  3 siblings, 2 replies; 40+ messages in thread
From: Matthew Garrett @ 2011-01-14 19:24 UTC (permalink / raw)
  To: akpm
  Cc: intel-gfx, dri-devel, linux-acpi, linux-kernel, rpurdie, Matthew Garrett

We may eventually end up with per-connector backlights, especially with
ddcci devices. Make sure that the parent node for the backlight device is
the connector rather than the PCI device.

Signed-off-by: Matthew Garrett <mjg@redhat.com>
---
 drivers/gpu/drm/nouveau/nouveau_backlight.c |   24 ++++++++++++++----------
 drivers/gpu/drm/nouveau/nouveau_connector.c |    9 +++++++++
 drivers/gpu/drm/nouveau/nouveau_drv.h       |    8 ++++----
 drivers/gpu/drm/nouveau/nouveau_state.c     |    6 ------
 4 files changed, 27 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
index 18d7bcc..00a55df 100644
--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
+++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
@@ -88,10 +88,11 @@ static const struct backlight_ops nv50_bl_ops = {
 	.update_status = nv50_set_intensity,
 };
 
-static int nouveau_nv40_backlight_init(struct drm_device *dev)
+static int nouveau_nv40_backlight_init(struct drm_connector *connector)
 {
-	struct backlight_properties props;
+	struct drm_device *dev = connector->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct backlight_properties props;
 	struct backlight_device *bd;
 
 	if (!(nv_rd32(dev, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK))
@@ -100,7 +101,7 @@ static int nouveau_nv40_backlight_init(struct drm_device *dev)
 	memset(&props, 0, sizeof(struct backlight_properties));
 	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 31;
-	bd = backlight_device_register("nv_backlight", &dev->pdev->dev, dev,
+	bd = backlight_device_register("nv_backlight", &connector->kdev, dev,
 				       &nv40_bl_ops, &props);
 	if (IS_ERR(bd))
 		return PTR_ERR(bd);
@@ -112,10 +113,11 @@ static int nouveau_nv40_backlight_init(struct drm_device *dev)
 	return 0;
 }
 
-static int nouveau_nv50_backlight_init(struct drm_device *dev)
+static int nouveau_nv50_backlight_init(struct drm_connector *connector)
 {
-	struct backlight_properties props;
+	struct drm_device *dev = connector->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct backlight_properties props;
 	struct backlight_device *bd;
 
 	if (!nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT))
@@ -124,7 +126,7 @@ static int nouveau_nv50_backlight_init(struct drm_device *dev)
 	memset(&props, 0, sizeof(struct backlight_properties));
 	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 1025;
-	bd = backlight_device_register("nv_backlight", &dev->pdev->dev, dev,
+	bd = backlight_device_register("nv_backlight", &connector->kdev, dev,
 				       &nv50_bl_ops, &props);
 	if (IS_ERR(bd))
 		return PTR_ERR(bd);
@@ -135,8 +137,9 @@ static int nouveau_nv50_backlight_init(struct drm_device *dev)
 	return 0;
 }
 
-int nouveau_backlight_init(struct drm_device *dev)
+int nouveau_backlight_init(struct drm_connector *connector)
 {
+	struct drm_device *dev = connector->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 
 #ifdef CONFIG_ACPI
@@ -149,9 +152,9 @@ int nouveau_backlight_init(struct drm_device *dev)
 
 	switch (dev_priv->card_type) {
 	case NV_40:
-		return nouveau_nv40_backlight_init(dev);
+		return nouveau_nv40_backlight_init(connector);
 	case NV_50:
-		return nouveau_nv50_backlight_init(dev);
+		return nouveau_nv50_backlight_init(connector);
 	default:
 		break;
 	}
@@ -159,8 +162,9 @@ int nouveau_backlight_init(struct drm_device *dev)
 	return 0;
 }
 
-void nouveau_backlight_exit(struct drm_device *dev)
+void nouveau_backlight_exit(struct drm_connector *connector)
 {
+	struct drm_device *dev = connector->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 
 	if (dev_priv->backlight) {
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index a21e000..3a1ecc7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -116,6 +116,10 @@ nouveau_connector_destroy(struct drm_connector *connector)
 				      nouveau_connector_hotplug, connector);
 	}
 
+	if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
+	    connector->connector_type == DRM_MODE_CONNECTOR_eDP)
+		nouveau_backlight_exit(connector);
+
 	kfree(nv_connector->edid);
 	drm_sysfs_connector_remove(connector);
 	drm_connector_cleanup(connector);
@@ -893,6 +897,11 @@ nouveau_connector_create(struct drm_device *dev, int index)
 	}
 
 	drm_sysfs_connector_add(connector);
+
+	if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
+	    connector->connector_type == DRM_MODE_CONNECTOR_eDP)
+		nouveau_backlight_init(connector);
+
 	dcb->drm = connector;
 	return dcb->drm;
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 46e3257..1918ed1 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -999,15 +999,15 @@ static inline int nouveau_acpi_edid(struct drm_device *dev, struct drm_connector
 
 /* nouveau_backlight.c */
 #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
-extern int nouveau_backlight_init(struct drm_device *);
-extern void nouveau_backlight_exit(struct drm_device *);
+extern int nouveau_backlight_init(struct drm_connector *);
+extern void nouveau_backlight_exit(struct drm_connector *);
 #else
-static inline int nouveau_backlight_init(struct drm_device *dev)
+static inline int nouveau_backlight_init(struct drm_connector *dev)
 {
 	return 0;
 }
 
-static inline void nouveau_backlight_exit(struct drm_device *dev) { }
+static inline void nouveau_backlight_exit(struct drm_connector *dev) { }
 #endif
 
 /* nouveau_bios.c */
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
index a54fc43..f688f04 100644
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -738,10 +738,6 @@ nouveau_card_init(struct drm_device *dev)
 			goto out_fence;
 	}
 
-	ret = nouveau_backlight_init(dev);
-	if (ret)
-		NV_ERROR(dev, "Error %d registering backlight\n", ret);
-
 	nouveau_fbcon_init(dev);
 	drm_kms_helper_poll_init(dev);
 	return 0;
@@ -793,8 +789,6 @@ static void nouveau_card_takedown(struct drm_device *dev)
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_engine *engine = &dev_priv->engine;
 
-	nouveau_backlight_exit(dev);
-
 	if (!engine->graph.accel_blocked) {
 		nouveau_fence_fini(dev);
 		nouveau_channel_put_unlocked(&dev_priv->channel);
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 5/5] ACPI: Tie ACPI backlight devices to PCI devices if possible
  2011-01-14 19:24 [PATCH 1/5] Backlight: Add backlight type Matthew Garrett
                   ` (2 preceding siblings ...)
  2011-01-14 19:24 ` [PATCH 4/5] nouveau: Change the backlight parent device to the connector, not the PCI dev Matthew Garrett
@ 2011-01-14 19:24 ` Matthew Garrett
  2011-02-06 20:35   ` Rafael J. Wysocki
  3 siblings, 1 reply; 40+ messages in thread
From: Matthew Garrett @ 2011-01-14 19:24 UTC (permalink / raw)
  To: akpm
  Cc: intel-gfx, dri-devel, linux-acpi, linux-kernel, rpurdie, Matthew Garrett

Dual-GPU machines may provide more than one ACPI backlight interface. Tie
the backlight device to the GPU in order to allow userspace to identify
the correct interface.

Signed-off-by: Matthew Garrett <mjg@redhat.com>
---
 drivers/acpi/video.c |   15 ++++++++++++++-
 1 files changed, 14 insertions(+), 1 deletions(-)

diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index a9eec8c..a18e497 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -782,6 +782,9 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
 
 	if (acpi_video_backlight_support()) {
 		struct backlight_properties props;
+		struct pci_dev *pdev;
+		acpi_handle acpi_parent;
+		struct device *parent = NULL;
 		int result;
 		static int count = 0;
 		char *name;
@@ -794,10 +797,20 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
 			return;
 		count++;
 
+		acpi_get_parent(device->dev->handle, &acpi_parent);
+
+		pdev = acpi_get_pci_dev(acpi_parent);
+		if (pdev) {
+			parent = &pdev->dev;
+			pci_dev_put(pdev);
+		}
+
 		memset(&props, 0, sizeof(struct backlight_properties));
 		props.type = BACKLIGHT_FIRMWARE;
 		props.max_brightness = device->brightness->count - 3;
-		device->backlight = backlight_device_register(name, NULL, device,
+		device->backlight = backlight_device_register(name,
+							      parent,
+							      device,
 							      &acpi_backlight_ops,
 							      &props);
 		kfree(name);
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* Re: [PATCH 4/5] nouveau: Change the backlight parent device to the connector, not the PCI dev
  2011-01-14 19:24 ` [PATCH 4/5] nouveau: Change the backlight parent device to the connector, not the PCI dev Matthew Garrett
@ 2011-01-14 19:30     ` Anca Emanuel
  2011-01-15  9:49   ` Ben Skeggs
  1 sibling, 0 replies; 40+ messages in thread
From: Anca Emanuel @ 2011-01-14 19:30 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: akpm, intel-gfx, dri-devel, linux-acpi, linux-kernel, rpurdie

On Fri, Jan 14, 2011 at 9:24 PM, Matthew Garrett <mjg@redhat.com> wrote:
> We may eventually end up with per-connector backlights, especially with
> ddcci devices. Make sure that the parent node for the backlight device is
> the connector rather than the PCI device.
>
> Signed-off-by: Matthew Garrett <mjg@redhat.com>
> ---
>  drivers/gpu/drm/nouveau/nouveau_backlight.c |   24 ++++++++++++++----------
>  drivers/gpu/drm/nouveau/nouveau_connector.c |    9 +++++++++
>  drivers/gpu/drm/nouveau/nouveau_drv.h       |    8 ++++----
>  drivers/gpu/drm/nouveau/nouveau_state.c     |    6 ------
>  4 files changed, 27 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
> index 18d7bcc..00a55df 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
> @@ -88,10 +88,11 @@ static const struct backlight_ops nv50_bl_ops = {
>        .update_status = nv50_set_intensity,
>  };
>
> -static int nouveau_nv40_backlight_init(struct drm_device *dev)
> +static int nouveau_nv40_backlight_init(struct drm_connector *connector)
>  {
> -       struct backlight_properties props;
> +       struct drm_device *dev = connector->dev;
>        struct drm_nouveau_private *dev_priv = dev->dev_private;
> +       struct backlight_properties props;
>        struct backlight_device *bd;
>
>        if (!(nv_rd32(dev, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK))
> @@ -100,7 +101,7 @@ static int nouveau_nv40_backlight_init(struct drm_device *dev)
>        memset(&props, 0, sizeof(struct backlight_properties));
>        props.type = BACKLIGHT_RAW;
>        props.max_brightness = 31;
> -       bd = backlight_device_register("nv_backlight", &dev->pdev->dev, dev,
> +       bd = backlight_device_register("nv_backlight", &connector->kdev, dev,
>                                       &nv40_bl_ops, &props);
>        if (IS_ERR(bd))
>                return PTR_ERR(bd);
> @@ -112,10 +113,11 @@ static int nouveau_nv40_backlight_init(struct drm_device *dev)
>        return 0;
>  }
>
> -static int nouveau_nv50_backlight_init(struct drm_device *dev)
> +static int nouveau_nv50_backlight_init(struct drm_connector *connector)
>  {
> -       struct backlight_properties props;
> +       struct drm_device *dev = connector->dev;
>        struct drm_nouveau_private *dev_priv = dev->dev_private;
> +       struct backlight_properties props;
>        struct backlight_device *bd;
>
>        if (!nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT))
> @@ -124,7 +126,7 @@ static int nouveau_nv50_backlight_init(struct drm_device *dev)
>        memset(&props, 0, sizeof(struct backlight_properties));
>        props.type = BACKLIGHT_RAW;
>        props.max_brightness = 1025;
> -       bd = backlight_device_register("nv_backlight", &dev->pdev->dev, dev,
> +       bd = backlight_device_register("nv_backlight", &connector->kdev, dev,
>                                       &nv50_bl_ops, &props);
>        if (IS_ERR(bd))
>                return PTR_ERR(bd);
> @@ -135,8 +137,9 @@ static int nouveau_nv50_backlight_init(struct drm_device *dev)
>        return 0;
>  }
>
> -int nouveau_backlight_init(struct drm_device *dev)
> +int nouveau_backlight_init(struct drm_connector *connector)
>  {
> +       struct drm_device *dev = connector->dev;
>        struct drm_nouveau_private *dev_priv = dev->dev_private;
>
>  #ifdef CONFIG_ACPI
> @@ -149,9 +152,9 @@ int nouveau_backlight_init(struct drm_device *dev)
>
>        switch (dev_priv->card_type) {
>        case NV_40:
> -               return nouveau_nv40_backlight_init(dev);
> +               return nouveau_nv40_backlight_init(connector);
>        case NV_50:
> -               return nouveau_nv50_backlight_init(dev);
> +               return nouveau_nv50_backlight_init(connector);
>        default:
>                break;
>        }
> @@ -159,8 +162,9 @@ int nouveau_backlight_init(struct drm_device *dev)
>        return 0;
>  }
>
> -void nouveau_backlight_exit(struct drm_device *dev)
> +void nouveau_backlight_exit(struct drm_connector *connector)
>  {
> +       struct drm_device *dev = connector->dev;
>        struct drm_nouveau_private *dev_priv = dev->dev_private;
>
>        if (dev_priv->backlight) {
> diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
> index a21e000..3a1ecc7 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_connector.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
> @@ -116,6 +116,10 @@ nouveau_connector_destroy(struct drm_connector *connector)
>                                      nouveau_connector_hotplug, connector);
>        }
>
> +       if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
> +           connector->connector_type == DRM_MODE_CONNECTOR_eDP)
> +               nouveau_backlight_exit(connector);
> +
>        kfree(nv_connector->edid);
>        drm_sysfs_connector_remove(connector);
>        drm_connector_cleanup(connector);
> @@ -893,6 +897,11 @@ nouveau_connector_create(struct drm_device *dev, int index)
>        }
>
>        drm_sysfs_connector_add(connector);
> +
> +       if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
> +           connector->connector_type == DRM_MODE_CONNECTOR_eDP)
> +               nouveau_backlight_init(connector);
> +
>        dcb->drm = connector;
>        return dcb->drm;
>
> diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
> index 46e3257..1918ed1 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_drv.h
> +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
> @@ -999,15 +999,15 @@ static inline int nouveau_acpi_edid(struct drm_device *dev, struct drm_connector
>
>  /* nouveau_backlight.c */
>  #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
> -extern int nouveau_backlight_init(struct drm_device *);
> -extern void nouveau_backlight_exit(struct drm_device *);
> +extern int nouveau_backlight_init(struct drm_connector *);
> +extern void nouveau_backlight_exit(struct drm_connector *);
>  #else
> -static inline int nouveau_backlight_init(struct drm_device *dev)
> +static inline int nouveau_backlight_init(struct drm_connector *dev)
>  {
>        return 0;
>  }
>
> -static inline void nouveau_backlight_exit(struct drm_device *dev) { }
> +static inline void nouveau_backlight_exit(struct drm_connector *dev) { }
>  #endif
>
>  /* nouveau_bios.c */
> diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
> index a54fc43..f688f04 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_state.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_state.c
> @@ -738,10 +738,6 @@ nouveau_card_init(struct drm_device *dev)
>                        goto out_fence;
>        }
>
> -       ret = nouveau_backlight_init(dev);
> -       if (ret)
> -               NV_ERROR(dev, "Error %d registering backlight\n", ret);
> -
>        nouveau_fbcon_init(dev);
>        drm_kms_helper_poll_init(dev);
>        return 0;
> @@ -793,8 +789,6 @@ static void nouveau_card_takedown(struct drm_device *dev)
>        struct drm_nouveau_private *dev_priv = dev->dev_private;
>        struct nouveau_engine *engine = &dev_priv->engine;
>
> -       nouveau_backlight_exit(dev);
> -
>        if (!engine->graph.accel_blocked) {
>                nouveau_fence_fini(dev);
>                nouveau_channel_put_unlocked(&dev_priv->channel);
> --
> 1.7.3.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
>

Hi Matthew Garrett,
I have problems with nouveau.
Do you know ?
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 4/5] nouveau: Change the backlight parent device to the connector, not the PCI dev
@ 2011-01-14 19:30     ` Anca Emanuel
  0 siblings, 0 replies; 40+ messages in thread
From: Anca Emanuel @ 2011-01-14 19:30 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: akpm, intel-gfx, dri-devel, linux-acpi, linux-kernel, rpurdie

On Fri, Jan 14, 2011 at 9:24 PM, Matthew Garrett <mjg@redhat.com> wrote:
> We may eventually end up with per-connector backlights, especially with
> ddcci devices. Make sure that the parent node for the backlight device is
> the connector rather than the PCI device.
>
> Signed-off-by: Matthew Garrett <mjg@redhat.com>
> ---
>  drivers/gpu/drm/nouveau/nouveau_backlight.c |   24 ++++++++++++++----------
>  drivers/gpu/drm/nouveau/nouveau_connector.c |    9 +++++++++
>  drivers/gpu/drm/nouveau/nouveau_drv.h       |    8 ++++----
>  drivers/gpu/drm/nouveau/nouveau_state.c     |    6 ------
>  4 files changed, 27 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
> index 18d7bcc..00a55df 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
> @@ -88,10 +88,11 @@ static const struct backlight_ops nv50_bl_ops = {
>        .update_status = nv50_set_intensity,
>  };
>
> -static int nouveau_nv40_backlight_init(struct drm_device *dev)
> +static int nouveau_nv40_backlight_init(struct drm_connector *connector)
>  {
> -       struct backlight_properties props;
> +       struct drm_device *dev = connector->dev;
>        struct drm_nouveau_private *dev_priv = dev->dev_private;
> +       struct backlight_properties props;
>        struct backlight_device *bd;
>
>        if (!(nv_rd32(dev, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK))
> @@ -100,7 +101,7 @@ static int nouveau_nv40_backlight_init(struct drm_device *dev)
>        memset(&props, 0, sizeof(struct backlight_properties));
>        props.type = BACKLIGHT_RAW;
>        props.max_brightness = 31;
> -       bd = backlight_device_register("nv_backlight", &dev->pdev->dev, dev,
> +       bd = backlight_device_register("nv_backlight", &connector->kdev, dev,
>                                       &nv40_bl_ops, &props);
>        if (IS_ERR(bd))
>                return PTR_ERR(bd);
> @@ -112,10 +113,11 @@ static int nouveau_nv40_backlight_init(struct drm_device *dev)
>        return 0;
>  }
>
> -static int nouveau_nv50_backlight_init(struct drm_device *dev)
> +static int nouveau_nv50_backlight_init(struct drm_connector *connector)
>  {
> -       struct backlight_properties props;
> +       struct drm_device *dev = connector->dev;
>        struct drm_nouveau_private *dev_priv = dev->dev_private;
> +       struct backlight_properties props;
>        struct backlight_device *bd;
>
>        if (!nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT))
> @@ -124,7 +126,7 @@ static int nouveau_nv50_backlight_init(struct drm_device *dev)
>        memset(&props, 0, sizeof(struct backlight_properties));
>        props.type = BACKLIGHT_RAW;
>        props.max_brightness = 1025;
> -       bd = backlight_device_register("nv_backlight", &dev->pdev->dev, dev,
> +       bd = backlight_device_register("nv_backlight", &connector->kdev, dev,
>                                       &nv50_bl_ops, &props);
>        if (IS_ERR(bd))
>                return PTR_ERR(bd);
> @@ -135,8 +137,9 @@ static int nouveau_nv50_backlight_init(struct drm_device *dev)
>        return 0;
>  }
>
> -int nouveau_backlight_init(struct drm_device *dev)
> +int nouveau_backlight_init(struct drm_connector *connector)
>  {
> +       struct drm_device *dev = connector->dev;
>        struct drm_nouveau_private *dev_priv = dev->dev_private;
>
>  #ifdef CONFIG_ACPI
> @@ -149,9 +152,9 @@ int nouveau_backlight_init(struct drm_device *dev)
>
>        switch (dev_priv->card_type) {
>        case NV_40:
> -               return nouveau_nv40_backlight_init(dev);
> +               return nouveau_nv40_backlight_init(connector);
>        case NV_50:
> -               return nouveau_nv50_backlight_init(dev);
> +               return nouveau_nv50_backlight_init(connector);
>        default:
>                break;
>        }
> @@ -159,8 +162,9 @@ int nouveau_backlight_init(struct drm_device *dev)
>        return 0;
>  }
>
> -void nouveau_backlight_exit(struct drm_device *dev)
> +void nouveau_backlight_exit(struct drm_connector *connector)
>  {
> +       struct drm_device *dev = connector->dev;
>        struct drm_nouveau_private *dev_priv = dev->dev_private;
>
>        if (dev_priv->backlight) {
> diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
> index a21e000..3a1ecc7 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_connector.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
> @@ -116,6 +116,10 @@ nouveau_connector_destroy(struct drm_connector *connector)
>                                      nouveau_connector_hotplug, connector);
>        }
>
> +       if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
> +           connector->connector_type == DRM_MODE_CONNECTOR_eDP)
> +               nouveau_backlight_exit(connector);
> +
>        kfree(nv_connector->edid);
>        drm_sysfs_connector_remove(connector);
>        drm_connector_cleanup(connector);
> @@ -893,6 +897,11 @@ nouveau_connector_create(struct drm_device *dev, int index)
>        }
>
>        drm_sysfs_connector_add(connector);
> +
> +       if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
> +           connector->connector_type == DRM_MODE_CONNECTOR_eDP)
> +               nouveau_backlight_init(connector);
> +
>        dcb->drm = connector;
>        return dcb->drm;
>
> diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
> index 46e3257..1918ed1 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_drv.h
> +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
> @@ -999,15 +999,15 @@ static inline int nouveau_acpi_edid(struct drm_device *dev, struct drm_connector
>
>  /* nouveau_backlight.c */
>  #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
> -extern int nouveau_backlight_init(struct drm_device *);
> -extern void nouveau_backlight_exit(struct drm_device *);
> +extern int nouveau_backlight_init(struct drm_connector *);
> +extern void nouveau_backlight_exit(struct drm_connector *);
>  #else
> -static inline int nouveau_backlight_init(struct drm_device *dev)
> +static inline int nouveau_backlight_init(struct drm_connector *dev)
>  {
>        return 0;
>  }
>
> -static inline void nouveau_backlight_exit(struct drm_device *dev) { }
> +static inline void nouveau_backlight_exit(struct drm_connector *dev) { }
>  #endif
>
>  /* nouveau_bios.c */
> diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
> index a54fc43..f688f04 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_state.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_state.c
> @@ -738,10 +738,6 @@ nouveau_card_init(struct drm_device *dev)
>                        goto out_fence;
>        }
>
> -       ret = nouveau_backlight_init(dev);
> -       if (ret)
> -               NV_ERROR(dev, "Error %d registering backlight\n", ret);
> -
>        nouveau_fbcon_init(dev);
>        drm_kms_helper_poll_init(dev);
>        return 0;
> @@ -793,8 +789,6 @@ static void nouveau_card_takedown(struct drm_device *dev)
>        struct drm_nouveau_private *dev_priv = dev->dev_private;
>        struct nouveau_engine *engine = &dev_priv->engine;
>
> -       nouveau_backlight_exit(dev);
> -
>        if (!engine->graph.accel_blocked) {
>                nouveau_fence_fini(dev);
>                nouveau_channel_put_unlocked(&dev_priv->channel);
> --
> 1.7.3.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
>

Hi Matthew Garrett,
I have problems with nouveau.
Do you know ?

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 4/5] nouveau: Change the backlight parent device to the connector, not the PCI dev
  2011-01-14 19:30     ` Anca Emanuel
  (?)
@ 2011-01-14 20:20     ` Matthew Garrett
  -1 siblings, 0 replies; 40+ messages in thread
From: Matthew Garrett @ 2011-01-14 20:20 UTC (permalink / raw)
  To: Anca Emanuel
  Cc: akpm, intel-gfx, dri-devel, linux-acpi, linux-kernel, rpurdie

On Fri, Jan 14, 2011 at 09:30:19PM +0200, Anca Emanuel wrote:

> Hi Matthew Garrett,
> I have problems with nouveau.
> Do you know ?

Your best bet is to follow the instructions on 
http://nouveau.freedesktop.org/wiki/Bugs to report a bug.

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 4/5] nouveau: Change the backlight parent device to the connector, not the PCI dev
  2011-01-14 19:24 ` [PATCH 4/5] nouveau: Change the backlight parent device to the connector, not the PCI dev Matthew Garrett
  2011-01-14 19:30     ` Anca Emanuel
@ 2011-01-15  9:49   ` Ben Skeggs
  1 sibling, 0 replies; 40+ messages in thread
From: Ben Skeggs @ 2011-01-15  9:49 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: akpm, intel-gfx, linux-kernel, dri-devel, linux-acpi, rpurdie

On Fri, 2011-01-14 at 14:24 -0500, Matthew Garrett wrote:
> We may eventually end up with per-connector backlights, especially with
> ddcci devices. Make sure that the parent node for the backlight device is
> the connector rather than the PCI device.
> 
> Signed-off-by: Matthew Garrett <mjg@redhat.com>
Acked-by: Ben Skeggs <bskeggs@redhat.com>

> ---
>  drivers/gpu/drm/nouveau/nouveau_backlight.c |   24 ++++++++++++++----------
>  drivers/gpu/drm/nouveau/nouveau_connector.c |    9 +++++++++
>  drivers/gpu/drm/nouveau/nouveau_drv.h       |    8 ++++----
>  drivers/gpu/drm/nouveau/nouveau_state.c     |    6 ------
>  4 files changed, 27 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
> index 18d7bcc..00a55df 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
> @@ -88,10 +88,11 @@ static const struct backlight_ops nv50_bl_ops = {
>  	.update_status = nv50_set_intensity,
>  };
>  
> -static int nouveau_nv40_backlight_init(struct drm_device *dev)
> +static int nouveau_nv40_backlight_init(struct drm_connector *connector)
>  {
> -	struct backlight_properties props;
> +	struct drm_device *dev = connector->dev;
>  	struct drm_nouveau_private *dev_priv = dev->dev_private;
> +	struct backlight_properties props;
>  	struct backlight_device *bd;
>  
>  	if (!(nv_rd32(dev, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK))
> @@ -100,7 +101,7 @@ static int nouveau_nv40_backlight_init(struct drm_device *dev)
>  	memset(&props, 0, sizeof(struct backlight_properties));
>  	props.type = BACKLIGHT_RAW;
>  	props.max_brightness = 31;
> -	bd = backlight_device_register("nv_backlight", &dev->pdev->dev, dev,
> +	bd = backlight_device_register("nv_backlight", &connector->kdev, dev,
>  				       &nv40_bl_ops, &props);
>  	if (IS_ERR(bd))
>  		return PTR_ERR(bd);
> @@ -112,10 +113,11 @@ static int nouveau_nv40_backlight_init(struct drm_device *dev)
>  	return 0;
>  }
>  
> -static int nouveau_nv50_backlight_init(struct drm_device *dev)
> +static int nouveau_nv50_backlight_init(struct drm_connector *connector)
>  {
> -	struct backlight_properties props;
> +	struct drm_device *dev = connector->dev;
>  	struct drm_nouveau_private *dev_priv = dev->dev_private;
> +	struct backlight_properties props;
>  	struct backlight_device *bd;
>  
>  	if (!nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT))
> @@ -124,7 +126,7 @@ static int nouveau_nv50_backlight_init(struct drm_device *dev)
>  	memset(&props, 0, sizeof(struct backlight_properties));
>  	props.type = BACKLIGHT_RAW;
>  	props.max_brightness = 1025;
> -	bd = backlight_device_register("nv_backlight", &dev->pdev->dev, dev,
> +	bd = backlight_device_register("nv_backlight", &connector->kdev, dev,
>  				       &nv50_bl_ops, &props);
>  	if (IS_ERR(bd))
>  		return PTR_ERR(bd);
> @@ -135,8 +137,9 @@ static int nouveau_nv50_backlight_init(struct drm_device *dev)
>  	return 0;
>  }
>  
> -int nouveau_backlight_init(struct drm_device *dev)
> +int nouveau_backlight_init(struct drm_connector *connector)
>  {
> +	struct drm_device *dev = connector->dev;
>  	struct drm_nouveau_private *dev_priv = dev->dev_private;
>  
>  #ifdef CONFIG_ACPI
> @@ -149,9 +152,9 @@ int nouveau_backlight_init(struct drm_device *dev)
>  
>  	switch (dev_priv->card_type) {
>  	case NV_40:
> -		return nouveau_nv40_backlight_init(dev);
> +		return nouveau_nv40_backlight_init(connector);
>  	case NV_50:
> -		return nouveau_nv50_backlight_init(dev);
> +		return nouveau_nv50_backlight_init(connector);
>  	default:
>  		break;
>  	}
> @@ -159,8 +162,9 @@ int nouveau_backlight_init(struct drm_device *dev)
>  	return 0;
>  }
>  
> -void nouveau_backlight_exit(struct drm_device *dev)
> +void nouveau_backlight_exit(struct drm_connector *connector)
>  {
> +	struct drm_device *dev = connector->dev;
>  	struct drm_nouveau_private *dev_priv = dev->dev_private;
>  
>  	if (dev_priv->backlight) {
> diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
> index a21e000..3a1ecc7 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_connector.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
> @@ -116,6 +116,10 @@ nouveau_connector_destroy(struct drm_connector *connector)
>  				      nouveau_connector_hotplug, connector);
>  	}
>  
> +	if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
> +	    connector->connector_type == DRM_MODE_CONNECTOR_eDP)
> +		nouveau_backlight_exit(connector);
> +
>  	kfree(nv_connector->edid);
>  	drm_sysfs_connector_remove(connector);
>  	drm_connector_cleanup(connector);
> @@ -893,6 +897,11 @@ nouveau_connector_create(struct drm_device *dev, int index)
>  	}
>  
>  	drm_sysfs_connector_add(connector);
> +
> +	if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
> +	    connector->connector_type == DRM_MODE_CONNECTOR_eDP)
> +		nouveau_backlight_init(connector);
> +
>  	dcb->drm = connector;
>  	return dcb->drm;
>  
> diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
> index 46e3257..1918ed1 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_drv.h
> +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
> @@ -999,15 +999,15 @@ static inline int nouveau_acpi_edid(struct drm_device *dev, struct drm_connector
>  
>  /* nouveau_backlight.c */
>  #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
> -extern int nouveau_backlight_init(struct drm_device *);
> -extern void nouveau_backlight_exit(struct drm_device *);
> +extern int nouveau_backlight_init(struct drm_connector *);
> +extern void nouveau_backlight_exit(struct drm_connector *);
>  #else
> -static inline int nouveau_backlight_init(struct drm_device *dev)
> +static inline int nouveau_backlight_init(struct drm_connector *dev)
>  {
>  	return 0;
>  }
>  
> -static inline void nouveau_backlight_exit(struct drm_device *dev) { }
> +static inline void nouveau_backlight_exit(struct drm_connector *dev) { }
>  #endif
>  
>  /* nouveau_bios.c */
> diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
> index a54fc43..f688f04 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_state.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_state.c
> @@ -738,10 +738,6 @@ nouveau_card_init(struct drm_device *dev)
>  			goto out_fence;
>  	}
>  
> -	ret = nouveau_backlight_init(dev);
> -	if (ret)
> -		NV_ERROR(dev, "Error %d registering backlight\n", ret);
> -
>  	nouveau_fbcon_init(dev);
>  	drm_kms_helper_poll_init(dev);
>  	return 0;
> @@ -793,8 +789,6 @@ static void nouveau_card_takedown(struct drm_device *dev)
>  	struct drm_nouveau_private *dev_priv = dev->dev_private;
>  	struct nouveau_engine *engine = &dev_priv->engine;
>  
> -	nouveau_backlight_exit(dev);
> -
>  	if (!engine->graph.accel_blocked) {
>  		nouveau_fence_fini(dev);
>  		nouveau_channel_put_unlocked(&dev_priv->channel);



^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 3/5] radeon: Expose backlight class device for legacy LVDS encoder
  2011-01-14 19:24 ` [PATCH 3/5] radeon: Expose backlight class device for legacy LVDS encoder Matthew Garrett
@ 2011-01-15 17:34     ` Alex Deucher
  2011-01-20  2:12     ` Andrew Morton
  1 sibling, 0 replies; 40+ messages in thread
From: Alex Deucher @ 2011-01-15 17:34 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: akpm, Michel Dänzer, linux-kernel, dri-devel, linux-acpi,
	rpurdie, Michel Dänzer, intel-gfx

On Fri, Jan 14, 2011 at 2:24 PM, Matthew Garrett <mjg@redhat.com> wrote:
> From: Michel Dänzer <michel@daenzer.net>
>
> Allows e.g. power management daemons to control the backlight level. Inspired
> by the corresponding code in radeonfb.
>
> (Updated to add backlight type and make the connector the parent device - mjg)
>
> Signed-off-by: Michel Dänzer <daenzer@vmware.com>
> Signed-off-by: Matthew Garrett <mjg@redhat.com>

Acked-by: Alex Deucher <alexdeucher@gmail.com>

> Cc: dri-devel@lists.freedesktop.org
> ---
>  drivers/gpu/drm/radeon/Kconfig                  |    1 +
>  drivers/gpu/drm/radeon/radeon_connectors.c      |   15 ++
>  drivers/gpu/drm/radeon/radeon_legacy_encoders.c |  257 ++++++++++++++++++++++-
>  drivers/gpu/drm/radeon/radeon_mode.h            |   10 +
>  4 files changed, 277 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/Kconfig b/drivers/gpu/drm/radeon/Kconfig
> index 1c02d23..9746fee 100644
> --- a/drivers/gpu/drm/radeon/Kconfig
> +++ b/drivers/gpu/drm/radeon/Kconfig
> @@ -1,6 +1,7 @@
>  config DRM_RADEON_KMS
>        bool "Enable modesetting on radeon by default - NEW DRIVER"
>        depends on DRM_RADEON
> +       select BACKLIGHT_CLASS_DEVICE
>        help
>          Choose this option if you want kernel modesetting enabled by default.
>
> diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
> index 22b7e3d..e842fb5 100644
> --- a/drivers/gpu/drm/radeon/radeon_connectors.c
> +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
> @@ -40,6 +40,10 @@ radeon_atombios_connected_scratch_regs(struct drm_connector *connector,
>                                       struct drm_encoder *encoder,
>                                       bool connected);
>
> +extern void
> +radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
> +                            struct drm_connector *drm_connector);
> +
>  void radeon_connector_hotplug(struct drm_connector *connector)
>  {
>        struct drm_device *dev = connector->dev;
> @@ -1517,6 +1521,17 @@ radeon_add_legacy_connector(struct drm_device *dev,
>                connector->polled = DRM_CONNECTOR_POLL_HPD;
>        connector->display_info.subpixel_order = subpixel_order;
>        drm_sysfs_connector_add(connector);
> +       if (connector_type == DRM_MODE_CONNECTOR_LVDS) {
> +               struct drm_encoder *drm_encoder;
> +
> +               list_for_each_entry(drm_encoder, &dev->mode_config.encoder_list, head) {
> +                       struct radeon_encoder *radeon_encoder;
> +
> +                       radeon_encoder = to_radeon_encoder(drm_encoder);
> +                       if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_LVDS)
> +                               radeon_legacy_backlight_init(radeon_encoder, connector);
> +               }
> +       }
>        return;
>
>  failed:
> diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
> index 59f834b..ba7dcc6 100644
> --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
> +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
> @@ -28,6 +28,10 @@
>  #include "radeon_drm.h"
>  #include "radeon.h"
>  #include "atom.h"
> +#include <linux/backlight.h>
> +#ifdef CONFIG_PMAC_BACKLIGHT
> +#include <asm/backlight.h>
> +#endif
>
>  static void radeon_legacy_encoder_disable(struct drm_encoder *encoder)
>  {
> @@ -39,7 +43,7 @@ static void radeon_legacy_encoder_disable(struct drm_encoder *encoder)
>        radeon_encoder->active_device = 0;
>  }
>
> -static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
> +static void radeon_legacy_lvds_update(struct drm_encoder *encoder, int mode)
>  {
>        struct drm_device *dev = encoder->dev;
>        struct radeon_device *rdev = dev->dev_private;
> @@ -47,15 +51,23 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
>        uint32_t lvds_gen_cntl, lvds_pll_cntl, pixclks_cntl, disp_pwr_man;
>        int panel_pwr_delay = 2000;
>        bool is_mac = false;
> +       uint8_t backlight_level;
>        DRM_DEBUG_KMS("\n");
>
> +       lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
> +       backlight_level = (lvds_gen_cntl >> RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
> +
>        if (radeon_encoder->enc_priv) {
>                if (rdev->is_atom_bios) {
>                        struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
>                        panel_pwr_delay = lvds->panel_pwr_delay;
> +                       if (lvds->bl_dev)
> +                               backlight_level = lvds->backlight_level;
>                } else {
>                        struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
>                        panel_pwr_delay = lvds->panel_pwr_delay;
> +                       if (lvds->bl_dev)
> +                               backlight_level = lvds->backlight_level;
>                }
>        }
>
> @@ -82,11 +94,13 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
>                lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET;
>                WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
>
> -               lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
> -               lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN | RADEON_LVDS_DIGON | RADEON_LVDS_BLON);
> +               lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS |
> +                                  RADEON_LVDS_BL_MOD_LEVEL_MASK);
> +               lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN |
> +                                 RADEON_LVDS_DIGON | RADEON_LVDS_BLON |
> +                                 (backlight_level << RADEON_LVDS_BL_MOD_LEVEL_SHIFT));
>                if (is_mac)
>                        lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN;
> -               lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS);
>                udelay(panel_pwr_delay * 1000);
>                WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
>                break;
> @@ -95,7 +109,6 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
>        case DRM_MODE_DPMS_OFF:
>                pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
>                WREG32_PLL_P(RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb);
> -               lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
>                lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
>                if (is_mac) {
>                        lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_EN;
> @@ -119,6 +132,25 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
>
>  }
>
> +static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
> +{
> +       struct radeon_device *rdev = encoder->dev->dev_private;
> +       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
> +       DRM_DEBUG("\n");
> +
> +       if (radeon_encoder->enc_priv) {
> +               if (rdev->is_atom_bios) {
> +                       struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
> +                       lvds->dpms_mode = mode;
> +               } else {
> +                       struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
> +                       lvds->dpms_mode = mode;
> +               }
> +       }
> +
> +       radeon_legacy_lvds_update(encoder, mode);
> +}
> +
>  static void radeon_legacy_lvds_prepare(struct drm_encoder *encoder)
>  {
>        struct radeon_device *rdev = encoder->dev->dev_private;
> @@ -237,9 +269,222 @@ static const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = {
>        .disable = radeon_legacy_encoder_disable,
>  };
>
> +#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
> +
> +#define MAX_RADEON_LEVEL 0xFF
> +
> +struct radeon_backlight_privdata {
> +       struct radeon_encoder *encoder;
> +       uint8_t negative;
> +};
> +
> +static uint8_t radeon_legacy_lvds_level(struct backlight_device *bd)
> +{
> +       struct radeon_backlight_privdata *pdata = bl_get_data(bd);
> +       uint8_t level;
> +
> +       /* Convert brightness to hardware level */
> +       if (bd->props.brightness < 0)
> +               level = 0;
> +       else if (bd->props.brightness > MAX_RADEON_LEVEL)
> +               level = MAX_RADEON_LEVEL;
> +       else
> +               level = bd->props.brightness;
> +
> +       if (pdata->negative)
> +               level = MAX_RADEON_LEVEL - level;
> +
> +       return level;
> +}
> +
> +static int radeon_legacy_backlight_update_status(struct backlight_device *bd)
> +{
> +       struct radeon_backlight_privdata *pdata = bl_get_data(bd);
> +       struct radeon_encoder *radeon_encoder = pdata->encoder;
> +       struct drm_device *dev = radeon_encoder->base.dev;
> +       struct radeon_device *rdev = dev->dev_private;
> +       int dpms_mode = DRM_MODE_DPMS_ON;
> +
> +       if (radeon_encoder->enc_priv) {
> +               if (rdev->is_atom_bios) {
> +                       struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
> +                       dpms_mode = lvds->dpms_mode;
> +                       lvds->backlight_level = radeon_legacy_lvds_level(bd);
> +               } else {
> +                       struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
> +                       dpms_mode = lvds->dpms_mode;
> +                       lvds->backlight_level = radeon_legacy_lvds_level(bd);
> +               }
> +       }
> +
> +       if (bd->props.brightness > 0)
> +               radeon_legacy_lvds_update(&radeon_encoder->base, dpms_mode);
> +       else
> +               radeon_legacy_lvds_update(&radeon_encoder->base, DRM_MODE_DPMS_OFF);
> +
> +       return 0;
> +}
> +
> +static int radeon_legacy_backlight_get_brightness(struct backlight_device *bd)
> +{
> +       struct radeon_backlight_privdata *pdata = bl_get_data(bd);
> +       struct radeon_encoder *radeon_encoder = pdata->encoder;
> +       struct drm_device *dev = radeon_encoder->base.dev;
> +       struct radeon_device *rdev = dev->dev_private;
> +       uint8_t backlight_level;
> +
> +       backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >>
> +                          RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
> +
> +       return pdata->negative ? MAX_RADEON_LEVEL - backlight_level : backlight_level;
> +}
> +
> +static const struct backlight_ops radeon_backlight_ops = {
> +       .get_brightness = radeon_legacy_backlight_get_brightness,
> +       .update_status  = radeon_legacy_backlight_update_status,
> +};
> +
> +void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
> +                                 struct drm_connector *drm_connector)
> +{
> +       struct drm_device *dev = radeon_encoder->base.dev;
> +       struct radeon_device *rdev = dev->dev_private;
> +       struct backlight_device *bd;
> +       struct backlight_properties props;
> +       struct radeon_backlight_privdata *pdata;
> +       uint8_t backlight_level;
> +
> +       if (!radeon_encoder->enc_priv)
> +               return;
> +
> +#ifdef CONFIG_PMAC_BACKLIGHT
> +       if (!pmac_has_backlight_type("ati") &&
> +           !pmac_has_backlight_type("mnca"))
> +               return;
> +#endif
> +
> +       pdata = kmalloc(sizeof(struct radeon_backlight_privdata), GFP_KERNEL);
> +       if (!pdata) {
> +               DRM_ERROR("Memory allocation failed\n");
> +               goto error;
> +       }
> +
> +       props.max_brightness = MAX_RADEON_LEVEL;
> +       props.type = BACKLIGHT_RAW;
> +       bd = backlight_device_register("radeon_bl", &drm_connector->kdev,
> +                                      pdata, &radeon_backlight_ops, &props);
> +       if (IS_ERR(bd)) {
> +               DRM_ERROR("Backlight registration failed\n");
> +               goto error;
> +       }
> +
> +       pdata->encoder = radeon_encoder;
> +
> +       backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >>
> +                          RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
> +
> +       /* First, try to detect backlight level sense based on the assumption
> +        * that firmware set it up at full brightness
> +        */
> +       if (backlight_level == 0)
> +               pdata->negative = true;
> +       else if (backlight_level == 0xff)
> +               pdata->negative = false;
> +       else {
> +               /* XXX hack... maybe some day we can figure out in what direction
> +                * backlight should work on a given panel?
> +                */
> +               pdata->negative = (rdev->family != CHIP_RV200 &&
> +                                  rdev->family != CHIP_RV250 &&
> +                                  rdev->family != CHIP_RV280 &&
> +                                  rdev->family != CHIP_RV350);
> +
> +#ifdef CONFIG_PMAC_BACKLIGHT
> +               pdata->negative = (pdata->negative ||
> +                                  of_machine_is_compatible("PowerBook4,3") ||
> +                                  of_machine_is_compatible("PowerBook6,3") ||
> +                                  of_machine_is_compatible("PowerBook6,5"));
> +#endif
> +       }
> +
> +       if (rdev->is_atom_bios) {
> +               struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
> +               lvds->bl_dev = bd;
> +       } else {
> +               struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
> +               lvds->bl_dev = bd;
> +       }
> +
> +       bd->props.brightness = radeon_legacy_backlight_get_brightness(bd);
> +       bd->props.power = FB_BLANK_UNBLANK;
> +       backlight_update_status(bd);
> +
> +       DRM_INFO("radeon legacy LVDS backlight initialized\n");
> +
> +       return;
> +
> +error:
> +       kfree(pdata);
> +       return;
> +}
> +
> +static void radeon_legacy_backlight_exit(struct radeon_encoder *radeon_encoder)
> +{
> +       struct drm_device *dev = radeon_encoder->base.dev;
> +       struct radeon_device *rdev = dev->dev_private;
> +       struct backlight_device *bd = NULL;
> +
> +       if (!radeon_encoder->enc_priv)
> +               return;
> +
> +       if (rdev->is_atom_bios) {
> +               struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
> +               bd = lvds->bl_dev;
> +               lvds->bl_dev = NULL;
> +       } else {
> +               struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
> +               bd = lvds->bl_dev;
> +               lvds->bl_dev = NULL;
> +       }
> +
> +       if (bd) {
> +               struct radeon_legacy_backlight_privdata *pdata;
> +
> +               pdata = bl_get_data(bd);
> +               backlight_device_unregister(bd);
> +               kfree(pdata);
> +
> +               DRM_INFO("radeon legacy LVDS backlight unloaded\n");
> +       }
> +}
> +
> +#else /* !CONFIG_BACKLIGHT_CLASS_DEVICE */
> +
> +static void radeon_legacy_backlight_init(struct radeon_encoder *encoder)
> +{
> +}
> +
> +static void radeon_legacy_backlight_exit(struct radeon_encoder *encoder)
> +{
> +}
> +
> +#endif
> +
> +
> +static void radeon_lvds_enc_destroy(struct drm_encoder *encoder)
> +{
> +       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
> +
> +       if (radeon_encoder->enc_priv) {
> +               radeon_legacy_backlight_exit(radeon_encoder);
> +               kfree(radeon_encoder->enc_priv);
> +       }
> +       drm_encoder_cleanup(encoder);
> +       kfree(radeon_encoder);
> +}
>
>  static const struct drm_encoder_funcs radeon_legacy_lvds_enc_funcs = {
> -       .destroy = radeon_enc_destroy,
> +       .destroy = radeon_lvds_enc_destroy,
>  };
>
>  static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode)
> diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
> index 12bdeab..32c6257 100644
> --- a/drivers/gpu/drm/radeon/radeon_mode.h
> +++ b/drivers/gpu/drm/radeon/radeon_mode.h
> @@ -300,6 +300,11 @@ struct radeon_encoder_lvds {
>        uint32_t lvds_gen_cntl;
>        /* panel mode */
>        struct drm_display_mode native_mode;
> +#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
> +       struct backlight_device *bl_dev;
> +       int      dpms_mode;
> +       uint8_t  backlight_level;
> +#endif
>  };
>
>  struct radeon_encoder_tv_dac {
> @@ -353,6 +358,11 @@ struct radeon_encoder_atom_dig {
>        uint32_t lcd_ss_id;
>        /* panel mode */
>        struct drm_display_mode native_mode;
> +#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
> +       struct backlight_device *bl_dev;
> +       int dpms_mode;
> +       uint8_t backlight_level;
> +#endif
>  };
>
>  struct radeon_encoder_atom_dac {
> --
> 1.7.3.4
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 3/5] radeon: Expose backlight class device for legacy LVDS encoder
@ 2011-01-15 17:34     ` Alex Deucher
  0 siblings, 0 replies; 40+ messages in thread
From: Alex Deucher @ 2011-01-15 17:34 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: akpm, Michel Dänzer, linux-kernel, dri-devel, linux-acpi,
	rpurdie, Michel Dänzer, intel-gfx

On Fri, Jan 14, 2011 at 2:24 PM, Matthew Garrett <mjg@redhat.com> wrote:
> From: Michel Dänzer <michel@daenzer.net>
>
> Allows e.g. power management daemons to control the backlight level. Inspired
> by the corresponding code in radeonfb.
>
> (Updated to add backlight type and make the connector the parent device - mjg)
>
> Signed-off-by: Michel Dänzer <daenzer@vmware.com>
> Signed-off-by: Matthew Garrett <mjg@redhat.com>

Acked-by: Alex Deucher <alexdeucher@gmail.com>

> Cc: dri-devel@lists.freedesktop.org
> ---
>  drivers/gpu/drm/radeon/Kconfig                  |    1 +
>  drivers/gpu/drm/radeon/radeon_connectors.c      |   15 ++
>  drivers/gpu/drm/radeon/radeon_legacy_encoders.c |  257 ++++++++++++++++++++++-
>  drivers/gpu/drm/radeon/radeon_mode.h            |   10 +
>  4 files changed, 277 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/Kconfig b/drivers/gpu/drm/radeon/Kconfig
> index 1c02d23..9746fee 100644
> --- a/drivers/gpu/drm/radeon/Kconfig
> +++ b/drivers/gpu/drm/radeon/Kconfig
> @@ -1,6 +1,7 @@
>  config DRM_RADEON_KMS
>        bool "Enable modesetting on radeon by default - NEW DRIVER"
>        depends on DRM_RADEON
> +       select BACKLIGHT_CLASS_DEVICE
>        help
>          Choose this option if you want kernel modesetting enabled by default.
>
> diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
> index 22b7e3d..e842fb5 100644
> --- a/drivers/gpu/drm/radeon/radeon_connectors.c
> +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
> @@ -40,6 +40,10 @@ radeon_atombios_connected_scratch_regs(struct drm_connector *connector,
>                                       struct drm_encoder *encoder,
>                                       bool connected);
>
> +extern void
> +radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
> +                            struct drm_connector *drm_connector);
> +
>  void radeon_connector_hotplug(struct drm_connector *connector)
>  {
>        struct drm_device *dev = connector->dev;
> @@ -1517,6 +1521,17 @@ radeon_add_legacy_connector(struct drm_device *dev,
>                connector->polled = DRM_CONNECTOR_POLL_HPD;
>        connector->display_info.subpixel_order = subpixel_order;
>        drm_sysfs_connector_add(connector);
> +       if (connector_type == DRM_MODE_CONNECTOR_LVDS) {
> +               struct drm_encoder *drm_encoder;
> +
> +               list_for_each_entry(drm_encoder, &dev->mode_config.encoder_list, head) {
> +                       struct radeon_encoder *radeon_encoder;
> +
> +                       radeon_encoder = to_radeon_encoder(drm_encoder);
> +                       if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_LVDS)
> +                               radeon_legacy_backlight_init(radeon_encoder, connector);
> +               }
> +       }
>        return;
>
>  failed:
> diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
> index 59f834b..ba7dcc6 100644
> --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
> +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
> @@ -28,6 +28,10 @@
>  #include "radeon_drm.h"
>  #include "radeon.h"
>  #include "atom.h"
> +#include <linux/backlight.h>
> +#ifdef CONFIG_PMAC_BACKLIGHT
> +#include <asm/backlight.h>
> +#endif
>
>  static void radeon_legacy_encoder_disable(struct drm_encoder *encoder)
>  {
> @@ -39,7 +43,7 @@ static void radeon_legacy_encoder_disable(struct drm_encoder *encoder)
>        radeon_encoder->active_device = 0;
>  }
>
> -static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
> +static void radeon_legacy_lvds_update(struct drm_encoder *encoder, int mode)
>  {
>        struct drm_device *dev = encoder->dev;
>        struct radeon_device *rdev = dev->dev_private;
> @@ -47,15 +51,23 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
>        uint32_t lvds_gen_cntl, lvds_pll_cntl, pixclks_cntl, disp_pwr_man;
>        int panel_pwr_delay = 2000;
>        bool is_mac = false;
> +       uint8_t backlight_level;
>        DRM_DEBUG_KMS("\n");
>
> +       lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
> +       backlight_level = (lvds_gen_cntl >> RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
> +
>        if (radeon_encoder->enc_priv) {
>                if (rdev->is_atom_bios) {
>                        struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
>                        panel_pwr_delay = lvds->panel_pwr_delay;
> +                       if (lvds->bl_dev)
> +                               backlight_level = lvds->backlight_level;
>                } else {
>                        struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
>                        panel_pwr_delay = lvds->panel_pwr_delay;
> +                       if (lvds->bl_dev)
> +                               backlight_level = lvds->backlight_level;
>                }
>        }
>
> @@ -82,11 +94,13 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
>                lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET;
>                WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
>
> -               lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
> -               lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN | RADEON_LVDS_DIGON | RADEON_LVDS_BLON);
> +               lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS |
> +                                  RADEON_LVDS_BL_MOD_LEVEL_MASK);
> +               lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN |
> +                                 RADEON_LVDS_DIGON | RADEON_LVDS_BLON |
> +                                 (backlight_level << RADEON_LVDS_BL_MOD_LEVEL_SHIFT));
>                if (is_mac)
>                        lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN;
> -               lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS);
>                udelay(panel_pwr_delay * 1000);
>                WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
>                break;
> @@ -95,7 +109,6 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
>        case DRM_MODE_DPMS_OFF:
>                pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
>                WREG32_PLL_P(RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb);
> -               lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
>                lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
>                if (is_mac) {
>                        lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_EN;
> @@ -119,6 +132,25 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
>
>  }
>
> +static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
> +{
> +       struct radeon_device *rdev = encoder->dev->dev_private;
> +       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
> +       DRM_DEBUG("\n");
> +
> +       if (radeon_encoder->enc_priv) {
> +               if (rdev->is_atom_bios) {
> +                       struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
> +                       lvds->dpms_mode = mode;
> +               } else {
> +                       struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
> +                       lvds->dpms_mode = mode;
> +               }
> +       }
> +
> +       radeon_legacy_lvds_update(encoder, mode);
> +}
> +
>  static void radeon_legacy_lvds_prepare(struct drm_encoder *encoder)
>  {
>        struct radeon_device *rdev = encoder->dev->dev_private;
> @@ -237,9 +269,222 @@ static const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = {
>        .disable = radeon_legacy_encoder_disable,
>  };
>
> +#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
> +
> +#define MAX_RADEON_LEVEL 0xFF
> +
> +struct radeon_backlight_privdata {
> +       struct radeon_encoder *encoder;
> +       uint8_t negative;
> +};
> +
> +static uint8_t radeon_legacy_lvds_level(struct backlight_device *bd)
> +{
> +       struct radeon_backlight_privdata *pdata = bl_get_data(bd);
> +       uint8_t level;
> +
> +       /* Convert brightness to hardware level */
> +       if (bd->props.brightness < 0)
> +               level = 0;
> +       else if (bd->props.brightness > MAX_RADEON_LEVEL)
> +               level = MAX_RADEON_LEVEL;
> +       else
> +               level = bd->props.brightness;
> +
> +       if (pdata->negative)
> +               level = MAX_RADEON_LEVEL - level;
> +
> +       return level;
> +}
> +
> +static int radeon_legacy_backlight_update_status(struct backlight_device *bd)
> +{
> +       struct radeon_backlight_privdata *pdata = bl_get_data(bd);
> +       struct radeon_encoder *radeon_encoder = pdata->encoder;
> +       struct drm_device *dev = radeon_encoder->base.dev;
> +       struct radeon_device *rdev = dev->dev_private;
> +       int dpms_mode = DRM_MODE_DPMS_ON;
> +
> +       if (radeon_encoder->enc_priv) {
> +               if (rdev->is_atom_bios) {
> +                       struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
> +                       dpms_mode = lvds->dpms_mode;
> +                       lvds->backlight_level = radeon_legacy_lvds_level(bd);
> +               } else {
> +                       struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
> +                       dpms_mode = lvds->dpms_mode;
> +                       lvds->backlight_level = radeon_legacy_lvds_level(bd);
> +               }
> +       }
> +
> +       if (bd->props.brightness > 0)
> +               radeon_legacy_lvds_update(&radeon_encoder->base, dpms_mode);
> +       else
> +               radeon_legacy_lvds_update(&radeon_encoder->base, DRM_MODE_DPMS_OFF);
> +
> +       return 0;
> +}
> +
> +static int radeon_legacy_backlight_get_brightness(struct backlight_device *bd)
> +{
> +       struct radeon_backlight_privdata *pdata = bl_get_data(bd);
> +       struct radeon_encoder *radeon_encoder = pdata->encoder;
> +       struct drm_device *dev = radeon_encoder->base.dev;
> +       struct radeon_device *rdev = dev->dev_private;
> +       uint8_t backlight_level;
> +
> +       backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >>
> +                          RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
> +
> +       return pdata->negative ? MAX_RADEON_LEVEL - backlight_level : backlight_level;
> +}
> +
> +static const struct backlight_ops radeon_backlight_ops = {
> +       .get_brightness = radeon_legacy_backlight_get_brightness,
> +       .update_status  = radeon_legacy_backlight_update_status,
> +};
> +
> +void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
> +                                 struct drm_connector *drm_connector)
> +{
> +       struct drm_device *dev = radeon_encoder->base.dev;
> +       struct radeon_device *rdev = dev->dev_private;
> +       struct backlight_device *bd;
> +       struct backlight_properties props;
> +       struct radeon_backlight_privdata *pdata;
> +       uint8_t backlight_level;
> +
> +       if (!radeon_encoder->enc_priv)
> +               return;
> +
> +#ifdef CONFIG_PMAC_BACKLIGHT
> +       if (!pmac_has_backlight_type("ati") &&
> +           !pmac_has_backlight_type("mnca"))
> +               return;
> +#endif
> +
> +       pdata = kmalloc(sizeof(struct radeon_backlight_privdata), GFP_KERNEL);
> +       if (!pdata) {
> +               DRM_ERROR("Memory allocation failed\n");
> +               goto error;
> +       }
> +
> +       props.max_brightness = MAX_RADEON_LEVEL;
> +       props.type = BACKLIGHT_RAW;
> +       bd = backlight_device_register("radeon_bl", &drm_connector->kdev,
> +                                      pdata, &radeon_backlight_ops, &props);
> +       if (IS_ERR(bd)) {
> +               DRM_ERROR("Backlight registration failed\n");
> +               goto error;
> +       }
> +
> +       pdata->encoder = radeon_encoder;
> +
> +       backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >>
> +                          RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
> +
> +       /* First, try to detect backlight level sense based on the assumption
> +        * that firmware set it up at full brightness
> +        */
> +       if (backlight_level == 0)
> +               pdata->negative = true;
> +       else if (backlight_level == 0xff)
> +               pdata->negative = false;
> +       else {
> +               /* XXX hack... maybe some day we can figure out in what direction
> +                * backlight should work on a given panel?
> +                */
> +               pdata->negative = (rdev->family != CHIP_RV200 &&
> +                                  rdev->family != CHIP_RV250 &&
> +                                  rdev->family != CHIP_RV280 &&
> +                                  rdev->family != CHIP_RV350);
> +
> +#ifdef CONFIG_PMAC_BACKLIGHT
> +               pdata->negative = (pdata->negative ||
> +                                  of_machine_is_compatible("PowerBook4,3") ||
> +                                  of_machine_is_compatible("PowerBook6,3") ||
> +                                  of_machine_is_compatible("PowerBook6,5"));
> +#endif
> +       }
> +
> +       if (rdev->is_atom_bios) {
> +               struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
> +               lvds->bl_dev = bd;
> +       } else {
> +               struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
> +               lvds->bl_dev = bd;
> +       }
> +
> +       bd->props.brightness = radeon_legacy_backlight_get_brightness(bd);
> +       bd->props.power = FB_BLANK_UNBLANK;
> +       backlight_update_status(bd);
> +
> +       DRM_INFO("radeon legacy LVDS backlight initialized\n");
> +
> +       return;
> +
> +error:
> +       kfree(pdata);
> +       return;
> +}
> +
> +static void radeon_legacy_backlight_exit(struct radeon_encoder *radeon_encoder)
> +{
> +       struct drm_device *dev = radeon_encoder->base.dev;
> +       struct radeon_device *rdev = dev->dev_private;
> +       struct backlight_device *bd = NULL;
> +
> +       if (!radeon_encoder->enc_priv)
> +               return;
> +
> +       if (rdev->is_atom_bios) {
> +               struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
> +               bd = lvds->bl_dev;
> +               lvds->bl_dev = NULL;
> +       } else {
> +               struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
> +               bd = lvds->bl_dev;
> +               lvds->bl_dev = NULL;
> +       }
> +
> +       if (bd) {
> +               struct radeon_legacy_backlight_privdata *pdata;
> +
> +               pdata = bl_get_data(bd);
> +               backlight_device_unregister(bd);
> +               kfree(pdata);
> +
> +               DRM_INFO("radeon legacy LVDS backlight unloaded\n");
> +       }
> +}
> +
> +#else /* !CONFIG_BACKLIGHT_CLASS_DEVICE */
> +
> +static void radeon_legacy_backlight_init(struct radeon_encoder *encoder)
> +{
> +}
> +
> +static void radeon_legacy_backlight_exit(struct radeon_encoder *encoder)
> +{
> +}
> +
> +#endif
> +
> +
> +static void radeon_lvds_enc_destroy(struct drm_encoder *encoder)
> +{
> +       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
> +
> +       if (radeon_encoder->enc_priv) {
> +               radeon_legacy_backlight_exit(radeon_encoder);
> +               kfree(radeon_encoder->enc_priv);
> +       }
> +       drm_encoder_cleanup(encoder);
> +       kfree(radeon_encoder);
> +}
>
>  static const struct drm_encoder_funcs radeon_legacy_lvds_enc_funcs = {
> -       .destroy = radeon_enc_destroy,
> +       .destroy = radeon_lvds_enc_destroy,
>  };
>
>  static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode)
> diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
> index 12bdeab..32c6257 100644
> --- a/drivers/gpu/drm/radeon/radeon_mode.h
> +++ b/drivers/gpu/drm/radeon/radeon_mode.h
> @@ -300,6 +300,11 @@ struct radeon_encoder_lvds {
>        uint32_t lvds_gen_cntl;
>        /* panel mode */
>        struct drm_display_mode native_mode;
> +#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
> +       struct backlight_device *bl_dev;
> +       int      dpms_mode;
> +       uint8_t  backlight_level;
> +#endif
>  };
>
>  struct radeon_encoder_tv_dac {
> @@ -353,6 +358,11 @@ struct radeon_encoder_atom_dig {
>        uint32_t lcd_ss_id;
>        /* panel mode */
>        struct drm_display_mode native_mode;
> +#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
> +       struct backlight_device *bl_dev;
> +       int dpms_mode;
> +       uint8_t backlight_level;
> +#endif
>  };
>
>  struct radeon_encoder_atom_dac {
> --
> 1.7.3.4
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 3/5] radeon: Expose backlight class device for legacy LVDS encoder
  2011-01-14 19:24 ` [PATCH 3/5] radeon: Expose backlight class device for legacy LVDS encoder Matthew Garrett
@ 2011-01-20  2:12     ` Andrew Morton
  2011-01-20  2:12     ` Andrew Morton
  1 sibling, 0 replies; 40+ messages in thread
From: Andrew Morton @ 2011-01-20  2:12 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: Michel Dänzer, linux-kernel, dri-devel, linux-acpi, rpurdie,
	Michel Dänzer, intel-gfx

On Fri, 14 Jan 2011 14:24:23 -0500
Matthew Garrett <mjg@redhat.com> wrote:

> From: Michel D__nzer <michel@daenzer.net>
> 
> Allows e.g. power management daemons to control the backlight level. Inspired
> by the corresponding code in radeonfb.
> 
> (Updated to add backlight type and make the connector the parent device - mjg)
> 

x86_64 allmodconfig:

drivers/gpu/drm/radeon/radeon_legacy_encoders.c: In function 'radeon_legacy_lvds_update':
drivers/gpu/drm/radeon/radeon_legacy_encoders.c:64: error: 'struct radeon_encoder_atom_dig' has no member named 'bl_dev'
drivers/gpu/drm/radeon/radeon_legacy_encoders.c:65: error: 'struct radeon_encoder_atom_dig' has no member named 'backlight_level'
drivers/gpu/drm/radeon/radeon_legacy_encoders.c:69: error: 'struct radeon_encoder_lvds' has no member named 'bl_dev'
drivers/gpu/drm/radeon/radeon_legacy_encoders.c:70: error: 'struct radeon_encoder_lvds' has no member named 'backlight_level'
drivers/gpu/drm/radeon/radeon_legacy_encoders.c: In function 'radeon_legacy_lvds_dpms':
drivers/gpu/drm/radeon/radeon_legacy_encoders.c:144: error: 'struct radeon_encoder_atom_dig' has no member named 'dpms_mode'
drivers/gpu/drm/radeon/radeon_legacy_encoders.c:147: error: 'struct radeon_encoder_lvds' has no member named 'dpms_mode'

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 3/5] radeon: Expose backlight class device for legacy LVDS encoder
@ 2011-01-20  2:12     ` Andrew Morton
  0 siblings, 0 replies; 40+ messages in thread
From: Andrew Morton @ 2011-01-20  2:12 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: intel-gfx, dri-devel, linux-acpi, linux-kernel, rpurdie,
	Michel Dänzer, Michel Dänzer

On Fri, 14 Jan 2011 14:24:23 -0500
Matthew Garrett <mjg@redhat.com> wrote:

> From: Michel D__nzer <michel@daenzer.net>
> 
> Allows e.g. power management daemons to control the backlight level. Inspired
> by the corresponding code in radeonfb.
> 
> (Updated to add backlight type and make the connector the parent device - mjg)
> 

x86_64 allmodconfig:

drivers/gpu/drm/radeon/radeon_legacy_encoders.c: In function 'radeon_legacy_lvds_update':
drivers/gpu/drm/radeon/radeon_legacy_encoders.c:64: error: 'struct radeon_encoder_atom_dig' has no member named 'bl_dev'
drivers/gpu/drm/radeon/radeon_legacy_encoders.c:65: error: 'struct radeon_encoder_atom_dig' has no member named 'backlight_level'
drivers/gpu/drm/radeon/radeon_legacy_encoders.c:69: error: 'struct radeon_encoder_lvds' has no member named 'bl_dev'
drivers/gpu/drm/radeon/radeon_legacy_encoders.c:70: error: 'struct radeon_encoder_lvds' has no member named 'backlight_level'
drivers/gpu/drm/radeon/radeon_legacy_encoders.c: In function 'radeon_legacy_lvds_dpms':
drivers/gpu/drm/radeon/radeon_legacy_encoders.c:144: error: 'struct radeon_encoder_atom_dig' has no member named 'dpms_mode'
drivers/gpu/drm/radeon/radeon_legacy_encoders.c:147: error: 'struct radeon_encoder_lvds' has no member named 'dpms_mode'


^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH v2] drm/radeon/kms: Expose backlight class device for legacy LVDS encoder.
  2011-01-20  2:12     ` Andrew Morton
@ 2011-01-20  9:05       ` Michel Dänzer
  -1 siblings, 0 replies; 40+ messages in thread
From: Michel Dänzer @ 2011-01-20  9:05 UTC (permalink / raw)
  To: Andrew Morton; +Cc: Matthew Garrett, dri-devel, linux-kernel, rpurdie

From: Michel Dänzer <daenzer@vmware.com>

Allows e.g. power management daemons to control the backlight level. Inspired
by the corresponding code in radeonfb.

v2: Fix problems when CONFIG_BACKLIGHT_CLASS_DEVICE isn't defined.

(Updated to add backlight type and make the connector the parent device - mjg)

Signed-off-by: Michel Dänzer <daenzer@vmware.com>
Signed-off-by: Matthew Garrett <mjg@redhat.com>
---
 drivers/gpu/drm/radeon/Kconfig                  |    1 +
 drivers/gpu/drm/radeon/radeon_connectors.c      |   15 ++
 drivers/gpu/drm/radeon/radeon_legacy_encoders.c |  257 ++++++++++++++++++++++-
 drivers/gpu/drm/radeon/radeon_mode.h            |    6 +
 4 files changed, 273 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/radeon/Kconfig b/drivers/gpu/drm/radeon/Kconfig
index 1c02d23..9746fee 100644
--- a/drivers/gpu/drm/radeon/Kconfig
+++ b/drivers/gpu/drm/radeon/Kconfig
@@ -1,6 +1,7 @@
 config DRM_RADEON_KMS
 	bool "Enable modesetting on radeon by default - NEW DRIVER"
 	depends on DRM_RADEON
+	select BACKLIGHT_CLASS_DEVICE
 	help
 	  Choose this option if you want kernel modesetting enabled by default.
 
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 5b00f92..c474d78 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -40,6 +40,10 @@ radeon_atombios_connected_scratch_regs(struct drm_connector *connector,
 				       struct drm_encoder *encoder,
 				       bool connected);
 
+extern void
+radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
+			     struct drm_connector *drm_connector);
+
 void radeon_connector_hotplug(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
@@ -1517,6 +1521,17 @@ radeon_add_legacy_connector(struct drm_device *dev,
 		connector->polled = DRM_CONNECTOR_POLL_HPD;
 	connector->display_info.subpixel_order = subpixel_order;
 	drm_sysfs_connector_add(connector);
+	if (connector_type == DRM_MODE_CONNECTOR_LVDS) {
+		struct drm_encoder *drm_encoder;
+
+		list_for_each_entry(drm_encoder, &dev->mode_config.encoder_list, head) {
+			struct radeon_encoder *radeon_encoder;
+
+			radeon_encoder = to_radeon_encoder(drm_encoder);
+			if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_LVDS)
+				radeon_legacy_backlight_init(radeon_encoder, connector);
+		}
+	}
 	return;
 
 failed:
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
index 59f834b..5b54268 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
@@ -28,6 +28,10 @@
 #include "radeon_drm.h"
 #include "radeon.h"
 #include "atom.h"
+#include <linux/backlight.h>
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
 
 static void radeon_legacy_encoder_disable(struct drm_encoder *encoder)
 {
@@ -39,7 +43,7 @@ static void radeon_legacy_encoder_disable(struct drm_encoder *encoder)
 	radeon_encoder->active_device = 0;
 }
 
-static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
+static void radeon_legacy_lvds_update(struct drm_encoder *encoder, int mode)
 {
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
@@ -47,15 +51,23 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
 	uint32_t lvds_gen_cntl, lvds_pll_cntl, pixclks_cntl, disp_pwr_man;
 	int panel_pwr_delay = 2000;
 	bool is_mac = false;
+	uint8_t backlight_level;
 	DRM_DEBUG_KMS("\n");
 
+	lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
+	backlight_level = (lvds_gen_cntl >> RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
+
 	if (radeon_encoder->enc_priv) {
 		if (rdev->is_atom_bios) {
 			struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
 			panel_pwr_delay = lvds->panel_pwr_delay;
+			if (lvds->bl_dev)
+				backlight_level = lvds->backlight_level;
 		} else {
 			struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
 			panel_pwr_delay = lvds->panel_pwr_delay;
+			if (lvds->bl_dev)
+				backlight_level = lvds->backlight_level;
 		}
 	}
 
@@ -82,11 +94,13 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
 		lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET;
 		WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
 
-		lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
-		lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN | RADEON_LVDS_DIGON | RADEON_LVDS_BLON);
+		lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS |
+				   RADEON_LVDS_BL_MOD_LEVEL_MASK);
+		lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN |
+				  RADEON_LVDS_DIGON | RADEON_LVDS_BLON |
+				  (backlight_level << RADEON_LVDS_BL_MOD_LEVEL_SHIFT));
 		if (is_mac)
 			lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN;
-		lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS);
 		udelay(panel_pwr_delay * 1000);
 		WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
 		break;
@@ -95,7 +109,6 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
 	case DRM_MODE_DPMS_OFF:
 		pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
 		WREG32_PLL_P(RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb);
-		lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
 		lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
 		if (is_mac) {
 			lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_EN;
@@ -119,6 +132,25 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
 
 }
 
+static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct radeon_device *rdev = encoder->dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	DRM_DEBUG("\n");
+
+	if (radeon_encoder->enc_priv) {
+		if (rdev->is_atom_bios) {
+			struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
+			lvds->dpms_mode = mode;
+		} else {
+			struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
+			lvds->dpms_mode = mode;
+		}
+	}
+
+	radeon_legacy_lvds_update(encoder, mode);
+}
+
 static void radeon_legacy_lvds_prepare(struct drm_encoder *encoder)
 {
 	struct radeon_device *rdev = encoder->dev->dev_private;
@@ -237,9 +269,222 @@ static const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = {
 	.disable = radeon_legacy_encoder_disable,
 };
 
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+
+#define MAX_RADEON_LEVEL 0xFF
+
+struct radeon_backlight_privdata {
+	struct radeon_encoder *encoder;
+	uint8_t negative;
+};
+
+static uint8_t radeon_legacy_lvds_level(struct backlight_device *bd)
+{
+	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
+	uint8_t level;
+
+	/* Convert brightness to hardware level */
+	if (bd->props.brightness < 0)
+		level = 0;
+	else if (bd->props.brightness > MAX_RADEON_LEVEL)
+		level = MAX_RADEON_LEVEL;
+	else
+		level = bd->props.brightness;
+
+	if (pdata->negative)
+		level = MAX_RADEON_LEVEL - level;
+
+	return level;
+}
+
+static int radeon_legacy_backlight_update_status(struct backlight_device *bd)
+{
+	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
+	struct radeon_encoder *radeon_encoder = pdata->encoder;
+	struct drm_device *dev = radeon_encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	int dpms_mode = DRM_MODE_DPMS_ON;
+
+	if (radeon_encoder->enc_priv) {
+		if (rdev->is_atom_bios) {
+			struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
+			dpms_mode = lvds->dpms_mode;
+			lvds->backlight_level = radeon_legacy_lvds_level(bd);
+		} else {
+			struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
+			dpms_mode = lvds->dpms_mode;
+			lvds->backlight_level = radeon_legacy_lvds_level(bd);
+		}
+	}
+
+	if (bd->props.brightness > 0)
+		radeon_legacy_lvds_update(&radeon_encoder->base, dpms_mode);
+	else
+		radeon_legacy_lvds_update(&radeon_encoder->base, DRM_MODE_DPMS_OFF);
+
+	return 0;
+}
+
+static int radeon_legacy_backlight_get_brightness(struct backlight_device *bd)
+{
+	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
+	struct radeon_encoder *radeon_encoder = pdata->encoder;
+	struct drm_device *dev = radeon_encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint8_t backlight_level;
+
+	backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >>
+			   RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
+
+	return pdata->negative ? MAX_RADEON_LEVEL - backlight_level : backlight_level;
+}
+
+static const struct backlight_ops radeon_backlight_ops = {
+	.get_brightness = radeon_legacy_backlight_get_brightness,
+	.update_status	= radeon_legacy_backlight_update_status,
+};
+
+void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
+				  struct drm_connector *drm_connector)
+{
+	struct drm_device *dev = radeon_encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct backlight_device *bd;
+	struct backlight_properties props;
+	struct radeon_backlight_privdata *pdata;
+	uint8_t backlight_level;
+
+	if (!radeon_encoder->enc_priv)
+		return;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	if (!pmac_has_backlight_type("ati") &&
+	    !pmac_has_backlight_type("mnca"))
+		return;
+#endif
+
+	pdata = kmalloc(sizeof(struct radeon_backlight_privdata), GFP_KERNEL);
+	if (!pdata) {
+		DRM_ERROR("Memory allocation failed\n");
+		goto error;
+	}
+
+	props.max_brightness = MAX_RADEON_LEVEL;
+	props.type = BACKLIGHT_RAW;
+	bd = backlight_device_register("radeon_bl", &drm_connector->kdev,
+				       pdata, &radeon_backlight_ops, &props);
+	if (IS_ERR(bd)) {
+		DRM_ERROR("Backlight registration failed\n");
+		goto error;
+	}
+
+	pdata->encoder = radeon_encoder;
+
+	backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >>
+			   RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
+
+	/* First, try to detect backlight level sense based on the assumption
+	 * that firmware set it up at full brightness
+	 */
+	if (backlight_level == 0)
+		pdata->negative = true;
+	else if (backlight_level == 0xff)
+		pdata->negative = false;
+	else {
+		/* XXX hack... maybe some day we can figure out in what direction
+		 * backlight should work on a given panel?
+		 */
+		pdata->negative = (rdev->family != CHIP_RV200 &&
+				   rdev->family != CHIP_RV250 &&
+				   rdev->family != CHIP_RV280 &&
+				   rdev->family != CHIP_RV350);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+		pdata->negative = (pdata->negative ||
+				   of_machine_is_compatible("PowerBook4,3") ||
+				   of_machine_is_compatible("PowerBook6,3") ||
+				   of_machine_is_compatible("PowerBook6,5"));
+#endif
+	}
+
+	if (rdev->is_atom_bios) {
+		struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
+		lvds->bl_dev = bd;
+	} else {
+		struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
+		lvds->bl_dev = bd;
+	}
+
+	bd->props.brightness = radeon_legacy_backlight_get_brightness(bd);
+	bd->props.power = FB_BLANK_UNBLANK;
+	backlight_update_status(bd);
+
+	DRM_INFO("radeon legacy LVDS backlight initialized\n");
+
+	return;
+
+error:
+	kfree(pdata);
+	return;
+}
+
+static void radeon_legacy_backlight_exit(struct radeon_encoder *radeon_encoder)
+{
+	struct drm_device *dev = radeon_encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct backlight_device *bd = NULL;
+
+	if (!radeon_encoder->enc_priv)
+		return;
+
+	if (rdev->is_atom_bios) {
+		struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
+		bd = lvds->bl_dev;
+		lvds->bl_dev = NULL;
+	} else {
+		struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
+		bd = lvds->bl_dev;
+		lvds->bl_dev = NULL;
+	}
+
+	if (bd) {
+		struct radeon_legacy_backlight_privdata *pdata;
+
+		pdata = bl_get_data(bd);
+		backlight_device_unregister(bd);
+		kfree(pdata);
+
+		DRM_INFO("radeon legacy LVDS backlight unloaded\n");
+	}
+}
+
+#else /* !CONFIG_BACKLIGHT_CLASS_DEVICE */
+
+void radeon_legacy_backlight_init(struct radeon_encoder *encoder)
+{
+}
+
+static void radeon_legacy_backlight_exit(struct radeon_encoder *encoder)
+{
+}
+
+#endif
+
+
+static void radeon_lvds_enc_destroy(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+
+	if (radeon_encoder->enc_priv) {
+		radeon_legacy_backlight_exit(radeon_encoder);
+		kfree(radeon_encoder->enc_priv);
+	}
+	drm_encoder_cleanup(encoder);
+	kfree(radeon_encoder);
+}
 
 static const struct drm_encoder_funcs radeon_legacy_lvds_enc_funcs = {
-	.destroy = radeon_enc_destroy,
+	.destroy = radeon_lvds_enc_destroy,
 };
 
 static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode)
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index fd185f7..0aa6007 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -300,6 +300,9 @@ struct radeon_encoder_lvds {
 	uint32_t lvds_gen_cntl;
 	/* panel mode */
 	struct drm_display_mode native_mode;
+	struct backlight_device *bl_dev;
+	int      dpms_mode;
+	uint8_t  backlight_level;
 };
 
 struct radeon_encoder_tv_dac {
@@ -353,6 +356,9 @@ struct radeon_encoder_atom_dig {
 	uint32_t lcd_ss_id;
 	/* panel mode */
 	struct drm_display_mode native_mode;
+	struct backlight_device *bl_dev;
+	int dpms_mode;
+	uint8_t backlight_level;
 };
 
 struct radeon_encoder_atom_dac {
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2] drm/radeon/kms: Expose backlight class device for legacy LVDS encoder.
@ 2011-01-20  9:05       ` Michel Dänzer
  0 siblings, 0 replies; 40+ messages in thread
From: Michel Dänzer @ 2011-01-20  9:05 UTC (permalink / raw)
  To: Andrew Morton; +Cc: rpurdie, linux-kernel, dri-devel, Matthew Garrett

From: Michel Dänzer <daenzer@vmware.com>

Allows e.g. power management daemons to control the backlight level. Inspired
by the corresponding code in radeonfb.

v2: Fix problems when CONFIG_BACKLIGHT_CLASS_DEVICE isn't defined.

(Updated to add backlight type and make the connector the parent device - mjg)

Signed-off-by: Michel Dänzer <daenzer@vmware.com>
Signed-off-by: Matthew Garrett <mjg@redhat.com>
---
 drivers/gpu/drm/radeon/Kconfig                  |    1 +
 drivers/gpu/drm/radeon/radeon_connectors.c      |   15 ++
 drivers/gpu/drm/radeon/radeon_legacy_encoders.c |  257 ++++++++++++++++++++++-
 drivers/gpu/drm/radeon/radeon_mode.h            |    6 +
 4 files changed, 273 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/radeon/Kconfig b/drivers/gpu/drm/radeon/Kconfig
index 1c02d23..9746fee 100644
--- a/drivers/gpu/drm/radeon/Kconfig
+++ b/drivers/gpu/drm/radeon/Kconfig
@@ -1,6 +1,7 @@
 config DRM_RADEON_KMS
 	bool "Enable modesetting on radeon by default - NEW DRIVER"
 	depends on DRM_RADEON
+	select BACKLIGHT_CLASS_DEVICE
 	help
 	  Choose this option if you want kernel modesetting enabled by default.
 
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 5b00f92..c474d78 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -40,6 +40,10 @@ radeon_atombios_connected_scratch_regs(struct drm_connector *connector,
 				       struct drm_encoder *encoder,
 				       bool connected);
 
+extern void
+radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
+			     struct drm_connector *drm_connector);
+
 void radeon_connector_hotplug(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
@@ -1517,6 +1521,17 @@ radeon_add_legacy_connector(struct drm_device *dev,
 		connector->polled = DRM_CONNECTOR_POLL_HPD;
 	connector->display_info.subpixel_order = subpixel_order;
 	drm_sysfs_connector_add(connector);
+	if (connector_type == DRM_MODE_CONNECTOR_LVDS) {
+		struct drm_encoder *drm_encoder;
+
+		list_for_each_entry(drm_encoder, &dev->mode_config.encoder_list, head) {
+			struct radeon_encoder *radeon_encoder;
+
+			radeon_encoder = to_radeon_encoder(drm_encoder);
+			if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_LVDS)
+				radeon_legacy_backlight_init(radeon_encoder, connector);
+		}
+	}
 	return;
 
 failed:
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
index 59f834b..5b54268 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
@@ -28,6 +28,10 @@
 #include "radeon_drm.h"
 #include "radeon.h"
 #include "atom.h"
+#include <linux/backlight.h>
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
 
 static void radeon_legacy_encoder_disable(struct drm_encoder *encoder)
 {
@@ -39,7 +43,7 @@ static void radeon_legacy_encoder_disable(struct drm_encoder *encoder)
 	radeon_encoder->active_device = 0;
 }
 
-static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
+static void radeon_legacy_lvds_update(struct drm_encoder *encoder, int mode)
 {
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
@@ -47,15 +51,23 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
 	uint32_t lvds_gen_cntl, lvds_pll_cntl, pixclks_cntl, disp_pwr_man;
 	int panel_pwr_delay = 2000;
 	bool is_mac = false;
+	uint8_t backlight_level;
 	DRM_DEBUG_KMS("\n");
 
+	lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
+	backlight_level = (lvds_gen_cntl >> RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
+
 	if (radeon_encoder->enc_priv) {
 		if (rdev->is_atom_bios) {
 			struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
 			panel_pwr_delay = lvds->panel_pwr_delay;
+			if (lvds->bl_dev)
+				backlight_level = lvds->backlight_level;
 		} else {
 			struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
 			panel_pwr_delay = lvds->panel_pwr_delay;
+			if (lvds->bl_dev)
+				backlight_level = lvds->backlight_level;
 		}
 	}
 
@@ -82,11 +94,13 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
 		lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET;
 		WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
 
-		lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
-		lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN | RADEON_LVDS_DIGON | RADEON_LVDS_BLON);
+		lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS |
+				   RADEON_LVDS_BL_MOD_LEVEL_MASK);
+		lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN |
+				  RADEON_LVDS_DIGON | RADEON_LVDS_BLON |
+				  (backlight_level << RADEON_LVDS_BL_MOD_LEVEL_SHIFT));
 		if (is_mac)
 			lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN;
-		lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS);
 		udelay(panel_pwr_delay * 1000);
 		WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
 		break;
@@ -95,7 +109,6 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
 	case DRM_MODE_DPMS_OFF:
 		pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
 		WREG32_PLL_P(RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb);
-		lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
 		lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
 		if (is_mac) {
 			lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_EN;
@@ -119,6 +132,25 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
 
 }
 
+static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct radeon_device *rdev = encoder->dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	DRM_DEBUG("\n");
+
+	if (radeon_encoder->enc_priv) {
+		if (rdev->is_atom_bios) {
+			struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
+			lvds->dpms_mode = mode;
+		} else {
+			struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
+			lvds->dpms_mode = mode;
+		}
+	}
+
+	radeon_legacy_lvds_update(encoder, mode);
+}
+
 static void radeon_legacy_lvds_prepare(struct drm_encoder *encoder)
 {
 	struct radeon_device *rdev = encoder->dev->dev_private;
@@ -237,9 +269,222 @@ static const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = {
 	.disable = radeon_legacy_encoder_disable,
 };
 
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+
+#define MAX_RADEON_LEVEL 0xFF
+
+struct radeon_backlight_privdata {
+	struct radeon_encoder *encoder;
+	uint8_t negative;
+};
+
+static uint8_t radeon_legacy_lvds_level(struct backlight_device *bd)
+{
+	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
+	uint8_t level;
+
+	/* Convert brightness to hardware level */
+	if (bd->props.brightness < 0)
+		level = 0;
+	else if (bd->props.brightness > MAX_RADEON_LEVEL)
+		level = MAX_RADEON_LEVEL;
+	else
+		level = bd->props.brightness;
+
+	if (pdata->negative)
+		level = MAX_RADEON_LEVEL - level;
+
+	return level;
+}
+
+static int radeon_legacy_backlight_update_status(struct backlight_device *bd)
+{
+	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
+	struct radeon_encoder *radeon_encoder = pdata->encoder;
+	struct drm_device *dev = radeon_encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	int dpms_mode = DRM_MODE_DPMS_ON;
+
+	if (radeon_encoder->enc_priv) {
+		if (rdev->is_atom_bios) {
+			struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
+			dpms_mode = lvds->dpms_mode;
+			lvds->backlight_level = radeon_legacy_lvds_level(bd);
+		} else {
+			struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
+			dpms_mode = lvds->dpms_mode;
+			lvds->backlight_level = radeon_legacy_lvds_level(bd);
+		}
+	}
+
+	if (bd->props.brightness > 0)
+		radeon_legacy_lvds_update(&radeon_encoder->base, dpms_mode);
+	else
+		radeon_legacy_lvds_update(&radeon_encoder->base, DRM_MODE_DPMS_OFF);
+
+	return 0;
+}
+
+static int radeon_legacy_backlight_get_brightness(struct backlight_device *bd)
+{
+	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
+	struct radeon_encoder *radeon_encoder = pdata->encoder;
+	struct drm_device *dev = radeon_encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint8_t backlight_level;
+
+	backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >>
+			   RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
+
+	return pdata->negative ? MAX_RADEON_LEVEL - backlight_level : backlight_level;
+}
+
+static const struct backlight_ops radeon_backlight_ops = {
+	.get_brightness = radeon_legacy_backlight_get_brightness,
+	.update_status	= radeon_legacy_backlight_update_status,
+};
+
+void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
+				  struct drm_connector *drm_connector)
+{
+	struct drm_device *dev = radeon_encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct backlight_device *bd;
+	struct backlight_properties props;
+	struct radeon_backlight_privdata *pdata;
+	uint8_t backlight_level;
+
+	if (!radeon_encoder->enc_priv)
+		return;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	if (!pmac_has_backlight_type("ati") &&
+	    !pmac_has_backlight_type("mnca"))
+		return;
+#endif
+
+	pdata = kmalloc(sizeof(struct radeon_backlight_privdata), GFP_KERNEL);
+	if (!pdata) {
+		DRM_ERROR("Memory allocation failed\n");
+		goto error;
+	}
+
+	props.max_brightness = MAX_RADEON_LEVEL;
+	props.type = BACKLIGHT_RAW;
+	bd = backlight_device_register("radeon_bl", &drm_connector->kdev,
+				       pdata, &radeon_backlight_ops, &props);
+	if (IS_ERR(bd)) {
+		DRM_ERROR("Backlight registration failed\n");
+		goto error;
+	}
+
+	pdata->encoder = radeon_encoder;
+
+	backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >>
+			   RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
+
+	/* First, try to detect backlight level sense based on the assumption
+	 * that firmware set it up at full brightness
+	 */
+	if (backlight_level == 0)
+		pdata->negative = true;
+	else if (backlight_level == 0xff)
+		pdata->negative = false;
+	else {
+		/* XXX hack... maybe some day we can figure out in what direction
+		 * backlight should work on a given panel?
+		 */
+		pdata->negative = (rdev->family != CHIP_RV200 &&
+				   rdev->family != CHIP_RV250 &&
+				   rdev->family != CHIP_RV280 &&
+				   rdev->family != CHIP_RV350);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+		pdata->negative = (pdata->negative ||
+				   of_machine_is_compatible("PowerBook4,3") ||
+				   of_machine_is_compatible("PowerBook6,3") ||
+				   of_machine_is_compatible("PowerBook6,5"));
+#endif
+	}
+
+	if (rdev->is_atom_bios) {
+		struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
+		lvds->bl_dev = bd;
+	} else {
+		struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
+		lvds->bl_dev = bd;
+	}
+
+	bd->props.brightness = radeon_legacy_backlight_get_brightness(bd);
+	bd->props.power = FB_BLANK_UNBLANK;
+	backlight_update_status(bd);
+
+	DRM_INFO("radeon legacy LVDS backlight initialized\n");
+
+	return;
+
+error:
+	kfree(pdata);
+	return;
+}
+
+static void radeon_legacy_backlight_exit(struct radeon_encoder *radeon_encoder)
+{
+	struct drm_device *dev = radeon_encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct backlight_device *bd = NULL;
+
+	if (!radeon_encoder->enc_priv)
+		return;
+
+	if (rdev->is_atom_bios) {
+		struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
+		bd = lvds->bl_dev;
+		lvds->bl_dev = NULL;
+	} else {
+		struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
+		bd = lvds->bl_dev;
+		lvds->bl_dev = NULL;
+	}
+
+	if (bd) {
+		struct radeon_legacy_backlight_privdata *pdata;
+
+		pdata = bl_get_data(bd);
+		backlight_device_unregister(bd);
+		kfree(pdata);
+
+		DRM_INFO("radeon legacy LVDS backlight unloaded\n");
+	}
+}
+
+#else /* !CONFIG_BACKLIGHT_CLASS_DEVICE */
+
+void radeon_legacy_backlight_init(struct radeon_encoder *encoder)
+{
+}
+
+static void radeon_legacy_backlight_exit(struct radeon_encoder *encoder)
+{
+}
+
+#endif
+
+
+static void radeon_lvds_enc_destroy(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+
+	if (radeon_encoder->enc_priv) {
+		radeon_legacy_backlight_exit(radeon_encoder);
+		kfree(radeon_encoder->enc_priv);
+	}
+	drm_encoder_cleanup(encoder);
+	kfree(radeon_encoder);
+}
 
 static const struct drm_encoder_funcs radeon_legacy_lvds_enc_funcs = {
-	.destroy = radeon_enc_destroy,
+	.destroy = radeon_lvds_enc_destroy,
 };
 
 static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode)
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index fd185f7..0aa6007 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -300,6 +300,9 @@ struct radeon_encoder_lvds {
 	uint32_t lvds_gen_cntl;
 	/* panel mode */
 	struct drm_display_mode native_mode;
+	struct backlight_device *bl_dev;
+	int      dpms_mode;
+	uint8_t  backlight_level;
 };
 
 struct radeon_encoder_tv_dac {
@@ -353,6 +356,9 @@ struct radeon_encoder_atom_dig {
 	uint32_t lcd_ss_id;
 	/* panel mode */
 	struct drm_display_mode native_mode;
+	struct backlight_device *bl_dev;
+	int dpms_mode;
+	uint8_t backlight_level;
 };
 
 struct radeon_encoder_atom_dac {
-- 
1.7.2.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* Re: [Intel-gfx] [PATCH 2/5] i915: Add native backlight control
  2011-01-14 19:24   ` Matthew Garrett
  (?)
@ 2011-01-20 20:30   ` Ali Gholami Rudi
  2011-01-20 21:13     ` Ali Gholami Rudi
  -1 siblings, 1 reply; 40+ messages in thread
From: Ali Gholami Rudi @ 2011-01-20 20:30 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: akpm, intel-gfx, linux-kernel, dri-devel, linux-acpi, rpurdie

Hi,

Matthew Garrett <mjg@redhat.com> wrote:
> Not all systems expose a firmware or platform mechanism for changing the
> backlight intensity on i915, so add native driver support.

After switching to 2.6.38-rc1 from 2.6.37
/sys/devices/virtual/backlight/acpi_video0/brightness
disappeared and I cannot control the backlight.
I tried using acpi_backlight=video but that didn't help
(this is an HP laptop BTW and I don't think there is a
native backlight control for it).

I tried to apply this patch but I get:

	drivers/gpu/drm/i915/intel_panel.c: In function 'intel_panel_setup_backlight':
	drivers/gpu/drm/i915/intel_panel.c:319: error: 'struct backlight_properties' has no member named 'type'
	drivers/gpu/drm/i915/intel_panel.c:319: error: 'BACKLIGHT_RAW' undeclared (first use in this function)
	drivers/gpu/drm/i915/intel_panel.c:319: error: (Each undeclared identifier is reported only once
	drivers/gpu/drm/i915/intel_panel.c:319: error: for each function it appears in.)
	make[4]: *** [drivers/gpu/drm/i915/intel_panel.o] Error 1
	make[3]: *** [drivers/gpu/drm/i915] Error 2
	make[2]: *** [drivers/gpu/drm] Error 2
	make[1]: *** [drivers/gpu] Error 2
	make: *** [drivers] Error 2

$ lspci | grep VGA
00:02.0 VGA compatible controller: Intel Corporation Mobile GME965/GLE960 Integrated Graphics Controller (rev 0c)
$ find /sys/ -name "*backlight*"
/sys/class/backlight
/sys/module/video/parameters/use_bios_initial_backlight

Thanks,
Ali


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 2/5] i915: Add native backlight control
  2011-01-20 20:30   ` [Intel-gfx] " Ali Gholami Rudi
@ 2011-01-20 21:13     ` Ali Gholami Rudi
  2011-01-20 23:13         ` Andrew Morton
  0 siblings, 1 reply; 40+ messages in thread
From: Ali Gholami Rudi @ 2011-01-20 21:13 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: intel-gfx, linux-kernel, dri-devel, linux-acpi, rpurdie, akpm

Ali Gholami Rudi <aliqrudi@gmail.com> wrote:
> I tried to apply this patch but I get:
> 
> 	drivers/gpu/drm/i915/intel_panel.c: In function 'intel_panel_setup_backlight':
> 	drivers/gpu/drm/i915/intel_panel.c:319: error: 'struct backlight_properties' has no member named 'type'
> 	drivers/gpu/drm/i915/intel_panel.c:319: error: 'BACKLIGHT_RAW' undeclared (first use in this function)
> 	drivers/gpu/drm/i915/intel_panel.c:319: error: (Each undeclared identifier is reported only once
> 	drivers/gpu/drm/i915/intel_panel.c:319: error: for each function it appears in.)

After applying patch 1/5, the patch applied cleanly.
Now I can change the brightness using
/sys/class/backlight/intel_backlight/brightness.
So it does fix my issue.

Thanks,
Ali

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [Intel-gfx] [PATCH 2/5] i915: Add native backlight control
  2011-01-20 21:13     ` Ali Gholami Rudi
@ 2011-01-20 23:13         ` Andrew Morton
  0 siblings, 0 replies; 40+ messages in thread
From: Andrew Morton @ 2011-01-20 23:13 UTC (permalink / raw)
  To: Ali Gholami Rudi
  Cc: intel-gfx, linux-kernel, dri-devel, linux-acpi, rpurdie, Matthew Garrett

On Fri, 21 Jan 2011 00:43:46 +0330
Ali Gholami Rudi <aliqrudi@gmail.com> wrote:

> Ali Gholami Rudi <aliqrudi@gmail.com> wrote:
> > I tried to apply this patch but I get:
> > 
> > 	drivers/gpu/drm/i915/intel_panel.c: In function 'intel_panel_setup_backlight':
> > 	drivers/gpu/drm/i915/intel_panel.c:319: error: 'struct backlight_properties' has no member named 'type'
> > 	drivers/gpu/drm/i915/intel_panel.c:319: error: 'BACKLIGHT_RAW' undeclared (first use in this function)
> > 	drivers/gpu/drm/i915/intel_panel.c:319: error: (Each undeclared identifier is reported only once
> > 	drivers/gpu/drm/i915/intel_panel.c:319: error: for each function it appears in.)
> 
> After applying patch 1/5, the patch applied cleanly.
> Now I can change the brightness using
> /sys/class/backlight/intel_backlight/brightness.
> So it does fix my issue.
> 

So we have a patch ordering issue and the
radeon-expose-backlight-class-device-for-legacy-lvds-encoder.patch
build error.

Matthew, I'll drop 'em all for now.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [Intel-gfx] [PATCH 2/5] i915: Add native backlight control
@ 2011-01-20 23:13         ` Andrew Morton
  0 siblings, 0 replies; 40+ messages in thread
From: Andrew Morton @ 2011-01-20 23:13 UTC (permalink / raw)
  To: Ali Gholami Rudi
  Cc: Matthew Garrett, intel-gfx, linux-kernel, dri-devel, linux-acpi, rpurdie

On Fri, 21 Jan 2011 00:43:46 +0330
Ali Gholami Rudi <aliqrudi@gmail.com> wrote:

> Ali Gholami Rudi <aliqrudi@gmail.com> wrote:
> > I tried to apply this patch but I get:
> > 
> > 	drivers/gpu/drm/i915/intel_panel.c: In function 'intel_panel_setup_backlight':
> > 	drivers/gpu/drm/i915/intel_panel.c:319: error: 'struct backlight_properties' has no member named 'type'
> > 	drivers/gpu/drm/i915/intel_panel.c:319: error: 'BACKLIGHT_RAW' undeclared (first use in this function)
> > 	drivers/gpu/drm/i915/intel_panel.c:319: error: (Each undeclared identifier is reported only once
> > 	drivers/gpu/drm/i915/intel_panel.c:319: error: for each function it appears in.)
> 
> After applying patch 1/5, the patch applied cleanly.
> Now I can change the brightness using
> /sys/class/backlight/intel_backlight/brightness.
> So it does fix my issue.
> 

So we have a patch ordering issue and the
radeon-expose-backlight-class-device-for-legacy-lvds-encoder.patch
build error.

Matthew, I'll drop 'em all for now.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [Intel-gfx] [PATCH 2/5] i915: Add native backlight control
  2011-01-20 23:13         ` Andrew Morton
  (?)
@ 2011-01-21  0:43         ` Matthew Garrett
  2011-01-21  1:03           ` Andrew Morton
  -1 siblings, 1 reply; 40+ messages in thread
From: Matthew Garrett @ 2011-01-21  0:43 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Ali Gholami Rudi, intel-gfx, linux-kernel, dri-devel, linux-acpi,
	rpurdie

On Thu, Jan 20, 2011 at 03:13:49PM -0800, Andrew Morton wrote:
> On Fri, 21 Jan 2011 00:43:46 +0330
> Ali Gholami Rudi <aliqrudi@gmail.com> wrote:
> 
> > Ali Gholami Rudi <aliqrudi@gmail.com> wrote:
> > > I tried to apply this patch but I get:
> > > 
> > > 	drivers/gpu/drm/i915/intel_panel.c: In function 'intel_panel_setup_backlight':
> > > 	drivers/gpu/drm/i915/intel_panel.c:319: error: 'struct backlight_properties' has no member named 'type'
> > > 	drivers/gpu/drm/i915/intel_panel.c:319: error: 'BACKLIGHT_RAW' undeclared (first use in this function)
> > > 	drivers/gpu/drm/i915/intel_panel.c:319: error: (Each undeclared identifier is reported only once
> > > 	drivers/gpu/drm/i915/intel_panel.c:319: error: for each function it appears in.)
> > 
> > After applying patch 1/5, the patch applied cleanly.
> > Now I can change the brightness using
> > /sys/class/backlight/intel_backlight/brightness.
> > So it does fix my issue.
> > 
> 
> So we have a patch ordering issue and the
> radeon-expose-backlight-class-device-for-legacy-lvds-encoder.patch
> build error.

He applied 2/5, it didn't build, he applied 1/5 and it built? I don't 
think that's a patch ordering issue :)

I think Michel's patch should fix the Radeon one. If not, can you drop 
that and keep the rest of the set? I'm travelling at the moment and 
won't have proper build access until the weekend.

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [Intel-gfx] [PATCH 2/5] i915: Add native backlight control
  2011-01-21  0:43         ` Matthew Garrett
@ 2011-01-21  1:03           ` Andrew Morton
  2011-01-21  4:57               ` [Intel-gfx] " Matthew Garrett
  0 siblings, 1 reply; 40+ messages in thread
From: Andrew Morton @ 2011-01-21  1:03 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: Ali Gholami Rudi, intel-gfx, linux-kernel, dri-devel, linux-acpi,
	rpurdie

On Fri, 21 Jan 2011 00:43:59 +0000
Matthew Garrett <mjg59@srcf.ucam.org> wrote:

> On Thu, Jan 20, 2011 at 03:13:49PM -0800, Andrew Morton wrote:
> > On Fri, 21 Jan 2011 00:43:46 +0330
> > Ali Gholami Rudi <aliqrudi@gmail.com> wrote:
> > 
> > > Ali Gholami Rudi <aliqrudi@gmail.com> wrote:
> > > > I tried to apply this patch but I get:
> > > > 
> > > > 	drivers/gpu/drm/i915/intel_panel.c: In function 'intel_panel_setup_backlight':
> > > > 	drivers/gpu/drm/i915/intel_panel.c:319: error: 'struct backlight_properties' has no member named 'type'
> > > > 	drivers/gpu/drm/i915/intel_panel.c:319: error: 'BACKLIGHT_RAW' undeclared (first use in this function)
> > > > 	drivers/gpu/drm/i915/intel_panel.c:319: error: (Each undeclared identifier is reported only once
> > > > 	drivers/gpu/drm/i915/intel_panel.c:319: error: for each function it appears in.)
> > > 
> > > After applying patch 1/5, the patch applied cleanly.
> > > Now I can change the brightness using
> > > /sys/class/backlight/intel_backlight/brightness.
> > > So it does fix my issue.
> > > 
> > 
> > So we have a patch ordering issue and the
> > radeon-expose-backlight-class-device-for-legacy-lvds-encoder.patch
> > build error.
> 
> He applied 2/5, it didn't build, he applied 1/5 and it built? I don't 
> think that's a patch ordering issue :)

What, you expect reading skills?

> I think Michel's patch should fix the Radeon one. If not, can you drop 
> that and keep the rest of the set? I'm travelling at the moment and 
> won't have proper build access until the weekend.

OK, I resurrected everything.

I updated the new drivers/video/backlight/adp5520_bl.c, but there's a
decent chance that unconverted drivers will sneak in.  I trust they
will still work OK?


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 2/5] i915: Add native backlight control
  2011-01-21  1:03           ` Andrew Morton
@ 2011-01-21  4:57               ` Matthew Garrett
  0 siblings, 0 replies; 40+ messages in thread
From: Matthew Garrett @ 2011-01-21  4:57 UTC (permalink / raw)
  To: Andrew Morton; +Cc: intel-gfx, linux-kernel, dri-devel, linux-acpi, rpurdie

On Thu, Jan 20, 2011 at 05:03:37PM -0800, Andrew Morton wrote:
> I updated the new drivers/video/backlight/adp5520_bl.c, but there's a
> decent chance that unconverted drivers will sneak in.  I trust they
> will still work OK?

They should fire a warning on registration but otherwise work. I'll send 
fixup patches for any I see.

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [Intel-gfx] [PATCH 2/5] i915: Add native backlight control
@ 2011-01-21  4:57               ` Matthew Garrett
  0 siblings, 0 replies; 40+ messages in thread
From: Matthew Garrett @ 2011-01-21  4:57 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Ali Gholami Rudi, intel-gfx, linux-kernel, dri-devel, linux-acpi,
	rpurdie

On Thu, Jan 20, 2011 at 05:03:37PM -0800, Andrew Morton wrote:
> I updated the new drivers/video/backlight/adp5520_bl.c, but there's a
> decent chance that unconverted drivers will sneak in.  I trust they
> will still work OK?

They should fire a warning on registration but otherwise work. I'll send 
fixup patches for any I see.

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 2/5] i915: Add native backlight control
  2011-01-21  4:57               ` [Intel-gfx] " Matthew Garrett
@ 2011-01-23  4:45                 ` Ali Gholami Rudi
  -1 siblings, 0 replies; 40+ messages in thread
From: Ali Gholami Rudi @ 2011-01-23  4:45 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: intel-gfx, linux-kernel, dri-devel, linux-acpi, rpurdie, Andrew Morton

Hi,

Now I'm getting this in my dmesg (1/5 and 2/5 still applied to -rc1):

	ACPI: thermal control disabled
	Non-volatile memory driver v1.3
	Linux agpgart interface v0.103
	agpgart-intel 0000:00:00.0: Intel 965GME/GLE Chipset
	agpgart-intel 0000:00:00.0: detected gtt size: 524288K total, 262144K mappable
	agpgart-intel 0000:00:00.0: detected 8192K stolen memory
	agpgart-intel 0000:00:00.0: AGP aperture is 256M @ 0xd0000000
	[drm] Initialized drm 1.1.0 20060810
	i915 0000:00:02.0: PCI INT A -> GSI 16 (level, low) -> IRQ 16
	i915 0000:00:02.0: setting latency timer to 64
	ioremap error for 0x3f7c5000-0x3f7c8000, requested 0x10, got 0x0
	i915 0000:00:02.0: irq 42 for MSI/MSI-X
	[drm] Supports vblank timestamp caching Rev 1 (10.10.2010).
	[drm] Driver supports precise vblank timestamp query.
	ACPI: Deprecated procfs I/F for battery is loaded, please retry with CONFIG_ACPI_PROCFS_POWER cleared
	ACPI: Battery Slot [C245] (battery present)
	------------[ cut here ]------------
	WARNING: at fs/sysfs/dir.c:455 sysfs_add_one+0x6e/0x83()
	Hardware name: Compaq 610
	sysfs: cannot create duplicate filename '/devices/pci0000:00/0000:00:02.0/drm/card0/card0-LVDS-1/intel_backlight'
	Modules linked in:
	Pid: 1, comm: swapper Not tainted 2.6.38-rc1+ #47
	Call Trace:
	 [<c1026828>] ? warn_slowpath_common+0x65/0x7a
	 [<c10b9404>] ? sysfs_add_one+0x6e/0x83
	 [<c10268a1>] ? warn_slowpath_fmt+0x26/0x2a
	 [<c10b9404>] ? sysfs_add_one+0x6e/0x83
	 [<c10b9b6d>] ? create_dir+0x56/0x89
	 [<c10b9c1f>] ? sysfs_create_dir+0x7f/0x94
	 [<c1111b14>] ? kobject_add_internal+0xab/0x15a
	 [<c1111c74>] ? kobject_add_varg+0x31/0x3d
	 [<c1111cea>] ? kobject_add+0x43/0x49
	 [<c11c1e14>] ? device_add+0x8f/0x4c0
	 [<c101dd19>] ? complete_all+0x35/0x3f
	 [<c11c7983>] ? device_pm_init+0x26/0x37
	 [<c11c2257>] ? device_register+0x12/0x15
	 [<c11354a1>] ? backlight_device_register+0xe4/0x133
	 [<c11b141a>] ? intel_panel_setup_backlight+0x58/0xa1
	 [<c11a74b1>] ? intel_modeset_init+0xa46/0xbca
	 [<c119297c>] ? i915_driver_load+0xab5/0xc0c
	 [<c1189140>] ? drm_get_pci_dev+0x130/0x20f
	 [<c12e3c47>] ? i915_pci_probe+0xd/0xf
	 [<c1122356>] ? local_pci_probe+0xe/0x10
	 [<c11229a4>] ? pci_device_probe+0x43/0x66
	 [<c11c3b43>] ? driver_probe_device+0x81/0xfd
	 [<c11c3c02>] ? __driver_attach+0x43/0x5f
	 [<c11c3533>] ? bus_for_each_dev+0x3d/0x67
	 [<c11c39fb>] ? driver_attach+0x14/0x16
	 [<c11c3bbf>] ? __driver_attach+0x0/0x5f
	 [<c11c2fc6>] ? bus_add_driver+0x9d/0x1cd
	 [<c11c3e2f>] ? driver_register+0x79/0xe0
	 [<c1122b69>] ? __pci_register_driver+0x38/0x95
	 [<c118924c>] ? drm_pci_init+0x2d/0x85
	 [<c11836b7>] ? drm_init+0x4c/0x4e
	 [<c14df3de>] ? i915_init+0x67/0x69
	 [<c100115e>] ? do_one_initcall+0x71/0x113
	 [<c14df377>] ? i915_init+0x0/0x69
	 [<c14c530a>] ? kernel_init+0x109/0x185
	 [<c14c5201>] ? kernel_init+0x0/0x185
	 [<c1002cb6>] ? kernel_thread_helper+0x6/0x10
	---[ end trace a1a080aaf8d35408 ]---
	kobject_add_internal failed for intel_backlight with -EEXIST, don't try to register things with the same name in the same directory.
	Pid: 1, comm: swapper Tainted: G        W   2.6.38-rc1+ #47
	Call Trace:
	 [<c1111b7a>] ? kobject_add_internal+0x111/0x15a
	 [<c1111b9b>] ? kobject_add_internal+0x132/0x15a
	 [<c1111c74>] ? kobject_add_varg+0x31/0x3d
	 [<c1111cea>] ? kobject_add+0x43/0x49
	 [<c11c1e14>] ? device_add+0x8f/0x4c0
	 [<c101dd19>] ? complete_all+0x35/0x3f
	 [<c11c7983>] ? device_pm_init+0x26/0x37
	 [<c11c2257>] ? device_register+0x12/0x15
	 [<c11354a1>] ? backlight_device_register+0xe4/0x133
	 [<c11b141a>] ? intel_panel_setup_backlight+0x58/0xa1
	 [<c11a74b1>] ? intel_modeset_init+0xa46/0xbca
	 [<c119297c>] ? i915_driver_load+0xab5/0xc0c
	 [<c1189140>] ? drm_get_pci_dev+0x130/0x20f
	 [<c12e3c47>] ? i915_pci_probe+0xd/0xf
	 [<c1122356>] ? local_pci_probe+0xe/0x10
	 [<c11229a4>] ? pci_device_probe+0x43/0x66
	 [<c11c3b43>] ? driver_probe_device+0x81/0xfd
	 [<c11c3c02>] ? __driver_attach+0x43/0x5f
	 [<c11c3533>] ? bus_for_each_dev+0x3d/0x67
	 [<c11c39fb>] ? driver_attach+0x14/0x16
	 [<c11c3bbf>] ? __driver_attach+0x0/0x5f
	 [<c11c2fc6>] ? bus_add_driver+0x9d/0x1cd
	 [<c11c3e2f>] ? driver_register+0x79/0xe0
	 [<c1122b69>] ? __pci_register_driver+0x38/0x95
	 [<c118924c>] ? drm_pci_init+0x2d/0x85
	 [<c11836b7>] ? drm_init+0x4c/0x4e
	 [<c14df3de>] ? i915_init+0x67/0x69
	 [<c100115e>] ? do_one_initcall+0x71/0x113
	 [<c14df377>] ? i915_init+0x0/0x69
	 [<c14c530a>] ? kernel_init+0x109/0x185
	 [<c14c5201>] ? kernel_init+0x0/0x185
	 [<c1002cb6>] ? kernel_thread_helper+0x6/0x10
	[drm:intel_panel_setup_backlight] *ERROR* Failed to register backlight: -17
	vgaarb: device changed decodes: PCI:0000:00:02.0,olddecodes=io+mem,decodes=io+mem:owns=io+mem
	[drm] initialized overlay support
	Console: switching to colour frame buffer device 170x48
	fb0: inteldrmfb frame buffer device
	drm: registered panic notifier
	[drm] Initialized i915 1.6.0 20080730 for 0000:00:02.0 on minor 0

Thanks,
Ali

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [Intel-gfx] [PATCH 2/5] i915: Add native backlight control
@ 2011-01-23  4:45                 ` Ali Gholami Rudi
  0 siblings, 0 replies; 40+ messages in thread
From: Ali Gholami Rudi @ 2011-01-23  4:45 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: Andrew Morton, Ali Gholami Rudi, intel-gfx, linux-kernel,
	dri-devel, linux-acpi, rpurdie

Hi,

Now I'm getting this in my dmesg (1/5 and 2/5 still applied to -rc1):

	ACPI: thermal control disabled
	Non-volatile memory driver v1.3
	Linux agpgart interface v0.103
	agpgart-intel 0000:00:00.0: Intel 965GME/GLE Chipset
	agpgart-intel 0000:00:00.0: detected gtt size: 524288K total, 262144K mappable
	agpgart-intel 0000:00:00.0: detected 8192K stolen memory
	agpgart-intel 0000:00:00.0: AGP aperture is 256M @ 0xd0000000
	[drm] Initialized drm 1.1.0 20060810
	i915 0000:00:02.0: PCI INT A -> GSI 16 (level, low) -> IRQ 16
	i915 0000:00:02.0: setting latency timer to 64
	ioremap error for 0x3f7c5000-0x3f7c8000, requested 0x10, got 0x0
	i915 0000:00:02.0: irq 42 for MSI/MSI-X
	[drm] Supports vblank timestamp caching Rev 1 (10.10.2010).
	[drm] Driver supports precise vblank timestamp query.
	ACPI: Deprecated procfs I/F for battery is loaded, please retry with CONFIG_ACPI_PROCFS_POWER cleared
	ACPI: Battery Slot [C245] (battery present)
	------------[ cut here ]------------
	WARNING: at fs/sysfs/dir.c:455 sysfs_add_one+0x6e/0x83()
	Hardware name: Compaq 610
	sysfs: cannot create duplicate filename '/devices/pci0000:00/0000:00:02.0/drm/card0/card0-LVDS-1/intel_backlight'
	Modules linked in:
	Pid: 1, comm: swapper Not tainted 2.6.38-rc1+ #47
	Call Trace:
	 [<c1026828>] ? warn_slowpath_common+0x65/0x7a
	 [<c10b9404>] ? sysfs_add_one+0x6e/0x83
	 [<c10268a1>] ? warn_slowpath_fmt+0x26/0x2a
	 [<c10b9404>] ? sysfs_add_one+0x6e/0x83
	 [<c10b9b6d>] ? create_dir+0x56/0x89
	 [<c10b9c1f>] ? sysfs_create_dir+0x7f/0x94
	 [<c1111b14>] ? kobject_add_internal+0xab/0x15a
	 [<c1111c74>] ? kobject_add_varg+0x31/0x3d
	 [<c1111cea>] ? kobject_add+0x43/0x49
	 [<c11c1e14>] ? device_add+0x8f/0x4c0
	 [<c101dd19>] ? complete_all+0x35/0x3f
	 [<c11c7983>] ? device_pm_init+0x26/0x37
	 [<c11c2257>] ? device_register+0x12/0x15
	 [<c11354a1>] ? backlight_device_register+0xe4/0x133
	 [<c11b141a>] ? intel_panel_setup_backlight+0x58/0xa1
	 [<c11a74b1>] ? intel_modeset_init+0xa46/0xbca
	 [<c119297c>] ? i915_driver_load+0xab5/0xc0c
	 [<c1189140>] ? drm_get_pci_dev+0x130/0x20f
	 [<c12e3c47>] ? i915_pci_probe+0xd/0xf
	 [<c1122356>] ? local_pci_probe+0xe/0x10
	 [<c11229a4>] ? pci_device_probe+0x43/0x66
	 [<c11c3b43>] ? driver_probe_device+0x81/0xfd
	 [<c11c3c02>] ? __driver_attach+0x43/0x5f
	 [<c11c3533>] ? bus_for_each_dev+0x3d/0x67
	 [<c11c39fb>] ? driver_attach+0x14/0x16
	 [<c11c3bbf>] ? __driver_attach+0x0/0x5f
	 [<c11c2fc6>] ? bus_add_driver+0x9d/0x1cd
	 [<c11c3e2f>] ? driver_register+0x79/0xe0
	 [<c1122b69>] ? __pci_register_driver+0x38/0x95
	 [<c118924c>] ? drm_pci_init+0x2d/0x85
	 [<c11836b7>] ? drm_init+0x4c/0x4e
	 [<c14df3de>] ? i915_init+0x67/0x69
	 [<c100115e>] ? do_one_initcall+0x71/0x113
	 [<c14df377>] ? i915_init+0x0/0x69
	 [<c14c530a>] ? kernel_init+0x109/0x185
	 [<c14c5201>] ? kernel_init+0x0/0x185
	 [<c1002cb6>] ? kernel_thread_helper+0x6/0x10
	---[ end trace a1a080aaf8d35408 ]---
	kobject_add_internal failed for intel_backlight with -EEXIST, don't try to register things with the same name in the same directory.
	Pid: 1, comm: swapper Tainted: G        W   2.6.38-rc1+ #47
	Call Trace:
	 [<c1111b7a>] ? kobject_add_internal+0x111/0x15a
	 [<c1111b9b>] ? kobject_add_internal+0x132/0x15a
	 [<c1111c74>] ? kobject_add_varg+0x31/0x3d
	 [<c1111cea>] ? kobject_add+0x43/0x49
	 [<c11c1e14>] ? device_add+0x8f/0x4c0
	 [<c101dd19>] ? complete_all+0x35/0x3f
	 [<c11c7983>] ? device_pm_init+0x26/0x37
	 [<c11c2257>] ? device_register+0x12/0x15
	 [<c11354a1>] ? backlight_device_register+0xe4/0x133
	 [<c11b141a>] ? intel_panel_setup_backlight+0x58/0xa1
	 [<c11a74b1>] ? intel_modeset_init+0xa46/0xbca
	 [<c119297c>] ? i915_driver_load+0xab5/0xc0c
	 [<c1189140>] ? drm_get_pci_dev+0x130/0x20f
	 [<c12e3c47>] ? i915_pci_probe+0xd/0xf
	 [<c1122356>] ? local_pci_probe+0xe/0x10
	 [<c11229a4>] ? pci_device_probe+0x43/0x66
	 [<c11c3b43>] ? driver_probe_device+0x81/0xfd
	 [<c11c3c02>] ? __driver_attach+0x43/0x5f
	 [<c11c3533>] ? bus_for_each_dev+0x3d/0x67
	 [<c11c39fb>] ? driver_attach+0x14/0x16
	 [<c11c3bbf>] ? __driver_attach+0x0/0x5f
	 [<c11c2fc6>] ? bus_add_driver+0x9d/0x1cd
	 [<c11c3e2f>] ? driver_register+0x79/0xe0
	 [<c1122b69>] ? __pci_register_driver+0x38/0x95
	 [<c118924c>] ? drm_pci_init+0x2d/0x85
	 [<c11836b7>] ? drm_init+0x4c/0x4e
	 [<c14df3de>] ? i915_init+0x67/0x69
	 [<c100115e>] ? do_one_initcall+0x71/0x113
	 [<c14df377>] ? i915_init+0x0/0x69
	 [<c14c530a>] ? kernel_init+0x109/0x185
	 [<c14c5201>] ? kernel_init+0x0/0x185
	 [<c1002cb6>] ? kernel_thread_helper+0x6/0x10
	[drm:intel_panel_setup_backlight] *ERROR* Failed to register backlight: -17
	vgaarb: device changed decodes: PCI:0000:00:02.0,olddecodes=io+mem,decodes=io+mem:owns=io+mem
	[drm] initialized overlay support
	Console: switching to colour frame buffer device 170x48
	fb0: inteldrmfb frame buffer device
	drm: registered panic notifier
	[drm] Initialized i915 1.6.0 20080730 for 0000:00:02.0 on minor 0

Thanks,
Ali


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [Intel-gfx] [PATCH 2/5] i915: Add native backlight control
  2011-01-23  4:45                 ` [Intel-gfx] " Ali Gholami Rudi
  (?)
@ 2011-01-23  4:56                 ` Matthew Garrett
  -1 siblings, 0 replies; 40+ messages in thread
From: Matthew Garrett @ 2011-01-23  4:56 UTC (permalink / raw)
  To: Ali Gholami Rudi
  Cc: Andrew Morton, intel-gfx, linux-kernel, dri-devel, linux-acpi, rpurdie

Well, that's odd. I'll look into it this week.

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 5/5] ACPI: Tie ACPI backlight devices to PCI devices if possible
  2011-01-14 19:24 ` [PATCH 5/5] ACPI: Tie ACPI backlight devices to PCI devices if possible Matthew Garrett
@ 2011-02-06 20:35   ` Rafael J. Wysocki
  2011-02-06 20:56       ` Matthew Garrett
  0 siblings, 1 reply; 40+ messages in thread
From: Rafael J. Wysocki @ 2011-02-06 20:35 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: akpm, intel-gfx, dri-devel, linux-acpi, linux-kernel, rpurdie

On Friday, January 14, 2011, Matthew Garrett wrote:
> Dual-GPU machines may provide more than one ACPI backlight interface. Tie
> the backlight device to the GPU in order to allow userspace to identify
> the correct interface.
> 
> Signed-off-by: Matthew Garrett <mjg@redhat.com>

Sorry for the late response, but I've just realized there's a problem with this
patch.

> ---
>  drivers/acpi/video.c |   15 ++++++++++++++-
>  1 files changed, 14 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
> index a9eec8c..a18e497 100644
> --- a/drivers/acpi/video.c
> +++ b/drivers/acpi/video.c
> @@ -782,6 +782,9 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
>  
>  	if (acpi_video_backlight_support()) {
>  		struct backlight_properties props;
> +		struct pci_dev *pdev;
> +		acpi_handle acpi_parent;
> +		struct device *parent = NULL;
>  		int result;
>  		static int count = 0;
>  		char *name;
> @@ -794,10 +797,20 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
>  			return;
>  		count++;
>  
> +		acpi_get_parent(device->dev->handle, &acpi_parent);
> +
> +		pdev = acpi_get_pci_dev(acpi_parent);
> +		if (pdev) {
> +			parent = &pdev->dev;
> +			pci_dev_put(pdev);
> +		}

I'm afraid you can't do that or suspend problems will happen.

Namely, the PM core assumes that parents will be registered before their
children and it is a very strong assumption.  If violated, it may lead to
a suspend sequence deadlock.

Unfortunately, it looks like the ACPI video device is registered before the
PCI device that's becoming it's parent, so the above assumption will be
violated.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 5/5] ACPI: Tie ACPI backlight devices to PCI devices if possible
  2011-02-06 20:35   ` Rafael J. Wysocki
@ 2011-02-06 20:56       ` Matthew Garrett
  0 siblings, 0 replies; 40+ messages in thread
From: Matthew Garrett @ 2011-02-06 20:56 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: intel-gfx, linux-kernel, dri-devel, linux-acpi, rpurdie, akpm

On Sun, Feb 06, 2011 at 09:35:07PM +0100, Rafael J. Wysocki wrote:
> > +		acpi_get_parent(device->dev->handle, &acpi_parent);
> > +
> > +		pdev = acpi_get_pci_dev(acpi_parent);
> > +		if (pdev) {
> > +			parent = &pdev->dev;
> > +			pci_dev_put(pdev);
> > +		}
> 
> I'm afraid you can't do that or suspend problems will happen.

Ugh. Ok, how can we fix this?

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 5/5] ACPI: Tie ACPI backlight devices to PCI devices if possible
@ 2011-02-06 20:56       ` Matthew Garrett
  0 siblings, 0 replies; 40+ messages in thread
From: Matthew Garrett @ 2011-02-06 20:56 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: akpm, intel-gfx, dri-devel, linux-acpi, linux-kernel, rpurdie

On Sun, Feb 06, 2011 at 09:35:07PM +0100, Rafael J. Wysocki wrote:
> > +		acpi_get_parent(device->dev->handle, &acpi_parent);
> > +
> > +		pdev = acpi_get_pci_dev(acpi_parent);
> > +		if (pdev) {
> > +			parent = &pdev->dev;
> > +			pci_dev_put(pdev);
> > +		}
> 
> I'm afraid you can't do that or suspend problems will happen.

Ugh. Ok, how can we fix this?

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 5/5] ACPI: Tie ACPI backlight devices to PCI devices if possible
  2011-02-06 20:56       ` Matthew Garrett
  (?)
@ 2011-02-06 22:41       ` Rafael J. Wysocki
  2011-02-06 22:53         ` Matthew Garrett
  -1 siblings, 1 reply; 40+ messages in thread
From: Rafael J. Wysocki @ 2011-02-06 22:41 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: akpm, intel-gfx, dri-devel, linux-acpi, linux-kernel, rpurdie

On Sunday, February 06, 2011, Matthew Garrett wrote:
> On Sun, Feb 06, 2011 at 09:35:07PM +0100, Rafael J. Wysocki wrote:
> > > +		acpi_get_parent(device->dev->handle, &acpi_parent);
> > > +
> > > +		pdev = acpi_get_pci_dev(acpi_parent);
> > > +		if (pdev) {
> > > +			parent = &pdev->dev;
> > > +			pci_dev_put(pdev);
> > > +		}
> > 
> > I'm afraid you can't do that or suspend problems will happen.
> 
> Ugh. Ok, how can we fix this?

Not nicely, I'm afraid.

One possible way is to use device_pm_move_after() to rearrange the devices in
the PM core's suspend list, but that will happen in the video device being
suspended before the new parent (and resumed after it) -- of course, the only
option is to move the ACPI video device after the new parent.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 5/5] ACPI: Tie ACPI backlight devices to PCI devices if possible
  2011-02-06 22:41       ` Rafael J. Wysocki
@ 2011-02-06 22:53         ` Matthew Garrett
  2011-02-06 23:01           ` Rafael J. Wysocki
  0 siblings, 1 reply; 40+ messages in thread
From: Matthew Garrett @ 2011-02-06 22:53 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: akpm, intel-gfx, dri-devel, linux-acpi, linux-kernel, rpurdie

On Sun, Feb 06, 2011 at 11:41:19PM +0100, Rafael J. Wysocki wrote:
> On Sunday, February 06, 2011, Matthew Garrett wrote:
> > Ugh. Ok, how can we fix this?
> 
> Not nicely, I'm afraid.
> 
> One possible way is to use device_pm_move_after() to rearrange the devices in
> the PM core's suspend list, but that will happen in the video device being
> suspended before the new parent (and resumed after it) -- of course, the only
> option is to move the ACPI video device after the new parent.

Hang on. Didn't we already have a related issue with the acpi video 
device being resumed before the video card, resulting in an SMI that 
hung the system? I thought we'd arranged things such that resuming the 
ACPI video device wouldn't actually do anything until after the PCI 
device had been handled? It seems like the correct thing is definitely 
for it to be suspended before and resumed after...

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 5/5] ACPI: Tie ACPI backlight devices to PCI devices if possible
  2011-02-06 22:53         ` Matthew Garrett
@ 2011-02-06 23:01           ` Rafael J. Wysocki
  2011-02-06 23:05               ` Matthew Garrett
  0 siblings, 1 reply; 40+ messages in thread
From: Rafael J. Wysocki @ 2011-02-06 23:01 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: akpm, intel-gfx, dri-devel, linux-acpi, linux-kernel, rpurdie

On Sunday, February 06, 2011, Matthew Garrett wrote:
> On Sun, Feb 06, 2011 at 11:41:19PM +0100, Rafael J. Wysocki wrote:
> > On Sunday, February 06, 2011, Matthew Garrett wrote:
> > > Ugh. Ok, how can we fix this?
> > 
> > Not nicely, I'm afraid.
> > 
> > One possible way is to use device_pm_move_after() to rearrange the devices in
> > the PM core's suspend list, but that will happen in the video device being
> > suspended before the new parent (and resumed after it) -- of course, the only
> > option is to move the ACPI video device after the new parent.
> 
> Hang on. Didn't we already have a related issue with the acpi video 
> device being resumed before the video card, resulting in an SMI that 
> hung the system? I thought we'd arranged things such that resuming the 
> ACPI video device wouldn't actually do anything until after the PCI 
> device had been handled? It seems like the correct thing is definitely 
> for it to be suspended before and resumed after...

Yes, it seems so, but I'm not sure what the short term consequences of that
change will be.  Perhaps there will be none. :-)

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 5/5] ACPI: Tie ACPI backlight devices to PCI devices if possible
  2011-02-06 23:01           ` Rafael J. Wysocki
@ 2011-02-06 23:05               ` Matthew Garrett
  0 siblings, 0 replies; 40+ messages in thread
From: Matthew Garrett @ 2011-02-06 23:05 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: intel-gfx, linux-kernel, dri-devel, linux-acpi, rpurdie, akpm

On Mon, Feb 07, 2011 at 12:01:25AM +0100, Rafael J. Wysocki wrote:

> Yes, it seems so, but I'm not sure what the short term consequences of that
> change will be.  Perhaps there will be none. :-)

Ok, I'll have a play with that. Maybe we should be fixing this up 
somehow in the acpi-pci glue code? It seems wrong to have acpi devices 
resumed before the PCI device they're associated with.

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 5/5] ACPI: Tie ACPI backlight devices to PCI devices if possible
@ 2011-02-06 23:05               ` Matthew Garrett
  0 siblings, 0 replies; 40+ messages in thread
From: Matthew Garrett @ 2011-02-06 23:05 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: akpm, intel-gfx, dri-devel, linux-acpi, linux-kernel, rpurdie

On Mon, Feb 07, 2011 at 12:01:25AM +0100, Rafael J. Wysocki wrote:

> Yes, it seems so, but I'm not sure what the short term consequences of that
> change will be.  Perhaps there will be none. :-)

Ok, I'll have a play with that. Maybe we should be fixing this up 
somehow in the acpi-pci glue code? It seems wrong to have acpi devices 
resumed before the PCI device they're associated with.

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 5/5] ACPI: Tie ACPI backlight devices to PCI devices if possible
  2011-02-06 23:05               ` Matthew Garrett
  (?)
@ 2011-02-06 23:34               ` Rafael J. Wysocki
  2011-02-07 21:32                 ` Bjorn Helgaas
  -1 siblings, 1 reply; 40+ messages in thread
From: Rafael J. Wysocki @ 2011-02-06 23:34 UTC (permalink / raw)
  To: Matthew Garrett, dri-devel
  Cc: akpm, linux-acpi, linux-kernel, rpurdie, Len Brown

On Monday, February 07, 2011, Matthew Garrett wrote:
> On Mon, Feb 07, 2011 at 12:01:25AM +0100, Rafael J. Wysocki wrote:
> 
> > Yes, it seems so, but I'm not sure what the short term consequences of that
> > change will be.  Perhaps there will be none. :-)
> 
> Ok, I'll have a play with that. Maybe we should be fixing this up 
> somehow in the acpi-pci glue code? It seems wrong to have acpi devices 
> resumed before the PCI device they're associated with.

Those device's don't have ACPI drivers and therefore they are not really
suspended or resumed, so we don't need to fix anything in that area.

Still, IMO, there is a design issue in the entire ACPI subsystem, because the
idea of "ACPI device" really is not well defined, so to speak.  Sometimes
they are just "device interfaces" that can be used to ask the firmware for
something (like in the case of the "ACPI devices" associated with PCI devices)
and sometimes they are "real devices" with real drivers.  The video device
apparently wants to be both at the same time, which is even more confusing. :-)

I _think_ that struct acpi_device shouldn't really contain the embedded device
object and each of struct acpi_device objects should be pointed to by the
archdata member of certain struct device.  In turn, struct acpi_device should
contain a pointer to the struct device that it's pointed to by via the archdata
field.  Then, the struct acpi_device objects will always be "device interfaces"
and all of the device-driver interactions will be represented through their
corresponding device objects.  That should allow us to avoid all of the
suspend-resume complications (and all sorts of other ugliness).

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 5/5] ACPI: Tie ACPI backlight devices to PCI devices if possible
  2011-02-06 23:34               ` Rafael J. Wysocki
@ 2011-02-07 21:32                 ` Bjorn Helgaas
  2011-02-07 21:34                     ` Matthew Garrett
  0 siblings, 1 reply; 40+ messages in thread
From: Bjorn Helgaas @ 2011-02-07 21:32 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Matthew Garrett, dri-devel, akpm, linux-acpi, linux-kernel,
	rpurdie, Len Brown

On Sunday, February 06, 2011 04:34:43 pm Rafael J. Wysocki wrote:
> 
> Still, IMO, there is a design issue in the entire ACPI subsystem, because the
> idea of "ACPI device" really is not well defined, so to speak.  Sometimes
> they are just "device interfaces" that can be used to ask the firmware for
> something (like in the case of the "ACPI devices" associated with PCI devices)
> and sometimes they are "real devices" with real drivers.  The video device
> apparently wants to be both at the same time, which is even more confusing. :-)

I'm not familiar with video devices, but I agree, this situation does
feel broken.  Is it the case that there's a PCI device as well as an
ACPI namespace Device for the same piece of hardware?  If so, I assume
the reason for the ACPI Device is to have a "standard" interface to
a platform knob like backlight control.

In that case, it seems like we should rely on PCI for enumeration and
driver binding, have some sort of hook the PCI driver could use to
twiddle that knob (using the ACPI methods), and make the ACPI Device
ineligible for driver binding.  In other words, it sounds like part
of the problem is that we have two drivers binding to what's really
a single piece of hardware.

Bjorn

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 5/5] ACPI: Tie ACPI backlight devices to PCI devices if possible
  2011-02-07 21:32                 ` Bjorn Helgaas
@ 2011-02-07 21:34                     ` Matthew Garrett
  0 siblings, 0 replies; 40+ messages in thread
From: Matthew Garrett @ 2011-02-07 21:34 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-kernel, dri-devel, Rafael J. Wysocki, linux-acpi, rpurdie,
	akpm, Len Brown

On Mon, Feb 07, 2011 at 02:32:35PM -0700, Bjorn Helgaas wrote:

> I'm not familiar with video devices, but I agree, this situation does
> feel broken.  Is it the case that there's a PCI device as well as an
> ACPI namespace Device for the same piece of hardware?  If so, I assume
> the reason for the ACPI Device is to have a "standard" interface to
> a platform knob like backlight control.
> 
> In that case, it seems like we should rely on PCI for enumeration and
> driver binding, have some sort of hook the PCI driver could use to
> twiddle that knob (using the ACPI methods), and make the ACPI Device
> ineligible for driver binding.  In other words, it sounds like part
> of the problem is that we have two drivers binding to what's really
> a single piece of hardware.

Part of the problem is that ACPI video devices aren't inherently PCI 
devices.

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 5/5] ACPI: Tie ACPI backlight devices to PCI devices if possible
@ 2011-02-07 21:34                     ` Matthew Garrett
  0 siblings, 0 replies; 40+ messages in thread
From: Matthew Garrett @ 2011-02-07 21:34 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Rafael J. Wysocki, dri-devel, akpm, linux-acpi, linux-kernel,
	rpurdie, Len Brown

On Mon, Feb 07, 2011 at 02:32:35PM -0700, Bjorn Helgaas wrote:

> I'm not familiar with video devices, but I agree, this situation does
> feel broken.  Is it the case that there's a PCI device as well as an
> ACPI namespace Device for the same piece of hardware?  If so, I assume
> the reason for the ACPI Device is to have a "standard" interface to
> a platform knob like backlight control.
> 
> In that case, it seems like we should rely on PCI for enumeration and
> driver binding, have some sort of hook the PCI driver could use to
> twiddle that knob (using the ACPI methods), and make the ACPI Device
> ineligible for driver binding.  In other words, it sounds like part
> of the problem is that we have two drivers binding to what's really
> a single piece of hardware.

Part of the problem is that ACPI video devices aren't inherently PCI 
devices.

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 5/5] ACPI: Tie ACPI backlight devices to PCI devices if possible
  2011-02-07 21:34                     ` Matthew Garrett
  (?)
@ 2011-02-07 22:04                     ` Rafael J. Wysocki
  -1 siblings, 0 replies; 40+ messages in thread
From: Rafael J. Wysocki @ 2011-02-07 22:04 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: Bjorn Helgaas, dri-devel, akpm, linux-acpi, linux-kernel,
	rpurdie, Len Brown

On Monday, February 07, 2011, Matthew Garrett wrote:
> On Mon, Feb 07, 2011 at 02:32:35PM -0700, Bjorn Helgaas wrote:
> 
> > I'm not familiar with video devices, but I agree, this situation does
> > feel broken.  Is it the case that there's a PCI device as well as an
> > ACPI namespace Device for the same piece of hardware?  If so, I assume
> > the reason for the ACPI Device is to have a "standard" interface to
> > a platform knob like backlight control.
> > 
> > In that case, it seems like we should rely on PCI for enumeration and
> > driver binding, have some sort of hook the PCI driver could use to
> > twiddle that knob (using the ACPI methods), and make the ACPI Device
> > ineligible for driver binding.  In other words, it sounds like part
> > of the problem is that we have two drivers binding to what's really
> > a single piece of hardware.
> 
> Part of the problem is that ACPI video devices aren't inherently PCI 
> devices.

To me, this really isn't about video devices.  The problem is that objects
of type struct acpi_device are treated _differently_ depending on the context.

In the meantime I've reviewed the code a bit and noticed that there's a
parent pointer in struct acpi_device, which basically duplicates the device
tree dependency, so it looks like the embedded dev in struct acpi_device is
really redundant.

^ permalink raw reply	[flat|nested] 40+ messages in thread

end of thread, other threads:[~2011-02-07 22:04 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-01-14 19:24 [PATCH 1/5] Backlight: Add backlight type Matthew Garrett
2011-01-14 19:24 ` [PATCH 2/5] i915: Add native backlight control Matthew Garrett
2011-01-14 19:24   ` Matthew Garrett
2011-01-20 20:30   ` [Intel-gfx] " Ali Gholami Rudi
2011-01-20 21:13     ` Ali Gholami Rudi
2011-01-20 23:13       ` [Intel-gfx] " Andrew Morton
2011-01-20 23:13         ` Andrew Morton
2011-01-21  0:43         ` Matthew Garrett
2011-01-21  1:03           ` Andrew Morton
2011-01-21  4:57             ` Matthew Garrett
2011-01-21  4:57               ` [Intel-gfx] " Matthew Garrett
2011-01-23  4:45               ` Ali Gholami Rudi
2011-01-23  4:45                 ` [Intel-gfx] " Ali Gholami Rudi
2011-01-23  4:56                 ` Matthew Garrett
2011-01-14 19:24 ` [PATCH 3/5] radeon: Expose backlight class device for legacy LVDS encoder Matthew Garrett
2011-01-15 17:34   ` Alex Deucher
2011-01-15 17:34     ` Alex Deucher
2011-01-20  2:12   ` Andrew Morton
2011-01-20  2:12     ` Andrew Morton
2011-01-20  9:05     ` [PATCH v2] drm/radeon/kms: " Michel Dänzer
2011-01-20  9:05       ` Michel Dänzer
2011-01-14 19:24 ` [PATCH 4/5] nouveau: Change the backlight parent device to the connector, not the PCI dev Matthew Garrett
2011-01-14 19:30   ` Anca Emanuel
2011-01-14 19:30     ` Anca Emanuel
2011-01-14 20:20     ` Matthew Garrett
2011-01-15  9:49   ` Ben Skeggs
2011-01-14 19:24 ` [PATCH 5/5] ACPI: Tie ACPI backlight devices to PCI devices if possible Matthew Garrett
2011-02-06 20:35   ` Rafael J. Wysocki
2011-02-06 20:56     ` Matthew Garrett
2011-02-06 20:56       ` Matthew Garrett
2011-02-06 22:41       ` Rafael J. Wysocki
2011-02-06 22:53         ` Matthew Garrett
2011-02-06 23:01           ` Rafael J. Wysocki
2011-02-06 23:05             ` Matthew Garrett
2011-02-06 23:05               ` Matthew Garrett
2011-02-06 23:34               ` Rafael J. Wysocki
2011-02-07 21:32                 ` Bjorn Helgaas
2011-02-07 21:34                   ` Matthew Garrett
2011-02-07 21:34                     ` Matthew Garrett
2011-02-07 22:04                     ` Rafael J. Wysocki

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.