2
* nbsmi.c -- Toshiba SMI low-level acces code
4
* This program is free software; you can redistribute it and/or modify it
5
* under the terms of the GNU General Public License as published by the
6
* Free Software Foundation; either version 2, or (at your option) any
9
* This program is distributed in the hope that it will be useful, but
10
* WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* General Public License for more details.
14
* Written by Mathieu Bérard <mathieu.berard@crans.org>, 2006
16
* Sources of inspirations for this code were:
17
* -Toshiba via provided hardware specification
18
* -Thorsten Zachmann with the 's1bl' project
19
* -Frederico Munoz with the 'tecra_acpi' project
25
#include <linux/preempt.h>
26
#include <linux/pci.h>
27
#include <linux/kref.h>
29
#include <asm/mc146818rtc.h>
30
#include <linux/workqueue.h>
31
#include <linux/delay.h>
33
/* copied from drivers/input/serio/i8042-io.h */
34
#define I8042_KBD_PHYS_DESC "isa0060/serio0"
37
* ATI's IXP PCI-LPC bridge
39
#define INTEL_PMBASE 0x40
40
#define INTEL_GPE0_EN 0x2c
42
#define BUFFER_SIZE 0x20
43
#define INTEL_OFFSET 0x60
44
#define INTEL_SMI_PORT 0xb2 /* APM_CNT port in INTEL ICH specs */
47
* Toshiba Specs state 0xef here but:
48
* -this would overflow (ef + 19 > ff)
49
* -code from Toshiba use e0, which make much more sense
52
#define ATI_OFFSET 0xe0
53
#define ATI_SMI_PORT 0xb0
55
#define EC_INDEX_PORT 0x300
56
#define EC_DATA_PORT 0x301
58
/* Masks decode for GetAeral */
65
* Private data of this backend
67
struct nbsmi_backend_data {
68
struct pci_dev *lpc_bridge; /* Southbridge chip ISA bridge/LPC interface PCI device */
69
u8 start_offset; /* Start offset in CMOS memory */
70
struct input_dev *nbsmi_input_dev;
71
struct work_struct fnkey_work;
75
* Possible list of supported southbridges
76
* Here mostly to implement a more or less clean PCI probing
77
* Works only because of previous DMI probing.
80
extern const struct pci_device_id lpc_bridge_table[];
83
* Since we are going to trigger an SMI, all registers (I assume this does not
84
* include esp and maybe ebp) and eflags may be mangled in the
86
* We also disable preemtion and IRQs upon SMI call.
88
static inline u32 ati_do_smi_call(u16 function)
93
local_irq_save(flags);
97
* eflags, eax, ebx, ecx, edx, esi and edi are clobbered upon writing to SMI_PORT
98
* thus the clobber list.
100
* Equivalent pseudocode:
102
* eax = function; [non null]
103
* outw(eax, ATI_SMI_PORT); <- This Trigger an SMI
104
* if( eax == 0 ) [success if eax has been cleared]
106
* if( inb(ATI_SMI_PORT + 1) == 0) [if not in eax, success maybe be stored here]
108
* retval = -EIO; [too bad]
111
__asm__ __volatile__("outw %%ax, %2; \
120
: "a"(function), "N"(ATI_SMI_PORT), "N"(ATI_SMI_PORT+1), "i"(-EIO)
121
: "memory", "ebx", "ecx", "edx", "esi", "edi", "cc");
123
local_irq_restore(flags);
124
preempt_enable_no_resched();
128
static inline u32 intel_do_smi_call(u16 function, struct pci_dev *lpc_bridge)
135
local_irq_save(flags);
139
* We get the PMBASE offset ( bits 15:7 at 0x40 offset of PCI config space )
140
* And we access offset 2c (GPE0_EN), save the state, disable all SCI
141
* and restore the state after the SMI call
143
pci_read_config_dword(lpc_bridge, INTEL_PMBASE, &sci_en);
144
sci_en = sci_en & 0xff80; /* Keep bits 15:7 */
145
sci_en += INTEL_GPE0_EN; /* GPEO_EN offset */
150
* eflags, eax, ebx, ecx, edx, esi and edi are clobbered upon writing to SMI_PORT
151
* thus the clobber list.
153
* Equivalent pseudocode:
155
* eax = function; [non null]
156
* outw(eax, INTEL_SMI_PORT); <- This Trigger an SMI
157
* if( eax == 0 ) [success if eax has been cleared]
159
* retval = -EIO; [too bad]
162
__asm__ __volatile__("outw %%ax, %2; \
168
: "a"(function), "N"(INTEL_SMI_PORT), "i"(-EIO)
169
: "memory", "ebx", "ecx", "edx", "esi", "edi", "cc");
172
local_irq_restore(flags);
173
preempt_enable_no_resched();
177
static int nbsmi_smi_command(u16 function,
178
const u8 * inputbuffer,
180
const struct nbsmi_backend_data *priv_data)
186
for (count = 0; count < BUFFER_SIZE; count++) {
187
outb(count + priv_data->start_offset, RTC_PORT(2));
188
outb(*(inputbuffer + count), RTC_PORT(3));
192
* We have to write 0xe4XX to smi_port
193
* where XX is the SMI function code
195
function = (function & 0xff) << 8;
198
switch (priv_data->lpc_bridge->vendor) {
199
case PCI_VENDOR_ID_INTEL:
200
retval = intel_do_smi_call(function, priv_data->lpc_bridge);
202
case PCI_VENDOR_ID_ATI:
203
retval = ati_do_smi_call(function);
210
printk(O_ERR "smi_command failed with error %u.\n", retval);
212
for (count = 0; count < BUFFER_SIZE; count++) {
213
outb(count + priv_data->start_offset, RTC_PORT(2));
214
*(outputbuffer + count) = inb(RTC_PORT(3));
220
static int nbsmi_smi_read_command(const struct omnibook_operation *io_op, u8 * data)
225
struct nbsmi_backend_data *priv_data = io_op->backend->data;
230
inputbuffer = kcalloc(BUFFER_SIZE, sizeof(u8), GFP_KERNEL);
236
outputbuffer = kcalloc(BUFFER_SIZE, sizeof(u8), GFP_KERNEL);
242
retval = nbsmi_smi_command((u16) io_op->read_addr, inputbuffer, outputbuffer, priv_data);
246
*data = outputbuffer[0];
248
if (io_op->read_mask)
249
*data &= io_op->read_mask;
259
static int nbsmi_smi_write_command(const struct omnibook_operation *io_op, u8 data)
264
struct nbsmi_backend_data *priv_data = io_op->backend->data;
269
inputbuffer = kcalloc(BUFFER_SIZE, sizeof(u8), GFP_KERNEL);
275
outputbuffer = kcalloc(BUFFER_SIZE, sizeof(u8), GFP_KERNEL);
281
inputbuffer[0] = data;
283
retval = nbsmi_smi_command((u16) io_op->write_addr, inputbuffer, outputbuffer, priv_data);
293
* Read/Write to INDEX/DATA interface at port 0x300 (SMSC Mailbox registers)
295
static inline void nbsmi_ec_read_command(u8 index, u8 * data)
297
outb(index, EC_INDEX_PORT);
298
*data = inb(EC_DATA_PORT);
302
static inline void nbsmi_ec_write_command(u8 index, u8 data)
304
outb(index, EC_INDEX_PORT);
305
outb(data, EC_DATA_PORT);
313
* 2. Scancode 0x6d generated by kbd controller
314
* 3. Scancode 0x6d caught by omnibook input handler
315
* 4. SMI Call issued -> Got keycode of last actually pressed Fn key
316
* 5. nbsmi_scan_table used to associate a detected keycode with a generated one
317
* 6. Generated keycode issued using the omnibook input device
321
* The input handler should only bind with the standard AT keyboard.
322
* XXX: Scancode 0x6d won't be detected if the keyboard has already been
323
* grabbed (the Xorg event input driver do that)
325
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21))
326
static int hook_connect(struct input_handler *handler,
327
struct input_dev *dev,
328
const struct input_device_id *id)
329
#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
330
static struct input_handle *hook_connect(struct input_handler *handler,
331
struct input_dev *dev,
332
const struct input_device_id *id)
334
static struct input_handle *hook_connect(struct input_handler *handler,
335
struct input_dev *dev,
336
struct input_device_id *id)
339
struct input_handle *handle;
342
/* the 0x0001 vendor magic number is found in atkbd.c */
343
if(!(dev->id.bustype == BUS_I8042 && dev->id.vendor == 0x0001))
346
if(!strstr(dev->phys, I8042_KBD_PHYS_DESC))
349
dprintk("hook_connect for device %s.\n", dev->name);
352
printk(O_WARN "Input device is grabbed by %s, Fn hotkeys won't work.\n",
355
handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
357
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21))
364
handle->handler = handler;
365
handle->name = "omnibook_scancode_hook";
366
handle->private = handler->private;
368
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21))
369
error = input_register_handle(handle);
371
dprintk("register_handle failed\n");
372
goto out_nobind_free;
374
error = input_open_device(handle);
376
dprintk("register_handle failed\n");
377
input_unregister_handle(handle);
378
goto out_nobind_free;
382
error = input_open_device(handle);
383
if (error==0) dprintk("Input device opened\n");
385
dprintk("opening input device failed\n");
386
goto out_nobind_free;
390
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21))
405
static void hook_disconnect(struct input_handle *handle)
407
dprintk("hook_disconnect.\n");
408
input_close_device(handle);
409
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21))
410
input_unregister_handle(handle);
416
* Hook for scancode 0x6d. Actual handling is done in a workqueue as
417
* the nbsmi backend might sleep.
420
static void hook_event(struct input_handle *handle, unsigned int event_type,
421
unsigned int event_code, int value)
423
if (event_type == EV_MSC && event_code == MSC_SCAN && value == SMI_FN_SCAN)
424
schedule_work(&((struct nbsmi_backend_data *)handle->private)->fnkey_work);
427
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
428
static const struct input_device_id hook_ids[] = {
430
static struct input_device_id hook_ids[] = {
433
.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
434
.evbit = { BIT(EV_KEY) },
436
{ }, /* Terminating entry */
439
static struct input_handler hook_handler = {
441
.connect = hook_connect,
442
.disconnect = hook_disconnect,
443
.name = OMNIBOOK_MODULE_NAME,
444
.id_table = hook_ids,
448
* Define some KEY_ that may be missing in input.h for some kernel versions
455
* Detected scancode to keycode table
457
static const struct {
458
unsigned int scancode;
459
unsigned int keycode;
460
} nbsmi_scan_table[] = {
461
{ KEY_ESC, KEY_MUTE},
462
{ KEY_F1, KEY_FN_F1},
463
{ KEY_F2, KEY_PROG1},
464
{ KEY_F3, KEY_SLEEP},
465
{ KEY_F4, KEY_SUSPEND},
466
{ KEY_F5, KEY_SWITCHVIDEOMODE},
467
{ KEY_F6, KEY_BRIGHTNESSDOWN},
468
{ KEY_F7, KEY_BRIGHTNESSUP},
470
{ KEY_F9, KEY_FN_F9},
471
{ KEY_SPACE, KEY_ZOOM},
475
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19))
476
static void omnibook_handle_fnkey(struct work_struct *work);
478
static void omnibook_handle_fnkey(void* data);
482
* Register the input handler and the input device in the input subsystem
484
static int register_input_subsystem(struct nbsmi_backend_data *priv_data)
487
struct input_dev *nbsmi_input_dev;
489
nbsmi_input_dev = input_allocate_device();
490
if (!nbsmi_input_dev) {
495
nbsmi_input_dev->name = "Omnibook NbSMI scancode generator";
496
nbsmi_input_dev->phys = "omnibook/input0";
497
nbsmi_input_dev->id.bustype = BUS_HOST;
499
set_bit(EV_KEY, nbsmi_input_dev->evbit);
501
for(i=0 ; i < ARRAY_SIZE(nbsmi_scan_table); i++)
502
set_bit(nbsmi_scan_table[i].keycode, nbsmi_input_dev->keybit);
504
retval = input_register_device(nbsmi_input_dev);
506
input_free_device(nbsmi_input_dev);
510
priv_data->nbsmi_input_dev = nbsmi_input_dev;
512
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19))
513
INIT_WORK(&priv_data->fnkey_work, *omnibook_handle_fnkey);
515
INIT_WORK(&priv_data->fnkey_work, *omnibook_handle_fnkey, priv_data);
519
hook_handler.private = priv_data;
521
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
522
retval = input_register_handler(&hook_handler);
524
input_register_handler(&hook_handler);
532
* Try to init the backend
533
* This function can be called blindly as it use a kref
534
* to check if the init sequence was already done.
536
static int omnibook_nbsmi_init(const struct omnibook_operation *io_op)
542
struct nbsmi_backend_data *priv_data;
544
/* ectypes other than TSM40 have no business with this backend */
545
if (!(omnibook_ectype & TSM40))
548
if (io_op->backend->already_failed) {
549
dprintk("NbSmi backend init already failed, skipping.\n");
553
if (!io_op->backend->data) {
554
/* Fist use of the backend */
555
dprintk("Try to init NbSmi\n");
556
mutex_init(&io_op->backend->mutex);
557
mutex_lock(&io_op->backend->mutex);
558
kref_init(&io_op->backend->kref);
560
priv_data = kzalloc(sizeof(struct nbsmi_backend_data), GFP_KERNEL);
566
/* PCI probing: find the LPC Super I/O bridge PCI device */
567
for (i = 0; !priv_data->lpc_bridge && lpc_bridge_table[i].vendor; ++i)
568
priv_data->lpc_bridge =
569
pci_get_device(lpc_bridge_table[i].vendor, lpc_bridge_table[i].device,
572
if (!priv_data->lpc_bridge) {
573
printk(O_ERR "Fail to find a supported LPC I/O bridge, please report\n");
578
if ((retval = pci_enable_device(priv_data->lpc_bridge))) {
579
printk(O_ERR "Unable to enable PCI device.\n");
583
switch (priv_data->lpc_bridge->vendor) {
584
case PCI_VENDOR_ID_INTEL:
585
priv_data->start_offset = INTEL_OFFSET;
586
smi_port = INTEL_SMI_PORT;
588
case PCI_VENDOR_ID_ATI:
589
priv_data->start_offset = ATI_OFFSET;
590
smi_port = ATI_SMI_PORT;
596
if (!request_region(smi_port, 2, OMNIBOOK_MODULE_NAME)) {
597
printk(O_ERR "Request SMI I/O region error\n");
602
if (!request_region(EC_INDEX_PORT, 2, OMNIBOOK_MODULE_NAME)) {
603
printk(O_ERR "Request EC I/O region error\n");
609
* Try some heuristic tests to avoid enabling this interface on unsuported laptops:
610
* See what a port 300h read index 8f gives. Guess there is nothing if read 0xff
613
nbsmi_ec_read_command(SMI_FN_PRESSED, &ec_data);
614
dprintk("NbSmi test probe read: %x\n", ec_data);
615
if (ec_data == 0xff) {
616
printk(O_ERR "Probing at SMSC Mailbox registers failed, disabling NbSmi\n");
621
retval = register_input_subsystem(priv_data);
625
io_op->backend->data = priv_data;
627
dprintk("NbSmi init ok\n");
628
mutex_unlock(&io_op->backend->mutex);
631
dprintk("NbSmi has already been initialized\n");
632
kref_get(&io_op->backend->kref);
636
release_region(EC_INDEX_PORT, 2);
638
release_region(smi_port, 2);
640
pci_dev_put(priv_data->lpc_bridge);
643
io_op->backend->data = NULL;
645
io_op->backend->already_failed = 1;
646
mutex_unlock(&io_op->backend->mutex);
647
mutex_destroy(&io_op->backend->mutex);
652
* Free all allocated stuff and unregister from the input subsystem
654
static void nbsmi_free(struct kref *ref)
657
struct omnibook_backend *backend;
658
struct nbsmi_backend_data *priv_data;
660
dprintk("NbSmi not used anymore: disposing\n");
662
backend = container_of(ref, struct omnibook_backend, kref);
663
priv_data = backend->data;
665
flush_scheduled_work();
666
input_unregister_handler(&hook_handler);
667
input_unregister_device(priv_data->nbsmi_input_dev);
669
mutex_lock(&backend->mutex);
671
switch (priv_data->lpc_bridge->vendor) {
672
case PCI_VENDOR_ID_INTEL:
673
smi_port = INTEL_SMI_PORT;
675
case PCI_VENDOR_ID_ATI:
676
smi_port = ATI_SMI_PORT;
682
pci_dev_put(priv_data->lpc_bridge);
683
release_region(smi_port, 2);
684
release_region(EC_INDEX_PORT, 2);
686
backend->data = NULL;
687
mutex_unlock(&backend->mutex);
688
mutex_destroy(&backend->mutex);
691
static void omnibook_nbsmi_exit(const struct omnibook_operation *io_op)
693
/* ectypes other than TSM40 have no business with this backend */
694
BUG_ON(!(omnibook_ectype & TSM40));
695
dprintk("Trying to dispose NbSmi\n");
696
kref_put(&io_op->backend->kref, nbsmi_free);
700
* Adjust the lcd backlight level by delta.
701
* Used for Fn+F6/F7 keypress
703
static int adjust_brighness(int delta)
705
struct omnibook_feature *lcd_feature = omnibook_find_feature("lcd");
706
struct omnibook_operation *io_op;
713
io_op = lcd_feature->io_op;
715
mutex_lock(&io_op->backend->mutex);
717
if(( retval = __backend_byte_read(io_op, &brgt)))
720
dprintk("FnF6/F7 pressed: adjusting britghtnes.\n");
722
if (((int) brgt + delta) < 0)
724
else if ((brgt + delta) > omnibook_max_brightness)
725
brgt = omnibook_max_brightness;
729
retval = __backend_byte_write(io_op, brgt);
732
mutex_unlock(&io_op->backend->mutex);
736
static const struct omnibook_operation last_scan_op = SIMPLE_BYTE(SMI,SMI_GET_FN_LAST_SCAN,0);
739
* Workqueue handler for Fn hotkeys
741
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19))
742
static void omnibook_handle_fnkey(struct work_struct *work)
744
static void omnibook_handle_fnkey(void* data)
749
struct input_dev *input_dev;
751
if(backend_byte_read(&last_scan_op, &gen_scan))
754
dprintk("detected scancode %x.\n", gen_scan);
757
adjust_brighness(-1);
760
adjust_brighness(+1);
764
for(i = 0 ; i < ARRAY_SIZE(nbsmi_scan_table); i++) {
765
if( gen_scan == nbsmi_scan_table[i].scancode) {
766
dprintk("generating keycode %i.\n", nbsmi_scan_table[i].keycode);
767
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19))
768
input_dev = container_of(work, struct nbsmi_backend_data, fnkey_work)->nbsmi_input_dev;
770
input_dev = ((struct nbsmi_backend_data *) data)->nbsmi_input_dev;
772
omnibook_report_key(input_dev, nbsmi_scan_table[i].keycode);
778
static int omnibook_nbsmi_get_wireless(const struct omnibook_operation *io_op, unsigned int *state)
781
struct omnibook_operation aerial_op = SIMPLE_BYTE(SMI, SMI_GET_KILL_SWITCH, 0);
784
if ((retval = nbsmi_smi_read_command(&aerial_op, &data)))
787
dprintk("get_wireless (kill switch) raw_state: %x\n", data);
789
*state = data ? KILLSWITCH : 0;
791
aerial_op.read_addr = SMI_GET_AERIAL;
793
if ((retval = nbsmi_smi_read_command(&aerial_op, &data)))
796
dprintk("get_wireless (aerial) raw_state: %x\n", data);
798
*state |= (data & WLEX_MASK) ? WIFI_EX : 0;
799
*state |= (data & WLAT_MASK) ? WIFI_STA : 0;
800
*state |= (data & BTEX_MASK) ? BT_EX : 0;
801
*state |= (data & BTAT_MASK) ? BT_STA : 0;
807
static int omnibook_nbsmi_set_wireless(const struct omnibook_operation *io_op, unsigned int state)
811
struct omnibook_operation aerial_op = SIMPLE_BYTE(SMI, SMI_SET_AERIAL, 0);
813
data = !!(state & BT_STA);
814
data |= !!(state & WIFI_STA) << 0x1;
816
dprintk("set_wireless raw_state: %x\n", data);
818
retval = nbsmi_smi_write_command(&aerial_op, data);
823
static int omnibook_nbmsi_hotkeys_get(const struct omnibook_operation *io_op, unsigned int *state)
827
struct omnibook_operation hotkeys_op = SIMPLE_BYTE(SMI, SMI_GET_FN_INTERFACE, 0);
829
retval = nbsmi_smi_read_command(&hotkeys_op, &data);
833
dprintk("get_hotkeys raw_state: %x\n", data);
835
*state = (data & SMI_FN_KEYS_MASK) ? HKEY_FN : 0;
836
*state |= (data & SMI_STICK_KEYS_MASK) ? HKEY_STICK : 0;
837
*state |= (data & SMI_FN_TWICE_LOCK_MASK) ? HKEY_TWICE_LOCK : 0;
838
*state |= (data & SMI_FN_DOCK_MASK) ? HKEY_DOCK : 0;
844
static int omnibook_nbmsi_hotkeys_set(const struct omnibook_operation *io_op, unsigned int state)
848
struct omnibook_operation hotkeys_op = SIMPLE_BYTE(SMI, SMI_SET_FN_F5_INTERFACE, 0);
851
data = !!(state & HKEY_FNF5);
853
dprintk("set_hotkeys (Fn F5) raw_state: %x\n", data);
855
retval = nbsmi_smi_write_command(&hotkeys_op, data);
859
hotkeys_op.write_addr = SMI_SET_FN_INTERFACE;
860
hotkeys_op.read_addr = SMI_GET_FN_INTERFACE;
862
data = (state & HKEY_FN) ? SMI_FN_KEYS_MASK : 0;
863
data |= (state & HKEY_STICK) ? SMI_STICK_KEYS_MASK : 0;
864
data |= (state & HKEY_TWICE_LOCK) ? SMI_FN_TWICE_LOCK_MASK : 0;
865
data |= (state & HKEY_DOCK) ? SMI_FN_DOCK_MASK : 0;
867
dprintk("set_hotkeys (Fn interface) raw_state: %x\n", data);
870
* Hardware seems to be quite stubborn and multiple retries may be
871
* required. The criteria here is simple: retry until probed state match
872
* the requested one (with timeout).
875
data_array = kcalloc(250, sizeof(u8), GFP_KERNEL);
879
for (i = 0; i < 250; i++) {
880
retval = nbsmi_smi_write_command(&hotkeys_op, data);
884
retval = nbsmi_smi_read_command(&hotkeys_op, &rdata);
887
data_array[i] = rdata;
889
dprintk("check loop ok after %i iters\n.",i);
894
dprintk("error or check loop timeout !!\n");
895
dprintk("forensics datas: ");
896
for (i = 0; i < 250; i++)
897
dprintk_simple("%x ", data_array[i]);
898
dprintk_simple("\n");
904
static const unsigned int nbsmi_display_mode_list[] = {
906
DISPLAY_LCD_ON | DISPLAY_CRT_ON,
908
DISPLAY_LCD_ON | DISPLAY_TVO_ON,
912
static int omnibook_nbmsi_display_get(const struct omnibook_operation *io_op, unsigned int *state)
917
retval = nbsmi_smi_read_command(io_op, &data);
921
if (data > (ARRAY_SIZE(nbsmi_display_mode_list) - 1))
924
*state = nbsmi_display_mode_list[data];
926
return DISPLAY_LCD_ON | DISPLAY_CRT_ON | DISPLAY_TVO_ON;
929
static int omnibook_nbmsi_display_set(const struct omnibook_operation *io_op, unsigned int state)
935
for (i = 0; i < ARRAY_SIZE(nbsmi_display_mode_list); i++) {
936
if (nbsmi_display_mode_list[i] == state) {
943
printk(O_ERR "Display mode %x is unsupported.\n", state);
947
retval = nbsmi_smi_write_command(io_op, matched);
951
return DISPLAY_LCD_ON | DISPLAY_CRT_ON | DISPLAY_TVO_ON;
954
struct omnibook_backend nbsmi_backend = {
956
.hotkeys_read_cap = HKEY_FN | HKEY_STICK | HKEY_TWICE_LOCK | HKEY_DOCK,
957
.hotkeys_write_cap = HKEY_FN | HKEY_STICK | HKEY_TWICE_LOCK | HKEY_DOCK | HKEY_FNF5,
958
.init = omnibook_nbsmi_init,
959
.exit = omnibook_nbsmi_exit,
960
.byte_read = nbsmi_smi_read_command,
961
.byte_write = nbsmi_smi_write_command,
962
.aerial_get = omnibook_nbsmi_get_wireless,
963
.aerial_set = omnibook_nbsmi_set_wireless,
964
.hotkeys_get = omnibook_nbmsi_hotkeys_get,
965
.hotkeys_set = omnibook_nbmsi_hotkeys_set,
966
.display_get = omnibook_nbmsi_display_get,
967
.display_set = omnibook_nbmsi_display_set,