staging: samsung-laptop: Extend samsung-laptop platform driver to support another flavor of its platform BIOS.
There are currently two implementations of the Samsung BIOS that controls the rfkill switch, backlight brightness / power and performance level. The samsung-laptop driver implements the BIOS flavor with the SECLINUX signature, this patch implements talking to the other BIOS with 'SwSmi@' signature. Both expose very similar functionality and way of accessing the commands. The differences are mostly offsets, command identifiers and some values. This patch introduces a sabi_config structure that contains information on identifying and accessing specific SABI flavors. Signed-off-by: Ingmar Steen <iksteen@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Родитель
f94fdeaa58
Коммит
988a29bf3d
|
@ -33,51 +33,6 @@
|
|||
*/
|
||||
#define MAX_BRIGHT 0x07
|
||||
|
||||
/* Brightness is 0 - 8, as described above. Value 0 is for the BIOS to use */
|
||||
#define GET_BRIGHTNESS 0x00
|
||||
#define SET_BRIGHTNESS 0x01
|
||||
|
||||
/* first byte:
|
||||
* 0x00 - wireless is off
|
||||
* 0x01 - wireless is on
|
||||
* second byte:
|
||||
* 0x02 - 3G is off
|
||||
* 0x03 - 3G is on
|
||||
* TODO, verify 3G is correct, that doesn't seem right...
|
||||
*/
|
||||
#define GET_WIRELESS_BUTTON 0x02
|
||||
#define SET_WIRELESS_BUTTON 0x03
|
||||
|
||||
/* 0 is off, 1 is on */
|
||||
#define GET_BACKLIGHT 0x04
|
||||
#define SET_BACKLIGHT 0x05
|
||||
|
||||
/*
|
||||
* 0x80 or 0x00 - no action
|
||||
* 0x81 - recovery key pressed
|
||||
*/
|
||||
#define GET_RECOVERY_METHOD 0x06
|
||||
#define SET_RECOVERY_METHOD 0x07
|
||||
|
||||
/* 0 is low, 1 is high */
|
||||
#define GET_PERFORMANCE_LEVEL 0x08
|
||||
#define SET_PERFORMANCE_LEVEL 0x09
|
||||
|
||||
/*
|
||||
* Tell the BIOS that Linux is running on this machine.
|
||||
* 81 is on, 80 is off
|
||||
*/
|
||||
#define SET_LINUX 0x0a
|
||||
|
||||
|
||||
#define MAIN_FUNCTION 0x4c49
|
||||
|
||||
#define SABI_HEADER_PORT 0x00
|
||||
#define SABI_HEADER_RE_MEM 0x02
|
||||
#define SABI_HEADER_IFACEFUNC 0x03
|
||||
#define SABI_HEADER_EN_MEM 0x04
|
||||
#define SABI_HEADER_DATA_OFFSET 0x05
|
||||
#define SABI_HEADER_DATA_SEGMENT 0x07
|
||||
|
||||
#define SABI_IFACE_MAIN 0x00
|
||||
#define SABI_IFACE_SUB 0x02
|
||||
|
@ -89,6 +44,169 @@ struct sabi_retval {
|
|||
u8 retval[20];
|
||||
};
|
||||
|
||||
struct sabi_header_offsets {
|
||||
u8 port;
|
||||
u8 re_mem;
|
||||
u8 iface_func;
|
||||
u8 en_mem;
|
||||
u8 data_offset;
|
||||
u8 data_segment;
|
||||
};
|
||||
|
||||
struct sabi_commands {
|
||||
/* Brightness is 0 - 8, as described above. Value 0 is for the BIOS to use */
|
||||
u8 get_brightness;
|
||||
u8 set_brightness;
|
||||
|
||||
/* first byte:
|
||||
* 0x00 - wireless is off
|
||||
* 0x01 - wireless is on
|
||||
* second byte:
|
||||
* 0x02 - 3G is off
|
||||
* 0x03 - 3G is on
|
||||
* TODO, verify 3G is correct, that doesn't seem right...
|
||||
*/
|
||||
u8 get_wireless_button;
|
||||
u8 set_wireless_button;
|
||||
|
||||
/* 0 is off, 1 is on */
|
||||
u8 get_backlight;
|
||||
u8 set_backlight;
|
||||
|
||||
/*
|
||||
* 0x80 or 0x00 - no action
|
||||
* 0x81 - recovery key pressed
|
||||
*/
|
||||
u8 get_recovery_mode;
|
||||
u8 set_recovery_mode;
|
||||
|
||||
/*
|
||||
* on seclinux: 0 is low, 1 is high,
|
||||
* on swsmi: 0 is normal, 1 is silent, 2 is turbo
|
||||
*/
|
||||
u8 get_performance_level;
|
||||
u8 set_performance_level;
|
||||
|
||||
/*
|
||||
* Tell the BIOS that Linux is running on this machine.
|
||||
* 81 is on, 80 is off
|
||||
*/
|
||||
u8 set_linux;
|
||||
};
|
||||
|
||||
struct sabi_performance_level {
|
||||
const char *name;
|
||||
u8 value;
|
||||
};
|
||||
|
||||
struct sabi_config {
|
||||
const char *test_string;
|
||||
u16 main_function;
|
||||
struct sabi_header_offsets header_offsets;
|
||||
struct sabi_commands commands;
|
||||
struct sabi_performance_level performance_levels[4];
|
||||
};
|
||||
|
||||
static struct sabi_config sabi_configs[] = {
|
||||
{
|
||||
test_string: "SECLINUX",
|
||||
|
||||
main_function: 0x4c59,
|
||||
|
||||
header_offsets: {
|
||||
port: 0x00,
|
||||
re_mem: 0x02,
|
||||
iface_func: 0x03,
|
||||
en_mem: 0x04,
|
||||
data_offset: 0x05,
|
||||
data_segment: 0x07,
|
||||
},
|
||||
|
||||
commands: {
|
||||
get_brightness: 0x00,
|
||||
set_brightness: 0x01,
|
||||
|
||||
get_wireless_button: 0x02,
|
||||
set_wireless_button: 0x03,
|
||||
|
||||
get_backlight: 0x04,
|
||||
set_backlight: 0x05,
|
||||
|
||||
get_recovery_mode: 0x06,
|
||||
set_recovery_mode: 0x07,
|
||||
|
||||
get_performance_level: 0x08,
|
||||
set_performance_level: 0x09,
|
||||
|
||||
set_linux: 0x0a,
|
||||
},
|
||||
|
||||
performance_levels: {
|
||||
{
|
||||
name: "silent",
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
name: "normal",
|
||||
value: 1,
|
||||
},
|
||||
{ },
|
||||
},
|
||||
},
|
||||
{
|
||||
test_string: "SwSmi@",
|
||||
|
||||
main_function: 0x5843,
|
||||
|
||||
header_offsets: {
|
||||
port: 0x00,
|
||||
re_mem: 0x04,
|
||||
iface_func: 0x02,
|
||||
en_mem: 0x03,
|
||||
data_offset: 0x05,
|
||||
data_segment: 0x07,
|
||||
},
|
||||
|
||||
commands: {
|
||||
get_brightness: 0x10,
|
||||
set_brightness: 0x11,
|
||||
|
||||
get_wireless_button: 0x12,
|
||||
set_wireless_button: 0x13,
|
||||
|
||||
get_backlight: 0x2d,
|
||||
set_backlight: 0x2e,
|
||||
|
||||
get_recovery_mode: 0xff,
|
||||
set_recovery_mode: 0xff,
|
||||
|
||||
get_performance_level: 0x31,
|
||||
set_performance_level: 0x32,
|
||||
|
||||
set_linux: 0xff,
|
||||
},
|
||||
|
||||
performance_levels: {
|
||||
{
|
||||
name: "normal",
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
name: "silent",
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
name: "overclock",
|
||||
value: 2,
|
||||
},
|
||||
{ },
|
||||
},
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct sabi_config *sabi_config;
|
||||
|
||||
static void __iomem *sabi;
|
||||
static void __iomem *sabi_iface;
|
||||
static void __iomem *f0000_segment;
|
||||
|
@ -109,21 +227,21 @@ MODULE_PARM_DESC(debug, "Debug enabled or not");
|
|||
static int sabi_get_command(u8 command, struct sabi_retval *sretval)
|
||||
{
|
||||
int retval = 0;
|
||||
u16 port = readw(sabi + SABI_HEADER_PORT);
|
||||
u16 port = readw(sabi + sabi_config->header_offsets.port);
|
||||
|
||||
mutex_lock(&sabi_mutex);
|
||||
|
||||
/* enable memory to be able to write to it */
|
||||
outb(readb(sabi + SABI_HEADER_EN_MEM), port);
|
||||
outb(readb(sabi + sabi_config->header_offsets.en_mem), port);
|
||||
|
||||
/* write out the command */
|
||||
writew(MAIN_FUNCTION, sabi_iface + SABI_IFACE_MAIN);
|
||||
writew(sabi_config->main_function, sabi_iface + SABI_IFACE_MAIN);
|
||||
writew(command, sabi_iface + SABI_IFACE_SUB);
|
||||
writeb(0, sabi_iface + SABI_IFACE_COMPLETE);
|
||||
outb(readb(sabi + SABI_HEADER_IFACEFUNC), port);
|
||||
outb(readb(sabi + sabi_config->header_offsets.iface_func), port);
|
||||
|
||||
/* write protect memory to make it safe */
|
||||
outb(readb(sabi + SABI_HEADER_RE_MEM), port);
|
||||
outb(readb(sabi + sabi_config->header_offsets.re_mem), port);
|
||||
|
||||
/* see if the command actually succeeded */
|
||||
if (readb(sabi_iface + SABI_IFACE_COMPLETE) == 0xaa &&
|
||||
|
@ -156,22 +274,22 @@ exit:
|
|||
static int sabi_set_command(u8 command, u8 data)
|
||||
{
|
||||
int retval = 0;
|
||||
u16 port = readw(sabi + SABI_HEADER_PORT);
|
||||
u16 port = readw(sabi + sabi_config->header_offsets.port);
|
||||
|
||||
mutex_lock(&sabi_mutex);
|
||||
|
||||
/* enable memory to be able to write to it */
|
||||
outb(readb(sabi + SABI_HEADER_EN_MEM), port);
|
||||
outb(readb(sabi + sabi_config->header_offsets.en_mem), port);
|
||||
|
||||
/* write out the command */
|
||||
writew(MAIN_FUNCTION, sabi_iface + SABI_IFACE_MAIN);
|
||||
writew(sabi_config->main_function, sabi_iface + SABI_IFACE_MAIN);
|
||||
writew(command, sabi_iface + SABI_IFACE_SUB);
|
||||
writeb(0, sabi_iface + SABI_IFACE_COMPLETE);
|
||||
writeb(data, sabi_iface + SABI_IFACE_DATA);
|
||||
outb(readb(sabi + SABI_HEADER_IFACEFUNC), port);
|
||||
outb(readb(sabi + sabi_config->header_offsets.iface_func), port);
|
||||
|
||||
/* write protect memory to make it safe */
|
||||
outb(readb(sabi + SABI_HEADER_RE_MEM), port);
|
||||
outb(readb(sabi + sabi_config->header_offsets.re_mem), port);
|
||||
|
||||
/* see if the command actually succeeded */
|
||||
if (readb(sabi_iface + SABI_IFACE_COMPLETE) == 0xaa &&
|
||||
|
@ -194,21 +312,21 @@ static void test_backlight(void)
|
|||
{
|
||||
struct sabi_retval sretval;
|
||||
|
||||
sabi_get_command(GET_BACKLIGHT, &sretval);
|
||||
sabi_get_command(sabi_config->commands.get_backlight, &sretval);
|
||||
printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
|
||||
|
||||
sabi_set_command(SET_BACKLIGHT, 0);
|
||||
sabi_set_command(sabi_config->commands.set_backlight, 0);
|
||||
printk(KERN_DEBUG "backlight should be off\n");
|
||||
|
||||
sabi_get_command(GET_BACKLIGHT, &sretval);
|
||||
sabi_get_command(sabi_config->commands.get_backlight, &sretval);
|
||||
printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
|
||||
|
||||
msleep(1000);
|
||||
|
||||
sabi_set_command(SET_BACKLIGHT, 1);
|
||||
sabi_set_command(sabi_config->commands.set_backlight, 1);
|
||||
printk(KERN_DEBUG "backlight should be on\n");
|
||||
|
||||
sabi_get_command(GET_BACKLIGHT, &sretval);
|
||||
sabi_get_command(sabi_config->commands.get_backlight, &sretval);
|
||||
printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
|
||||
}
|
||||
|
||||
|
@ -216,21 +334,21 @@ static void test_wireless(void)
|
|||
{
|
||||
struct sabi_retval sretval;
|
||||
|
||||
sabi_get_command(GET_WIRELESS_BUTTON, &sretval);
|
||||
sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
|
||||
printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
|
||||
|
||||
sabi_set_command(SET_WIRELESS_BUTTON, 0);
|
||||
sabi_set_command(sabi_config->commands.set_wireless_button, 0);
|
||||
printk(KERN_DEBUG "wireless led should be off\n");
|
||||
|
||||
sabi_get_command(GET_WIRELESS_BUTTON, &sretval);
|
||||
sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
|
||||
printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
|
||||
|
||||
msleep(1000);
|
||||
|
||||
sabi_set_command(SET_WIRELESS_BUTTON, 1);
|
||||
sabi_set_command(sabi_config->commands.set_wireless_button, 1);
|
||||
printk(KERN_DEBUG "wireless led should be on\n");
|
||||
|
||||
sabi_get_command(GET_WIRELESS_BUTTON, &sretval);
|
||||
sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
|
||||
printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
|
||||
}
|
||||
|
||||
|
@ -240,7 +358,7 @@ static u8 read_brightness(void)
|
|||
int user_brightness = 0;
|
||||
int retval;
|
||||
|
||||
retval = sabi_get_command(GET_BRIGHTNESS, &sretval);
|
||||
retval = sabi_get_command(sabi_config->commands.get_brightness, &sretval);
|
||||
if (!retval)
|
||||
user_brightness = sretval.retval[0];
|
||||
if (user_brightness != 0)
|
||||
|
@ -250,7 +368,7 @@ static u8 read_brightness(void)
|
|||
|
||||
static void set_brightness(u8 user_brightness)
|
||||
{
|
||||
sabi_set_command(SET_BRIGHTNESS, user_brightness + 1);
|
||||
sabi_set_command(sabi_config->commands.set_brightness, user_brightness + 1);
|
||||
}
|
||||
|
||||
static int get_brightness(struct backlight_device *bd)
|
||||
|
@ -263,9 +381,9 @@ static int update_status(struct backlight_device *bd)
|
|||
set_brightness(bd->props.brightness);
|
||||
|
||||
if (bd->props.power == FB_BLANK_UNBLANK)
|
||||
sabi_set_command(SET_BACKLIGHT, 1);
|
||||
sabi_set_command(sabi_config->commands.set_backlight, 1);
|
||||
else
|
||||
sabi_set_command(SET_BACKLIGHT, 0);
|
||||
sabi_set_command(sabi_config->commands.set_backlight, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -282,9 +400,9 @@ static int rfkill_set(void *data, bool blocked)
|
|||
* blocked == true is off
|
||||
*/
|
||||
if (blocked)
|
||||
sabi_set_command(SET_WIRELESS_BUTTON, 0);
|
||||
sabi_set_command(sabi_config->commands.set_wireless_button, 0);
|
||||
else
|
||||
sabi_set_command(SET_WIRELESS_BUTTON, 1);
|
||||
sabi_set_command(sabi_config->commands.set_wireless_button, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -317,47 +435,51 @@ static void destroy_wireless(void)
|
|||
rfkill_destroy(rfk);
|
||||
}
|
||||
|
||||
static ssize_t get_silent_state(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t get_performance_level(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct sabi_retval sretval;
|
||||
int retval;
|
||||
int pLevel;
|
||||
|
||||
/* Read the state */
|
||||
retval = sabi_get_command(GET_PERFORMANCE_LEVEL, &sretval);
|
||||
retval = sabi_get_command(sabi_config->commands.get_performance_level, &sretval);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
/* The logic is backwards, yeah, lots of fun... */
|
||||
if (sretval.retval[0] == 0)
|
||||
retval = 1;
|
||||
else
|
||||
retval = 0;
|
||||
return sprintf(buf, "%d\n", retval);
|
||||
for (pLevel = 0; sabi_config->performance_levels[pLevel].name; ++pLevel)
|
||||
{
|
||||
if (sretval.retval[0] == sabi_config->performance_levels[pLevel].value)
|
||||
return sprintf(buf, "%s\n", sabi_config->performance_levels[pLevel].name);
|
||||
}
|
||||
return sprintf(buf, "%s\n", "unknown");
|
||||
}
|
||||
|
||||
static ssize_t set_silent_state(struct device *dev,
|
||||
static ssize_t set_performance_level(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
char value;
|
||||
|
||||
if (count >= 1) {
|
||||
value = buf[0];
|
||||
if ((value == '0') || (value == 'n') || (value == 'N')) {
|
||||
/* Turn speed up */
|
||||
sabi_set_command(SET_PERFORMANCE_LEVEL, 0x01);
|
||||
} else if ((value == '1') || (value == 'y') || (value == 'Y')) {
|
||||
/* Turn speed down */
|
||||
sabi_set_command(SET_PERFORMANCE_LEVEL, 0x00);
|
||||
} else {
|
||||
return -EINVAL;
|
||||
int pLevel;
|
||||
for (pLevel = 0; sabi_config->performance_levels[pLevel].name; ++pLevel)
|
||||
{
|
||||
struct sabi_performance_level *level =
|
||||
&sabi_config->performance_levels[pLevel];
|
||||
if (!strncasecmp(level->name, buf, strlen(level->name)))
|
||||
{
|
||||
sabi_set_command(sabi_config->commands.set_performance_level,
|
||||
level->value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!sabi_config->performance_levels[pLevel].name)
|
||||
return -EINVAL;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR(silent, S_IWUSR | S_IRUGO,
|
||||
get_silent_state, set_silent_state);
|
||||
static DEVICE_ATTR(performance_level, S_IWUSR | S_IRUGO,
|
||||
get_performance_level, set_performance_level);
|
||||
|
||||
|
||||
static int __init dmi_check_cb(const struct dmi_system_id *id)
|
||||
|
@ -392,14 +514,31 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(dmi, samsung_dmi_table);
|
||||
|
||||
static int find_signature(void __iomem *memcheck, const char *testStr)
|
||||
{
|
||||
int pStr;
|
||||
int loca;
|
||||
pStr = 0;
|
||||
for (loca = 0; loca < 0xffff; loca++) {
|
||||
char temp = readb(memcheck + loca);
|
||||
|
||||
if (temp == testStr[pStr]) {
|
||||
if (pStr == strlen(testStr)-1)
|
||||
break;
|
||||
++pStr;
|
||||
} else {
|
||||
pStr = 0;
|
||||
}
|
||||
}
|
||||
return loca;
|
||||
}
|
||||
|
||||
static int __init samsung_init(void)
|
||||
{
|
||||
struct backlight_properties props;
|
||||
struct sabi_retval sretval;
|
||||
const char *testStr = "SECLINUX";
|
||||
void __iomem *memcheck;
|
||||
unsigned int ifaceP;
|
||||
int pStr;
|
||||
int pConfig;
|
||||
int loca;
|
||||
int retval;
|
||||
|
||||
|
@ -414,50 +553,45 @@ static int __init samsung_init(void)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Try to find the signature "SECLINUX" in memory to find the header */
|
||||
pStr = 0;
|
||||
memcheck = f0000_segment;
|
||||
for (loca = 0; loca < 0xffff; loca++) {
|
||||
char temp = readb(memcheck + loca);
|
||||
|
||||
if (temp == testStr[pStr]) {
|
||||
if (pStr == strlen(testStr)-1)
|
||||
break;
|
||||
++pStr;
|
||||
} else {
|
||||
pStr = 0;
|
||||
}
|
||||
/* Try to find one of the signatures in memory to find the header */
|
||||
for (pConfig = 0; sabi_configs[pConfig].test_string != 0; ++pConfig)
|
||||
{
|
||||
sabi_config = &sabi_configs[pConfig];
|
||||
loca = find_signature(f0000_segment, sabi_config->test_string);
|
||||
if (loca != 0xffff)
|
||||
break;
|
||||
}
|
||||
|
||||
if (loca == 0xffff) {
|
||||
printk(KERN_ERR "This computer does not support SABI\n");
|
||||
goto error_no_signature;
|
||||
}
|
||||
}
|
||||
|
||||
/* point to the SMI port Number */
|
||||
loca += 1;
|
||||
sabi = (memcheck + loca);
|
||||
sabi = (f0000_segment + loca);
|
||||
|
||||
if (debug) {
|
||||
printk(KERN_DEBUG "This computer supports SABI==%x\n",
|
||||
loca + 0xf0000 - 6);
|
||||
printk(KERN_DEBUG "SABI header:\n");
|
||||
printk(KERN_DEBUG " SMI Port Number = 0x%04x\n",
|
||||
readw(sabi + SABI_HEADER_PORT));
|
||||
readw(sabi + sabi_config->header_offsets.port));
|
||||
printk(KERN_DEBUG " SMI Interface Function = 0x%02x\n",
|
||||
readb(sabi + SABI_HEADER_IFACEFUNC));
|
||||
readb(sabi + sabi_config->header_offsets.iface_func));
|
||||
printk(KERN_DEBUG " SMI enable memory buffer = 0x%02x\n",
|
||||
readb(sabi + SABI_HEADER_EN_MEM));
|
||||
readb(sabi + sabi_config->header_offsets.en_mem));
|
||||
printk(KERN_DEBUG " SMI restore memory buffer = 0x%02x\n",
|
||||
readb(sabi + SABI_HEADER_RE_MEM));
|
||||
readb(sabi + sabi_config->header_offsets.re_mem));
|
||||
printk(KERN_DEBUG " SABI data offset = 0x%04x\n",
|
||||
readw(sabi + SABI_HEADER_DATA_OFFSET));
|
||||
readw(sabi + sabi_config->header_offsets.data_offset));
|
||||
printk(KERN_DEBUG " SABI data segment = 0x%04x\n",
|
||||
readw(sabi + SABI_HEADER_DATA_SEGMENT));
|
||||
readw(sabi + sabi_config->header_offsets.data_segment));
|
||||
}
|
||||
|
||||
/* Get a pointer to the SABI Interface */
|
||||
ifaceP = (readw(sabi + SABI_HEADER_DATA_SEGMENT) & 0x0ffff) << 4;
|
||||
ifaceP += readw(sabi + SABI_HEADER_DATA_OFFSET) & 0x0ffff;
|
||||
ifaceP = (readw(sabi + sabi_config->header_offsets.data_segment) & 0x0ffff) << 4;
|
||||
ifaceP += readw(sabi + sabi_config->header_offsets.data_offset) & 0x0ffff;
|
||||
sabi_iface = ioremap(ifaceP, 16);
|
||||
if (!sabi_iface) {
|
||||
printk(KERN_ERR "Can't remap %x\n", ifaceP);
|
||||
|
@ -470,15 +604,18 @@ static int __init samsung_init(void)
|
|||
test_backlight();
|
||||
test_wireless();
|
||||
|
||||
retval = sabi_get_command(GET_BRIGHTNESS, &sretval);
|
||||
retval = sabi_get_command(sabi_config->commands.get_brightness, &sretval);
|
||||
printk(KERN_DEBUG "brightness = 0x%02x\n", sretval.retval[0]);
|
||||
}
|
||||
|
||||
/* Turn on "Linux" mode in the BIOS */
|
||||
retval = sabi_set_command(SET_LINUX, 0x81);
|
||||
if (retval) {
|
||||
printk(KERN_ERR KBUILD_MODNAME ": Linux mode was not set!\n");
|
||||
goto error_no_platform;
|
||||
if (sabi_config->commands.set_linux != 0xff)
|
||||
{
|
||||
retval = sabi_set_command(sabi_config->commands.set_linux, 0x81);
|
||||
if (retval) {
|
||||
printk(KERN_ERR KBUILD_MODNAME ": Linux mode was not set!\n");
|
||||
goto error_no_platform;
|
||||
}
|
||||
}
|
||||
|
||||
/* knock up a platform device to hang stuff off of */
|
||||
|
@ -503,7 +640,7 @@ static int __init samsung_init(void)
|
|||
if (retval)
|
||||
goto error_no_rfk;
|
||||
|
||||
retval = device_create_file(&sdev->dev, &dev_attr_silent);
|
||||
retval = device_create_file(&sdev->dev, &dev_attr_performance_level);
|
||||
if (retval)
|
||||
goto error_file_create;
|
||||
|
||||
|
@ -530,9 +667,10 @@ error_no_signature:
|
|||
static void __exit samsung_exit(void)
|
||||
{
|
||||
/* Turn off "Linux" mode in the BIOS */
|
||||
sabi_set_command(SET_LINUX, 0x80);
|
||||
if (sabi_config->commands.set_linux != 0xff)
|
||||
sabi_set_command(sabi_config->commands.set_linux, 0x80);
|
||||
|
||||
device_remove_file(&sdev->dev, &dev_attr_silent);
|
||||
device_remove_file(&sdev->dev, &dev_attr_performance_level);
|
||||
backlight_device_unregister(backlight_device);
|
||||
destroy_wireless();
|
||||
iounmap(sabi_iface);
|
||||
|
|
Загрузка…
Ссылка в новой задаче