14 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
16 #include <linux/kernel.h>
19 #include <linux/i2c.h>
21 #include <linux/pci.h>
25 #include <linux/module.h>
27 #include <linux/device.h>
29 #include <linux/ctype.h>
30 #include <linux/reboot.h>
39 static ushort resumeline = 898;
69 static int dcon_hw_init(
struct dcon_priv *dcon,
int is_init)
75 if ((ver >> 8) != 0xDC) {
76 pr_err(
"DCON ID not 0xDCxx: 0x%04x instead.\n", ver);
82 pr_info(
"Discovered DCON version %x\n", ver & 0xFF);
83 rc = pdata->
init(dcon);
85 pr_err(
"Unable to init.\n");
92 "DCON v1 is unsupported, giving up..\n");
98 dcon_write(dcon, 0x3a, 0xc040);
99 dcon_write(dcon, 0x41, 0x0000);
100 dcon_write(dcon, 0x41, 0x0101);
101 dcon_write(dcon, 0x42, 0x0101);
129 static int dcon_bus_stabilize(
struct dcon_priv *dcon,
int is_powered_down)
135 if (is_powered_down) {
139 pr_warn(
"unable to force dcon to power up: %d!\n", x);
147 for (x = -1, timeout = 50; timeout && x < 0; timeout--) {
152 pr_err(
"unable to stabilize dcon's smbus, reasserting power and praying.\n");
153 BUG_ON(olpc_board_at_least(olpc_board(0xc2)));
162 return dcon_hw_init(dcon, 0);
182 static int dcon_set_mono_mode(
struct dcon_priv *dcon,
bool enable_mono)
184 if (dcon->
mono == enable_mono)
187 dcon->
mono = enable_mono;
207 static void dcon_sleep(
struct dcon_priv *dcon,
bool sleep)
213 if (dcon->
asleep == sleep)
216 if (!olpc_board_at_least(olpc_board(0xc2)))
223 pr_warn(
"unable to force dcon to power down: %d!\n", x);
230 x = dcon_bus_stabilize(dcon, 1);
232 pr_warn(
"unable to reinit dcon hardware: %d!\n", x);
237 dcon_set_backlight(dcon, dcon->
bl_val);
248 static void dcon_load_holdoff(
struct dcon_priv *dcon)
253 delta_t = timespec_sub(now, dcon->
load_time);
254 if (delta_t.tv_sec != 0 ||
262 static bool dcon_blank_fb(
struct dcon_priv *dcon,
bool blank)
276 unlock_fb_info(dcon->
fbinfo);
279 dev_err(&dcon->
client->dev,
"couldn't %sblank framebuffer\n",
297 dcon_load_holdoff(dcon);
303 pr_info(
"dcon_source_switch to CPU\n");
307 pr_err(
"couldn't enable scanline interrupt!\n");
315 pr_err(
"Timeout entering CPU mode; expect a screen glitch.\n");
319 pr_err(
"couldn't disable scanline interrupt!\n");
329 if (!dcon_blank_fb(dcon,
false)) {
330 pr_err(
"Failed to enter CPU mode\n");
339 pr_info(
"The CPU has control\n");
346 pr_info(
"dcon_source_switch to DCON\n");
360 pr_err(
"Timeout entering DCON mode; expect a screen glitch.\n");
374 if (dcon->
switched && delta_t.tv_sec == 0 &&
376 pr_err(
"missed loading, retrying\n");
385 dcon_blank_fb(dcon,
true);
386 pr_info(
"The DCON has control\n");
396 static void dcon_set_source(
struct dcon_priv *dcon,
int arg)
407 static void dcon_set_source_sync(
struct dcon_priv *dcon,
int arg)
409 dcon_set_source(dcon, arg);
445 return sprintf(buf,
"%d\n", resumeline);
451 unsigned long enable_mono;
454 rc = kstrtoul(buf, 10, &enable_mono);
470 ret = kstrtoul(buf, 10, &output);
474 pr_info(
"dcon_freeze_store: %lu\n", output);
512 unsigned long output;
515 ret = kstrtoul(buf, 10, &output);
525 __ATTR(sleep, 0644, dcon_sleep_show, dcon_sleep_store),
526 __ATTR(freeze, 0644, dcon_freeze_show, dcon_freeze_store),
527 __ATTR(monochrome, 0644, dcon_mono_show, dcon_mono_store),
528 __ATTR(resumeline, 0644, dcon_resumeline_show, dcon_resumeline_store),
533 struct dcon_priv *dcon = bl_get_data(dev);
534 u8 level = dev->
props.brightness & 0x0F;
539 if (level != dcon->
bl_val)
540 dcon_set_backlight(dcon, level);
547 struct dcon_priv *dcon = bl_get_data(dev);
552 .update_status = dcon_bl_update,
553 .get_brightness = dcon_bl_get,
557 .max_brightness = 15,
563 unsigned long foo,
void *bar)
567 if (!dcon || !dcon->
client)
577 unsigned long e,
void *
p)
584 .notifier_call = unfreeze_on_panic,
597 int *blank = (
int *)evdata->
data;
601 dcon_sleep(dcon, *blank ?
true :
false);
626 dcon->
reboot_nb.notifier_call = dcon_reboot_notify;
628 dcon->
fbevent_nb.notifier_call = dcon_fb_notifier;
630 i2c_set_clientdata(client, dcon);
632 if (num_registered_fb < 1) {
633 dev_err(&client->
dev,
"DCON driver requires a registered fb\n");
639 rc = dcon_hw_init(dcon, 1);
647 if (dcon_device ==
NULL) {
648 pr_err(
"Unable to create the DCON device\n");
653 platform_set_drvdata(dcon_device, dcon);
656 pr_err(
"Unable to add the DCON device\n");
660 for (i = 0; i <
ARRAY_SIZE(dcon_device_files); i++) {
662 &dcon_device_files[i]);
664 dev_err(&dcon_device->
dev,
"Cannot create sysfs file\n");
674 dcon, &dcon_bl_ops, &dcon_bl_props);
675 if (IS_ERR(dcon->
bl_dev)) {
676 dev_err(&client->
dev,
"cannot register backlight dev (%ld)\n",
688 for (j = 0; j <
i; j++)
700 static int dcon_remove(
struct i2c_client *client)
702 struct dcon_priv *dcon = i2c_get_clientdata(client);
713 if (dcon_device !=
NULL)
725 struct dcon_priv *dcon = i2c_get_clientdata(client);
735 static int dcon_resume(
struct i2c_client *client)
737 struct dcon_priv *dcon = i2c_get_clientdata(client);
740 dcon_bus_stabilize(dcon, 0);
758 switch (status & 3) {
760 pr_debug(
"DCONLOAD_MISSED interrupt\n");
782 pr_debug(
"switching w/ status 0/0\n");
784 pr_debug(
"scanline interrupt w/CPU\n");
803 .id_table = dcon_idtable,
806 .detect = dcon_detect,
807 .address_list = normal_i2c,
809 .suspend = dcon_suspend,
810 .resume = dcon_resume,
814 static int __init olpc_dcon_init(
void)
816 #ifdef CONFIG_FB_OLPC_DCON_1_5
818 if (olpc_board_at_least(olpc_board(0xd0)))
821 #ifdef CONFIG_FB_OLPC_DCON_1
826 return i2c_add_driver(&dcon_driver);
829 static void __exit olpc_dcon_exit(
void)