sony-laptop: additional platform attributes coming from SNY6001
Register additional platform attributes coming from the SPIC (sonypi) driver. Signed-off-by: Mattia Dongili <malattia@linux.it> Signed-off-by: Len Brown <len.brown@intel.com>
This commit is contained in:
parent
1549ee6fb1
commit
49a11deade
1 changed files with 204 additions and 1 deletions
|
@ -774,7 +774,8 @@ static int sony_nc_add(struct acpi_device *device)
|
|||
|
||||
}
|
||||
|
||||
if (sony_pf_add())
|
||||
result = sony_pf_add();
|
||||
if (result)
|
||||
goto outbacklight;
|
||||
|
||||
/* create sony_pf sysfs attributes related to the SNC device */
|
||||
|
@ -903,6 +904,8 @@ struct sony_pic_irq {
|
|||
|
||||
struct sony_pic_dev {
|
||||
int model;
|
||||
u8 camera_power;
|
||||
u8 bluetooth_power;
|
||||
struct acpi_device *acpi_dev;
|
||||
struct sony_pic_irq *cur_irq;
|
||||
struct sony_pic_ioport *cur_ioport;
|
||||
|
@ -1181,6 +1184,186 @@ static u8 sony_pic_call2(u8 dev, u8 fn)
|
|||
return v1;
|
||||
}
|
||||
|
||||
static u8 sony_pic_call3(u8 dev, u8 fn, u8 v)
|
||||
{
|
||||
u8 v1;
|
||||
|
||||
wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, ITERATIONS_LONG);
|
||||
outb(dev, spic_dev.cur_ioport->io.minimum + 4);
|
||||
wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, ITERATIONS_LONG);
|
||||
outb(fn, spic_dev.cur_ioport->io.minimum);
|
||||
wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, ITERATIONS_LONG);
|
||||
outb(v, spic_dev.cur_ioport->io.minimum);
|
||||
v1 = inb_p(spic_dev.cur_ioport->io.minimum);
|
||||
dprintk("sony_pic_call3: 0x%.4x\n", v1);
|
||||
return v1;
|
||||
}
|
||||
|
||||
/* camera tests and poweron/poweroff */
|
||||
#define SONYPI_CAMERA_PICTURE 5
|
||||
#define SONYPI_CAMERA_MUTE_MASK 0x40
|
||||
#define SONYPI_CAMERA_CONTROL 0x10
|
||||
#define SONYPI_CAMERA_STATUS 7
|
||||
#define SONYPI_CAMERA_STATUS_READY 0x2
|
||||
#define SONYPI_CAMERA_STATUS_POSITION 0x4
|
||||
|
||||
static int sony_pic_camera_ready(void)
|
||||
{
|
||||
u8 v;
|
||||
|
||||
v = sony_pic_call2(0x8f, SONYPI_CAMERA_STATUS);
|
||||
return (v != 0xff && (v & SONYPI_CAMERA_STATUS_READY));
|
||||
}
|
||||
|
||||
static void sony_pic_camera_off(void)
|
||||
{
|
||||
wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE,
|
||||
SONYPI_CAMERA_MUTE_MASK),
|
||||
ITERATIONS_SHORT);
|
||||
|
||||
if (!spic_dev.camera_power)
|
||||
return;
|
||||
|
||||
sony_pic_call2(0x91, 0);
|
||||
spic_dev.camera_power = 0;
|
||||
}
|
||||
|
||||
static void sony_pic_camera_on(void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (spic_dev.camera_power)
|
||||
return;
|
||||
|
||||
for (j = 5; j > 0; j--) {
|
||||
|
||||
while (sony_pic_call2(0x91, 0x1))
|
||||
msleep(10);
|
||||
sony_pic_call1(0x93);
|
||||
|
||||
for (i = 400; i > 0; i--) {
|
||||
if (sony_pic_camera_ready())
|
||||
break;
|
||||
msleep(10);
|
||||
}
|
||||
if (i)
|
||||
break;
|
||||
}
|
||||
|
||||
if (j == 0) {
|
||||
printk(KERN_WARNING "sonypi: failed to power on camera\n");
|
||||
return;
|
||||
}
|
||||
|
||||
wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_CONTROL,
|
||||
0x5a),
|
||||
ITERATIONS_SHORT);
|
||||
|
||||
spic_dev.camera_power = 1;
|
||||
}
|
||||
|
||||
static ssize_t sony_pic_camerapower_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buffer, size_t count)
|
||||
{
|
||||
unsigned long value;
|
||||
if (count > 31)
|
||||
return -EINVAL;
|
||||
|
||||
value = simple_strtoul(buffer, NULL, 10);
|
||||
if (value)
|
||||
sony_pic_camera_on();
|
||||
else
|
||||
sony_pic_camera_off();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t sony_pic_camerapower_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buffer)
|
||||
{
|
||||
return snprintf(buffer, PAGE_SIZE, "%d\n", spic_dev.camera_power);
|
||||
}
|
||||
|
||||
/* bluetooth subsystem power state */
|
||||
static void sony_pic_set_bluetoothpower(u8 state)
|
||||
{
|
||||
state = !!state;
|
||||
if (spic_dev.bluetooth_power == state)
|
||||
return;
|
||||
sony_pic_call2(0x96, state);
|
||||
sony_pic_call1(0x82);
|
||||
spic_dev.bluetooth_power = state;
|
||||
}
|
||||
|
||||
static ssize_t sony_pic_bluetoothpower_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buffer, size_t count)
|
||||
{
|
||||
unsigned long value;
|
||||
if (count > 31)
|
||||
return -EINVAL;
|
||||
|
||||
value = simple_strtoul(buffer, NULL, 10);
|
||||
sony_pic_set_bluetoothpower(value);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t sony_pic_bluetoothpower_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buffer)
|
||||
{
|
||||
return snprintf(buffer, PAGE_SIZE, "%d\n", spic_dev.bluetooth_power);
|
||||
}
|
||||
|
||||
/* fan speed */
|
||||
/* FAN0 information (reverse engineered from ACPI tables) */
|
||||
#define SONY_PIC_FAN0_STATUS 0x93
|
||||
static ssize_t sony_pic_fanspeed_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buffer, size_t count)
|
||||
{
|
||||
unsigned long value;
|
||||
if (count > 31)
|
||||
return -EINVAL;
|
||||
|
||||
value = simple_strtoul(buffer, NULL, 10);
|
||||
if (ec_write(SONY_PIC_FAN0_STATUS, value))
|
||||
return -EIO;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t sony_pic_fanspeed_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buffer)
|
||||
{
|
||||
u8 value = 0;
|
||||
if (ec_read(SONY_PIC_FAN0_STATUS, &value))
|
||||
return -EIO;
|
||||
|
||||
return snprintf(buffer, PAGE_SIZE, "%d\n", value);
|
||||
}
|
||||
|
||||
#define SPIC_ATTR(_name, _mode) \
|
||||
struct device_attribute spic_attr_##_name = __ATTR(_name, \
|
||||
_mode, sony_pic_## _name ##_show, \
|
||||
sony_pic_## _name ##_store)
|
||||
|
||||
static SPIC_ATTR(camerapower, 0644);
|
||||
static SPIC_ATTR(bluetoothpower, 0644);
|
||||
static SPIC_ATTR(fanspeed, 0644);
|
||||
|
||||
static struct attribute *spic_attributes[] = {
|
||||
&spic_attr_camerapower.attr,
|
||||
&spic_attr_bluetoothpower.attr,
|
||||
&spic_attr_fanspeed.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group spic_attribute_group = {
|
||||
.attrs = spic_attributes
|
||||
};
|
||||
|
||||
/*
|
||||
* ACPI callbacks
|
||||
*/
|
||||
|
@ -1447,6 +1630,10 @@ static int sony_pic_remove(struct acpi_device *device, int type)
|
|||
|
||||
sony_laptop_remove_input();
|
||||
|
||||
/* pf attrs */
|
||||
sysfs_remove_group(&sony_pf_device->dev.kobj, &spic_attribute_group);
|
||||
sony_pf_remove();
|
||||
|
||||
list_for_each_entry_safe(io, tmp_io, &spic_dev.ioports, list) {
|
||||
list_del(&io->list);
|
||||
kfree(io);
|
||||
|
@ -1536,8 +1723,24 @@ static int sony_pic_add(struct acpi_device *device)
|
|||
goto err_free_irq;
|
||||
}
|
||||
|
||||
spic_dev.bluetooth_power = -1;
|
||||
/* create device attributes */
|
||||
result = sony_pf_add();
|
||||
if (result)
|
||||
goto err_disable_device;
|
||||
|
||||
result = sysfs_create_group(&sony_pf_device->dev.kobj, &spic_attribute_group);
|
||||
if (result)
|
||||
goto err_remove_pf;
|
||||
|
||||
return 0;
|
||||
|
||||
err_remove_pf:
|
||||
sony_pf_remove();
|
||||
|
||||
err_disable_device:
|
||||
sony_pic_disable(device);
|
||||
|
||||
err_free_irq:
|
||||
free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
|
||||
|
||||
|
|
Loading…
Reference in a new issue