From: Martin Lucina <mato@kotelna.sk>
To: linux-acpi@vger.kernel.org
Cc: laforge@gnumonks.org
Subject: [RFC] [PATCH] panasonic-laptop.c: add support for CD power management
Date: Tue, 13 Jan 2009 17:32:34 +0100 [thread overview]
Message-ID: <20090113163233.GA734@dezo.moloch.sk> (raw)
Hello,
attached is a patch to the panasonic-laptop driver to enable power
management (i.e. on/off) of the built-in optical drive. It creates a
sysfs interface /sys/devices/platform/panasonic/cdpower which can be
either queried or written to. Writing "0" enables the device, "1"
disables it.
This code is based on reading the existing code[1][2],
examining the DSDT on my CF-W4 system and experimentation.
The presence of the CF-Y series in the DMI table is based on the
assumption that this method works on recent CF-Yx models.
I have a few questions I'd like to clear up before actually submitting
this for inclusion:
1) Is a platform device the right way to do this?
2) Rather than checking the DMI system vendor and product name would it
be a better approach to simply check for the presence of the \_SB.FBAY()
and \_SB.STAT() ACPI methods and enable the platform device on any
(Panasonic) system where these are present? This would seem like a
more future-proof approach.
3) Please advise on the correct way to propagate an error result from
the functions that call the ACPI methods {get,set}optd_power_state() to
userspace in the sysfs interface. I couldn't find a straightforward
example anywhere.
Thanks!
-mato
[1] Referenced here http://www.da-cha.jp/letsnote as "A patch to handle
CD on/off button(need to merge)" (now a dead link)
[2] http://www.netlab.is.tsukuba.ac.jp/~yokota/izumi/panasonic_acpi/,
see the 20070907 version ("includes small hack for CD-ROM drive")
---
--- linux-2.6.28/drivers/misc/panasonic-laptop.c.orig 2009-01-13 17:01:53.327106958 +0100
+++ linux-2.6.28/drivers/misc/panasonic-laptop.c 2009-01-13 17:04:04.911106197 +0100
@@ -24,6 +24,8 @@
*---------------------------------------------------------------------------
*
* ChangeLog:
+ * Jan.13, 2009 Martin Lucina <mato@kotelna.sk>
+ * -v0.96 add support for optical drive power in Y and W series
* Sep.23, 2008 Harald Welte <laforge@gnumonks.org>
* -v0.95 rename driver from drivers/acpi/pcc_acpi.c to
* drivers/misc/panasonic-laptop.c
@@ -127,6 +129,8 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/dmi.h>
#ifndef ACPI_HOTKEY_COMPONENT
@@ -219,6 +223,7 @@ struct pcc_acpi {
struct acpi_device *device;
struct input_dev *input_dev;
struct backlight_device *backlight;
+ struct platform_device *platform;
int keymap[KEYMAP_SIZE];
};
@@ -226,6 +231,27 @@ struct pcc_keyinput {
struct acpi_hotkey *hotkey;
};
+/* known models with optical drive */
+static struct dmi_system_id pcc_platform_dmi_table[] = {
+ {
+ .ident = "Panasonic Toughbook W Series",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR,
+ "Matsushita Electric Industrial Co.,Ltd."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "CF-W"),
+ },
+ },
+ {
+ .ident = "Panasonic Toughbook Y Series",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR,
+ "Matsushita Electric Industrial Co.,Ltd."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "CF-Y"),
+ },
+ },
+ { }
+};
+
/* method access functions */
static int acpi_pcc_write_sset(struct pcc_acpi *pcc, int func, int val)
{
@@ -360,6 +386,63 @@ static struct backlight_ops pcc_backligh
.update_status = bl_set_status,
};
+/* get optical driver power state */
+
+static int get_optd_power_state(void)
+{
+ acpi_status status;
+ unsigned long long state;
+ int result;
+
+ status = acpi_evaluate_integer(NULL, "\\_SB.STAT", NULL, &state);
+ if (ACPI_FAILURE(status)) {
+ result = -EIO;
+ goto out;
+ }
+ switch (state) {
+ case 0: /* power off */
+ result = 1;
+ break;
+ case 0x0f: /* power on */
+ result = 0;
+ break;
+ default:
+ result = -EIO;
+ break;
+ }
+out:
+ return result;
+}
+
+/* set optical drive power state */
+
+static int set_optd_power_state(int new_state)
+{
+ int state, result;
+ acpi_status status;
+
+ state = get_optd_power_state();
+ if (new_state == state)
+ return 0;
+
+ result = 0;
+ switch (new_state) {
+ case 0: /* power on */
+ status = acpi_evaluate_object (NULL, "\\_SB.FBAY", NULL, NULL);
+ if (ACPI_FAILURE(status))
+ result = -EIO;
+ break;
+ case 1: /* power off */
+ status = acpi_evaluate_object (NULL, "\\_SB.CDDI", NULL, NULL);
+ if (ACPI_FAILURE(status))
+ result = -EIO;
+ break;
+ default:
+ result = -EINVAL;
+ break;
+ }
+ return result;
+}
/* sysfs user interface functions */
@@ -427,10 +510,29 @@ static ssize_t set_sticky(struct device
return count;
}
+static ssize_t show_cdpower(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", get_optd_power_state());
+}
+
+static ssize_t set_cdpower(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int value;
+
+ if (count) {
+ value = simple_strtoul(buf, NULL, 10);
+ set_optd_power_state (value);
+ }
+ return count;
+}
+
static DEVICE_ATTR(numbatt, S_IRUGO, show_numbatt, NULL);
static DEVICE_ATTR(lcdtype, S_IRUGO, show_lcdtype, NULL);
static DEVICE_ATTR(mute, S_IRUGO, show_mute, NULL);
static DEVICE_ATTR(sticky_key, S_IRUGO | S_IWUSR, show_sticky, set_sticky);
+static DEVICE_ATTR(cdpower, S_IRUGO | S_IWUSR, show_cdpower, set_cdpower);
static struct attribute *pcc_sysfs_entries[] = {
&dev_attr_numbatt.attr,
@@ -691,8 +793,26 @@ static int acpi_pcc_hotkey_add(struct ac
if (result)
goto out_backlight;
+ /* platform device initialization */
+ if (!dmi_check_system(pcc_platform_dmi_table)) {
+ pcc->platform = NULL;
+ goto out_no_optd;
+ }
+ pcc->platform = platform_device_register_simple("panasonic", -1,
+ NULL, 0);
+ if (IS_ERR(pcc->platform)) {
+ result = PTR_ERR(pcc->platform);
+ goto out_backlight;
+ }
+ result = device_create_file(&pcc->platform->dev, &dev_attr_cdpower);
+ if (result)
+ goto out_platform;
+
+out_no_optd:
return 0;
+out_platform:
+ platform_device_unregister(pcc->platform);
out_backlight:
backlight_device_unregister(pcc->backlight);
out_notify:
@@ -738,6 +858,11 @@ static int acpi_pcc_hotkey_remove(struct
if (!device || !pcc)
return -EINVAL;
+ if (pcc->platform) {
+ device_remove_file(&pcc->platform->dev, &dev_attr_cdpower);
+ platform_device_unregister(pcc->platform);
+ }
+
sysfs_remove_group(&device->dev.kobj, &pcc_attr_group);
backlight_device_unregister(pcc->backlight);
next reply other threads:[~2009-01-13 17:03 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-01-13 16:32 Martin Lucina [this message]
2009-01-13 17:16 ` [RFC] [PATCH] panasonic-laptop.c: add support for CD power management Karthik Gopalakrishnan
2009-01-13 19:14 ` Martin Lucina
2009-01-14 6:08 ` Harald Welte
2009-01-14 18:42 ` [PATCH] panasonic-laptop.c: add support for optical drive power control Martin Lucina
2009-04-05 4:53 ` Len Brown
2009-04-06 16:22 ` Martin Lucina
2009-04-07 5:59 ` Len Brown
2009-04-07 23:07 ` Harald Welte
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090113163233.GA734@dezo.moloch.sk \
--to=mato@kotelna.sk \
--cc=laforge@gnumonks.org \
--cc=linux-acpi@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox