📄 sony-laptop.c
字号:
wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG); outb(fn, spic_dev.cur_ioport->io1.minimum); v1 = inb_p(spic_dev.cur_ioport->io1.minimum); dprintk("sony_pic_call2: 0x%.4x\n", v1); return v1;}static u8 sony_pic_call3(u8 dev, u8 fn, u8 v){ u8 v1; wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG); outb(dev, spic_dev.cur_ioport->io1.minimum + 4); wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG); outb(fn, spic_dev.cur_ioport->io1.minimum); wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG); outb(v, spic_dev.cur_ioport->io1.minimum); v1 = inb_p(spic_dev.cur_ioport->io1.minimum); dprintk("sony_pic_call3: 0x%.4x\n", v1); return v1;}/* camera tests and poweron/poweroff */#define SONYPI_CAMERA_PICTURE 5#define SONYPI_CAMERA_CONTROL 0x10#define SONYPI_CAMERA_BRIGHTNESS 0#define SONYPI_CAMERA_CONTRAST 1#define SONYPI_CAMERA_HUE 2#define SONYPI_CAMERA_COLOR 3#define SONYPI_CAMERA_SHARPNESS 4#define SONYPI_CAMERA_EXPOSURE_MASK 0xC#define SONYPI_CAMERA_WHITE_BALANCE_MASK 0x3#define SONYPI_CAMERA_PICTURE_MODE_MASK 0x30#define SONYPI_CAMERA_MUTE_MASK 0x40/* the rest don't need a loop until not 0xff */#define SONYPI_CAMERA_AGC 6#define SONYPI_CAMERA_AGC_MASK 0x30#define SONYPI_CAMERA_SHUTTER_MASK 0x7#define SONYPI_CAMERA_SHUTDOWN_REQUEST 7#define SONYPI_CAMERA_CONTROL 0x10#define SONYPI_CAMERA_STATUS 7#define SONYPI_CAMERA_STATUS_READY 0x2#define SONYPI_CAMERA_STATUS_POSITION 0x4#define SONYPI_DIRECTION_BACKWARDS 0x4#define SONYPI_CAMERA_REVISION 8#define SONYPI_CAMERA_ROMVERSION 9static 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 int __sony_pic_camera_off(void){ if (!camera) { printk(KERN_WARNING DRV_PFX "camera control not enabled\n"); return -ENODEV; } wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE, SONYPI_CAMERA_MUTE_MASK), ITERATIONS_SHORT); if (spic_dev.camera_power) { sony_pic_call2(0x91, 0); spic_dev.camera_power = 0; } return 0;}static int __sony_pic_camera_on(void){ int i, j, x; if (!camera) { printk(KERN_WARNING DRV_PFX "camera control not enabled\n"); return -ENODEV; } if (spic_dev.camera_power) return 0; for (j = 5; j > 0; j--) { for (x = 0; x < 100 && sony_pic_call2(0x91, 0x1); x++) 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 DRV_PFX "failed to power on camera\n"); return -ENODEV; } wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_CONTROL, 0x5a), ITERATIONS_SHORT); spic_dev.camera_power = 1; return 0;}/* External camera command (exported to the motion eye v4l driver) */int sony_pic_camera_command(int command, u8 value){ if (!camera) return -EIO; mutex_lock(&spic_dev.lock); switch (command) { case SONY_PIC_COMMAND_SETCAMERA: if (value) __sony_pic_camera_on(); else __sony_pic_camera_off(); break; case SONY_PIC_COMMAND_SETCAMERABRIGHTNESS: wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_BRIGHTNESS, value), ITERATIONS_SHORT); break; case SONY_PIC_COMMAND_SETCAMERACONTRAST: wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_CONTRAST, value), ITERATIONS_SHORT); break; case SONY_PIC_COMMAND_SETCAMERAHUE: wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_HUE, value), ITERATIONS_SHORT); break; case SONY_PIC_COMMAND_SETCAMERACOLOR: wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_COLOR, value), ITERATIONS_SHORT); break; case SONY_PIC_COMMAND_SETCAMERASHARPNESS: wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_SHARPNESS, value), ITERATIONS_SHORT); break; case SONY_PIC_COMMAND_SETCAMERAPICTURE: wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE, value), ITERATIONS_SHORT); break; case SONY_PIC_COMMAND_SETCAMERAAGC: wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_AGC, value), ITERATIONS_SHORT); break; default: printk(KERN_ERR DRV_PFX "sony_pic_camera_command invalid: %d\n", command); break; } mutex_unlock(&spic_dev.lock); return 0;}EXPORT_SYMBOL(sony_pic_camera_command);/* gprs/edge modem (SZ460N and SZ210P), thanks to Joshua Wise */static void sony_pic_set_wwanpower(u8 state){ state = !!state; mutex_lock(&spic_dev.lock); if (spic_dev.wwan_power == state) { mutex_unlock(&spic_dev.lock); return; } sony_pic_call2(0xB0, state); spic_dev.wwan_power = state; mutex_unlock(&spic_dev.lock);}static ssize_t sony_pic_wwanpower_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_wwanpower(value); return count;}static ssize_t sony_pic_wwanpower_show(struct device *dev, struct device_attribute *attr, char *buffer){ ssize_t count; mutex_lock(&spic_dev.lock); count = snprintf(buffer, PAGE_SIZE, "%d\n", spic_dev.wwan_power); mutex_unlock(&spic_dev.lock); return count;}/* 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); mutex_lock(&spic_dev.lock); __sony_pic_set_bluetoothpower(value); mutex_unlock(&spic_dev.lock); return count;}static ssize_t sony_pic_bluetoothpower_show(struct device *dev, struct device_attribute *attr, char *buffer){ ssize_t count = 0; mutex_lock(&spic_dev.lock); count = snprintf(buffer, PAGE_SIZE, "%d\n", spic_dev.bluetooth_power); mutex_unlock(&spic_dev.lock); return count;}/* fan speed *//* FAN0 information (reverse engineered from ACPI tables) */#define SONY_PIC_FAN0_STATUS 0x93static int sony_pic_set_fanspeed(unsigned long value){ return ec_write(SONY_PIC_FAN0_STATUS, value);}static int sony_pic_get_fanspeed(u8 *value){ return ec_read(SONY_PIC_FAN0_STATUS, value);}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 (sony_pic_set_fanspeed(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 (sony_pic_get_fanspeed(&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(bluetoothpower, 0644);static SPIC_ATTR(wwanpower, 0644);static SPIC_ATTR(fanspeed, 0644);static struct attribute *spic_attributes[] = { &spic_attr_bluetoothpower.attr, &spic_attr_wwanpower.attr, &spic_attr_fanspeed.attr, NULL};static struct attribute_group spic_attribute_group = { .attrs = spic_attributes};/******** SONYPI compatibility **********/#ifdef CONFIG_SONYPI_COMPAT/* battery / brightness / temperature addresses */#define SONYPI_BAT_FLAGS 0x81#define SONYPI_LCD_LIGHT 0x96#define SONYPI_BAT1_PCTRM 0xa0#define SONYPI_BAT1_LEFT 0xa2#define SONYPI_BAT1_MAXRT 0xa4#define SONYPI_BAT2_PCTRM 0xa8#define SONYPI_BAT2_LEFT 0xaa#define SONYPI_BAT2_MAXRT 0xac#define SONYPI_BAT1_MAXTK 0xb0#define SONYPI_BAT1_FULL 0xb2#define SONYPI_BAT2_MAXTK 0xb8#define SONYPI_BAT2_FULL 0xba#define SONYPI_TEMP_STATUS 0xC1struct sonypi_compat_s { struct fasync_struct *fifo_async; struct kfifo *fifo; spinlock_t fifo_lock; wait_queue_head_t fifo_proc_list; atomic_t open_count;};static struct sonypi_compat_s sonypi_compat = { .open_count = ATOMIC_INIT(0),};static int sonypi_misc_fasync(int fd, struct file *filp, int on){ int retval; retval = fasync_helper(fd, filp, on, &sonypi_compat.fifo_async); if (retval < 0) return retval; return 0;}static int sonypi_misc_release(struct inode *inode, struct file *file){ sonypi_misc_fasync(-1, file, 0); atomic_dec(&sonypi_compat.open_count); return 0;}static int sonypi_misc_open(struct inode *inode, struct file *file){ /* Flush input queue on first open */ if (atomic_inc_return(&sonypi_compat.open_count) == 1) kfifo_reset(sonypi_compat.fifo); return 0;}static ssize_t sonypi_misc_read(struct file *file, char __user *buf, size_t count, loff_t *pos){ ssize_t ret; unsigned char c; if ((kfifo_len(sonypi_compat.fifo) == 0) && (file->f_flags & O_NONBLOCK)) return -EAGAIN; ret = wait_event_interruptible(sonypi_compat.fifo_proc_list, kfifo_len(sonypi_compat.fifo) != 0); if (ret) return ret; while (ret < count && (kfifo_get(sonypi_compat.fifo, &c, sizeof(c)) == sizeof(c))) { if (put_user(c, buf++)) return -EFAULT; ret++; } if (ret > 0) { struct inode *inode = file->f_path.dentry->d_inode; inode->i_atime = current_fs_time(inode->i_sb); } return ret;}static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait){ poll_wait(file, &sonypi_compat.fifo_proc_list, wait); if (kfifo_len(sonypi_compat.fifo)) return POLLIN | POLLRDNORM; return 0;}static int ec_read16(u8 addr, u16 *value){ u8 val_lb, val_hb; if (ec_read(addr, &val_lb)) return -1; if (ec_read(addr + 1, &val_hb)) return -1; *value = val_lb | (val_hb << 8); return 0;}static int sonypi_misc_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg){ int ret = 0; void __user *argp = (void __user *)arg; u8 val8; u16 val16; int value; mutex_lock(&spic_dev.lock); switch (cmd) { case SONYPI_IOCGBRT: if (sony_backlight_device == NULL) { ret = -EIO; break; } if (acpi_callgetfunc(sony_nc_acpi_handle, "GBRT", &value)) { ret = -EIO; break; } val8 = ((value & 0xff) - 1) << 5; if (copy_to_user(argp, &val8, sizeof(val8))) ret = -EFAULT; break; case SONYPI_IOCSBRT: if (sony_backlight_device == NULL) { ret = -EIO; break; } if (copy_from_user(&val8, argp, sizeof(val8))) { ret = -EFAULT; break; } if (acpi_callsetfunc(sony_nc_acpi_handle, "SBRT", (val8 >> 5) + 1, NULL)) { ret = -EIO; break; } /* sync the backlight device status */ sony_backlight_device->props.brightness = sony_backlight_get_brightness(sony_backlight_device); break; case SONYPI_IOCGBAT1CAP: if (ec_read16(SONYPI_BAT1_FULL, &val16)) { ret = -EIO; break; } if (copy_to_user(argp, &val16, sizeof(val16))) ret = -EFAULT; break; case SONYPI_IOCGBAT1REM: if (ec_read16(SONYPI_BAT1_LEFT, &val16)) { ret = -EIO; break; } if (copy_to_user(argp, &val16, sizeof(val16))) ret = -EFAULT; break; case SONYPI_IOCGBAT2CAP: if (ec_read16(SONYPI_BAT2_FULL, &val16)) { ret = -EIO; break; } if (copy_to_user(argp, &val16, sizeof(val16))) ret = -EFAULT; break; case SONYPI_IOCGBAT2REM: if (ec_read16(SONYPI_BAT2_LEFT, &val16)) { ret = -EIO; break; } if (copy_to_user(argp, &val16, sizeof(val16))) ret = -EFAULT; break; case SONYPI_IOCGBATFLAGS: if (ec_read(SONYPI_BAT_FLAGS, &val8)) { ret = -EIO; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -