// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Sony Programmable I/O Control Device driver for VAIO
*
* Copyright (C) 2007 Mattia Dongili <malattia@linux.it>
*
* Copyright (C) 2001-2005 Stelian Pop <stelian@popies.net>
*
* Copyright (C) 2005 Narayanan R S <nars@kadamba.org>
*
* Copyright (C) 2001-2002 Alcôve <www.alcove.com>
*
* Copyright (C) 2001 Michael Ashley <m.ashley@unsw.edu.au>
*
* Copyright (C) 2001 Junichi Morita <jun1m@mars.dti.ne.jp>
*
* Copyright (C) 2000 Takaya Kinjo <t-kinjo@tc4.so-net.ne.jp>
*
* Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com>
*
* Earlier work by Werner Almesberger, Paul `Rusty' Russell and Paul Mackerras.
*/
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/input.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/miscdevice.h>
#include <linux/poll.h>
#include <linux/delay.h>
#include <linux/wait.h>
#include <linux/acpi.h>
#include <linux/dmi.h>
#include <linux/err.h>
#include <linux/kfifo.h>
#include <linux/platform_device.h>
#include <linux/gfp.h>
#include <linux/string_choices.h>
#include <linux/uaccess.h>
#include <asm/io.h>
#include <linux/sonypi.h>
#define SONYPI_DRIVER_VERSION "1.26"
MODULE_AUTHOR("Stelian Pop <stelian@popies.net>");
MODULE_DESCRIPTION("Sony Programmable I/O Control Device driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(SONYPI_DRIVER_VERSION);
static int minor = -1;
module_param(minor, int, 0);
MODULE_PARM_DESC(minor,
"minor number of the misc device, default is -1 (automatic)");
static int verbose; /* = 0 */
module_param(verbose, int, 0644);
MODULE_PARM_DESC(verbose, "be verbose, default is 0 (no)");
static int fnkeyinit; /* = 0 */
module_param(fnkeyinit, int, 0444);
MODULE_PARM_DESC(fnkeyinit,
"set this if your Fn keys do not generate any event");
static int camera; /* = 0 */
module_param(camera, int, 0444);
MODULE_PARM_DESC(camera,
"set this if you have a MotionEye camera (PictureBook series)");
static int compat; /* = 0 */
module_param(compat, int, 0444);
MODULE_PARM_DESC(compat,
"set this if you want to enable backward compatibility mode");
static unsigned long mask = 0xffffffff;
module_param(mask, ulong, 0644);
MODULE_PARM_DESC(mask,
"set this to the mask of event you want to enable (see doc)");
static int useinput = 1;
module_param(useinput, int, 0444);
MODULE_PARM_DESC(useinput,
"set this if you would like sonypi to feed events to the input subsystem");
static int check_ioport = 1;
module_param(check_ioport, int, 0444);
MODULE_PARM_DESC(check_ioport,
"set this to 0 if you think the automatic ioport check for sony-laptop is wrong");
#define SONYPI_DEVICE_MODEL_TYPE1 1
#define SONYPI_DEVICE_MODEL_TYPE2 2
#define SONYPI_DEVICE_MODEL_TYPE3 3
/* type1 models use those */
#define SONYPI_IRQ_PORT 0x8034
#define SONYPI_IRQ_SHIFT 22
#define SONYPI_TYPE1_BASE 0x50
#define SONYPI_G10A (SONYPI_TYPE1_BASE+0x14)
#define SONYPI_TYPE1_REGION_SIZE 0x08
#define SONYPI_TYPE1_EVTYPE_OFFSET 0x04
/* type2 series specifics */
#define SONYPI_SIRQ 0x9b
#define SONYPI_SLOB 0x9c
#define SONYPI_SHIB 0x9d
#define SONYPI_TYPE2_REGION_SIZE 0x20
#define SONYPI_TYPE2_EVTYPE_OFFSET 0x12
/* type3 series specifics */
#define SONYPI_TYPE3_BASE 0x40
#define SONYPI_TYPE3_GID2 (SONYPI_TYPE3_BASE+0x48) /* 16 bits */
#define SONYPI_TYPE3_MISC (SONYPI_TYPE3_BASE+0x6d) /* 8 bits */
#define SONYPI_TYPE3_REGION_SIZE 0x20
#define SONYPI_TYPE3_EVTYPE_OFFSET 0x12
/* battery / brightness 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
/* FAN0 information (reverse engineered from ACPI tables) */
#define SONYPI_FAN0_STATUS 0x93
#define SONYPI_TEMP_STATUS 0xC1
/* ioports used for brightness and type2 events */
#define SONYPI_DATA_IOPORT 0x62
#define SONYPI_CST_IOPORT 0x66
/* The set of possible ioports */
struct sonypi_ioport_list {
u16 port1;
u16 port2;
};
static struct sonypi_ioport_list sonypi_type1_ioport_list[] = {
{ 0x10c0, 0x10c4 }, /* looks like the default on C1Vx */
{ 0x1080, 0x1084 },
{ 0x1090, 0x1094 },
{ 0x10a0, 0x10a4 },
{ 0x10b0, 0x10b4 },
{ 0x0, 0x0 }
};
static struct sonypi_ioport_list sonypi_type2_ioport_list[] = {
{ 0x1080, 0x1084 },
{ 0x10a0, 0x10a4 },
{ 0x10c0, 0x10c4 },
{ 0x10e0, 0x10e4 },
{ 0x0, 0x0 }
};
/* same as in type 2 models */
static struct sonypi_ioport_list *sonypi_type3_ioport_list =
sonypi_type2_ioport_list;
/* The set of possible interrupts */
struct sonypi_irq_list {
u16 irq;
u16 bits;
};
static struct sonypi_irq_list sonypi_type1_irq_list[] = {
{ 11, 0x2 }, /* IRQ 11, GO22=0,GO23=1 in AML */
{ 10, 0x1 }, /* IRQ 10, GO22=1,GO23=0 in AML */
{ 5, 0x0 }, /* IRQ 5, GO22=0,GO23=0 in AML */
{ 0, 0x3 } /* no IRQ, GO22=1,GO23=1 in AML */
};
static struct sonypi_irq_list sonypi_type2_irq_list[] = {
{ 11, 0x80 }, /* IRQ 11, 0x80 in SIRQ in AML */
{ 10, 0x40 }, /* IRQ 10, 0x40 in SIRQ in AML */
{ 9, 0x20 }, /* IRQ 9, 0x20 in SIRQ in AML */
{ 6, 0x10 }, /* IRQ 6, 0x10 in SIRQ in AML */
{ 0, 0x00 } /* no IRQ, 0x00 in SIRQ in AML */
};
/* same as in type2 models */
static struct sonypi_irq_list *sonypi_type3_irq_list = sonypi_type2_irq_list;
#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_PICTURE 5
#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 9
/* Event masks */
#define SONYPI_JOGGER_MASK 0x00000001
#define SONYPI_CAPTURE_MASK 0x00000002
#define SONYPI_FNKEY_MASK 0x00000004
#define SONYPI_BLUETOOTH_MASK 0x00000008
#define SONYPI_PKEY_MASK 0x00000010
#define SONYPI_BACK_MASK 0x00000020
#define SONYPI_HELP_MASK 0x00000040
#define SONYPI_LID_MASK 0x00000080
#define SONYPI_ZOOM_MASK 0x00000100
#define SONYPI_THUMBPHRASE_MASK 0x00000200
#define SONYPI_MEYE_MASK 0x00000400
#define SONYPI_MEMORYSTICK_MASK 0x00000800
#define SONYPI_BATTERY_MASK 0x00001000
#define SONYPI_WIRELESS_MASK 0x00002000
struct sonypi_event {
u8 data;
u8 event;
};
/* The set of possible button release events */
static struct sonypi_event sonypi_releaseev[] = {
{ 0x00, SONYPI_EVENT_ANYBUTTON_RELEASED },
{ 0, 0 }
};
/* The set of possible jogger events */
static struct sonypi_event sonypi_joggerev[] = {
{ 0x1f, SONYPI_EVENT_JOGDIAL_UP },
{ 0x01, SONYPI_EVENT_JOGDIAL_DOWN },
{ 0x5f, SONYPI_EVENT_JOGDIAL_UP_PRESSED },
|