4 * Copyright (C) 2007,2008 Jakub Schmidtke (sjakub@gmail.com)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 * This module is based on usbled and asus-laptop modules.
26 * Asus OLED support is based on asusoled program taken from
27 * <http://lapsus.berlios.de/asus_oled.html>.
32 #include <linux/kernel.h>
33 #include <linux/errno.h>
34 #include <linux/init.h>
35 #include <linux/slab.h>
36 #include <linux/module.h>
37 #include <linux/usb.h>
38 #include <linux/platform_device.h>
39 #include <linux/ctype.h>
41 #define ASUS_OLED_VERSION "0.04-dev"
42 #define ASUS_OLED_NAME "asus-oled"
43 #define ASUS_OLED_UNDERSCORE_NAME "asus_oled"
45 #define ASUS_OLED_STATIC 's'
46 #define ASUS_OLED_ROLL 'r'
47 #define ASUS_OLED_FLASH 'f'
49 #define ASUS_OLED_MAX_WIDTH 1792
50 #define ASUS_OLED_DISP_HEIGHT 32
51 #define ASUS_OLED_PACKET_BUF_SIZE 256
53 #define USB_VENDOR_ID_ASUS 0x0b05
54 #define USB_DEVICE_ID_ASUS_LCM 0x1726
55 #define USB_DEVICE_ID_ASUS_LCM2 0x175b
57 MODULE_AUTHOR("Jakub Schmidtke, sjakub@gmail.com");
58 MODULE_DESCRIPTION("Asus OLED Driver");
59 MODULE_LICENSE("GPL");
60 MODULE_VERSION(ASUS_OLED_VERSION
);
62 static struct class *oled_class
;
65 static uint start_off
;
67 module_param(start_off
, uint
, 0644);
69 MODULE_PARM_DESC(start_off
,
70 "Set to 1 to switch off OLED display after it is attached");
78 struct oled_dev_desc_str
{
81 /* width of display */
83 /* formula to be used while packing the picture */
84 enum oled_pack_mode packMode
;
88 /* table of devices that work with this driver */
89 static const struct usb_device_id id_table
[] = {
90 /* Asus G1/G2 (and variants)*/
91 { USB_DEVICE(USB_VENDOR_ID_ASUS
, USB_DEVICE_ID_ASUS_LCM
) },
92 /* Asus G50V (and possibly others - G70? G71?)*/
93 { USB_DEVICE(USB_VENDOR_ID_ASUS
, USB_DEVICE_ID_ASUS_LCM2
) },
97 /* parameters of specific devices */
98 static struct oled_dev_desc_str oled_dev_desc_table
[] = {
99 { USB_VENDOR_ID_ASUS
, USB_DEVICE_ID_ASUS_LCM
, 128, PACK_MODE_G1
,
101 { USB_VENDOR_ID_ASUS
, USB_DEVICE_ID_ASUS_LCM2
, 256, PACK_MODE_G50
,
106 MODULE_DEVICE_TABLE(usb
, id_table
);
108 struct asus_oled_header
{
119 } __attribute((packed
));
121 struct asus_oled_packet
{
122 struct asus_oled_header header
;
123 uint8_t bitmap
[ASUS_OLED_PACKET_BUF_SIZE
];
124 } __attribute((packed
));
126 struct asus_oled_dev
{
127 struct usb_device
*udev
;
130 enum oled_pack_mode pack_mode
;
140 uint8_t enabled_post_resume
;
144 static void setup_packet_header(struct asus_oled_packet
*packet
, char flags
,
145 char value3
, char buffer1
, char buffer2
, char value6
,
146 char value7
, char value8
)
148 memset(packet
, 0, sizeof(struct asus_oled_header
));
149 packet
->header
.magic1
= 0x55;
150 packet
->header
.magic2
= 0xaa;
151 packet
->header
.flags
= flags
;
152 packet
->header
.value3
= value3
;
153 packet
->header
.buffer1
= buffer1
;
154 packet
->header
.buffer2
= buffer2
;
155 packet
->header
.value6
= value6
;
156 packet
->header
.value7
= value7
;
157 packet
->header
.value8
= value8
;
160 static void enable_oled(struct asus_oled_dev
*odev
, uint8_t enabl
)
164 struct asus_oled_packet
*packet
;
166 packet
= kzalloc(sizeof(struct asus_oled_packet
), GFP_KERNEL
);
170 setup_packet_header(packet
, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00);
173 packet
->bitmap
[0] = 0xaf;
175 packet
->bitmap
[0] = 0xae;
177 retval
= usb_bulk_msg(odev
->udev
,
178 usb_sndbulkpipe(odev
->udev
, 2),
180 sizeof(struct asus_oled_header
) + 1,
185 dev_dbg(&odev
->udev
->dev
, "retval = %d\n", retval
);
187 odev
->enabled
= enabl
;
192 static ssize_t
set_enabled(struct device
*dev
, struct device_attribute
*attr
,
193 const char *buf
, size_t count
)
195 struct usb_interface
*intf
= to_usb_interface(dev
);
196 struct asus_oled_dev
*odev
= usb_get_intfdata(intf
);
198 if (kstrtoul(buf
, 10, &value
))
201 enable_oled(odev
, value
);
206 static ssize_t
class_set_enabled(struct device
*device
,
207 struct device_attribute
*attr
,
208 const char *buf
, size_t count
)
210 struct asus_oled_dev
*odev
=
211 (struct asus_oled_dev
*) dev_get_drvdata(device
);
214 if (kstrtoul(buf
, 10, &value
))
217 enable_oled(odev
, value
);
222 static ssize_t
get_enabled(struct device
*dev
, struct device_attribute
*attr
,
225 struct usb_interface
*intf
= to_usb_interface(dev
);
226 struct asus_oled_dev
*odev
= usb_get_intfdata(intf
);
228 return sprintf(buf
, "%d\n", odev
->enabled
);
231 static ssize_t
class_get_enabled(struct device
*device
,
232 struct device_attribute
*attr
, char *buf
)
234 struct asus_oled_dev
*odev
=
235 (struct asus_oled_dev
*) dev_get_drvdata(device
);
237 return sprintf(buf
, "%d\n", odev
->enabled
);
240 static void send_packets(struct usb_device
*udev
,
241 struct asus_oled_packet
*packet
,
242 char *buf
, uint8_t p_type
, size_t p_num
)
247 for (i
= 0; i
< p_num
; i
++) {
252 setup_packet_header(packet
, 0x40, 0x80, p_num
,
253 i
+ 1, 0x00, 0x01, 0xff);
255 case ASUS_OLED_STATIC
:
256 setup_packet_header(packet
, 0x10 + i
, 0x80, 0x01,
257 0x01, 0x00, 0x01, 0x00);
259 case ASUS_OLED_FLASH
:
260 setup_packet_header(packet
, 0x10 + i
, 0x80, 0x01,
261 0x01, 0x00, 0x00, 0xff);
265 memcpy(packet
->bitmap
, buf
+ (ASUS_OLED_PACKET_BUF_SIZE
*i
),
266 ASUS_OLED_PACKET_BUF_SIZE
);
268 retval
= usb_bulk_msg(udev
, usb_sndctrlpipe(udev
, 2),
269 packet
, sizeof(struct asus_oled_packet
),
273 dev_dbg(&udev
->dev
, "retval = %d\n", retval
);
277 static void send_packet(struct usb_device
*udev
,
278 struct asus_oled_packet
*packet
,
279 size_t offset
, size_t len
, char *buf
, uint8_t b1
,
280 uint8_t b2
, uint8_t b3
, uint8_t b4
, uint8_t b5
,
285 setup_packet_header(packet
, b1
, b2
, b3
, b4
, b5
, b6
, 0x00);
286 memcpy(packet
->bitmap
, buf
+ offset
, len
);
288 retval
= usb_bulk_msg(udev
,
289 usb_sndctrlpipe(udev
, 2),
291 sizeof(struct asus_oled_packet
),
296 dev_dbg(&udev
->dev
, "retval = %d\n", retval
);
300 static void send_packets_g50(struct usb_device
*udev
,
301 struct asus_oled_packet
*packet
, char *buf
)
303 send_packet(udev
, packet
, 0, 0x100, buf
,
304 0x10, 0x00, 0x02, 0x01, 0x00, 0x01);
305 send_packet(udev
, packet
, 0x100, 0x080, buf
,
306 0x10, 0x00, 0x02, 0x02, 0x80, 0x00);
308 send_packet(udev
, packet
, 0x180, 0x100, buf
,
309 0x11, 0x00, 0x03, 0x01, 0x00, 0x01);
310 send_packet(udev
, packet
, 0x280, 0x100, buf
,
311 0x11, 0x00, 0x03, 0x02, 0x00, 0x01);
312 send_packet(udev
, packet
, 0x380, 0x080, buf
,
313 0x11, 0x00, 0x03, 0x03, 0x80, 0x00);
317 static void send_data(struct asus_oled_dev
*odev
)
319 size_t packet_num
= odev
->buf_size
/ ASUS_OLED_PACKET_BUF_SIZE
;
320 struct asus_oled_packet
*packet
;
322 packet
= kzalloc(sizeof(struct asus_oled_packet
), GFP_KERNEL
);
326 if (odev
->pack_mode
== PACK_MODE_G1
) {
328 * When sending roll-mode data the display updated only
329 * first packet. I have no idea why, but when static picture
330 * is sent just before rolling picture everything works fine.
332 if (odev
->pic_mode
== ASUS_OLED_ROLL
)
333 send_packets(odev
->udev
, packet
, odev
->buf
,
334 ASUS_OLED_STATIC
, 2);
336 /* Only ROLL mode can use more than 2 packets.*/
337 if (odev
->pic_mode
!= ASUS_OLED_ROLL
&& packet_num
> 2)
340 send_packets(odev
->udev
, packet
, odev
->buf
,
341 odev
->pic_mode
, packet_num
);
342 } else if (odev
->pack_mode
== PACK_MODE_G50
) {
343 send_packets_g50(odev
->udev
, packet
, odev
->buf
);
349 static int append_values(struct asus_oled_dev
*odev
, uint8_t val
, size_t count
)
351 odev
->last_val
= val
;
354 odev
->buf_offs
+= count
;
358 while (count
-- > 0) {
359 size_t x
= odev
->buf_offs
% odev
->width
;
360 size_t y
= odev
->buf_offs
/ odev
->width
;
366 switch (odev
->pack_mode
) {
369 * i = (x/128)*640 + 127 - x + (y/8)*128;
370 * This one for 128 is the same, but might be better
371 * for different widths?
373 i
= (x
/odev
->dev_width
)*640 +
374 odev
->dev_width
- 1 - x
+
375 (y
/8)*odev
->dev_width
;
379 i
= (odev
->dev_width
- 1 - x
)/8 + y
*odev
->dev_width
/8;
384 dev_err(odev
->dev
, "Unknown OLED Pack Mode: %d!\n",
389 if (i
>= odev
->buf_size
) {
390 dev_err(odev
->dev
, "Buffer overflow! Report a bug: offs: %zu >= %zu i: %zu (x: %zu y: %zu)\n",
391 odev
->buf_offs
, odev
->buf_size
, i
, x
, y
);
395 switch (odev
->pack_mode
) {
397 odev
->buf
[i
] &= ~(1<<(y
%8));
401 odev
->buf
[i
] &= ~(1<<(x
%8));
405 /* cannot get here; stops gcc complaining*/
415 static ssize_t
odev_set_picture(struct asus_oled_dev
*odev
,
416 const char *buf
, size_t count
)
418 size_t offs
= 0, max_offs
;
423 if (tolower(buf
[0]) == 'b') {
424 /* binary mode, set the entire memory*/
428 odev
->buf_size
= (odev
->dev_width
* ASUS_OLED_DISP_HEIGHT
) / 8;
431 odev
->buf
= kmalloc(odev
->buf_size
, GFP_KERNEL
);
432 if (odev
->buf
== NULL
) {
434 dev_err(odev
->dev
, "Out of memory!\n");
438 memset(odev
->buf
, 0xff, odev
->buf_size
);
440 for (i
= 1; i
< count
&& i
<= 32 * 32; i
++) {
441 odev
->buf
[i
-1] = buf
[i
];
442 odev
->buf_offs
= i
-1;
445 odev
->width
= odev
->dev_width
/ 8;
446 odev
->height
= ASUS_OLED_DISP_HEIGHT
;
461 if (count
< 10 || buf
[2] != ':')
465 switch (tolower(buf
[1])) {
466 case ASUS_OLED_STATIC
:
468 case ASUS_OLED_FLASH
:
469 odev
->pic_mode
= buf
[1];
472 dev_err(odev
->dev
, "Wrong picture mode: '%c'.\n",
478 for (i
= 3; i
< count
; ++i
) {
479 if (buf
[i
] >= '0' && buf
[i
] <= '9') {
480 w
= 10*w
+ (buf
[i
] - '0');
482 if (w
> ASUS_OLED_MAX_WIDTH
)
484 } else if (tolower(buf
[i
]) == 'x') {
491 for (++i
; i
< count
; ++i
) {
492 if (buf
[i
] >= '0' && buf
[i
] <= '9') {
493 h
= 10*h
+ (buf
[i
] - '0');
495 if (h
> ASUS_OLED_DISP_HEIGHT
)
497 } else if (tolower(buf
[i
]) == '>') {
504 if (w
< 1 || w
> ASUS_OLED_MAX_WIDTH
)
507 if (h
< 1 || h
> ASUS_OLED_DISP_HEIGHT
)
510 if (i
>= count
|| buf
[i
] != '>')
515 if (w
% (odev
->dev_width
) != 0)
516 w_mem
= (w
/(odev
->dev_width
) + 1)*(odev
->dev_width
);
520 if (h
< ASUS_OLED_DISP_HEIGHT
)
521 h_mem
= ASUS_OLED_DISP_HEIGHT
;
525 odev
->buf_size
= w_mem
* h_mem
/ 8;
528 odev
->buf
= kmalloc(odev
->buf_size
, GFP_KERNEL
);
530 if (odev
->buf
== NULL
) {
532 dev_err(odev
->dev
, "Out of memory!\n");
536 memset(odev
->buf
, 0xff, odev
->buf_size
);
545 if (odev
->pic_mode
== ASUS_OLED_FLASH
) {
546 if (h
< ASUS_OLED_DISP_HEIGHT
/2)
547 odev
->y_shift
= (ASUS_OLED_DISP_HEIGHT
/2 - h
)/2;
549 if (h
< ASUS_OLED_DISP_HEIGHT
)
550 odev
->y_shift
= (ASUS_OLED_DISP_HEIGHT
- h
)/2;
553 if (w
< (odev
->dev_width
))
554 odev
->x_shift
= ((odev
->dev_width
) - w
)/2;
557 max_offs
= odev
->width
* odev
->height
;
559 while (offs
< count
&& odev
->buf_offs
< max_offs
) {
562 if (buf
[offs
] == '1' || buf
[offs
] == '#') {
563 ret
= append_values(odev
, 1, 1);
566 } else if (buf
[offs
] == '0' || buf
[offs
] == ' ') {
567 ret
= append_values(odev
, 0, 1);
570 } else if (buf
[offs
] == '\n') {
572 * New line detected. Lets assume, that all characters
573 * till the end of the line were equal to the last
574 * character in this line.
576 if (odev
->buf_offs
% odev
->width
!= 0)
577 ret
= append_values(odev
, odev
->last_val
,
588 if (odev
->buf_offs
>= max_offs
)
594 dev_err(odev
->dev
, "Wrong picture width specified.\n");
598 dev_err(odev
->dev
, "Wrong picture height specified.\n");
602 dev_err(odev
->dev
, "Wrong picture header.\n");
606 static ssize_t
set_picture(struct device
*dev
, struct device_attribute
*attr
,
607 const char *buf
, size_t count
)
609 struct usb_interface
*intf
= to_usb_interface(dev
);
611 return odev_set_picture(usb_get_intfdata(intf
), buf
, count
);
614 static ssize_t
class_set_picture(struct device
*device
,
615 struct device_attribute
*attr
,
616 const char *buf
, size_t count
)
618 return odev_set_picture((struct asus_oled_dev
*)
619 dev_get_drvdata(device
), buf
, count
);
622 #define ASUS_OLED_DEVICE_ATTR(_file) dev_attr_asus_oled_##_file
624 static DEVICE_ATTR(asus_oled_enabled
, S_IWUSR
| S_IRUGO
,
625 get_enabled
, set_enabled
);
626 static DEVICE_ATTR(asus_oled_picture
, S_IWUSR
, NULL
, set_picture
);
628 static DEVICE_ATTR(enabled
, S_IWUSR
| S_IRUGO
,
629 class_get_enabled
, class_set_enabled
);
630 static DEVICE_ATTR(picture
, S_IWUSR
, NULL
, class_set_picture
);
632 static int asus_oled_probe(struct usb_interface
*interface
,
633 const struct usb_device_id
*id
)
635 struct usb_device
*udev
= interface_to_usbdev(interface
);
636 struct asus_oled_dev
*odev
= NULL
;
637 int retval
= -ENOMEM
;
638 uint16_t dev_width
= 0;
639 enum oled_pack_mode pack_mode
= PACK_MODE_LAST
;
640 const struct oled_dev_desc_str
*dev_desc
= oled_dev_desc_table
;
641 const char *desc
= NULL
;
644 /* Even possible? Just to make sure...*/
645 dev_err(&interface
->dev
, "No usb_device_id provided!\n");
649 for (; dev_desc
->idVendor
; dev_desc
++) {
650 if (dev_desc
->idVendor
== id
->idVendor
651 && dev_desc
->idProduct
== id
->idProduct
) {
652 dev_width
= dev_desc
->devWidth
;
653 desc
= dev_desc
->devDesc
;
654 pack_mode
= dev_desc
->packMode
;
659 if (!desc
|| dev_width
< 1 || pack_mode
== PACK_MODE_LAST
) {
660 dev_err(&interface
->dev
,
661 "Missing or incomplete device description!\n");
665 odev
= kzalloc(sizeof(struct asus_oled_dev
), GFP_KERNEL
);
669 odev
->udev
= usb_get_dev(udev
);
670 odev
->pic_mode
= ASUS_OLED_STATIC
;
671 odev
->dev_width
= dev_width
;
672 odev
->pack_mode
= pack_mode
;
684 usb_set_intfdata(interface
, odev
);
686 retval
= device_create_file(&interface
->dev
,
687 &ASUS_OLED_DEVICE_ATTR(enabled
));
691 retval
= device_create_file(&interface
->dev
,
692 &ASUS_OLED_DEVICE_ATTR(picture
));
696 odev
->dev
= device_create(oled_class
, &interface
->dev
, MKDEV(0, 0),
697 NULL
, "oled_%d", ++oled_num
);
699 if (IS_ERR(odev
->dev
)) {
700 retval
= PTR_ERR(odev
->dev
);
704 dev_set_drvdata(odev
->dev
, odev
);
706 retval
= device_create_file(odev
->dev
, &dev_attr_enabled
);
708 goto err_class_enabled
;
710 retval
= device_create_file(odev
->dev
, &dev_attr_picture
);
712 goto err_class_picture
;
714 dev_info(&interface
->dev
,
715 "Attached Asus OLED device: %s [width %u, pack_mode %d]\n",
716 desc
, odev
->dev_width
, odev
->pack_mode
);
719 enable_oled(odev
, 0);
724 device_remove_file(odev
->dev
, &dev_attr_picture
);
727 device_remove_file(odev
->dev
, &dev_attr_enabled
);
728 device_unregister(odev
->dev
);
731 device_remove_file(&interface
->dev
, &ASUS_OLED_DEVICE_ATTR(enabled
));
732 device_remove_file(&interface
->dev
, &ASUS_OLED_DEVICE_ATTR(picture
));
734 usb_set_intfdata(interface
, NULL
);
735 usb_put_dev(odev
->udev
);
741 static void asus_oled_disconnect(struct usb_interface
*interface
)
743 struct asus_oled_dev
*odev
;
745 odev
= usb_get_intfdata(interface
);
746 usb_set_intfdata(interface
, NULL
);
748 device_remove_file(odev
->dev
, &dev_attr_picture
);
749 device_remove_file(odev
->dev
, &dev_attr_enabled
);
750 device_unregister(odev
->dev
);
752 device_remove_file(&interface
->dev
, &ASUS_OLED_DEVICE_ATTR(picture
));
753 device_remove_file(&interface
->dev
, &ASUS_OLED_DEVICE_ATTR(enabled
));
755 usb_put_dev(odev
->udev
);
761 dev_info(&interface
->dev
, "Disconnected Asus OLED device\n");
765 static int asus_oled_suspend(struct usb_interface
*intf
, pm_message_t message
)
767 struct asus_oled_dev
*odev
;
769 odev
= usb_get_intfdata(intf
);
773 odev
->enabled_post_resume
= odev
->enabled
;
774 enable_oled(odev
, 0);
779 static int asus_oled_resume(struct usb_interface
*intf
)
781 struct asus_oled_dev
*odev
;
783 odev
= usb_get_intfdata(intf
);
787 enable_oled(odev
, odev
->enabled_post_resume
);
792 #define asus_oled_suspend NULL
793 #define asus_oled_resume NULL
796 static struct usb_driver oled_driver
= {
797 .name
= ASUS_OLED_NAME
,
798 .probe
= asus_oled_probe
,
799 .disconnect
= asus_oled_disconnect
,
800 .id_table
= id_table
,
801 .suspend
= asus_oled_suspend
,
802 .resume
= asus_oled_resume
,
805 static CLASS_ATTR_STRING(version
, S_IRUGO
,
806 ASUS_OLED_UNDERSCORE_NAME
" " ASUS_OLED_VERSION
);
808 static int __init
asus_oled_init(void)
811 oled_class
= class_create(THIS_MODULE
, ASUS_OLED_UNDERSCORE_NAME
);
813 if (IS_ERR(oled_class
)) {
814 pr_err("Error creating " ASUS_OLED_UNDERSCORE_NAME
" class\n");
815 return PTR_ERR(oled_class
);
818 retval
= class_create_file(oled_class
, &class_attr_version
.attr
);
820 pr_err("Error creating class version file\n");
824 retval
= usb_register(&oled_driver
);
827 pr_err("usb_register failed. Error number %d\n", retval
);
834 class_destroy(oled_class
);
838 static void __exit
asus_oled_exit(void)
840 usb_deregister(&oled_driver
);
841 class_remove_file(oled_class
, &class_attr_version
.attr
);
842 class_destroy(oled_class
);
845 module_init(asus_oled_init
);
846 module_exit(asus_oled_exit
);