diff options
Diffstat (limited to 'drivers')
255 files changed, 21902 insertions, 3252 deletions
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index 6318f6b57360..d8e8c49c0cbd 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig | |||
@@ -54,7 +54,7 @@ config FIRMWARE_IN_KERNEL | |||
54 | such firmware, and do not wish to use an initrd. | 54 | such firmware, and do not wish to use an initrd. |
55 | 55 | ||
56 | This single option controls the inclusion of firmware for | 56 | This single option controls the inclusion of firmware for |
57 | every driver which usees request_firmare() and ships its | 57 | every driver which uses request_firmare() and ships its |
58 | firmware in the kernel source tree, to avoid a proliferation | 58 | firmware in the kernel source tree, to avoid a proliferation |
59 | of 'Include firmware for xxx device' options. | 59 | of 'Include firmware for xxx device' options. |
60 | 60 | ||
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index c9c92b00fd55..b7e571031ecd 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -164,8 +164,7 @@ static ssize_t firmware_loading_store(struct device *dev, | |||
164 | } | 164 | } |
165 | /* fallthrough */ | 165 | /* fallthrough */ |
166 | default: | 166 | default: |
167 | printk(KERN_ERR "%s: unexpected value (%d)\n", __func__, | 167 | dev_err(dev, "%s: unexpected value (%d)\n", __func__, loading); |
168 | loading); | ||
169 | /* fallthrough */ | 168 | /* fallthrough */ |
170 | case -1: | 169 | case -1: |
171 | fw_load_abort(fw_priv); | 170 | fw_load_abort(fw_priv); |
@@ -309,7 +308,7 @@ static int fw_register_device(struct device **dev_p, const char *fw_name, | |||
309 | *dev_p = NULL; | 308 | *dev_p = NULL; |
310 | 309 | ||
311 | if (!fw_priv || !f_dev) { | 310 | if (!fw_priv || !f_dev) { |
312 | printk(KERN_ERR "%s: kmalloc failed\n", __func__); | 311 | dev_err(device, "%s: kmalloc failed\n", __func__); |
313 | retval = -ENOMEM; | 312 | retval = -ENOMEM; |
314 | goto error_kfree; | 313 | goto error_kfree; |
315 | } | 314 | } |
@@ -329,8 +328,7 @@ static int fw_register_device(struct device **dev_p, const char *fw_name, | |||
329 | f_dev->uevent_suppress = 1; | 328 | f_dev->uevent_suppress = 1; |
330 | retval = device_register(f_dev); | 329 | retval = device_register(f_dev); |
331 | if (retval) { | 330 | if (retval) { |
332 | printk(KERN_ERR "%s: device_register failed\n", | 331 | dev_err(device, "%s: device_register failed\n", __func__); |
333 | __func__); | ||
334 | goto error_kfree; | 332 | goto error_kfree; |
335 | } | 333 | } |
336 | *dev_p = f_dev; | 334 | *dev_p = f_dev; |
@@ -363,15 +361,13 @@ static int fw_setup_device(struct firmware *fw, struct device **dev_p, | |||
363 | fw_priv->fw = fw; | 361 | fw_priv->fw = fw; |
364 | retval = sysfs_create_bin_file(&f_dev->kobj, &fw_priv->attr_data); | 362 | retval = sysfs_create_bin_file(&f_dev->kobj, &fw_priv->attr_data); |
365 | if (retval) { | 363 | if (retval) { |
366 | printk(KERN_ERR "%s: sysfs_create_bin_file failed\n", | 364 | dev_err(device, "%s: sysfs_create_bin_file failed\n", __func__); |
367 | __func__); | ||
368 | goto error_unreg; | 365 | goto error_unreg; |
369 | } | 366 | } |
370 | 367 | ||
371 | retval = device_create_file(f_dev, &dev_attr_loading); | 368 | retval = device_create_file(f_dev, &dev_attr_loading); |
372 | if (retval) { | 369 | if (retval) { |
373 | printk(KERN_ERR "%s: device_create_file failed\n", | 370 | dev_err(device, "%s: device_create_file failed\n", __func__); |
374 | __func__); | ||
375 | goto error_unreg; | 371 | goto error_unreg; |
376 | } | 372 | } |
377 | 373 | ||
@@ -401,8 +397,8 @@ _request_firmware(const struct firmware **firmware_p, const char *name, | |||
401 | 397 | ||
402 | *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL); | 398 | *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL); |
403 | if (!firmware) { | 399 | if (!firmware) { |
404 | printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n", | 400 | dev_err(device, "%s: kmalloc(struct firmware) failed\n", |
405 | __func__); | 401 | __func__); |
406 | retval = -ENOMEM; | 402 | retval = -ENOMEM; |
407 | goto out; | 403 | goto out; |
408 | } | 404 | } |
@@ -411,15 +407,15 @@ _request_firmware(const struct firmware **firmware_p, const char *name, | |||
411 | builtin++) { | 407 | builtin++) { |
412 | if (strcmp(name, builtin->name)) | 408 | if (strcmp(name, builtin->name)) |
413 | continue; | 409 | continue; |
414 | printk(KERN_INFO "firmware: using built-in firmware %s\n", | 410 | dev_info(device, "firmware: using built-in firmware %s\n", |
415 | name); | 411 | name); |
416 | firmware->size = builtin->size; | 412 | firmware->size = builtin->size; |
417 | firmware->data = builtin->data; | 413 | firmware->data = builtin->data; |
418 | return 0; | 414 | return 0; |
419 | } | 415 | } |
420 | 416 | ||
421 | if (uevent) | 417 | if (uevent) |
422 | printk(KERN_INFO "firmware: requesting %s\n", name); | 418 | dev_info(device, "firmware: requesting %s\n", name); |
423 | 419 | ||
424 | retval = fw_setup_device(firmware, &f_dev, name, device, uevent); | 420 | retval = fw_setup_device(firmware, &f_dev, name, device, uevent); |
425 | if (retval) | 421 | if (retval) |
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 9e60f7c739c6..dfcbfe504867 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -42,10 +42,8 @@ struct resource *platform_get_resource(struct platform_device *dev, | |||
42 | for (i = 0; i < dev->num_resources; i++) { | 42 | for (i = 0; i < dev->num_resources; i++) { |
43 | struct resource *r = &dev->resource[i]; | 43 | struct resource *r = &dev->resource[i]; |
44 | 44 | ||
45 | if ((r->flags & (IORESOURCE_IO|IORESOURCE_MEM| | 45 | if (type == resource_type(r) && num-- == 0) |
46 | IORESOURCE_IRQ|IORESOURCE_DMA)) == type) | 46 | return r; |
47 | if (num-- == 0) | ||
48 | return r; | ||
49 | } | 47 | } |
50 | return NULL; | 48 | return NULL; |
51 | } | 49 | } |
@@ -78,10 +76,8 @@ struct resource *platform_get_resource_byname(struct platform_device *dev, | |||
78 | for (i = 0; i < dev->num_resources; i++) { | 76 | for (i = 0; i < dev->num_resources; i++) { |
79 | struct resource *r = &dev->resource[i]; | 77 | struct resource *r = &dev->resource[i]; |
80 | 78 | ||
81 | if ((r->flags & (IORESOURCE_IO|IORESOURCE_MEM| | 79 | if (type == resource_type(r) && !strcmp(r->name, name)) |
82 | IORESOURCE_IRQ|IORESOURCE_DMA)) == type) | 80 | return r; |
83 | if (!strcmp(r->name, name)) | ||
84 | return r; | ||
85 | } | 81 | } |
86 | return NULL; | 82 | return NULL; |
87 | } | 83 | } |
@@ -259,9 +255,9 @@ int platform_device_add(struct platform_device *pdev) | |||
259 | 255 | ||
260 | p = r->parent; | 256 | p = r->parent; |
261 | if (!p) { | 257 | if (!p) { |
262 | if (r->flags & IORESOURCE_MEM) | 258 | if (resource_type(r) == IORESOURCE_MEM) |
263 | p = &iomem_resource; | 259 | p = &iomem_resource; |
264 | else if (r->flags & IORESOURCE_IO) | 260 | else if (resource_type(r) == IORESOURCE_IO) |
265 | p = &ioport_resource; | 261 | p = &ioport_resource; |
266 | } | 262 | } |
267 | 263 | ||
@@ -282,9 +278,14 @@ int platform_device_add(struct platform_device *pdev) | |||
282 | return ret; | 278 | return ret; |
283 | 279 | ||
284 | failed: | 280 | failed: |
285 | while (--i >= 0) | 281 | while (--i >= 0) { |
286 | if (pdev->resource[i].flags & (IORESOURCE_MEM|IORESOURCE_IO)) | 282 | struct resource *r = &pdev->resource[i]; |
287 | release_resource(&pdev->resource[i]); | 283 | unsigned long type = resource_type(r); |
284 | |||
285 | if (type == IORESOURCE_MEM || type == IORESOURCE_IO) | ||
286 | release_resource(r); | ||
287 | } | ||
288 | |||
288 | return ret; | 289 | return ret; |
289 | } | 290 | } |
290 | EXPORT_SYMBOL_GPL(platform_device_add); | 291 | EXPORT_SYMBOL_GPL(platform_device_add); |
@@ -306,7 +307,9 @@ void platform_device_del(struct platform_device *pdev) | |||
306 | 307 | ||
307 | for (i = 0; i < pdev->num_resources; i++) { | 308 | for (i = 0; i < pdev->num_resources; i++) { |
308 | struct resource *r = &pdev->resource[i]; | 309 | struct resource *r = &pdev->resource[i]; |
309 | if (r->flags & (IORESOURCE_MEM|IORESOURCE_IO)) | 310 | unsigned long type = resource_type(r); |
311 | |||
312 | if (type == IORESOURCE_MEM || type == IORESOURCE_IO) | ||
310 | release_resource(r); | 313 | release_resource(r); |
311 | } | 314 | } |
312 | } | 315 | } |
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index b0eb6afdd861..692c20ba5144 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -778,10 +778,7 @@ EXPORT_SYMBOL_GPL(device_suspend); | |||
778 | 778 | ||
779 | void __suspend_report_result(const char *function, void *fn, int ret) | 779 | void __suspend_report_result(const char *function, void *fn, int ret) |
780 | { | 780 | { |
781 | if (ret) { | 781 | if (ret) |
782 | printk(KERN_ERR "%s(): ", function); | 782 | printk(KERN_ERR "%s(): %pF returns %d\n", function, fn, ret); |
783 | print_fn_descriptor_symbol("%s returns ", fn); | ||
784 | printk("%d\n", ret); | ||
785 | } | ||
786 | } | 783 | } |
787 | EXPORT_SYMBOL_GPL(__suspend_report_result); | 784 | EXPORT_SYMBOL_GPL(__suspend_report_result); |
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 700ff9679457..122254155ae1 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -1043,15 +1043,6 @@ config HPET | |||
1043 | open selects one of the timers supported by the HPET. The timers are | 1043 | open selects one of the timers supported by the HPET. The timers are |
1044 | non-periodic and/or periodic. | 1044 | non-periodic and/or periodic. |
1045 | 1045 | ||
1046 | config HPET_RTC_IRQ | ||
1047 | bool | ||
1048 | default HPET_EMULATE_RTC | ||
1049 | depends on RTC && HPET | ||
1050 | help | ||
1051 | If you say Y here, you will disable RTC_IRQ in drivers/char/rtc.c. It | ||
1052 | is assumed the platform called hpet_alloc with the RTC IRQ values for | ||
1053 | the HPET timers. | ||
1054 | |||
1055 | config HPET_MMAP | 1046 | config HPET_MMAP |
1056 | bool "Allow mmap of HPET" | 1047 | bool "Allow mmap of HPET" |
1057 | default y | 1048 | default y |
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c index b899d9182c7d..05674febb0c6 100644 --- a/drivers/char/applicom.c +++ b/drivers/char/applicom.c | |||
@@ -478,7 +478,7 @@ static int do_ac_read(int IndexCard, char __user *buf, | |||
478 | struct st_ram_io *st_loc, struct mailbox *mailbox) | 478 | struct st_ram_io *st_loc, struct mailbox *mailbox) |
479 | { | 479 | { |
480 | void __iomem *from = apbs[IndexCard].RamIO + RAM_TO_PC; | 480 | void __iomem *from = apbs[IndexCard].RamIO + RAM_TO_PC; |
481 | unsigned char *to = (unsigned char *)&mailbox; | 481 | unsigned char *to = (unsigned char *)mailbox; |
482 | #ifdef DEBUG | 482 | #ifdef DEBUG |
483 | int c; | 483 | int c; |
484 | #endif | 484 | #endif |
diff --git a/drivers/char/ds1286.c b/drivers/char/ds1286.c index fb584938c9c3..5329d482b582 100644 --- a/drivers/char/ds1286.c +++ b/drivers/char/ds1286.c | |||
@@ -443,7 +443,6 @@ static void ds1286_get_time(struct rtc_time *rtc_tm) | |||
443 | { | 443 | { |
444 | unsigned char save_control; | 444 | unsigned char save_control; |
445 | unsigned long flags; | 445 | unsigned long flags; |
446 | unsigned long uip_watchdog = jiffies; | ||
447 | 446 | ||
448 | /* | 447 | /* |
449 | * read RTC once any update in progress is done. The update | 448 | * read RTC once any update in progress is done. The update |
@@ -456,8 +455,7 @@ static void ds1286_get_time(struct rtc_time *rtc_tm) | |||
456 | */ | 455 | */ |
457 | 456 | ||
458 | if (ds1286_is_updating() != 0) | 457 | if (ds1286_is_updating() != 0) |
459 | while (time_before(jiffies, uip_watchdog + 2*HZ/100)) | 458 | msleep(20); |
460 | barrier(); | ||
461 | 459 | ||
462 | /* | 460 | /* |
463 | * Only the values that we read from the RTC are set. We leave | 461 | * Only the values that we read from the RTC are set. We leave |
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c index 51738bdd834e..d4e7dca06e4f 100644 --- a/drivers/char/hw_random/omap-rng.c +++ b/drivers/char/hw_random/omap-rng.c | |||
@@ -118,18 +118,21 @@ static int __init omap_rng_probe(struct platform_device *pdev) | |||
118 | 118 | ||
119 | mem = request_mem_region(res->start, res->end - res->start + 1, | 119 | mem = request_mem_region(res->start, res->end - res->start + 1, |
120 | pdev->name); | 120 | pdev->name); |
121 | if (mem == NULL) | 121 | if (mem == NULL) { |
122 | return -EBUSY; | 122 | ret = -EBUSY; |
123 | goto err_region; | ||
124 | } | ||
123 | 125 | ||
124 | dev_set_drvdata(&pdev->dev, mem); | 126 | dev_set_drvdata(&pdev->dev, mem); |
125 | rng_base = (u32 __force __iomem *)io_p2v(res->start); | 127 | rng_base = ioremap(res->start, res->end - res->start + 1); |
128 | if (!rng_base) { | ||
129 | ret = -ENOMEM; | ||
130 | goto err_ioremap; | ||
131 | } | ||
126 | 132 | ||
127 | ret = hwrng_register(&omap_rng_ops); | 133 | ret = hwrng_register(&omap_rng_ops); |
128 | if (ret) { | 134 | if (ret) |
129 | release_resource(mem); | 135 | goto err_register; |
130 | rng_base = NULL; | ||
131 | return ret; | ||
132 | } | ||
133 | 136 | ||
134 | dev_info(&pdev->dev, "OMAP Random Number Generator ver. %02x\n", | 137 | dev_info(&pdev->dev, "OMAP Random Number Generator ver. %02x\n", |
135 | omap_rng_read_reg(RNG_REV_REG)); | 138 | omap_rng_read_reg(RNG_REV_REG)); |
@@ -138,6 +141,18 @@ static int __init omap_rng_probe(struct platform_device *pdev) | |||
138 | rng_dev = pdev; | 141 | rng_dev = pdev; |
139 | 142 | ||
140 | return 0; | 143 | return 0; |
144 | |||
145 | err_register: | ||
146 | iounmap(rng_base); | ||
147 | rng_base = NULL; | ||
148 | err_ioremap: | ||
149 | release_resource(mem); | ||
150 | err_region: | ||
151 | if (cpu_is_omap24xx()) { | ||
152 | clk_disable(rng_ick); | ||
153 | clk_put(rng_ick); | ||
154 | } | ||
155 | return ret; | ||
141 | } | 156 | } |
142 | 157 | ||
143 | static int __exit omap_rng_remove(struct platform_device *pdev) | 158 | static int __exit omap_rng_remove(struct platform_device *pdev) |
@@ -148,6 +163,8 @@ static int __exit omap_rng_remove(struct platform_device *pdev) | |||
148 | 163 | ||
149 | omap_rng_write_reg(RNG_MASK_REG, 0x0); | 164 | omap_rng_write_reg(RNG_MASK_REG, 0x0); |
150 | 165 | ||
166 | iounmap(rng_base); | ||
167 | |||
151 | if (cpu_is_omap24xx()) { | 168 | if (cpu_is_omap24xx()) { |
152 | clk_disable(rng_ick); | 169 | clk_disable(rng_ick); |
153 | clk_put(rng_ick); | 170 | clk_put(rng_ick); |
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 7b3a212c86b1..de26a978fbdd 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c | |||
@@ -1249,7 +1249,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) | |||
1249 | return; | 1249 | return; |
1250 | } | 1250 | } |
1251 | 1251 | ||
1252 | if (keycode > NR_KEYS) | 1252 | if (keycode >= NR_KEYS) |
1253 | if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8) | 1253 | if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8) |
1254 | keysym = K(KT_BRL, keycode - KEY_BRL_DOT1 + 1); | 1254 | keysym = K(KT_BRL, keycode - KEY_BRL_DOT1 + 1); |
1255 | else | 1255 | else |
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index 5df4003ad873..12d327a2c9ba 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c | |||
@@ -513,7 +513,7 @@ static int moxa_real_load_code(struct moxa_board_conf *brd, const void *ptr, | |||
513 | size_t len) | 513 | size_t len) |
514 | { | 514 | { |
515 | void __iomem *baseAddr = brd->basemem; | 515 | void __iomem *baseAddr = brd->basemem; |
516 | const u16 *uptr = ptr; | 516 | const __le16 *uptr = ptr; |
517 | size_t wlen, len2, j; | 517 | size_t wlen, len2, j; |
518 | unsigned long key, loadbuf, loadlen, checksum, checksum_ok; | 518 | unsigned long key, loadbuf, loadlen, checksum, checksum_ok; |
519 | unsigned int i, retry; | 519 | unsigned int i, retry; |
diff --git a/drivers/char/random.c b/drivers/char/random.c index 6af435b89867..c8752eaad483 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -1205,7 +1205,7 @@ static int proc_do_uuid(ctl_table *table, int write, struct file *filp, | |||
1205 | return proc_dostring(&fake_table, write, filp, buffer, lenp, ppos); | 1205 | return proc_dostring(&fake_table, write, filp, buffer, lenp, ppos); |
1206 | } | 1206 | } |
1207 | 1207 | ||
1208 | static int uuid_strategy(ctl_table *table, int __user *name, int nlen, | 1208 | static int uuid_strategy(ctl_table *table, |
1209 | void __user *oldval, size_t __user *oldlenp, | 1209 | void __user *oldval, size_t __user *oldlenp, |
1210 | void __user *newval, size_t newlen) | 1210 | void __user *newval, size_t newlen) |
1211 | { | 1211 | { |
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index b47710c17885..17683de95717 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c | |||
@@ -96,7 +96,7 @@ static unsigned long rtc_port; | |||
96 | static int rtc_irq; | 96 | static int rtc_irq; |
97 | #endif | 97 | #endif |
98 | 98 | ||
99 | #ifdef CONFIG_HPET_RTC_IRQ | 99 | #ifdef CONFIG_HPET_EMULATE_RTC |
100 | #undef RTC_IRQ | 100 | #undef RTC_IRQ |
101 | #endif | 101 | #endif |
102 | 102 | ||
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 8fdfe9c871e3..dce4cc0e6953 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/reboot.h> | 23 | #include <linux/reboot.h> |
24 | #include <linux/sysrq.h> | 24 | #include <linux/sysrq.h> |
25 | #include <linux/kbd_kern.h> | 25 | #include <linux/kbd_kern.h> |
26 | #include <linux/proc_fs.h> | ||
26 | #include <linux/quotaops.h> | 27 | #include <linux/quotaops.h> |
27 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
28 | #include <linux/module.h> | 29 | #include <linux/module.h> |
@@ -326,6 +327,7 @@ static struct sysrq_key_op sysrq_moom_op = { | |||
326 | .handler = sysrq_handle_moom, | 327 | .handler = sysrq_handle_moom, |
327 | .help_msg = "Full", | 328 | .help_msg = "Full", |
328 | .action_msg = "Manual OOM execution", | 329 | .action_msg = "Manual OOM execution", |
330 | .enable_mask = SYSRQ_ENABLE_SIGNAL, | ||
329 | }; | 331 | }; |
330 | 332 | ||
331 | static void sysrq_handle_kill(int key, struct tty_struct *tty) | 333 | static void sysrq_handle_kill(int key, struct tty_struct *tty) |
@@ -533,3 +535,32 @@ int unregister_sysrq_key(int key, struct sysrq_key_op *op_p) | |||
533 | return __sysrq_swap_key_ops(key, NULL, op_p); | 535 | return __sysrq_swap_key_ops(key, NULL, op_p); |
534 | } | 536 | } |
535 | EXPORT_SYMBOL(unregister_sysrq_key); | 537 | EXPORT_SYMBOL(unregister_sysrq_key); |
538 | |||
539 | #ifdef CONFIG_PROC_FS | ||
540 | /* | ||
541 | * writing 'C' to /proc/sysrq-trigger is like sysrq-C | ||
542 | */ | ||
543 | static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf, | ||
544 | size_t count, loff_t *ppos) | ||
545 | { | ||
546 | if (count) { | ||
547 | char c; | ||
548 | |||
549 | if (get_user(c, buf)) | ||
550 | return -EFAULT; | ||
551 | __handle_sysrq(c, NULL, 0); | ||
552 | } | ||
553 | return count; | ||
554 | } | ||
555 | |||
556 | static const struct file_operations proc_sysrq_trigger_operations = { | ||
557 | .write = write_sysrq_trigger, | ||
558 | }; | ||
559 | |||
560 | static int __init sysrq_init(void) | ||
561 | { | ||
562 | proc_create("sysrq-trigger", S_IWUSR, NULL, &proc_sysrq_trigger_operations); | ||
563 | return 0; | ||
564 | } | ||
565 | module_init(sysrq_init); | ||
566 | #endif | ||
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 1fee7034a386..e70d13defde4 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -525,19 +525,19 @@ void tpm_get_timeouts(struct tpm_chip *chip) | |||
525 | timeout = | 525 | timeout = |
526 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))); | 526 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))); |
527 | if (timeout) | 527 | if (timeout) |
528 | chip->vendor.timeout_a = msecs_to_jiffies(timeout); | 528 | chip->vendor.timeout_a = usecs_to_jiffies(timeout); |
529 | timeout = | 529 | timeout = |
530 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_2_IDX))); | 530 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_2_IDX))); |
531 | if (timeout) | 531 | if (timeout) |
532 | chip->vendor.timeout_b = msecs_to_jiffies(timeout); | 532 | chip->vendor.timeout_b = usecs_to_jiffies(timeout); |
533 | timeout = | 533 | timeout = |
534 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_3_IDX))); | 534 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_3_IDX))); |
535 | if (timeout) | 535 | if (timeout) |
536 | chip->vendor.timeout_c = msecs_to_jiffies(timeout); | 536 | chip->vendor.timeout_c = usecs_to_jiffies(timeout); |
537 | timeout = | 537 | timeout = |
538 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_4_IDX))); | 538 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_4_IDX))); |
539 | if (timeout) | 539 | if (timeout) |
540 | chip->vendor.timeout_d = msecs_to_jiffies(timeout); | 540 | chip->vendor.timeout_d = usecs_to_jiffies(timeout); |
541 | 541 | ||
542 | duration: | 542 | duration: |
543 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | 543 | memcpy(data, tpm_cap, sizeof(tpm_cap)); |
@@ -554,15 +554,22 @@ duration: | |||
554 | return; | 554 | return; |
555 | 555 | ||
556 | chip->vendor.duration[TPM_SHORT] = | 556 | chip->vendor.duration[TPM_SHORT] = |
557 | msecs_to_jiffies(be32_to_cpu | 557 | usecs_to_jiffies(be32_to_cpu |
558 | (*((__be32 *) (data + | 558 | (*((__be32 *) (data + |
559 | TPM_GET_CAP_RET_UINT32_1_IDX)))); | 559 | TPM_GET_CAP_RET_UINT32_1_IDX)))); |
560 | /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above | ||
561 | * value wrong and apparently reports msecs rather than usecs. So we | ||
562 | * fix up the resulting too-small TPM_SHORT value to make things work. | ||
563 | */ | ||
564 | if (chip->vendor.duration[TPM_SHORT] < (HZ/100)) | ||
565 | chip->vendor.duration[TPM_SHORT] = HZ; | ||
566 | |||
560 | chip->vendor.duration[TPM_MEDIUM] = | 567 | chip->vendor.duration[TPM_MEDIUM] = |
561 | msecs_to_jiffies(be32_to_cpu | 568 | usecs_to_jiffies(be32_to_cpu |
562 | (*((__be32 *) (data + | 569 | (*((__be32 *) (data + |
563 | TPM_GET_CAP_RET_UINT32_2_IDX)))); | 570 | TPM_GET_CAP_RET_UINT32_2_IDX)))); |
564 | chip->vendor.duration[TPM_LONG] = | 571 | chip->vendor.duration[TPM_LONG] = |
565 | msecs_to_jiffies(be32_to_cpu | 572 | usecs_to_jiffies(be32_to_cpu |
566 | (*((__be32 *) (data + | 573 | (*((__be32 *) (data + |
567 | TPM_GET_CAP_RET_UINT32_3_IDX)))); | 574 | TPM_GET_CAP_RET_UINT32_3_IDX)))); |
568 | } | 575 | } |
@@ -1180,11 +1187,8 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, | |||
1180 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | 1187 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); |
1181 | devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL); | 1188 | devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL); |
1182 | 1189 | ||
1183 | if (chip == NULL || devname == NULL) { | 1190 | if (chip == NULL || devname == NULL) |
1184 | kfree(chip); | 1191 | goto out_free; |
1185 | kfree(devname); | ||
1186 | return NULL; | ||
1187 | } | ||
1188 | 1192 | ||
1189 | mutex_init(&chip->buffer_mutex); | 1193 | mutex_init(&chip->buffer_mutex); |
1190 | mutex_init(&chip->tpm_mutex); | 1194 | mutex_init(&chip->tpm_mutex); |
@@ -1201,8 +1205,7 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, | |||
1201 | 1205 | ||
1202 | if (chip->dev_num >= TPM_NUM_DEVICES) { | 1206 | if (chip->dev_num >= TPM_NUM_DEVICES) { |
1203 | dev_err(dev, "No available tpm device numbers\n"); | 1207 | dev_err(dev, "No available tpm device numbers\n"); |
1204 | kfree(chip); | 1208 | goto out_free; |
1205 | return NULL; | ||
1206 | } else if (chip->dev_num == 0) | 1209 | } else if (chip->dev_num == 0) |
1207 | chip->vendor.miscdev.minor = TPM_MINOR; | 1210 | chip->vendor.miscdev.minor = TPM_MINOR; |
1208 | else | 1211 | else |
@@ -1243,6 +1246,11 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, | |||
1243 | spin_unlock(&driver_lock); | 1246 | spin_unlock(&driver_lock); |
1244 | 1247 | ||
1245 | return chip; | 1248 | return chip; |
1249 | |||
1250 | out_free: | ||
1251 | kfree(chip); | ||
1252 | kfree(devname); | ||
1253 | return NULL; | ||
1246 | } | 1254 | } |
1247 | EXPORT_SYMBOL_GPL(tpm_register_hardware); | 1255 | EXPORT_SYMBOL_GPL(tpm_register_hardware); |
1248 | 1256 | ||
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index a0f7ffb68087..d8f83e26e4a4 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -59,7 +59,7 @@ | |||
59 | * by Martin Mares <mj@atrey.karlin.mff.cuni.cz>, July 1998 | 59 | * by Martin Mares <mj@atrey.karlin.mff.cuni.cz>, July 1998 |
60 | * | 60 | * |
61 | * Removed old-style timers, introduced console_timer, made timer | 61 | * Removed old-style timers, introduced console_timer, made timer |
62 | * deletion SMP-safe. 17Jun00, Andrew Morton <andrewm@uow.edu.au> | 62 | * deletion SMP-safe. 17Jun00, Andrew Morton |
63 | * | 63 | * |
64 | * Removed console_lock, enabled interrupts across all console operations | 64 | * Removed console_lock, enabled interrupts across all console operations |
65 | * 13 March 2001, Andrew Morton | 65 | * 13 March 2001, Andrew Morton |
diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index 4a16b5b61cfb..f0d9b415db50 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c | |||
@@ -119,6 +119,7 @@ | |||
119 | #define FERR_NF_UNCORRECTABLE (FERR_NF_M12ERR | \ | 119 | #define FERR_NF_UNCORRECTABLE (FERR_NF_M12ERR | \ |
120 | FERR_NF_M11ERR | \ | 120 | FERR_NF_M11ERR | \ |
121 | FERR_NF_M10ERR | \ | 121 | FERR_NF_M10ERR | \ |
122 | FERR_NF_M9ERR | \ | ||
122 | FERR_NF_M8ERR | \ | 123 | FERR_NF_M8ERR | \ |
123 | FERR_NF_M7ERR | \ | 124 | FERR_NF_M7ERR | \ |
124 | FERR_NF_M6ERR | \ | 125 | FERR_NF_M6ERR | \ |
@@ -301,6 +302,9 @@ static char *numcol_toString[] = { | |||
301 | }; | 302 | }; |
302 | #endif | 303 | #endif |
303 | 304 | ||
305 | /* enables the report of miscellaneous messages as CE errors - default off */ | ||
306 | static int misc_messages; | ||
307 | |||
304 | /* Enumeration of supported devices */ | 308 | /* Enumeration of supported devices */ |
305 | enum i5000_chips { | 309 | enum i5000_chips { |
306 | I5000P = 0, | 310 | I5000P = 0, |
@@ -466,7 +470,8 @@ static void i5000_process_fatal_error_info(struct mem_ctl_info *mci, | |||
466 | struct i5000_error_info *info, | 470 | struct i5000_error_info *info, |
467 | int handle_errors) | 471 | int handle_errors) |
468 | { | 472 | { |
469 | char msg[EDAC_MC_LABEL_LEN + 1 + 90]; | 473 | char msg[EDAC_MC_LABEL_LEN + 1 + 160]; |
474 | char *specific = NULL; | ||
470 | u32 allErrors; | 475 | u32 allErrors; |
471 | int branch; | 476 | int branch; |
472 | int channel; | 477 | int channel; |
@@ -480,11 +485,6 @@ static void i5000_process_fatal_error_info(struct mem_ctl_info *mci, | |||
480 | if (!allErrors) | 485 | if (!allErrors) |
481 | return; /* if no error, return now */ | 486 | return; /* if no error, return now */ |
482 | 487 | ||
483 | /* ONLY ONE of the possible error bits will be set, as per the docs */ | ||
484 | i5000_mc_printk(mci, KERN_ERR, | ||
485 | "FATAL ERRORS Found!!! 1st FATAL Err Reg= 0x%x\n", | ||
486 | allErrors); | ||
487 | |||
488 | branch = EXTRACT_FBDCHAN_INDX(info->ferr_fat_fbd); | 488 | branch = EXTRACT_FBDCHAN_INDX(info->ferr_fat_fbd); |
489 | channel = branch; | 489 | channel = branch; |
490 | 490 | ||
@@ -501,28 +501,42 @@ static void i5000_process_fatal_error_info(struct mem_ctl_info *mci, | |||
501 | rdwr ? "Write" : "Read", ras, cas); | 501 | rdwr ? "Write" : "Read", ras, cas); |
502 | 502 | ||
503 | /* Only 1 bit will be on */ | 503 | /* Only 1 bit will be on */ |
504 | if (allErrors & FERR_FAT_M1ERR) { | 504 | switch (allErrors) { |
505 | i5000_mc_printk(mci, KERN_ERR, | 505 | case FERR_FAT_M1ERR: |
506 | "Alert on non-redundant retry or fast " | 506 | specific = "Alert on non-redundant retry or fast " |
507 | "reset timeout\n"); | 507 | "reset timeout"; |
508 | 508 | break; | |
509 | } else if (allErrors & FERR_FAT_M2ERR) { | 509 | case FERR_FAT_M2ERR: |
510 | i5000_mc_printk(mci, KERN_ERR, | 510 | specific = "Northbound CRC error on non-redundant " |
511 | "Northbound CRC error on non-redundant " | 511 | "retry"; |
512 | "retry\n"); | 512 | break; |
513 | 513 | case FERR_FAT_M3ERR: | |
514 | } else if (allErrors & FERR_FAT_M3ERR) { | 514 | { |
515 | i5000_mc_printk(mci, KERN_ERR, | 515 | static int done; |
516 | ">Tmid Thermal event with intelligent " | 516 | |
517 | "throttling disabled\n"); | 517 | /* |
518 | * This error is generated to inform that the intelligent | ||
519 | * throttling is disabled and the temperature passed the | ||
520 | * specified middle point. Since this is something the BIOS | ||
521 | * should take care of, we'll warn only once to avoid | ||
522 | * worthlessly flooding the log. | ||
523 | */ | ||
524 | if (done) | ||
525 | return; | ||
526 | done++; | ||
527 | |||
528 | specific = ">Tmid Thermal event with intelligent " | ||
529 | "throttling disabled"; | ||
530 | } | ||
531 | break; | ||
518 | } | 532 | } |
519 | 533 | ||
520 | /* Form out message */ | 534 | /* Form out message */ |
521 | snprintf(msg, sizeof(msg), | 535 | snprintf(msg, sizeof(msg), |
522 | "(Branch=%d DRAM-Bank=%d RDWR=%s RAS=%d CAS=%d " | 536 | "(Branch=%d DRAM-Bank=%d RDWR=%s RAS=%d CAS=%d " |
523 | "FATAL Err=0x%x)", | 537 | "FATAL Err=0x%x (%s))", |
524 | branch >> 1, bank, rdwr ? "Write" : "Read", ras, cas, | 538 | branch >> 1, bank, rdwr ? "Write" : "Read", ras, cas, |
525 | allErrors); | 539 | allErrors, specific); |
526 | 540 | ||
527 | /* Call the helper to output message */ | 541 | /* Call the helper to output message */ |
528 | edac_mc_handle_fbd_ue(mci, rank, channel, channel + 1, msg); | 542 | edac_mc_handle_fbd_ue(mci, rank, channel, channel + 1, msg); |
@@ -539,7 +553,8 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci, | |||
539 | struct i5000_error_info *info, | 553 | struct i5000_error_info *info, |
540 | int handle_errors) | 554 | int handle_errors) |
541 | { | 555 | { |
542 | char msg[EDAC_MC_LABEL_LEN + 1 + 90]; | 556 | char msg[EDAC_MC_LABEL_LEN + 1 + 170]; |
557 | char *specific = NULL; | ||
543 | u32 allErrors; | 558 | u32 allErrors; |
544 | u32 ue_errors; | 559 | u32 ue_errors; |
545 | u32 ce_errors; | 560 | u32 ce_errors; |
@@ -557,10 +572,6 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci, | |||
557 | return; /* if no error, return now */ | 572 | return; /* if no error, return now */ |
558 | 573 | ||
559 | /* ONLY ONE of the possible error bits will be set, as per the docs */ | 574 | /* ONLY ONE of the possible error bits will be set, as per the docs */ |
560 | i5000_mc_printk(mci, KERN_WARNING, | ||
561 | "NON-FATAL ERRORS Found!!! 1st NON-FATAL Err " | ||
562 | "Reg= 0x%x\n", allErrors); | ||
563 | |||
564 | ue_errors = allErrors & FERR_NF_UNCORRECTABLE; | 575 | ue_errors = allErrors & FERR_NF_UNCORRECTABLE; |
565 | if (ue_errors) { | 576 | if (ue_errors) { |
566 | debugf0("\tUncorrected bits= 0x%x\n", ue_errors); | 577 | debugf0("\tUncorrected bits= 0x%x\n", ue_errors); |
@@ -579,12 +590,47 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci, | |||
579 | rank, channel, channel + 1, branch >> 1, bank, | 590 | rank, channel, channel + 1, branch >> 1, bank, |
580 | rdwr ? "Write" : "Read", ras, cas); | 591 | rdwr ? "Write" : "Read", ras, cas); |
581 | 592 | ||
593 | switch (ue_errors) { | ||
594 | case FERR_NF_M12ERR: | ||
595 | specific = "Non-Aliased Uncorrectable Patrol Data ECC"; | ||
596 | break; | ||
597 | case FERR_NF_M11ERR: | ||
598 | specific = "Non-Aliased Uncorrectable Spare-Copy " | ||
599 | "Data ECC"; | ||
600 | break; | ||
601 | case FERR_NF_M10ERR: | ||
602 | specific = "Non-Aliased Uncorrectable Mirrored Demand " | ||
603 | "Data ECC"; | ||
604 | break; | ||
605 | case FERR_NF_M9ERR: | ||
606 | specific = "Non-Aliased Uncorrectable Non-Mirrored " | ||
607 | "Demand Data ECC"; | ||
608 | break; | ||
609 | case FERR_NF_M8ERR: | ||
610 | specific = "Aliased Uncorrectable Patrol Data ECC"; | ||
611 | break; | ||
612 | case FERR_NF_M7ERR: | ||
613 | specific = "Aliased Uncorrectable Spare-Copy Data ECC"; | ||
614 | break; | ||
615 | case FERR_NF_M6ERR: | ||
616 | specific = "Aliased Uncorrectable Mirrored Demand " | ||
617 | "Data ECC"; | ||
618 | break; | ||
619 | case FERR_NF_M5ERR: | ||
620 | specific = "Aliased Uncorrectable Non-Mirrored Demand " | ||
621 | "Data ECC"; | ||
622 | break; | ||
623 | case FERR_NF_M4ERR: | ||
624 | specific = "Uncorrectable Data ECC on Replay"; | ||
625 | break; | ||
626 | } | ||
627 | |||
582 | /* Form out message */ | 628 | /* Form out message */ |
583 | snprintf(msg, sizeof(msg), | 629 | snprintf(msg, sizeof(msg), |
584 | "(Branch=%d DRAM-Bank=%d RDWR=%s RAS=%d " | 630 | "(Branch=%d DRAM-Bank=%d RDWR=%s RAS=%d " |
585 | "CAS=%d, UE Err=0x%x)", | 631 | "CAS=%d, UE Err=0x%x (%s))", |
586 | branch >> 1, bank, rdwr ? "Write" : "Read", ras, cas, | 632 | branch >> 1, bank, rdwr ? "Write" : "Read", ras, cas, |
587 | ue_errors); | 633 | ue_errors, specific); |
588 | 634 | ||
589 | /* Call the helper to output message */ | 635 | /* Call the helper to output message */ |
590 | edac_mc_handle_fbd_ue(mci, rank, channel, channel + 1, msg); | 636 | edac_mc_handle_fbd_ue(mci, rank, channel, channel + 1, msg); |
@@ -616,51 +662,74 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci, | |||
616 | rank, channel, branch >> 1, bank, | 662 | rank, channel, branch >> 1, bank, |
617 | rdwr ? "Write" : "Read", ras, cas); | 663 | rdwr ? "Write" : "Read", ras, cas); |
618 | 664 | ||
665 | switch (ce_errors) { | ||
666 | case FERR_NF_M17ERR: | ||
667 | specific = "Correctable Non-Mirrored Demand Data ECC"; | ||
668 | break; | ||
669 | case FERR_NF_M18ERR: | ||
670 | specific = "Correctable Mirrored Demand Data ECC"; | ||
671 | break; | ||
672 | case FERR_NF_M19ERR: | ||
673 | specific = "Correctable Spare-Copy Data ECC"; | ||
674 | break; | ||
675 | case FERR_NF_M20ERR: | ||
676 | specific = "Correctable Patrol Data ECC"; | ||
677 | break; | ||
678 | } | ||
679 | |||
619 | /* Form out message */ | 680 | /* Form out message */ |
620 | snprintf(msg, sizeof(msg), | 681 | snprintf(msg, sizeof(msg), |
621 | "(Branch=%d DRAM-Bank=%d RDWR=%s RAS=%d " | 682 | "(Branch=%d DRAM-Bank=%d RDWR=%s RAS=%d " |
622 | "CAS=%d, CE Err=0x%x)", branch >> 1, bank, | 683 | "CAS=%d, CE Err=0x%x (%s))", branch >> 1, bank, |
623 | rdwr ? "Write" : "Read", ras, cas, ce_errors); | 684 | rdwr ? "Write" : "Read", ras, cas, ce_errors, |
685 | specific); | ||
624 | 686 | ||
625 | /* Call the helper to output message */ | 687 | /* Call the helper to output message */ |
626 | edac_mc_handle_fbd_ce(mci, rank, channel, msg); | 688 | edac_mc_handle_fbd_ce(mci, rank, channel, msg); |
627 | } | 689 | } |
628 | 690 | ||
629 | /* See if any of the thermal errors have fired */ | 691 | if (!misc_messages) |
630 | misc_errors = allErrors & FERR_NF_THERMAL; | 692 | return; |
631 | if (misc_errors) { | ||
632 | i5000_printk(KERN_WARNING, "\tTHERMAL Error, bits= 0x%x\n", | ||
633 | misc_errors); | ||
634 | } | ||
635 | |||
636 | /* See if any of the thermal errors have fired */ | ||
637 | misc_errors = allErrors & FERR_NF_NON_RETRY; | ||
638 | if (misc_errors) { | ||
639 | i5000_printk(KERN_WARNING, "\tNON-Retry Errors, bits= 0x%x\n", | ||
640 | misc_errors); | ||
641 | } | ||
642 | 693 | ||
643 | /* See if any of the thermal errors have fired */ | 694 | misc_errors = allErrors & (FERR_NF_NON_RETRY | FERR_NF_NORTH_CRC | |
644 | misc_errors = allErrors & FERR_NF_NORTH_CRC; | 695 | FERR_NF_SPD_PROTOCOL | FERR_NF_DIMM_SPARE); |
645 | if (misc_errors) { | 696 | if (misc_errors) { |
646 | i5000_printk(KERN_WARNING, | 697 | switch (misc_errors) { |
647 | "\tNORTHBOUND CRC Error, bits= 0x%x\n", | 698 | case FERR_NF_M13ERR: |
648 | misc_errors); | 699 | specific = "Non-Retry or Redundant Retry FBD Memory " |
649 | } | 700 | "Alert or Redundant Fast Reset Timeout"; |
701 | break; | ||
702 | case FERR_NF_M14ERR: | ||
703 | specific = "Non-Retry or Redundant Retry FBD " | ||
704 | "Configuration Alert"; | ||
705 | break; | ||
706 | case FERR_NF_M15ERR: | ||
707 | specific = "Non-Retry or Redundant Retry FBD " | ||
708 | "Northbound CRC error on read data"; | ||
709 | break; | ||
710 | case FERR_NF_M21ERR: | ||
711 | specific = "FBD Northbound CRC error on " | ||
712 | "FBD Sync Status"; | ||
713 | break; | ||
714 | case FERR_NF_M22ERR: | ||
715 | specific = "SPD protocol error"; | ||
716 | break; | ||
717 | case FERR_NF_M27ERR: | ||
718 | specific = "DIMM-spare copy started"; | ||
719 | break; | ||
720 | case FERR_NF_M28ERR: | ||
721 | specific = "DIMM-spare copy completed"; | ||
722 | break; | ||
723 | } | ||
724 | branch = EXTRACT_FBDCHAN_INDX(info->ferr_nf_fbd); | ||
650 | 725 | ||
651 | /* See if any of the thermal errors have fired */ | 726 | /* Form out message */ |
652 | misc_errors = allErrors & FERR_NF_SPD_PROTOCOL; | 727 | snprintf(msg, sizeof(msg), |
653 | if (misc_errors) { | 728 | "(Branch=%d Err=%#x (%s))", branch >> 1, |
654 | i5000_printk(KERN_WARNING, | 729 | misc_errors, specific); |
655 | "\tSPD Protocol Error, bits= 0x%x\n", | ||
656 | misc_errors); | ||
657 | } | ||
658 | 730 | ||
659 | /* See if any of the thermal errors have fired */ | 731 | /* Call the helper to output message */ |
660 | misc_errors = allErrors & FERR_NF_DIMM_SPARE; | 732 | edac_mc_handle_fbd_ce(mci, 0, 0, msg); |
661 | if (misc_errors) { | ||
662 | i5000_printk(KERN_WARNING, "\tDIMM-Spare Error, bits= 0x%x\n", | ||
663 | misc_errors); | ||
664 | } | 733 | } |
665 | } | 734 | } |
666 | 735 | ||
@@ -1497,3 +1566,6 @@ MODULE_DESCRIPTION("MC Driver for Intel I5000 memory controllers - " | |||
1497 | 1566 | ||
1498 | module_param(edac_op_state, int, 0444); | 1567 | module_param(edac_op_state, int, 0444); |
1499 | MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI"); | 1568 | MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI"); |
1569 | module_param(misc_messages, int, 0444); | ||
1570 | MODULE_PARM_DESC(misc_messages, "Log miscellaneous non fatal messages"); | ||
1571 | |||
diff --git a/drivers/edac/i82443bxgx_edac.c b/drivers/edac/i82443bxgx_edac.c index c5305e3ee434..577760a82a0f 100644 --- a/drivers/edac/i82443bxgx_edac.c +++ b/drivers/edac/i82443bxgx_edac.c | |||
@@ -114,6 +114,12 @@ struct i82443bxgx_edacmc_error_info { | |||
114 | 114 | ||
115 | static struct edac_pci_ctl_info *i82443bxgx_pci; | 115 | static struct edac_pci_ctl_info *i82443bxgx_pci; |
116 | 116 | ||
117 | static struct pci_dev *mci_pdev; /* init dev: in case that AGP code has | ||
118 | * already registered driver | ||
119 | */ | ||
120 | |||
121 | static int i82443bxgx_registered = 1; | ||
122 | |||
117 | static void i82443bxgx_edacmc_get_error_info(struct mem_ctl_info *mci, | 123 | static void i82443bxgx_edacmc_get_error_info(struct mem_ctl_info *mci, |
118 | struct i82443bxgx_edacmc_error_info | 124 | struct i82443bxgx_edacmc_error_info |
119 | *info) | 125 | *info) |
@@ -345,10 +351,17 @@ EXPORT_SYMBOL_GPL(i82443bxgx_edacmc_probe1); | |||
345 | static int __devinit i82443bxgx_edacmc_init_one(struct pci_dev *pdev, | 351 | static int __devinit i82443bxgx_edacmc_init_one(struct pci_dev *pdev, |
346 | const struct pci_device_id *ent) | 352 | const struct pci_device_id *ent) |
347 | { | 353 | { |
354 | int rc; | ||
355 | |||
348 | debugf0("MC: " __FILE__ ": %s()\n", __func__); | 356 | debugf0("MC: " __FILE__ ": %s()\n", __func__); |
349 | 357 | ||
350 | /* don't need to call pci_device_enable() */ | 358 | /* don't need to call pci_device_enable() */ |
351 | return i82443bxgx_edacmc_probe1(pdev, ent->driver_data); | 359 | rc = i82443bxgx_edacmc_probe1(pdev, ent->driver_data); |
360 | |||
361 | if (mci_pdev == NULL) | ||
362 | mci_pdev = pci_dev_get(pdev); | ||
363 | |||
364 | return rc; | ||
352 | } | 365 | } |
353 | 366 | ||
354 | static void __devexit i82443bxgx_edacmc_remove_one(struct pci_dev *pdev) | 367 | static void __devexit i82443bxgx_edacmc_remove_one(struct pci_dev *pdev) |
@@ -387,15 +400,61 @@ static struct pci_driver i82443bxgx_edacmc_driver = { | |||
387 | 400 | ||
388 | static int __init i82443bxgx_edacmc_init(void) | 401 | static int __init i82443bxgx_edacmc_init(void) |
389 | { | 402 | { |
403 | int pci_rc; | ||
390 | /* Ensure that the OPSTATE is set correctly for POLL or NMI */ | 404 | /* Ensure that the OPSTATE is set correctly for POLL or NMI */ |
391 | opstate_init(); | 405 | opstate_init(); |
392 | 406 | ||
393 | return pci_register_driver(&i82443bxgx_edacmc_driver); | 407 | pci_rc = pci_register_driver(&i82443bxgx_edacmc_driver); |
408 | if (pci_rc < 0) | ||
409 | goto fail0; | ||
410 | |||
411 | if (mci_pdev == NULL) { | ||
412 | const struct pci_device_id *id = &i82443bxgx_pci_tbl[0]; | ||
413 | int i = 0; | ||
414 | i82443bxgx_registered = 0; | ||
415 | |||
416 | while (mci_pdev == NULL && id->vendor != 0) { | ||
417 | mci_pdev = pci_get_device(id->vendor, | ||
418 | id->device, NULL); | ||
419 | i++; | ||
420 | id = &i82443bxgx_pci_tbl[i]; | ||
421 | } | ||
422 | if (!mci_pdev) { | ||
423 | debugf0("i82443bxgx pci_get_device fail\n"); | ||
424 | pci_rc = -ENODEV; | ||
425 | goto fail1; | ||
426 | } | ||
427 | |||
428 | pci_rc = i82443bxgx_edacmc_init_one(mci_pdev, i82443bxgx_pci_tbl); | ||
429 | |||
430 | if (pci_rc < 0) { | ||
431 | debugf0("i82443bxgx init fail\n"); | ||
432 | pci_rc = -ENODEV; | ||
433 | goto fail1; | ||
434 | } | ||
435 | } | ||
436 | |||
437 | return 0; | ||
438 | |||
439 | fail1: | ||
440 | pci_unregister_driver(&i82443bxgx_edacmc_driver); | ||
441 | |||
442 | fail0: | ||
443 | if (mci_pdev != NULL) | ||
444 | pci_dev_put(mci_pdev); | ||
445 | |||
446 | return pci_rc; | ||
394 | } | 447 | } |
395 | 448 | ||
396 | static void __exit i82443bxgx_edacmc_exit(void) | 449 | static void __exit i82443bxgx_edacmc_exit(void) |
397 | { | 450 | { |
398 | pci_unregister_driver(&i82443bxgx_edacmc_driver); | 451 | pci_unregister_driver(&i82443bxgx_edacmc_driver); |
452 | |||
453 | if (!i82443bxgx_registered) | ||
454 | i82443bxgx_edacmc_remove_one(mci_pdev); | ||
455 | |||
456 | if (mci_pdev) | ||
457 | pci_dev_put(mci_pdev); | ||
399 | } | 458 | } |
400 | 459 | ||
401 | module_init(i82443bxgx_edacmc_init); | 460 | module_init(i82443bxgx_edacmc_init); |
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index 2265d9ca1535..0cfcb2d075a0 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <linux/mod_devicetable.h> | 18 | #include <linux/mod_devicetable.h> |
19 | #include <linux/edac.h> | 19 | #include <linux/edac.h> |
20 | #include <linux/smp.h> | ||
20 | 21 | ||
21 | #include <linux/of_platform.h> | 22 | #include <linux/of_platform.h> |
22 | #include <linux/of_device.h> | 23 | #include <linux/of_device.h> |
@@ -40,7 +41,7 @@ static u32 orig_pci_err_en; | |||
40 | #endif | 41 | #endif |
41 | 42 | ||
42 | static u32 orig_l2_err_disable; | 43 | static u32 orig_l2_err_disable; |
43 | static u32 orig_hid1; | 44 | static u32 orig_hid1[2]; |
44 | 45 | ||
45 | /************************ MC SYSFS parts ***********************************/ | 46 | /************************ MC SYSFS parts ***********************************/ |
46 | 47 | ||
@@ -647,6 +648,9 @@ static struct of_device_id mpc85xx_l2_err_of_match[] = { | |||
647 | { | 648 | { |
648 | .compatible = "fsl,8568-l2-cache-controller", | 649 | .compatible = "fsl,8568-l2-cache-controller", |
649 | }, | 650 | }, |
651 | { | ||
652 | .compatible = "fsl,mpc8572-l2-cache-controller", | ||
653 | }, | ||
650 | {}, | 654 | {}, |
651 | }; | 655 | }; |
652 | 656 | ||
@@ -912,7 +916,8 @@ static int __devinit mpc85xx_mc_err_probe(struct of_device *op, | |||
912 | /* register interrupts */ | 916 | /* register interrupts */ |
913 | pdata->irq = irq_of_parse_and_map(op->node, 0); | 917 | pdata->irq = irq_of_parse_and_map(op->node, 0); |
914 | res = devm_request_irq(&op->dev, pdata->irq, | 918 | res = devm_request_irq(&op->dev, pdata->irq, |
915 | mpc85xx_mc_isr, IRQF_DISABLED, | 919 | mpc85xx_mc_isr, |
920 | IRQF_DISABLED | IRQF_SHARED, | ||
916 | "[EDAC] MC err", mci); | 921 | "[EDAC] MC err", mci); |
917 | if (res < 0) { | 922 | if (res < 0) { |
918 | printk(KERN_ERR "%s: Unable to request irq %d for " | 923 | printk(KERN_ERR "%s: Unable to request irq %d for " |
@@ -980,6 +985,9 @@ static struct of_device_id mpc85xx_mc_err_of_match[] = { | |||
980 | { | 985 | { |
981 | .compatible = "fsl,8568-memory-controller", | 986 | .compatible = "fsl,8568-memory-controller", |
982 | }, | 987 | }, |
988 | { | ||
989 | .compatible = "fsl,mpc8572-memory-controller", | ||
990 | }, | ||
983 | {}, | 991 | {}, |
984 | }; | 992 | }; |
985 | 993 | ||
@@ -995,6 +1003,14 @@ static struct of_platform_driver mpc85xx_mc_err_driver = { | |||
995 | }, | 1003 | }, |
996 | }; | 1004 | }; |
997 | 1005 | ||
1006 | |||
1007 | static void __init mpc85xx_mc_clear_rfxe(void *data) | ||
1008 | { | ||
1009 | orig_hid1[smp_processor_id()] = mfspr(SPRN_HID1); | ||
1010 | mtspr(SPRN_HID1, (orig_hid1[smp_processor_id()] & ~0x20000)); | ||
1011 | } | ||
1012 | |||
1013 | |||
998 | static int __init mpc85xx_mc_init(void) | 1014 | static int __init mpc85xx_mc_init(void) |
999 | { | 1015 | { |
1000 | int res = 0; | 1016 | int res = 0; |
@@ -1030,19 +1046,22 @@ static int __init mpc85xx_mc_init(void) | |||
1030 | * need to clear HID1[RFXE] to disable machine check int | 1046 | * need to clear HID1[RFXE] to disable machine check int |
1031 | * so we can catch it | 1047 | * so we can catch it |
1032 | */ | 1048 | */ |
1033 | if (edac_op_state == EDAC_OPSTATE_INT) { | 1049 | if (edac_op_state == EDAC_OPSTATE_INT) |
1034 | orig_hid1 = mfspr(SPRN_HID1); | 1050 | on_each_cpu(mpc85xx_mc_clear_rfxe, NULL, 0); |
1035 | mtspr(SPRN_HID1, (orig_hid1 & ~0x20000)); | ||
1036 | } | ||
1037 | 1051 | ||
1038 | return 0; | 1052 | return 0; |
1039 | } | 1053 | } |
1040 | 1054 | ||
1041 | module_init(mpc85xx_mc_init); | 1055 | module_init(mpc85xx_mc_init); |
1042 | 1056 | ||
1057 | static void __exit mpc85xx_mc_restore_hid1(void *data) | ||
1058 | { | ||
1059 | mtspr(SPRN_HID1, orig_hid1[smp_processor_id()]); | ||
1060 | } | ||
1061 | |||
1043 | static void __exit mpc85xx_mc_exit(void) | 1062 | static void __exit mpc85xx_mc_exit(void) |
1044 | { | 1063 | { |
1045 | mtspr(SPRN_HID1, orig_hid1); | 1064 | on_each_cpu(mpc85xx_mc_restore_hid1, NULL, 0); |
1046 | #ifdef CONFIG_PCI | 1065 | #ifdef CONFIG_PCI |
1047 | of_unregister_platform_driver(&mpc85xx_pci_err_driver); | 1066 | of_unregister_platform_driver(&mpc85xx_pci_err_driver); |
1048 | #endif | 1067 | #endif |
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 8d2940517c99..9112830107a5 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -67,17 +67,28 @@ static inline void desc_set_label(struct gpio_desc *d, const char *label) | |||
67 | * when setting direction, and otherwise illegal. Until board setup code | 67 | * when setting direction, and otherwise illegal. Until board setup code |
68 | * and drivers use explicit requests everywhere (which won't happen when | 68 | * and drivers use explicit requests everywhere (which won't happen when |
69 | * those calls have no teeth) we can't avoid autorequesting. This nag | 69 | * those calls have no teeth) we can't avoid autorequesting. This nag |
70 | * message should motivate switching to explicit requests... | 70 | * message should motivate switching to explicit requests... so should |
71 | * the weaker cleanup after faults, compared to gpio_request(). | ||
71 | */ | 72 | */ |
72 | static void gpio_ensure_requested(struct gpio_desc *desc) | 73 | static int gpio_ensure_requested(struct gpio_desc *desc, unsigned offset) |
73 | { | 74 | { |
74 | if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) { | 75 | if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) { |
75 | pr_warning("GPIO-%d autorequested\n", (int)(desc - gpio_desc)); | 76 | struct gpio_chip *chip = desc->chip; |
77 | int gpio = chip->base + offset; | ||
78 | |||
79 | if (!try_module_get(chip->owner)) { | ||
80 | pr_err("GPIO-%d: module can't be gotten \n", gpio); | ||
81 | clear_bit(FLAG_REQUESTED, &desc->flags); | ||
82 | /* lose */ | ||
83 | return -EIO; | ||
84 | } | ||
85 | pr_warning("GPIO-%d autorequested\n", gpio); | ||
76 | desc_set_label(desc, "[auto]"); | 86 | desc_set_label(desc, "[auto]"); |
77 | if (!try_module_get(desc->chip->owner)) | 87 | /* caller must chip->request() w/o spinlock */ |
78 | pr_err("GPIO-%d: module can't be gotten \n", | 88 | if (chip->request) |
79 | (int)(desc - gpio_desc)); | 89 | return 1; |
80 | } | 90 | } |
91 | return 0; | ||
81 | } | 92 | } |
82 | 93 | ||
83 | /* caller holds gpio_lock *OR* gpio is marked as requested */ | 94 | /* caller holds gpio_lock *OR* gpio is marked as requested */ |
@@ -752,6 +763,7 @@ EXPORT_SYMBOL_GPL(gpiochip_remove); | |||
752 | int gpio_request(unsigned gpio, const char *label) | 763 | int gpio_request(unsigned gpio, const char *label) |
753 | { | 764 | { |
754 | struct gpio_desc *desc; | 765 | struct gpio_desc *desc; |
766 | struct gpio_chip *chip; | ||
755 | int status = -EINVAL; | 767 | int status = -EINVAL; |
756 | unsigned long flags; | 768 | unsigned long flags; |
757 | 769 | ||
@@ -760,14 +772,15 @@ int gpio_request(unsigned gpio, const char *label) | |||
760 | if (!gpio_is_valid(gpio)) | 772 | if (!gpio_is_valid(gpio)) |
761 | goto done; | 773 | goto done; |
762 | desc = &gpio_desc[gpio]; | 774 | desc = &gpio_desc[gpio]; |
763 | if (desc->chip == NULL) | 775 | chip = desc->chip; |
776 | if (chip == NULL) | ||
764 | goto done; | 777 | goto done; |
765 | 778 | ||
766 | if (!try_module_get(desc->chip->owner)) | 779 | if (!try_module_get(chip->owner)) |
767 | goto done; | 780 | goto done; |
768 | 781 | ||
769 | /* NOTE: gpio_request() can be called in early boot, | 782 | /* NOTE: gpio_request() can be called in early boot, |
770 | * before IRQs are enabled. | 783 | * before IRQs are enabled, for non-sleeping (SOC) GPIOs. |
771 | */ | 784 | */ |
772 | 785 | ||
773 | if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) { | 786 | if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) { |
@@ -775,7 +788,20 @@ int gpio_request(unsigned gpio, const char *label) | |||
775 | status = 0; | 788 | status = 0; |
776 | } else { | 789 | } else { |
777 | status = -EBUSY; | 790 | status = -EBUSY; |
778 | module_put(desc->chip->owner); | 791 | module_put(chip->owner); |
792 | } | ||
793 | |||
794 | if (chip->request) { | ||
795 | /* chip->request may sleep */ | ||
796 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
797 | status = chip->request(chip, gpio - chip->base); | ||
798 | spin_lock_irqsave(&gpio_lock, flags); | ||
799 | |||
800 | if (status < 0) { | ||
801 | desc_set_label(desc, NULL); | ||
802 | module_put(chip->owner); | ||
803 | clear_bit(FLAG_REQUESTED, &desc->flags); | ||
804 | } | ||
779 | } | 805 | } |
780 | 806 | ||
781 | done: | 807 | done: |
@@ -791,6 +817,9 @@ void gpio_free(unsigned gpio) | |||
791 | { | 817 | { |
792 | unsigned long flags; | 818 | unsigned long flags; |
793 | struct gpio_desc *desc; | 819 | struct gpio_desc *desc; |
820 | struct gpio_chip *chip; | ||
821 | |||
822 | might_sleep(); | ||
794 | 823 | ||
795 | if (!gpio_is_valid(gpio)) { | 824 | if (!gpio_is_valid(gpio)) { |
796 | WARN_ON(extra_checks); | 825 | WARN_ON(extra_checks); |
@@ -802,9 +831,17 @@ void gpio_free(unsigned gpio) | |||
802 | spin_lock_irqsave(&gpio_lock, flags); | 831 | spin_lock_irqsave(&gpio_lock, flags); |
803 | 832 | ||
804 | desc = &gpio_desc[gpio]; | 833 | desc = &gpio_desc[gpio]; |
805 | if (desc->chip && test_and_clear_bit(FLAG_REQUESTED, &desc->flags)) { | 834 | chip = desc->chip; |
835 | if (chip && test_bit(FLAG_REQUESTED, &desc->flags)) { | ||
836 | if (chip->free) { | ||
837 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
838 | might_sleep_if(extra_checks && chip->can_sleep); | ||
839 | chip->free(chip, gpio - chip->base); | ||
840 | spin_lock_irqsave(&gpio_lock, flags); | ||
841 | } | ||
806 | desc_set_label(desc, NULL); | 842 | desc_set_label(desc, NULL); |
807 | module_put(desc->chip->owner); | 843 | module_put(desc->chip->owner); |
844 | clear_bit(FLAG_REQUESTED, &desc->flags); | ||
808 | } else | 845 | } else |
809 | WARN_ON(extra_checks); | 846 | WARN_ON(extra_checks); |
810 | 847 | ||
@@ -869,7 +906,9 @@ int gpio_direction_input(unsigned gpio) | |||
869 | gpio -= chip->base; | 906 | gpio -= chip->base; |
870 | if (gpio >= chip->ngpio) | 907 | if (gpio >= chip->ngpio) |
871 | goto fail; | 908 | goto fail; |
872 | gpio_ensure_requested(desc); | 909 | status = gpio_ensure_requested(desc, gpio); |
910 | if (status < 0) | ||
911 | goto fail; | ||
873 | 912 | ||
874 | /* now we know the gpio is valid and chip won't vanish */ | 913 | /* now we know the gpio is valid and chip won't vanish */ |
875 | 914 | ||
@@ -877,9 +916,22 @@ int gpio_direction_input(unsigned gpio) | |||
877 | 916 | ||
878 | might_sleep_if(extra_checks && chip->can_sleep); | 917 | might_sleep_if(extra_checks && chip->can_sleep); |
879 | 918 | ||
919 | if (status) { | ||
920 | status = chip->request(chip, gpio); | ||
921 | if (status < 0) { | ||
922 | pr_debug("GPIO-%d: chip request fail, %d\n", | ||
923 | chip->base + gpio, status); | ||
924 | /* and it's not available to anyone else ... | ||
925 | * gpio_request() is the fully clean solution. | ||
926 | */ | ||
927 | goto lose; | ||
928 | } | ||
929 | } | ||
930 | |||
880 | status = chip->direction_input(chip, gpio); | 931 | status = chip->direction_input(chip, gpio); |
881 | if (status == 0) | 932 | if (status == 0) |
882 | clear_bit(FLAG_IS_OUT, &desc->flags); | 933 | clear_bit(FLAG_IS_OUT, &desc->flags); |
934 | lose: | ||
883 | return status; | 935 | return status; |
884 | fail: | 936 | fail: |
885 | spin_unlock_irqrestore(&gpio_lock, flags); | 937 | spin_unlock_irqrestore(&gpio_lock, flags); |
@@ -907,7 +959,9 @@ int gpio_direction_output(unsigned gpio, int value) | |||
907 | gpio -= chip->base; | 959 | gpio -= chip->base; |
908 | if (gpio >= chip->ngpio) | 960 | if (gpio >= chip->ngpio) |
909 | goto fail; | 961 | goto fail; |
910 | gpio_ensure_requested(desc); | 962 | status = gpio_ensure_requested(desc, gpio); |
963 | if (status < 0) | ||
964 | goto fail; | ||
911 | 965 | ||
912 | /* now we know the gpio is valid and chip won't vanish */ | 966 | /* now we know the gpio is valid and chip won't vanish */ |
913 | 967 | ||
@@ -915,9 +969,22 @@ int gpio_direction_output(unsigned gpio, int value) | |||
915 | 969 | ||
916 | might_sleep_if(extra_checks && chip->can_sleep); | 970 | might_sleep_if(extra_checks && chip->can_sleep); |
917 | 971 | ||
972 | if (status) { | ||
973 | status = chip->request(chip, gpio); | ||
974 | if (status < 0) { | ||
975 | pr_debug("GPIO-%d: chip request fail, %d\n", | ||
976 | chip->base + gpio, status); | ||
977 | /* and it's not available to anyone else ... | ||
978 | * gpio_request() is the fully clean solution. | ||
979 | */ | ||
980 | goto lose; | ||
981 | } | ||
982 | } | ||
983 | |||
918 | status = chip->direction_output(chip, gpio, value); | 984 | status = chip->direction_output(chip, gpio, value); |
919 | if (status == 0) | 985 | if (status == 0) |
920 | set_bit(FLAG_IS_OUT, &desc->flags); | 986 | set_bit(FLAG_IS_OUT, &desc->flags); |
987 | lose: | ||
921 | return status; | 988 | return status; |
922 | fail: | 989 | fail: |
923 | spin_unlock_irqrestore(&gpio_lock, flags); | 990 | spin_unlock_irqrestore(&gpio_lock, flags); |
@@ -1008,6 +1075,24 @@ int __gpio_cansleep(unsigned gpio) | |||
1008 | } | 1075 | } |
1009 | EXPORT_SYMBOL_GPL(__gpio_cansleep); | 1076 | EXPORT_SYMBOL_GPL(__gpio_cansleep); |
1010 | 1077 | ||
1078 | /** | ||
1079 | * __gpio_to_irq() - return the IRQ corresponding to a GPIO | ||
1080 | * @gpio: gpio whose IRQ will be returned (already requested) | ||
1081 | * Context: any | ||
1082 | * | ||
1083 | * This is used directly or indirectly to implement gpio_to_irq(). | ||
1084 | * It returns the number of the IRQ signaled by this (input) GPIO, | ||
1085 | * or a negative errno. | ||
1086 | */ | ||
1087 | int __gpio_to_irq(unsigned gpio) | ||
1088 | { | ||
1089 | struct gpio_chip *chip; | ||
1090 | |||
1091 | chip = gpio_to_chip(gpio); | ||
1092 | return chip->to_irq ? chip->to_irq(chip, gpio - chip->base) : -ENXIO; | ||
1093 | } | ||
1094 | EXPORT_SYMBOL_GPL(__gpio_to_irq); | ||
1095 | |||
1011 | 1096 | ||
1012 | 1097 | ||
1013 | /* There's no value in making it easy to inline GPIO calls that may sleep. | 1098 | /* There's no value in making it easy to inline GPIO calls that may sleep. |
diff --git a/drivers/gpio/max7301.c b/drivers/gpio/max7301.c index 39c795ad8312..8b24d784db93 100644 --- a/drivers/gpio/max7301.c +++ b/drivers/gpio/max7301.c | |||
@@ -255,10 +255,6 @@ static int __devinit max7301_probe(struct spi_device *spi) | |||
255 | ts->chip.dev = &spi->dev; | 255 | ts->chip.dev = &spi->dev; |
256 | ts->chip.owner = THIS_MODULE; | 256 | ts->chip.owner = THIS_MODULE; |
257 | 257 | ||
258 | ret = gpiochip_add(&ts->chip); | ||
259 | if (ret) | ||
260 | goto exit_destroy; | ||
261 | |||
262 | /* | 258 | /* |
263 | * tristate all pins in hardware and cache the | 259 | * tristate all pins in hardware and cache the |
264 | * register values for later use. | 260 | * register values for later use. |
@@ -269,17 +265,19 @@ static int __devinit max7301_probe(struct spi_device *spi) | |||
269 | max7301_write(spi, 0x08 + i, 0xAA); | 265 | max7301_write(spi, 0x08 + i, 0xAA); |
270 | ts->port_config[i] = 0xAA; | 266 | ts->port_config[i] = 0xAA; |
271 | for (j = 0; j < 4; j++) { | 267 | for (j = 0; j < 4; j++) { |
272 | int idx = ts->chip.base + (i - 1) * 4 + j; | 268 | int offset = (i - 1) * 4 + j; |
273 | ret = gpio_direction_input(idx); | 269 | ret = max7301_direction_input(&ts->chip, offset); |
274 | if (ret) | 270 | if (ret) |
275 | goto exit_remove; | 271 | goto exit_destroy; |
276 | gpio_free(idx); | ||
277 | } | 272 | } |
278 | } | 273 | } |
274 | |||
275 | ret = gpiochip_add(&ts->chip); | ||
276 | if (ret) | ||
277 | goto exit_destroy; | ||
278 | |||
279 | return ret; | 279 | return ret; |
280 | 280 | ||
281 | exit_remove: | ||
282 | gpiochip_remove(&ts->chip); | ||
283 | exit_destroy: | 281 | exit_destroy: |
284 | dev_set_drvdata(&spi->dev, NULL); | 282 | dev_set_drvdata(&spi->dev, NULL); |
285 | mutex_destroy(&ts->lock); | 283 | mutex_destroy(&ts->lock); |
@@ -325,13 +323,15 @@ static int __init max7301_init(void) | |||
325 | { | 323 | { |
326 | return spi_register_driver(&max7301_driver); | 324 | return spi_register_driver(&max7301_driver); |
327 | } | 325 | } |
326 | /* register after spi postcore initcall and before | ||
327 | * subsys initcalls that may rely on these GPIOs | ||
328 | */ | ||
329 | subsys_initcall(max7301_init); | ||
328 | 330 | ||
329 | static void __exit max7301_exit(void) | 331 | static void __exit max7301_exit(void) |
330 | { | 332 | { |
331 | spi_unregister_driver(&max7301_driver); | 333 | spi_unregister_driver(&max7301_driver); |
332 | } | 334 | } |
333 | |||
334 | module_init(max7301_init); | ||
335 | module_exit(max7301_exit); | 335 | module_exit(max7301_exit); |
336 | 336 | ||
337 | MODULE_AUTHOR("Juergen Beisert"); | 337 | MODULE_AUTHOR("Juergen Beisert"); |
diff --git a/drivers/gpio/max732x.c b/drivers/gpio/max732x.c index b51c8135ca28..55ae9a41897a 100644 --- a/drivers/gpio/max732x.c +++ b/drivers/gpio/max732x.c | |||
@@ -372,7 +372,10 @@ static int __init max732x_init(void) | |||
372 | { | 372 | { |
373 | return i2c_add_driver(&max732x_driver); | 373 | return i2c_add_driver(&max732x_driver); |
374 | } | 374 | } |
375 | module_init(max732x_init); | 375 | /* register after i2c postcore initcall and before |
376 | * subsys initcalls that may rely on these GPIOs | ||
377 | */ | ||
378 | subsys_initcall(max732x_init); | ||
376 | 379 | ||
377 | static void __exit max732x_exit(void) | 380 | static void __exit max732x_exit(void) |
378 | { | 381 | { |
diff --git a/drivers/gpio/mcp23s08.c b/drivers/gpio/mcp23s08.c index 8a1b405fefda..89c1d222e9d1 100644 --- a/drivers/gpio/mcp23s08.c +++ b/drivers/gpio/mcp23s08.c | |||
@@ -419,7 +419,10 @@ static int __init mcp23s08_init(void) | |||
419 | { | 419 | { |
420 | return spi_register_driver(&mcp23s08_driver); | 420 | return spi_register_driver(&mcp23s08_driver); |
421 | } | 421 | } |
422 | module_init(mcp23s08_init); | 422 | /* register after spi postcore initcall and before |
423 | * subsys initcalls that may rely on these GPIOs | ||
424 | */ | ||
425 | subsys_initcall(mcp23s08_init); | ||
423 | 426 | ||
424 | static void __exit mcp23s08_exit(void) | 427 | static void __exit mcp23s08_exit(void) |
425 | { | 428 | { |
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c index cc8468692ae0..9ceeb89f1325 100644 --- a/drivers/gpio/pca953x.c +++ b/drivers/gpio/pca953x.c | |||
@@ -289,7 +289,10 @@ static int __init pca953x_init(void) | |||
289 | { | 289 | { |
290 | return i2c_add_driver(&pca953x_driver); | 290 | return i2c_add_driver(&pca953x_driver); |
291 | } | 291 | } |
292 | module_init(pca953x_init); | 292 | /* register after i2c postcore initcall and before |
293 | * subsys initcalls that may rely on these GPIOs | ||
294 | */ | ||
295 | subsys_initcall(pca953x_init); | ||
293 | 296 | ||
294 | static void __exit pca953x_exit(void) | 297 | static void __exit pca953x_exit(void) |
295 | { | 298 | { |
diff --git a/drivers/gpio/pcf857x.c b/drivers/gpio/pcf857x.c index fc9c6ae739ee..4bc2070dd4a1 100644 --- a/drivers/gpio/pcf857x.c +++ b/drivers/gpio/pcf857x.c | |||
@@ -351,7 +351,10 @@ static int __init pcf857x_init(void) | |||
351 | { | 351 | { |
352 | return i2c_add_driver(&pcf857x_driver); | 352 | return i2c_add_driver(&pcf857x_driver); |
353 | } | 353 | } |
354 | module_init(pcf857x_init); | 354 | /* register after i2c postcore initcall and before |
355 | * subsys initcalls that may rely on these GPIOs | ||
356 | */ | ||
357 | subsys_initcall(pcf857x_init); | ||
355 | 358 | ||
356 | static void __exit pcf857x_exit(void) | 359 | static void __exit pcf857x_exit(void) |
357 | { | 360 | { |
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 88974342933c..9ac4720e647b 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
@@ -517,7 +517,7 @@ static int i915_dispatch_flip(struct drm_device * dev) | |||
517 | RING_LOCALS; | 517 | RING_LOCALS; |
518 | 518 | ||
519 | DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n", | 519 | DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n", |
520 | __FUNCTION__, | 520 | __func__, |
521 | dev_priv->current_page, | 521 | dev_priv->current_page, |
522 | dev_priv->sarea_priv->pf_current_page); | 522 | dev_priv->sarea_priv->pf_current_page); |
523 | 523 | ||
@@ -642,7 +642,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, | |||
642 | static int i915_flip_bufs(struct drm_device *dev, void *data, | 642 | static int i915_flip_bufs(struct drm_device *dev, void *data, |
643 | struct drm_file *file_priv) | 643 | struct drm_file *file_priv) |
644 | { | 644 | { |
645 | DRM_DEBUG("%s\n", __FUNCTION__); | 645 | DRM_DEBUG("%s\n", __func__); |
646 | 646 | ||
647 | LOCK_TEST_WITH_RETURN(dev, file_priv); | 647 | LOCK_TEST_WITH_RETURN(dev, file_priv); |
648 | 648 | ||
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index da64108de775..f5999a91614e 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
@@ -17,25 +17,6 @@ config HID | |||
17 | tristate "Generic HID support" | 17 | tristate "Generic HID support" |
18 | depends on INPUT | 18 | depends on INPUT |
19 | default y | 19 | default y |
20 | select HID_A4TECH if !EMBEDDED | ||
21 | select HID_APPLE if !EMBEDDED | ||
22 | select HID_BELKIN if !EMBEDDED | ||
23 | select HID_BRIGHT if !EMBEDDED | ||
24 | select HID_CHERRY if !EMBEDDED | ||
25 | select HID_CHICONY if !EMBEDDED | ||
26 | select HID_CYPRESS if !EMBEDDED | ||
27 | select HID_DELL if !EMBEDDED | ||
28 | select HID_EZKEY if !EMBEDDED | ||
29 | select HID_GYRATION if !EMBEDDED | ||
30 | select HID_LOGITECH if !EMBEDDED | ||
31 | select HID_MICROSOFT if !EMBEDDED | ||
32 | select HID_MONTEREY if !EMBEDDED | ||
33 | select HID_PANTHERLORD if !EMBEDDED | ||
34 | select HID_PETALYNX if !EMBEDDED | ||
35 | select HID_SAMSUNG if !EMBEDDED | ||
36 | select HID_SONY if !EMBEDDED | ||
37 | select HID_SUNPLUS if !EMBEDDED | ||
38 | |||
39 | ---help--- | 20 | ---help--- |
40 | A human interface device (HID) is a type of computer device that | 21 | A human interface device (HID) is a type of computer device that |
41 | interacts directly with and takes input from humans. The term "HID" | 22 | interacts directly with and takes input from humans. The term "HID" |
@@ -102,89 +83,86 @@ config HID_COMPAT | |||
102 | If unsure, say Y. | 83 | If unsure, say Y. |
103 | 84 | ||
104 | config HID_A4TECH | 85 | config HID_A4TECH |
105 | tristate "A4 tech" | 86 | tristate "A4 tech" if EMBEDDED |
106 | default m | ||
107 | depends on USB_HID | 87 | depends on USB_HID |
88 | default y | ||
108 | ---help--- | 89 | ---help--- |
109 | Support for A4 tech X5 and WOP-35 / Trust 450L mice. | 90 | Support for A4 tech X5 and WOP-35 / Trust 450L mice. |
110 | 91 | ||
111 | config HID_APPLE | 92 | config HID_APPLE |
112 | tristate "Apple" | 93 | tristate "Apple" if EMBEDDED |
113 | default m | ||
114 | depends on (USB_HID || BT_HIDP) | 94 | depends on (USB_HID || BT_HIDP) |
95 | default y | ||
115 | ---help--- | 96 | ---help--- |
116 | Support for some Apple devices which less or more break | 97 | Support for some Apple devices which less or more break |
117 | HID specification. | 98 | HID specification. |
118 | 99 | ||
119 | Say Y here if you want support for the special keys (Fn, Numlock) on | 100 | Say Y here if you want support for keyboards of Apple iBooks, PowerBooks, |
120 | Apple iBooks, PowerBooks, MacBooks, MacBook Pros and aluminum USB | 101 | MacBooks, MacBook Pros and Apple Aluminum. |
121 | keyboards. | ||
122 | |||
123 | If unsure, say M. | ||
124 | 102 | ||
125 | config HID_BELKIN | 103 | config HID_BELKIN |
126 | tristate "Belkin" | 104 | tristate "Belkin" if EMBEDDED |
127 | default m | ||
128 | depends on USB_HID | 105 | depends on USB_HID |
106 | default y | ||
129 | ---help--- | 107 | ---help--- |
130 | Support for Belkin Flip KVM and Wireless keyboard. | 108 | Support for Belkin Flip KVM and Wireless keyboard. |
131 | 109 | ||
132 | config HID_BRIGHT | 110 | config HID_BRIGHT |
133 | tristate "Bright" | 111 | tristate "Bright" if EMBEDDED |
134 | default m | ||
135 | depends on USB_HID | 112 | depends on USB_HID |
113 | default y | ||
136 | ---help--- | 114 | ---help--- |
137 | Support for Bright ABNT-2 keyboard. | 115 | Support for Bright ABNT-2 keyboard. |
138 | 116 | ||
139 | config HID_CHERRY | 117 | config HID_CHERRY |
140 | tristate "Cherry" | 118 | tristate "Cherry" if EMBEDDED |
141 | default m | ||
142 | depends on USB_HID | 119 | depends on USB_HID |
120 | default y | ||
143 | ---help--- | 121 | ---help--- |
144 | Support for Cherry Cymotion. | 122 | Support for Cherry Cymotion keyboard. |
145 | 123 | ||
146 | config HID_CHICONY | 124 | config HID_CHICONY |
147 | tristate "Chicony" | 125 | tristate "Chicony" if EMBEDDED |
148 | default m | ||
149 | depends on USB_HID | 126 | depends on USB_HID |
127 | default y | ||
150 | ---help--- | 128 | ---help--- |
151 | Support for Chicony Tactical pad. | 129 | Support for Chicony Tactical pad. |
152 | 130 | ||
153 | config HID_CYPRESS | 131 | config HID_CYPRESS |
154 | tristate "Cypress" | 132 | tristate "Cypress" if EMBEDDED |
155 | default m | ||
156 | depends on USB_HID | 133 | depends on USB_HID |
134 | default y | ||
157 | ---help--- | 135 | ---help--- |
158 | Support for Cypress mouse and barcodes. | 136 | Support for cypress mouse and barcode readers. |
159 | 137 | ||
160 | config HID_DELL | 138 | config HID_DELL |
161 | tristate "Dell" | 139 | tristate "Dell" if EMBEDDED |
162 | default m | ||
163 | depends on USB_HID | 140 | depends on USB_HID |
141 | default y | ||
164 | ---help--- | 142 | ---help--- |
165 | Support for Dell W7658. | 143 | Support for quirky Dell HID hardware that require |
144 | special LED handling (W7658 and SK8115 models) | ||
166 | 145 | ||
167 | config HID_EZKEY | 146 | config HID_EZKEY |
168 | tristate "Ezkey" | 147 | tristate "Ezkey" if EMBEDDED |
169 | default m | ||
170 | depends on USB_HID | 148 | depends on USB_HID |
149 | default y | ||
171 | ---help--- | 150 | ---help--- |
172 | Support for Ezkey mouse and barcodes. | 151 | Support for Ezkey BTC 8193 keyboard. |
173 | 152 | ||
174 | config HID_GYRATION | 153 | config HID_GYRATION |
175 | tristate "Gyration" | 154 | tristate "Gyration" if EMBEDDED |
176 | default m | ||
177 | depends on USB_HID | 155 | depends on USB_HID |
156 | default y | ||
178 | ---help--- | 157 | ---help--- |
179 | Support for Gyration remote. | 158 | Support for Gyration remote control. |
180 | 159 | ||
181 | config HID_LOGITECH | 160 | config HID_LOGITECH |
182 | tristate "Logitech" | 161 | tristate "Logitech" if EMBEDDED |
183 | default m | ||
184 | depends on USB_HID | 162 | depends on USB_HID |
163 | default y | ||
185 | ---help--- | 164 | ---help--- |
186 | Support for some Logitech devices which breaks less or more | 165 | Support for Logitech devices that are not fully compliant with HID standard. |
187 | HID specification. | ||
188 | 166 | ||
189 | config LOGITECH_FF | 167 | config LOGITECH_FF |
190 | bool "Logitech force feedback" | 168 | bool "Logitech force feedback" |
@@ -211,28 +189,26 @@ config LOGIRUMBLEPAD2_FF | |||
211 | Rumblepad 2 devices. | 189 | Rumblepad 2 devices. |
212 | 190 | ||
213 | config HID_MICROSOFT | 191 | config HID_MICROSOFT |
214 | tristate "Microsoft" | 192 | tristate "Microsoft" if EMBEDDED |
215 | default m | ||
216 | depends on USB_HID | 193 | depends on USB_HID |
194 | default y | ||
217 | ---help--- | 195 | ---help--- |
218 | Support for some Microsoft devices which breaks less or more | 196 | Support for Microsoft devices that are not fully compliant with HID standard. |
219 | HID specification. | ||
220 | 197 | ||
221 | config HID_MONTEREY | 198 | config HID_MONTEREY |
222 | tristate "Monterey" | 199 | tristate "Monterey" if EMBEDDED |
223 | default m | ||
224 | depends on USB_HID | 200 | depends on USB_HID |
201 | default y | ||
225 | ---help--- | 202 | ---help--- |
226 | Support for Monterey Genius KB29E. | 203 | Support for Monterey Genius KB29E. |
227 | 204 | ||
228 | config HID_PANTHERLORD | 205 | config HID_PANTHERLORD |
229 | tristate "Pantherlord devices support" | 206 | tristate "Pantherlord devices support" if EMBEDDED |
230 | default m | ||
231 | depends on USB_HID | 207 | depends on USB_HID |
208 | default y | ||
232 | ---help--- | 209 | ---help--- |
233 | Support for PantherLord/GreenAsia based device support. | 210 | Support for PantherLord/GreenAsia based device support. |
234 | 211 | ||
235 | |||
236 | config PANTHERLORD_FF | 212 | config PANTHERLORD_FF |
237 | bool "Pantherlord force feedback support" | 213 | bool "Pantherlord force feedback support" |
238 | depends on HID_PANTHERLORD | 214 | depends on HID_PANTHERLORD |
@@ -242,32 +218,32 @@ config PANTHERLORD_FF | |||
242 | or adapter and want to enable force feedback support for it. | 218 | or adapter and want to enable force feedback support for it. |
243 | 219 | ||
244 | config HID_PETALYNX | 220 | config HID_PETALYNX |
245 | tristate "Petalynx" | 221 | tristate "Petalynx" if EMBEDDED |
246 | default m | ||
247 | depends on USB_HID | 222 | depends on USB_HID |
223 | default y | ||
248 | ---help--- | 224 | ---help--- |
249 | Support for Petalynx Maxter remote. | 225 | Support for Petalynx Maxter remote control. |
250 | 226 | ||
251 | config HID_SAMSUNG | 227 | config HID_SAMSUNG |
252 | tristate "Samsung" | 228 | tristate "Samsung" if EMBEDDED |
253 | default m | ||
254 | depends on USB_HID | 229 | depends on USB_HID |
230 | default y | ||
255 | ---help--- | 231 | ---help--- |
256 | Support for Samsung IR remote. | 232 | Support for Samsung InfraRed remote control. |
257 | 233 | ||
258 | config HID_SONY | 234 | config HID_SONY |
259 | tristate "Sony" | 235 | tristate "Sony" if EMBEDDED |
260 | default m | ||
261 | depends on USB_HID | 236 | depends on USB_HID |
237 | default y | ||
262 | ---help--- | 238 | ---help--- |
263 | Support for Sony PS3 controller. | 239 | Support for Sony PS3 controller. |
264 | 240 | ||
265 | config HID_SUNPLUS | 241 | config HID_SUNPLUS |
266 | tristate "Sunplus" | 242 | tristate "Sunplus" if EMBEDDED |
267 | default m | ||
268 | depends on USB_HID | 243 | depends on USB_HID |
244 | default y | ||
269 | ---help--- | 245 | ---help--- |
270 | Support for Sunplus WDesktop input device. | 246 | Support for Sunplus wireless desktop. |
271 | 247 | ||
272 | config THRUSTMASTER_FF | 248 | config THRUSTMASTER_FF |
273 | tristate "ThrustMaster devices support" | 249 | tristate "ThrustMaster devices support" |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 8a7d9dbb4d07..721a36d97582 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -1518,6 +1518,8 @@ static const struct hid_device_id hid_ignore_list[] = { | |||
1518 | { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0003) }, | 1518 | { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0003) }, |
1519 | { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) }, | 1519 | { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) }, |
1520 | { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD) }, | 1520 | { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD) }, |
1521 | { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD2) }, | ||
1522 | { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD3) }, | ||
1521 | { HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY1) }, | 1523 | { HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY1) }, |
1522 | { HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY2) }, | 1524 | { HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY2) }, |
1523 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) }, | 1525 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) }, |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index aad9ed1b406e..d9a1ba920c23 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
@@ -354,6 +354,8 @@ | |||
354 | 354 | ||
355 | #define USB_VENDOR_ID_SOUNDGRAPH 0x15c2 | 355 | #define USB_VENDOR_ID_SOUNDGRAPH 0x15c2 |
356 | #define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD 0x0038 | 356 | #define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD 0x0038 |
357 | #define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD2 0x0036 | ||
358 | #define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD3 0x0034 | ||
357 | 359 | ||
358 | #define USB_VENDOR_ID_SUN 0x0430 | 360 | #define USB_VENDOR_ID_SUN 0x0430 |
359 | #define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab | 361 | #define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab |
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index e7eb7bf9ddec..608038d64f81 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c | |||
@@ -589,11 +589,16 @@ omap_i2c_probe(struct platform_device *pdev) | |||
589 | 589 | ||
590 | dev->dev = &pdev->dev; | 590 | dev->dev = &pdev->dev; |
591 | dev->irq = irq->start; | 591 | dev->irq = irq->start; |
592 | dev->base = (void __iomem *) IO_ADDRESS(mem->start); | 592 | dev->base = ioremap(mem->start, mem->end - mem->start + 1); |
593 | if (!dev->base) { | ||
594 | r = -ENOMEM; | ||
595 | goto err_free_mem; | ||
596 | } | ||
597 | |||
593 | platform_set_drvdata(pdev, dev); | 598 | platform_set_drvdata(pdev, dev); |
594 | 599 | ||
595 | if ((r = omap_i2c_get_clocks(dev)) != 0) | 600 | if ((r = omap_i2c_get_clocks(dev)) != 0) |
596 | goto err_free_mem; | 601 | goto err_iounmap; |
597 | 602 | ||
598 | omap_i2c_unidle(dev); | 603 | omap_i2c_unidle(dev); |
599 | 604 | ||
@@ -640,6 +645,8 @@ err_unuse_clocks: | |||
640 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); | 645 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); |
641 | omap_i2c_idle(dev); | 646 | omap_i2c_idle(dev); |
642 | omap_i2c_put_clocks(dev); | 647 | omap_i2c_put_clocks(dev); |
648 | err_iounmap: | ||
649 | iounmap(dev->base); | ||
643 | err_free_mem: | 650 | err_free_mem: |
644 | platform_set_drvdata(pdev, NULL); | 651 | platform_set_drvdata(pdev, NULL); |
645 | kfree(dev); | 652 | kfree(dev); |
@@ -661,6 +668,7 @@ omap_i2c_remove(struct platform_device *pdev) | |||
661 | i2c_del_adapter(&dev->adapter); | 668 | i2c_del_adapter(&dev->adapter); |
662 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); | 669 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); |
663 | omap_i2c_put_clocks(dev); | 670 | omap_i2c_put_clocks(dev); |
671 | iounmap(dev->base); | ||
664 | kfree(dev); | 672 | kfree(dev); |
665 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 673 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
666 | release_mem_region(mem->start, (mem->end - mem->start) + 1); | 674 | release_mem_region(mem->start, (mem->end - mem->start) + 1); |
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 6c6dd2facede..74a369a6116f 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | # Select HAVE_IDE if IDE is supported | 5 | # Select HAVE_IDE if IDE is supported |
6 | config HAVE_IDE | 6 | config HAVE_IDE |
7 | def_bool n | 7 | bool |
8 | 8 | ||
9 | menuconfig IDE | 9 | menuconfig IDE |
10 | tristate "ATA/ATAPI/MFM/RLL support" | 10 | tristate "ATA/ATAPI/MFM/RLL support" |
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index 078e4eed0894..2880eaae157a 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c | |||
@@ -231,6 +231,7 @@ static void gameport_find_driver(struct gameport *gameport) | |||
231 | enum gameport_event_type { | 231 | enum gameport_event_type { |
232 | GAMEPORT_REGISTER_PORT, | 232 | GAMEPORT_REGISTER_PORT, |
233 | GAMEPORT_REGISTER_DRIVER, | 233 | GAMEPORT_REGISTER_DRIVER, |
234 | GAMEPORT_ATTACH_DRIVER, | ||
234 | }; | 235 | }; |
235 | 236 | ||
236 | struct gameport_event { | 237 | struct gameport_event { |
@@ -245,11 +246,12 @@ static LIST_HEAD(gameport_event_list); | |||
245 | static DECLARE_WAIT_QUEUE_HEAD(gameport_wait); | 246 | static DECLARE_WAIT_QUEUE_HEAD(gameport_wait); |
246 | static struct task_struct *gameport_task; | 247 | static struct task_struct *gameport_task; |
247 | 248 | ||
248 | static void gameport_queue_event(void *object, struct module *owner, | 249 | static int gameport_queue_event(void *object, struct module *owner, |
249 | enum gameport_event_type event_type) | 250 | enum gameport_event_type event_type) |
250 | { | 251 | { |
251 | unsigned long flags; | 252 | unsigned long flags; |
252 | struct gameport_event *event; | 253 | struct gameport_event *event; |
254 | int retval = 0; | ||
253 | 255 | ||
254 | spin_lock_irqsave(&gameport_event_lock, flags); | 256 | spin_lock_irqsave(&gameport_event_lock, flags); |
255 | 257 | ||
@@ -268,24 +270,34 @@ static void gameport_queue_event(void *object, struct module *owner, | |||
268 | } | 270 | } |
269 | } | 271 | } |
270 | 272 | ||
271 | if ((event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC))) { | 273 | event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC); |
272 | if (!try_module_get(owner)) { | 274 | if (!event) { |
273 | printk(KERN_WARNING "gameport: Can't get module reference, dropping event %d\n", event_type); | 275 | printk(KERN_ERR |
274 | kfree(event); | 276 | "gameport: Not enough memory to queue event %d\n", |
275 | goto out; | 277 | event_type); |
276 | } | 278 | retval = -ENOMEM; |
277 | 279 | goto out; | |
278 | event->type = event_type; | 280 | } |
279 | event->object = object; | ||
280 | event->owner = owner; | ||
281 | 281 | ||
282 | list_add_tail(&event->node, &gameport_event_list); | 282 | if (!try_module_get(owner)) { |
283 | wake_up(&gameport_wait); | 283 | printk(KERN_WARNING |
284 | } else { | 284 | "gameport: Can't get module reference, dropping event %d\n", |
285 | printk(KERN_ERR "gameport: Not enough memory to queue event %d\n", event_type); | 285 | event_type); |
286 | kfree(event); | ||
287 | retval = -EINVAL; | ||
288 | goto out; | ||
286 | } | 289 | } |
290 | |||
291 | event->type = event_type; | ||
292 | event->object = object; | ||
293 | event->owner = owner; | ||
294 | |||
295 | list_add_tail(&event->node, &gameport_event_list); | ||
296 | wake_up(&gameport_wait); | ||
297 | |||
287 | out: | 298 | out: |
288 | spin_unlock_irqrestore(&gameport_event_lock, flags); | 299 | spin_unlock_irqrestore(&gameport_event_lock, flags); |
300 | return retval; | ||
289 | } | 301 | } |
290 | 302 | ||
291 | static void gameport_free_event(struct gameport_event *event) | 303 | static void gameport_free_event(struct gameport_event *event) |
@@ -378,9 +390,10 @@ static void gameport_handle_event(void) | |||
378 | } | 390 | } |
379 | 391 | ||
380 | /* | 392 | /* |
381 | * Remove all events that have been submitted for a given gameport port. | 393 | * Remove all events that have been submitted for a given object, |
394 | * be it a gameport port or a driver. | ||
382 | */ | 395 | */ |
383 | static void gameport_remove_pending_events(struct gameport *gameport) | 396 | static void gameport_remove_pending_events(void *object) |
384 | { | 397 | { |
385 | struct list_head *node, *next; | 398 | struct list_head *node, *next; |
386 | struct gameport_event *event; | 399 | struct gameport_event *event; |
@@ -390,7 +403,7 @@ static void gameport_remove_pending_events(struct gameport *gameport) | |||
390 | 403 | ||
391 | list_for_each_safe(node, next, &gameport_event_list) { | 404 | list_for_each_safe(node, next, &gameport_event_list) { |
392 | event = list_entry(node, struct gameport_event, node); | 405 | event = list_entry(node, struct gameport_event, node); |
393 | if (event->object == gameport) { | 406 | if (event->object == object) { |
394 | list_del_init(node); | 407 | list_del_init(node); |
395 | gameport_free_event(event); | 408 | gameport_free_event(event); |
396 | } | 409 | } |
@@ -705,10 +718,40 @@ static void gameport_add_driver(struct gameport_driver *drv) | |||
705 | drv->driver.name, error); | 718 | drv->driver.name, error); |
706 | } | 719 | } |
707 | 720 | ||
708 | void __gameport_register_driver(struct gameport_driver *drv, struct module *owner) | 721 | int __gameport_register_driver(struct gameport_driver *drv, struct module *owner, |
722 | const char *mod_name) | ||
709 | { | 723 | { |
724 | int error; | ||
725 | |||
710 | drv->driver.bus = &gameport_bus; | 726 | drv->driver.bus = &gameport_bus; |
711 | gameport_queue_event(drv, owner, GAMEPORT_REGISTER_DRIVER); | 727 | drv->driver.owner = owner; |
728 | drv->driver.mod_name = mod_name; | ||
729 | |||
730 | /* | ||
731 | * Temporarily disable automatic binding because probing | ||
732 | * takes long time and we are better off doing it in kgameportd | ||
733 | */ | ||
734 | drv->ignore = 1; | ||
735 | |||
736 | error = driver_register(&drv->driver); | ||
737 | if (error) { | ||
738 | printk(KERN_ERR | ||
739 | "gameport: driver_register() failed for %s, error: %d\n", | ||
740 | drv->driver.name, error); | ||
741 | return error; | ||
742 | } | ||
743 | |||
744 | /* | ||
745 | * Reset ignore flag and let kgameportd bind the driver to free ports | ||
746 | */ | ||
747 | drv->ignore = 0; | ||
748 | error = gameport_queue_event(drv, NULL, GAMEPORT_ATTACH_DRIVER); | ||
749 | if (error) { | ||
750 | driver_unregister(&drv->driver); | ||
751 | return error; | ||
752 | } | ||
753 | |||
754 | return 0; | ||
712 | } | 755 | } |
713 | 756 | ||
714 | void gameport_unregister_driver(struct gameport_driver *drv) | 757 | void gameport_unregister_driver(struct gameport_driver *drv) |
@@ -716,7 +759,9 @@ void gameport_unregister_driver(struct gameport_driver *drv) | |||
716 | struct gameport *gameport; | 759 | struct gameport *gameport; |
717 | 760 | ||
718 | mutex_lock(&gameport_mutex); | 761 | mutex_lock(&gameport_mutex); |
762 | |||
719 | drv->ignore = 1; /* so gameport_find_driver ignores it */ | 763 | drv->ignore = 1; /* so gameport_find_driver ignores it */ |
764 | gameport_remove_pending_events(drv); | ||
720 | 765 | ||
721 | start_over: | 766 | start_over: |
722 | list_for_each_entry(gameport, &gameport_list, node) { | 767 | list_for_each_entry(gameport, &gameport_list, node) { |
@@ -729,6 +774,7 @@ start_over: | |||
729 | } | 774 | } |
730 | 775 | ||
731 | driver_unregister(&drv->driver); | 776 | driver_unregister(&drv->driver); |
777 | |||
732 | mutex_unlock(&gameport_mutex); | 778 | mutex_unlock(&gameport_mutex); |
733 | } | 779 | } |
734 | 780 | ||
diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c index 92498d470b1f..6489f4010c4f 100644 --- a/drivers/input/joystick/a3d.c +++ b/drivers/input/joystick/a3d.c | |||
@@ -414,8 +414,7 @@ static struct gameport_driver a3d_drv = { | |||
414 | 414 | ||
415 | static int __init a3d_init(void) | 415 | static int __init a3d_init(void) |
416 | { | 416 | { |
417 | gameport_register_driver(&a3d_drv); | 417 | return gameport_register_driver(&a3d_drv); |
418 | return 0; | ||
419 | } | 418 | } |
420 | 419 | ||
421 | static void __exit a3d_exit(void) | 420 | static void __exit a3d_exit(void) |
diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c index d1ca8a14950f..89c4c084d4ad 100644 --- a/drivers/input/joystick/adi.c +++ b/drivers/input/joystick/adi.c | |||
@@ -572,8 +572,7 @@ static struct gameport_driver adi_drv = { | |||
572 | 572 | ||
573 | static int __init adi_init(void) | 573 | static int __init adi_init(void) |
574 | { | 574 | { |
575 | gameport_register_driver(&adi_drv); | 575 | return gameport_register_driver(&adi_drv); |
576 | return 0; | ||
577 | } | 576 | } |
578 | 577 | ||
579 | static void __exit adi_exit(void) | 578 | static void __exit adi_exit(void) |
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 708c5ae13b24..356b3a25efa2 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c | |||
@@ -761,9 +761,7 @@ static struct gameport_driver analog_drv = { | |||
761 | static int __init analog_init(void) | 761 | static int __init analog_init(void) |
762 | { | 762 | { |
763 | analog_parse_options(); | 763 | analog_parse_options(); |
764 | gameport_register_driver(&analog_drv); | 764 | return gameport_register_driver(&analog_drv); |
765 | |||
766 | return 0; | ||
767 | } | 765 | } |
768 | 766 | ||
769 | static void __exit analog_exit(void) | 767 | static void __exit analog_exit(void) |
diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c index 639b975a8ed7..3497b87c3d05 100644 --- a/drivers/input/joystick/cobra.c +++ b/drivers/input/joystick/cobra.c | |||
@@ -263,8 +263,7 @@ static struct gameport_driver cobra_drv = { | |||
263 | 263 | ||
264 | static int __init cobra_init(void) | 264 | static int __init cobra_init(void) |
265 | { | 265 | { |
266 | gameport_register_driver(&cobra_drv); | 266 | return gameport_register_driver(&cobra_drv); |
267 | return 0; | ||
268 | } | 267 | } |
269 | 268 | ||
270 | static void __exit cobra_exit(void) | 269 | static void __exit cobra_exit(void) |
diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c index cb6eef1f2d99..67c207f5b1a1 100644 --- a/drivers/input/joystick/gf2k.c +++ b/drivers/input/joystick/gf2k.c | |||
@@ -375,8 +375,7 @@ static struct gameport_driver gf2k_drv = { | |||
375 | 375 | ||
376 | static int __init gf2k_init(void) | 376 | static int __init gf2k_init(void) |
377 | { | 377 | { |
378 | gameport_register_driver(&gf2k_drv); | 378 | return gameport_register_driver(&gf2k_drv); |
379 | return 0; | ||
380 | } | 379 | } |
381 | 380 | ||
382 | static void __exit gf2k_exit(void) | 381 | static void __exit gf2k_exit(void) |
diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c index 684e07cfccc8..fc55899ba6c5 100644 --- a/drivers/input/joystick/grip.c +++ b/drivers/input/joystick/grip.c | |||
@@ -426,8 +426,7 @@ static struct gameport_driver grip_drv = { | |||
426 | 426 | ||
427 | static int __init grip_init(void) | 427 | static int __init grip_init(void) |
428 | { | 428 | { |
429 | gameport_register_driver(&grip_drv); | 429 | return gameport_register_driver(&grip_drv); |
430 | return 0; | ||
431 | } | 430 | } |
432 | 431 | ||
433 | static void __exit grip_exit(void) | 432 | static void __exit grip_exit(void) |
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c index 8279481b16e7..2d47baf47769 100644 --- a/drivers/input/joystick/grip_mp.c +++ b/drivers/input/joystick/grip_mp.c | |||
@@ -689,8 +689,7 @@ static struct gameport_driver grip_drv = { | |||
689 | 689 | ||
690 | static int __init grip_init(void) | 690 | static int __init grip_init(void) |
691 | { | 691 | { |
692 | gameport_register_driver(&grip_drv); | 692 | return gameport_register_driver(&grip_drv); |
693 | return 0; | ||
694 | } | 693 | } |
695 | 694 | ||
696 | static void __exit grip_exit(void) | 695 | static void __exit grip_exit(void) |
diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c index 25ec3fad9f27..4058d4b272fe 100644 --- a/drivers/input/joystick/guillemot.c +++ b/drivers/input/joystick/guillemot.c | |||
@@ -283,8 +283,7 @@ static struct gameport_driver guillemot_drv = { | |||
283 | 283 | ||
284 | static int __init guillemot_init(void) | 284 | static int __init guillemot_init(void) |
285 | { | 285 | { |
286 | gameport_register_driver(&guillemot_drv); | 286 | return gameport_register_driver(&guillemot_drv); |
287 | return 0; | ||
288 | } | 287 | } |
289 | 288 | ||
290 | static void __exit guillemot_exit(void) | 289 | static void __exit guillemot_exit(void) |
diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c index 8c3290b68205..2478289aeeea 100644 --- a/drivers/input/joystick/interact.c +++ b/drivers/input/joystick/interact.c | |||
@@ -317,8 +317,7 @@ static struct gameport_driver interact_drv = { | |||
317 | 317 | ||
318 | static int __init interact_init(void) | 318 | static int __init interact_init(void) |
319 | { | 319 | { |
320 | gameport_register_driver(&interact_drv); | 320 | return gameport_register_driver(&interact_drv); |
321 | return 0; | ||
322 | } | 321 | } |
323 | 322 | ||
324 | static void __exit interact_exit(void) | 323 | static void __exit interact_exit(void) |
diff --git a/drivers/input/joystick/joydump.c b/drivers/input/joystick/joydump.c index 2a1b82c8b31c..cd894a0564a2 100644 --- a/drivers/input/joystick/joydump.c +++ b/drivers/input/joystick/joydump.c | |||
@@ -161,8 +161,7 @@ static struct gameport_driver joydump_drv = { | |||
161 | 161 | ||
162 | static int __init joydump_init(void) | 162 | static int __init joydump_init(void) |
163 | { | 163 | { |
164 | gameport_register_driver(&joydump_drv); | 164 | return gameport_register_driver(&joydump_drv); |
165 | return 0; | ||
166 | } | 165 | } |
167 | 166 | ||
168 | static void __exit joydump_exit(void) | 167 | static void __exit joydump_exit(void) |
diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c index 7b4865fdee54..ca13a6bec33e 100644 --- a/drivers/input/joystick/sidewinder.c +++ b/drivers/input/joystick/sidewinder.c | |||
@@ -818,8 +818,7 @@ static struct gameport_driver sw_drv = { | |||
818 | 818 | ||
819 | static int __init sw_init(void) | 819 | static int __init sw_init(void) |
820 | { | 820 | { |
821 | gameport_register_driver(&sw_drv); | 821 | return gameport_register_driver(&sw_drv); |
822 | return 0; | ||
823 | } | 822 | } |
824 | 823 | ||
825 | static void __exit sw_exit(void) | 824 | static void __exit sw_exit(void) |
diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c index 60c37bcb938d..d6c609807115 100644 --- a/drivers/input/joystick/tmdc.c +++ b/drivers/input/joystick/tmdc.c | |||
@@ -438,8 +438,7 @@ static struct gameport_driver tmdc_drv = { | |||
438 | 438 | ||
439 | static int __init tmdc_init(void) | 439 | static int __init tmdc_init(void) |
440 | { | 440 | { |
441 | gameport_register_driver(&tmdc_drv); | 441 | return gameport_register_driver(&tmdc_drv); |
442 | return 0; | ||
443 | } | 442 | } |
444 | 443 | ||
445 | static void __exit tmdc_exit(void) | 444 | static void __exit tmdc_exit(void) |
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 6791be81eb29..839d1c9622f6 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c | |||
@@ -455,10 +455,10 @@ static void xpad_bulk_out(struct urb *urb) | |||
455 | case -ENOENT: | 455 | case -ENOENT: |
456 | case -ESHUTDOWN: | 456 | case -ESHUTDOWN: |
457 | /* this urb is terminated, clean up */ | 457 | /* this urb is terminated, clean up */ |
458 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | 458 | dbg("%s - urb shutting down with status: %d", __func__, urb->status); |
459 | break; | 459 | break; |
460 | default: | 460 | default: |
461 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | 461 | dbg("%s - nonzero urb status received: %d", __func__, urb->status); |
462 | } | 462 | } |
463 | } | 463 | } |
464 | 464 | ||
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index b1ce10f50bcf..22016ca15351 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
@@ -834,10 +834,10 @@ static void atkbd_disconnect(struct serio *serio) | |||
834 | } | 834 | } |
835 | 835 | ||
836 | /* | 836 | /* |
837 | * Most special keys (Fn+F?) on Dell Latitudes do not generate release | 837 | * Most special keys (Fn+F?) on Dell laptops do not generate release |
838 | * events so we have to do it ourselves. | 838 | * events so we have to do it ourselves. |
839 | */ | 839 | */ |
840 | static void atkbd_latitude_keymap_fixup(struct atkbd *atkbd) | 840 | static void atkbd_dell_laptop_keymap_fixup(struct atkbd *atkbd) |
841 | { | 841 | { |
842 | const unsigned int forced_release_keys[] = { | 842 | const unsigned int forced_release_keys[] = { |
843 | 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8f, 0x93, | 843 | 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8f, 0x93, |
@@ -1207,15 +1207,13 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun | |||
1207 | { | 1207 | { |
1208 | struct input_dev *old_dev, *new_dev; | 1208 | struct input_dev *old_dev, *new_dev; |
1209 | unsigned long value; | 1209 | unsigned long value; |
1210 | char *rest; | ||
1211 | int err; | 1210 | int err; |
1212 | unsigned char old_extra, old_set; | 1211 | unsigned char old_extra, old_set; |
1213 | 1212 | ||
1214 | if (!atkbd->write) | 1213 | if (!atkbd->write) |
1215 | return -EIO; | 1214 | return -EIO; |
1216 | 1215 | ||
1217 | value = simple_strtoul(buf, &rest, 10); | 1216 | if (strict_strtoul(buf, 10, &value) || value > 1) |
1218 | if (*rest || value > 1) | ||
1219 | return -EINVAL; | 1217 | return -EINVAL; |
1220 | 1218 | ||
1221 | if (atkbd->extra != value) { | 1219 | if (atkbd->extra != value) { |
@@ -1264,12 +1262,10 @@ static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t cou | |||
1264 | { | 1262 | { |
1265 | struct input_dev *old_dev, *new_dev; | 1263 | struct input_dev *old_dev, *new_dev; |
1266 | unsigned long value; | 1264 | unsigned long value; |
1267 | char *rest; | ||
1268 | int err; | 1265 | int err; |
1269 | unsigned char old_scroll; | 1266 | unsigned char old_scroll; |
1270 | 1267 | ||
1271 | value = simple_strtoul(buf, &rest, 10); | 1268 | if (strict_strtoul(buf, 10, &value) || value > 1) |
1272 | if (*rest || value > 1) | ||
1273 | return -EINVAL; | 1269 | return -EINVAL; |
1274 | 1270 | ||
1275 | if (atkbd->scroll != value) { | 1271 | if (atkbd->scroll != value) { |
@@ -1310,15 +1306,13 @@ static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count) | |||
1310 | { | 1306 | { |
1311 | struct input_dev *old_dev, *new_dev; | 1307 | struct input_dev *old_dev, *new_dev; |
1312 | unsigned long value; | 1308 | unsigned long value; |
1313 | char *rest; | ||
1314 | int err; | 1309 | int err; |
1315 | unsigned char old_set, old_extra; | 1310 | unsigned char old_set, old_extra; |
1316 | 1311 | ||
1317 | if (!atkbd->write) | 1312 | if (!atkbd->write) |
1318 | return -EIO; | 1313 | return -EIO; |
1319 | 1314 | ||
1320 | value = simple_strtoul(buf, &rest, 10); | 1315 | if (strict_strtoul(buf, 10, &value) || (value != 2 && value != 3)) |
1321 | if (*rest || (value != 2 && value != 3)) | ||
1322 | return -EINVAL; | 1316 | return -EINVAL; |
1323 | 1317 | ||
1324 | if (atkbd->set != value) { | 1318 | if (atkbd->set != value) { |
@@ -1361,15 +1355,13 @@ static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t | |||
1361 | { | 1355 | { |
1362 | struct input_dev *old_dev, *new_dev; | 1356 | struct input_dev *old_dev, *new_dev; |
1363 | unsigned long value; | 1357 | unsigned long value; |
1364 | char *rest; | ||
1365 | int err; | 1358 | int err; |
1366 | unsigned char old_softrepeat, old_softraw; | 1359 | unsigned char old_softrepeat, old_softraw; |
1367 | 1360 | ||
1368 | if (!atkbd->write) | 1361 | if (!atkbd->write) |
1369 | return -EIO; | 1362 | return -EIO; |
1370 | 1363 | ||
1371 | value = simple_strtoul(buf, &rest, 10); | 1364 | if (strict_strtoul(buf, 10, &value) || value > 1) |
1372 | if (*rest || value > 1) | ||
1373 | return -EINVAL; | 1365 | return -EINVAL; |
1374 | 1366 | ||
1375 | if (atkbd->softrepeat != value) { | 1367 | if (atkbd->softrepeat != value) { |
@@ -1413,12 +1405,10 @@ static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t co | |||
1413 | { | 1405 | { |
1414 | struct input_dev *old_dev, *new_dev; | 1406 | struct input_dev *old_dev, *new_dev; |
1415 | unsigned long value; | 1407 | unsigned long value; |
1416 | char *rest; | ||
1417 | int err; | 1408 | int err; |
1418 | unsigned char old_softraw; | 1409 | unsigned char old_softraw; |
1419 | 1410 | ||
1420 | value = simple_strtoul(buf, &rest, 10); | 1411 | if (strict_strtoul(buf, 10, &value) || value > 1) |
1421 | if (*rest || value > 1) | ||
1422 | return -EINVAL; | 1412 | return -EINVAL; |
1423 | 1413 | ||
1424 | if (atkbd->softraw != value) { | 1414 | if (atkbd->softraw != value) { |
@@ -1461,13 +1451,13 @@ static int __init atkbd_setup_fixup(const struct dmi_system_id *id) | |||
1461 | 1451 | ||
1462 | static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | 1452 | static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { |
1463 | { | 1453 | { |
1464 | .ident = "Dell Latitude series", | 1454 | .ident = "Dell Laptop", |
1465 | .matches = { | 1455 | .matches = { |
1466 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 1456 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
1467 | DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"), | 1457 | DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */ |
1468 | }, | 1458 | }, |
1469 | .callback = atkbd_setup_fixup, | 1459 | .callback = atkbd_setup_fixup, |
1470 | .driver_data = atkbd_latitude_keymap_fixup, | 1460 | .driver_data = atkbd_dell_laptop_keymap_fixup, |
1471 | }, | 1461 | }, |
1472 | { | 1462 | { |
1473 | .ident = "HP 2133", | 1463 | .ident = "HP 2133", |
diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index e348cfccc17a..19284016e0f4 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * | 8 | * |
9 | * | 9 | * |
10 | * Modified: | 10 | * Modified: |
11 | * Copyright 2007 Analog Devices Inc. | 11 | * Copyright 2007-2008 Analog Devices Inc. |
12 | * | 12 | * |
13 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | 13 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ |
14 | * | 14 | * |
@@ -81,6 +81,9 @@ struct bf54x_kpad { | |||
81 | unsigned short *keycode; | 81 | unsigned short *keycode; |
82 | struct timer_list timer; | 82 | struct timer_list timer; |
83 | unsigned int keyup_test_jiffies; | 83 | unsigned int keyup_test_jiffies; |
84 | unsigned short kpad_msel; | ||
85 | unsigned short kpad_prescale; | ||
86 | unsigned short kpad_ctl; | ||
84 | }; | 87 | }; |
85 | 88 | ||
86 | static inline int bfin_kpad_find_key(struct bf54x_kpad *bf54x_kpad, | 89 | static inline int bfin_kpad_find_key(struct bf54x_kpad *bf54x_kpad, |
@@ -360,6 +363,10 @@ static int bfin_kpad_suspend(struct platform_device *pdev, pm_message_t state) | |||
360 | { | 363 | { |
361 | struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); | 364 | struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); |
362 | 365 | ||
366 | bf54x_kpad->kpad_msel = bfin_read_KPAD_MSEL(); | ||
367 | bf54x_kpad->kpad_prescale = bfin_read_KPAD_PRESCALE(); | ||
368 | bf54x_kpad->kpad_ctl = bfin_read_KPAD_CTL(); | ||
369 | |||
363 | if (device_may_wakeup(&pdev->dev)) | 370 | if (device_may_wakeup(&pdev->dev)) |
364 | enable_irq_wake(bf54x_kpad->irq); | 371 | enable_irq_wake(bf54x_kpad->irq); |
365 | 372 | ||
@@ -370,6 +377,10 @@ static int bfin_kpad_resume(struct platform_device *pdev) | |||
370 | { | 377 | { |
371 | struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); | 378 | struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); |
372 | 379 | ||
380 | bfin_write_KPAD_MSEL(bf54x_kpad->kpad_msel); | ||
381 | bfin_write_KPAD_PRESCALE(bf54x_kpad->kpad_prescale); | ||
382 | bfin_write_KPAD_CTL(bf54x_kpad->kpad_ctl); | ||
383 | |||
373 | if (device_may_wakeup(&pdev->dev)) | 384 | if (device_may_wakeup(&pdev->dev)) |
374 | disable_irq_wake(bf54x_kpad->irq); | 385 | disable_irq_wake(bf54x_kpad->irq); |
375 | 386 | ||
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index ec96b369dd7a..05f3f43582c2 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c | |||
@@ -36,9 +36,10 @@ struct gpio_keys_drvdata { | |||
36 | struct gpio_button_data data[0]; | 36 | struct gpio_button_data data[0]; |
37 | }; | 37 | }; |
38 | 38 | ||
39 | static void gpio_keys_report_event(struct gpio_keys_button *button, | 39 | static void gpio_keys_report_event(struct gpio_button_data *bdata) |
40 | struct input_dev *input) | ||
41 | { | 40 | { |
41 | struct gpio_keys_button *button = bdata->button; | ||
42 | struct input_dev *input = bdata->input; | ||
42 | unsigned int type = button->type ?: EV_KEY; | 43 | unsigned int type = button->type ?: EV_KEY; |
43 | int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low; | 44 | int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low; |
44 | 45 | ||
@@ -50,34 +51,23 @@ static void gpio_check_button(unsigned long _data) | |||
50 | { | 51 | { |
51 | struct gpio_button_data *data = (struct gpio_button_data *)_data; | 52 | struct gpio_button_data *data = (struct gpio_button_data *)_data; |
52 | 53 | ||
53 | gpio_keys_report_event(data->button, data->input); | 54 | gpio_keys_report_event(data); |
54 | } | 55 | } |
55 | 56 | ||
56 | static irqreturn_t gpio_keys_isr(int irq, void *dev_id) | 57 | static irqreturn_t gpio_keys_isr(int irq, void *dev_id) |
57 | { | 58 | { |
58 | struct platform_device *pdev = dev_id; | 59 | struct gpio_button_data *bdata = dev_id; |
59 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | 60 | struct gpio_keys_button *button = bdata->button; |
60 | struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); | ||
61 | int i; | ||
62 | 61 | ||
63 | for (i = 0; i < pdata->nbuttons; i++) { | 62 | BUG_ON(irq != gpio_to_irq(button->gpio)); |
64 | struct gpio_keys_button *button = &pdata->buttons[i]; | ||
65 | 63 | ||
66 | if (irq == gpio_to_irq(button->gpio)) { | 64 | if (button->debounce_interval) |
67 | struct gpio_button_data *bdata = &ddata->data[i]; | 65 | mod_timer(&bdata->timer, |
68 | 66 | jiffies + msecs_to_jiffies(button->debounce_interval)); | |
69 | if (button->debounce_interval) | 67 | else |
70 | mod_timer(&bdata->timer, | 68 | gpio_keys_report_event(bdata); |
71 | jiffies + | ||
72 | msecs_to_jiffies(button->debounce_interval)); | ||
73 | else | ||
74 | gpio_keys_report_event(button, bdata->input); | ||
75 | |||
76 | return IRQ_HANDLED; | ||
77 | } | ||
78 | } | ||
79 | 69 | ||
80 | return IRQ_NONE; | 70 | return IRQ_HANDLED; |
81 | } | 71 | } |
82 | 72 | ||
83 | static int __devinit gpio_keys_probe(struct platform_device *pdev) | 73 | static int __devinit gpio_keys_probe(struct platform_device *pdev) |
@@ -151,7 +141,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
151 | IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_RISING | | 141 | IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_RISING | |
152 | IRQF_TRIGGER_FALLING, | 142 | IRQF_TRIGGER_FALLING, |
153 | button->desc ? button->desc : "gpio_keys", | 143 | button->desc ? button->desc : "gpio_keys", |
154 | pdev); | 144 | bdata); |
155 | if (error) { | 145 | if (error) { |
156 | pr_err("gpio-keys: Unable to claim irq %d; error %d\n", | 146 | pr_err("gpio-keys: Unable to claim irq %d; error %d\n", |
157 | irq, error); | 147 | irq, error); |
@@ -178,7 +168,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
178 | 168 | ||
179 | fail2: | 169 | fail2: |
180 | while (--i >= 0) { | 170 | while (--i >= 0) { |
181 | free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev); | 171 | free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); |
182 | if (pdata->buttons[i].debounce_interval) | 172 | if (pdata->buttons[i].debounce_interval) |
183 | del_timer_sync(&ddata->data[i].timer); | 173 | del_timer_sync(&ddata->data[i].timer); |
184 | gpio_free(pdata->buttons[i].gpio); | 174 | gpio_free(pdata->buttons[i].gpio); |
@@ -203,7 +193,7 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) | |||
203 | 193 | ||
204 | for (i = 0; i < pdata->nbuttons; i++) { | 194 | for (i = 0; i < pdata->nbuttons; i++) { |
205 | int irq = gpio_to_irq(pdata->buttons[i].gpio); | 195 | int irq = gpio_to_irq(pdata->buttons[i].gpio); |
206 | free_irq(irq, pdev); | 196 | free_irq(irq, &ddata->data[i]); |
207 | if (pdata->buttons[i].debounce_interval) | 197 | if (pdata->buttons[i].debounce_interval) |
208 | del_timer_sync(&ddata->data[i].timer); | 198 | del_timer_sync(&ddata->data[i].timer); |
209 | gpio_free(pdata->buttons[i].gpio); | 199 | gpio_free(pdata->buttons[i].gpio); |
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index dcea87a0bc56..69e674ecf19a 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c | |||
@@ -62,7 +62,7 @@ struct omap_kp { | |||
62 | unsigned int debounce; | 62 | unsigned int debounce; |
63 | }; | 63 | }; |
64 | 64 | ||
65 | DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0); | 65 | static DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0); |
66 | 66 | ||
67 | static int *keymap; | 67 | static int *keymap; |
68 | static unsigned int *row_gpios; | 68 | static unsigned int *row_gpios; |
@@ -72,12 +72,9 @@ static unsigned int *col_gpios; | |||
72 | static void set_col_gpio_val(struct omap_kp *omap_kp, u8 value) | 72 | static void set_col_gpio_val(struct omap_kp *omap_kp, u8 value) |
73 | { | 73 | { |
74 | int col; | 74 | int col; |
75 | for (col = 0; col < omap_kp->cols; col++) { | 75 | |
76 | if (value & (1 << col)) | 76 | for (col = 0; col < omap_kp->cols; col++) |
77 | omap_set_gpio_dataout(col_gpios[col], 1); | 77 | gpio_set_value(col_gpios[col], value & (1 << col)); |
78 | else | ||
79 | omap_set_gpio_dataout(col_gpios[col], 0); | ||
80 | } | ||
81 | } | 78 | } |
82 | 79 | ||
83 | static u8 get_row_gpio_val(struct omap_kp *omap_kp) | 80 | static u8 get_row_gpio_val(struct omap_kp *omap_kp) |
@@ -86,7 +83,7 @@ static u8 get_row_gpio_val(struct omap_kp *omap_kp) | |||
86 | u8 value = 0; | 83 | u8 value = 0; |
87 | 84 | ||
88 | for (row = 0; row < omap_kp->rows; row++) { | 85 | for (row = 0; row < omap_kp->rows; row++) { |
89 | if (omap_get_gpio_datain(row_gpios[row])) | 86 | if (gpio_get_value(row_gpios[row])) |
90 | value |= (1 << row); | 87 | value |= (1 << row); |
91 | } | 88 | } |
92 | return value; | 89 | return value; |
@@ -333,23 +330,23 @@ static int __init omap_kp_probe(struct platform_device *pdev) | |||
333 | if (cpu_is_omap24xx()) { | 330 | if (cpu_is_omap24xx()) { |
334 | /* Cols: outputs */ | 331 | /* Cols: outputs */ |
335 | for (col_idx = 0; col_idx < omap_kp->cols; col_idx++) { | 332 | for (col_idx = 0; col_idx < omap_kp->cols; col_idx++) { |
336 | if (omap_request_gpio(col_gpios[col_idx]) < 0) { | 333 | if (gpio_request(col_gpios[col_idx], "omap_kp_col") < 0) { |
337 | printk(KERN_ERR "Failed to request" | 334 | printk(KERN_ERR "Failed to request" |
338 | "GPIO%d for keypad\n", | 335 | "GPIO%d for keypad\n", |
339 | col_gpios[col_idx]); | 336 | col_gpios[col_idx]); |
340 | goto err1; | 337 | goto err1; |
341 | } | 338 | } |
342 | omap_set_gpio_direction(col_gpios[col_idx], 0); | 339 | gpio_direction_output(col_gpios[col_idx], 0); |
343 | } | 340 | } |
344 | /* Rows: inputs */ | 341 | /* Rows: inputs */ |
345 | for (row_idx = 0; row_idx < omap_kp->rows; row_idx++) { | 342 | for (row_idx = 0; row_idx < omap_kp->rows; row_idx++) { |
346 | if (omap_request_gpio(row_gpios[row_idx]) < 0) { | 343 | if (gpio_request(row_gpios[row_idx], "omap_kp_row") < 0) { |
347 | printk(KERN_ERR "Failed to request" | 344 | printk(KERN_ERR "Failed to request" |
348 | "GPIO%d for keypad\n", | 345 | "GPIO%d for keypad\n", |
349 | row_gpios[row_idx]); | 346 | row_gpios[row_idx]); |
350 | goto err2; | 347 | goto err2; |
351 | } | 348 | } |
352 | omap_set_gpio_direction(row_gpios[row_idx], 1); | 349 | gpio_direction_input(row_gpios[row_idx]); |
353 | } | 350 | } |
354 | } else { | 351 | } else { |
355 | col_idx = 0; | 352 | col_idx = 0; |
@@ -418,10 +415,10 @@ err3: | |||
418 | device_remove_file(&pdev->dev, &dev_attr_enable); | 415 | device_remove_file(&pdev->dev, &dev_attr_enable); |
419 | err2: | 416 | err2: |
420 | for (i = row_idx - 1; i >=0; i--) | 417 | for (i = row_idx - 1; i >=0; i--) |
421 | omap_free_gpio(row_gpios[i]); | 418 | gpio_free(row_gpios[i]); |
422 | err1: | 419 | err1: |
423 | for (i = col_idx - 1; i >=0; i--) | 420 | for (i = col_idx - 1; i >=0; i--) |
424 | omap_free_gpio(col_gpios[i]); | 421 | gpio_free(col_gpios[i]); |
425 | 422 | ||
426 | kfree(omap_kp); | 423 | kfree(omap_kp); |
427 | input_free_device(input_dev); | 424 | input_free_device(input_dev); |
@@ -438,9 +435,9 @@ static int omap_kp_remove(struct platform_device *pdev) | |||
438 | if (cpu_is_omap24xx()) { | 435 | if (cpu_is_omap24xx()) { |
439 | int i; | 436 | int i; |
440 | for (i = 0; i < omap_kp->cols; i++) | 437 | for (i = 0; i < omap_kp->cols; i++) |
441 | omap_free_gpio(col_gpios[i]); | 438 | gpio_free(col_gpios[i]); |
442 | for (i = 0; i < omap_kp->rows; i++) { | 439 | for (i = 0; i < omap_kp->rows; i++) { |
443 | omap_free_gpio(row_gpios[i]); | 440 | gpio_free(row_gpios[i]); |
444 | free_irq(OMAP_GPIO_IRQ(row_gpios[i]), 0); | 441 | free_irq(OMAP_GPIO_IRQ(row_gpios[i]), 0); |
445 | } | 442 | } |
446 | } else { | 443 | } else { |
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index e99b7882f382..199055db5082 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -180,6 +180,19 @@ config INPUT_YEALINK | |||
180 | To compile this driver as a module, choose M here: the module will be | 180 | To compile this driver as a module, choose M here: the module will be |
181 | called yealink. | 181 | called yealink. |
182 | 182 | ||
183 | config INPUT_CM109 | ||
184 | tristate "C-Media CM109 USB I/O Controller" | ||
185 | depends on EXPERIMENTAL | ||
186 | depends on USB_ARCH_HAS_HCD | ||
187 | select USB | ||
188 | help | ||
189 | Say Y here if you want to enable keyboard and buzzer functions of the | ||
190 | C-Media CM109 usb phones. The audio part is enabled by the generic | ||
191 | usb sound driver, so you might want to enable that as well. | ||
192 | |||
193 | To compile this driver as a module, choose M here: the module will be | ||
194 | called cm109. | ||
195 | |||
183 | config INPUT_UINPUT | 196 | config INPUT_UINPUT |
184 | tristate "User level driver support" | 197 | tristate "User level driver support" |
185 | help | 198 | help |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index f48009b52226..d7db2aeb8a98 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
@@ -16,6 +16,7 @@ obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o | |||
16 | obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o | 16 | obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o |
17 | obj-$(CONFIG_INPUT_POWERMATE) += powermate.o | 17 | obj-$(CONFIG_INPUT_POWERMATE) += powermate.o |
18 | obj-$(CONFIG_INPUT_YEALINK) += yealink.o | 18 | obj-$(CONFIG_INPUT_YEALINK) += yealink.o |
19 | obj-$(CONFIG_INPUT_CM109) += cm109.o | ||
19 | obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o | 20 | obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o |
20 | obj-$(CONFIG_INPUT_UINPUT) += uinput.o | 21 | obj-$(CONFIG_INPUT_UINPUT) += uinput.o |
21 | obj-$(CONFIG_INPUT_APANEL) += apanel.o | 22 | obj-$(CONFIG_INPUT_APANEL) += apanel.o |
diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index a7fabafbd94c..3c9988dc0e9f 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * ati_remote2 - ATI/Philips USB RF remote driver | 2 | * ati_remote2 - ATI/Philips USB RF remote driver |
3 | * | 3 | * |
4 | * Copyright (C) 2005 Ville Syrjala <syrjala@sci.fi> | 4 | * Copyright (C) 2005-2008 Ville Syrjala <syrjala@sci.fi> |
5 | * Copyright (C) 2007 Peter Stokes <linux@dadeos.freeserve.co.uk> | 5 | * Copyright (C) 2007-2008 Peter Stokes <linux@dadeos.co.uk> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 | 8 | * it under the terms of the GNU General Public License version 2 |
@@ -12,7 +12,7 @@ | |||
12 | #include <linux/usb/input.h> | 12 | #include <linux/usb/input.h> |
13 | 13 | ||
14 | #define DRIVER_DESC "ATI/Philips USB RF remote driver" | 14 | #define DRIVER_DESC "ATI/Philips USB RF remote driver" |
15 | #define DRIVER_VERSION "0.2" | 15 | #define DRIVER_VERSION "0.3" |
16 | 16 | ||
17 | MODULE_DESCRIPTION(DRIVER_DESC); | 17 | MODULE_DESCRIPTION(DRIVER_DESC); |
18 | MODULE_VERSION(DRIVER_VERSION); | 18 | MODULE_VERSION(DRIVER_VERSION); |
@@ -27,7 +27,7 @@ MODULE_LICENSE("GPL"); | |||
27 | * A remote's "channel" may be altered by pressing and holding the "PC" button for | 27 | * A remote's "channel" may be altered by pressing and holding the "PC" button for |
28 | * approximately 3 seconds, after which the button will slowly flash the count of the | 28 | * approximately 3 seconds, after which the button will slowly flash the count of the |
29 | * currently configured "channel", using the numeric keypad enter a number between 1 and | 29 | * currently configured "channel", using the numeric keypad enter a number between 1 and |
30 | * 16 and then the "PC" button again, the button will slowly flash the count of the | 30 | * 16 and then press the "PC" button again, the button will slowly flash the count of the |
31 | * newly configured "channel". | 31 | * newly configured "channel". |
32 | */ | 32 | */ |
33 | 33 | ||
@@ -45,9 +45,25 @@ static struct usb_device_id ati_remote2_id_table[] = { | |||
45 | }; | 45 | }; |
46 | MODULE_DEVICE_TABLE(usb, ati_remote2_id_table); | 46 | MODULE_DEVICE_TABLE(usb, ati_remote2_id_table); |
47 | 47 | ||
48 | static struct { | 48 | static DEFINE_MUTEX(ati_remote2_mutex); |
49 | int hw_code; | 49 | |
50 | int key_code; | 50 | enum { |
51 | ATI_REMOTE2_OPENED = 0x1, | ||
52 | ATI_REMOTE2_SUSPENDED = 0x2, | ||
53 | }; | ||
54 | |||
55 | enum { | ||
56 | ATI_REMOTE2_AUX1, | ||
57 | ATI_REMOTE2_AUX2, | ||
58 | ATI_REMOTE2_AUX3, | ||
59 | ATI_REMOTE2_AUX4, | ||
60 | ATI_REMOTE2_PC, | ||
61 | ATI_REMOTE2_MODES, | ||
62 | }; | ||
63 | |||
64 | static const struct { | ||
65 | u8 hw_code; | ||
66 | u16 keycode; | ||
51 | } ati_remote2_key_table[] = { | 67 | } ati_remote2_key_table[] = { |
52 | { 0x00, KEY_0 }, | 68 | { 0x00, KEY_0 }, |
53 | { 0x01, KEY_1 }, | 69 | { 0x01, KEY_1 }, |
@@ -73,6 +89,7 @@ static struct { | |||
73 | { 0x37, KEY_RECORD }, | 89 | { 0x37, KEY_RECORD }, |
74 | { 0x38, KEY_DVD }, | 90 | { 0x38, KEY_DVD }, |
75 | { 0x39, KEY_TV }, | 91 | { 0x39, KEY_TV }, |
92 | { 0x3f, KEY_PROG1 }, /* AUX1-AUX4 and PC */ | ||
76 | { 0x54, KEY_MENU }, | 93 | { 0x54, KEY_MENU }, |
77 | { 0x58, KEY_UP }, | 94 | { 0x58, KEY_UP }, |
78 | { 0x59, KEY_DOWN }, | 95 | { 0x59, KEY_DOWN }, |
@@ -91,15 +108,9 @@ static struct { | |||
91 | { 0xa9, BTN_LEFT }, | 108 | { 0xa9, BTN_LEFT }, |
92 | { 0xaa, BTN_RIGHT }, | 109 | { 0xaa, BTN_RIGHT }, |
93 | { 0xbe, KEY_QUESTION }, | 110 | { 0xbe, KEY_QUESTION }, |
94 | { 0xd5, KEY_FRONT }, | ||
95 | { 0xd0, KEY_EDIT }, | 111 | { 0xd0, KEY_EDIT }, |
112 | { 0xd5, KEY_FRONT }, | ||
96 | { 0xf9, KEY_INFO }, | 113 | { 0xf9, KEY_INFO }, |
97 | { (0x00 << 8) | 0x3f, KEY_PROG1 }, | ||
98 | { (0x01 << 8) | 0x3f, KEY_PROG2 }, | ||
99 | { (0x02 << 8) | 0x3f, KEY_PROG3 }, | ||
100 | { (0x03 << 8) | 0x3f, KEY_PROG4 }, | ||
101 | { (0x04 << 8) | 0x3f, KEY_PC }, | ||
102 | { 0, KEY_RESERVED } | ||
103 | }; | 114 | }; |
104 | 115 | ||
105 | struct ati_remote2 { | 116 | struct ati_remote2 { |
@@ -117,46 +128,106 @@ struct ati_remote2 { | |||
117 | 128 | ||
118 | char name[64]; | 129 | char name[64]; |
119 | char phys[64]; | 130 | char phys[64]; |
131 | |||
132 | /* Each mode (AUX1-AUX4 and PC) can have an independent keymap. */ | ||
133 | u16 keycode[ATI_REMOTE2_MODES][ARRAY_SIZE(ati_remote2_key_table)]; | ||
134 | |||
135 | unsigned int flags; | ||
120 | }; | 136 | }; |
121 | 137 | ||
122 | static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id); | 138 | static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id); |
123 | static void ati_remote2_disconnect(struct usb_interface *interface); | 139 | static void ati_remote2_disconnect(struct usb_interface *interface); |
140 | static int ati_remote2_suspend(struct usb_interface *interface, pm_message_t message); | ||
141 | static int ati_remote2_resume(struct usb_interface *interface); | ||
124 | 142 | ||
125 | static struct usb_driver ati_remote2_driver = { | 143 | static struct usb_driver ati_remote2_driver = { |
126 | .name = "ati_remote2", | 144 | .name = "ati_remote2", |
127 | .probe = ati_remote2_probe, | 145 | .probe = ati_remote2_probe, |
128 | .disconnect = ati_remote2_disconnect, | 146 | .disconnect = ati_remote2_disconnect, |
129 | .id_table = ati_remote2_id_table, | 147 | .id_table = ati_remote2_id_table, |
148 | .suspend = ati_remote2_suspend, | ||
149 | .resume = ati_remote2_resume, | ||
150 | .supports_autosuspend = 1, | ||
130 | }; | 151 | }; |
131 | 152 | ||
132 | static int ati_remote2_open(struct input_dev *idev) | 153 | static int ati_remote2_submit_urbs(struct ati_remote2 *ar2) |
133 | { | 154 | { |
134 | struct ati_remote2 *ar2 = input_get_drvdata(idev); | ||
135 | int r; | 155 | int r; |
136 | 156 | ||
137 | r = usb_submit_urb(ar2->urb[0], GFP_KERNEL); | 157 | r = usb_submit_urb(ar2->urb[0], GFP_KERNEL); |
138 | if (r) { | 158 | if (r) { |
139 | dev_err(&ar2->intf[0]->dev, | 159 | dev_err(&ar2->intf[0]->dev, |
140 | "%s: usb_submit_urb() = %d\n", __func__, r); | 160 | "%s(): usb_submit_urb() = %d\n", __func__, r); |
141 | return r; | 161 | return r; |
142 | } | 162 | } |
143 | r = usb_submit_urb(ar2->urb[1], GFP_KERNEL); | 163 | r = usb_submit_urb(ar2->urb[1], GFP_KERNEL); |
144 | if (r) { | 164 | if (r) { |
145 | usb_kill_urb(ar2->urb[0]); | 165 | usb_kill_urb(ar2->urb[0]); |
146 | dev_err(&ar2->intf[1]->dev, | 166 | dev_err(&ar2->intf[1]->dev, |
147 | "%s: usb_submit_urb() = %d\n", __func__, r); | 167 | "%s(): usb_submit_urb() = %d\n", __func__, r); |
148 | return r; | 168 | return r; |
149 | } | 169 | } |
150 | 170 | ||
151 | return 0; | 171 | return 0; |
152 | } | 172 | } |
153 | 173 | ||
174 | static void ati_remote2_kill_urbs(struct ati_remote2 *ar2) | ||
175 | { | ||
176 | usb_kill_urb(ar2->urb[1]); | ||
177 | usb_kill_urb(ar2->urb[0]); | ||
178 | } | ||
179 | |||
180 | static int ati_remote2_open(struct input_dev *idev) | ||
181 | { | ||
182 | struct ati_remote2 *ar2 = input_get_drvdata(idev); | ||
183 | int r; | ||
184 | |||
185 | dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__); | ||
186 | |||
187 | r = usb_autopm_get_interface(ar2->intf[0]); | ||
188 | if (r) { | ||
189 | dev_err(&ar2->intf[0]->dev, | ||
190 | "%s(): usb_autopm_get_interface() = %d\n", __func__, r); | ||
191 | goto fail1; | ||
192 | } | ||
193 | |||
194 | mutex_lock(&ati_remote2_mutex); | ||
195 | |||
196 | if (!(ar2->flags & ATI_REMOTE2_SUSPENDED)) { | ||
197 | r = ati_remote2_submit_urbs(ar2); | ||
198 | if (r) | ||
199 | goto fail2; | ||
200 | } | ||
201 | |||
202 | ar2->flags |= ATI_REMOTE2_OPENED; | ||
203 | |||
204 | mutex_unlock(&ati_remote2_mutex); | ||
205 | |||
206 | usb_autopm_put_interface(ar2->intf[0]); | ||
207 | |||
208 | return 0; | ||
209 | |||
210 | fail2: | ||
211 | mutex_unlock(&ati_remote2_mutex); | ||
212 | usb_autopm_put_interface(ar2->intf[0]); | ||
213 | fail1: | ||
214 | return r; | ||
215 | } | ||
216 | |||
154 | static void ati_remote2_close(struct input_dev *idev) | 217 | static void ati_remote2_close(struct input_dev *idev) |
155 | { | 218 | { |
156 | struct ati_remote2 *ar2 = input_get_drvdata(idev); | 219 | struct ati_remote2 *ar2 = input_get_drvdata(idev); |
157 | 220 | ||
158 | usb_kill_urb(ar2->urb[0]); | 221 | dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__); |
159 | usb_kill_urb(ar2->urb[1]); | 222 | |
223 | mutex_lock(&ati_remote2_mutex); | ||
224 | |||
225 | if (!(ar2->flags & ATI_REMOTE2_SUSPENDED)) | ||
226 | ati_remote2_kill_urbs(ar2); | ||
227 | |||
228 | ar2->flags &= ~ATI_REMOTE2_OPENED; | ||
229 | |||
230 | mutex_unlock(&ati_remote2_mutex); | ||
160 | } | 231 | } |
161 | 232 | ||
162 | static void ati_remote2_input_mouse(struct ati_remote2 *ar2) | 233 | static void ati_remote2_input_mouse(struct ati_remote2 *ar2) |
@@ -172,7 +243,7 @@ static void ati_remote2_input_mouse(struct ati_remote2 *ar2) | |||
172 | 243 | ||
173 | mode = data[0] & 0x0F; | 244 | mode = data[0] & 0x0F; |
174 | 245 | ||
175 | if (mode > 4) { | 246 | if (mode > ATI_REMOTE2_PC) { |
176 | dev_err(&ar2->intf[0]->dev, | 247 | dev_err(&ar2->intf[0]->dev, |
177 | "Unknown mode byte (%02x %02x %02x %02x)\n", | 248 | "Unknown mode byte (%02x %02x %02x %02x)\n", |
178 | data[3], data[2], data[1], data[0]); | 249 | data[3], data[2], data[1], data[0]); |
@@ -191,7 +262,7 @@ static int ati_remote2_lookup(unsigned int hw_code) | |||
191 | { | 262 | { |
192 | int i; | 263 | int i; |
193 | 264 | ||
194 | for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++) | 265 | for (i = 0; i < ARRAY_SIZE(ati_remote2_key_table); i++) |
195 | if (ati_remote2_key_table[i].hw_code == hw_code) | 266 | if (ati_remote2_key_table[i].hw_code == hw_code) |
196 | return i; | 267 | return i; |
197 | 268 | ||
@@ -211,7 +282,7 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2) | |||
211 | 282 | ||
212 | mode = data[0] & 0x0F; | 283 | mode = data[0] & 0x0F; |
213 | 284 | ||
214 | if (mode > 4) { | 285 | if (mode > ATI_REMOTE2_PC) { |
215 | dev_err(&ar2->intf[1]->dev, | 286 | dev_err(&ar2->intf[1]->dev, |
216 | "Unknown mode byte (%02x %02x %02x %02x)\n", | 287 | "Unknown mode byte (%02x %02x %02x %02x)\n", |
217 | data[3], data[2], data[1], data[0]); | 288 | data[3], data[2], data[1], data[0]); |
@@ -219,10 +290,6 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2) | |||
219 | } | 290 | } |
220 | 291 | ||
221 | hw_code = data[2]; | 292 | hw_code = data[2]; |
222 | /* | ||
223 | * Mode keys (AUX1-AUX4, PC) all generate the same code byte. | ||
224 | * Use the mode byte to figure out which one was pressed. | ||
225 | */ | ||
226 | if (hw_code == 0x3f) { | 293 | if (hw_code == 0x3f) { |
227 | /* | 294 | /* |
228 | * For some incomprehensible reason the mouse pad generates | 295 | * For some incomprehensible reason the mouse pad generates |
@@ -236,8 +303,6 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2) | |||
236 | 303 | ||
237 | if (data[1] == 0) | 304 | if (data[1] == 0) |
238 | ar2->mode = mode; | 305 | ar2->mode = mode; |
239 | |||
240 | hw_code |= mode << 8; | ||
241 | } | 306 | } |
242 | 307 | ||
243 | if (!((1 << mode) & mode_mask)) | 308 | if (!((1 << mode) & mode_mask)) |
@@ -260,8 +325,8 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2) | |||
260 | case 2: /* repeat */ | 325 | case 2: /* repeat */ |
261 | 326 | ||
262 | /* No repeat for mouse buttons. */ | 327 | /* No repeat for mouse buttons. */ |
263 | if (ati_remote2_key_table[index].key_code == BTN_LEFT || | 328 | if (ar2->keycode[mode][index] == BTN_LEFT || |
264 | ati_remote2_key_table[index].key_code == BTN_RIGHT) | 329 | ar2->keycode[mode][index] == BTN_RIGHT) |
265 | return; | 330 | return; |
266 | 331 | ||
267 | if (!time_after_eq(jiffies, ar2->jiffies)) | 332 | if (!time_after_eq(jiffies, ar2->jiffies)) |
@@ -276,7 +341,7 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2) | |||
276 | return; | 341 | return; |
277 | } | 342 | } |
278 | 343 | ||
279 | input_event(idev, EV_KEY, ati_remote2_key_table[index].key_code, data[1]); | 344 | input_event(idev, EV_KEY, ar2->keycode[mode][index], data[1]); |
280 | input_sync(idev); | 345 | input_sync(idev); |
281 | } | 346 | } |
282 | 347 | ||
@@ -287,6 +352,7 @@ static void ati_remote2_complete_mouse(struct urb *urb) | |||
287 | 352 | ||
288 | switch (urb->status) { | 353 | switch (urb->status) { |
289 | case 0: | 354 | case 0: |
355 | usb_mark_last_busy(ar2->udev); | ||
290 | ati_remote2_input_mouse(ar2); | 356 | ati_remote2_input_mouse(ar2); |
291 | break; | 357 | break; |
292 | case -ENOENT: | 358 | case -ENOENT: |
@@ -297,6 +363,7 @@ static void ati_remote2_complete_mouse(struct urb *urb) | |||
297 | "%s(): urb status = %d\n", __func__, urb->status); | 363 | "%s(): urb status = %d\n", __func__, urb->status); |
298 | return; | 364 | return; |
299 | default: | 365 | default: |
366 | usb_mark_last_busy(ar2->udev); | ||
300 | dev_err(&ar2->intf[0]->dev, | 367 | dev_err(&ar2->intf[0]->dev, |
301 | "%s(): urb status = %d\n", __func__, urb->status); | 368 | "%s(): urb status = %d\n", __func__, urb->status); |
302 | } | 369 | } |
@@ -314,6 +381,7 @@ static void ati_remote2_complete_key(struct urb *urb) | |||
314 | 381 | ||
315 | switch (urb->status) { | 382 | switch (urb->status) { |
316 | case 0: | 383 | case 0: |
384 | usb_mark_last_busy(ar2->udev); | ||
317 | ati_remote2_input_key(ar2); | 385 | ati_remote2_input_key(ar2); |
318 | break; | 386 | break; |
319 | case -ENOENT: | 387 | case -ENOENT: |
@@ -324,6 +392,7 @@ static void ati_remote2_complete_key(struct urb *urb) | |||
324 | "%s(): urb status = %d\n", __func__, urb->status); | 392 | "%s(): urb status = %d\n", __func__, urb->status); |
325 | return; | 393 | return; |
326 | default: | 394 | default: |
395 | usb_mark_last_busy(ar2->udev); | ||
327 | dev_err(&ar2->intf[1]->dev, | 396 | dev_err(&ar2->intf[1]->dev, |
328 | "%s(): urb status = %d\n", __func__, urb->status); | 397 | "%s(): urb status = %d\n", __func__, urb->status); |
329 | } | 398 | } |
@@ -334,10 +403,60 @@ static void ati_remote2_complete_key(struct urb *urb) | |||
334 | "%s(): usb_submit_urb() = %d\n", __func__, r); | 403 | "%s(): usb_submit_urb() = %d\n", __func__, r); |
335 | } | 404 | } |
336 | 405 | ||
406 | static int ati_remote2_getkeycode(struct input_dev *idev, | ||
407 | int scancode, int *keycode) | ||
408 | { | ||
409 | struct ati_remote2 *ar2 = input_get_drvdata(idev); | ||
410 | int index, mode; | ||
411 | |||
412 | mode = scancode >> 8; | ||
413 | if (mode > ATI_REMOTE2_PC || !((1 << mode) & mode_mask)) | ||
414 | return -EINVAL; | ||
415 | |||
416 | index = ati_remote2_lookup(scancode & 0xFF); | ||
417 | if (index < 0) | ||
418 | return -EINVAL; | ||
419 | |||
420 | *keycode = ar2->keycode[mode][index]; | ||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | static int ati_remote2_setkeycode(struct input_dev *idev, int scancode, int keycode) | ||
425 | { | ||
426 | struct ati_remote2 *ar2 = input_get_drvdata(idev); | ||
427 | int index, mode, old_keycode; | ||
428 | |||
429 | mode = scancode >> 8; | ||
430 | if (mode > ATI_REMOTE2_PC || !((1 << mode) & mode_mask)) | ||
431 | return -EINVAL; | ||
432 | |||
433 | index = ati_remote2_lookup(scancode & 0xFF); | ||
434 | if (index < 0) | ||
435 | return -EINVAL; | ||
436 | |||
437 | if (keycode < KEY_RESERVED || keycode > KEY_MAX) | ||
438 | return -EINVAL; | ||
439 | |||
440 | old_keycode = ar2->keycode[mode][index]; | ||
441 | ar2->keycode[mode][index] = keycode; | ||
442 | set_bit(keycode, idev->keybit); | ||
443 | |||
444 | for (mode = 0; mode < ATI_REMOTE2_MODES; mode++) { | ||
445 | for (index = 0; index < ARRAY_SIZE(ati_remote2_key_table); index++) { | ||
446 | if (ar2->keycode[mode][index] == old_keycode) | ||
447 | return 0; | ||
448 | } | ||
449 | } | ||
450 | |||
451 | clear_bit(old_keycode, idev->keybit); | ||
452 | |||
453 | return 0; | ||
454 | } | ||
455 | |||
337 | static int ati_remote2_input_init(struct ati_remote2 *ar2) | 456 | static int ati_remote2_input_init(struct ati_remote2 *ar2) |
338 | { | 457 | { |
339 | struct input_dev *idev; | 458 | struct input_dev *idev; |
340 | int i, retval; | 459 | int index, mode, retval; |
341 | 460 | ||
342 | idev = input_allocate_device(); | 461 | idev = input_allocate_device(); |
343 | if (!idev) | 462 | if (!idev) |
@@ -350,8 +469,26 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2) | |||
350 | idev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | | 469 | idev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | |
351 | BIT_MASK(BTN_RIGHT); | 470 | BIT_MASK(BTN_RIGHT); |
352 | idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); | 471 | idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); |
353 | for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++) | 472 | |
354 | set_bit(ati_remote2_key_table[i].key_code, idev->keybit); | 473 | for (mode = 0; mode < ATI_REMOTE2_MODES; mode++) { |
474 | for (index = 0; index < ARRAY_SIZE(ati_remote2_key_table); index++) { | ||
475 | ar2->keycode[mode][index] = ati_remote2_key_table[index].keycode; | ||
476 | set_bit(ar2->keycode[mode][index], idev->keybit); | ||
477 | } | ||
478 | } | ||
479 | |||
480 | /* AUX1-AUX4 and PC generate the same scancode. */ | ||
481 | index = ati_remote2_lookup(0x3f); | ||
482 | ar2->keycode[ATI_REMOTE2_AUX1][index] = KEY_PROG1; | ||
483 | ar2->keycode[ATI_REMOTE2_AUX2][index] = KEY_PROG2; | ||
484 | ar2->keycode[ATI_REMOTE2_AUX3][index] = KEY_PROG3; | ||
485 | ar2->keycode[ATI_REMOTE2_AUX4][index] = KEY_PROG4; | ||
486 | ar2->keycode[ATI_REMOTE2_PC][index] = KEY_PC; | ||
487 | set_bit(KEY_PROG1, idev->keybit); | ||
488 | set_bit(KEY_PROG2, idev->keybit); | ||
489 | set_bit(KEY_PROG3, idev->keybit); | ||
490 | set_bit(KEY_PROG4, idev->keybit); | ||
491 | set_bit(KEY_PC, idev->keybit); | ||
355 | 492 | ||
356 | idev->rep[REP_DELAY] = 250; | 493 | idev->rep[REP_DELAY] = 250; |
357 | idev->rep[REP_PERIOD] = 33; | 494 | idev->rep[REP_PERIOD] = 33; |
@@ -359,6 +496,9 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2) | |||
359 | idev->open = ati_remote2_open; | 496 | idev->open = ati_remote2_open; |
360 | idev->close = ati_remote2_close; | 497 | idev->close = ati_remote2_close; |
361 | 498 | ||
499 | idev->getkeycode = ati_remote2_getkeycode; | ||
500 | idev->setkeycode = ati_remote2_setkeycode; | ||
501 | |||
362 | idev->name = ar2->name; | 502 | idev->name = ar2->name; |
363 | idev->phys = ar2->phys; | 503 | idev->phys = ar2->phys; |
364 | 504 | ||
@@ -490,6 +630,8 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d | |||
490 | 630 | ||
491 | usb_set_intfdata(interface, ar2); | 631 | usb_set_intfdata(interface, ar2); |
492 | 632 | ||
633 | interface->needs_remote_wakeup = 1; | ||
634 | |||
493 | return 0; | 635 | return 0; |
494 | 636 | ||
495 | fail2: | 637 | fail2: |
@@ -522,6 +664,57 @@ static void ati_remote2_disconnect(struct usb_interface *interface) | |||
522 | kfree(ar2); | 664 | kfree(ar2); |
523 | } | 665 | } |
524 | 666 | ||
667 | static int ati_remote2_suspend(struct usb_interface *interface, | ||
668 | pm_message_t message) | ||
669 | { | ||
670 | struct ati_remote2 *ar2; | ||
671 | struct usb_host_interface *alt = interface->cur_altsetting; | ||
672 | |||
673 | if (alt->desc.bInterfaceNumber) | ||
674 | return 0; | ||
675 | |||
676 | ar2 = usb_get_intfdata(interface); | ||
677 | |||
678 | dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__); | ||
679 | |||
680 | mutex_lock(&ati_remote2_mutex); | ||
681 | |||
682 | if (ar2->flags & ATI_REMOTE2_OPENED) | ||
683 | ati_remote2_kill_urbs(ar2); | ||
684 | |||
685 | ar2->flags |= ATI_REMOTE2_SUSPENDED; | ||
686 | |||
687 | mutex_unlock(&ati_remote2_mutex); | ||
688 | |||
689 | return 0; | ||
690 | } | ||
691 | |||
692 | static int ati_remote2_resume(struct usb_interface *interface) | ||
693 | { | ||
694 | struct ati_remote2 *ar2; | ||
695 | struct usb_host_interface *alt = interface->cur_altsetting; | ||
696 | int r = 0; | ||
697 | |||
698 | if (alt->desc.bInterfaceNumber) | ||
699 | return 0; | ||
700 | |||
701 | ar2 = usb_get_intfdata(interface); | ||
702 | |||
703 | dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__); | ||
704 | |||
705 | mutex_lock(&ati_remote2_mutex); | ||
706 | |||
707 | if (ar2->flags & ATI_REMOTE2_OPENED) | ||
708 | r = ati_remote2_submit_urbs(ar2); | ||
709 | |||
710 | if (!r) | ||
711 | ar2->flags &= ~ATI_REMOTE2_SUSPENDED; | ||
712 | |||
713 | mutex_unlock(&ati_remote2_mutex); | ||
714 | |||
715 | return r; | ||
716 | } | ||
717 | |||
525 | static int __init ati_remote2_init(void) | 718 | static int __init ati_remote2_init(void) |
526 | { | 719 | { |
527 | int r; | 720 | int r; |
diff --git a/drivers/input/misc/cm109.c b/drivers/input/misc/cm109.c new file mode 100644 index 000000000000..bce160f4349b --- /dev/null +++ b/drivers/input/misc/cm109.c | |||
@@ -0,0 +1,882 @@ | |||
1 | /* | ||
2 | * Driver for the VoIP USB phones with CM109 chipsets. | ||
3 | * | ||
4 | * Copyright (C) 2007 - 2008 Alfred E. Heggestad <aeh@db.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | * Tested devices: | ||
13 | * - Komunikate KIP1000 | ||
14 | * - Genius G-talk | ||
15 | * - Allied-Telesis Corega USBPH01 | ||
16 | * - ... | ||
17 | * | ||
18 | * This driver is based on the yealink.c driver | ||
19 | * | ||
20 | * Thanks to: | ||
21 | * - Authors of yealink.c | ||
22 | * - Thomas Reitmayr | ||
23 | * - Oliver Neukum for good review comments and code | ||
24 | * - Shaun Jackman <sjackman@gmail.com> for Genius G-talk keymap | ||
25 | * - Dmitry Torokhov for valuable input and review | ||
26 | * | ||
27 | * Todo: | ||
28 | * - Read/write EEPROM | ||
29 | */ | ||
30 | |||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/slab.h> | ||
34 | #include <linux/module.h> | ||
35 | #include <linux/moduleparam.h> | ||
36 | #include <linux/rwsem.h> | ||
37 | #include <linux/usb/input.h> | ||
38 | |||
39 | #define DRIVER_VERSION "20080805" | ||
40 | #define DRIVER_AUTHOR "Alfred E. Heggestad" | ||
41 | #define DRIVER_DESC "CM109 phone driver" | ||
42 | |||
43 | static char *phone = "kip1000"; | ||
44 | module_param(phone, charp, S_IRUSR); | ||
45 | MODULE_PARM_DESC(phone, "Phone name {kip1000, gtalk, usbph01}"); | ||
46 | |||
47 | enum { | ||
48 | /* HID Registers */ | ||
49 | HID_IR0 = 0x00, /* Record/Playback-mute button, Volume up/down */ | ||
50 | HID_IR1 = 0x01, /* GPI, generic registers or EEPROM_DATA0 */ | ||
51 | HID_IR2 = 0x02, /* Generic registers or EEPROM_DATA1 */ | ||
52 | HID_IR3 = 0x03, /* Generic registers or EEPROM_CTRL */ | ||
53 | HID_OR0 = 0x00, /* Mapping control, buzzer, SPDIF (offset 0x04) */ | ||
54 | HID_OR1 = 0x01, /* GPO - General Purpose Output */ | ||
55 | HID_OR2 = 0x02, /* Set GPIO to input/output mode */ | ||
56 | HID_OR3 = 0x03, /* SPDIF status channel or EEPROM_CTRL */ | ||
57 | |||
58 | /* HID_IR0 */ | ||
59 | RECORD_MUTE = 1 << 3, | ||
60 | PLAYBACK_MUTE = 1 << 2, | ||
61 | VOLUME_DOWN = 1 << 1, | ||
62 | VOLUME_UP = 1 << 0, | ||
63 | |||
64 | /* HID_OR0 */ | ||
65 | /* bits 7-6 | ||
66 | 0: HID_OR1-2 are used for GPO; HID_OR0, 3 are used for buzzer | ||
67 | and SPDIF | ||
68 | 1: HID_OR0-3 are used as generic HID registers | ||
69 | 2: Values written to HID_OR0-3 are also mapped to MCU_CTRL, | ||
70 | EEPROM_DATA0-1, EEPROM_CTRL (see Note) | ||
71 | 3: Reserved | ||
72 | */ | ||
73 | HID_OR_GPO_BUZ_SPDIF = 0 << 6, | ||
74 | HID_OR_GENERIC_HID_REG = 1 << 6, | ||
75 | HID_OR_MAP_MCU_EEPROM = 2 << 6, | ||
76 | |||
77 | BUZZER_ON = 1 << 5, | ||
78 | |||
79 | /* up to 256 normal keys, up to 16 special keys */ | ||
80 | KEYMAP_SIZE = 256 + 16, | ||
81 | }; | ||
82 | |||
83 | /* CM109 protocol packet */ | ||
84 | struct cm109_ctl_packet { | ||
85 | u8 byte[4]; | ||
86 | } __attribute__ ((packed)); | ||
87 | |||
88 | enum { USB_PKT_LEN = sizeof(struct cm109_ctl_packet) }; | ||
89 | |||
90 | /* CM109 device structure */ | ||
91 | struct cm109_dev { | ||
92 | struct input_dev *idev; /* input device */ | ||
93 | struct usb_device *udev; /* usb device */ | ||
94 | struct usb_interface *intf; | ||
95 | |||
96 | /* irq input channel */ | ||
97 | struct cm109_ctl_packet *irq_data; | ||
98 | dma_addr_t irq_dma; | ||
99 | struct urb *urb_irq; | ||
100 | |||
101 | /* control output channel */ | ||
102 | struct cm109_ctl_packet *ctl_data; | ||
103 | dma_addr_t ctl_dma; | ||
104 | struct usb_ctrlrequest *ctl_req; | ||
105 | dma_addr_t ctl_req_dma; | ||
106 | struct urb *urb_ctl; | ||
107 | /* | ||
108 | * The 3 bitfields below are protected by ctl_submit_lock. | ||
109 | * They have to be separate since they are accessed from IRQ | ||
110 | * context. | ||
111 | */ | ||
112 | unsigned irq_urb_pending:1; /* irq_urb is in flight */ | ||
113 | unsigned ctl_urb_pending:1; /* ctl_urb is in flight */ | ||
114 | unsigned buzzer_pending:1; /* need to issue buzz command */ | ||
115 | spinlock_t ctl_submit_lock; | ||
116 | |||
117 | unsigned char buzzer_state; /* on/off */ | ||
118 | |||
119 | /* flags */ | ||
120 | unsigned open:1; | ||
121 | unsigned resetting:1; | ||
122 | unsigned shutdown:1; | ||
123 | |||
124 | /* This mutex protects writes to the above flags */ | ||
125 | struct mutex pm_mutex; | ||
126 | |||
127 | unsigned short keymap[KEYMAP_SIZE]; | ||
128 | |||
129 | char phys[64]; /* physical device path */ | ||
130 | int key_code; /* last reported key */ | ||
131 | int keybit; /* 0=new scan 1,2,4,8=scan columns */ | ||
132 | u8 gpi; /* Cached value of GPI (high nibble) */ | ||
133 | }; | ||
134 | |||
135 | /****************************************************************************** | ||
136 | * CM109 key interface | ||
137 | *****************************************************************************/ | ||
138 | |||
139 | static unsigned short special_keymap(int code) | ||
140 | { | ||
141 | if (code > 0xff) { | ||
142 | switch (code - 0xff) { | ||
143 | case RECORD_MUTE: return KEY_MUTE; | ||
144 | case PLAYBACK_MUTE: return KEY_MUTE; | ||
145 | case VOLUME_DOWN: return KEY_VOLUMEDOWN; | ||
146 | case VOLUME_UP: return KEY_VOLUMEUP; | ||
147 | } | ||
148 | } | ||
149 | return KEY_RESERVED; | ||
150 | } | ||
151 | |||
152 | /* Map device buttons to internal key events. | ||
153 | * | ||
154 | * The "up" and "down" keys, are symbolised by arrows on the button. | ||
155 | * The "pickup" and "hangup" keys are symbolised by a green and red phone | ||
156 | * on the button. | ||
157 | |||
158 | Komunikate KIP1000 Keyboard Matrix | ||
159 | |||
160 | -> -- 1 -- 2 -- 3 --> GPI pin 4 (0x10) | ||
161 | | | | | | ||
162 | <- -- 4 -- 5 -- 6 --> GPI pin 5 (0x20) | ||
163 | | | | | | ||
164 | END - 7 -- 8 -- 9 --> GPI pin 6 (0x40) | ||
165 | | | | | | ||
166 | OK -- * -- 0 -- # --> GPI pin 7 (0x80) | ||
167 | | | | | | ||
168 | |||
169 | /|\ /|\ /|\ /|\ | ||
170 | | | | | | ||
171 | GPO | ||
172 | pin: 3 2 1 0 | ||
173 | 0x8 0x4 0x2 0x1 | ||
174 | |||
175 | */ | ||
176 | static unsigned short keymap_kip1000(int scancode) | ||
177 | { | ||
178 | switch (scancode) { /* phone key: */ | ||
179 | case 0x82: return KEY_NUMERIC_0; /* 0 */ | ||
180 | case 0x14: return KEY_NUMERIC_1; /* 1 */ | ||
181 | case 0x12: return KEY_NUMERIC_2; /* 2 */ | ||
182 | case 0x11: return KEY_NUMERIC_3; /* 3 */ | ||
183 | case 0x24: return KEY_NUMERIC_4; /* 4 */ | ||
184 | case 0x22: return KEY_NUMERIC_5; /* 5 */ | ||
185 | case 0x21: return KEY_NUMERIC_6; /* 6 */ | ||
186 | case 0x44: return KEY_NUMERIC_7; /* 7 */ | ||
187 | case 0x42: return KEY_NUMERIC_8; /* 8 */ | ||
188 | case 0x41: return KEY_NUMERIC_9; /* 9 */ | ||
189 | case 0x81: return KEY_NUMERIC_POUND; /* # */ | ||
190 | case 0x84: return KEY_NUMERIC_STAR; /* * */ | ||
191 | case 0x88: return KEY_ENTER; /* pickup */ | ||
192 | case 0x48: return KEY_ESC; /* hangup */ | ||
193 | case 0x28: return KEY_LEFT; /* IN */ | ||
194 | case 0x18: return KEY_RIGHT; /* OUT */ | ||
195 | default: return special_keymap(scancode); | ||
196 | } | ||
197 | } | ||
198 | |||
199 | /* | ||
200 | Contributed by Shaun Jackman <sjackman@gmail.com> | ||
201 | |||
202 | Genius G-Talk keyboard matrix | ||
203 | 0 1 2 3 | ||
204 | 4: 0 4 8 Talk | ||
205 | 5: 1 5 9 End | ||
206 | 6: 2 6 # Up | ||
207 | 7: 3 7 * Down | ||
208 | */ | ||
209 | static unsigned short keymap_gtalk(int scancode) | ||
210 | { | ||
211 | switch (scancode) { | ||
212 | case 0x11: return KEY_NUMERIC_0; | ||
213 | case 0x21: return KEY_NUMERIC_1; | ||
214 | case 0x41: return KEY_NUMERIC_2; | ||
215 | case 0x81: return KEY_NUMERIC_3; | ||
216 | case 0x12: return KEY_NUMERIC_4; | ||
217 | case 0x22: return KEY_NUMERIC_5; | ||
218 | case 0x42: return KEY_NUMERIC_6; | ||
219 | case 0x82: return KEY_NUMERIC_7; | ||
220 | case 0x14: return KEY_NUMERIC_8; | ||
221 | case 0x24: return KEY_NUMERIC_9; | ||
222 | case 0x44: return KEY_NUMERIC_POUND; /* # */ | ||
223 | case 0x84: return KEY_NUMERIC_STAR; /* * */ | ||
224 | case 0x18: return KEY_ENTER; /* Talk (green handset) */ | ||
225 | case 0x28: return KEY_ESC; /* End (red handset) */ | ||
226 | case 0x48: return KEY_UP; /* Menu up (rocker switch) */ | ||
227 | case 0x88: return KEY_DOWN; /* Menu down (rocker switch) */ | ||
228 | default: return special_keymap(scancode); | ||
229 | } | ||
230 | } | ||
231 | |||
232 | /* | ||
233 | * Keymap for Allied-Telesis Corega USBPH01 | ||
234 | * http://www.alliedtelesis-corega.com/2/1344/1437/1360/chprd.html | ||
235 | * | ||
236 | * Contributed by july@nat.bg | ||
237 | */ | ||
238 | static unsigned short keymap_usbph01(int scancode) | ||
239 | { | ||
240 | switch (scancode) { | ||
241 | case 0x11: return KEY_NUMERIC_0; /* 0 */ | ||
242 | case 0x21: return KEY_NUMERIC_1; /* 1 */ | ||
243 | case 0x41: return KEY_NUMERIC_2; /* 2 */ | ||
244 | case 0x81: return KEY_NUMERIC_3; /* 3 */ | ||
245 | case 0x12: return KEY_NUMERIC_4; /* 4 */ | ||
246 | case 0x22: return KEY_NUMERIC_5; /* 5 */ | ||
247 | case 0x42: return KEY_NUMERIC_6; /* 6 */ | ||
248 | case 0x82: return KEY_NUMERIC_7; /* 7 */ | ||
249 | case 0x14: return KEY_NUMERIC_8; /* 8 */ | ||
250 | case 0x24: return KEY_NUMERIC_9; /* 9 */ | ||
251 | case 0x44: return KEY_NUMERIC_POUND; /* # */ | ||
252 | case 0x84: return KEY_NUMERIC_STAR; /* * */ | ||
253 | case 0x18: return KEY_ENTER; /* pickup */ | ||
254 | case 0x28: return KEY_ESC; /* hangup */ | ||
255 | case 0x48: return KEY_LEFT; /* IN */ | ||
256 | case 0x88: return KEY_RIGHT; /* OUT */ | ||
257 | default: return special_keymap(scancode); | ||
258 | } | ||
259 | } | ||
260 | |||
261 | static unsigned short (*keymap)(int) = keymap_kip1000; | ||
262 | |||
263 | /* | ||
264 | * Completes a request by converting the data into events for the | ||
265 | * input subsystem. | ||
266 | */ | ||
267 | static void report_key(struct cm109_dev *dev, int key) | ||
268 | { | ||
269 | struct input_dev *idev = dev->idev; | ||
270 | |||
271 | if (dev->key_code >= 0) { | ||
272 | /* old key up */ | ||
273 | input_report_key(idev, dev->key_code, 0); | ||
274 | } | ||
275 | |||
276 | dev->key_code = key; | ||
277 | if (key >= 0) { | ||
278 | /* new valid key */ | ||
279 | input_report_key(idev, key, 1); | ||
280 | } | ||
281 | |||
282 | input_sync(idev); | ||
283 | } | ||
284 | |||
285 | /****************************************************************************** | ||
286 | * CM109 usb communication interface | ||
287 | *****************************************************************************/ | ||
288 | |||
289 | static void cm109_submit_buzz_toggle(struct cm109_dev *dev) | ||
290 | { | ||
291 | int error; | ||
292 | |||
293 | if (dev->buzzer_state) | ||
294 | dev->ctl_data->byte[HID_OR0] |= BUZZER_ON; | ||
295 | else | ||
296 | dev->ctl_data->byte[HID_OR0] &= ~BUZZER_ON; | ||
297 | |||
298 | error = usb_submit_urb(dev->urb_ctl, GFP_ATOMIC); | ||
299 | if (error) | ||
300 | err("%s: usb_submit_urb (urb_ctl) failed %d", __func__, error); | ||
301 | } | ||
302 | |||
303 | /* | ||
304 | * IRQ handler | ||
305 | */ | ||
306 | static void cm109_urb_irq_callback(struct urb *urb) | ||
307 | { | ||
308 | struct cm109_dev *dev = urb->context; | ||
309 | const int status = urb->status; | ||
310 | int error; | ||
311 | |||
312 | dev_dbg(&urb->dev->dev, "### URB IRQ: [0x%02x 0x%02x 0x%02x 0x%02x] keybit=0x%02x\n", | ||
313 | dev->irq_data->byte[0], | ||
314 | dev->irq_data->byte[1], | ||
315 | dev->irq_data->byte[2], | ||
316 | dev->irq_data->byte[3], | ||
317 | dev->keybit); | ||
318 | |||
319 | if (status) { | ||
320 | if (status == -ESHUTDOWN) | ||
321 | return; | ||
322 | err("%s: urb status %d", __func__, status); | ||
323 | } | ||
324 | |||
325 | /* Special keys */ | ||
326 | if (dev->irq_data->byte[HID_IR0] & 0x0f) { | ||
327 | const int code = (dev->irq_data->byte[HID_IR0] & 0x0f); | ||
328 | report_key(dev, dev->keymap[0xff + code]); | ||
329 | } | ||
330 | |||
331 | /* Scan key column */ | ||
332 | if (dev->keybit == 0xf) { | ||
333 | |||
334 | /* Any changes ? */ | ||
335 | if ((dev->gpi & 0xf0) == (dev->irq_data->byte[HID_IR1] & 0xf0)) | ||
336 | goto out; | ||
337 | |||
338 | dev->gpi = dev->irq_data->byte[HID_IR1] & 0xf0; | ||
339 | dev->keybit = 0x1; | ||
340 | } else { | ||
341 | report_key(dev, dev->keymap[dev->irq_data->byte[HID_IR1]]); | ||
342 | |||
343 | dev->keybit <<= 1; | ||
344 | if (dev->keybit > 0x8) | ||
345 | dev->keybit = 0xf; | ||
346 | } | ||
347 | |||
348 | out: | ||
349 | |||
350 | spin_lock(&dev->ctl_submit_lock); | ||
351 | |||
352 | dev->irq_urb_pending = 0; | ||
353 | |||
354 | if (likely(!dev->shutdown)) { | ||
355 | |||
356 | if (dev->buzzer_state) | ||
357 | dev->ctl_data->byte[HID_OR0] |= BUZZER_ON; | ||
358 | else | ||
359 | dev->ctl_data->byte[HID_OR0] &= ~BUZZER_ON; | ||
360 | |||
361 | dev->ctl_data->byte[HID_OR1] = dev->keybit; | ||
362 | dev->ctl_data->byte[HID_OR2] = dev->keybit; | ||
363 | |||
364 | dev->buzzer_pending = 0; | ||
365 | dev->ctl_urb_pending = 1; | ||
366 | |||
367 | error = usb_submit_urb(dev->urb_ctl, GFP_ATOMIC); | ||
368 | if (error) | ||
369 | err("%s: usb_submit_urb (urb_ctl) failed %d", | ||
370 | __func__, error); | ||
371 | } | ||
372 | |||
373 | spin_unlock(&dev->ctl_submit_lock); | ||
374 | } | ||
375 | |||
376 | static void cm109_urb_ctl_callback(struct urb *urb) | ||
377 | { | ||
378 | struct cm109_dev *dev = urb->context; | ||
379 | const int status = urb->status; | ||
380 | int error; | ||
381 | |||
382 | dev_dbg(&urb->dev->dev, "### URB CTL: [0x%02x 0x%02x 0x%02x 0x%02x]\n", | ||
383 | dev->ctl_data->byte[0], | ||
384 | dev->ctl_data->byte[1], | ||
385 | dev->ctl_data->byte[2], | ||
386 | dev->ctl_data->byte[3]); | ||
387 | |||
388 | if (status) | ||
389 | err("%s: urb status %d", __func__, status); | ||
390 | |||
391 | spin_lock(&dev->ctl_submit_lock); | ||
392 | |||
393 | dev->ctl_urb_pending = 0; | ||
394 | |||
395 | if (likely(!dev->shutdown)) { | ||
396 | |||
397 | if (dev->buzzer_pending) { | ||
398 | dev->buzzer_pending = 0; | ||
399 | dev->ctl_urb_pending = 1; | ||
400 | cm109_submit_buzz_toggle(dev); | ||
401 | } else if (likely(!dev->irq_urb_pending)) { | ||
402 | /* ask for key data */ | ||
403 | dev->irq_urb_pending = 1; | ||
404 | error = usb_submit_urb(dev->urb_irq, GFP_ATOMIC); | ||
405 | if (error) | ||
406 | err("%s: usb_submit_urb (urb_irq) failed %d", | ||
407 | __func__, error); | ||
408 | } | ||
409 | } | ||
410 | |||
411 | spin_unlock(&dev->ctl_submit_lock); | ||
412 | } | ||
413 | |||
414 | static void cm109_toggle_buzzer_async(struct cm109_dev *dev) | ||
415 | { | ||
416 | unsigned long flags; | ||
417 | |||
418 | spin_lock_irqsave(&dev->ctl_submit_lock, flags); | ||
419 | |||
420 | if (dev->ctl_urb_pending) { | ||
421 | /* URB completion will resubmit */ | ||
422 | dev->buzzer_pending = 1; | ||
423 | } else { | ||
424 | dev->ctl_urb_pending = 1; | ||
425 | cm109_submit_buzz_toggle(dev); | ||
426 | } | ||
427 | |||
428 | spin_unlock_irqrestore(&dev->ctl_submit_lock, flags); | ||
429 | } | ||
430 | |||
431 | static void cm109_toggle_buzzer_sync(struct cm109_dev *dev, int on) | ||
432 | { | ||
433 | int error; | ||
434 | |||
435 | if (on) | ||
436 | dev->ctl_data->byte[HID_OR0] |= BUZZER_ON; | ||
437 | else | ||
438 | dev->ctl_data->byte[HID_OR0] &= ~BUZZER_ON; | ||
439 | |||
440 | error = usb_control_msg(dev->udev, | ||
441 | usb_sndctrlpipe(dev->udev, 0), | ||
442 | dev->ctl_req->bRequest, | ||
443 | dev->ctl_req->bRequestType, | ||
444 | le16_to_cpu(dev->ctl_req->wValue), | ||
445 | le16_to_cpu(dev->ctl_req->wIndex), | ||
446 | dev->ctl_data, | ||
447 | USB_PKT_LEN, USB_CTRL_SET_TIMEOUT); | ||
448 | if (error && error != EINTR) | ||
449 | err("%s: usb_control_msg() failed %d", __func__, error); | ||
450 | } | ||
451 | |||
452 | static void cm109_stop_traffic(struct cm109_dev *dev) | ||
453 | { | ||
454 | dev->shutdown = 1; | ||
455 | /* | ||
456 | * Make sure other CPUs see this | ||
457 | */ | ||
458 | smp_wmb(); | ||
459 | |||
460 | usb_kill_urb(dev->urb_ctl); | ||
461 | usb_kill_urb(dev->urb_irq); | ||
462 | |||
463 | cm109_toggle_buzzer_sync(dev, 0); | ||
464 | |||
465 | dev->shutdown = 0; | ||
466 | smp_wmb(); | ||
467 | } | ||
468 | |||
469 | static void cm109_restore_state(struct cm109_dev *dev) | ||
470 | { | ||
471 | if (dev->open) { | ||
472 | /* | ||
473 | * Restore buzzer state. | ||
474 | * This will also kick regular URB submission | ||
475 | */ | ||
476 | cm109_toggle_buzzer_async(dev); | ||
477 | } | ||
478 | } | ||
479 | |||
480 | /****************************************************************************** | ||
481 | * input event interface | ||
482 | *****************************************************************************/ | ||
483 | |||
484 | static int cm109_input_open(struct input_dev *idev) | ||
485 | { | ||
486 | struct cm109_dev *dev = input_get_drvdata(idev); | ||
487 | int error; | ||
488 | |||
489 | error = usb_autopm_get_interface(dev->intf); | ||
490 | if (error < 0) { | ||
491 | err("%s - cannot autoresume, result %d", | ||
492 | __func__, error); | ||
493 | return error; | ||
494 | } | ||
495 | |||
496 | mutex_lock(&dev->pm_mutex); | ||
497 | |||
498 | dev->buzzer_state = 0; | ||
499 | dev->key_code = -1; /* no keys pressed */ | ||
500 | dev->keybit = 0xf; | ||
501 | |||
502 | /* issue INIT */ | ||
503 | dev->ctl_data->byte[HID_OR0] = HID_OR_GPO_BUZ_SPDIF; | ||
504 | dev->ctl_data->byte[HID_OR1] = dev->keybit; | ||
505 | dev->ctl_data->byte[HID_OR2] = dev->keybit; | ||
506 | dev->ctl_data->byte[HID_OR3] = 0x00; | ||
507 | |||
508 | error = usb_submit_urb(dev->urb_ctl, GFP_KERNEL); | ||
509 | if (error) | ||
510 | err("%s: usb_submit_urb (urb_ctl) failed %d", __func__, error); | ||
511 | else | ||
512 | dev->open = 1; | ||
513 | |||
514 | mutex_unlock(&dev->pm_mutex); | ||
515 | |||
516 | if (error) | ||
517 | usb_autopm_put_interface(dev->intf); | ||
518 | |||
519 | return error; | ||
520 | } | ||
521 | |||
522 | static void cm109_input_close(struct input_dev *idev) | ||
523 | { | ||
524 | struct cm109_dev *dev = input_get_drvdata(idev); | ||
525 | |||
526 | mutex_lock(&dev->pm_mutex); | ||
527 | |||
528 | /* | ||
529 | * Once we are here event delivery is stopped so we | ||
530 | * don't need to worry about someone starting buzzer | ||
531 | * again | ||
532 | */ | ||
533 | cm109_stop_traffic(dev); | ||
534 | dev->open = 0; | ||
535 | |||
536 | mutex_unlock(&dev->pm_mutex); | ||
537 | |||
538 | usb_autopm_put_interface(dev->intf); | ||
539 | } | ||
540 | |||
541 | static int cm109_input_ev(struct input_dev *idev, unsigned int type, | ||
542 | unsigned int code, int value) | ||
543 | { | ||
544 | struct cm109_dev *dev = input_get_drvdata(idev); | ||
545 | |||
546 | dev_dbg(&dev->udev->dev, | ||
547 | "input_ev: type=%u code=%u value=%d\n", type, code, value); | ||
548 | |||
549 | if (type != EV_SND) | ||
550 | return -EINVAL; | ||
551 | |||
552 | switch (code) { | ||
553 | case SND_TONE: | ||
554 | case SND_BELL: | ||
555 | dev->buzzer_state = !!value; | ||
556 | if (!dev->resetting) | ||
557 | cm109_toggle_buzzer_async(dev); | ||
558 | return 0; | ||
559 | |||
560 | default: | ||
561 | return -EINVAL; | ||
562 | } | ||
563 | } | ||
564 | |||
565 | |||
566 | /****************************************************************************** | ||
567 | * Linux interface and usb initialisation | ||
568 | *****************************************************************************/ | ||
569 | |||
570 | struct driver_info { | ||
571 | char *name; | ||
572 | }; | ||
573 | |||
574 | static const struct driver_info info_cm109 = { | ||
575 | .name = "CM109 USB driver", | ||
576 | }; | ||
577 | |||
578 | enum { | ||
579 | VENDOR_ID = 0x0d8c, /* C-Media Electronics */ | ||
580 | PRODUCT_ID_CM109 = 0x000e, /* CM109 defines range 0x0008 - 0x000f */ | ||
581 | }; | ||
582 | |||
583 | /* table of devices that work with this driver */ | ||
584 | static const struct usb_device_id cm109_usb_table[] = { | ||
585 | { | ||
586 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE | | ||
587 | USB_DEVICE_ID_MATCH_INT_INFO, | ||
588 | .idVendor = VENDOR_ID, | ||
589 | .idProduct = PRODUCT_ID_CM109, | ||
590 | .bInterfaceClass = USB_CLASS_HID, | ||
591 | .bInterfaceSubClass = 0, | ||
592 | .bInterfaceProtocol = 0, | ||
593 | .driver_info = (kernel_ulong_t) &info_cm109 | ||
594 | }, | ||
595 | /* you can add more devices here with product ID 0x0008 - 0x000f */ | ||
596 | { } | ||
597 | }; | ||
598 | |||
599 | static void cm109_usb_cleanup(struct cm109_dev *dev) | ||
600 | { | ||
601 | if (dev->ctl_req) | ||
602 | usb_buffer_free(dev->udev, sizeof(*(dev->ctl_req)), | ||
603 | dev->ctl_req, dev->ctl_req_dma); | ||
604 | if (dev->ctl_data) | ||
605 | usb_buffer_free(dev->udev, USB_PKT_LEN, | ||
606 | dev->ctl_data, dev->ctl_dma); | ||
607 | if (dev->irq_data) | ||
608 | usb_buffer_free(dev->udev, USB_PKT_LEN, | ||
609 | dev->irq_data, dev->irq_dma); | ||
610 | |||
611 | usb_free_urb(dev->urb_irq); /* parameter validation in core/urb */ | ||
612 | usb_free_urb(dev->urb_ctl); /* parameter validation in core/urb */ | ||
613 | kfree(dev); | ||
614 | } | ||
615 | |||
616 | static void cm109_usb_disconnect(struct usb_interface *interface) | ||
617 | { | ||
618 | struct cm109_dev *dev = usb_get_intfdata(interface); | ||
619 | |||
620 | usb_set_intfdata(interface, NULL); | ||
621 | input_unregister_device(dev->idev); | ||
622 | cm109_usb_cleanup(dev); | ||
623 | } | ||
624 | |||
625 | static int cm109_usb_probe(struct usb_interface *intf, | ||
626 | const struct usb_device_id *id) | ||
627 | { | ||
628 | struct usb_device *udev = interface_to_usbdev(intf); | ||
629 | struct driver_info *nfo = (struct driver_info *)id->driver_info; | ||
630 | struct usb_host_interface *interface; | ||
631 | struct usb_endpoint_descriptor *endpoint; | ||
632 | struct cm109_dev *dev; | ||
633 | struct input_dev *input_dev = NULL; | ||
634 | int ret, pipe, i; | ||
635 | int error = -ENOMEM; | ||
636 | |||
637 | interface = intf->cur_altsetting; | ||
638 | endpoint = &interface->endpoint[0].desc; | ||
639 | |||
640 | if (!usb_endpoint_is_int_in(endpoint)) | ||
641 | return -ENODEV; | ||
642 | |||
643 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
644 | if (!dev) | ||
645 | return -ENOMEM; | ||
646 | |||
647 | spin_lock_init(&dev->ctl_submit_lock); | ||
648 | mutex_init(&dev->pm_mutex); | ||
649 | |||
650 | dev->udev = udev; | ||
651 | dev->intf = intf; | ||
652 | |||
653 | dev->idev = input_dev = input_allocate_device(); | ||
654 | if (!input_dev) | ||
655 | goto err_out; | ||
656 | |||
657 | /* allocate usb buffers */ | ||
658 | dev->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN, | ||
659 | GFP_KERNEL, &dev->irq_dma); | ||
660 | if (!dev->irq_data) | ||
661 | goto err_out; | ||
662 | |||
663 | dev->ctl_data = usb_buffer_alloc(udev, USB_PKT_LEN, | ||
664 | GFP_KERNEL, &dev->ctl_dma); | ||
665 | if (!dev->ctl_data) | ||
666 | goto err_out; | ||
667 | |||
668 | dev->ctl_req = usb_buffer_alloc(udev, sizeof(*(dev->ctl_req)), | ||
669 | GFP_KERNEL, &dev->ctl_req_dma); | ||
670 | if (!dev->ctl_req) | ||
671 | goto err_out; | ||
672 | |||
673 | /* allocate urb structures */ | ||
674 | dev->urb_irq = usb_alloc_urb(0, GFP_KERNEL); | ||
675 | if (!dev->urb_irq) | ||
676 | goto err_out; | ||
677 | |||
678 | dev->urb_ctl = usb_alloc_urb(0, GFP_KERNEL); | ||
679 | if (!dev->urb_ctl) | ||
680 | goto err_out; | ||
681 | |||
682 | /* get a handle to the interrupt data pipe */ | ||
683 | pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress); | ||
684 | ret = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); | ||
685 | if (ret != USB_PKT_LEN) | ||
686 | err("invalid payload size %d, expected %d", ret, USB_PKT_LEN); | ||
687 | |||
688 | /* initialise irq urb */ | ||
689 | usb_fill_int_urb(dev->urb_irq, udev, pipe, dev->irq_data, | ||
690 | USB_PKT_LEN, | ||
691 | cm109_urb_irq_callback, dev, endpoint->bInterval); | ||
692 | dev->urb_irq->transfer_dma = dev->irq_dma; | ||
693 | dev->urb_irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
694 | dev->urb_irq->dev = udev; | ||
695 | |||
696 | /* initialise ctl urb */ | ||
697 | dev->ctl_req->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | | ||
698 | USB_DIR_OUT; | ||
699 | dev->ctl_req->bRequest = USB_REQ_SET_CONFIGURATION; | ||
700 | dev->ctl_req->wValue = cpu_to_le16(0x200); | ||
701 | dev->ctl_req->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber); | ||
702 | dev->ctl_req->wLength = cpu_to_le16(USB_PKT_LEN); | ||
703 | |||
704 | usb_fill_control_urb(dev->urb_ctl, udev, usb_sndctrlpipe(udev, 0), | ||
705 | (void *)dev->ctl_req, dev->ctl_data, USB_PKT_LEN, | ||
706 | cm109_urb_ctl_callback, dev); | ||
707 | dev->urb_ctl->setup_dma = dev->ctl_req_dma; | ||
708 | dev->urb_ctl->transfer_dma = dev->ctl_dma; | ||
709 | dev->urb_ctl->transfer_flags |= URB_NO_SETUP_DMA_MAP | | ||
710 | URB_NO_TRANSFER_DMA_MAP; | ||
711 | dev->urb_ctl->dev = udev; | ||
712 | |||
713 | /* find out the physical bus location */ | ||
714 | usb_make_path(udev, dev->phys, sizeof(dev->phys)); | ||
715 | strlcat(dev->phys, "/input0", sizeof(dev->phys)); | ||
716 | |||
717 | /* register settings for the input device */ | ||
718 | input_dev->name = nfo->name; | ||
719 | input_dev->phys = dev->phys; | ||
720 | usb_to_input_id(udev, &input_dev->id); | ||
721 | input_dev->dev.parent = &intf->dev; | ||
722 | |||
723 | input_set_drvdata(input_dev, dev); | ||
724 | input_dev->open = cm109_input_open; | ||
725 | input_dev->close = cm109_input_close; | ||
726 | input_dev->event = cm109_input_ev; | ||
727 | |||
728 | input_dev->keycode = dev->keymap; | ||
729 | input_dev->keycodesize = sizeof(unsigned char); | ||
730 | input_dev->keycodemax = ARRAY_SIZE(dev->keymap); | ||
731 | |||
732 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_SND); | ||
733 | input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE); | ||
734 | |||
735 | /* register available key events */ | ||
736 | for (i = 0; i < KEYMAP_SIZE; i++) { | ||
737 | unsigned short k = keymap(i); | ||
738 | dev->keymap[i] = k; | ||
739 | __set_bit(k, input_dev->keybit); | ||
740 | } | ||
741 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
742 | |||
743 | error = input_register_device(dev->idev); | ||
744 | if (error) | ||
745 | goto err_out; | ||
746 | |||
747 | usb_set_intfdata(intf, dev); | ||
748 | |||
749 | return 0; | ||
750 | |||
751 | err_out: | ||
752 | input_free_device(input_dev); | ||
753 | cm109_usb_cleanup(dev); | ||
754 | return error; | ||
755 | } | ||
756 | |||
757 | static int cm109_usb_suspend(struct usb_interface *intf, pm_message_t message) | ||
758 | { | ||
759 | struct cm109_dev *dev = usb_get_intfdata(intf); | ||
760 | |||
761 | dev_info(&intf->dev, "cm109: usb_suspend (event=%d)\n", message.event); | ||
762 | |||
763 | mutex_lock(&dev->pm_mutex); | ||
764 | cm109_stop_traffic(dev); | ||
765 | mutex_unlock(&dev->pm_mutex); | ||
766 | |||
767 | return 0; | ||
768 | } | ||
769 | |||
770 | static int cm109_usb_resume(struct usb_interface *intf) | ||
771 | { | ||
772 | struct cm109_dev *dev = usb_get_intfdata(intf); | ||
773 | |||
774 | dev_info(&intf->dev, "cm109: usb_resume\n"); | ||
775 | |||
776 | mutex_lock(&dev->pm_mutex); | ||
777 | cm109_restore_state(dev); | ||
778 | mutex_unlock(&dev->pm_mutex); | ||
779 | |||
780 | return 0; | ||
781 | } | ||
782 | |||
783 | static int cm109_usb_pre_reset(struct usb_interface *intf) | ||
784 | { | ||
785 | struct cm109_dev *dev = usb_get_intfdata(intf); | ||
786 | |||
787 | mutex_lock(&dev->pm_mutex); | ||
788 | |||
789 | /* | ||
790 | * Make sure input events don't try to toggle buzzer | ||
791 | * while we are resetting | ||
792 | */ | ||
793 | dev->resetting = 1; | ||
794 | smp_wmb(); | ||
795 | |||
796 | cm109_stop_traffic(dev); | ||
797 | |||
798 | return 0; | ||
799 | } | ||
800 | |||
801 | static int cm109_usb_post_reset(struct usb_interface *intf) | ||
802 | { | ||
803 | struct cm109_dev *dev = usb_get_intfdata(intf); | ||
804 | |||
805 | dev->resetting = 0; | ||
806 | smp_wmb(); | ||
807 | |||
808 | cm109_restore_state(dev); | ||
809 | |||
810 | mutex_unlock(&dev->pm_mutex); | ||
811 | |||
812 | return 0; | ||
813 | } | ||
814 | |||
815 | static struct usb_driver cm109_driver = { | ||
816 | .name = "cm109", | ||
817 | .probe = cm109_usb_probe, | ||
818 | .disconnect = cm109_usb_disconnect, | ||
819 | .suspend = cm109_usb_suspend, | ||
820 | .resume = cm109_usb_resume, | ||
821 | .reset_resume = cm109_usb_resume, | ||
822 | .pre_reset = cm109_usb_pre_reset, | ||
823 | .post_reset = cm109_usb_post_reset, | ||
824 | .id_table = cm109_usb_table, | ||
825 | .supports_autosuspend = 1, | ||
826 | }; | ||
827 | |||
828 | static int __init cm109_select_keymap(void) | ||
829 | { | ||
830 | /* Load the phone keymap */ | ||
831 | if (!strcasecmp(phone, "kip1000")) { | ||
832 | keymap = keymap_kip1000; | ||
833 | printk(KERN_INFO KBUILD_MODNAME ": " | ||
834 | "Keymap for Komunikate KIP1000 phone loaded\n"); | ||
835 | } else if (!strcasecmp(phone, "gtalk")) { | ||
836 | keymap = keymap_gtalk; | ||
837 | printk(KERN_INFO KBUILD_MODNAME ": " | ||
838 | "Keymap for Genius G-talk phone loaded\n"); | ||
839 | } else if (!strcasecmp(phone, "usbph01")) { | ||
840 | keymap = keymap_usbph01; | ||
841 | printk(KERN_INFO KBUILD_MODNAME ": " | ||
842 | "Keymap for Allied-Telesis Corega USBPH01 phone loaded\n"); | ||
843 | } else { | ||
844 | printk(KERN_ERR KBUILD_MODNAME ": " | ||
845 | "Unsupported phone: %s\n", phone); | ||
846 | return -EINVAL; | ||
847 | } | ||
848 | |||
849 | return 0; | ||
850 | } | ||
851 | |||
852 | static int __init cm109_init(void) | ||
853 | { | ||
854 | int err; | ||
855 | |||
856 | err = cm109_select_keymap(); | ||
857 | if (err) | ||
858 | return err; | ||
859 | |||
860 | err = usb_register(&cm109_driver); | ||
861 | if (err) | ||
862 | return err; | ||
863 | |||
864 | printk(KERN_INFO KBUILD_MODNAME ": " | ||
865 | DRIVER_DESC ": " DRIVER_VERSION " (C) " DRIVER_AUTHOR "\n"); | ||
866 | |||
867 | return 0; | ||
868 | } | ||
869 | |||
870 | static void __exit cm109_exit(void) | ||
871 | { | ||
872 | usb_deregister(&cm109_driver); | ||
873 | } | ||
874 | |||
875 | module_init(cm109_init); | ||
876 | module_exit(cm109_exit); | ||
877 | |||
878 | MODULE_DEVICE_TABLE(usb, cm109_usb_table); | ||
879 | |||
880 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
881 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
882 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/misc/map_to_7segment.h b/drivers/input/misc/map_to_7segment.h deleted file mode 100644 index a424094d9fe2..000000000000 --- a/drivers/input/misc/map_to_7segment.h +++ /dev/null | |||
@@ -1,189 +0,0 @@ | |||
1 | /* | ||
2 | * drivers/usb/input/map_to_7segment.h | ||
3 | * | ||
4 | * Copyright (c) 2005 Henk Vergonet <Henk.Vergonet@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation; either version 2 of | ||
9 | * the License, or (at your option) any later version. | ||
10 | * | ||
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. | ||
15 | * | ||
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 | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #ifndef MAP_TO_7SEGMENT_H | ||
22 | #define MAP_TO_7SEGMENT_H | ||
23 | |||
24 | /* This file provides translation primitives and tables for the conversion | ||
25 | * of (ASCII) characters to a 7-segments notation. | ||
26 | * | ||
27 | * The 7 segment's wikipedia notation below is used as standard. | ||
28 | * See: http://en.wikipedia.org/wiki/Seven_segment_display | ||
29 | * | ||
30 | * Notation: +-a-+ | ||
31 | * f b | ||
32 | * +-g-+ | ||
33 | * e c | ||
34 | * +-d-+ | ||
35 | * | ||
36 | * Usage: | ||
37 | * | ||
38 | * Register a map variable, and fill it with a character set: | ||
39 | * static SEG7_DEFAULT_MAP(map_seg7); | ||
40 | * | ||
41 | * | ||
42 | * Then use for conversion: | ||
43 | * seg7 = map_to_seg7(&map_seg7, some_char); | ||
44 | * ... | ||
45 | * | ||
46 | * In device drivers it is recommended, if required, to make the char map | ||
47 | * accessible via the sysfs interface using the following scheme: | ||
48 | * | ||
49 | * static ssize_t show_map(struct device *dev, char *buf) { | ||
50 | * memcpy(buf, &map_seg7, sizeof(map_seg7)); | ||
51 | * return sizeof(map_seg7); | ||
52 | * } | ||
53 | * static ssize_t store_map(struct device *dev, const char *buf, size_t cnt) { | ||
54 | * if(cnt != sizeof(map_seg7)) | ||
55 | * return -EINVAL; | ||
56 | * memcpy(&map_seg7, buf, cnt); | ||
57 | * return cnt; | ||
58 | * } | ||
59 | * static DEVICE_ATTR(map_seg7, PERMS_RW, show_map, store_map); | ||
60 | * | ||
61 | * History: | ||
62 | * 2005-05-31 RFC linux-kernel@vger.kernel.org | ||
63 | */ | ||
64 | #include <linux/errno.h> | ||
65 | |||
66 | |||
67 | #define BIT_SEG7_A 0 | ||
68 | #define BIT_SEG7_B 1 | ||
69 | #define BIT_SEG7_C 2 | ||
70 | #define BIT_SEG7_D 3 | ||
71 | #define BIT_SEG7_E 4 | ||
72 | #define BIT_SEG7_F 5 | ||
73 | #define BIT_SEG7_G 6 | ||
74 | #define BIT_SEG7_RESERVED 7 | ||
75 | |||
76 | struct seg7_conversion_map { | ||
77 | unsigned char table[128]; | ||
78 | }; | ||
79 | |||
80 | static inline int map_to_seg7(struct seg7_conversion_map *map, int c) | ||
81 | { | ||
82 | return c >= 0 && c < sizeof(map->table) ? map->table[c] : -EINVAL; | ||
83 | } | ||
84 | |||
85 | #define SEG7_CONVERSION_MAP(_name, _map) \ | ||
86 | struct seg7_conversion_map _name = { .table = { _map } } | ||
87 | |||
88 | /* | ||
89 | * It is recommended to use a facility that allows user space to redefine | ||
90 | * custom character sets for LCD devices. Please use a sysfs interface | ||
91 | * as described above. | ||
92 | */ | ||
93 | #define MAP_TO_SEG7_SYSFS_FILE "map_seg7" | ||
94 | |||
95 | /******************************************************************************* | ||
96 | * ASCII conversion table | ||
97 | ******************************************************************************/ | ||
98 | |||
99 | #define _SEG7(l,a,b,c,d,e,f,g) \ | ||
100 | ( a<<BIT_SEG7_A | b<<BIT_SEG7_B | c<<BIT_SEG7_C | d<<BIT_SEG7_D | \ | ||
101 | e<<BIT_SEG7_E | f<<BIT_SEG7_F | g<<BIT_SEG7_G ) | ||
102 | |||
103 | #define _MAP_0_32_ASCII_SEG7_NON_PRINTABLE \ | ||
104 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||
105 | |||
106 | #define _MAP_33_47_ASCII_SEG7_SYMBOL \ | ||
107 | _SEG7('!',0,0,0,0,1,1,0), _SEG7('"',0,1,0,0,0,1,0), _SEG7('#',0,1,1,0,1,1,0),\ | ||
108 | _SEG7('$',1,0,1,1,0,1,1), _SEG7('%',0,0,1,0,0,1,0), _SEG7('&',1,0,1,1,1,1,1),\ | ||
109 | _SEG7('\'',0,0,0,0,0,1,0),_SEG7('(',1,0,0,1,1,1,0), _SEG7(')',1,1,1,1,0,0,0),\ | ||
110 | _SEG7('*',0,1,1,0,1,1,1), _SEG7('+',0,1,1,0,0,0,1), _SEG7(',',0,0,0,0,1,0,0),\ | ||
111 | _SEG7('-',0,0,0,0,0,0,1), _SEG7('.',0,0,0,0,1,0,0), _SEG7('/',0,1,0,0,1,0,1), | ||
112 | |||
113 | #define _MAP_48_57_ASCII_SEG7_NUMERIC \ | ||
114 | _SEG7('0',1,1,1,1,1,1,0), _SEG7('1',0,1,1,0,0,0,0), _SEG7('2',1,1,0,1,1,0,1),\ | ||
115 | _SEG7('3',1,1,1,1,0,0,1), _SEG7('4',0,1,1,0,0,1,1), _SEG7('5',1,0,1,1,0,1,1),\ | ||
116 | _SEG7('6',1,0,1,1,1,1,1), _SEG7('7',1,1,1,0,0,0,0), _SEG7('8',1,1,1,1,1,1,1),\ | ||
117 | _SEG7('9',1,1,1,1,0,1,1), | ||
118 | |||
119 | #define _MAP_58_64_ASCII_SEG7_SYMBOL \ | ||
120 | _SEG7(':',0,0,0,1,0,0,1), _SEG7(';',0,0,0,1,0,0,1), _SEG7('<',1,0,0,0,0,1,1),\ | ||
121 | _SEG7('=',0,0,0,1,0,0,1), _SEG7('>',1,1,0,0,0,0,1), _SEG7('?',1,1,1,0,0,1,0),\ | ||
122 | _SEG7('@',1,1,0,1,1,1,1), | ||
123 | |||
124 | #define _MAP_65_90_ASCII_SEG7_ALPHA_UPPR \ | ||
125 | _SEG7('A',1,1,1,0,1,1,1), _SEG7('B',1,1,1,1,1,1,1), _SEG7('C',1,0,0,1,1,1,0),\ | ||
126 | _SEG7('D',1,1,1,1,1,1,0), _SEG7('E',1,0,0,1,1,1,1), _SEG7('F',1,0,0,0,1,1,1),\ | ||
127 | _SEG7('G',1,1,1,1,0,1,1), _SEG7('H',0,1,1,0,1,1,1), _SEG7('I',0,1,1,0,0,0,0),\ | ||
128 | _SEG7('J',0,1,1,1,0,0,0), _SEG7('K',0,1,1,0,1,1,1), _SEG7('L',0,0,0,1,1,1,0),\ | ||
129 | _SEG7('M',1,1,1,0,1,1,0), _SEG7('N',1,1,1,0,1,1,0), _SEG7('O',1,1,1,1,1,1,0),\ | ||
130 | _SEG7('P',1,1,0,0,1,1,1), _SEG7('Q',1,1,1,1,1,1,0), _SEG7('R',1,1,1,0,1,1,1),\ | ||
131 | _SEG7('S',1,0,1,1,0,1,1), _SEG7('T',0,0,0,1,1,1,1), _SEG7('U',0,1,1,1,1,1,0),\ | ||
132 | _SEG7('V',0,1,1,1,1,1,0), _SEG7('W',0,1,1,1,1,1,1), _SEG7('X',0,1,1,0,1,1,1),\ | ||
133 | _SEG7('Y',0,1,1,0,0,1,1), _SEG7('Z',1,1,0,1,1,0,1), | ||
134 | |||
135 | #define _MAP_91_96_ASCII_SEG7_SYMBOL \ | ||
136 | _SEG7('[',1,0,0,1,1,1,0), _SEG7('\\',0,0,1,0,0,1,1),_SEG7(']',1,1,1,1,0,0,0),\ | ||
137 | _SEG7('^',1,1,0,0,0,1,0), _SEG7('_',0,0,0,1,0,0,0), _SEG7('`',0,1,0,0,0,0,0), | ||
138 | |||
139 | #define _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \ | ||
140 | _SEG7('A',1,1,1,0,1,1,1), _SEG7('b',0,0,1,1,1,1,1), _SEG7('c',0,0,0,1,1,0,1),\ | ||
141 | _SEG7('d',0,1,1,1,1,0,1), _SEG7('E',1,0,0,1,1,1,1), _SEG7('F',1,0,0,0,1,1,1),\ | ||
142 | _SEG7('G',1,1,1,1,0,1,1), _SEG7('h',0,0,1,0,1,1,1), _SEG7('i',0,0,1,0,0,0,0),\ | ||
143 | _SEG7('j',0,0,1,1,0,0,0), _SEG7('k',0,0,1,0,1,1,1), _SEG7('L',0,0,0,1,1,1,0),\ | ||
144 | _SEG7('M',1,1,1,0,1,1,0), _SEG7('n',0,0,1,0,1,0,1), _SEG7('o',0,0,1,1,1,0,1),\ | ||
145 | _SEG7('P',1,1,0,0,1,1,1), _SEG7('q',1,1,1,0,0,1,1), _SEG7('r',0,0,0,0,1,0,1),\ | ||
146 | _SEG7('S',1,0,1,1,0,1,1), _SEG7('T',0,0,0,1,1,1,1), _SEG7('u',0,0,1,1,1,0,0),\ | ||
147 | _SEG7('v',0,0,1,1,1,0,0), _SEG7('W',0,1,1,1,1,1,1), _SEG7('X',0,1,1,0,1,1,1),\ | ||
148 | _SEG7('y',0,1,1,1,0,1,1), _SEG7('Z',1,1,0,1,1,0,1), | ||
149 | |||
150 | #define _MAP_123_126_ASCII_SEG7_SYMBOL \ | ||
151 | _SEG7('{',1,0,0,1,1,1,0), _SEG7('|',0,0,0,0,1,1,0), _SEG7('}',1,1,1,1,0,0,0),\ | ||
152 | _SEG7('~',1,0,0,0,0,0,0), | ||
153 | |||
154 | /* Maps */ | ||
155 | |||
156 | /* This set tries to map as close as possible to the visible characteristics | ||
157 | * of the ASCII symbol, lowercase and uppercase letters may differ in | ||
158 | * presentation on the display. | ||
159 | */ | ||
160 | #define MAP_ASCII7SEG_ALPHANUM \ | ||
161 | _MAP_0_32_ASCII_SEG7_NON_PRINTABLE \ | ||
162 | _MAP_33_47_ASCII_SEG7_SYMBOL \ | ||
163 | _MAP_48_57_ASCII_SEG7_NUMERIC \ | ||
164 | _MAP_58_64_ASCII_SEG7_SYMBOL \ | ||
165 | _MAP_65_90_ASCII_SEG7_ALPHA_UPPR \ | ||
166 | _MAP_91_96_ASCII_SEG7_SYMBOL \ | ||
167 | _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \ | ||
168 | _MAP_123_126_ASCII_SEG7_SYMBOL | ||
169 | |||
170 | /* This set tries to map as close as possible to the symbolic characteristics | ||
171 | * of the ASCII character for maximum discrimination. | ||
172 | * For now this means all alpha chars are in lower case representations. | ||
173 | * (This for example facilitates the use of hex numbers with uppercase input.) | ||
174 | */ | ||
175 | #define MAP_ASCII7SEG_ALPHANUM_LC \ | ||
176 | _MAP_0_32_ASCII_SEG7_NON_PRINTABLE \ | ||
177 | _MAP_33_47_ASCII_SEG7_SYMBOL \ | ||
178 | _MAP_48_57_ASCII_SEG7_NUMERIC \ | ||
179 | _MAP_58_64_ASCII_SEG7_SYMBOL \ | ||
180 | _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \ | ||
181 | _MAP_91_96_ASCII_SEG7_SYMBOL \ | ||
182 | _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \ | ||
183 | _MAP_123_126_ASCII_SEG7_SYMBOL | ||
184 | |||
185 | #define SEG7_DEFAULT_MAP(_name) \ | ||
186 | SEG7_CONVERSION_MAP(_name,MAP_ASCII7SEG_ALPHANUM) | ||
187 | |||
188 | #endif /* MAP_TO_7SEGMENT_H */ | ||
189 | |||
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index fe268be3293b..7c8957dd22c0 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c | |||
@@ -277,6 +277,16 @@ static struct key_entry keymap_fs_amilo_pro_v2000[] __initdata = { | |||
277 | { KE_END, 0 } | 277 | { KE_END, 0 } |
278 | }; | 278 | }; |
279 | 279 | ||
280 | static struct key_entry keymap_fs_amilo_pro_v3505[] __initdata = { | ||
281 | { KE_KEY, 0x01, {KEY_HELP} }, /* Fn+F1 */ | ||
282 | { KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Fn+F4 */ | ||
283 | { KE_BLUETOOTH, 0x30 }, /* Fn+F10 */ | ||
284 | { KE_KEY, 0x31, {KEY_MAIL} }, /* mail button */ | ||
285 | { KE_KEY, 0x36, {KEY_WWW} }, /* www button */ | ||
286 | { KE_WIFI, 0x78 }, /* satelite dish button */ | ||
287 | { KE_END, 0 } | ||
288 | }; | ||
289 | |||
280 | static struct key_entry keymap_fujitsu_n3510[] __initdata = { | 290 | static struct key_entry keymap_fujitsu_n3510[] __initdata = { |
281 | { KE_KEY, 0x11, {KEY_PROG1} }, | 291 | { KE_KEY, 0x11, {KEY_PROG1} }, |
282 | { KE_KEY, 0x12, {KEY_PROG2} }, | 292 | { KE_KEY, 0x12, {KEY_PROG2} }, |
@@ -618,6 +628,15 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
618 | }, | 628 | }, |
619 | { | 629 | { |
620 | .callback = dmi_matched, | 630 | .callback = dmi_matched, |
631 | .ident = "Fujitsu-Siemens Amilo Pro Edition V3505", | ||
632 | .matches = { | ||
633 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | ||
634 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro Edition V3505"), | ||
635 | }, | ||
636 | .driver_data = keymap_fs_amilo_pro_v3505 | ||
637 | }, | ||
638 | { | ||
639 | .callback = dmi_matched, | ||
621 | .ident = "Fujitsu-Siemens Amilo M7400", | 640 | .ident = "Fujitsu-Siemens Amilo M7400", |
622 | .matches = { | 641 | .matches = { |
623 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | 642 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), |
diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c index facefd3dba29..11b5c7e84ed1 100644 --- a/drivers/input/misc/yealink.c +++ b/drivers/input/misc/yealink.c | |||
@@ -52,8 +52,8 @@ | |||
52 | #include <linux/module.h> | 52 | #include <linux/module.h> |
53 | #include <linux/rwsem.h> | 53 | #include <linux/rwsem.h> |
54 | #include <linux/usb/input.h> | 54 | #include <linux/usb/input.h> |
55 | #include <linux/map_to_7segment.h> | ||
55 | 56 | ||
56 | #include "map_to_7segment.h" | ||
57 | #include "yealink.h" | 57 | #include "yealink.h" |
58 | 58 | ||
59 | #define DRIVER_VERSION "yld-20051230" | 59 | #define DRIVER_VERSION "yld-20051230" |
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index f996546fc443..f488b6852baf 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig | |||
@@ -96,6 +96,16 @@ config MOUSE_PS2_TOUCHKIT | |||
96 | 96 | ||
97 | If unsure, say N. | 97 | If unsure, say N. |
98 | 98 | ||
99 | config MOUSE_PS2_OLPC | ||
100 | bool "OLPC PS/2 mouse protocol extension" | ||
101 | depends on MOUSE_PS2 && OLPC | ||
102 | help | ||
103 | Say Y here if you have an OLPC XO-1 laptop (with built-in | ||
104 | PS/2 touchpad/tablet device). The manufacturer calls the | ||
105 | touchpad an HGPK. | ||
106 | |||
107 | If unsure, say N. | ||
108 | |||
99 | config MOUSE_SERIAL | 109 | config MOUSE_SERIAL |
100 | tristate "Serial mouse" | 110 | tristate "Serial mouse" |
101 | select SERIO | 111 | select SERIO |
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index d4d202516090..8e6e69097801 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile | |||
@@ -21,6 +21,7 @@ obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o | |||
21 | psmouse-objs := psmouse-base.o synaptics.o | 21 | psmouse-objs := psmouse-base.o synaptics.o |
22 | 22 | ||
23 | psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o | 23 | psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o |
24 | psmouse-$(CONFIG_MOUSE_PS2_OLPC) += hgpk.o | ||
24 | psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP) += logips2pp.o | 25 | psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP) += logips2pp.o |
25 | psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o | 26 | psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o |
26 | psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o | 27 | psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o |
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 385e32bcf6a6..cbedf957cc58 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -54,6 +54,7 @@ static const struct alps_model_info alps_model_data[] = { | |||
54 | { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ | 54 | { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ |
55 | { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, | 55 | { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, |
56 | { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ | 56 | { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ |
57 | { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude E6500 */ | ||
57 | { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FW_BK_1 } /* Dell Vostro 1400 */ | 58 | { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FW_BK_1 } /* Dell Vostro 1400 */ |
58 | }; | 59 | }; |
59 | 60 | ||
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index 1f41ae94f26b..079816e6b23b 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c | |||
@@ -136,12 +136,28 @@ MODULE_DEVICE_TABLE(usb, atp_table); | |||
136 | #define ATP_GEYSER_MODE_REQUEST_INDEX 0 | 136 | #define ATP_GEYSER_MODE_REQUEST_INDEX 0 |
137 | #define ATP_GEYSER_MODE_VENDOR_VALUE 0x04 | 137 | #define ATP_GEYSER_MODE_VENDOR_VALUE 0x04 |
138 | 138 | ||
139 | /** | ||
140 | * enum atp_status_bits - status bit meanings | ||
141 | * | ||
142 | * These constants represent the meaning of the status bits. | ||
143 | * (only Geyser 3/4) | ||
144 | * | ||
145 | * @ATP_STATUS_BUTTON: The button was pressed | ||
146 | * @ATP_STATUS_BASE_UPDATE: Update of the base values (untouched pad) | ||
147 | * @ATP_STATUS_FROM_RESET: Reset previously performed | ||
148 | */ | ||
149 | enum atp_status_bits { | ||
150 | ATP_STATUS_BUTTON = BIT(0), | ||
151 | ATP_STATUS_BASE_UPDATE = BIT(2), | ||
152 | ATP_STATUS_FROM_RESET = BIT(4), | ||
153 | }; | ||
154 | |||
139 | /* Structure to hold all of our device specific stuff */ | 155 | /* Structure to hold all of our device specific stuff */ |
140 | struct atp { | 156 | struct atp { |
141 | char phys[64]; | 157 | char phys[64]; |
142 | struct usb_device *udev; /* usb device */ | 158 | struct usb_device *udev; /* usb device */ |
143 | struct urb *urb; /* usb request block */ | 159 | struct urb *urb; /* usb request block */ |
144 | signed char *data; /* transferred data */ | 160 | u8 *data; /* transferred data */ |
145 | struct input_dev *input; /* input dev */ | 161 | struct input_dev *input; /* input dev */ |
146 | enum atp_touchpad_type type; /* type of touchpad */ | 162 | enum atp_touchpad_type type; /* type of touchpad */ |
147 | bool open; | 163 | bool open; |
@@ -251,8 +267,6 @@ static void atp_reinit(struct work_struct *work) | |||
251 | int retval; | 267 | int retval; |
252 | 268 | ||
253 | dprintk("appletouch: putting appletouch to sleep (reinit)\n"); | 269 | dprintk("appletouch: putting appletouch to sleep (reinit)\n"); |
254 | dev->idlecount = 0; | ||
255 | |||
256 | atp_geyser_init(udev); | 270 | atp_geyser_init(udev); |
257 | 271 | ||
258 | retval = usb_submit_urb(dev->urb, GFP_ATOMIC); | 272 | retval = usb_submit_urb(dev->urb, GFP_ATOMIC); |
@@ -327,11 +341,14 @@ static inline void atp_report_fingers(struct input_dev *input, int fingers) | |||
327 | input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2); | 341 | input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2); |
328 | } | 342 | } |
329 | 343 | ||
330 | static void atp_complete(struct urb *urb) | 344 | /* Check URB status and for correct length of data package */ |
345 | |||
346 | #define ATP_URB_STATUS_SUCCESS 0 | ||
347 | #define ATP_URB_STATUS_ERROR 1 | ||
348 | #define ATP_URB_STATUS_ERROR_FATAL 2 | ||
349 | |||
350 | static int atp_status_check(struct urb *urb) | ||
331 | { | 351 | { |
332 | int x, y, x_z, y_z, x_f, y_f; | ||
333 | int retval, i, j; | ||
334 | int key; | ||
335 | struct atp *dev = urb->context; | 352 | struct atp *dev = urb->context; |
336 | 353 | ||
337 | switch (urb->status) { | 354 | switch (urb->status) { |
@@ -351,11 +368,12 @@ static void atp_complete(struct urb *urb) | |||
351 | /* This urb is terminated, clean up */ | 368 | /* This urb is terminated, clean up */ |
352 | dbg("atp_complete: urb shutting down with status: %d", | 369 | dbg("atp_complete: urb shutting down with status: %d", |
353 | urb->status); | 370 | urb->status); |
354 | return; | 371 | return ATP_URB_STATUS_ERROR_FATAL; |
372 | |||
355 | default: | 373 | default: |
356 | dbg("atp_complete: nonzero urb status received: %d", | 374 | dbg("atp_complete: nonzero urb status received: %d", |
357 | urb->status); | 375 | urb->status); |
358 | goto exit; | 376 | return ATP_URB_STATUS_ERROR; |
359 | } | 377 | } |
360 | 378 | ||
361 | /* drop incomplete datasets */ | 379 | /* drop incomplete datasets */ |
@@ -363,30 +381,33 @@ static void atp_complete(struct urb *urb) | |||
363 | dprintk("appletouch: incomplete data package" | 381 | dprintk("appletouch: incomplete data package" |
364 | " (first byte: %d, length: %d).\n", | 382 | " (first byte: %d, length: %d).\n", |
365 | dev->data[0], dev->urb->actual_length); | 383 | dev->data[0], dev->urb->actual_length); |
366 | goto exit; | 384 | return ATP_URB_STATUS_ERROR; |
367 | } | 385 | } |
368 | 386 | ||
369 | /* reorder the sensors values */ | 387 | return ATP_URB_STATUS_SUCCESS; |
370 | if (dev->type == ATP_GEYSER3 || dev->type == ATP_GEYSER4) { | 388 | } |
371 | memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); | ||
372 | 389 | ||
373 | /* | 390 | /* |
374 | * The values are laid out like this: | 391 | * USB interrupt callback functions |
375 | * -, Y1, Y2, -, Y3, Y4, -, ..., -, X1, X2, -, X3, X4, ... | 392 | */ |
376 | * '-' is an unused value. | ||
377 | */ | ||
378 | 393 | ||
379 | /* read X values */ | 394 | /* Interrupt function for older touchpads: FOUNTAIN/GEYSER1/GEYSER2 */ |
380 | for (i = 0, j = 19; i < 20; i += 2, j += 3) { | 395 | |
381 | dev->xy_cur[i] = dev->data[j + 1]; | 396 | static void atp_complete_geyser_1_2(struct urb *urb) |
382 | dev->xy_cur[i + 1] = dev->data[j + 2]; | 397 | { |
383 | } | 398 | int x, y, x_z, y_z, x_f, y_f; |
384 | /* read Y values */ | 399 | int retval, i, j; |
385 | for (i = 0, j = 1; i < 9; i += 2, j += 3) { | 400 | int key; |
386 | dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1]; | 401 | struct atp *dev = urb->context; |
387 | dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2]; | 402 | int status = atp_status_check(urb); |
388 | } | 403 | |
389 | } else if (dev->type == ATP_GEYSER2) { | 404 | if (status == ATP_URB_STATUS_ERROR_FATAL) |
405 | return; | ||
406 | else if (status == ATP_URB_STATUS_ERROR) | ||
407 | goto exit; | ||
408 | |||
409 | /* reorder the sensors values */ | ||
410 | if (dev->type == ATP_GEYSER2) { | ||
390 | memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); | 411 | memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); |
391 | 412 | ||
392 | /* | 413 | /* |
@@ -427,34 +448,40 @@ static void atp_complete(struct urb *urb) | |||
427 | /* first sample */ | 448 | /* first sample */ |
428 | dev->valid = true; | 449 | dev->valid = true; |
429 | dev->x_old = dev->y_old = -1; | 450 | dev->x_old = dev->y_old = -1; |
451 | |||
452 | /* Store first sample */ | ||
430 | memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); | 453 | memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); |
431 | 454 | ||
432 | if (dev->size_detect_done || | 455 | /* Perform size detection, if not done already */ |
433 | dev->type == ATP_GEYSER3) /* No 17" Macbooks (yet) */ | 456 | if (!dev->size_detect_done) { |
434 | goto exit; | 457 | |
458 | /* 17" Powerbooks have extra X sensors */ | ||
459 | for (i = (dev->type == ATP_GEYSER2 ? 15 : 16); | ||
460 | i < ATP_XSENSORS; i++) { | ||
461 | if (!dev->xy_cur[i]) | ||
462 | continue; | ||
463 | |||
464 | printk(KERN_INFO | ||
465 | "appletouch: 17\" model detected.\n"); | ||
466 | |||
467 | if (dev->type == ATP_GEYSER2) | ||
468 | input_set_abs_params(dev->input, ABS_X, | ||
469 | 0, | ||
470 | (20 - 1) * | ||
471 | ATP_XFACT - 1, | ||
472 | ATP_FUZZ, 0); | ||
473 | else | ||
474 | input_set_abs_params(dev->input, ABS_X, | ||
475 | 0, | ||
476 | (26 - 1) * | ||
477 | ATP_XFACT - 1, | ||
478 | ATP_FUZZ, 0); | ||
479 | break; | ||
480 | } | ||
435 | 481 | ||
436 | /* 17" Powerbooks have extra X sensors */ | 482 | dev->size_detect_done = 1; |
437 | for (i = (dev->type == ATP_GEYSER2 ? 15 : 16); | 483 | goto exit; |
438 | i < ATP_XSENSORS; i++) { | ||
439 | if (!dev->xy_cur[i]) | ||
440 | continue; | ||
441 | |||
442 | printk(KERN_INFO "appletouch: 17\" model detected.\n"); | ||
443 | if (dev->type == ATP_GEYSER2) | ||
444 | input_set_abs_params(dev->input, ABS_X, 0, | ||
445 | (20 - 1) * | ||
446 | ATP_XFACT - 1, | ||
447 | ATP_FUZZ, 0); | ||
448 | else | ||
449 | input_set_abs_params(dev->input, ABS_X, 0, | ||
450 | (ATP_XSENSORS - 1) * | ||
451 | ATP_XFACT - 1, | ||
452 | ATP_FUZZ, 0); | ||
453 | break; | ||
454 | } | 484 | } |
455 | |||
456 | dev->size_detect_done = 1; | ||
457 | goto exit; | ||
458 | } | 485 | } |
459 | 486 | ||
460 | for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) { | 487 | for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) { |
@@ -475,7 +502,118 @@ static void atp_complete(struct urb *urb) | |||
475 | ATP_XFACT, &x_z, &x_f); | 502 | ATP_XFACT, &x_z, &x_f); |
476 | y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS, | 503 | y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS, |
477 | ATP_YFACT, &y_z, &y_f); | 504 | ATP_YFACT, &y_z, &y_f); |
478 | key = dev->data[dev->datalen - 1] & 1; | 505 | key = dev->data[dev->datalen - 1] & ATP_STATUS_BUTTON; |
506 | |||
507 | if (x && y) { | ||
508 | if (dev->x_old != -1) { | ||
509 | x = (dev->x_old * 3 + x) >> 2; | ||
510 | y = (dev->y_old * 3 + y) >> 2; | ||
511 | dev->x_old = x; | ||
512 | dev->y_old = y; | ||
513 | |||
514 | if (debug > 1) | ||
515 | printk(KERN_DEBUG "appletouch: " | ||
516 | "X: %3d Y: %3d Xz: %3d Yz: %3d\n", | ||
517 | x, y, x_z, y_z); | ||
518 | |||
519 | input_report_key(dev->input, BTN_TOUCH, 1); | ||
520 | input_report_abs(dev->input, ABS_X, x); | ||
521 | input_report_abs(dev->input, ABS_Y, y); | ||
522 | input_report_abs(dev->input, ABS_PRESSURE, | ||
523 | min(ATP_PRESSURE, x_z + y_z)); | ||
524 | atp_report_fingers(dev->input, max(x_f, y_f)); | ||
525 | } | ||
526 | dev->x_old = x; | ||
527 | dev->y_old = y; | ||
528 | |||
529 | } else if (!x && !y) { | ||
530 | |||
531 | dev->x_old = dev->y_old = -1; | ||
532 | input_report_key(dev->input, BTN_TOUCH, 0); | ||
533 | input_report_abs(dev->input, ABS_PRESSURE, 0); | ||
534 | atp_report_fingers(dev->input, 0); | ||
535 | |||
536 | /* reset the accumulator on release */ | ||
537 | memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); | ||
538 | } | ||
539 | |||
540 | input_report_key(dev->input, BTN_LEFT, key); | ||
541 | input_sync(dev->input); | ||
542 | |||
543 | exit: | ||
544 | retval = usb_submit_urb(dev->urb, GFP_ATOMIC); | ||
545 | if (retval) | ||
546 | err("atp_complete: usb_submit_urb failed with result %d", | ||
547 | retval); | ||
548 | } | ||
549 | |||
550 | /* Interrupt function for older touchpads: GEYSER3/GEYSER4 */ | ||
551 | |||
552 | static void atp_complete_geyser_3_4(struct urb *urb) | ||
553 | { | ||
554 | int x, y, x_z, y_z, x_f, y_f; | ||
555 | int retval, i, j; | ||
556 | int key; | ||
557 | struct atp *dev = urb->context; | ||
558 | int status = atp_status_check(urb); | ||
559 | |||
560 | if (status == ATP_URB_STATUS_ERROR_FATAL) | ||
561 | return; | ||
562 | else if (status == ATP_URB_STATUS_ERROR) | ||
563 | goto exit; | ||
564 | |||
565 | /* Reorder the sensors values: | ||
566 | * | ||
567 | * The values are laid out like this: | ||
568 | * -, Y1, Y2, -, Y3, Y4, -, ..., -, X1, X2, -, X3, X4, ... | ||
569 | * '-' is an unused value. | ||
570 | */ | ||
571 | |||
572 | /* read X values */ | ||
573 | for (i = 0, j = 19; i < 20; i += 2, j += 3) { | ||
574 | dev->xy_cur[i] = dev->data[j + 1]; | ||
575 | dev->xy_cur[i + 1] = dev->data[j + 2]; | ||
576 | } | ||
577 | /* read Y values */ | ||
578 | for (i = 0, j = 1; i < 9; i += 2, j += 3) { | ||
579 | dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1]; | ||
580 | dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2]; | ||
581 | } | ||
582 | |||
583 | dbg_dump("sample", dev->xy_cur); | ||
584 | |||
585 | /* Just update the base values (i.e. touchpad in untouched state) */ | ||
586 | if (dev->data[dev->datalen - 1] & ATP_STATUS_BASE_UPDATE) { | ||
587 | |||
588 | dprintk(KERN_DEBUG "appletouch: updated base values\n"); | ||
589 | |||
590 | memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); | ||
591 | goto exit; | ||
592 | } | ||
593 | |||
594 | for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) { | ||
595 | /* calculate the change */ | ||
596 | dev->xy_acc[i] = dev->xy_cur[i] - dev->xy_old[i]; | ||
597 | |||
598 | /* this is a round-robin value, so couple with that */ | ||
599 | if (dev->xy_acc[i] > 127) | ||
600 | dev->xy_acc[i] -= 256; | ||
601 | |||
602 | if (dev->xy_acc[i] < -127) | ||
603 | dev->xy_acc[i] += 256; | ||
604 | |||
605 | /* prevent down drifting */ | ||
606 | if (dev->xy_acc[i] < 0) | ||
607 | dev->xy_acc[i] = 0; | ||
608 | } | ||
609 | |||
610 | dbg_dump("accumulator", dev->xy_acc); | ||
611 | |||
612 | x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS, | ||
613 | ATP_XFACT, &x_z, &x_f); | ||
614 | y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS, | ||
615 | ATP_YFACT, &y_z, &y_f); | ||
616 | key = dev->data[dev->datalen - 1] & ATP_STATUS_BUTTON; | ||
479 | 617 | ||
480 | if (x && y) { | 618 | if (x && y) { |
481 | if (dev->x_old != -1) { | 619 | if (dev->x_old != -1) { |
@@ -514,28 +652,27 @@ static void atp_complete(struct urb *urb) | |||
514 | input_sync(dev->input); | 652 | input_sync(dev->input); |
515 | 653 | ||
516 | /* | 654 | /* |
517 | * Many Geysers will continue to send packets continually after | 655 | * Geysers 3/4 will continue to send packets continually after |
518 | * the first touch unless reinitialised. Do so if it's been | 656 | * the first touch unless reinitialised. Do so if it's been |
519 | * idle for a while in order to avoid waking the kernel up | 657 | * idle for a while in order to avoid waking the kernel up |
520 | * several hundred times a second. Re-initialization does not | 658 | * several hundred times a second. |
521 | * work on Fountain touchpads. | ||
522 | */ | 659 | */ |
523 | if (dev->type != ATP_FOUNTAIN) { | 660 | |
524 | /* | 661 | /* |
525 | * Button must not be pressed when entering suspend, | 662 | * Button must not be pressed when entering suspend, |
526 | * otherwise we will never release the button. | 663 | * otherwise we will never release the button. |
527 | */ | 664 | */ |
528 | if (!x && !y && !key) { | 665 | if (!x && !y && !key) { |
529 | dev->idlecount++; | 666 | dev->idlecount++; |
530 | if (dev->idlecount == 10) { | 667 | if (dev->idlecount == 10) { |
531 | dev->valid = false; | 668 | dev->x_old = dev->y_old = -1; |
532 | schedule_work(&dev->work); | ||
533 | /* Don't resubmit urb here, wait for reinit */ | ||
534 | return; | ||
535 | } | ||
536 | } else | ||
537 | dev->idlecount = 0; | 669 | dev->idlecount = 0; |
538 | } | 670 | schedule_work(&dev->work); |
671 | /* Don't resubmit urb here, wait for reinit */ | ||
672 | return; | ||
673 | } | ||
674 | } else | ||
675 | dev->idlecount = 0; | ||
539 | 676 | ||
540 | exit: | 677 | exit: |
541 | retval = usb_submit_urb(dev->urb, GFP_ATOMIC); | 678 | retval = usb_submit_urb(dev->urb, GFP_ATOMIC); |
@@ -632,9 +769,19 @@ static int atp_probe(struct usb_interface *iface, | |||
632 | if (!dev->data) | 769 | if (!dev->data) |
633 | goto err_free_urb; | 770 | goto err_free_urb; |
634 | 771 | ||
635 | usb_fill_int_urb(dev->urb, udev, | 772 | /* Select the USB complete (callback) function */ |
636 | usb_rcvintpipe(udev, int_in_endpointAddr), | 773 | if (dev->type == ATP_FOUNTAIN || |
637 | dev->data, dev->datalen, atp_complete, dev, 1); | 774 | dev->type == ATP_GEYSER1 || |
775 | dev->type == ATP_GEYSER2) | ||
776 | usb_fill_int_urb(dev->urb, udev, | ||
777 | usb_rcvintpipe(udev, int_in_endpointAddr), | ||
778 | dev->data, dev->datalen, | ||
779 | atp_complete_geyser_1_2, dev, 1); | ||
780 | else | ||
781 | usb_fill_int_urb(dev->urb, udev, | ||
782 | usb_rcvintpipe(udev, int_in_endpointAddr), | ||
783 | dev->data, dev->datalen, | ||
784 | atp_complete_geyser_3_4, dev, 1); | ||
638 | 785 | ||
639 | error = atp_handle_geyser(dev); | 786 | error = atp_handle_geyser(dev); |
640 | if (error) | 787 | if (error) |
@@ -751,8 +898,6 @@ static int atp_suspend(struct usb_interface *iface, pm_message_t message) | |||
751 | struct atp *dev = usb_get_intfdata(iface); | 898 | struct atp *dev = usb_get_intfdata(iface); |
752 | 899 | ||
753 | usb_kill_urb(dev->urb); | 900 | usb_kill_urb(dev->urb); |
754 | dev->valid = false; | ||
755 | |||
756 | return 0; | 901 | return 0; |
757 | } | 902 | } |
758 | 903 | ||
diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c new file mode 100644 index 000000000000..e82d34201e97 --- /dev/null +++ b/drivers/input/mouse/hgpk.c | |||
@@ -0,0 +1,477 @@ | |||
1 | /* | ||
2 | * OLPC HGPK (XO-1) touchpad PS/2 mouse driver | ||
3 | * | ||
4 | * Copyright (c) 2006-2008 One Laptop Per Child | ||
5 | * Authors: | ||
6 | * Zephaniah E. Hull | ||
7 | * Andres Salomon <dilinger@debian.org> | ||
8 | * | ||
9 | * This driver is partly based on the ALPS driver, which is: | ||
10 | * | ||
11 | * Copyright (c) 2003 Neil Brown <neilb@cse.unsw.edu.au> | ||
12 | * Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com> | ||
13 | * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru> | ||
14 | * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz> | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License version 2 as | ||
18 | * published by the Free Software Foundation. | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | * The spec from ALPS is available from | ||
23 | * <http://wiki.laptop.org/go/Touch_Pad/Tablet>. It refers to this | ||
24 | * device as HGPK (Hybrid GS, PT, and Keymatrix). | ||
25 | * | ||
26 | * The earliest versions of the device had simultaneous reporting; that | ||
27 | * was removed. After that, the device used the Advanced Mode GS/PT streaming | ||
28 | * stuff. That turned out to be too buggy to support, so we've finally | ||
29 | * switched to Mouse Mode (which utilizes only the center 1/3 of the touchpad). | ||
30 | */ | ||
31 | |||
32 | #define DEBUG | ||
33 | #include <linux/input.h> | ||
34 | #include <linux/serio.h> | ||
35 | #include <linux/libps2.h> | ||
36 | #include <linux/delay.h> | ||
37 | #include <asm/olpc.h> | ||
38 | |||
39 | #include "psmouse.h" | ||
40 | #include "hgpk.h" | ||
41 | |||
42 | static int tpdebug; | ||
43 | module_param(tpdebug, int, 0644); | ||
44 | MODULE_PARM_DESC(tpdebug, "enable debugging, dumping packets to KERN_DEBUG."); | ||
45 | |||
46 | static int recalib_delta = 100; | ||
47 | module_param(recalib_delta, int, 0644); | ||
48 | MODULE_PARM_DESC(recalib_delta, | ||
49 | "packets containing a delta this large will cause a recalibration."); | ||
50 | |||
51 | /* | ||
52 | * When the touchpad gets ultra-sensitive, one can keep their finger 1/2" | ||
53 | * above the pad and still have it send packets. This causes a jump cursor | ||
54 | * when one places their finger on the pad. We can probably detect the | ||
55 | * jump as we see a large deltas (>= 100px). In mouse mode, I've been | ||
56 | * unable to even come close to 100px deltas during normal usage, so I think | ||
57 | * this threshold is safe. If a large delta occurs, trigger a recalibration. | ||
58 | */ | ||
59 | static void hgpk_jumpy_hack(struct psmouse *psmouse, int x, int y) | ||
60 | { | ||
61 | struct hgpk_data *priv = psmouse->private; | ||
62 | |||
63 | if (abs(x) > recalib_delta || abs(y) > recalib_delta) { | ||
64 | hgpk_err(psmouse, ">%dpx jump detected (%d,%d)\n", | ||
65 | recalib_delta, x, y); | ||
66 | /* My car gets forty rods to the hogshead and that's the | ||
67 | * way I likes it! */ | ||
68 | psmouse_queue_work(psmouse, &priv->recalib_wq, | ||
69 | msecs_to_jiffies(1000)); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | /* | ||
74 | * We have no idea why this particular hardware bug occurs. The touchpad | ||
75 | * will randomly start spewing packets without anything touching the | ||
76 | * pad. This wouldn't necessarily be bad, but it's indicative of a | ||
77 | * severely miscalibrated pad; attempting to use the touchpad while it's | ||
78 | * spewing means the cursor will jump all over the place, and act "drunk". | ||
79 | * | ||
80 | * The packets that are spewed tend to all have deltas between -2 and 2, and | ||
81 | * the cursor will move around without really going very far. It will | ||
82 | * tend to end up in the same location; if we tally up the changes over | ||
83 | * 100 packets, we end up w/ a final delta of close to 0. This happens | ||
84 | * pretty regularly when the touchpad is spewing, and is pretty hard to | ||
85 | * manually trigger (at least for *my* fingers). So, it makes a perfect | ||
86 | * scheme for detecting spews. | ||
87 | */ | ||
88 | static void hgpk_spewing_hack(struct psmouse *psmouse, | ||
89 | int l, int r, int x, int y) | ||
90 | { | ||
91 | struct hgpk_data *priv = psmouse->private; | ||
92 | |||
93 | /* ignore button press packets; many in a row could trigger | ||
94 | * a false-positive! */ | ||
95 | if (l || r) | ||
96 | return; | ||
97 | |||
98 | priv->x_tally += x; | ||
99 | priv->y_tally += y; | ||
100 | |||
101 | if (++priv->count > 100) { | ||
102 | if (abs(priv->x_tally) < 3 && abs(priv->y_tally) < 3) { | ||
103 | hgpk_dbg(psmouse, "packet spew detected (%d,%d)\n", | ||
104 | priv->x_tally, priv->y_tally); | ||
105 | psmouse_queue_work(psmouse, &priv->recalib_wq, | ||
106 | msecs_to_jiffies(1000)); | ||
107 | } | ||
108 | /* reset every 100 packets */ | ||
109 | priv->count = 0; | ||
110 | priv->x_tally = 0; | ||
111 | priv->y_tally = 0; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | /* | ||
116 | * HGPK Mouse Mode format (standard mouse format, sans middle button) | ||
117 | * | ||
118 | * byte 0: y-over x-over y-neg x-neg 1 0 swr swl | ||
119 | * byte 1: x7 x6 x5 x4 x3 x2 x1 x0 | ||
120 | * byte 2: y7 y6 y5 y4 y3 y2 y1 y0 | ||
121 | * | ||
122 | * swr/swl are the left/right buttons. | ||
123 | * x-neg/y-neg are the x and y delta negative bits | ||
124 | * x-over/y-over are the x and y overflow bits | ||
125 | */ | ||
126 | static int hgpk_validate_byte(unsigned char *packet) | ||
127 | { | ||
128 | return (packet[0] & 0x0C) == 0x08; | ||
129 | } | ||
130 | |||
131 | static void hgpk_process_packet(struct psmouse *psmouse) | ||
132 | { | ||
133 | struct input_dev *dev = psmouse->dev; | ||
134 | unsigned char *packet = psmouse->packet; | ||
135 | int x, y, left, right; | ||
136 | |||
137 | left = packet[0] & 1; | ||
138 | right = (packet[0] >> 1) & 1; | ||
139 | |||
140 | x = packet[1] - ((packet[0] << 4) & 0x100); | ||
141 | y = ((packet[0] << 3) & 0x100) - packet[2]; | ||
142 | |||
143 | hgpk_jumpy_hack(psmouse, x, y); | ||
144 | hgpk_spewing_hack(psmouse, left, right, x, y); | ||
145 | |||
146 | if (tpdebug) | ||
147 | hgpk_dbg(psmouse, "l=%d r=%d x=%d y=%d\n", left, right, x, y); | ||
148 | |||
149 | input_report_key(dev, BTN_LEFT, left); | ||
150 | input_report_key(dev, BTN_RIGHT, right); | ||
151 | |||
152 | input_report_rel(dev, REL_X, x); | ||
153 | input_report_rel(dev, REL_Y, y); | ||
154 | |||
155 | input_sync(dev); | ||
156 | } | ||
157 | |||
158 | static psmouse_ret_t hgpk_process_byte(struct psmouse *psmouse) | ||
159 | { | ||
160 | struct hgpk_data *priv = psmouse->private; | ||
161 | |||
162 | if (hgpk_validate_byte(psmouse->packet)) { | ||
163 | hgpk_dbg(psmouse, "%s: (%d) %02x %02x %02x\n", | ||
164 | __func__, psmouse->pktcnt, psmouse->packet[0], | ||
165 | psmouse->packet[1], psmouse->packet[2]); | ||
166 | return PSMOUSE_BAD_DATA; | ||
167 | } | ||
168 | |||
169 | if (psmouse->pktcnt >= psmouse->pktsize) { | ||
170 | hgpk_process_packet(psmouse); | ||
171 | return PSMOUSE_FULL_PACKET; | ||
172 | } | ||
173 | |||
174 | if (priv->recalib_window) { | ||
175 | if (time_before(jiffies, priv->recalib_window)) { | ||
176 | /* | ||
177 | * ugh, got a packet inside our recalibration | ||
178 | * window, schedule another recalibration. | ||
179 | */ | ||
180 | hgpk_dbg(psmouse, | ||
181 | "packet inside calibration window, " | ||
182 | "queueing another recalibration\n"); | ||
183 | psmouse_queue_work(psmouse, &priv->recalib_wq, | ||
184 | msecs_to_jiffies(1000)); | ||
185 | } | ||
186 | priv->recalib_window = 0; | ||
187 | } | ||
188 | |||
189 | return PSMOUSE_GOOD_DATA; | ||
190 | } | ||
191 | |||
192 | static int hgpk_force_recalibrate(struct psmouse *psmouse) | ||
193 | { | ||
194 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
195 | struct hgpk_data *priv = psmouse->private; | ||
196 | |||
197 | /* C-series touchpads added the recalibrate command */ | ||
198 | if (psmouse->model < HGPK_MODEL_C) | ||
199 | return 0; | ||
200 | |||
201 | /* we don't want to race with the irq handler, nor with resyncs */ | ||
202 | psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); | ||
203 | |||
204 | /* start by resetting the device */ | ||
205 | psmouse_reset(psmouse); | ||
206 | |||
207 | /* send the recalibrate request */ | ||
208 | if (ps2_command(ps2dev, NULL, 0xf5) || | ||
209 | ps2_command(ps2dev, NULL, 0xf5) || | ||
210 | ps2_command(ps2dev, NULL, 0xe6) || | ||
211 | ps2_command(ps2dev, NULL, 0xf5)) { | ||
212 | return -1; | ||
213 | } | ||
214 | |||
215 | /* according to ALPS, 150mS is required for recalibration */ | ||
216 | msleep(150); | ||
217 | |||
218 | /* XXX: If a finger is down during this delay, recalibration will | ||
219 | * detect capacitance incorrectly. This is a hardware bug, and | ||
220 | * we don't have a good way to deal with it. The 2s window stuff | ||
221 | * (below) is our best option for now. | ||
222 | */ | ||
223 | |||
224 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) | ||
225 | return -1; | ||
226 | |||
227 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | ||
228 | |||
229 | /* After we recalibrate, we shouldn't get any packets for 2s. If | ||
230 | * we do, it's likely that someone's finger was on the touchpad. | ||
231 | * If someone's finger *was* on the touchpad, it's probably | ||
232 | * miscalibrated. So, we should schedule another recalibration | ||
233 | */ | ||
234 | priv->recalib_window = jiffies + msecs_to_jiffies(2000); | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | /* | ||
240 | * This kills power to the touchpad; according to ALPS, current consumption | ||
241 | * goes down to 50uA after running this. To turn power back on, we drive | ||
242 | * MS-DAT low. | ||
243 | */ | ||
244 | static int hgpk_toggle_power(struct psmouse *psmouse, int enable) | ||
245 | { | ||
246 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
247 | int timeo; | ||
248 | |||
249 | /* Added on D-series touchpads */ | ||
250 | if (psmouse->model < HGPK_MODEL_D) | ||
251 | return 0; | ||
252 | |||
253 | if (enable) { | ||
254 | psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); | ||
255 | |||
256 | /* | ||
257 | * Sending a byte will drive MS-DAT low; this will wake up | ||
258 | * the controller. Once we get an ACK back from it, it | ||
259 | * means we can continue with the touchpad re-init. ALPS | ||
260 | * tells us that 1s should be long enough, so set that as | ||
261 | * the upper bound. | ||
262 | */ | ||
263 | for (timeo = 20; timeo > 0; timeo--) { | ||
264 | if (!ps2_sendbyte(&psmouse->ps2dev, | ||
265 | PSMOUSE_CMD_DISABLE, 20)) | ||
266 | break; | ||
267 | msleep(50); | ||
268 | } | ||
269 | |||
270 | psmouse_reset(psmouse); | ||
271 | |||
272 | /* should be all set, enable the touchpad */ | ||
273 | ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE); | ||
274 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | ||
275 | |||
276 | } else { | ||
277 | hgpk_dbg(psmouse, "Powering off touchpad.\n"); | ||
278 | psmouse_set_state(psmouse, PSMOUSE_IGNORE); | ||
279 | |||
280 | if (ps2_command(ps2dev, NULL, 0xec) || | ||
281 | ps2_command(ps2dev, NULL, 0xec) || | ||
282 | ps2_command(ps2dev, NULL, 0xea)) { | ||
283 | return -1; | ||
284 | } | ||
285 | |||
286 | /* probably won't see an ACK, the touchpad will be off */ | ||
287 | ps2_sendbyte(&psmouse->ps2dev, 0xec, 20); | ||
288 | } | ||
289 | |||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static int hgpk_poll(struct psmouse *psmouse) | ||
294 | { | ||
295 | /* We can't poll, so always return failure. */ | ||
296 | return -1; | ||
297 | } | ||
298 | |||
299 | static int hgpk_reconnect(struct psmouse *psmouse) | ||
300 | { | ||
301 | /* During suspend/resume the ps2 rails remain powered. We don't want | ||
302 | * to do a reset because it's flush data out of buffers; however, | ||
303 | * earlier prototypes (B1) had some brokenness that required a reset. */ | ||
304 | if (olpc_board_at_least(olpc_board(0xb2))) | ||
305 | if (psmouse->ps2dev.serio->dev.power.power_state.event != | ||
306 | PM_EVENT_ON) | ||
307 | return 0; | ||
308 | |||
309 | psmouse_reset(psmouse); | ||
310 | |||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | static ssize_t hgpk_show_powered(struct psmouse *psmouse, void *data, char *buf) | ||
315 | { | ||
316 | struct hgpk_data *priv = psmouse->private; | ||
317 | |||
318 | return sprintf(buf, "%d\n", priv->powered); | ||
319 | } | ||
320 | |||
321 | static ssize_t hgpk_set_powered(struct psmouse *psmouse, void *data, | ||
322 | const char *buf, size_t count) | ||
323 | { | ||
324 | struct hgpk_data *priv = psmouse->private; | ||
325 | unsigned long value; | ||
326 | int err; | ||
327 | |||
328 | err = strict_strtoul(buf, 10, &value); | ||
329 | if (err || value > 1) | ||
330 | return -EINVAL; | ||
331 | |||
332 | if (value != priv->powered) { | ||
333 | /* | ||
334 | * hgpk_toggle_power will deal w/ state so | ||
335 | * we're not racing w/ irq | ||
336 | */ | ||
337 | err = hgpk_toggle_power(psmouse, value); | ||
338 | if (!err) | ||
339 | priv->powered = value; | ||
340 | } | ||
341 | |||
342 | return err ? err : count; | ||
343 | } | ||
344 | |||
345 | __PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL, | ||
346 | hgpk_show_powered, hgpk_set_powered, 0); | ||
347 | |||
348 | static void hgpk_disconnect(struct psmouse *psmouse) | ||
349 | { | ||
350 | struct hgpk_data *priv = psmouse->private; | ||
351 | |||
352 | device_remove_file(&psmouse->ps2dev.serio->dev, | ||
353 | &psmouse_attr_powered.dattr); | ||
354 | psmouse_reset(psmouse); | ||
355 | kfree(priv); | ||
356 | } | ||
357 | |||
358 | static void hgpk_recalib_work(struct work_struct *work) | ||
359 | { | ||
360 | struct delayed_work *w = container_of(work, struct delayed_work, work); | ||
361 | struct hgpk_data *priv = container_of(w, struct hgpk_data, recalib_wq); | ||
362 | struct psmouse *psmouse = priv->psmouse; | ||
363 | |||
364 | hgpk_dbg(psmouse, "recalibrating touchpad..\n"); | ||
365 | |||
366 | if (hgpk_force_recalibrate(psmouse)) | ||
367 | hgpk_err(psmouse, "recalibration failed!\n"); | ||
368 | } | ||
369 | |||
370 | static int hgpk_register(struct psmouse *psmouse) | ||
371 | { | ||
372 | struct input_dev *dev = psmouse->dev; | ||
373 | int err; | ||
374 | |||
375 | /* unset the things that psmouse-base sets which we don't have */ | ||
376 | __clear_bit(BTN_MIDDLE, dev->keybit); | ||
377 | |||
378 | /* set the things we do have */ | ||
379 | __set_bit(EV_KEY, dev->evbit); | ||
380 | __set_bit(EV_REL, dev->evbit); | ||
381 | |||
382 | __set_bit(REL_X, dev->relbit); | ||
383 | __set_bit(REL_Y, dev->relbit); | ||
384 | |||
385 | __set_bit(BTN_LEFT, dev->keybit); | ||
386 | __set_bit(BTN_RIGHT, dev->keybit); | ||
387 | |||
388 | /* register handlers */ | ||
389 | psmouse->protocol_handler = hgpk_process_byte; | ||
390 | psmouse->poll = hgpk_poll; | ||
391 | psmouse->disconnect = hgpk_disconnect; | ||
392 | psmouse->reconnect = hgpk_reconnect; | ||
393 | psmouse->pktsize = 3; | ||
394 | |||
395 | /* Disable the idle resync. */ | ||
396 | psmouse->resync_time = 0; | ||
397 | /* Reset after a lot of bad bytes. */ | ||
398 | psmouse->resetafter = 1024; | ||
399 | |||
400 | err = device_create_file(&psmouse->ps2dev.serio->dev, | ||
401 | &psmouse_attr_powered.dattr); | ||
402 | if (err) | ||
403 | hgpk_err(psmouse, "Failed to create sysfs attribute\n"); | ||
404 | |||
405 | return err; | ||
406 | } | ||
407 | |||
408 | int hgpk_init(struct psmouse *psmouse) | ||
409 | { | ||
410 | struct hgpk_data *priv; | ||
411 | int err = -ENOMEM; | ||
412 | |||
413 | priv = kzalloc(sizeof(struct hgpk_data), GFP_KERNEL); | ||
414 | if (!priv) | ||
415 | goto alloc_fail; | ||
416 | |||
417 | psmouse->private = priv; | ||
418 | priv->psmouse = psmouse; | ||
419 | priv->powered = 1; | ||
420 | INIT_DELAYED_WORK(&priv->recalib_wq, hgpk_recalib_work); | ||
421 | |||
422 | err = psmouse_reset(psmouse); | ||
423 | if (err) | ||
424 | goto init_fail; | ||
425 | |||
426 | err = hgpk_register(psmouse); | ||
427 | if (err) | ||
428 | goto init_fail; | ||
429 | |||
430 | return 0; | ||
431 | |||
432 | init_fail: | ||
433 | kfree(priv); | ||
434 | alloc_fail: | ||
435 | return err; | ||
436 | } | ||
437 | |||
438 | static enum hgpk_model_t hgpk_get_model(struct psmouse *psmouse) | ||
439 | { | ||
440 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
441 | unsigned char param[3]; | ||
442 | |||
443 | /* E7, E7, E7, E9 gets us a 3 byte identifier */ | ||
444 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || | ||
445 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || | ||
446 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || | ||
447 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { | ||
448 | return -EIO; | ||
449 | } | ||
450 | |||
451 | hgpk_dbg(psmouse, "ID: %02x %02x %02x", param[0], param[1], param[2]); | ||
452 | |||
453 | /* HGPK signature: 0x67, 0x00, 0x<model> */ | ||
454 | if (param[0] != 0x67 || param[1] != 0x00) | ||
455 | return -ENODEV; | ||
456 | |||
457 | hgpk_info(psmouse, "OLPC touchpad revision 0x%x\n", param[2]); | ||
458 | |||
459 | return param[2]; | ||
460 | } | ||
461 | |||
462 | int hgpk_detect(struct psmouse *psmouse, int set_properties) | ||
463 | { | ||
464 | int version; | ||
465 | |||
466 | version = hgpk_get_model(psmouse); | ||
467 | if (version < 0) | ||
468 | return version; | ||
469 | |||
470 | if (set_properties) { | ||
471 | psmouse->vendor = "ALPS"; | ||
472 | psmouse->name = "HGPK"; | ||
473 | psmouse->model = version; | ||
474 | } | ||
475 | |||
476 | return 0; | ||
477 | } | ||
diff --git a/drivers/input/mouse/hgpk.h b/drivers/input/mouse/hgpk.h new file mode 100644 index 000000000000..a4b2a96f5f54 --- /dev/null +++ b/drivers/input/mouse/hgpk.h | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * OLPC HGPK (XO-1) touchpad PS/2 mouse driver | ||
3 | */ | ||
4 | |||
5 | #ifndef _HGPK_H | ||
6 | #define _HGPK_H | ||
7 | |||
8 | enum hgpk_model_t { | ||
9 | HGPK_MODEL_PREA = 0x0a, /* pre-B1s */ | ||
10 | HGPK_MODEL_A = 0x14, /* found on B1s, PT disabled in hardware */ | ||
11 | HGPK_MODEL_B = 0x28, /* B2s, has capacitance issues */ | ||
12 | HGPK_MODEL_C = 0x3c, | ||
13 | HGPK_MODEL_D = 0x50, /* C1, mass production */ | ||
14 | }; | ||
15 | |||
16 | struct hgpk_data { | ||
17 | struct psmouse *psmouse; | ||
18 | int powered; | ||
19 | int count, x_tally, y_tally; /* hardware workaround stuff */ | ||
20 | unsigned long recalib_window; | ||
21 | struct delayed_work recalib_wq; | ||
22 | }; | ||
23 | |||
24 | #define hgpk_dbg(psmouse, format, arg...) \ | ||
25 | dev_dbg(&(psmouse)->ps2dev.serio->dev, format, ## arg) | ||
26 | #define hgpk_err(psmouse, format, arg...) \ | ||
27 | dev_err(&(psmouse)->ps2dev.serio->dev, format, ## arg) | ||
28 | #define hgpk_info(psmouse, format, arg...) \ | ||
29 | dev_info(&(psmouse)->ps2dev.serio->dev, format, ## arg) | ||
30 | #define hgpk_warn(psmouse, format, arg...) \ | ||
31 | dev_warn(&(psmouse)->ps2dev.serio->dev, format, ## arg) | ||
32 | #define hgpk_notice(psmouse, format, arg...) \ | ||
33 | dev_notice(&(psmouse)->ps2dev.serio->dev, format, ## arg) | ||
34 | |||
35 | #ifdef CONFIG_MOUSE_PS2_OLPC | ||
36 | int hgpk_detect(struct psmouse *psmouse, int set_properties); | ||
37 | int hgpk_init(struct psmouse *psmouse); | ||
38 | #else | ||
39 | static inline int hgpk_detect(struct psmouse *psmouse, int set_properties) | ||
40 | { | ||
41 | return -ENODEV; | ||
42 | } | ||
43 | static inline int hgpk_init(struct psmouse *psmouse) | ||
44 | { | ||
45 | return -ENODEV; | ||
46 | } | ||
47 | #endif | ||
48 | |||
49 | #endif | ||
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index 0c5660d28caa..390f1dbb98a4 100644 --- a/drivers/input/mouse/logips2pp.c +++ b/drivers/input/mouse/logips2pp.c | |||
@@ -157,10 +157,8 @@ static ssize_t ps2pp_attr_show_smartscroll(struct psmouse *psmouse, void *data, | |||
157 | static ssize_t ps2pp_attr_set_smartscroll(struct psmouse *psmouse, void *data, const char *buf, size_t count) | 157 | static ssize_t ps2pp_attr_set_smartscroll(struct psmouse *psmouse, void *data, const char *buf, size_t count) |
158 | { | 158 | { |
159 | unsigned long value; | 159 | unsigned long value; |
160 | char *rest; | ||
161 | 160 | ||
162 | value = simple_strtoul(buf, &rest, 10); | 161 | if (strict_strtoul(buf, 10, &value) || value > 1) |
163 | if (*rest || value > 1) | ||
164 | return -EINVAL; | 162 | return -EINVAL; |
165 | 163 | ||
166 | ps2pp_set_smartscroll(psmouse, value); | 164 | ps2pp_set_smartscroll(psmouse, value); |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index f5a6be1d3c46..126e977e199e 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include "synaptics.h" | 25 | #include "synaptics.h" |
26 | #include "logips2pp.h" | 26 | #include "logips2pp.h" |
27 | #include "alps.h" | 27 | #include "alps.h" |
28 | #include "hgpk.h" | ||
28 | #include "lifebook.h" | 29 | #include "lifebook.h" |
29 | #include "trackpoint.h" | 30 | #include "trackpoint.h" |
30 | #include "touchkit_ps2.h" | 31 | #include "touchkit_ps2.h" |
@@ -201,6 +202,12 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse) | |||
201 | return PSMOUSE_FULL_PACKET; | 202 | return PSMOUSE_FULL_PACKET; |
202 | } | 203 | } |
203 | 204 | ||
205 | void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work, | ||
206 | unsigned long delay) | ||
207 | { | ||
208 | queue_delayed_work(kpsmoused_wq, work, delay); | ||
209 | } | ||
210 | |||
204 | /* | 211 | /* |
205 | * __psmouse_set_state() sets new psmouse state and resets all flags. | 212 | * __psmouse_set_state() sets new psmouse state and resets all flags. |
206 | */ | 213 | */ |
@@ -220,7 +227,7 @@ static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_sta | |||
220 | * is not a concern. | 227 | * is not a concern. |
221 | */ | 228 | */ |
222 | 229 | ||
223 | static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) | 230 | void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) |
224 | { | 231 | { |
225 | serio_pause_rx(psmouse->ps2dev.serio); | 232 | serio_pause_rx(psmouse->ps2dev.serio); |
226 | __psmouse_set_state(psmouse, new_state); | 233 | __psmouse_set_state(psmouse, new_state); |
@@ -305,7 +312,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, | |||
305 | psmouse->name, psmouse->phys, psmouse->pktcnt); | 312 | psmouse->name, psmouse->phys, psmouse->pktcnt); |
306 | psmouse->badbyte = psmouse->packet[0]; | 313 | psmouse->badbyte = psmouse->packet[0]; |
307 | __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); | 314 | __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); |
308 | queue_work(kpsmoused_wq, &psmouse->resync_work); | 315 | psmouse_queue_work(psmouse, &psmouse->resync_work, 0); |
309 | goto out; | 316 | goto out; |
310 | } | 317 | } |
311 | 318 | ||
@@ -342,7 +349,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, | |||
342 | time_after(jiffies, psmouse->last + psmouse->resync_time * HZ)) { | 349 | time_after(jiffies, psmouse->last + psmouse->resync_time * HZ)) { |
343 | psmouse->badbyte = psmouse->packet[0]; | 350 | psmouse->badbyte = psmouse->packet[0]; |
344 | __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); | 351 | __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); |
345 | queue_work(kpsmoused_wq, &psmouse->resync_work); | 352 | psmouse_queue_work(psmouse, &psmouse->resync_work, 0); |
346 | goto out; | 353 | goto out; |
347 | } | 354 | } |
348 | 355 | ||
@@ -630,8 +637,20 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
630 | } | 637 | } |
631 | } | 638 | } |
632 | 639 | ||
633 | if (max_proto > PSMOUSE_IMEX) { | 640 | /* |
641 | * Try OLPC HGPK touchpad. | ||
642 | */ | ||
643 | if (max_proto > PSMOUSE_IMEX && | ||
644 | hgpk_detect(psmouse, set_properties) == 0) { | ||
645 | if (!set_properties || hgpk_init(psmouse) == 0) | ||
646 | return PSMOUSE_HGPK; | ||
647 | /* | ||
648 | * Init failed, try basic relative protocols | ||
649 | */ | ||
650 | max_proto = PSMOUSE_IMEX; | ||
651 | } | ||
634 | 652 | ||
653 | if (max_proto > PSMOUSE_IMEX) { | ||
635 | if (genius_detect(psmouse, set_properties) == 0) | 654 | if (genius_detect(psmouse, set_properties) == 0) |
636 | return PSMOUSE_GENPS; | 655 | return PSMOUSE_GENPS; |
637 | 656 | ||
@@ -762,6 +781,14 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
762 | .detect = touchkit_ps2_detect, | 781 | .detect = touchkit_ps2_detect, |
763 | }, | 782 | }, |
764 | #endif | 783 | #endif |
784 | #ifdef CONFIG_MOUSE_PS2_OLPC | ||
785 | { | ||
786 | .type = PSMOUSE_HGPK, | ||
787 | .name = "OLPC HGPK", | ||
788 | .alias = "hgpk", | ||
789 | .detect = hgpk_detect, | ||
790 | }, | ||
791 | #endif | ||
765 | { | 792 | { |
766 | .type = PSMOUSE_CORTRON, | 793 | .type = PSMOUSE_CORTRON, |
767 | .name = "CortronPS/2", | 794 | .name = "CortronPS/2", |
@@ -935,7 +962,7 @@ static int psmouse_poll(struct psmouse *psmouse) | |||
935 | static void psmouse_resync(struct work_struct *work) | 962 | static void psmouse_resync(struct work_struct *work) |
936 | { | 963 | { |
937 | struct psmouse *parent = NULL, *psmouse = | 964 | struct psmouse *parent = NULL, *psmouse = |
938 | container_of(work, struct psmouse, resync_work); | 965 | container_of(work, struct psmouse, resync_work.work); |
939 | struct serio *serio = psmouse->ps2dev.serio; | 966 | struct serio *serio = psmouse->ps2dev.serio; |
940 | psmouse_ret_t rc = PSMOUSE_GOOD_DATA; | 967 | psmouse_ret_t rc = PSMOUSE_GOOD_DATA; |
941 | int failed = 0, enabled = 0; | 968 | int failed = 0, enabled = 0; |
@@ -1194,7 +1221,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
1194 | goto err_free; | 1221 | goto err_free; |
1195 | 1222 | ||
1196 | ps2_init(&psmouse->ps2dev, serio); | 1223 | ps2_init(&psmouse->ps2dev, serio); |
1197 | INIT_WORK(&psmouse->resync_work, psmouse_resync); | 1224 | INIT_DELAYED_WORK(&psmouse->resync_work, psmouse_resync); |
1198 | psmouse->dev = input_dev; | 1225 | psmouse->dev = input_dev; |
1199 | snprintf(psmouse->phys, sizeof(psmouse->phys), "%s/input0", serio->phys); | 1226 | snprintf(psmouse->phys, sizeof(psmouse->phys), "%s/input0", serio->phys); |
1200 | 1227 | ||
@@ -1395,25 +1422,29 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev | |||
1395 | 1422 | ||
1396 | psmouse = serio_get_drvdata(serio); | 1423 | psmouse = serio_get_drvdata(serio); |
1397 | 1424 | ||
1398 | if (psmouse->state == PSMOUSE_IGNORE) { | 1425 | if (attr->protect) { |
1399 | retval = -ENODEV; | 1426 | if (psmouse->state == PSMOUSE_IGNORE) { |
1400 | goto out_unlock; | 1427 | retval = -ENODEV; |
1401 | } | 1428 | goto out_unlock; |
1429 | } | ||
1402 | 1430 | ||
1403 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { | 1431 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { |
1404 | parent = serio_get_drvdata(serio->parent); | 1432 | parent = serio_get_drvdata(serio->parent); |
1405 | psmouse_deactivate(parent); | 1433 | psmouse_deactivate(parent); |
1406 | } | 1434 | } |
1407 | 1435 | ||
1408 | psmouse_deactivate(psmouse); | 1436 | psmouse_deactivate(psmouse); |
1437 | } | ||
1409 | 1438 | ||
1410 | retval = attr->set(psmouse, attr->data, buf, count); | 1439 | retval = attr->set(psmouse, attr->data, buf, count); |
1411 | 1440 | ||
1412 | if (retval != -ENODEV) | 1441 | if (attr->protect) { |
1413 | psmouse_activate(psmouse); | 1442 | if (retval != -ENODEV) |
1443 | psmouse_activate(psmouse); | ||
1414 | 1444 | ||
1415 | if (parent) | 1445 | if (parent) |
1416 | psmouse_activate(parent); | 1446 | psmouse_activate(parent); |
1447 | } | ||
1417 | 1448 | ||
1418 | out_unlock: | 1449 | out_unlock: |
1419 | mutex_unlock(&psmouse_mutex); | 1450 | mutex_unlock(&psmouse_mutex); |
@@ -1433,10 +1464,8 @@ static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const | |||
1433 | { | 1464 | { |
1434 | unsigned int *field = (unsigned int *)((char *)psmouse + (size_t)offset); | 1465 | unsigned int *field = (unsigned int *)((char *)psmouse + (size_t)offset); |
1435 | unsigned long value; | 1466 | unsigned long value; |
1436 | char *rest; | ||
1437 | 1467 | ||
1438 | value = simple_strtoul(buf, &rest, 10); | 1468 | if (strict_strtoul(buf, 10, &value)) |
1439 | if (*rest) | ||
1440 | return -EINVAL; | 1469 | return -EINVAL; |
1441 | 1470 | ||
1442 | if ((unsigned int)value != value) | 1471 | if ((unsigned int)value != value) |
@@ -1549,10 +1578,8 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co | |||
1549 | static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const char *buf, size_t count) | 1578 | static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const char *buf, size_t count) |
1550 | { | 1579 | { |
1551 | unsigned long value; | 1580 | unsigned long value; |
1552 | char *rest; | ||
1553 | 1581 | ||
1554 | value = simple_strtoul(buf, &rest, 10); | 1582 | if (strict_strtoul(buf, 10, &value)) |
1555 | if (*rest) | ||
1556 | return -EINVAL; | 1583 | return -EINVAL; |
1557 | 1584 | ||
1558 | psmouse->set_rate(psmouse, value); | 1585 | psmouse->set_rate(psmouse, value); |
@@ -1562,10 +1589,8 @@ static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const | |||
1562 | static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, void *data, const char *buf, size_t count) | 1589 | static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, void *data, const char *buf, size_t count) |
1563 | { | 1590 | { |
1564 | unsigned long value; | 1591 | unsigned long value; |
1565 | char *rest; | ||
1566 | 1592 | ||
1567 | value = simple_strtoul(buf, &rest, 10); | 1593 | if (strict_strtoul(buf, 10, &value)) |
1568 | if (*rest) | ||
1569 | return -EINVAL; | 1594 | return -EINVAL; |
1570 | 1595 | ||
1571 | psmouse->set_resolution(psmouse, value); | 1596 | psmouse->set_resolution(psmouse, value); |
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index 1317bdd8cc7c..8b608a1cdd12 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h | |||
@@ -39,7 +39,7 @@ struct psmouse { | |||
39 | void *private; | 39 | void *private; |
40 | struct input_dev *dev; | 40 | struct input_dev *dev; |
41 | struct ps2dev ps2dev; | 41 | struct ps2dev ps2dev; |
42 | struct work_struct resync_work; | 42 | struct delayed_work resync_work; |
43 | char *vendor; | 43 | char *vendor; |
44 | char *name; | 44 | char *name; |
45 | unsigned char packet[8]; | 45 | unsigned char packet[8]; |
@@ -89,20 +89,24 @@ enum psmouse_type { | |||
89 | PSMOUSE_TRACKPOINT, | 89 | PSMOUSE_TRACKPOINT, |
90 | PSMOUSE_TOUCHKIT_PS2, | 90 | PSMOUSE_TOUCHKIT_PS2, |
91 | PSMOUSE_CORTRON, | 91 | PSMOUSE_CORTRON, |
92 | PSMOUSE_HGPK, | ||
92 | PSMOUSE_AUTO /* This one should always be last */ | 93 | PSMOUSE_AUTO /* This one should always be last */ |
93 | }; | 94 | }; |
94 | 95 | ||
96 | void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work, | ||
97 | unsigned long delay); | ||
95 | int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command); | 98 | int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command); |
96 | int psmouse_reset(struct psmouse *psmouse); | 99 | int psmouse_reset(struct psmouse *psmouse); |
100 | void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state); | ||
97 | void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution); | 101 | void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution); |
98 | 102 | ||
99 | |||
100 | struct psmouse_attribute { | 103 | struct psmouse_attribute { |
101 | struct device_attribute dattr; | 104 | struct device_attribute dattr; |
102 | void *data; | 105 | void *data; |
103 | ssize_t (*show)(struct psmouse *psmouse, void *data, char *buf); | 106 | ssize_t (*show)(struct psmouse *psmouse, void *data, char *buf); |
104 | ssize_t (*set)(struct psmouse *psmouse, void *data, | 107 | ssize_t (*set)(struct psmouse *psmouse, void *data, |
105 | const char *buf, size_t count); | 108 | const char *buf, size_t count); |
109 | int protect; | ||
106 | }; | 110 | }; |
107 | #define to_psmouse_attr(a) container_of((a), struct psmouse_attribute, dattr) | 111 | #define to_psmouse_attr(a) container_of((a), struct psmouse_attribute, dattr) |
108 | 112 | ||
@@ -111,7 +115,7 @@ ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *at | |||
111 | ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *attr, | 115 | ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *attr, |
112 | const char *buf, size_t count); | 116 | const char *buf, size_t count); |
113 | 117 | ||
114 | #define PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set) \ | 118 | #define __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, _protect) \ |
115 | static ssize_t _show(struct psmouse *, void *data, char *); \ | 119 | static ssize_t _show(struct psmouse *, void *data, char *); \ |
116 | static ssize_t _set(struct psmouse *, void *data, const char *, size_t); \ | 120 | static ssize_t _set(struct psmouse *, void *data, const char *, size_t); \ |
117 | static struct psmouse_attribute psmouse_attr_##_name = { \ | 121 | static struct psmouse_attribute psmouse_attr_##_name = { \ |
@@ -126,6 +130,10 @@ static struct psmouse_attribute psmouse_attr_##_name = { \ | |||
126 | .data = _data, \ | 130 | .data = _data, \ |
127 | .show = _show, \ | 131 | .show = _show, \ |
128 | .set = _set, \ | 132 | .set = _set, \ |
133 | .protect = _protect, \ | ||
129 | } | 134 | } |
130 | 135 | ||
136 | #define PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set) \ | ||
137 | __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, 1) | ||
138 | |||
131 | #endif /* _PSMOUSE_H */ | 139 | #endif /* _PSMOUSE_H */ |
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c index 26b845fc186a..e68c814c4361 100644 --- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c | |||
@@ -89,10 +89,8 @@ static ssize_t trackpoint_set_int_attr(struct psmouse *psmouse, void *data, | |||
89 | struct trackpoint_attr_data *attr = data; | 89 | struct trackpoint_attr_data *attr = data; |
90 | unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset); | 90 | unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset); |
91 | unsigned long value; | 91 | unsigned long value; |
92 | char *rest; | ||
93 | 92 | ||
94 | value = simple_strtoul(buf, &rest, 10); | 93 | if (strict_strtoul(buf, 10, &value) || value > 255) |
95 | if (*rest || value > 255) | ||
96 | return -EINVAL; | 94 | return -EINVAL; |
97 | 95 | ||
98 | *field = value; | 96 | *field = value; |
@@ -117,10 +115,8 @@ static ssize_t trackpoint_set_bit_attr(struct psmouse *psmouse, void *data, | |||
117 | struct trackpoint_attr_data *attr = data; | 115 | struct trackpoint_attr_data *attr = data; |
118 | unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset); | 116 | unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset); |
119 | unsigned long value; | 117 | unsigned long value; |
120 | char *rest; | ||
121 | 118 | ||
122 | value = simple_strtoul(buf, &rest, 10); | 119 | if (strict_strtoul(buf, 10, &value) || value > 1) |
123 | if (*rest || value > 1) | ||
124 | return -EINVAL; | 120 | return -EINVAL; |
125 | 121 | ||
126 | if (attr->inverted) | 122 | if (attr->inverted) |
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 5aafe24984c5..a321aea2c7b5 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
@@ -322,6 +322,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { | |||
322 | DMI_MATCH(DMI_PRODUCT_NAME, "N34AS6"), | 322 | DMI_MATCH(DMI_PRODUCT_NAME, "N34AS6"), |
323 | }, | 323 | }, |
324 | }, | 324 | }, |
325 | { | ||
326 | .ident = "IBM 2656", | ||
327 | .matches = { | ||
328 | DMI_MATCH(DMI_SYS_VENDOR, "IBM"), | ||
329 | DMI_MATCH(DMI_PRODUCT_NAME, "2656"), | ||
330 | }, | ||
331 | }, | ||
325 | { } | 332 | { } |
326 | }; | 333 | }; |
327 | 334 | ||
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index c9397c8ee97e..470770c09260 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c | |||
@@ -373,6 +373,12 @@ static struct serio_device_id serio_raw_serio_ids[] = { | |||
373 | .id = SERIO_ANY, | 373 | .id = SERIO_ANY, |
374 | .extra = SERIO_ANY, | 374 | .extra = SERIO_ANY, |
375 | }, | 375 | }, |
376 | { | ||
377 | .type = SERIO_8042_XL, | ||
378 | .proto = SERIO_ANY, | ||
379 | .id = SERIO_ANY, | ||
380 | .extra = SERIO_ANY, | ||
381 | }, | ||
376 | { 0 } | 382 | { 0 } |
377 | }; | 383 | }; |
378 | 384 | ||
diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c index 8f037a1d44a6..e53c838f1866 100644 --- a/drivers/input/tablet/aiptek.c +++ b/drivers/input/tablet/aiptek.c | |||
@@ -1202,16 +1202,22 @@ static ssize_t | |||
1202 | store_tabletXtilt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 1202 | store_tabletXtilt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1203 | { | 1203 | { |
1204 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1204 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1205 | int x; | 1205 | long x; |
1206 | |||
1207 | if (strict_strtol(buf, 10, &x)) { | ||
1208 | size_t len = buf[count - 1] == '\n' ? count - 1 : count; | ||
1209 | |||
1210 | if (strncmp(buf, "disable", len)) | ||
1211 | return -EINVAL; | ||
1206 | 1212 | ||
1207 | if (strcmp(buf, "disable") == 0) { | ||
1208 | aiptek->newSetting.xTilt = AIPTEK_TILT_DISABLE; | 1213 | aiptek->newSetting.xTilt = AIPTEK_TILT_DISABLE; |
1209 | } else { | 1214 | } else { |
1210 | x = (int)simple_strtol(buf, NULL, 10); | 1215 | if (x < AIPTEK_TILT_MIN || x > AIPTEK_TILT_MAX) |
1211 | if (x >= AIPTEK_TILT_MIN && x <= AIPTEK_TILT_MAX) { | 1216 | return -EINVAL; |
1212 | aiptek->newSetting.xTilt = x; | 1217 | |
1213 | } | 1218 | aiptek->newSetting.xTilt = x; |
1214 | } | 1219 | } |
1220 | |||
1215 | return count; | 1221 | return count; |
1216 | } | 1222 | } |
1217 | 1223 | ||
@@ -1238,16 +1244,22 @@ static ssize_t | |||
1238 | store_tabletYtilt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 1244 | store_tabletYtilt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1239 | { | 1245 | { |
1240 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1246 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1241 | int y; | 1247 | long y; |
1248 | |||
1249 | if (strict_strtol(buf, 10, &y)) { | ||
1250 | size_t len = buf[count - 1] == '\n' ? count - 1 : count; | ||
1251 | |||
1252 | if (strncmp(buf, "disable", len)) | ||
1253 | return -EINVAL; | ||
1242 | 1254 | ||
1243 | if (strcmp(buf, "disable") == 0) { | ||
1244 | aiptek->newSetting.yTilt = AIPTEK_TILT_DISABLE; | 1255 | aiptek->newSetting.yTilt = AIPTEK_TILT_DISABLE; |
1245 | } else { | 1256 | } else { |
1246 | y = (int)simple_strtol(buf, NULL, 10); | 1257 | if (y < AIPTEK_TILT_MIN || y > AIPTEK_TILT_MAX) |
1247 | if (y >= AIPTEK_TILT_MIN && y <= AIPTEK_TILT_MAX) { | 1258 | return -EINVAL; |
1248 | aiptek->newSetting.yTilt = y; | 1259 | |
1249 | } | 1260 | aiptek->newSetting.yTilt = y; |
1250 | } | 1261 | } |
1262 | |||
1251 | return count; | 1263 | return count; |
1252 | } | 1264 | } |
1253 | 1265 | ||
@@ -1269,8 +1281,12 @@ static ssize_t | |||
1269 | store_tabletJitterDelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 1281 | store_tabletJitterDelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1270 | { | 1282 | { |
1271 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1283 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1284 | long j; | ||
1285 | |||
1286 | if (strict_strtol(buf, 10, &j)) | ||
1287 | return -EINVAL; | ||
1272 | 1288 | ||
1273 | aiptek->newSetting.jitterDelay = (int)simple_strtol(buf, NULL, 10); | 1289 | aiptek->newSetting.jitterDelay = (int)j; |
1274 | return count; | 1290 | return count; |
1275 | } | 1291 | } |
1276 | 1292 | ||
@@ -1294,8 +1310,12 @@ static ssize_t | |||
1294 | store_tabletProgrammableDelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 1310 | store_tabletProgrammableDelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1295 | { | 1311 | { |
1296 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1312 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1313 | long d; | ||
1297 | 1314 | ||
1298 | aiptek->newSetting.programmableDelay = (int)simple_strtol(buf, NULL, 10); | 1315 | if (strict_strtol(buf, 10, &d)) |
1316 | return -EINVAL; | ||
1317 | |||
1318 | aiptek->newSetting.programmableDelay = (int)d; | ||
1299 | return count; | 1319 | return count; |
1300 | } | 1320 | } |
1301 | 1321 | ||
@@ -1541,8 +1561,11 @@ static ssize_t | |||
1541 | store_tabletWheel(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 1561 | store_tabletWheel(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1542 | { | 1562 | { |
1543 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1563 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1564 | long w; | ||
1565 | |||
1566 | if (strict_strtol(buf, 10, &w)) return -EINVAL; | ||
1544 | 1567 | ||
1545 | aiptek->newSetting.wheel = (int)simple_strtol(buf, NULL, 10); | 1568 | aiptek->newSetting.wheel = (int)w; |
1546 | return count; | 1569 | return count; |
1547 | } | 1570 | } |
1548 | 1571 | ||
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 8583c766d565..b9b7fc6ff1eb 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c | |||
@@ -69,6 +69,17 @@ struct ts_event { | |||
69 | int ignore; | 69 | int ignore; |
70 | }; | 70 | }; |
71 | 71 | ||
72 | /* | ||
73 | * We allocate this separately to avoid cache line sharing issues when | ||
74 | * driver is used with DMA-based SPI controllers (like atmel_spi) on | ||
75 | * systems where main memory is not DMA-coherent (most non-x86 boards). | ||
76 | */ | ||
77 | struct ads7846_packet { | ||
78 | u8 read_x, read_y, read_z1, read_z2, pwrdown; | ||
79 | u16 dummy; /* for the pwrdown read */ | ||
80 | struct ts_event tc; | ||
81 | }; | ||
82 | |||
72 | struct ads7846 { | 83 | struct ads7846 { |
73 | struct input_dev *input; | 84 | struct input_dev *input; |
74 | char phys[32]; | 85 | char phys[32]; |
@@ -86,9 +97,7 @@ struct ads7846 { | |||
86 | u16 x_plate_ohms; | 97 | u16 x_plate_ohms; |
87 | u16 pressure_max; | 98 | u16 pressure_max; |
88 | 99 | ||
89 | u8 read_x, read_y, read_z1, read_z2, pwrdown; | 100 | struct ads7846_packet *packet; |
90 | u16 dummy; /* for the pwrdown read */ | ||
91 | struct ts_event tc; | ||
92 | 101 | ||
93 | struct spi_transfer xfer[18]; | 102 | struct spi_transfer xfer[18]; |
94 | struct spi_message msg[5]; | 103 | struct spi_message msg[5]; |
@@ -463,10 +472,11 @@ static ssize_t ads7846_disable_store(struct device *dev, | |||
463 | const char *buf, size_t count) | 472 | const char *buf, size_t count) |
464 | { | 473 | { |
465 | struct ads7846 *ts = dev_get_drvdata(dev); | 474 | struct ads7846 *ts = dev_get_drvdata(dev); |
466 | char *endp; | 475 | long i; |
467 | int i; | 476 | |
477 | if (strict_strtoul(buf, 10, &i)) | ||
478 | return -EINVAL; | ||
468 | 479 | ||
469 | i = simple_strtoul(buf, &endp, 10); | ||
470 | spin_lock_irq(&ts->lock); | 480 | spin_lock_irq(&ts->lock); |
471 | 481 | ||
472 | if (i) | 482 | if (i) |
@@ -512,16 +522,17 @@ static int get_pendown_state(struct ads7846 *ts) | |||
512 | static void ads7846_rx(void *ads) | 522 | static void ads7846_rx(void *ads) |
513 | { | 523 | { |
514 | struct ads7846 *ts = ads; | 524 | struct ads7846 *ts = ads; |
525 | struct ads7846_packet *packet = ts->packet; | ||
515 | unsigned Rt; | 526 | unsigned Rt; |
516 | u16 x, y, z1, z2; | 527 | u16 x, y, z1, z2; |
517 | 528 | ||
518 | /* ads7846_rx_val() did in-place conversion (including byteswap) from | 529 | /* ads7846_rx_val() did in-place conversion (including byteswap) from |
519 | * on-the-wire format as part of debouncing to get stable readings. | 530 | * on-the-wire format as part of debouncing to get stable readings. |
520 | */ | 531 | */ |
521 | x = ts->tc.x; | 532 | x = packet->tc.x; |
522 | y = ts->tc.y; | 533 | y = packet->tc.y; |
523 | z1 = ts->tc.z1; | 534 | z1 = packet->tc.z1; |
524 | z2 = ts->tc.z2; | 535 | z2 = packet->tc.z2; |
525 | 536 | ||
526 | /* range filtering */ | 537 | /* range filtering */ |
527 | if (x == MAX_12BIT) | 538 | if (x == MAX_12BIT) |
@@ -545,10 +556,10 @@ static void ads7846_rx(void *ads) | |||
545 | * the maximum. Don't report it to user space, repeat at least | 556 | * the maximum. Don't report it to user space, repeat at least |
546 | * once more the measurement | 557 | * once more the measurement |
547 | */ | 558 | */ |
548 | if (ts->tc.ignore || Rt > ts->pressure_max) { | 559 | if (packet->tc.ignore || Rt > ts->pressure_max) { |
549 | #ifdef VERBOSE | 560 | #ifdef VERBOSE |
550 | pr_debug("%s: ignored %d pressure %d\n", | 561 | pr_debug("%s: ignored %d pressure %d\n", |
551 | ts->spi->dev.bus_id, ts->tc.ignore, Rt); | 562 | ts->spi->dev.bus_id, packet->tc.ignore, Rt); |
552 | #endif | 563 | #endif |
553 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), | 564 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), |
554 | HRTIMER_MODE_REL); | 565 | HRTIMER_MODE_REL); |
@@ -641,6 +652,7 @@ static int ads7846_no_filter(void *ads, int data_idx, int *val) | |||
641 | static void ads7846_rx_val(void *ads) | 652 | static void ads7846_rx_val(void *ads) |
642 | { | 653 | { |
643 | struct ads7846 *ts = ads; | 654 | struct ads7846 *ts = ads; |
655 | struct ads7846_packet *packet = ts->packet; | ||
644 | struct spi_message *m; | 656 | struct spi_message *m; |
645 | struct spi_transfer *t; | 657 | struct spi_transfer *t; |
646 | int val; | 658 | int val; |
@@ -660,7 +672,7 @@ static void ads7846_rx_val(void *ads) | |||
660 | case ADS7846_FILTER_REPEAT: | 672 | case ADS7846_FILTER_REPEAT: |
661 | break; | 673 | break; |
662 | case ADS7846_FILTER_IGNORE: | 674 | case ADS7846_FILTER_IGNORE: |
663 | ts->tc.ignore = 1; | 675 | packet->tc.ignore = 1; |
664 | /* Last message will contain ads7846_rx() as the | 676 | /* Last message will contain ads7846_rx() as the |
665 | * completion function. | 677 | * completion function. |
666 | */ | 678 | */ |
@@ -668,7 +680,7 @@ static void ads7846_rx_val(void *ads) | |||
668 | break; | 680 | break; |
669 | case ADS7846_FILTER_OK: | 681 | case ADS7846_FILTER_OK: |
670 | *(u16 *)t->rx_buf = val; | 682 | *(u16 *)t->rx_buf = val; |
671 | ts->tc.ignore = 0; | 683 | packet->tc.ignore = 0; |
672 | m = &ts->msg[++ts->msg_idx]; | 684 | m = &ts->msg[++ts->msg_idx]; |
673 | break; | 685 | break; |
674 | default: | 686 | default: |
@@ -773,7 +785,6 @@ static void ads7846_disable(struct ads7846 *ts) | |||
773 | /* we know the chip's in lowpower mode since we always | 785 | /* we know the chip's in lowpower mode since we always |
774 | * leave it that way after every request | 786 | * leave it that way after every request |
775 | */ | 787 | */ |
776 | |||
777 | } | 788 | } |
778 | 789 | ||
779 | /* Must be called with ts->lock held */ | 790 | /* Must be called with ts->lock held */ |
@@ -849,6 +860,7 @@ static int __devinit setup_pendown(struct spi_device *spi, struct ads7846 *ts) | |||
849 | static int __devinit ads7846_probe(struct spi_device *spi) | 860 | static int __devinit ads7846_probe(struct spi_device *spi) |
850 | { | 861 | { |
851 | struct ads7846 *ts; | 862 | struct ads7846 *ts; |
863 | struct ads7846_packet *packet; | ||
852 | struct input_dev *input_dev; | 864 | struct input_dev *input_dev; |
853 | struct ads7846_platform_data *pdata = spi->dev.platform_data; | 865 | struct ads7846_platform_data *pdata = spi->dev.platform_data; |
854 | struct spi_message *m; | 866 | struct spi_message *m; |
@@ -884,14 +896,16 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
884 | return err; | 896 | return err; |
885 | 897 | ||
886 | ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL); | 898 | ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL); |
899 | packet = kzalloc(sizeof(struct ads7846_packet), GFP_KERNEL); | ||
887 | input_dev = input_allocate_device(); | 900 | input_dev = input_allocate_device(); |
888 | if (!ts || !input_dev) { | 901 | if (!ts || !packet || !input_dev) { |
889 | err = -ENOMEM; | 902 | err = -ENOMEM; |
890 | goto err_free_mem; | 903 | goto err_free_mem; |
891 | } | 904 | } |
892 | 905 | ||
893 | dev_set_drvdata(&spi->dev, ts); | 906 | dev_set_drvdata(&spi->dev, ts); |
894 | 907 | ||
908 | ts->packet = packet; | ||
895 | ts->spi = spi; | 909 | ts->spi = spi; |
896 | ts->input = input_dev; | 910 | ts->input = input_dev; |
897 | ts->vref_mv = pdata->vref_mv; | 911 | ts->vref_mv = pdata->vref_mv; |
@@ -963,13 +977,13 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
963 | spi_message_init(m); | 977 | spi_message_init(m); |
964 | 978 | ||
965 | /* y- still on; turn on only y+ (and ADC) */ | 979 | /* y- still on; turn on only y+ (and ADC) */ |
966 | ts->read_y = READ_Y(vref); | 980 | packet->read_y = READ_Y(vref); |
967 | x->tx_buf = &ts->read_y; | 981 | x->tx_buf = &packet->read_y; |
968 | x->len = 1; | 982 | x->len = 1; |
969 | spi_message_add_tail(x, m); | 983 | spi_message_add_tail(x, m); |
970 | 984 | ||
971 | x++; | 985 | x++; |
972 | x->rx_buf = &ts->tc.y; | 986 | x->rx_buf = &packet->tc.y; |
973 | x->len = 2; | 987 | x->len = 2; |
974 | spi_message_add_tail(x, m); | 988 | spi_message_add_tail(x, m); |
975 | 989 | ||
@@ -981,12 +995,12 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
981 | x->delay_usecs = pdata->settle_delay_usecs; | 995 | x->delay_usecs = pdata->settle_delay_usecs; |
982 | 996 | ||
983 | x++; | 997 | x++; |
984 | x->tx_buf = &ts->read_y; | 998 | x->tx_buf = &packet->read_y; |
985 | x->len = 1; | 999 | x->len = 1; |
986 | spi_message_add_tail(x, m); | 1000 | spi_message_add_tail(x, m); |
987 | 1001 | ||
988 | x++; | 1002 | x++; |
989 | x->rx_buf = &ts->tc.y; | 1003 | x->rx_buf = &packet->tc.y; |
990 | x->len = 2; | 1004 | x->len = 2; |
991 | spi_message_add_tail(x, m); | 1005 | spi_message_add_tail(x, m); |
992 | } | 1006 | } |
@@ -999,13 +1013,13 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
999 | 1013 | ||
1000 | /* turn y- off, x+ on, then leave in lowpower */ | 1014 | /* turn y- off, x+ on, then leave in lowpower */ |
1001 | x++; | 1015 | x++; |
1002 | ts->read_x = READ_X(vref); | 1016 | packet->read_x = READ_X(vref); |
1003 | x->tx_buf = &ts->read_x; | 1017 | x->tx_buf = &packet->read_x; |
1004 | x->len = 1; | 1018 | x->len = 1; |
1005 | spi_message_add_tail(x, m); | 1019 | spi_message_add_tail(x, m); |
1006 | 1020 | ||
1007 | x++; | 1021 | x++; |
1008 | x->rx_buf = &ts->tc.x; | 1022 | x->rx_buf = &packet->tc.x; |
1009 | x->len = 2; | 1023 | x->len = 2; |
1010 | spi_message_add_tail(x, m); | 1024 | spi_message_add_tail(x, m); |
1011 | 1025 | ||
@@ -1014,12 +1028,12 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1014 | x->delay_usecs = pdata->settle_delay_usecs; | 1028 | x->delay_usecs = pdata->settle_delay_usecs; |
1015 | 1029 | ||
1016 | x++; | 1030 | x++; |
1017 | x->tx_buf = &ts->read_x; | 1031 | x->tx_buf = &packet->read_x; |
1018 | x->len = 1; | 1032 | x->len = 1; |
1019 | spi_message_add_tail(x, m); | 1033 | spi_message_add_tail(x, m); |
1020 | 1034 | ||
1021 | x++; | 1035 | x++; |
1022 | x->rx_buf = &ts->tc.x; | 1036 | x->rx_buf = &packet->tc.x; |
1023 | x->len = 2; | 1037 | x->len = 2; |
1024 | spi_message_add_tail(x, m); | 1038 | spi_message_add_tail(x, m); |
1025 | } | 1039 | } |
@@ -1033,13 +1047,13 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1033 | spi_message_init(m); | 1047 | spi_message_init(m); |
1034 | 1048 | ||
1035 | x++; | 1049 | x++; |
1036 | ts->read_z1 = READ_Z1(vref); | 1050 | packet->read_z1 = READ_Z1(vref); |
1037 | x->tx_buf = &ts->read_z1; | 1051 | x->tx_buf = &packet->read_z1; |
1038 | x->len = 1; | 1052 | x->len = 1; |
1039 | spi_message_add_tail(x, m); | 1053 | spi_message_add_tail(x, m); |
1040 | 1054 | ||
1041 | x++; | 1055 | x++; |
1042 | x->rx_buf = &ts->tc.z1; | 1056 | x->rx_buf = &packet->tc.z1; |
1043 | x->len = 2; | 1057 | x->len = 2; |
1044 | spi_message_add_tail(x, m); | 1058 | spi_message_add_tail(x, m); |
1045 | 1059 | ||
@@ -1048,12 +1062,12 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1048 | x->delay_usecs = pdata->settle_delay_usecs; | 1062 | x->delay_usecs = pdata->settle_delay_usecs; |
1049 | 1063 | ||
1050 | x++; | 1064 | x++; |
1051 | x->tx_buf = &ts->read_z1; | 1065 | x->tx_buf = &packet->read_z1; |
1052 | x->len = 1; | 1066 | x->len = 1; |
1053 | spi_message_add_tail(x, m); | 1067 | spi_message_add_tail(x, m); |
1054 | 1068 | ||
1055 | x++; | 1069 | x++; |
1056 | x->rx_buf = &ts->tc.z1; | 1070 | x->rx_buf = &packet->tc.z1; |
1057 | x->len = 2; | 1071 | x->len = 2; |
1058 | spi_message_add_tail(x, m); | 1072 | spi_message_add_tail(x, m); |
1059 | } | 1073 | } |
@@ -1065,13 +1079,13 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1065 | spi_message_init(m); | 1079 | spi_message_init(m); |
1066 | 1080 | ||
1067 | x++; | 1081 | x++; |
1068 | ts->read_z2 = READ_Z2(vref); | 1082 | packet->read_z2 = READ_Z2(vref); |
1069 | x->tx_buf = &ts->read_z2; | 1083 | x->tx_buf = &packet->read_z2; |
1070 | x->len = 1; | 1084 | x->len = 1; |
1071 | spi_message_add_tail(x, m); | 1085 | spi_message_add_tail(x, m); |
1072 | 1086 | ||
1073 | x++; | 1087 | x++; |
1074 | x->rx_buf = &ts->tc.z2; | 1088 | x->rx_buf = &packet->tc.z2; |
1075 | x->len = 2; | 1089 | x->len = 2; |
1076 | spi_message_add_tail(x, m); | 1090 | spi_message_add_tail(x, m); |
1077 | 1091 | ||
@@ -1080,12 +1094,12 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1080 | x->delay_usecs = pdata->settle_delay_usecs; | 1094 | x->delay_usecs = pdata->settle_delay_usecs; |
1081 | 1095 | ||
1082 | x++; | 1096 | x++; |
1083 | x->tx_buf = &ts->read_z2; | 1097 | x->tx_buf = &packet->read_z2; |
1084 | x->len = 1; | 1098 | x->len = 1; |
1085 | spi_message_add_tail(x, m); | 1099 | spi_message_add_tail(x, m); |
1086 | 1100 | ||
1087 | x++; | 1101 | x++; |
1088 | x->rx_buf = &ts->tc.z2; | 1102 | x->rx_buf = &packet->tc.z2; |
1089 | x->len = 2; | 1103 | x->len = 2; |
1090 | spi_message_add_tail(x, m); | 1104 | spi_message_add_tail(x, m); |
1091 | } | 1105 | } |
@@ -1099,13 +1113,13 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1099 | spi_message_init(m); | 1113 | spi_message_init(m); |
1100 | 1114 | ||
1101 | x++; | 1115 | x++; |
1102 | ts->pwrdown = PWRDOWN; | 1116 | packet->pwrdown = PWRDOWN; |
1103 | x->tx_buf = &ts->pwrdown; | 1117 | x->tx_buf = &packet->pwrdown; |
1104 | x->len = 1; | 1118 | x->len = 1; |
1105 | spi_message_add_tail(x, m); | 1119 | spi_message_add_tail(x, m); |
1106 | 1120 | ||
1107 | x++; | 1121 | x++; |
1108 | x->rx_buf = &ts->dummy; | 1122 | x->rx_buf = &packet->dummy; |
1109 | x->len = 2; | 1123 | x->len = 2; |
1110 | CS_CHANGE(*x); | 1124 | CS_CHANGE(*x); |
1111 | spi_message_add_tail(x, m); | 1125 | spi_message_add_tail(x, m); |
@@ -1158,6 +1172,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1158 | ts->filter_cleanup(ts->filter_data); | 1172 | ts->filter_cleanup(ts->filter_data); |
1159 | err_free_mem: | 1173 | err_free_mem: |
1160 | input_free_device(input_dev); | 1174 | input_free_device(input_dev); |
1175 | kfree(packet); | ||
1161 | kfree(ts); | 1176 | kfree(ts); |
1162 | return err; | 1177 | return err; |
1163 | } | 1178 | } |
@@ -1183,6 +1198,7 @@ static int __devexit ads7846_remove(struct spi_device *spi) | |||
1183 | if (ts->filter_cleanup) | 1198 | if (ts->filter_cleanup) |
1184 | ts->filter_cleanup(ts->filter_data); | 1199 | ts->filter_cleanup(ts->filter_data); |
1185 | 1200 | ||
1201 | kfree(ts->packet); | ||
1186 | kfree(ts); | 1202 | kfree(ts); |
1187 | 1203 | ||
1188 | dev_dbg(&spi->dev, "unregistered touchscreen\n"); | 1204 | dev_dbg(&spi->dev, "unregistered touchscreen\n"); |
diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index eee126b19e8b..a89a6a8f05e6 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c | |||
@@ -91,6 +91,9 @@ struct atmel_tsadcc { | |||
91 | char phys[32]; | 91 | char phys[32]; |
92 | struct clk *clk; | 92 | struct clk *clk; |
93 | int irq; | 93 | int irq; |
94 | unsigned int prev_absx; | ||
95 | unsigned int prev_absy; | ||
96 | unsigned char bufferedmeasure; | ||
94 | }; | 97 | }; |
95 | 98 | ||
96 | static void __iomem *tsc_base; | 99 | static void __iomem *tsc_base; |
@@ -100,10 +103,9 @@ static void __iomem *tsc_base; | |||
100 | 103 | ||
101 | static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) | 104 | static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) |
102 | { | 105 | { |
103 | struct input_dev *input_dev = ((struct atmel_tsadcc *)dev)->input; | 106 | struct atmel_tsadcc *ts_dev = (struct atmel_tsadcc *)dev; |
107 | struct input_dev *input_dev = ts_dev->input; | ||
104 | 108 | ||
105 | unsigned int absx; | ||
106 | unsigned int absy; | ||
107 | unsigned int status; | 109 | unsigned int status; |
108 | unsigned int reg; | 110 | unsigned int reg; |
109 | 111 | ||
@@ -121,6 +123,7 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) | |||
121 | atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT); | 123 | atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT); |
122 | 124 | ||
123 | input_report_key(input_dev, BTN_TOUCH, 0); | 125 | input_report_key(input_dev, BTN_TOUCH, 0); |
126 | ts_dev->bufferedmeasure = 0; | ||
124 | input_sync(input_dev); | 127 | input_sync(input_dev); |
125 | 128 | ||
126 | } else if (status & ATMEL_TSADCC_PENCNT) { | 129 | } else if (status & ATMEL_TSADCC_PENCNT) { |
@@ -138,16 +141,23 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) | |||
138 | } else if (status & ATMEL_TSADCC_EOC(3)) { | 141 | } else if (status & ATMEL_TSADCC_EOC(3)) { |
139 | /* Conversion finished */ | 142 | /* Conversion finished */ |
140 | 143 | ||
141 | absx = atmel_tsadcc_read(ATMEL_TSADCC_CDR3) << 10; | 144 | if (ts_dev->bufferedmeasure) { |
142 | absx /= atmel_tsadcc_read(ATMEL_TSADCC_CDR2); | 145 | /* Last measurement is always discarded, since it can |
143 | 146 | * be erroneous. | |
144 | absy = atmel_tsadcc_read(ATMEL_TSADCC_CDR1) << 10; | 147 | * Always report previous measurement */ |
145 | absy /= atmel_tsadcc_read(ATMEL_TSADCC_CDR0); | 148 | input_report_abs(input_dev, ABS_X, ts_dev->prev_absx); |
146 | 149 | input_report_abs(input_dev, ABS_Y, ts_dev->prev_absy); | |
147 | input_report_abs(input_dev, ABS_X, absx); | 150 | input_report_key(input_dev, BTN_TOUCH, 1); |
148 | input_report_abs(input_dev, ABS_Y, absy); | 151 | input_sync(input_dev); |
149 | input_report_key(input_dev, BTN_TOUCH, 1); | 152 | } else |
150 | input_sync(input_dev); | 153 | ts_dev->bufferedmeasure = 1; |
154 | |||
155 | /* Now make new measurement */ | ||
156 | ts_dev->prev_absx = atmel_tsadcc_read(ATMEL_TSADCC_CDR3) << 10; | ||
157 | ts_dev->prev_absx /= atmel_tsadcc_read(ATMEL_TSADCC_CDR2); | ||
158 | |||
159 | ts_dev->prev_absy = atmel_tsadcc_read(ATMEL_TSADCC_CDR1) << 10; | ||
160 | ts_dev->prev_absy /= atmel_tsadcc_read(ATMEL_TSADCC_CDR0); | ||
151 | } | 161 | } |
152 | 162 | ||
153 | return IRQ_HANDLED; | 163 | return IRQ_HANDLED; |
@@ -223,6 +233,7 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) | |||
223 | } | 233 | } |
224 | 234 | ||
225 | ts_dev->input = input_dev; | 235 | ts_dev->input = input_dev; |
236 | ts_dev->bufferedmeasure = 0; | ||
226 | 237 | ||
227 | snprintf(ts_dev->phys, sizeof(ts_dev->phys), | 238 | snprintf(ts_dev->phys, sizeof(ts_dev->phys), |
228 | "%s/input0", pdev->dev.bus_id); | 239 | "%s/input0", pdev->dev.bus_id); |
diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c index 37a555f37306..ba648750a8d9 100644 --- a/drivers/input/touchscreen/mainstone-wm97xx.c +++ b/drivers/input/touchscreen/mainstone-wm97xx.c | |||
@@ -3,8 +3,7 @@ | |||
3 | * Wolfson WM97xx AC97 Codecs. | 3 | * Wolfson WM97xx AC97 Codecs. |
4 | * | 4 | * |
5 | * Copyright 2004, 2007 Wolfson Microelectronics PLC. | 5 | * Copyright 2004, 2007 Wolfson Microelectronics PLC. |
6 | * Author: Liam Girdwood | 6 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> |
7 | * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com | ||
8 | * Parts Copyright : Ian Molton <spyro@f2s.com> | 7 | * Parts Copyright : Ian Molton <spyro@f2s.com> |
9 | * Andrew Zabolotny <zap@homelink.ru> | 8 | * Andrew Zabolotny <zap@homelink.ru> |
10 | * | 9 | * |
@@ -296,6 +295,6 @@ module_init(mainstone_wm97xx_init); | |||
296 | module_exit(mainstone_wm97xx_exit); | 295 | module_exit(mainstone_wm97xx_exit); |
297 | 296 | ||
298 | /* Module information */ | 297 | /* Module information */ |
299 | MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>"); | 298 | MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>"); |
300 | MODULE_DESCRIPTION("wm97xx continuous touch driver for mainstone"); | 299 | MODULE_DESCRIPTION("wm97xx continuous touch driver for mainstone"); |
301 | MODULE_LICENSE("GPL"); | 300 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/input/touchscreen/wm9705.c b/drivers/input/touchscreen/wm9705.c index 372efbc694ff..6b5be742c27d 100644 --- a/drivers/input/touchscreen/wm9705.c +++ b/drivers/input/touchscreen/wm9705.c | |||
@@ -2,8 +2,7 @@ | |||
2 | * wm9705.c -- Codec driver for Wolfson WM9705 AC97 Codec. | 2 | * wm9705.c -- Codec driver for Wolfson WM9705 AC97 Codec. |
3 | * | 3 | * |
4 | * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC. | 4 | * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC. |
5 | * Author: Liam Girdwood | 5 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> |
6 | * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com | ||
7 | * Parts Copyright : Ian Molton <spyro@f2s.com> | 6 | * Parts Copyright : Ian Molton <spyro@f2s.com> |
8 | * Andrew Zabolotny <zap@homelink.ru> | 7 | * Andrew Zabolotny <zap@homelink.ru> |
9 | * Russell King <rmk@arm.linux.org.uk> | 8 | * Russell King <rmk@arm.linux.org.uk> |
@@ -347,6 +346,6 @@ struct wm97xx_codec_drv wm9705_codec = { | |||
347 | EXPORT_SYMBOL_GPL(wm9705_codec); | 346 | EXPORT_SYMBOL_GPL(wm9705_codec); |
348 | 347 | ||
349 | /* Module information */ | 348 | /* Module information */ |
350 | MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>"); | 349 | MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>"); |
351 | MODULE_DESCRIPTION("WM9705 Touch Screen Driver"); | 350 | MODULE_DESCRIPTION("WM9705 Touch Screen Driver"); |
352 | MODULE_LICENSE("GPL"); | 351 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/input/touchscreen/wm9712.c b/drivers/input/touchscreen/wm9712.c index c8bb1e7335fc..7490b05c3566 100644 --- a/drivers/input/touchscreen/wm9712.c +++ b/drivers/input/touchscreen/wm9712.c | |||
@@ -2,8 +2,7 @@ | |||
2 | * wm9712.c -- Codec driver for Wolfson WM9712 AC97 Codecs. | 2 | * wm9712.c -- Codec driver for Wolfson WM9712 AC97 Codecs. |
3 | * | 3 | * |
4 | * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC. | 4 | * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC. |
5 | * Author: Liam Girdwood | 5 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> |
6 | * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com | ||
7 | * Parts Copyright : Ian Molton <spyro@f2s.com> | 6 | * Parts Copyright : Ian Molton <spyro@f2s.com> |
8 | * Andrew Zabolotny <zap@homelink.ru> | 7 | * Andrew Zabolotny <zap@homelink.ru> |
9 | * Russell King <rmk@arm.linux.org.uk> | 8 | * Russell King <rmk@arm.linux.org.uk> |
@@ -462,6 +461,6 @@ struct wm97xx_codec_drv wm9712_codec = { | |||
462 | EXPORT_SYMBOL_GPL(wm9712_codec); | 461 | EXPORT_SYMBOL_GPL(wm9712_codec); |
463 | 462 | ||
464 | /* Module information */ | 463 | /* Module information */ |
465 | MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>"); | 464 | MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>"); |
466 | MODULE_DESCRIPTION("WM9712 Touch Screen Driver"); | 465 | MODULE_DESCRIPTION("WM9712 Touch Screen Driver"); |
467 | MODULE_LICENSE("GPL"); | 466 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/input/touchscreen/wm9713.c b/drivers/input/touchscreen/wm9713.c index 781ee83547e6..238b5132712e 100644 --- a/drivers/input/touchscreen/wm9713.c +++ b/drivers/input/touchscreen/wm9713.c | |||
@@ -2,8 +2,7 @@ | |||
2 | * wm9713.c -- Codec touch driver for Wolfson WM9713 AC97 Codec. | 2 | * wm9713.c -- Codec touch driver for Wolfson WM9713 AC97 Codec. |
3 | * | 3 | * |
4 | * Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC. | 4 | * Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC. |
5 | * Author: Liam Girdwood | 5 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> |
6 | * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com | ||
7 | * Parts Copyright : Ian Molton <spyro@f2s.com> | 6 | * Parts Copyright : Ian Molton <spyro@f2s.com> |
8 | * Andrew Zabolotny <zap@homelink.ru> | 7 | * Andrew Zabolotny <zap@homelink.ru> |
9 | * Russell King <rmk@arm.linux.org.uk> | 8 | * Russell King <rmk@arm.linux.org.uk> |
@@ -476,6 +475,6 @@ struct wm97xx_codec_drv wm9713_codec = { | |||
476 | EXPORT_SYMBOL_GPL(wm9713_codec); | 475 | EXPORT_SYMBOL_GPL(wm9713_codec); |
477 | 476 | ||
478 | /* Module information */ | 477 | /* Module information */ |
479 | MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>"); | 478 | MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>"); |
480 | MODULE_DESCRIPTION("WM9713 Touch Screen Driver"); | 479 | MODULE_DESCRIPTION("WM9713 Touch Screen Driver"); |
481 | MODULE_LICENSE("GPL"); | 480 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index d589ab0e3adc..d15aa11d7056 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c | |||
@@ -3,8 +3,7 @@ | |||
3 | * and WM9713 AC97 Codecs. | 3 | * and WM9713 AC97 Codecs. |
4 | * | 4 | * |
5 | * Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC. | 5 | * Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC. |
6 | * Author: Liam Girdwood | 6 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> |
7 | * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com | ||
8 | * Parts Copyright : Ian Molton <spyro@f2s.com> | 7 | * Parts Copyright : Ian Molton <spyro@f2s.com> |
9 | * Andrew Zabolotny <zap@homelink.ru> | 8 | * Andrew Zabolotny <zap@homelink.ru> |
10 | * Russell King <rmk@arm.linux.org.uk> | 9 | * Russell King <rmk@arm.linux.org.uk> |
@@ -824,6 +823,6 @@ module_init(wm97xx_init); | |||
824 | module_exit(wm97xx_exit); | 823 | module_exit(wm97xx_exit); |
825 | 824 | ||
826 | /* Module information */ | 825 | /* Module information */ |
827 | MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>"); | 826 | MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>"); |
828 | MODULE_DESCRIPTION("WM97xx Core - Touch Screen / AUX ADC / GPIO Driver"); | 827 | MODULE_DESCRIPTION("WM97xx Core - Touch Screen / AUX ADC / GPIO Driver"); |
829 | MODULE_LICENSE("GPL"); | 828 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c index 268547dbfbd3..f26c1f9a475b 100644 --- a/drivers/md/faulty.c +++ b/drivers/md/faulty.c | |||
@@ -287,6 +287,8 @@ static int run(mddev_t *mddev) | |||
287 | int i; | 287 | int i; |
288 | 288 | ||
289 | conf_t *conf = kmalloc(sizeof(*conf), GFP_KERNEL); | 289 | conf_t *conf = kmalloc(sizeof(*conf), GFP_KERNEL); |
290 | if (!conf) | ||
291 | return -ENOMEM; | ||
290 | 292 | ||
291 | for (i=0; i<Modes; i++) { | 293 | for (i=0; i<Modes; i++) { |
292 | atomic_set(&conf->counters[i], 0); | 294 | atomic_set(&conf->counters[i], 0); |
diff --git a/drivers/md/linear.c b/drivers/md/linear.c index b9cbee688fae..190147c79e79 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c | |||
@@ -16,16 +16,8 @@ | |||
16 | Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 16 | Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/module.h> | ||
20 | |||
21 | #include <linux/raid/md.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/raid/linear.h> | 19 | #include <linux/raid/linear.h> |
24 | 20 | ||
25 | #define MAJOR_NR MD_MAJOR | ||
26 | #define MD_DRIVER | ||
27 | #define MD_PERSONALITY | ||
28 | |||
29 | /* | 21 | /* |
30 | * find which device holds a particular offset | 22 | * find which device holds a particular offset |
31 | */ | 23 | */ |
@@ -33,16 +25,15 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector) | |||
33 | { | 25 | { |
34 | dev_info_t *hash; | 26 | dev_info_t *hash; |
35 | linear_conf_t *conf = mddev_to_conf(mddev); | 27 | linear_conf_t *conf = mddev_to_conf(mddev); |
36 | sector_t block = sector >> 1; | ||
37 | 28 | ||
38 | /* | 29 | /* |
39 | * sector_div(a,b) returns the remainer and sets a to a/b | 30 | * sector_div(a,b) returns the remainer and sets a to a/b |
40 | */ | 31 | */ |
41 | block >>= conf->preshift; | 32 | sector >>= conf->sector_shift; |
42 | (void)sector_div(block, conf->hash_spacing); | 33 | (void)sector_div(sector, conf->spacing); |
43 | hash = conf->hash_table[block]; | 34 | hash = conf->hash_table[sector]; |
44 | 35 | ||
45 | while ((sector>>1) >= (hash->size + hash->offset)) | 36 | while (sector >= hash->num_sectors + hash->start_sector) |
46 | hash++; | 37 | hash++; |
47 | return hash; | 38 | return hash; |
48 | } | 39 | } |
@@ -65,7 +56,7 @@ static int linear_mergeable_bvec(struct request_queue *q, | |||
65 | sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev); | 56 | sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev); |
66 | 57 | ||
67 | dev0 = which_dev(mddev, sector); | 58 | dev0 = which_dev(mddev, sector); |
68 | maxsectors = (dev0->size << 1) - (sector - (dev0->offset<<1)); | 59 | maxsectors = dev0->num_sectors - (sector - dev0->start_sector); |
69 | 60 | ||
70 | if (maxsectors < bio_sectors) | 61 | if (maxsectors < bio_sectors) |
71 | maxsectors = 0; | 62 | maxsectors = 0; |
@@ -112,8 +103,8 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) | |||
112 | dev_info_t **table; | 103 | dev_info_t **table; |
113 | mdk_rdev_t *rdev; | 104 | mdk_rdev_t *rdev; |
114 | int i, nb_zone, cnt; | 105 | int i, nb_zone, cnt; |
115 | sector_t min_spacing; | 106 | sector_t min_sectors; |
116 | sector_t curr_offset; | 107 | sector_t curr_sector; |
117 | struct list_head *tmp; | 108 | struct list_head *tmp; |
118 | 109 | ||
119 | conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(dev_info_t), | 110 | conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(dev_info_t), |
@@ -145,7 +136,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) | |||
145 | mddev->queue->max_sectors > (PAGE_SIZE>>9)) | 136 | mddev->queue->max_sectors > (PAGE_SIZE>>9)) |
146 | blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); | 137 | blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); |
147 | 138 | ||
148 | disk->size = rdev->size; | 139 | disk->num_sectors = rdev->size * 2; |
149 | conf->array_sectors += rdev->size * 2; | 140 | conf->array_sectors += rdev->size * 2; |
150 | 141 | ||
151 | cnt++; | 142 | cnt++; |
@@ -155,34 +146,34 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) | |||
155 | goto out; | 146 | goto out; |
156 | } | 147 | } |
157 | 148 | ||
158 | min_spacing = conf->array_sectors / 2; | 149 | min_sectors = conf->array_sectors; |
159 | sector_div(min_spacing, PAGE_SIZE/sizeof(struct dev_info *)); | 150 | sector_div(min_sectors, PAGE_SIZE/sizeof(struct dev_info *)); |
160 | 151 | ||
161 | /* min_spacing is the minimum spacing that will fit the hash | 152 | /* min_sectors is the minimum spacing that will fit the hash |
162 | * table in one PAGE. This may be much smaller than needed. | 153 | * table in one PAGE. This may be much smaller than needed. |
163 | * We find the smallest non-terminal set of consecutive devices | 154 | * We find the smallest non-terminal set of consecutive devices |
164 | * that is larger than min_spacing as use the size of that as | 155 | * that is larger than min_sectors and use the size of that as |
165 | * the actual spacing | 156 | * the actual spacing |
166 | */ | 157 | */ |
167 | conf->hash_spacing = conf->array_sectors / 2; | 158 | conf->spacing = conf->array_sectors; |
168 | for (i=0; i < cnt-1 ; i++) { | 159 | for (i=0; i < cnt-1 ; i++) { |
169 | sector_t sz = 0; | 160 | sector_t tmp = 0; |
170 | int j; | 161 | int j; |
171 | for (j = i; j < cnt - 1 && sz < min_spacing; j++) | 162 | for (j = i; j < cnt - 1 && tmp < min_sectors; j++) |
172 | sz += conf->disks[j].size; | 163 | tmp += conf->disks[j].num_sectors; |
173 | if (sz >= min_spacing && sz < conf->hash_spacing) | 164 | if (tmp >= min_sectors && tmp < conf->spacing) |
174 | conf->hash_spacing = sz; | 165 | conf->spacing = tmp; |
175 | } | 166 | } |
176 | 167 | ||
177 | /* hash_spacing may be too large for sector_div to work with, | 168 | /* spacing may be too large for sector_div to work with, |
178 | * so we might need to pre-shift | 169 | * so we might need to pre-shift |
179 | */ | 170 | */ |
180 | conf->preshift = 0; | 171 | conf->sector_shift = 0; |
181 | if (sizeof(sector_t) > sizeof(u32)) { | 172 | if (sizeof(sector_t) > sizeof(u32)) { |
182 | sector_t space = conf->hash_spacing; | 173 | sector_t space = conf->spacing; |
183 | while (space > (sector_t)(~(u32)0)) { | 174 | while (space > (sector_t)(~(u32)0)) { |
184 | space >>= 1; | 175 | space >>= 1; |
185 | conf->preshift++; | 176 | conf->sector_shift++; |
186 | } | 177 | } |
187 | } | 178 | } |
188 | /* | 179 | /* |
@@ -194,9 +185,9 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) | |||
194 | unsigned round; | 185 | unsigned round; |
195 | unsigned long base; | 186 | unsigned long base; |
196 | 187 | ||
197 | sz = conf->array_sectors >> (conf->preshift + 1); | 188 | sz = conf->array_sectors >> conf->sector_shift; |
198 | sz += 1; /* force round-up */ | 189 | sz += 1; /* force round-up */ |
199 | base = conf->hash_spacing >> conf->preshift; | 190 | base = conf->spacing >> conf->sector_shift; |
200 | round = sector_div(sz, base); | 191 | round = sector_div(sz, base); |
201 | nb_zone = sz + (round ? 1 : 0); | 192 | nb_zone = sz + (round ? 1 : 0); |
202 | } | 193 | } |
@@ -211,32 +202,31 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) | |||
211 | * Here we generate the linear hash table | 202 | * Here we generate the linear hash table |
212 | * First calculate the device offsets. | 203 | * First calculate the device offsets. |
213 | */ | 204 | */ |
214 | conf->disks[0].offset = 0; | 205 | conf->disks[0].start_sector = 0; |
215 | for (i = 1; i < raid_disks; i++) | 206 | for (i = 1; i < raid_disks; i++) |
216 | conf->disks[i].offset = | 207 | conf->disks[i].start_sector = |
217 | conf->disks[i-1].offset + | 208 | conf->disks[i-1].start_sector + |
218 | conf->disks[i-1].size; | 209 | conf->disks[i-1].num_sectors; |
219 | 210 | ||
220 | table = conf->hash_table; | 211 | table = conf->hash_table; |
221 | curr_offset = 0; | ||
222 | i = 0; | 212 | i = 0; |
223 | for (curr_offset = 0; | 213 | for (curr_sector = 0; |
224 | curr_offset < conf->array_sectors / 2; | 214 | curr_sector < conf->array_sectors; |
225 | curr_offset += conf->hash_spacing) { | 215 | curr_sector += conf->spacing) { |
226 | 216 | ||
227 | while (i < raid_disks-1 && | 217 | while (i < raid_disks-1 && |
228 | curr_offset >= conf->disks[i+1].offset) | 218 | curr_sector >= conf->disks[i+1].start_sector) |
229 | i++; | 219 | i++; |
230 | 220 | ||
231 | *table ++ = conf->disks + i; | 221 | *table ++ = conf->disks + i; |
232 | } | 222 | } |
233 | 223 | ||
234 | if (conf->preshift) { | 224 | if (conf->sector_shift) { |
235 | conf->hash_spacing >>= conf->preshift; | 225 | conf->spacing >>= conf->sector_shift; |
236 | /* round hash_spacing up so that when we divide by it, | 226 | /* round spacing up so that when we divide by it, |
237 | * we err on the side of "too-low", which is safest. | 227 | * we err on the side of "too-low", which is safest. |
238 | */ | 228 | */ |
239 | conf->hash_spacing++; | 229 | conf->spacing++; |
240 | } | 230 | } |
241 | 231 | ||
242 | BUG_ON(table - conf->hash_table > nb_zone); | 232 | BUG_ON(table - conf->hash_table > nb_zone); |
@@ -317,7 +307,6 @@ static int linear_make_request (struct request_queue *q, struct bio *bio) | |||
317 | const int rw = bio_data_dir(bio); | 307 | const int rw = bio_data_dir(bio); |
318 | mddev_t *mddev = q->queuedata; | 308 | mddev_t *mddev = q->queuedata; |
319 | dev_info_t *tmp_dev; | 309 | dev_info_t *tmp_dev; |
320 | sector_t block; | ||
321 | int cpu; | 310 | int cpu; |
322 | 311 | ||
323 | if (unlikely(bio_barrier(bio))) { | 312 | if (unlikely(bio_barrier(bio))) { |
@@ -332,29 +321,33 @@ static int linear_make_request (struct request_queue *q, struct bio *bio) | |||
332 | part_stat_unlock(); | 321 | part_stat_unlock(); |
333 | 322 | ||
334 | tmp_dev = which_dev(mddev, bio->bi_sector); | 323 | tmp_dev = which_dev(mddev, bio->bi_sector); |
335 | block = bio->bi_sector >> 1; | ||
336 | 324 | ||
337 | if (unlikely(block >= (tmp_dev->size + tmp_dev->offset) | 325 | if (unlikely(bio->bi_sector >= (tmp_dev->num_sectors + |
338 | || block < tmp_dev->offset)) { | 326 | tmp_dev->start_sector) |
327 | || (bio->bi_sector < | ||
328 | tmp_dev->start_sector))) { | ||
339 | char b[BDEVNAME_SIZE]; | 329 | char b[BDEVNAME_SIZE]; |
340 | 330 | ||
341 | printk("linear_make_request: Block %llu out of bounds on " | 331 | printk("linear_make_request: Sector %llu out of bounds on " |
342 | "dev %s size %llu offset %llu\n", | 332 | "dev %s: %llu sectors, offset %llu\n", |
343 | (unsigned long long)block, | 333 | (unsigned long long)bio->bi_sector, |
344 | bdevname(tmp_dev->rdev->bdev, b), | 334 | bdevname(tmp_dev->rdev->bdev, b), |
345 | (unsigned long long)tmp_dev->size, | 335 | (unsigned long long)tmp_dev->num_sectors, |
346 | (unsigned long long)tmp_dev->offset); | 336 | (unsigned long long)tmp_dev->start_sector); |
347 | bio_io_error(bio); | 337 | bio_io_error(bio); |
348 | return 0; | 338 | return 0; |
349 | } | 339 | } |
350 | if (unlikely(bio->bi_sector + (bio->bi_size >> 9) > | 340 | if (unlikely(bio->bi_sector + (bio->bi_size >> 9) > |
351 | (tmp_dev->offset + tmp_dev->size)<<1)) { | 341 | tmp_dev->start_sector + tmp_dev->num_sectors)) { |
352 | /* This bio crosses a device boundary, so we have to | 342 | /* This bio crosses a device boundary, so we have to |
353 | * split it. | 343 | * split it. |
354 | */ | 344 | */ |
355 | struct bio_pair *bp; | 345 | struct bio_pair *bp; |
346 | |||
356 | bp = bio_split(bio, | 347 | bp = bio_split(bio, |
357 | ((tmp_dev->offset + tmp_dev->size)<<1) - bio->bi_sector); | 348 | tmp_dev->start_sector + tmp_dev->num_sectors |
349 | - bio->bi_sector); | ||
350 | |||
358 | if (linear_make_request(q, &bp->bio1)) | 351 | if (linear_make_request(q, &bp->bio1)) |
359 | generic_make_request(&bp->bio1); | 352 | generic_make_request(&bp->bio1); |
360 | if (linear_make_request(q, &bp->bio2)) | 353 | if (linear_make_request(q, &bp->bio2)) |
@@ -364,7 +357,8 @@ static int linear_make_request (struct request_queue *q, struct bio *bio) | |||
364 | } | 357 | } |
365 | 358 | ||
366 | bio->bi_bdev = tmp_dev->rdev->bdev; | 359 | bio->bi_bdev = tmp_dev->rdev->bdev; |
367 | bio->bi_sector = bio->bi_sector - (tmp_dev->offset << 1) + tmp_dev->rdev->data_offset; | 360 | bio->bi_sector = bio->bi_sector - tmp_dev->start_sector |
361 | + tmp_dev->rdev->data_offset; | ||
368 | 362 | ||
369 | return 1; | 363 | return 1; |
370 | } | 364 | } |
@@ -372,29 +366,6 @@ static int linear_make_request (struct request_queue *q, struct bio *bio) | |||
372 | static void linear_status (struct seq_file *seq, mddev_t *mddev) | 366 | static void linear_status (struct seq_file *seq, mddev_t *mddev) |
373 | { | 367 | { |
374 | 368 | ||
375 | #undef MD_DEBUG | ||
376 | #ifdef MD_DEBUG | ||
377 | int j; | ||
378 | linear_conf_t *conf = mddev_to_conf(mddev); | ||
379 | sector_t s = 0; | ||
380 | |||
381 | seq_printf(seq, " "); | ||
382 | for (j = 0; j < mddev->raid_disks; j++) | ||
383 | { | ||
384 | char b[BDEVNAME_SIZE]; | ||
385 | s += conf->smallest_size; | ||
386 | seq_printf(seq, "[%s", | ||
387 | bdevname(conf->hash_table[j][0].rdev->bdev,b)); | ||
388 | |||
389 | while (s > conf->hash_table[j][0].offset + | ||
390 | conf->hash_table[j][0].size) | ||
391 | seq_printf(seq, "/%s] ", | ||
392 | bdevname(conf->hash_table[j][1].rdev->bdev,b)); | ||
393 | else | ||
394 | seq_printf(seq, "] "); | ||
395 | } | ||
396 | seq_printf(seq, "\n"); | ||
397 | #endif | ||
398 | seq_printf(seq, " %dk rounding", mddev->chunk_size/1024); | 369 | seq_printf(seq, " %dk rounding", mddev->chunk_size/1024); |
399 | } | 370 | } |
400 | 371 | ||
diff --git a/drivers/md/md.c b/drivers/md/md.c index 0a3a4bdcd4af..aaa3d465de4e 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -32,31 +32,21 @@ | |||
32 | Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 32 | Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
33 | */ | 33 | */ |
34 | 34 | ||
35 | #include <linux/module.h> | ||
36 | #include <linux/kernel.h> | ||
37 | #include <linux/kthread.h> | 35 | #include <linux/kthread.h> |
38 | #include <linux/linkage.h> | ||
39 | #include <linux/raid/md.h> | 36 | #include <linux/raid/md.h> |
40 | #include <linux/raid/bitmap.h> | 37 | #include <linux/raid/bitmap.h> |
41 | #include <linux/sysctl.h> | 38 | #include <linux/sysctl.h> |
42 | #include <linux/buffer_head.h> /* for invalidate_bdev */ | 39 | #include <linux/buffer_head.h> /* for invalidate_bdev */ |
43 | #include <linux/poll.h> | 40 | #include <linux/poll.h> |
44 | #include <linux/mutex.h> | ||
45 | #include <linux/ctype.h> | 41 | #include <linux/ctype.h> |
46 | #include <linux/freezer.h> | 42 | #include <linux/hdreg.h> |
47 | 43 | #include <linux/proc_fs.h> | |
48 | #include <linux/init.h> | 44 | #include <linux/random.h> |
49 | 45 | #include <linux/reboot.h> | |
50 | #include <linux/file.h> | 46 | #include <linux/file.h> |
51 | 47 | #include <linux/delay.h> | |
52 | #ifdef CONFIG_KMOD | ||
53 | #include <linux/kmod.h> | ||
54 | #endif | ||
55 | |||
56 | #include <asm/unaligned.h> | ||
57 | 48 | ||
58 | #define MAJOR_NR MD_MAJOR | 49 | #define MAJOR_NR MD_MAJOR |
59 | #define MD_DRIVER | ||
60 | 50 | ||
61 | /* 63 partitions with the alternate major number (mdp) */ | 51 | /* 63 partitions with the alternate major number (mdp) */ |
62 | #define MdpMinorShift 6 | 52 | #define MdpMinorShift 6 |
@@ -66,7 +56,7 @@ | |||
66 | 56 | ||
67 | 57 | ||
68 | #ifndef MODULE | 58 | #ifndef MODULE |
69 | static void autostart_arrays (int part); | 59 | static void autostart_arrays(int part); |
70 | #endif | 60 | #endif |
71 | 61 | ||
72 | static LIST_HEAD(pers_list); | 62 | static LIST_HEAD(pers_list); |
@@ -212,7 +202,7 @@ static DEFINE_SPINLOCK(all_mddevs_lock); | |||
212 | ) | 202 | ) |
213 | 203 | ||
214 | 204 | ||
215 | static int md_fail_request (struct request_queue *q, struct bio *bio) | 205 | static int md_fail_request(struct request_queue *q, struct bio *bio) |
216 | { | 206 | { |
217 | bio_io_error(bio); | 207 | bio_io_error(bio); |
218 | return 0; | 208 | return 0; |
@@ -2106,8 +2096,6 @@ rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len) | |||
2106 | 2096 | ||
2107 | if (strict_strtoull(buf, 10, &size) < 0) | 2097 | if (strict_strtoull(buf, 10, &size) < 0) |
2108 | return -EINVAL; | 2098 | return -EINVAL; |
2109 | if (size < my_mddev->size) | ||
2110 | return -EINVAL; | ||
2111 | if (my_mddev->pers && rdev->raid_disk >= 0) { | 2099 | if (my_mddev->pers && rdev->raid_disk >= 0) { |
2112 | if (my_mddev->persistent) { | 2100 | if (my_mddev->persistent) { |
2113 | size = super_types[my_mddev->major_version]. | 2101 | size = super_types[my_mddev->major_version]. |
@@ -2118,9 +2106,9 @@ rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len) | |||
2118 | size = (rdev->bdev->bd_inode->i_size >> 10); | 2106 | size = (rdev->bdev->bd_inode->i_size >> 10); |
2119 | size -= rdev->data_offset/2; | 2107 | size -= rdev->data_offset/2; |
2120 | } | 2108 | } |
2121 | if (size < my_mddev->size) | ||
2122 | return -EINVAL; /* component must fit device */ | ||
2123 | } | 2109 | } |
2110 | if (size < my_mddev->size) | ||
2111 | return -EINVAL; /* component must fit device */ | ||
2124 | 2112 | ||
2125 | rdev->size = size; | 2113 | rdev->size = size; |
2126 | if (size > oldsize && my_mddev->external) { | 2114 | if (size > oldsize && my_mddev->external) { |
@@ -2406,12 +2394,11 @@ safe_delay_store(mddev_t *mddev, const char *cbuf, size_t len) | |||
2406 | int i; | 2394 | int i; |
2407 | unsigned long msec; | 2395 | unsigned long msec; |
2408 | char buf[30]; | 2396 | char buf[30]; |
2409 | char *e; | 2397 | |
2410 | /* remove a period, and count digits after it */ | 2398 | /* remove a period, and count digits after it */ |
2411 | if (len >= sizeof(buf)) | 2399 | if (len >= sizeof(buf)) |
2412 | return -EINVAL; | 2400 | return -EINVAL; |
2413 | strlcpy(buf, cbuf, len); | 2401 | strlcpy(buf, cbuf, sizeof(buf)); |
2414 | buf[len] = 0; | ||
2415 | for (i=0; i<len; i++) { | 2402 | for (i=0; i<len; i++) { |
2416 | if (dot) { | 2403 | if (dot) { |
2417 | if (isdigit(buf[i])) { | 2404 | if (isdigit(buf[i])) { |
@@ -2424,8 +2411,7 @@ safe_delay_store(mddev_t *mddev, const char *cbuf, size_t len) | |||
2424 | buf[i] = 0; | 2411 | buf[i] = 0; |
2425 | } | 2412 | } |
2426 | } | 2413 | } |
2427 | msec = simple_strtoul(buf, &e, 10); | 2414 | if (strict_strtoul(buf, 10, &msec) < 0) |
2428 | if (e == buf || (*e && *e != '\n')) | ||
2429 | return -EINVAL; | 2415 | return -EINVAL; |
2430 | msec = (msec * 1000) / scale; | 2416 | msec = (msec * 1000) / scale; |
2431 | if (msec == 0) | 2417 | if (msec == 0) |
@@ -2727,9 +2713,9 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len) | |||
2727 | break; | 2713 | break; |
2728 | case read_auto: | 2714 | case read_auto: |
2729 | if (mddev->pers) { | 2715 | if (mddev->pers) { |
2730 | if (mddev->ro != 1) | 2716 | if (mddev->ro == 0) |
2731 | err = do_md_stop(mddev, 1, 0); | 2717 | err = do_md_stop(mddev, 1, 0); |
2732 | else | 2718 | else if (mddev->ro == 1) |
2733 | err = restart_array(mddev); | 2719 | err = restart_array(mddev); |
2734 | if (err == 0) { | 2720 | if (err == 0) { |
2735 | mddev->ro = 2; | 2721 | mddev->ro = 2; |
@@ -2945,7 +2931,13 @@ metadata_store(mddev_t *mddev, const char *buf, size_t len) | |||
2945 | { | 2931 | { |
2946 | int major, minor; | 2932 | int major, minor; |
2947 | char *e; | 2933 | char *e; |
2948 | if (!list_empty(&mddev->disks)) | 2934 | /* Changing the details of 'external' metadata is |
2935 | * always permitted. Otherwise there must be | ||
2936 | * no devices attached to the array. | ||
2937 | */ | ||
2938 | if (mddev->external && strncmp(buf, "external:", 9) == 0) | ||
2939 | ; | ||
2940 | else if (!list_empty(&mddev->disks)) | ||
2949 | return -EBUSY; | 2941 | return -EBUSY; |
2950 | 2942 | ||
2951 | if (cmd_match(buf, "none")) { | 2943 | if (cmd_match(buf, "none")) { |
@@ -3527,17 +3519,12 @@ static int do_md_run(mddev_t * mddev) | |||
3527 | return -EINVAL; | 3519 | return -EINVAL; |
3528 | } | 3520 | } |
3529 | /* | 3521 | /* |
3530 | * chunk-size has to be a power of 2 and multiples of PAGE_SIZE | 3522 | * chunk-size has to be a power of 2 |
3531 | */ | 3523 | */ |
3532 | if ( (1 << ffz(~chunk_size)) != chunk_size) { | 3524 | if ( (1 << ffz(~chunk_size)) != chunk_size) { |
3533 | printk(KERN_ERR "chunk_size of %d not valid\n", chunk_size); | 3525 | printk(KERN_ERR "chunk_size of %d not valid\n", chunk_size); |
3534 | return -EINVAL; | 3526 | return -EINVAL; |
3535 | } | 3527 | } |
3536 | if (chunk_size < PAGE_SIZE) { | ||
3537 | printk(KERN_ERR "too small chunk_size: %d < %ld\n", | ||
3538 | chunk_size, PAGE_SIZE); | ||
3539 | return -EINVAL; | ||
3540 | } | ||
3541 | 3528 | ||
3542 | /* devices must have minimum size of one chunk */ | 3529 | /* devices must have minimum size of one chunk */ |
3543 | rdev_for_each(rdev, tmp, mddev) { | 3530 | rdev_for_each(rdev, tmp, mddev) { |
@@ -3555,12 +3542,10 @@ static int do_md_run(mddev_t * mddev) | |||
3555 | } | 3542 | } |
3556 | } | 3543 | } |
3557 | 3544 | ||
3558 | #ifdef CONFIG_KMOD | ||
3559 | if (mddev->level != LEVEL_NONE) | 3545 | if (mddev->level != LEVEL_NONE) |
3560 | request_module("md-level-%d", mddev->level); | 3546 | request_module("md-level-%d", mddev->level); |
3561 | else if (mddev->clevel[0]) | 3547 | else if (mddev->clevel[0]) |
3562 | request_module("md-%s", mddev->clevel); | 3548 | request_module("md-%s", mddev->clevel); |
3563 | #endif | ||
3564 | 3549 | ||
3565 | /* | 3550 | /* |
3566 | * Drop all container device buffers, from now on | 3551 | * Drop all container device buffers, from now on |
@@ -3971,10 +3956,10 @@ static void autorun_array(mddev_t *mddev) | |||
3971 | } | 3956 | } |
3972 | printk("\n"); | 3957 | printk("\n"); |
3973 | 3958 | ||
3974 | err = do_md_run (mddev); | 3959 | err = do_md_run(mddev); |
3975 | if (err) { | 3960 | if (err) { |
3976 | printk(KERN_WARNING "md: do_md_run() returned %d\n", err); | 3961 | printk(KERN_WARNING "md: do_md_run() returned %d\n", err); |
3977 | do_md_stop (mddev, 0, 0); | 3962 | do_md_stop(mddev, 0, 0); |
3978 | } | 3963 | } |
3979 | } | 3964 | } |
3980 | 3965 | ||
@@ -4333,7 +4318,7 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) | |||
4333 | 4318 | ||
4334 | if (!(info->state & (1<<MD_DISK_FAULTY))) { | 4319 | if (!(info->state & (1<<MD_DISK_FAULTY))) { |
4335 | int err; | 4320 | int err; |
4336 | rdev = md_import_device (dev, -1, 0); | 4321 | rdev = md_import_device(dev, -1, 0); |
4337 | if (IS_ERR(rdev)) { | 4322 | if (IS_ERR(rdev)) { |
4338 | printk(KERN_WARNING | 4323 | printk(KERN_WARNING |
4339 | "md: error, md_import_device() returned %ld\n", | 4324 | "md: error, md_import_device() returned %ld\n", |
@@ -4415,7 +4400,7 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev) | |||
4415 | return -EINVAL; | 4400 | return -EINVAL; |
4416 | } | 4401 | } |
4417 | 4402 | ||
4418 | rdev = md_import_device (dev, -1, 0); | 4403 | rdev = md_import_device(dev, -1, 0); |
4419 | if (IS_ERR(rdev)) { | 4404 | if (IS_ERR(rdev)) { |
4420 | printk(KERN_WARNING | 4405 | printk(KERN_WARNING |
4421 | "md: error, md_import_device() returned %ld\n", | 4406 | "md: error, md_import_device() returned %ld\n", |
@@ -4934,11 +4919,11 @@ static int md_ioctl(struct inode *inode, struct file *file, | |||
4934 | goto done_unlock; | 4919 | goto done_unlock; |
4935 | 4920 | ||
4936 | case STOP_ARRAY: | 4921 | case STOP_ARRAY: |
4937 | err = do_md_stop (mddev, 0, 1); | 4922 | err = do_md_stop(mddev, 0, 1); |
4938 | goto done_unlock; | 4923 | goto done_unlock; |
4939 | 4924 | ||
4940 | case STOP_ARRAY_RO: | 4925 | case STOP_ARRAY_RO: |
4941 | err = do_md_stop (mddev, 1, 1); | 4926 | err = do_md_stop(mddev, 1, 1); |
4942 | goto done_unlock; | 4927 | goto done_unlock; |
4943 | 4928 | ||
4944 | } | 4929 | } |
@@ -4987,7 +4972,7 @@ static int md_ioctl(struct inode *inode, struct file *file, | |||
4987 | goto done_unlock; | 4972 | goto done_unlock; |
4988 | 4973 | ||
4989 | case RUN_ARRAY: | 4974 | case RUN_ARRAY: |
4990 | err = do_md_run (mddev); | 4975 | err = do_md_run(mddev); |
4991 | goto done_unlock; | 4976 | goto done_unlock; |
4992 | 4977 | ||
4993 | case SET_BITMAP_FILE: | 4978 | case SET_BITMAP_FILE: |
@@ -5425,11 +5410,11 @@ static int md_seq_show(struct seq_file *seq, void *v) | |||
5425 | seq_printf(seq, " super non-persistent"); | 5410 | seq_printf(seq, " super non-persistent"); |
5426 | 5411 | ||
5427 | if (mddev->pers) { | 5412 | if (mddev->pers) { |
5428 | mddev->pers->status (seq, mddev); | 5413 | mddev->pers->status(seq, mddev); |
5429 | seq_printf(seq, "\n "); | 5414 | seq_printf(seq, "\n "); |
5430 | if (mddev->pers->sync_request) { | 5415 | if (mddev->pers->sync_request) { |
5431 | if (mddev->curr_resync > 2) { | 5416 | if (mddev->curr_resync > 2) { |
5432 | status_resync (seq, mddev); | 5417 | status_resync(seq, mddev); |
5433 | seq_printf(seq, "\n "); | 5418 | seq_printf(seq, "\n "); |
5434 | } else if (mddev->curr_resync == 1 || mddev->curr_resync == 2) | 5419 | } else if (mddev->curr_resync == 1 || mddev->curr_resync == 2) |
5435 | seq_printf(seq, "\tresync=DELAYED\n "); | 5420 | seq_printf(seq, "\tresync=DELAYED\n "); |
@@ -6260,7 +6245,7 @@ static int md_notify_reboot(struct notifier_block *this, | |||
6260 | * appears to still be in use. Hence | 6245 | * appears to still be in use. Hence |
6261 | * the '100'. | 6246 | * the '100'. |
6262 | */ | 6247 | */ |
6263 | do_md_stop (mddev, 1, 100); | 6248 | do_md_stop(mddev, 1, 100); |
6264 | mddev_unlock(mddev); | 6249 | mddev_unlock(mddev); |
6265 | } | 6250 | } |
6266 | /* | 6251 | /* |
@@ -6304,7 +6289,7 @@ static int __init md_init(void) | |||
6304 | raid_table_header = register_sysctl_table(raid_root_table); | 6289 | raid_table_header = register_sysctl_table(raid_root_table); |
6305 | 6290 | ||
6306 | md_geninit(); | 6291 | md_geninit(); |
6307 | return (0); | 6292 | return 0; |
6308 | } | 6293 | } |
6309 | 6294 | ||
6310 | 6295 | ||
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 8bb8794129b3..8744014b9d80 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c | |||
@@ -19,16 +19,7 @@ | |||
19 | * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 19 | * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | #include <linux/raid/multipath.h> | 22 | #include <linux/raid/multipath.h> |
26 | #include <linux/buffer_head.h> | ||
27 | #include <asm/atomic.h> | ||
28 | |||
29 | #define MAJOR_NR MD_MAJOR | ||
30 | #define MD_DRIVER | ||
31 | #define MD_PERSONALITY | ||
32 | 23 | ||
33 | #define MAX_WORK_PER_DISK 128 | 24 | #define MAX_WORK_PER_DISK 128 |
34 | 25 | ||
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 53508a8a981d..8ac6488ad0dc 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c | |||
@@ -18,13 +18,8 @@ | |||
18 | Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 18 | Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/raid/raid0.h> | 21 | #include <linux/raid/raid0.h> |
23 | 22 | ||
24 | #define MAJOR_NR MD_MAJOR | ||
25 | #define MD_DRIVER | ||
26 | #define MD_PERSONALITY | ||
27 | |||
28 | static void raid0_unplug(struct request_queue *q) | 23 | static void raid0_unplug(struct request_queue *q) |
29 | { | 24 | { |
30 | mddev_t *mddev = q->queuedata; | 25 | mddev_t *mddev = q->queuedata; |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index b9764429d856..9c788e2489b1 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -32,6 +32,7 @@ | |||
32 | */ | 32 | */ |
33 | 33 | ||
34 | #include "dm-bio-list.h" | 34 | #include "dm-bio-list.h" |
35 | #include <linux/delay.h> | ||
35 | #include <linux/raid/raid1.h> | 36 | #include <linux/raid/raid1.h> |
36 | #include <linux/raid/bitmap.h> | 37 | #include <linux/raid/bitmap.h> |
37 | 38 | ||
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 8bdc9bfc2887..da5129a24b18 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -19,6 +19,7 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include "dm-bio-list.h" | 21 | #include "dm-bio-list.h" |
22 | #include <linux/delay.h> | ||
22 | #include <linux/raid/raid10.h> | 23 | #include <linux/raid/raid10.h> |
23 | #include <linux/raid/bitmap.h> | 24 | #include <linux/raid/bitmap.h> |
24 | 25 | ||
@@ -2028,8 +2029,9 @@ static int run(mddev_t *mddev) | |||
2028 | int nc, fc, fo; | 2029 | int nc, fc, fo; |
2029 | sector_t stride, size; | 2030 | sector_t stride, size; |
2030 | 2031 | ||
2031 | if (mddev->chunk_size == 0) { | 2032 | if (mddev->chunk_size < PAGE_SIZE) { |
2032 | printk(KERN_ERR "md/raid10: non-zero chunk size required.\n"); | 2033 | printk(KERN_ERR "md/raid10: chunk size must be " |
2034 | "at least PAGE_SIZE(%ld).\n", PAGE_SIZE); | ||
2033 | return -EINVAL; | 2035 | return -EINVAL; |
2034 | } | 2036 | } |
2035 | 2037 | ||
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index ae16794bef20..a36a7435edf5 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -43,12 +43,7 @@ | |||
43 | * miss any bits. | 43 | * miss any bits. |
44 | */ | 44 | */ |
45 | 45 | ||
46 | #include <linux/module.h> | ||
47 | #include <linux/slab.h> | ||
48 | #include <linux/highmem.h> | ||
49 | #include <linux/bitops.h> | ||
50 | #include <linux/kthread.h> | 46 | #include <linux/kthread.h> |
51 | #include <asm/atomic.h> | ||
52 | #include "raid6.h" | 47 | #include "raid6.h" |
53 | 48 | ||
54 | #include <linux/raid/bitmap.h> | 49 | #include <linux/raid/bitmap.h> |
@@ -275,7 +270,7 @@ static int grow_buffers(struct stripe_head *sh, int num) | |||
275 | return 0; | 270 | return 0; |
276 | } | 271 | } |
277 | 272 | ||
278 | static void raid5_build_block (struct stripe_head *sh, int i); | 273 | static void raid5_build_block(struct stripe_head *sh, int i); |
279 | 274 | ||
280 | static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx, int disks) | 275 | static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx, int disks) |
281 | { | 276 | { |
@@ -1151,7 +1146,7 @@ static void raid5_end_read_request(struct bio * bi, int error) | |||
1151 | release_stripe(sh); | 1146 | release_stripe(sh); |
1152 | } | 1147 | } |
1153 | 1148 | ||
1154 | static void raid5_end_write_request (struct bio *bi, int error) | 1149 | static void raid5_end_write_request(struct bio *bi, int error) |
1155 | { | 1150 | { |
1156 | struct stripe_head *sh = bi->bi_private; | 1151 | struct stripe_head *sh = bi->bi_private; |
1157 | raid5_conf_t *conf = sh->raid_conf; | 1152 | raid5_conf_t *conf = sh->raid_conf; |
@@ -1183,7 +1178,7 @@ static void raid5_end_write_request (struct bio *bi, int error) | |||
1183 | 1178 | ||
1184 | static sector_t compute_blocknr(struct stripe_head *sh, int i); | 1179 | static sector_t compute_blocknr(struct stripe_head *sh, int i); |
1185 | 1180 | ||
1186 | static void raid5_build_block (struct stripe_head *sh, int i) | 1181 | static void raid5_build_block(struct stripe_head *sh, int i) |
1187 | { | 1182 | { |
1188 | struct r5dev *dev = &sh->dev[i]; | 1183 | struct r5dev *dev = &sh->dev[i]; |
1189 | 1184 | ||
@@ -1221,10 +1216,10 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) | |||
1221 | set_bit(MD_RECOVERY_INTR, &mddev->recovery); | 1216 | set_bit(MD_RECOVERY_INTR, &mddev->recovery); |
1222 | } | 1217 | } |
1223 | set_bit(Faulty, &rdev->flags); | 1218 | set_bit(Faulty, &rdev->flags); |
1224 | printk (KERN_ALERT | 1219 | printk(KERN_ALERT |
1225 | "raid5: Disk failure on %s, disabling device.\n" | 1220 | "raid5: Disk failure on %s, disabling device.\n" |
1226 | "raid5: Operation continuing on %d devices.\n", | 1221 | "raid5: Operation continuing on %d devices.\n", |
1227 | bdevname(rdev->bdev,b), conf->raid_disks - mddev->degraded); | 1222 | bdevname(rdev->bdev,b), conf->raid_disks - mddev->degraded); |
1228 | } | 1223 | } |
1229 | } | 1224 | } |
1230 | 1225 | ||
@@ -1320,8 +1315,8 @@ static sector_t raid5_compute_sector(sector_t r_sector, unsigned int raid_disks, | |||
1320 | *dd_idx = (*pd_idx + 2 + *dd_idx) % raid_disks; | 1315 | *dd_idx = (*pd_idx + 2 + *dd_idx) % raid_disks; |
1321 | break; | 1316 | break; |
1322 | default: | 1317 | default: |
1323 | printk (KERN_CRIT "raid6: unsupported algorithm %d\n", | 1318 | printk(KERN_CRIT "raid6: unsupported algorithm %d\n", |
1324 | conf->algorithm); | 1319 | conf->algorithm); |
1325 | } | 1320 | } |
1326 | break; | 1321 | break; |
1327 | } | 1322 | } |
@@ -1396,8 +1391,8 @@ static sector_t compute_blocknr(struct stripe_head *sh, int i) | |||
1396 | } | 1391 | } |
1397 | break; | 1392 | break; |
1398 | default: | 1393 | default: |
1399 | printk (KERN_CRIT "raid6: unsupported algorithm %d\n", | 1394 | printk(KERN_CRIT "raid6: unsupported algorithm %d\n", |
1400 | conf->algorithm); | 1395 | conf->algorithm); |
1401 | } | 1396 | } |
1402 | break; | 1397 | break; |
1403 | } | 1398 | } |
@@ -1405,7 +1400,7 @@ static sector_t compute_blocknr(struct stripe_head *sh, int i) | |||
1405 | chunk_number = stripe * data_disks + i; | 1400 | chunk_number = stripe * data_disks + i; |
1406 | r_sector = (sector_t)chunk_number * sectors_per_chunk + chunk_offset; | 1401 | r_sector = (sector_t)chunk_number * sectors_per_chunk + chunk_offset; |
1407 | 1402 | ||
1408 | check = raid5_compute_sector (r_sector, raid_disks, data_disks, &dummy1, &dummy2, conf); | 1403 | check = raid5_compute_sector(r_sector, raid_disks, data_disks, &dummy1, &dummy2, conf); |
1409 | if (check != sh->sector || dummy1 != dd_idx || dummy2 != sh->pd_idx) { | 1404 | if (check != sh->sector || dummy1 != dd_idx || dummy2 != sh->pd_idx) { |
1410 | printk(KERN_ERR "compute_blocknr: map not correct\n"); | 1405 | printk(KERN_ERR "compute_blocknr: map not correct\n"); |
1411 | return 0; | 1406 | return 0; |
@@ -4012,6 +4007,13 @@ static int run(mddev_t *mddev) | |||
4012 | return -EIO; | 4007 | return -EIO; |
4013 | } | 4008 | } |
4014 | 4009 | ||
4010 | if (mddev->chunk_size < PAGE_SIZE) { | ||
4011 | printk(KERN_ERR "md/raid5: chunk_size must be at least " | ||
4012 | "PAGE_SIZE but %d < %ld\n", | ||
4013 | mddev->chunk_size, PAGE_SIZE); | ||
4014 | return -EINVAL; | ||
4015 | } | ||
4016 | |||
4015 | if (mddev->reshape_position != MaxSector) { | 4017 | if (mddev->reshape_position != MaxSector) { |
4016 | /* Check that we can continue the reshape. | 4018 | /* Check that we can continue the reshape. |
4017 | * Currently only disks can change, it must | 4019 | * Currently only disks can change, it must |
@@ -4289,7 +4291,7 @@ static int stop(mddev_t *mddev) | |||
4289 | } | 4291 | } |
4290 | 4292 | ||
4291 | #ifdef DEBUG | 4293 | #ifdef DEBUG |
4292 | static void print_sh (struct seq_file *seq, struct stripe_head *sh) | 4294 | static void print_sh(struct seq_file *seq, struct stripe_head *sh) |
4293 | { | 4295 | { |
4294 | int i; | 4296 | int i; |
4295 | 4297 | ||
@@ -4305,7 +4307,7 @@ static void print_sh (struct seq_file *seq, struct stripe_head *sh) | |||
4305 | seq_printf(seq, "\n"); | 4307 | seq_printf(seq, "\n"); |
4306 | } | 4308 | } |
4307 | 4309 | ||
4308 | static void printall (struct seq_file *seq, raid5_conf_t *conf) | 4310 | static void printall(struct seq_file *seq, raid5_conf_t *conf) |
4309 | { | 4311 | { |
4310 | struct stripe_head *sh; | 4312 | struct stripe_head *sh; |
4311 | struct hlist_node *hn; | 4313 | struct hlist_node *hn; |
@@ -4323,7 +4325,7 @@ static void printall (struct seq_file *seq, raid5_conf_t *conf) | |||
4323 | } | 4325 | } |
4324 | #endif | 4326 | #endif |
4325 | 4327 | ||
4326 | static void status (struct seq_file *seq, mddev_t *mddev) | 4328 | static void status(struct seq_file *seq, mddev_t *mddev) |
4327 | { | 4329 | { |
4328 | raid5_conf_t *conf = (raid5_conf_t *) mddev->private; | 4330 | raid5_conf_t *conf = (raid5_conf_t *) mddev->private; |
4329 | int i; | 4331 | int i; |
diff --git a/drivers/md/raid6.h b/drivers/md/raid6.h index 31cbee71365f..98dcde88470e 100644 --- a/drivers/md/raid6.h +++ b/drivers/md/raid6.h | |||
@@ -18,15 +18,6 @@ | |||
18 | /* Set to 1 to use kernel-wide empty_zero_page */ | 18 | /* Set to 1 to use kernel-wide empty_zero_page */ |
19 | #define RAID6_USE_EMPTY_ZERO_PAGE 0 | 19 | #define RAID6_USE_EMPTY_ZERO_PAGE 0 |
20 | 20 | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/stddef.h> | ||
23 | #include <linux/compiler.h> | ||
24 | #include <linux/types.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/errno.h> | ||
27 | #include <linux/mempool.h> | ||
28 | #include <linux/list.h> | ||
29 | #include <linux/vmalloc.h> | ||
30 | #include <linux/raid/md.h> | 21 | #include <linux/raid/md.h> |
31 | #include <linux/raid/raid5.h> | 22 | #include <linux/raid/raid5.h> |
32 | 23 | ||
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index c325e926de8a..1798b779a25a 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c | |||
@@ -39,10 +39,6 @@ | |||
39 | #include <asm/io.h> | 39 | #include <asm/io.h> |
40 | #include <linux/mutex.h> | 40 | #include <linux/mutex.h> |
41 | 41 | ||
42 | #ifdef CONFIG_KMOD | ||
43 | #include <linux/kmod.h> | ||
44 | #endif | ||
45 | |||
46 | #include "cpia.h" | 42 | #include "cpia.h" |
47 | 43 | ||
48 | static int video_nr = -1; | 44 | static int video_nr = -1; |
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index b26b563a0b0a..9e4f50639975 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c | |||
@@ -45,10 +45,6 @@ | |||
45 | 45 | ||
46 | #include <linux/workqueue.h> | 46 | #include <linux/workqueue.h> |
47 | 47 | ||
48 | #ifdef CONFIG_KMOD | ||
49 | #include <linux/kmod.h> | ||
50 | #endif | ||
51 | |||
52 | #include "usbvision.h" | 48 | #include "usbvision.h" |
53 | 49 | ||
54 | static unsigned int core_debug; | 50 | static unsigned int core_debug; |
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index e10b256aeba4..77aeb39b2750 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c | |||
@@ -69,10 +69,6 @@ | |||
69 | 69 | ||
70 | #include <linux/workqueue.h> | 70 | #include <linux/workqueue.h> |
71 | 71 | ||
72 | #ifdef CONFIG_KMOD | ||
73 | #include <linux/kmod.h> | ||
74 | #endif | ||
75 | |||
76 | #include "usbvision.h" | 72 | #include "usbvision.h" |
77 | #include "usbvision-cards.h" | 73 | #include "usbvision-cards.h" |
78 | 74 | ||
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index 79937d1031fc..928cb4037372 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c | |||
@@ -36,10 +36,6 @@ | |||
36 | #include <asm/system.h> | 36 | #include <asm/system.h> |
37 | #include <asm/pgtable.h> | 37 | #include <asm/pgtable.h> |
38 | 38 | ||
39 | #ifdef CONFIG_KMOD | ||
40 | #include <linux/kmod.h> | ||
41 | #endif | ||
42 | |||
43 | static unsigned int debug; | 39 | static unsigned int debug; |
44 | module_param(debug, int, 0644); | 40 | module_param(debug, int, 0644); |
45 | MODULE_PARM_DESC(debug, "enable debug messages"); | 41 | MODULE_PARM_DESC(debug, "enable debug messages"); |
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 20c3be8617ea..846763d7349e 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c | |||
@@ -60,10 +60,6 @@ | |||
60 | #include <media/v4l2-common.h> | 60 | #include <media/v4l2-common.h> |
61 | #include <media/v4l2-chip-ident.h> | 61 | #include <media/v4l2-chip-ident.h> |
62 | 62 | ||
63 | #ifdef CONFIG_KMOD | ||
64 | #include <linux/kmod.h> | ||
65 | #endif | ||
66 | |||
67 | #include <linux/videodev2.h> | 63 | #include <linux/videodev2.h> |
68 | 64 | ||
69 | MODULE_AUTHOR("Bill Dirks, Justin Schoeman, Gerd Knorr"); | 65 | MODULE_AUTHOR("Bill Dirks, Justin Schoeman, Gerd Knorr"); |
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index 8ec57df1904f..1efc5f3462c6 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c | |||
@@ -30,10 +30,7 @@ | |||
30 | #include <linux/mm.h> | 30 | #include <linux/mm.h> |
31 | #include <linux/time.h> | 31 | #include <linux/time.h> |
32 | #include <linux/version.h> | 32 | #include <linux/version.h> |
33 | |||
34 | #ifdef CONFIG_KMOD | ||
35 | #include <linux/kmod.h> | 33 | #include <linux/kmod.h> |
36 | #endif | ||
37 | 34 | ||
38 | #include <linux/i2c.h> | 35 | #include <linux/i2c.h> |
39 | #include <linux/i2c-algo-sgi.h> | 36 | #include <linux/i2c-algo-sgi.h> |
@@ -4634,7 +4631,7 @@ static int __init vino_module_init(void) | |||
4634 | } | 4631 | } |
4635 | vino_init_stage++; | 4632 | vino_init_stage++; |
4636 | 4633 | ||
4637 | #if defined(CONFIG_KMOD) && defined(MODULE) | 4634 | #ifdef MODULE |
4638 | request_module("saa7191"); | 4635 | request_module("saa7191"); |
4639 | request_module("indycam"); | 4636 | request_module("indycam"); |
4640 | #endif | 4637 | #endif |
diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c index 11edf79f57be..dcd45dbd82dc 100644 --- a/drivers/media/video/w9968cf.c +++ b/drivers/media/video/w9968cf.c | |||
@@ -111,7 +111,7 @@ static int specific_debug = W9968CF_SPECIFIC_DEBUG; | |||
111 | 111 | ||
112 | static unsigned int param_nv[24]; /* number of values per parameter */ | 112 | static unsigned int param_nv[24]; /* number of values per parameter */ |
113 | 113 | ||
114 | #ifdef CONFIG_KMOD | 114 | #ifdef CONFIG_MODULES |
115 | module_param(ovmod_load, bool, 0644); | 115 | module_param(ovmod_load, bool, 0644); |
116 | #endif | 116 | #endif |
117 | module_param(simcams, ushort, 0644); | 117 | module_param(simcams, ushort, 0644); |
@@ -144,7 +144,7 @@ module_param(debug, ushort, 0644); | |||
144 | module_param(specific_debug, bool, 0644); | 144 | module_param(specific_debug, bool, 0644); |
145 | #endif | 145 | #endif |
146 | 146 | ||
147 | #ifdef CONFIG_KMOD | 147 | #ifdef CONFIG_MODULES |
148 | MODULE_PARM_DESC(ovmod_load, | 148 | MODULE_PARM_DESC(ovmod_load, |
149 | "\n<0|1> Automatic 'ovcamchip' module loading." | 149 | "\n<0|1> Automatic 'ovcamchip' module loading." |
150 | "\n0 disabled, 1 enabled." | 150 | "\n0 disabled, 1 enabled." |
diff --git a/drivers/message/i2o/Makefile b/drivers/message/i2o/Makefile index 2c2e39aa1efa..b0982dacfd0a 100644 --- a/drivers/message/i2o/Makefile +++ b/drivers/message/i2o/Makefile | |||
@@ -5,7 +5,7 @@ | |||
5 | # In the future, some of these should be built conditionally. | 5 | # In the future, some of these should be built conditionally. |
6 | # | 6 | # |
7 | 7 | ||
8 | i2o_core-y += iop.o driver.o device.o debug.o pci.o exec-osm.o | 8 | i2o_core-y += iop.o driver.o device.o debug.o pci.o exec-osm.o memory.o |
9 | i2o_bus-y += bus-osm.o | 9 | i2o_bus-y += bus-osm.o |
10 | i2o_config-y += config-osm.o | 10 | i2o_config-y += config-osm.o |
11 | obj-$(CONFIG_I2O) += i2o_core.o | 11 | obj-$(CONFIG_I2O) += i2o_core.o |
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c index 8774c670e668..54c2e9ae23e5 100644 --- a/drivers/message/i2o/device.c +++ b/drivers/message/i2o/device.c | |||
@@ -467,7 +467,7 @@ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, | |||
467 | 467 | ||
468 | res.virt = NULL; | 468 | res.virt = NULL; |
469 | 469 | ||
470 | if (i2o_dma_alloc(dev, &res, reslen, GFP_KERNEL)) | 470 | if (i2o_dma_alloc(dev, &res, reslen)) |
471 | return -ENOMEM; | 471 | return -ENOMEM; |
472 | 472 | ||
473 | msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); | 473 | msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); |
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index 6cbcc21de518..56faef1a1d55 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c | |||
@@ -388,8 +388,8 @@ static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind) | |||
388 | 388 | ||
389 | dev = &c->pdev->dev; | 389 | dev = &c->pdev->dev; |
390 | 390 | ||
391 | if (i2o_dma_realloc | 391 | if (i2o_dma_realloc(dev, &c->dlct, |
392 | (dev, &c->dlct, le32_to_cpu(sb->expected_lct_size), GFP_KERNEL)) | 392 | le32_to_cpu(sb->expected_lct_size))) |
393 | return -ENOMEM; | 393 | return -ENOMEM; |
394 | 394 | ||
395 | msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); | 395 | msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); |
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c index 4238de98d4a6..a3fabdbe6ca6 100644 --- a/drivers/message/i2o/i2o_config.c +++ b/drivers/message/i2o/i2o_config.c | |||
@@ -260,7 +260,7 @@ static int i2o_cfg_swdl(unsigned long arg) | |||
260 | if (IS_ERR(msg)) | 260 | if (IS_ERR(msg)) |
261 | return PTR_ERR(msg); | 261 | return PTR_ERR(msg); |
262 | 262 | ||
263 | if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize, GFP_KERNEL)) { | 263 | if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize)) { |
264 | i2o_msg_nop(c, msg); | 264 | i2o_msg_nop(c, msg); |
265 | return -ENOMEM; | 265 | return -ENOMEM; |
266 | } | 266 | } |
@@ -339,7 +339,7 @@ static int i2o_cfg_swul(unsigned long arg) | |||
339 | if (IS_ERR(msg)) | 339 | if (IS_ERR(msg)) |
340 | return PTR_ERR(msg); | 340 | return PTR_ERR(msg); |
341 | 341 | ||
342 | if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize, GFP_KERNEL)) { | 342 | if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize)) { |
343 | i2o_msg_nop(c, msg); | 343 | i2o_msg_nop(c, msg); |
344 | return -ENOMEM; | 344 | return -ENOMEM; |
345 | } | 345 | } |
@@ -634,9 +634,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, | |||
634 | sg_size = sg[i].flag_count & 0xffffff; | 634 | sg_size = sg[i].flag_count & 0xffffff; |
635 | p = &(sg_list[sg_index]); | 635 | p = &(sg_list[sg_index]); |
636 | /* Allocate memory for the transfer */ | 636 | /* Allocate memory for the transfer */ |
637 | if (i2o_dma_alloc | 637 | if (i2o_dma_alloc(&c->pdev->dev, p, sg_size)) { |
638 | (&c->pdev->dev, p, sg_size, | ||
639 | PCI_DMA_BIDIRECTIONAL)) { | ||
640 | printk(KERN_DEBUG | 638 | printk(KERN_DEBUG |
641 | "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", | 639 | "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", |
642 | c->name, sg_size, i, sg_count); | 640 | c->name, sg_size, i, sg_count); |
@@ -780,12 +778,11 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
780 | u32 size = 0; | 778 | u32 size = 0; |
781 | u32 reply_size = 0; | 779 | u32 reply_size = 0; |
782 | u32 rcode = 0; | 780 | u32 rcode = 0; |
783 | void *sg_list[SG_TABLESIZE]; | 781 | struct i2o_dma sg_list[SG_TABLESIZE]; |
784 | u32 sg_offset = 0; | 782 | u32 sg_offset = 0; |
785 | u32 sg_count = 0; | 783 | u32 sg_count = 0; |
786 | int sg_index = 0; | 784 | int sg_index = 0; |
787 | u32 i = 0; | 785 | u32 i = 0; |
788 | void *p = NULL; | ||
789 | i2o_status_block *sb; | 786 | i2o_status_block *sb; |
790 | struct i2o_message *msg; | 787 | struct i2o_message *msg; |
791 | unsigned int iop; | 788 | unsigned int iop; |
@@ -842,6 +839,7 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
842 | memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE); | 839 | memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE); |
843 | if (sg_offset) { | 840 | if (sg_offset) { |
844 | struct sg_simple_element *sg; | 841 | struct sg_simple_element *sg; |
842 | struct i2o_dma *p; | ||
845 | 843 | ||
846 | if (sg_offset * 4 >= size) { | 844 | if (sg_offset * 4 >= size) { |
847 | rcode = -EFAULT; | 845 | rcode = -EFAULT; |
@@ -871,22 +869,22 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
871 | goto sg_list_cleanup; | 869 | goto sg_list_cleanup; |
872 | } | 870 | } |
873 | sg_size = sg[i].flag_count & 0xffffff; | 871 | sg_size = sg[i].flag_count & 0xffffff; |
872 | p = &(sg_list[sg_index]); | ||
873 | if (i2o_dma_alloc(&c->pdev->dev, p, sg_size)) { | ||
874 | /* Allocate memory for the transfer */ | 874 | /* Allocate memory for the transfer */ |
875 | p = kmalloc(sg_size, GFP_KERNEL); | ||
876 | if (!p) { | ||
877 | printk(KERN_DEBUG | 875 | printk(KERN_DEBUG |
878 | "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", | 876 | "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", |
879 | c->name, sg_size, i, sg_count); | 877 | c->name, sg_size, i, sg_count); |
880 | rcode = -ENOMEM; | 878 | rcode = -ENOMEM; |
881 | goto sg_list_cleanup; | 879 | goto sg_list_cleanup; |
882 | } | 880 | } |
883 | sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame. | 881 | sg_index++; |
884 | /* Copy in the user's SG buffer if necessary */ | 882 | /* Copy in the user's SG buffer if necessary */ |
885 | if (sg[i]. | 883 | if (sg[i]. |
886 | flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) { | 884 | flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) { |
887 | // TODO 64bit fix | 885 | // TODO 64bit fix |
888 | if (copy_from_user | 886 | if (copy_from_user |
889 | (p, (void __user *)sg[i].addr_bus, | 887 | (p->virt, (void __user *)sg[i].addr_bus, |
890 | sg_size)) { | 888 | sg_size)) { |
891 | printk(KERN_DEBUG | 889 | printk(KERN_DEBUG |
892 | "%s: Could not copy SG buf %d FROM user\n", | 890 | "%s: Could not copy SG buf %d FROM user\n", |
@@ -895,8 +893,7 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
895 | goto sg_list_cleanup; | 893 | goto sg_list_cleanup; |
896 | } | 894 | } |
897 | } | 895 | } |
898 | //TODO 64bit fix | 896 | sg[i].addr_bus = p->phys; |
899 | sg[i].addr_bus = virt_to_bus(p); | ||
900 | } | 897 | } |
901 | } | 898 | } |
902 | 899 | ||
@@ -908,7 +905,7 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
908 | } | 905 | } |
909 | 906 | ||
910 | if (sg_offset) { | 907 | if (sg_offset) { |
911 | u32 rmsg[128]; | 908 | u32 rmsg[I2O_OUTBOUND_MSG_FRAME_SIZE]; |
912 | /* Copy back the Scatter Gather buffers back to user space */ | 909 | /* Copy back the Scatter Gather buffers back to user space */ |
913 | u32 j; | 910 | u32 j; |
914 | // TODO 64bit fix | 911 | // TODO 64bit fix |
@@ -942,11 +939,11 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
942 | sg_size = sg[j].flag_count & 0xffffff; | 939 | sg_size = sg[j].flag_count & 0xffffff; |
943 | // TODO 64bit fix | 940 | // TODO 64bit fix |
944 | if (copy_to_user | 941 | if (copy_to_user |
945 | ((void __user *)sg[j].addr_bus, sg_list[j], | 942 | ((void __user *)sg[j].addr_bus, sg_list[j].virt, |
946 | sg_size)) { | 943 | sg_size)) { |
947 | printk(KERN_WARNING | 944 | printk(KERN_WARNING |
948 | "%s: Could not copy %p TO user %x\n", | 945 | "%s: Could not copy %p TO user %x\n", |
949 | c->name, sg_list[j], | 946 | c->name, sg_list[j].virt, |
950 | sg[j].addr_bus); | 947 | sg[j].addr_bus); |
951 | rcode = -EFAULT; | 948 | rcode = -EFAULT; |
952 | goto sg_list_cleanup; | 949 | goto sg_list_cleanup; |
@@ -973,7 +970,7 @@ sg_list_cleanup: | |||
973 | } | 970 | } |
974 | 971 | ||
975 | for (i = 0; i < sg_index; i++) | 972 | for (i = 0; i < sg_index; i++) |
976 | kfree(sg_list[i]); | 973 | i2o_dma_free(&c->pdev->dev, &sg_list[i]); |
977 | 974 | ||
978 | cleanup: | 975 | cleanup: |
979 | kfree(reply); | 976 | kfree(reply); |
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c index da715e11c1b2..be2b5926d26c 100644 --- a/drivers/message/i2o/iop.c +++ b/drivers/message/i2o/iop.c | |||
@@ -1004,7 +1004,7 @@ static int i2o_hrt_get(struct i2o_controller *c) | |||
1004 | 1004 | ||
1005 | size = hrt->num_entries * hrt->entry_len << 2; | 1005 | size = hrt->num_entries * hrt->entry_len << 2; |
1006 | if (size > c->hrt.len) { | 1006 | if (size > c->hrt.len) { |
1007 | if (i2o_dma_realloc(dev, &c->hrt, size, GFP_KERNEL)) | 1007 | if (i2o_dma_realloc(dev, &c->hrt, size)) |
1008 | return -ENOMEM; | 1008 | return -ENOMEM; |
1009 | else | 1009 | else |
1010 | hrt = c->hrt.virt; | 1010 | hrt = c->hrt.virt; |
diff --git a/drivers/message/i2o/memory.c b/drivers/message/i2o/memory.c new file mode 100644 index 000000000000..f5cc95c564e2 --- /dev/null +++ b/drivers/message/i2o/memory.c | |||
@@ -0,0 +1,313 @@ | |||
1 | /* | ||
2 | * Functions to handle I2O memory | ||
3 | * | ||
4 | * Pulled from the inlines in i2o headers and uninlined | ||
5 | * | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/i2o.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/string.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include "core.h" | ||
19 | |||
20 | /* Protects our 32/64bit mask switching */ | ||
21 | static DEFINE_MUTEX(mem_lock); | ||
22 | |||
23 | /** | ||
24 | * i2o_sg_tablesize - Calculate the maximum number of elements in a SGL | ||
25 | * @c: I2O controller for which the calculation should be done | ||
26 | * @body_size: maximum body size used for message in 32-bit words. | ||
27 | * | ||
28 | * Return the maximum number of SG elements in a SG list. | ||
29 | */ | ||
30 | u16 i2o_sg_tablesize(struct i2o_controller *c, u16 body_size) | ||
31 | { | ||
32 | i2o_status_block *sb = c->status_block.virt; | ||
33 | u16 sg_count = | ||
34 | (sb->inbound_frame_size - sizeof(struct i2o_message) / 4) - | ||
35 | body_size; | ||
36 | |||
37 | if (c->pae_support) { | ||
38 | /* | ||
39 | * for 64-bit a SG attribute element must be added and each | ||
40 | * SG element needs 12 bytes instead of 8. | ||
41 | */ | ||
42 | sg_count -= 2; | ||
43 | sg_count /= 3; | ||
44 | } else | ||
45 | sg_count /= 2; | ||
46 | |||
47 | if (c->short_req && (sg_count > 8)) | ||
48 | sg_count = 8; | ||
49 | |||
50 | return sg_count; | ||
51 | } | ||
52 | EXPORT_SYMBOL_GPL(i2o_sg_tablesize); | ||
53 | |||
54 | |||
55 | /** | ||
56 | * i2o_dma_map_single - Map pointer to controller and fill in I2O message. | ||
57 | * @c: I2O controller | ||
58 | * @ptr: pointer to the data which should be mapped | ||
59 | * @size: size of data in bytes | ||
60 | * @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE | ||
61 | * @sg_ptr: pointer to the SG list inside the I2O message | ||
62 | * | ||
63 | * This function does all necessary DMA handling and also writes the I2O | ||
64 | * SGL elements into the I2O message. For details on DMA handling see also | ||
65 | * dma_map_single(). The pointer sg_ptr will only be set to the end of the | ||
66 | * SG list if the allocation was successful. | ||
67 | * | ||
68 | * Returns DMA address which must be checked for failures using | ||
69 | * dma_mapping_error(). | ||
70 | */ | ||
71 | dma_addr_t i2o_dma_map_single(struct i2o_controller *c, void *ptr, | ||
72 | size_t size, | ||
73 | enum dma_data_direction direction, | ||
74 | u32 ** sg_ptr) | ||
75 | { | ||
76 | u32 sg_flags; | ||
77 | u32 *mptr = *sg_ptr; | ||
78 | dma_addr_t dma_addr; | ||
79 | |||
80 | switch (direction) { | ||
81 | case DMA_TO_DEVICE: | ||
82 | sg_flags = 0xd4000000; | ||
83 | break; | ||
84 | case DMA_FROM_DEVICE: | ||
85 | sg_flags = 0xd0000000; | ||
86 | break; | ||
87 | default: | ||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | dma_addr = dma_map_single(&c->pdev->dev, ptr, size, direction); | ||
92 | if (!dma_mapping_error(&c->pdev->dev, dma_addr)) { | ||
93 | #ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 | ||
94 | if ((sizeof(dma_addr_t) > 4) && c->pae_support) { | ||
95 | *mptr++ = cpu_to_le32(0x7C020002); | ||
96 | *mptr++ = cpu_to_le32(PAGE_SIZE); | ||
97 | } | ||
98 | #endif | ||
99 | |||
100 | *mptr++ = cpu_to_le32(sg_flags | size); | ||
101 | *mptr++ = cpu_to_le32(i2o_dma_low(dma_addr)); | ||
102 | #ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 | ||
103 | if ((sizeof(dma_addr_t) > 4) && c->pae_support) | ||
104 | *mptr++ = cpu_to_le32(i2o_dma_high(dma_addr)); | ||
105 | #endif | ||
106 | *sg_ptr = mptr; | ||
107 | } | ||
108 | return dma_addr; | ||
109 | } | ||
110 | EXPORT_SYMBOL_GPL(i2o_dma_map_single); | ||
111 | |||
112 | /** | ||
113 | * i2o_dma_map_sg - Map a SG List to controller and fill in I2O message. | ||
114 | * @c: I2O controller | ||
115 | * @sg: SG list to be mapped | ||
116 | * @sg_count: number of elements in the SG list | ||
117 | * @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE | ||
118 | * @sg_ptr: pointer to the SG list inside the I2O message | ||
119 | * | ||
120 | * This function does all necessary DMA handling and also writes the I2O | ||
121 | * SGL elements into the I2O message. For details on DMA handling see also | ||
122 | * dma_map_sg(). The pointer sg_ptr will only be set to the end of the SG | ||
123 | * list if the allocation was successful. | ||
124 | * | ||
125 | * Returns 0 on failure or 1 on success. | ||
126 | */ | ||
127 | int i2o_dma_map_sg(struct i2o_controller *c, struct scatterlist *sg, | ||
128 | int sg_count, enum dma_data_direction direction, u32 ** sg_ptr) | ||
129 | { | ||
130 | u32 sg_flags; | ||
131 | u32 *mptr = *sg_ptr; | ||
132 | |||
133 | switch (direction) { | ||
134 | case DMA_TO_DEVICE: | ||
135 | sg_flags = 0x14000000; | ||
136 | break; | ||
137 | case DMA_FROM_DEVICE: | ||
138 | sg_flags = 0x10000000; | ||
139 | break; | ||
140 | default: | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | sg_count = dma_map_sg(&c->pdev->dev, sg, sg_count, direction); | ||
145 | if (!sg_count) | ||
146 | return 0; | ||
147 | |||
148 | #ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 | ||
149 | if ((sizeof(dma_addr_t) > 4) && c->pae_support) { | ||
150 | *mptr++ = cpu_to_le32(0x7C020002); | ||
151 | *mptr++ = cpu_to_le32(PAGE_SIZE); | ||
152 | } | ||
153 | #endif | ||
154 | |||
155 | while (sg_count-- > 0) { | ||
156 | if (!sg_count) | ||
157 | sg_flags |= 0xC0000000; | ||
158 | *mptr++ = cpu_to_le32(sg_flags | sg_dma_len(sg)); | ||
159 | *mptr++ = cpu_to_le32(i2o_dma_low(sg_dma_address(sg))); | ||
160 | #ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 | ||
161 | if ((sizeof(dma_addr_t) > 4) && c->pae_support) | ||
162 | *mptr++ = cpu_to_le32(i2o_dma_high(sg_dma_address(sg))); | ||
163 | #endif | ||
164 | sg = sg_next(sg); | ||
165 | } | ||
166 | *sg_ptr = mptr; | ||
167 | |||
168 | return 1; | ||
169 | } | ||
170 | EXPORT_SYMBOL_GPL(i2o_dma_map_sg); | ||
171 | |||
172 | /** | ||
173 | * i2o_dma_alloc - Allocate DMA memory | ||
174 | * @dev: struct device pointer to the PCI device of the I2O controller | ||
175 | * @addr: i2o_dma struct which should get the DMA buffer | ||
176 | * @len: length of the new DMA memory | ||
177 | * | ||
178 | * Allocate a coherent DMA memory and write the pointers into addr. | ||
179 | * | ||
180 | * Returns 0 on success or -ENOMEM on failure. | ||
181 | */ | ||
182 | int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr, size_t len) | ||
183 | { | ||
184 | struct pci_dev *pdev = to_pci_dev(dev); | ||
185 | int dma_64 = 0; | ||
186 | |||
187 | mutex_lock(&mem_lock); | ||
188 | if ((sizeof(dma_addr_t) > 4) && (pdev->dma_mask == DMA_64BIT_MASK)) { | ||
189 | dma_64 = 1; | ||
190 | if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { | ||
191 | mutex_unlock(&mem_lock); | ||
192 | return -ENOMEM; | ||
193 | } | ||
194 | } | ||
195 | |||
196 | addr->virt = dma_alloc_coherent(dev, len, &addr->phys, GFP_KERNEL); | ||
197 | |||
198 | if ((sizeof(dma_addr_t) > 4) && dma_64) | ||
199 | if (pci_set_dma_mask(pdev, DMA_64BIT_MASK)) | ||
200 | printk(KERN_WARNING "i2o: unable to set 64-bit DMA"); | ||
201 | mutex_unlock(&mem_lock); | ||
202 | |||
203 | if (!addr->virt) | ||
204 | return -ENOMEM; | ||
205 | |||
206 | memset(addr->virt, 0, len); | ||
207 | addr->len = len; | ||
208 | |||
209 | return 0; | ||
210 | } | ||
211 | EXPORT_SYMBOL_GPL(i2o_dma_alloc); | ||
212 | |||
213 | |||
214 | /** | ||
215 | * i2o_dma_free - Free DMA memory | ||
216 | * @dev: struct device pointer to the PCI device of the I2O controller | ||
217 | * @addr: i2o_dma struct which contains the DMA buffer | ||
218 | * | ||
219 | * Free a coherent DMA memory and set virtual address of addr to NULL. | ||
220 | */ | ||
221 | void i2o_dma_free(struct device *dev, struct i2o_dma *addr) | ||
222 | { | ||
223 | if (addr->virt) { | ||
224 | if (addr->phys) | ||
225 | dma_free_coherent(dev, addr->len, addr->virt, | ||
226 | addr->phys); | ||
227 | else | ||
228 | kfree(addr->virt); | ||
229 | addr->virt = NULL; | ||
230 | } | ||
231 | } | ||
232 | EXPORT_SYMBOL_GPL(i2o_dma_free); | ||
233 | |||
234 | |||
235 | /** | ||
236 | * i2o_dma_realloc - Realloc DMA memory | ||
237 | * @dev: struct device pointer to the PCI device of the I2O controller | ||
238 | * @addr: pointer to a i2o_dma struct DMA buffer | ||
239 | * @len: new length of memory | ||
240 | * | ||
241 | * If there was something allocated in the addr, free it first. If len > 0 | ||
242 | * than try to allocate it and write the addresses back to the addr | ||
243 | * structure. If len == 0 set the virtual address to NULL. | ||
244 | * | ||
245 | * Returns the 0 on success or negative error code on failure. | ||
246 | */ | ||
247 | int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr, size_t len) | ||
248 | { | ||
249 | i2o_dma_free(dev, addr); | ||
250 | |||
251 | if (len) | ||
252 | return i2o_dma_alloc(dev, addr, len); | ||
253 | |||
254 | return 0; | ||
255 | } | ||
256 | EXPORT_SYMBOL_GPL(i2o_dma_realloc); | ||
257 | |||
258 | /* | ||
259 | * i2o_pool_alloc - Allocate an slab cache and mempool | ||
260 | * @mempool: pointer to struct i2o_pool to write data into. | ||
261 | * @name: name which is used to identify cache | ||
262 | * @size: size of each object | ||
263 | * @min_nr: minimum number of objects | ||
264 | * | ||
265 | * First allocates a slab cache with name and size. Then allocates a | ||
266 | * mempool which uses the slab cache for allocation and freeing. | ||
267 | * | ||
268 | * Returns 0 on success or negative error code on failure. | ||
269 | */ | ||
270 | int i2o_pool_alloc(struct i2o_pool *pool, const char *name, | ||
271 | size_t size, int min_nr) | ||
272 | { | ||
273 | pool->name = kmalloc(strlen(name) + 1, GFP_KERNEL); | ||
274 | if (!pool->name) | ||
275 | goto exit; | ||
276 | strcpy(pool->name, name); | ||
277 | |||
278 | pool->slab = | ||
279 | kmem_cache_create(pool->name, size, 0, SLAB_HWCACHE_ALIGN, NULL); | ||
280 | if (!pool->slab) | ||
281 | goto free_name; | ||
282 | |||
283 | pool->mempool = mempool_create_slab_pool(min_nr, pool->slab); | ||
284 | if (!pool->mempool) | ||
285 | goto free_slab; | ||
286 | |||
287 | return 0; | ||
288 | |||
289 | free_slab: | ||
290 | kmem_cache_destroy(pool->slab); | ||
291 | |||
292 | free_name: | ||
293 | kfree(pool->name); | ||
294 | |||
295 | exit: | ||
296 | return -ENOMEM; | ||
297 | } | ||
298 | EXPORT_SYMBOL_GPL(i2o_pool_alloc); | ||
299 | |||
300 | /* | ||
301 | * i2o_pool_free - Free slab cache and mempool again | ||
302 | * @mempool: pointer to struct i2o_pool which should be freed | ||
303 | * | ||
304 | * Note that you have to return all objects to the mempool again before | ||
305 | * calling i2o_pool_free(). | ||
306 | */ | ||
307 | void i2o_pool_free(struct i2o_pool *pool) | ||
308 | { | ||
309 | mempool_destroy(pool->mempool); | ||
310 | kmem_cache_destroy(pool->slab); | ||
311 | kfree(pool->name); | ||
312 | }; | ||
313 | EXPORT_SYMBOL_GPL(i2o_pool_free); | ||
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c index 685a89547a51..610ef1204e68 100644 --- a/drivers/message/i2o/pci.c +++ b/drivers/message/i2o/pci.c | |||
@@ -186,31 +186,29 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) | |||
186 | } | 186 | } |
187 | } | 187 | } |
188 | 188 | ||
189 | if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) { | 189 | if (i2o_dma_alloc(dev, &c->status, 8)) { |
190 | i2o_pci_free(c); | 190 | i2o_pci_free(c); |
191 | return -ENOMEM; | 191 | return -ENOMEM; |
192 | } | 192 | } |
193 | 193 | ||
194 | if (i2o_dma_alloc(dev, &c->hrt, sizeof(i2o_hrt), GFP_KERNEL)) { | 194 | if (i2o_dma_alloc(dev, &c->hrt, sizeof(i2o_hrt))) { |
195 | i2o_pci_free(c); | 195 | i2o_pci_free(c); |
196 | return -ENOMEM; | 196 | return -ENOMEM; |
197 | } | 197 | } |
198 | 198 | ||
199 | if (i2o_dma_alloc(dev, &c->dlct, 8192, GFP_KERNEL)) { | 199 | if (i2o_dma_alloc(dev, &c->dlct, 8192)) { |
200 | i2o_pci_free(c); | 200 | i2o_pci_free(c); |
201 | return -ENOMEM; | 201 | return -ENOMEM; |
202 | } | 202 | } |
203 | 203 | ||
204 | if (i2o_dma_alloc(dev, &c->status_block, sizeof(i2o_status_block), | 204 | if (i2o_dma_alloc(dev, &c->status_block, sizeof(i2o_status_block))) { |
205 | GFP_KERNEL)) { | ||
206 | i2o_pci_free(c); | 205 | i2o_pci_free(c); |
207 | return -ENOMEM; | 206 | return -ENOMEM; |
208 | } | 207 | } |
209 | 208 | ||
210 | if (i2o_dma_alloc | 209 | if (i2o_dma_alloc(dev, &c->out_queue, |
211 | (dev, &c->out_queue, | 210 | I2O_MAX_OUTBOUND_MSG_FRAMES * I2O_OUTBOUND_MSG_FRAME_SIZE * |
212 | I2O_MAX_OUTBOUND_MSG_FRAMES * I2O_OUTBOUND_MSG_FRAME_SIZE * | 211 | sizeof(u32))) { |
213 | sizeof(u32), GFP_KERNEL)) { | ||
214 | i2o_pci_free(c); | 212 | i2o_pci_free(c); |
215 | return -ENOMEM; | 213 | return -ENOMEM; |
216 | } | 214 | } |
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index a726f3b01a6b..efd3aa08b88b 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
@@ -15,7 +15,7 @@ if MISC_DEVICES | |||
15 | 15 | ||
16 | config ATMEL_PWM | 16 | config ATMEL_PWM |
17 | tristate "Atmel AT32/AT91 PWM support" | 17 | tristate "Atmel AT32/AT91 PWM support" |
18 | depends on AVR32 || ARCH_AT91 | 18 | depends on AVR32 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9 |
19 | help | 19 | help |
20 | This option enables device driver support for the PWM channels | 20 | This option enables device driver support for the PWM channels |
21 | on certain Atmel prcoessors. Pulse Width Modulation is used for | 21 | on certain Atmel prcoessors. Pulse Width Modulation is used for |
@@ -409,6 +409,7 @@ config EEEPC_LAPTOP | |||
409 | depends on BACKLIGHT_CLASS_DEVICE | 409 | depends on BACKLIGHT_CLASS_DEVICE |
410 | depends on HWMON | 410 | depends on HWMON |
411 | depends on EXPERIMENTAL | 411 | depends on EXPERIMENTAL |
412 | depends on RFKILL | ||
412 | ---help--- | 413 | ---help--- |
413 | This driver supports the Fn-Fx keys on Eee PC laptops. | 414 | This driver supports the Fn-Fx keys on Eee PC laptops. |
414 | It also adds the ability to switch camera/wlan on/off. | 415 | It also adds the ability to switch camera/wlan on/off. |
diff --git a/drivers/misc/hp-wmi.c b/drivers/misc/hp-wmi.c index 6d407c2a4f91..5dabfb69ee53 100644 --- a/drivers/misc/hp-wmi.c +++ b/drivers/misc/hp-wmi.c | |||
@@ -309,7 +309,7 @@ static int hp_wmi_setkeycode(struct input_dev *dev, int scancode, int keycode) | |||
309 | return -EINVAL; | 309 | return -EINVAL; |
310 | } | 310 | } |
311 | 311 | ||
312 | void hp_wmi_notify(u32 value, void *context) | 312 | static void hp_wmi_notify(u32 value, void *context) |
313 | { | 313 | { |
314 | struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; | 314 | struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; |
315 | static struct key_entry *key; | 315 | static struct key_entry *key; |
diff --git a/drivers/misc/sgi-gru/gru.h b/drivers/misc/sgi-gru/gru.h index 40df7cb3f0a5..f93f03a9e6e9 100644 --- a/drivers/misc/sgi-gru/gru.h +++ b/drivers/misc/sgi-gru/gru.h | |||
@@ -30,9 +30,9 @@ | |||
30 | /* | 30 | /* |
31 | * Size used to map GRU GSeg | 31 | * Size used to map GRU GSeg |
32 | */ | 32 | */ |
33 | #if defined CONFIG_IA64 | 33 | #if defined(CONFIG_IA64) |
34 | #define GRU_GSEG_PAGESIZE (256 * 1024UL) | 34 | #define GRU_GSEG_PAGESIZE (256 * 1024UL) |
35 | #elif defined CONFIG_X86_64 | 35 | #elif defined(CONFIG_X86_64) |
36 | #define GRU_GSEG_PAGESIZE (256 * 1024UL) /* ZZZ 2MB ??? */ | 36 | #define GRU_GSEG_PAGESIZE (256 * 1024UL) /* ZZZ 2MB ??? */ |
37 | #else | 37 | #else |
38 | #error "Unsupported architecture" | 38 | #error "Unsupported architecture" |
diff --git a/drivers/misc/sgi-gru/gru_instructions.h b/drivers/misc/sgi-gru/gru_instructions.h index 0dc36225c7c6..48762e7b98be 100644 --- a/drivers/misc/sgi-gru/gru_instructions.h +++ b/drivers/misc/sgi-gru/gru_instructions.h | |||
@@ -26,7 +26,7 @@ | |||
26 | * Architecture dependent functions | 26 | * Architecture dependent functions |
27 | */ | 27 | */ |
28 | 28 | ||
29 | #if defined CONFIG_IA64 | 29 | #if defined(CONFIG_IA64) |
30 | #include <linux/compiler.h> | 30 | #include <linux/compiler.h> |
31 | #include <asm/intrinsics.h> | 31 | #include <asm/intrinsics.h> |
32 | #define __flush_cache(p) ia64_fc(p) | 32 | #define __flush_cache(p) ia64_fc(p) |
@@ -36,7 +36,7 @@ | |||
36 | barrier(); \ | 36 | barrier(); \ |
37 | *((volatile int *)(p)) = v; /* force st.rel */ \ | 37 | *((volatile int *)(p)) = v; /* force st.rel */ \ |
38 | } while (0) | 38 | } while (0) |
39 | #elif defined CONFIG_X86_64 | 39 | #elif defined(CONFIG_X86_64) |
40 | #define __flush_cache(p) clflush(p) | 40 | #define __flush_cache(p) clflush(p) |
41 | #define gru_ordered_store_int(p,v) \ | 41 | #define gru_ordered_store_int(p,v) \ |
42 | do { \ | 42 | do { \ |
@@ -299,6 +299,7 @@ static inline void gru_flush_cache(void *p) | |||
299 | static inline void gru_start_instruction(struct gru_instruction *ins, int op32) | 299 | static inline void gru_start_instruction(struct gru_instruction *ins, int op32) |
300 | { | 300 | { |
301 | gru_ordered_store_int(ins, op32); | 301 | gru_ordered_store_int(ins, op32); |
302 | gru_flush_cache(ins); | ||
302 | } | 303 | } |
303 | 304 | ||
304 | 305 | ||
@@ -604,8 +605,9 @@ static inline int gru_get_cb_substatus(void *cb) | |||
604 | static inline int gru_check_status(void *cb) | 605 | static inline int gru_check_status(void *cb) |
605 | { | 606 | { |
606 | struct gru_control_block_status *cbs = (void *)cb; | 607 | struct gru_control_block_status *cbs = (void *)cb; |
607 | int ret = cbs->istatus; | 608 | int ret; |
608 | 609 | ||
610 | ret = cbs->istatus; | ||
609 | if (ret == CBS_CALL_OS) | 611 | if (ret == CBS_CALL_OS) |
610 | ret = gru_check_status_proc(cb); | 612 | ret = gru_check_status_proc(cb); |
611 | return ret; | 613 | return ret; |
@@ -617,7 +619,7 @@ static inline int gru_check_status(void *cb) | |||
617 | static inline int gru_wait(void *cb) | 619 | static inline int gru_wait(void *cb) |
618 | { | 620 | { |
619 | struct gru_control_block_status *cbs = (void *)cb; | 621 | struct gru_control_block_status *cbs = (void *)cb; |
620 | int ret = cbs->istatus;; | 622 | int ret = cbs->istatus; |
621 | 623 | ||
622 | if (ret != CBS_IDLE) | 624 | if (ret != CBS_IDLE) |
623 | ret = gru_wait_proc(cb); | 625 | ret = gru_wait_proc(cb); |
diff --git a/drivers/misc/sgi-gru/grufault.c b/drivers/misc/sgi-gru/grufault.c index 3d33015bbf31..8c389d606c30 100644 --- a/drivers/misc/sgi-gru/grufault.c +++ b/drivers/misc/sgi-gru/grufault.c | |||
@@ -214,12 +214,14 @@ static int non_atomic_pte_lookup(struct vm_area_struct *vma, | |||
214 | } | 214 | } |
215 | 215 | ||
216 | /* | 216 | /* |
217 | * | ||
218 | * atomic_pte_lookup | 217 | * atomic_pte_lookup |
219 | * | 218 | * |
220 | * Convert a user virtual address to a physical address | 219 | * Convert a user virtual address to a physical address |
221 | * Only supports Intel large pages (2MB only) on x86_64. | 220 | * Only supports Intel large pages (2MB only) on x86_64. |
222 | * ZZZ - hugepage support is incomplete | 221 | * ZZZ - hugepage support is incomplete |
222 | * | ||
223 | * NOTE: mmap_sem is already held on entry to this function. This | ||
224 | * guarantees existence of the page tables. | ||
223 | */ | 225 | */ |
224 | static int atomic_pte_lookup(struct vm_area_struct *vma, unsigned long vaddr, | 226 | static int atomic_pte_lookup(struct vm_area_struct *vma, unsigned long vaddr, |
225 | int write, unsigned long *paddr, int *pageshift) | 227 | int write, unsigned long *paddr, int *pageshift) |
@@ -229,9 +231,6 @@ static int atomic_pte_lookup(struct vm_area_struct *vma, unsigned long vaddr, | |||
229 | pud_t *pudp; | 231 | pud_t *pudp; |
230 | pte_t pte; | 232 | pte_t pte; |
231 | 233 | ||
232 | WARN_ON(irqs_disabled()); /* ZZZ debug */ | ||
233 | |||
234 | local_irq_disable(); | ||
235 | pgdp = pgd_offset(vma->vm_mm, vaddr); | 234 | pgdp = pgd_offset(vma->vm_mm, vaddr); |
236 | if (unlikely(pgd_none(*pgdp))) | 235 | if (unlikely(pgd_none(*pgdp))) |
237 | goto err; | 236 | goto err; |
@@ -250,8 +249,6 @@ static int atomic_pte_lookup(struct vm_area_struct *vma, unsigned long vaddr, | |||
250 | #endif | 249 | #endif |
251 | pte = *pte_offset_kernel(pmdp, vaddr); | 250 | pte = *pte_offset_kernel(pmdp, vaddr); |
252 | 251 | ||
253 | local_irq_enable(); | ||
254 | |||
255 | if (unlikely(!pte_present(pte) || | 252 | if (unlikely(!pte_present(pte) || |
256 | (write && (!pte_write(pte) || !pte_dirty(pte))))) | 253 | (write && (!pte_write(pte) || !pte_dirty(pte))))) |
257 | return 1; | 254 | return 1; |
@@ -324,6 +321,7 @@ static int gru_try_dropin(struct gru_thread_state *gts, | |||
324 | * Atomic lookup is faster & usually works even if called in non-atomic | 321 | * Atomic lookup is faster & usually works even if called in non-atomic |
325 | * context. | 322 | * context. |
326 | */ | 323 | */ |
324 | rmb(); /* Must/check ms_range_active before loading PTEs */ | ||
327 | ret = atomic_pte_lookup(vma, vaddr, write, &paddr, &pageshift); | 325 | ret = atomic_pte_lookup(vma, vaddr, write, &paddr, &pageshift); |
328 | if (ret) { | 326 | if (ret) { |
329 | if (!cb) | 327 | if (!cb) |
@@ -543,6 +541,7 @@ int gru_get_exception_detail(unsigned long arg) | |||
543 | ucbnum = get_cb_number((void *)excdet.cb); | 541 | ucbnum = get_cb_number((void *)excdet.cb); |
544 | cbrnum = thread_cbr_number(gts, ucbnum); | 542 | cbrnum = thread_cbr_number(gts, ucbnum); |
545 | cbe = get_cbe_by_index(gts->ts_gru, cbrnum); | 543 | cbe = get_cbe_by_index(gts->ts_gru, cbrnum); |
544 | prefetchw(cbe); /* Harmless on hardware, required for emulator */ | ||
546 | excdet.opc = cbe->opccpy; | 545 | excdet.opc = cbe->opccpy; |
547 | excdet.exopc = cbe->exopccpy; | 546 | excdet.exopc = cbe->exopccpy; |
548 | excdet.ecause = cbe->ecause; | 547 | excdet.ecause = cbe->ecause; |
diff --git a/drivers/misc/sgi-gru/grufile.c b/drivers/misc/sgi-gru/grufile.c index d61cee796efd..5c027b6b4e5a 100644 --- a/drivers/misc/sgi-gru/grufile.c +++ b/drivers/misc/sgi-gru/grufile.c | |||
@@ -113,7 +113,7 @@ static int gru_file_mmap(struct file *file, struct vm_area_struct *vma) | |||
113 | return -EPERM; | 113 | return -EPERM; |
114 | 114 | ||
115 | if (vma->vm_start & (GRU_GSEG_PAGESIZE - 1) || | 115 | if (vma->vm_start & (GRU_GSEG_PAGESIZE - 1) || |
116 | vma->vm_end & (GRU_GSEG_PAGESIZE - 1)) | 116 | vma->vm_end & (GRU_GSEG_PAGESIZE - 1)) |
117 | return -EINVAL; | 117 | return -EINVAL; |
118 | 118 | ||
119 | vma->vm_flags |= | 119 | vma->vm_flags |= |
@@ -398,6 +398,12 @@ static int __init gru_init(void) | |||
398 | irq = get_base_irq(); | 398 | irq = get_base_irq(); |
399 | for (chip = 0; chip < GRU_CHIPLETS_PER_BLADE; chip++) { | 399 | for (chip = 0; chip < GRU_CHIPLETS_PER_BLADE; chip++) { |
400 | ret = request_irq(irq + chip, gru_intr, 0, id, NULL); | 400 | ret = request_irq(irq + chip, gru_intr, 0, id, NULL); |
401 | /* TODO: fix irq handling on x86. For now ignore failures because | ||
402 | * interrupts are not required & not yet fully supported */ | ||
403 | if (ret) { | ||
404 | printk("!!!WARNING: GRU ignoring request failure!!!\n"); | ||
405 | ret = 0; | ||
406 | } | ||
401 | if (ret) { | 407 | if (ret) { |
402 | printk(KERN_ERR "%s: request_irq failed\n", | 408 | printk(KERN_ERR "%s: request_irq failed\n", |
403 | GRU_DRIVER_ID_STR); | 409 | GRU_DRIVER_ID_STR); |
diff --git a/drivers/misc/sgi-gru/gruhandles.h b/drivers/misc/sgi-gru/gruhandles.h index d16031d62673..b63018d60fe1 100644 --- a/drivers/misc/sgi-gru/gruhandles.h +++ b/drivers/misc/sgi-gru/gruhandles.h | |||
@@ -91,12 +91,7 @@ | |||
91 | #define GSEGPOFF(h) ((h) & (GRU_SIZE - 1)) | 91 | #define GSEGPOFF(h) ((h) & (GRU_SIZE - 1)) |
92 | 92 | ||
93 | /* Convert an arbitrary handle address to the beginning of the GRU segment */ | 93 | /* Convert an arbitrary handle address to the beginning of the GRU segment */ |
94 | #ifndef __PLUGIN__ | ||
95 | #define GRUBASE(h) ((void *)((unsigned long)(h) & ~(GRU_SIZE - 1))) | 94 | #define GRUBASE(h) ((void *)((unsigned long)(h) & ~(GRU_SIZE - 1))) |
96 | #else | ||
97 | extern void *gmu_grubase(void *h); | ||
98 | #define GRUBASE(h) gmu_grubase(h) | ||
99 | #endif | ||
100 | 95 | ||
101 | /* General addressing macros. */ | 96 | /* General addressing macros. */ |
102 | static inline void *get_gseg_base_address(void *base, int ctxnum) | 97 | static inline void *get_gseg_base_address(void *base, int ctxnum) |
diff --git a/drivers/misc/sgi-gru/grukservices.c b/drivers/misc/sgi-gru/grukservices.c index dfd49af0fe18..880c55dfb662 100644 --- a/drivers/misc/sgi-gru/grukservices.c +++ b/drivers/misc/sgi-gru/grukservices.c | |||
@@ -122,6 +122,7 @@ int gru_get_cb_exception_detail(void *cb, | |||
122 | struct gru_control_block_extended *cbe; | 122 | struct gru_control_block_extended *cbe; |
123 | 123 | ||
124 | cbe = get_cbe(GRUBASE(cb), get_cb_number(cb)); | 124 | cbe = get_cbe(GRUBASE(cb), get_cb_number(cb)); |
125 | prefetchw(cbe); /* Harmless on hardware, required for emulator */ | ||
125 | excdet->opc = cbe->opccpy; | 126 | excdet->opc = cbe->opccpy; |
126 | excdet->exopc = cbe->exopccpy; | 127 | excdet->exopc = cbe->exopccpy; |
127 | excdet->ecause = cbe->ecause; | 128 | excdet->ecause = cbe->ecause; |
@@ -466,7 +467,7 @@ int gru_send_message_gpa(unsigned long mq, void *mesg, unsigned int bytes) | |||
466 | STAT(mesq_send); | 467 | STAT(mesq_send); |
467 | BUG_ON(bytes < sizeof(int) || bytes > 2 * GRU_CACHE_LINE_BYTES); | 468 | BUG_ON(bytes < sizeof(int) || bytes > 2 * GRU_CACHE_LINE_BYTES); |
468 | 469 | ||
469 | clines = (bytes + GRU_CACHE_LINE_BYTES - 1) / GRU_CACHE_LINE_BYTES; | 470 | clines = DIV_ROUND_UP(bytes, GRU_CACHE_LINE_BYTES); |
470 | if (gru_get_cpu_resources(bytes, &cb, &dsr)) | 471 | if (gru_get_cpu_resources(bytes, &cb, &dsr)) |
471 | return MQE_BUG_NO_RESOURCES; | 472 | return MQE_BUG_NO_RESOURCES; |
472 | memcpy(dsr, mesg, bytes); | 473 | memcpy(dsr, mesg, bytes); |
diff --git a/drivers/misc/sgi-gru/grumain.c b/drivers/misc/sgi-gru/grumain.c index 0eeb8dddd2f5..e11e1ac50900 100644 --- a/drivers/misc/sgi-gru/grumain.c +++ b/drivers/misc/sgi-gru/grumain.c | |||
@@ -432,29 +432,35 @@ static inline long gru_copy_handle(void *d, void *s) | |||
432 | return GRU_HANDLE_BYTES; | 432 | return GRU_HANDLE_BYTES; |
433 | } | 433 | } |
434 | 434 | ||
435 | /* rewrite in assembly & use lots of prefetch */ | 435 | static void gru_prefetch_context(void *gseg, void *cb, void *cbe, unsigned long cbrmap, |
436 | static void gru_load_context_data(void *save, void *grubase, int ctxnum, | 436 | unsigned long length) |
437 | unsigned long cbrmap, unsigned long dsrmap) | ||
438 | { | 437 | { |
439 | void *gseg, *cb, *cbe; | ||
440 | unsigned long length; | ||
441 | int i, scr; | 438 | int i, scr; |
442 | 439 | ||
443 | gseg = grubase + ctxnum * GRU_GSEG_STRIDE; | ||
444 | length = hweight64(dsrmap) * GRU_DSR_AU_BYTES; | ||
445 | prefetch_data(gseg + GRU_DS_BASE, length / GRU_CACHE_LINE_BYTES, | 440 | prefetch_data(gseg + GRU_DS_BASE, length / GRU_CACHE_LINE_BYTES, |
446 | GRU_CACHE_LINE_BYTES); | 441 | GRU_CACHE_LINE_BYTES); |
447 | 442 | ||
448 | cb = gseg + GRU_CB_BASE; | ||
449 | cbe = grubase + GRU_CBE_BASE; | ||
450 | for_each_cbr_in_allocation_map(i, &cbrmap, scr) { | 443 | for_each_cbr_in_allocation_map(i, &cbrmap, scr) { |
451 | prefetch_data(cb, 1, GRU_CACHE_LINE_BYTES); | 444 | prefetch_data(cb, 1, GRU_CACHE_LINE_BYTES); |
452 | prefetch_data(cbe + i * GRU_HANDLE_STRIDE, 1, | 445 | prefetch_data(cbe + i * GRU_HANDLE_STRIDE, 1, |
453 | GRU_CACHE_LINE_BYTES); | 446 | GRU_CACHE_LINE_BYTES); |
454 | cb += GRU_HANDLE_STRIDE; | 447 | cb += GRU_HANDLE_STRIDE; |
455 | } | 448 | } |
449 | } | ||
450 | |||
451 | static void gru_load_context_data(void *save, void *grubase, int ctxnum, | ||
452 | unsigned long cbrmap, unsigned long dsrmap) | ||
453 | { | ||
454 | void *gseg, *cb, *cbe; | ||
455 | unsigned long length; | ||
456 | int i, scr; | ||
456 | 457 | ||
458 | gseg = grubase + ctxnum * GRU_GSEG_STRIDE; | ||
457 | cb = gseg + GRU_CB_BASE; | 459 | cb = gseg + GRU_CB_BASE; |
460 | cbe = grubase + GRU_CBE_BASE; | ||
461 | length = hweight64(dsrmap) * GRU_DSR_AU_BYTES; | ||
462 | gru_prefetch_context(gseg, cb, cbe, cbrmap, length); | ||
463 | |||
458 | for_each_cbr_in_allocation_map(i, &cbrmap, scr) { | 464 | for_each_cbr_in_allocation_map(i, &cbrmap, scr) { |
459 | save += gru_copy_handle(cb, save); | 465 | save += gru_copy_handle(cb, save); |
460 | save += gru_copy_handle(cbe + i * GRU_HANDLE_STRIDE, save); | 466 | save += gru_copy_handle(cbe + i * GRU_HANDLE_STRIDE, save); |
@@ -472,15 +478,16 @@ static void gru_unload_context_data(void *save, void *grubase, int ctxnum, | |||
472 | int i, scr; | 478 | int i, scr; |
473 | 479 | ||
474 | gseg = grubase + ctxnum * GRU_GSEG_STRIDE; | 480 | gseg = grubase + ctxnum * GRU_GSEG_STRIDE; |
475 | |||
476 | cb = gseg + GRU_CB_BASE; | 481 | cb = gseg + GRU_CB_BASE; |
477 | cbe = grubase + GRU_CBE_BASE; | 482 | cbe = grubase + GRU_CBE_BASE; |
483 | length = hweight64(dsrmap) * GRU_DSR_AU_BYTES; | ||
484 | gru_prefetch_context(gseg, cb, cbe, cbrmap, length); | ||
485 | |||
478 | for_each_cbr_in_allocation_map(i, &cbrmap, scr) { | 486 | for_each_cbr_in_allocation_map(i, &cbrmap, scr) { |
479 | save += gru_copy_handle(save, cb); | 487 | save += gru_copy_handle(save, cb); |
480 | save += gru_copy_handle(save, cbe + i * GRU_HANDLE_STRIDE); | 488 | save += gru_copy_handle(save, cbe + i * GRU_HANDLE_STRIDE); |
481 | cb += GRU_HANDLE_STRIDE; | 489 | cb += GRU_HANDLE_STRIDE; |
482 | } | 490 | } |
483 | length = hweight64(dsrmap) * GRU_DSR_AU_BYTES; | ||
484 | memcpy(save, gseg + GRU_DS_BASE, length); | 491 | memcpy(save, gseg + GRU_DS_BASE, length); |
485 | } | 492 | } |
486 | 493 | ||
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index c16028872bbb..1b9fc3c6b875 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c | |||
@@ -172,7 +172,7 @@ struct mmc_omap_host { | |||
172 | struct omap_mmc_platform_data *pdata; | 172 | struct omap_mmc_platform_data *pdata; |
173 | }; | 173 | }; |
174 | 174 | ||
175 | void mmc_omap_fclk_offdelay(struct mmc_omap_slot *slot) | 175 | static void mmc_omap_fclk_offdelay(struct mmc_omap_slot *slot) |
176 | { | 176 | { |
177 | unsigned long tick_ns; | 177 | unsigned long tick_ns; |
178 | 178 | ||
@@ -182,7 +182,7 @@ void mmc_omap_fclk_offdelay(struct mmc_omap_slot *slot) | |||
182 | } | 182 | } |
183 | } | 183 | } |
184 | 184 | ||
185 | void mmc_omap_fclk_enable(struct mmc_omap_host *host, unsigned int enable) | 185 | static void mmc_omap_fclk_enable(struct mmc_omap_host *host, unsigned int enable) |
186 | { | 186 | { |
187 | unsigned long flags; | 187 | unsigned long flags; |
188 | 188 | ||
@@ -1455,7 +1455,9 @@ static int __init mmc_omap_probe(struct platform_device *pdev) | |||
1455 | 1455 | ||
1456 | host->irq = irq; | 1456 | host->irq = irq; |
1457 | host->phys_base = host->mem_res->start; | 1457 | host->phys_base = host->mem_res->start; |
1458 | host->virt_base = (void __iomem *) IO_ADDRESS(host->phys_base); | 1458 | host->virt_base = ioremap(res->start, res->end - res->start + 1); |
1459 | if (!host->virt_base) | ||
1460 | goto err_ioremap; | ||
1459 | 1461 | ||
1460 | if (cpu_is_omap24xx()) { | 1462 | if (cpu_is_omap24xx()) { |
1461 | host->iclk = clk_get(&pdev->dev, "mmc_ick"); | 1463 | host->iclk = clk_get(&pdev->dev, "mmc_ick"); |
@@ -1510,6 +1512,8 @@ err_free_iclk: | |||
1510 | clk_put(host->iclk); | 1512 | clk_put(host->iclk); |
1511 | } | 1513 | } |
1512 | err_free_mmc_host: | 1514 | err_free_mmc_host: |
1515 | iounmap(host->virt_base); | ||
1516 | err_ioremap: | ||
1513 | kfree(host); | 1517 | kfree(host); |
1514 | err_free_mem_region: | 1518 | err_free_mem_region: |
1515 | release_mem_region(res->start, res->end - res->start + 1); | 1519 | release_mem_region(res->start, res->end - res->start + 1); |
@@ -1536,6 +1540,7 @@ static int mmc_omap_remove(struct platform_device *pdev) | |||
1536 | if (host->fclk && !IS_ERR(host->fclk)) | 1540 | if (host->fclk && !IS_ERR(host->fclk)) |
1537 | clk_put(host->fclk); | 1541 | clk_put(host->fclk); |
1538 | 1542 | ||
1543 | iounmap(host->virt_base); | ||
1539 | release_mem_region(pdev->resource[0].start, | 1544 | release_mem_region(pdev->resource[0].start, |
1540 | pdev->resource[0].end - pdev->resource[0].start + 1); | 1545 | pdev->resource[0].end - pdev->resource[0].start + 1); |
1541 | 1546 | ||
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index edb90b58a9b1..9a06dc93ee0d 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c | |||
@@ -564,10 +564,8 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types, | |||
564 | 564 | ||
565 | for ( ; ret <= 0 && *types; types++) { | 565 | for ( ; ret <= 0 && *types; types++) { |
566 | parser = get_partition_parser(*types); | 566 | parser = get_partition_parser(*types); |
567 | #ifdef CONFIG_KMOD | ||
568 | if (!parser && !request_module("%s", *types)) | 567 | if (!parser && !request_module("%s", *types)) |
569 | parser = get_partition_parser(*types); | 568 | parser = get_partition_parser(*types); |
570 | #endif | ||
571 | if (!parser) { | 569 | if (!parser) { |
572 | printk(KERN_NOTICE "%s partition parsing not available\n", | 570 | printk(KERN_NOTICE "%s partition parsing not available\n", |
573 | *types); | 571 | *types); |
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c index 26d42987971f..782994ead0e8 100644 --- a/drivers/mtd/nand/ams-delta.c +++ b/drivers/mtd/nand/ams-delta.c | |||
@@ -145,7 +145,7 @@ static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd, | |||
145 | 145 | ||
146 | static int ams_delta_nand_ready(struct mtd_info *mtd) | 146 | static int ams_delta_nand_ready(struct mtd_info *mtd) |
147 | { | 147 | { |
148 | return omap_get_gpio_datain(AMS_DELTA_GPIO_PIN_NAND_RB); | 148 | return gpio_get_value(AMS_DELTA_GPIO_PIN_NAND_RB); |
149 | } | 149 | } |
150 | 150 | ||
151 | /* | 151 | /* |
@@ -185,7 +185,7 @@ static int __init ams_delta_init(void) | |||
185 | this->read_buf = ams_delta_read_buf; | 185 | this->read_buf = ams_delta_read_buf; |
186 | this->verify_buf = ams_delta_verify_buf; | 186 | this->verify_buf = ams_delta_verify_buf; |
187 | this->cmd_ctrl = ams_delta_hwcontrol; | 187 | this->cmd_ctrl = ams_delta_hwcontrol; |
188 | if (!omap_request_gpio(AMS_DELTA_GPIO_PIN_NAND_RB)) { | 188 | if (gpio_request(AMS_DELTA_GPIO_PIN_NAND_RB, "nand_rdy") == 0) { |
189 | this->dev_ready = ams_delta_nand_ready; | 189 | this->dev_ready = ams_delta_nand_ready; |
190 | } else { | 190 | } else { |
191 | this->dev_ready = NULL; | 191 | this->dev_ready = NULL; |
diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index b9d097c9f6bb..3a7bc524af33 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c | |||
@@ -40,7 +40,7 @@ | |||
40 | v1.14 10/15/97 Avoided waiting..discard message for fast machines -djb | 40 | v1.14 10/15/97 Avoided waiting..discard message for fast machines -djb |
41 | v1.15 1/31/98 Faster recovery for Tx errors. -djb | 41 | v1.15 1/31/98 Faster recovery for Tx errors. -djb |
42 | v1.16 2/3/98 Different ID port handling to avoid sound cards. -djb | 42 | v1.16 2/3/98 Different ID port handling to avoid sound cards. -djb |
43 | v1.18 12Mar2001 Andrew Morton <andrewm@uow.edu.au> | 43 | v1.18 12Mar2001 Andrew Morton |
44 | - Avoid bogus detect of 3c590's (Andrzej Krzysztofowicz) | 44 | - Avoid bogus detect of 3c590's (Andrzej Krzysztofowicz) |
45 | - Reviewed against 1.18 from scyld.com | 45 | - Reviewed against 1.18 from scyld.com |
46 | v1.18a 17Nov2001 Jeff Garzik <jgarzik@pobox.com> | 46 | v1.18a 17Nov2001 Jeff Garzik <jgarzik@pobox.com> |
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index a28de8182802..7107620f615d 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c | |||
@@ -36,8 +36,7 @@ | |||
36 | 36 | ||
37 | Alan Cox : Removed 1.2 support, added 2.1 extra counters. | 37 | Alan Cox : Removed 1.2 support, added 2.1 extra counters. |
38 | 38 | ||
39 | Andrew Morton : andrewm@uow.edu.au | 39 | Andrew Morton : Kernel 2.3.48 |
40 | : Kernel 2.3.48 | ||
41 | : Handle kmalloc() failures | 40 | : Handle kmalloc() failures |
42 | : Other resource allocation fixes | 41 | : Other resource allocation fixes |
43 | : Add SMP locks | 42 | : Add SMP locks |
@@ -49,7 +48,7 @@ | |||
49 | : Fixed an out-of-mem bug in dma_rx() | 48 | : Fixed an out-of-mem bug in dma_rx() |
50 | : Updated Documentation/networking/cs89x0.txt | 49 | : Updated Documentation/networking/cs89x0.txt |
51 | 50 | ||
52 | Andrew Morton : andrewm@uow.edu.au / Kernel 2.3.99-pre1 | 51 | Andrew Morton : Kernel 2.3.99-pre1 |
53 | : Use skb_reserve to longword align IP header (two places) | 52 | : Use skb_reserve to longword align IP header (two places) |
54 | : Remove a delay loop from dma_rx() | 53 | : Remove a delay loop from dma_rx() |
55 | : Replace '100' with HZ | 54 | : Replace '100' with HZ |
@@ -57,11 +56,11 @@ | |||
57 | : Added 'cs89x0_dma=N' kernel boot option | 56 | : Added 'cs89x0_dma=N' kernel boot option |
58 | : Correctly initialise lp->lock in non-module compile | 57 | : Correctly initialise lp->lock in non-module compile |
59 | 58 | ||
60 | Andrew Morton : andrewm@uow.edu.au / Kernel 2.3.99-pre4-1 | 59 | Andrew Morton : Kernel 2.3.99-pre4-1 |
61 | : MOD_INC/DEC race fix (see | 60 | : MOD_INC/DEC race fix (see |
62 | : http://www.uwsg.indiana.edu/hypermail/linux/kernel/0003.3/1532.html) | 61 | : http://www.uwsg.indiana.edu/hypermail/linux/kernel/0003.3/1532.html) |
63 | 62 | ||
64 | Andrew Morton : andrewm@uow.edu.au / Kernel 2.4.0-test7-pre2 | 63 | Andrew Morton : Kernel 2.4.0-test7-pre2 |
65 | : Enhanced EEPROM support to cover more devices, | 64 | : Enhanced EEPROM support to cover more devices, |
66 | : abstracted IRQ mapping to support CONFIG_ARCH_CLPS7500 arch | 65 | : abstracted IRQ mapping to support CONFIG_ARCH_CLPS7500 arch |
67 | : (Jason Gunthorpe <jgg@ualberta.ca>) | 66 | : (Jason Gunthorpe <jgg@ualberta.ca>) |
@@ -156,7 +155,7 @@ | |||
156 | #include "cs89x0.h" | 155 | #include "cs89x0.h" |
157 | 156 | ||
158 | static char version[] __initdata = | 157 | static char version[] __initdata = |
159 | "cs89x0.c: v2.4.3-pre1 Russell Nelson <nelson@crynwr.com>, Andrew Morton <andrewm@uow.edu.au>\n"; | 158 | "cs89x0.c: v2.4.3-pre1 Russell Nelson <nelson@crynwr.com>, Andrew Morton\n"; |
160 | 159 | ||
161 | #define DRV_NAME "cs89x0" | 160 | #define DRV_NAME "cs89x0" |
162 | 161 | ||
@@ -1877,7 +1876,7 @@ MODULE_PARM_DESC(dmasize , "(ignored)"); | |||
1877 | MODULE_PARM_DESC(use_dma , "(ignored)"); | 1876 | MODULE_PARM_DESC(use_dma , "(ignored)"); |
1878 | #endif | 1877 | #endif |
1879 | 1878 | ||
1880 | MODULE_AUTHOR("Mike Cruse, Russwll Nelson <nelson@crynwr.com>, Andrew Morton <andrewm@uow.edu.au>"); | 1879 | MODULE_AUTHOR("Mike Cruse, Russwll Nelson <nelson@crynwr.com>, Andrew Morton"); |
1881 | MODULE_LICENSE("GPL"); | 1880 | MODULE_LICENSE("GPL"); |
1882 | 1881 | ||
1883 | 1882 | ||
diff --git a/drivers/net/irda/sir_dongle.c b/drivers/net/irda/sir_dongle.c index 36030241f7a9..2a9930e6e2af 100644 --- a/drivers/net/irda/sir_dongle.c +++ b/drivers/net/irda/sir_dongle.c | |||
@@ -67,9 +67,7 @@ int sirdev_get_dongle(struct sir_dev *dev, IRDA_DONGLE type) | |||
67 | const struct dongle_driver *drv = NULL; | 67 | const struct dongle_driver *drv = NULL; |
68 | int err = -EINVAL; | 68 | int err = -EINVAL; |
69 | 69 | ||
70 | #ifdef CONFIG_KMOD | ||
71 | request_module("irda-dongle-%d", type); | 70 | request_module("irda-dongle-%d", type); |
72 | #endif | ||
73 | 71 | ||
74 | if (dev->dongle_drv != NULL) | 72 | if (dev->dongle_drv != NULL) |
75 | return -EBUSY; | 73 | return -EBUSY; |
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 03d027c68879..7e857e938adb 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c | |||
@@ -2127,13 +2127,9 @@ ppp_set_compress(struct ppp *ppp, unsigned long arg) | |||
2127 | || ccp_option[1] < 2 || ccp_option[1] > data.length) | 2127 | || ccp_option[1] < 2 || ccp_option[1] > data.length) |
2128 | goto out; | 2128 | goto out; |
2129 | 2129 | ||
2130 | cp = find_compressor(ccp_option[0]); | 2130 | cp = try_then_request_module( |
2131 | #ifdef CONFIG_KMOD | 2131 | find_compressor(ccp_option[0]), |
2132 | if (!cp) { | 2132 | "ppp-compress-%d", ccp_option[0]); |
2133 | request_module("ppp-compress-%d", ccp_option[0]); | ||
2134 | cp = find_compressor(ccp_option[0]); | ||
2135 | } | ||
2136 | #endif /* CONFIG_KMOD */ | ||
2137 | if (!cp) | 2133 | if (!cp) |
2138 | goto out; | 2134 | goto out; |
2139 | 2135 | ||
diff --git a/drivers/net/pppox.c b/drivers/net/pppox.c index c6898c1fc54d..03aecc97fb45 100644 --- a/drivers/net/pppox.c +++ b/drivers/net/pppox.c | |||
@@ -115,13 +115,8 @@ static int pppox_create(struct net *net, struct socket *sock, int protocol) | |||
115 | goto out; | 115 | goto out; |
116 | 116 | ||
117 | rc = -EPROTONOSUPPORT; | 117 | rc = -EPROTONOSUPPORT; |
118 | #ifdef CONFIG_KMOD | 118 | if (!pppox_protos[protocol]) |
119 | if (!pppox_protos[protocol]) { | 119 | request_module("pppox-proto-%d", protocol); |
120 | char buffer[32]; | ||
121 | sprintf(buffer, "pppox-proto-%d", protocol); | ||
122 | request_module(buffer); | ||
123 | } | ||
124 | #endif | ||
125 | if (!pppox_protos[protocol] || | 120 | if (!pppox_protos[protocol] || |
126 | !try_module_get(pppox_protos[protocol]->owner)) | 121 | !try_module_get(pppox_protos[protocol]->owner)) |
127 | goto out; | 122 | goto out; |
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 74726990d59e..f05f584ab7bc 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c | |||
@@ -1640,6 +1640,11 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, | |||
1640 | return ret; | 1640 | return ret; |
1641 | } | 1641 | } |
1642 | 1642 | ||
1643 | static int ath9k_no_fragmentation(struct ieee80211_hw *hw, u32 value) | ||
1644 | { | ||
1645 | return -EOPNOTSUPP; | ||
1646 | } | ||
1647 | |||
1643 | static struct ieee80211_ops ath9k_ops = { | 1648 | static struct ieee80211_ops ath9k_ops = { |
1644 | .tx = ath9k_tx, | 1649 | .tx = ath9k_tx, |
1645 | .start = ath9k_start, | 1650 | .start = ath9k_start, |
@@ -1664,7 +1669,8 @@ static struct ieee80211_ops ath9k_ops = { | |||
1664 | .get_tsf = ath9k_get_tsf, | 1669 | .get_tsf = ath9k_get_tsf, |
1665 | .reset_tsf = ath9k_reset_tsf, | 1670 | .reset_tsf = ath9k_reset_tsf, |
1666 | .tx_last_beacon = NULL, | 1671 | .tx_last_beacon = NULL, |
1667 | .ampdu_action = ath9k_ampdu_action | 1672 | .ampdu_action = ath9k_ampdu_action, |
1673 | .set_frag_threshold = ath9k_no_fragmentation, | ||
1668 | }; | 1674 | }; |
1669 | 1675 | ||
1670 | static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 1676 | static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index f6003e7996af..5155b8a760a7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -833,12 +833,12 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | |||
833 | switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { | 833 | switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { |
834 | case CSR_HW_REV_TYPE_5100: | 834 | case CSR_HW_REV_TYPE_5100: |
835 | case CSR_HW_REV_TYPE_5300: | 835 | case CSR_HW_REV_TYPE_5300: |
836 | /* 5X00 wants in Celsius */ | 836 | case CSR_HW_REV_TYPE_5350: |
837 | /* 5X00 and 5350 wants in Celsius */ | ||
837 | priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD; | 838 | priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD; |
838 | break; | 839 | break; |
839 | case CSR_HW_REV_TYPE_5150: | 840 | case CSR_HW_REV_TYPE_5150: |
840 | case CSR_HW_REV_TYPE_5350: | 841 | /* 5150 wants in Kelvin */ |
841 | /* 5X50 wants in Kelvin */ | ||
842 | priv->hw_params.ct_kill_threshold = | 842 | priv->hw_params.ct_kill_threshold = |
843 | CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD); | 843 | CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD); |
844 | break; | 844 | break; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 93944de923ca..e2a58e477036 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -2422,7 +2422,7 @@ static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta, | |||
2422 | void *priv_sta) | 2422 | void *priv_sta) |
2423 | { | 2423 | { |
2424 | struct iwl_lq_sta *lq_sta = priv_sta; | 2424 | struct iwl_lq_sta *lq_sta = priv_sta; |
2425 | struct iwl_priv *priv = priv_r; | 2425 | struct iwl_priv *priv __maybe_unused = priv_r; |
2426 | 2426 | ||
2427 | IWL_DEBUG_RATE("enter\n"); | 2427 | IWL_DEBUG_RATE("enter\n"); |
2428 | kfree(lq_sta); | 2428 | kfree(lq_sta); |
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index a912fb68c099..297696de2da0 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c | |||
@@ -823,7 +823,9 @@ int lbs_update_channel(struct lbs_private *priv) | |||
823 | int lbs_set_channel(struct lbs_private *priv, u8 channel) | 823 | int lbs_set_channel(struct lbs_private *priv, u8 channel) |
824 | { | 824 | { |
825 | struct cmd_ds_802_11_rf_channel cmd; | 825 | struct cmd_ds_802_11_rf_channel cmd; |
826 | #ifdef DEBUG | ||
826 | u8 old_channel = priv->curbssparams.channel; | 827 | u8 old_channel = priv->curbssparams.channel; |
828 | #endif | ||
827 | int ret = 0; | 829 | int ret = 0; |
828 | 830 | ||
829 | lbs_deb_enter(LBS_DEB_CMD); | 831 | lbs_deb_enter(LBS_DEB_CMD); |
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index e585684e59a0..6fcf2bda7cdf 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c | |||
@@ -378,6 +378,7 @@ static int orinoco_cs_resume(struct pcmcia_device *link) | |||
378 | struct orinoco_private *priv = netdev_priv(dev); | 378 | struct orinoco_private *priv = netdev_priv(dev); |
379 | struct orinoco_pccard *card = priv->card; | 379 | struct orinoco_pccard *card = priv->card; |
380 | int err = 0; | 380 | int err = 0; |
381 | unsigned long flags; | ||
381 | 382 | ||
382 | if (! test_bit(0, &card->hard_reset_in_progress)) { | 383 | if (! test_bit(0, &card->hard_reset_in_progress)) { |
383 | err = orinoco_reinit_firmware(dev); | 384 | err = orinoco_reinit_firmware(dev); |
@@ -387,7 +388,7 @@ static int orinoco_cs_resume(struct pcmcia_device *link) | |||
387 | return -EIO; | 388 | return -EIO; |
388 | } | 389 | } |
389 | 390 | ||
390 | spin_lock(&priv->lock); | 391 | spin_lock_irqsave(&priv->lock, flags); |
391 | 392 | ||
392 | netif_device_attach(dev); | 393 | netif_device_attach(dev); |
393 | priv->hw_unavailable--; | 394 | priv->hw_unavailable--; |
@@ -399,7 +400,7 @@ static int orinoco_cs_resume(struct pcmcia_device *link) | |||
399 | dev->name, err); | 400 | dev->name, err); |
400 | } | 401 | } |
401 | 402 | ||
402 | spin_unlock(&priv->lock); | 403 | spin_unlock_irqrestore(&priv->lock, flags); |
403 | } | 404 | } |
404 | 405 | ||
405 | return err; | 406 | return err; |
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 1994aa199d37..117c7d3a52b0 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c | |||
@@ -479,7 +479,6 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) | |||
479 | printk(KERN_ERR "p54: eeprom parse failed!\n"); | 479 | printk(KERN_ERR "p54: eeprom parse failed!\n"); |
480 | return err; | 480 | return err; |
481 | } | 481 | } |
482 | EXPORT_SYMBOL_GPL(p54_parse_eeprom); | ||
483 | 482 | ||
484 | static int p54_rssi_to_dbm(struct ieee80211_hw *dev, int rssi) | 483 | static int p54_rssi_to_dbm(struct ieee80211_hw *dev, int rssi) |
485 | { | 484 | { |
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 1912f5e9a0a9..75d749bccb0d 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c | |||
@@ -39,6 +39,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { | |||
39 | {USB_DEVICE(0x0846, 0x4200)}, /* Netgear WG121 */ | 39 | {USB_DEVICE(0x0846, 0x4200)}, /* Netgear WG121 */ |
40 | {USB_DEVICE(0x0846, 0x4210)}, /* Netgear WG121 the second ? */ | 40 | {USB_DEVICE(0x0846, 0x4210)}, /* Netgear WG121 the second ? */ |
41 | {USB_DEVICE(0x0846, 0x4220)}, /* Netgear WG111 */ | 41 | {USB_DEVICE(0x0846, 0x4220)}, /* Netgear WG111 */ |
42 | {USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */ | ||
42 | {USB_DEVICE(0x0cde, 0x0006)}, /* Medion 40900, Roper Europe */ | 43 | {USB_DEVICE(0x0cde, 0x0006)}, /* Medion 40900, Roper Europe */ |
43 | {USB_DEVICE(0x124a, 0x4023)}, /* Shuttle PN15, Airvast WM168g, IOGear GWU513 */ | 44 | {USB_DEVICE(0x124a, 0x4023)}, /* Shuttle PN15, Airvast WM168g, IOGear GWU513 */ |
44 | {USB_DEVICE(0x1915, 0x2234)}, /* Linksys WUSB54G OEM */ | 45 | {USB_DEVICE(0x1915, 0x2234)}, /* Linksys WUSB54G OEM */ |
@@ -63,8 +64,8 @@ static struct usb_device_id p54u_table[] __devinitdata = { | |||
63 | {USB_DEVICE(0x0cde, 0x0006)}, /* Medion MD40900 */ | 64 | {USB_DEVICE(0x0cde, 0x0006)}, /* Medion MD40900 */ |
64 | {USB_DEVICE(0x0cde, 0x0008)}, /* Sagem XG703A */ | 65 | {USB_DEVICE(0x0cde, 0x0008)}, /* Sagem XG703A */ |
65 | {USB_DEVICE(0x0d8e, 0x3762)}, /* DLink DWL-G120 Cohiba */ | 66 | {USB_DEVICE(0x0d8e, 0x3762)}, /* DLink DWL-G120 Cohiba */ |
66 | {USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */ | ||
67 | {USB_DEVICE(0x124a, 0x4025)}, /* IOGear GWU513 (GW3887IK chip) */ | 67 | {USB_DEVICE(0x124a, 0x4025)}, /* IOGear GWU513 (GW3887IK chip) */ |
68 | {USB_DEVICE(0x1260, 0xee22)}, /* SMC 2862W-G version 2 */ | ||
68 | {USB_DEVICE(0x13b1, 0x000a)}, /* Linksys WUSB54G ver 2 */ | 69 | {USB_DEVICE(0x13b1, 0x000a)}, /* Linksys WUSB54G ver 2 */ |
69 | {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */ | 70 | {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */ |
70 | {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */ | 71 | {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */ |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 1676ac484790..451d410ecdae 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -374,7 +374,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) | |||
374 | struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); | 374 | struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); |
375 | struct txentry_desc txdesc; | 375 | struct txentry_desc txdesc; |
376 | struct skb_frame_desc *skbdesc; | 376 | struct skb_frame_desc *skbdesc; |
377 | unsigned int iv_len; | 377 | unsigned int iv_len = 0; |
378 | 378 | ||
379 | if (unlikely(rt2x00queue_full(queue))) | 379 | if (unlikely(rt2x00queue_full(queue))) |
380 | return -EINVAL; | 380 | return -EINVAL; |
@@ -395,6 +395,9 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) | |||
395 | entry->skb = skb; | 395 | entry->skb = skb; |
396 | rt2x00queue_create_tx_descriptor(entry, &txdesc); | 396 | rt2x00queue_create_tx_descriptor(entry, &txdesc); |
397 | 397 | ||
398 | if (IEEE80211_SKB_CB(skb)->control.hw_key != NULL) | ||
399 | iv_len = IEEE80211_SKB_CB(skb)->control.hw_key->iv_len; | ||
400 | |||
398 | /* | 401 | /* |
399 | * All information is retreived from the skb->cb array, | 402 | * All information is retreived from the skb->cb array, |
400 | * now we should claim ownership of the driver part of that | 403 | * now we should claim ownership of the driver part of that |
@@ -410,9 +413,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) | |||
410 | * the frame so we can provide it to the driver seperately. | 413 | * the frame so we can provide it to the driver seperately. |
411 | */ | 414 | */ |
412 | if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) && | 415 | if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) && |
413 | !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags) && | 416 | !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) { |
414 | (IEEE80211_SKB_CB(skb)->control.hw_key != NULL)) { | ||
415 | iv_len = IEEE80211_SKB_CB(skb)->control.hw_key->iv_len; | ||
416 | rt2x00crypto_tx_remove_iv(skb, iv_len); | 417 | rt2x00crypto_tx_remove_iv(skb, iv_len); |
417 | } | 418 | } |
418 | 419 | ||
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index e9902613e2ee..431e3c78bf27 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c | |||
@@ -33,10 +33,13 @@ MODULE_LICENSE("GPL"); | |||
33 | static struct usb_device_id rtl8187_table[] __devinitdata = { | 33 | static struct usb_device_id rtl8187_table[] __devinitdata = { |
34 | /* Asus */ | 34 | /* Asus */ |
35 | {USB_DEVICE(0x0b05, 0x171d), .driver_info = DEVICE_RTL8187}, | 35 | {USB_DEVICE(0x0b05, 0x171d), .driver_info = DEVICE_RTL8187}, |
36 | /* Belkin */ | ||
37 | {USB_DEVICE(0x050d, 0x705e), .driver_info = DEVICE_RTL8187B}, | ||
36 | /* Realtek */ | 38 | /* Realtek */ |
37 | {USB_DEVICE(0x0bda, 0x8187), .driver_info = DEVICE_RTL8187}, | 39 | {USB_DEVICE(0x0bda, 0x8187), .driver_info = DEVICE_RTL8187}, |
38 | {USB_DEVICE(0x0bda, 0x8189), .driver_info = DEVICE_RTL8187B}, | 40 | {USB_DEVICE(0x0bda, 0x8189), .driver_info = DEVICE_RTL8187B}, |
39 | {USB_DEVICE(0x0bda, 0x8197), .driver_info = DEVICE_RTL8187B}, | 41 | {USB_DEVICE(0x0bda, 0x8197), .driver_info = DEVICE_RTL8187B}, |
42 | {USB_DEVICE(0x0bda, 0x8198), .driver_info = DEVICE_RTL8187B}, | ||
40 | /* Netgear */ | 43 | /* Netgear */ |
41 | {USB_DEVICE(0x0846, 0x6100), .driver_info = DEVICE_RTL8187}, | 44 | {USB_DEVICE(0x0846, 0x6100), .driver_info = DEVICE_RTL8187}, |
42 | {USB_DEVICE(0x0846, 0x6a00), .driver_info = DEVICE_RTL8187}, | 45 | {USB_DEVICE(0x0846, 0x6a00), .driver_info = DEVICE_RTL8187}, |
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index b0c71c3be467..852789ad34b3 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c | |||
@@ -426,10 +426,11 @@ spectrum_cs_suspend(struct pcmcia_device *link) | |||
426 | { | 426 | { |
427 | struct net_device *dev = link->priv; | 427 | struct net_device *dev = link->priv; |
428 | struct orinoco_private *priv = netdev_priv(dev); | 428 | struct orinoco_private *priv = netdev_priv(dev); |
429 | unsigned long flags; | ||
429 | int err = 0; | 430 | int err = 0; |
430 | 431 | ||
431 | /* Mark the device as stopped, to block IO until later */ | 432 | /* Mark the device as stopped, to block IO until later */ |
432 | spin_lock(&priv->lock); | 433 | spin_lock_irqsave(&priv->lock, flags); |
433 | 434 | ||
434 | err = __orinoco_down(dev); | 435 | err = __orinoco_down(dev); |
435 | if (err) | 436 | if (err) |
@@ -439,7 +440,7 @@ spectrum_cs_suspend(struct pcmcia_device *link) | |||
439 | netif_device_detach(dev); | 440 | netif_device_detach(dev); |
440 | priv->hw_unavailable++; | 441 | priv->hw_unavailable++; |
441 | 442 | ||
442 | spin_unlock(&priv->lock); | 443 | spin_unlock_irqrestore(&priv->lock, flags); |
443 | 444 | ||
444 | return err; | 445 | return err; |
445 | } | 446 | } |
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 3c3dd403f5dd..5c7a87e38951 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c | |||
@@ -471,7 +471,7 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
471 | unsigned int offset = offset_in_page(data); | 471 | unsigned int offset = offset_in_page(data); |
472 | unsigned int len = skb_headlen(skb); | 472 | unsigned int len = skb_headlen(skb); |
473 | 473 | ||
474 | frags += (offset + len + PAGE_SIZE - 1) / PAGE_SIZE; | 474 | frags += DIV_ROUND_UP(offset + len, PAGE_SIZE); |
475 | if (unlikely(frags > MAX_SKB_FRAGS + 1)) { | 475 | if (unlikely(frags > MAX_SKB_FRAGS + 1)) { |
476 | printk(KERN_ALERT "xennet: skb rides the rocket: %d frags\n", | 476 | printk(KERN_ALERT "xennet: skb rides the rocket: %d frags\n", |
477 | frags); | 477 | frags); |
diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c index 2f047e573d86..f5f75844954c 100644 --- a/drivers/nubus/nubus.c +++ b/drivers/nubus/nubus.c | |||
@@ -126,7 +126,7 @@ static void nubus_advance(unsigned char **ptr, int len, int map) | |||
126 | { | 126 | { |
127 | while(not_useful(p,map)) | 127 | while(not_useful(p,map)) |
128 | p++; | 128 | p++; |
129 | p++; | 129 | p++; |
130 | len--; | 130 | len--; |
131 | } | 131 | } |
132 | *ptr = p; | 132 | *ptr = p; |
diff --git a/drivers/parport/ChangeLog b/drivers/parport/ChangeLog index db717c1d62a5..8565bbbeb6ec 100644 --- a/drivers/parport/ChangeLog +++ b/drivers/parport/ChangeLog | |||
@@ -311,7 +311,7 @@ | |||
311 | * ieee1284_ops.c (parport_ieee1284_read_nibble): Reset nAutoFd | 311 | * ieee1284_ops.c (parport_ieee1284_read_nibble): Reset nAutoFd |
312 | on timeout. Matches 2.2.x behaviour. | 312 | on timeout. Matches 2.2.x behaviour. |
313 | 313 | ||
314 | 2001-03-02 Andrew Morton <andrewm@uow.edu.au> | 314 | 2001-03-02 Andrew Morton |
315 | 315 | ||
316 | * parport_pc.c (registered_parport): New static variable. | 316 | * parport_pc.c (registered_parport): New static variable. |
317 | (parport_pc_find_ports): Set it when we register PCI driver. | 317 | (parport_pc_find_ports): Set it when we register PCI driver. |
diff --git a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c index e97059415ab4..ac2a805ac7ea 100644 --- a/drivers/parport/ieee1284.c +++ b/drivers/parport/ieee1284.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $Id: parport_ieee1284.c,v 1.4 1997/10/19 21:37:21 philip Exp $ | 1 | /* |
2 | * IEEE-1284 implementation for parport. | 2 | * IEEE-1284 implementation for parport. |
3 | * | 3 | * |
4 | * Authors: Phil Blundell <philb@gnu.org> | 4 | * Authors: Phil Blundell <philb@gnu.org> |
diff --git a/drivers/parport/probe.c b/drivers/parport/probe.c index cd565bb4e1a9..0f6550719bcf 100644 --- a/drivers/parport/probe.c +++ b/drivers/parport/probe.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $Id: parport_probe.c,v 1.1 1999/07/03 08:56:17 davem Exp $ | 1 | /* |
2 | * Parallel port device probing code | 2 | * Parallel port device probing code |
3 | * | 3 | * |
4 | * Authors: Carsten Gross, carsten@sol.wohnheim.uni-ulm.de | 4 | * Authors: Carsten Gross, carsten@sol.wohnheim.uni-ulm.de |
diff --git a/drivers/parport/share.c b/drivers/parport/share.c index a8a62bbbb576..0ebca450ed29 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $Id: parport_share.c,v 1.15 1998/01/11 12:06:17 philip Exp $ | 1 | /* |
2 | * Parallel-port resource manager code. | 2 | * Parallel-port resource manager code. |
3 | * | 3 | * |
4 | * Authors: David Campbell <campbell@tirian.che.curtin.edu.au> | 4 | * Authors: David Campbell <campbell@tirian.che.curtin.edu.au> |
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index 74d1c906c5d6..b46c60b72708 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile | |||
@@ -64,10 +64,11 @@ sa1100_cs-$(CONFIG_SA1100_SHANNON) += sa1100_shannon.o | |||
64 | sa1100_cs-$(CONFIG_SA1100_SIMPAD) += sa1100_simpad.o | 64 | sa1100_cs-$(CONFIG_SA1100_SIMPAD) += sa1100_simpad.o |
65 | 65 | ||
66 | pxa2xx_lubbock_cs-y += pxa2xx_lubbock.o sa1111_generic.o | 66 | pxa2xx_lubbock_cs-y += pxa2xx_lubbock.o sa1111_generic.o |
67 | pxa2xx_cm_x2xx_cs-y += pxa2xx_cm_x2xx.o pxa2xx_cm_x255.o pxa2xx_cm_x270.o | ||
67 | pxa2xx-obj-$(CONFIG_ARCH_LUBBOCK) += pxa2xx_lubbock_cs.o | 68 | pxa2xx-obj-$(CONFIG_ARCH_LUBBOCK) += pxa2xx_lubbock_cs.o |
68 | pxa2xx-obj-$(CONFIG_MACH_MAINSTONE) += pxa2xx_mainstone.o | 69 | pxa2xx-obj-$(CONFIG_MACH_MAINSTONE) += pxa2xx_mainstone.o |
69 | pxa2xx-obj-$(CONFIG_PXA_SHARPSL) += pxa2xx_sharpsl.o | 70 | pxa2xx-obj-$(CONFIG_PXA_SHARPSL) += pxa2xx_sharpsl.o |
70 | pxa2xx-obj-$(CONFIG_MACH_ARMCORE) += pxa2xx_cm_x2xx.o pxa2xx_cm_x255.o pxa2xx_cm_x270.o | 71 | pxa2xx-obj-$(CONFIG_MACH_ARMCORE) += pxa2xx_cm_x2xx_cs.o |
71 | pxa2xx-obj-$(CONFIG_ARCH_VIPER) += pxa2xx_viper.o | 72 | pxa2xx-obj-$(CONFIG_ARCH_VIPER) += pxa2xx_viper.o |
72 | pxa2xx-obj-$(CONFIG_TRIZEPS_PCMCIA) += pxa2xx_trizeps.o | 73 | pxa2xx-obj-$(CONFIG_TRIZEPS_PCMCIA) += pxa2xx_trizeps.o |
73 | pxa2xx-obj-$(CONFIG_MACH_PALMTX) += pxa2xx_palmtx.o | 74 | pxa2xx-obj-$(CONFIG_MACH_PALMTX) += pxa2xx_palmtx.o |
diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index 3532984a9cab..3b8b9d3cb03d 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h | |||
@@ -147,7 +147,7 @@ char *pnp_resource_type_name(struct resource *res); | |||
147 | void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc); | 147 | void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc); |
148 | 148 | ||
149 | void pnp_free_resources(struct pnp_dev *dev); | 149 | void pnp_free_resources(struct pnp_dev *dev); |
150 | int pnp_resource_type(struct resource *res); | 150 | unsigned long pnp_resource_type(struct resource *res); |
151 | 151 | ||
152 | struct pnp_resource { | 152 | struct pnp_resource { |
153 | struct list_head list; | 153 | struct list_head list; |
diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c index 7d65da821229..817fe626e15b 100644 --- a/drivers/pnp/core.c +++ b/drivers/pnp/core.c | |||
@@ -210,7 +210,6 @@ void __pnp_remove_device(struct pnp_dev *dev) | |||
210 | 210 | ||
211 | static int __init pnp_init(void) | 211 | static int __init pnp_init(void) |
212 | { | 212 | { |
213 | printk(KERN_INFO "Linux Plug and Play Support v0.97 (c) Adam Belay\n"); | ||
214 | return bus_register(&pnp_bus_type); | 213 | return bus_register(&pnp_bus_type); |
215 | } | 214 | } |
216 | 215 | ||
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c index 0bdf9b8a5e58..d15e2b77af88 100644 --- a/drivers/pnp/quirks.c +++ b/drivers/pnp/quirks.c | |||
@@ -245,7 +245,7 @@ static void quirk_system_pci_resources(struct pnp_dev *dev) | |||
245 | */ | 245 | */ |
246 | for_each_pci_dev(pdev) { | 246 | for_each_pci_dev(pdev) { |
247 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { | 247 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { |
248 | unsigned int type; | 248 | unsigned long type; |
249 | 249 | ||
250 | type = pci_resource_flags(pdev, i) & | 250 | type = pci_resource_flags(pdev, i) & |
251 | (IORESOURCE_IO | IORESOURCE_MEM); | 251 | (IORESOURCE_IO | IORESOURCE_MEM); |
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 4cfe3a1efdfb..dbae23acdd5b 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c | |||
@@ -467,14 +467,14 @@ int pnp_check_dma(struct pnp_dev *dev, struct resource *res) | |||
467 | #endif | 467 | #endif |
468 | } | 468 | } |
469 | 469 | ||
470 | int pnp_resource_type(struct resource *res) | 470 | unsigned long pnp_resource_type(struct resource *res) |
471 | { | 471 | { |
472 | return res->flags & (IORESOURCE_IO | IORESOURCE_MEM | | 472 | return res->flags & (IORESOURCE_IO | IORESOURCE_MEM | |
473 | IORESOURCE_IRQ | IORESOURCE_DMA); | 473 | IORESOURCE_IRQ | IORESOURCE_DMA); |
474 | } | 474 | } |
475 | 475 | ||
476 | struct resource *pnp_get_resource(struct pnp_dev *dev, | 476 | struct resource *pnp_get_resource(struct pnp_dev *dev, |
477 | unsigned int type, unsigned int num) | 477 | unsigned long type, unsigned int num) |
478 | { | 478 | { |
479 | struct pnp_resource *pnp_res; | 479 | struct pnp_resource *pnp_res; |
480 | struct resource *res; | 480 | struct resource *res; |
diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c index 32570af3c5c9..5fbca2681baa 100644 --- a/drivers/power/olpc_battery.c +++ b/drivers/power/olpc_battery.c | |||
@@ -205,9 +205,9 @@ static int olpc_bat_get_property(struct power_supply *psy, | |||
205 | union power_supply_propval *val) | 205 | union power_supply_propval *val) |
206 | { | 206 | { |
207 | int ret = 0; | 207 | int ret = 0; |
208 | int16_t ec_word; | 208 | __be16 ec_word; |
209 | uint8_t ec_byte; | 209 | uint8_t ec_byte; |
210 | uint64_t ser_buf; | 210 | __be64 ser_buf; |
211 | 211 | ||
212 | ret = olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &ec_byte, 1); | 212 | ret = olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &ec_byte, 1); |
213 | if (ret) | 213 | if (ret) |
@@ -257,16 +257,14 @@ static int olpc_bat_get_property(struct power_supply *psy, | |||
257 | if (ret) | 257 | if (ret) |
258 | return ret; | 258 | return ret; |
259 | 259 | ||
260 | ec_word = be16_to_cpu(ec_word); | 260 | val->intval = (int)be16_to_cpu(ec_word) * 9760L / 32; |
261 | val->intval = ec_word * 9760L / 32; | ||
262 | break; | 261 | break; |
263 | case POWER_SUPPLY_PROP_CURRENT_AVG: | 262 | case POWER_SUPPLY_PROP_CURRENT_AVG: |
264 | ret = olpc_ec_cmd(EC_BAT_CURRENT, NULL, 0, (void *)&ec_word, 2); | 263 | ret = olpc_ec_cmd(EC_BAT_CURRENT, NULL, 0, (void *)&ec_word, 2); |
265 | if (ret) | 264 | if (ret) |
266 | return ret; | 265 | return ret; |
267 | 266 | ||
268 | ec_word = be16_to_cpu(ec_word); | 267 | val->intval = (int)be16_to_cpu(ec_word) * 15625L / 120; |
269 | val->intval = ec_word * 15625L / 120; | ||
270 | break; | 268 | break; |
271 | case POWER_SUPPLY_PROP_CAPACITY: | 269 | case POWER_SUPPLY_PROP_CAPACITY: |
272 | ret = olpc_ec_cmd(EC_BAT_SOC, NULL, 0, &ec_byte, 1); | 270 | ret = olpc_ec_cmd(EC_BAT_SOC, NULL, 0, &ec_byte, 1); |
@@ -278,24 +276,22 @@ static int olpc_bat_get_property(struct power_supply *psy, | |||
278 | ret = olpc_ec_cmd(EC_BAT_TEMP, NULL, 0, (void *)&ec_word, 2); | 276 | ret = olpc_ec_cmd(EC_BAT_TEMP, NULL, 0, (void *)&ec_word, 2); |
279 | if (ret) | 277 | if (ret) |
280 | return ret; | 278 | return ret; |
281 | ec_word = be16_to_cpu(ec_word); | 279 | |
282 | val->intval = ec_word * 100 / 256; | 280 | val->intval = (int)be16_to_cpu(ec_word) * 100 / 256; |
283 | break; | 281 | break; |
284 | case POWER_SUPPLY_PROP_TEMP_AMBIENT: | 282 | case POWER_SUPPLY_PROP_TEMP_AMBIENT: |
285 | ret = olpc_ec_cmd(EC_AMB_TEMP, NULL, 0, (void *)&ec_word, 2); | 283 | ret = olpc_ec_cmd(EC_AMB_TEMP, NULL, 0, (void *)&ec_word, 2); |
286 | if (ret) | 284 | if (ret) |
287 | return ret; | 285 | return ret; |
288 | 286 | ||
289 | ec_word = be16_to_cpu(ec_word); | 287 | val->intval = (int)be16_to_cpu(ec_word) * 100 / 256; |
290 | val->intval = ec_word * 100 / 256; | ||
291 | break; | 288 | break; |
292 | case POWER_SUPPLY_PROP_CHARGE_COUNTER: | 289 | case POWER_SUPPLY_PROP_CHARGE_COUNTER: |
293 | ret = olpc_ec_cmd(EC_BAT_ACR, NULL, 0, (void *)&ec_word, 2); | 290 | ret = olpc_ec_cmd(EC_BAT_ACR, NULL, 0, (void *)&ec_word, 2); |
294 | if (ret) | 291 | if (ret) |
295 | return ret; | 292 | return ret; |
296 | 293 | ||
297 | ec_word = be16_to_cpu(ec_word); | 294 | val->intval = (int)be16_to_cpu(ec_word) * 6250 / 15; |
298 | val->intval = ec_word * 6250 / 15; | ||
299 | break; | 295 | break; |
300 | case POWER_SUPPLY_PROP_SERIAL_NUMBER: | 296 | case POWER_SUPPLY_PROP_SERIAL_NUMBER: |
301 | ret = olpc_ec_cmd(EC_BAT_SERIAL, NULL, 0, (void *)&ser_buf, 8); | 297 | ret = olpc_ec_cmd(EC_BAT_SERIAL, NULL, 0, (void *)&ser_buf, 8); |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index f3d7fd3406a6..f660ef3e5b29 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -220,22 +220,22 @@ config RTC_DRV_PCF8583 | |||
220 | will be called rtc-pcf8583. | 220 | will be called rtc-pcf8583. |
221 | 221 | ||
222 | config RTC_DRV_M41T80 | 222 | config RTC_DRV_M41T80 |
223 | tristate "ST M41T80/81/82/83/84/85/87" | 223 | tristate "ST M41T65/M41T80/81/82/83/84/85/87" |
224 | help | 224 | help |
225 | If you say Y here you will get support for the | 225 | If you say Y here you will get support for the ST M41T60 |
226 | ST M41T80 RTC chips series. Currently following chips are | 226 | and M41T80 RTC chips series. Currently, the following chips are |
227 | supported: M41T80, M41T81, M41T82, M41T83, M41ST84, M41ST85 | 227 | supported: M41T65, M41T80, M41T81, M41T82, M41T83, M41ST84, |
228 | and M41ST87. | 228 | M41ST85, and M41ST87. |
229 | 229 | ||
230 | This driver can also be built as a module. If so, the module | 230 | This driver can also be built as a module. If so, the module |
231 | will be called rtc-m41t80. | 231 | will be called rtc-m41t80. |
232 | 232 | ||
233 | config RTC_DRV_M41T80_WDT | 233 | config RTC_DRV_M41T80_WDT |
234 | bool "ST M41T80 series RTC watchdog timer" | 234 | bool "ST M41T65/M41T80 series RTC watchdog timer" |
235 | depends on RTC_DRV_M41T80 | 235 | depends on RTC_DRV_M41T80 |
236 | help | 236 | help |
237 | If you say Y here you will get support for the | 237 | If you say Y here you will get support for the |
238 | watchdog timer in ST M41T80 RTC chips series. | 238 | watchdog timer in the ST M41T60 and M41T80 RTC chips series. |
239 | 239 | ||
240 | config RTC_DRV_TWL92330 | 240 | config RTC_DRV_TWL92330 |
241 | boolean "TI TWL92330/Menelaus" | 241 | boolean "TI TWL92330/Menelaus" |
@@ -319,6 +319,15 @@ config RTC_DRV_RS5C348 | |||
319 | This driver can also be built as a module. If so, the module | 319 | This driver can also be built as a module. If so, the module |
320 | will be called rtc-rs5c348. | 320 | will be called rtc-rs5c348. |
321 | 321 | ||
322 | config RTC_DRV_DS3234 | ||
323 | tristate "Maxim/Dallas DS3234" | ||
324 | help | ||
325 | If you say yes here you get support for the | ||
326 | Maxim/Dallas DS3234 SPI RTC chip. | ||
327 | |||
328 | This driver can also be built as a module. If so, the module | ||
329 | will be called rtc-ds3234. | ||
330 | |||
322 | endif # SPI_MASTER | 331 | endif # SPI_MASTER |
323 | 332 | ||
324 | comment "Platform RTC drivers" | 333 | comment "Platform RTC drivers" |
@@ -603,7 +612,7 @@ config RTC_DRV_RS5C313 | |||
603 | 612 | ||
604 | config RTC_DRV_PPC | 613 | config RTC_DRV_PPC |
605 | tristate "PowerPC machine dependent RTC support" | 614 | tristate "PowerPC machine dependent RTC support" |
606 | depends on PPC_MERGE | 615 | depends on PPC |
607 | help | 616 | help |
608 | The PowerPC kernel has machine-specific functions for accessing | 617 | The PowerPC kernel has machine-specific functions for accessing |
609 | the RTC. This exposes that functionality through the generic RTC | 618 | the RTC. This exposes that functionality through the generic RTC |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 37a71b727262..d05928b3ca94 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -32,6 +32,7 @@ obj-$(CONFIG_RTC_DRV_DS1511) += rtc-ds1511.o | |||
32 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o | 32 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o |
33 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o | 33 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o |
34 | obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o | 34 | obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o |
35 | obj-$(CONFIG_RTC_DRV_DS3234) += rtc-ds3234.o | ||
35 | obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o | 36 | obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o |
36 | obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o | 37 | obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o |
37 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o | 38 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o |
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index 4e888cc8be5b..37082616482b 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c | |||
@@ -29,10 +29,10 @@ | |||
29 | #include <linux/completion.h> | 29 | #include <linux/completion.h> |
30 | 30 | ||
31 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
32 | |||
32 | #include <mach/at91_rtc.h> | 33 | #include <mach/at91_rtc.h> |
33 | 34 | ||
34 | 35 | ||
35 | #define AT91_RTC_FREQ 1 | ||
36 | #define AT91_RTC_EPOCH 1900UL /* just like arch/arm/common/rtctime.c */ | 36 | #define AT91_RTC_EPOCH 1900UL /* just like arch/arm/common/rtctime.c */ |
37 | 37 | ||
38 | static DECLARE_COMPLETION(at91_rtc_updated); | 38 | static DECLARE_COMPLETION(at91_rtc_updated); |
@@ -228,8 +228,6 @@ static int at91_rtc_proc(struct device *dev, struct seq_file *seq) | |||
228 | (imr & AT91_RTC_ACKUPD) ? "yes" : "no"); | 228 | (imr & AT91_RTC_ACKUPD) ? "yes" : "no"); |
229 | seq_printf(seq, "periodic_IRQ\t: %s\n", | 229 | seq_printf(seq, "periodic_IRQ\t: %s\n", |
230 | (imr & AT91_RTC_SECEV) ? "yes" : "no"); | 230 | (imr & AT91_RTC_SECEV) ? "yes" : "no"); |
231 | seq_printf(seq, "periodic_freq\t: %ld\n", | ||
232 | (unsigned long) AT91_RTC_FREQ); | ||
233 | 231 | ||
234 | return 0; | 232 | return 0; |
235 | } | 233 | } |
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 52e2743b04ec..079e9ed907e0 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c | |||
@@ -432,9 +432,15 @@ static int rtc_dev_release(struct inode *inode, struct file *file) | |||
432 | { | 432 | { |
433 | struct rtc_device *rtc = file->private_data; | 433 | struct rtc_device *rtc = file->private_data; |
434 | 434 | ||
435 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL | 435 | /* We shut down the repeating IRQs that userspace enabled, |
436 | clear_uie(rtc); | 436 | * since nothing is listening to them. |
437 | #endif | 437 | * - Update (UIE) ... currently only managed through ioctls |
438 | * - Periodic (PIE) ... also used through rtc_*() interface calls | ||
439 | * | ||
440 | * Leave the alarm alone; it may be set to trigger a system wakeup | ||
441 | * later, or be used by kernel code, and is a one-shot event anyway. | ||
442 | */ | ||
443 | rtc_dev_ioctl(file, RTC_UIE_OFF, 0); | ||
438 | rtc_irq_set_state(rtc, NULL, 0); | 444 | rtc_irq_set_state(rtc, NULL, 0); |
439 | 445 | ||
440 | if (rtc->ops->release) | 446 | if (rtc->ops->release) |
diff --git a/drivers/rtc/rtc-ds1286.c b/drivers/rtc/rtc-ds1286.c index 4b4c1b6a4187..4fcb16bbff4a 100644 --- a/drivers/rtc/rtc-ds1286.c +++ b/drivers/rtc/rtc-ds1286.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
18 | #include <linux/bcd.h> | 18 | #include <linux/bcd.h> |
19 | #include <linux/ds1286.h> | 19 | #include <linux/ds1286.h> |
20 | #include <linux/io.h> | ||
20 | 21 | ||
21 | #define DRV_VERSION "1.0" | 22 | #define DRV_VERSION "1.0" |
22 | 23 | ||
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index bbf97e65202a..4fcf0734a6ef 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c | |||
@@ -23,10 +23,6 @@ | |||
23 | * to have set the chip up as a clock (turning on the oscillator and | 23 | * to have set the chip up as a clock (turning on the oscillator and |
24 | * setting the date and time), Linux can ignore the non-clock features. | 24 | * setting the date and time), Linux can ignore the non-clock features. |
25 | * That's a natural job for a factory or repair bench. | 25 | * That's a natural job for a factory or repair bench. |
26 | * | ||
27 | * This is currently a simple no-alarms driver. If your board has the | ||
28 | * alarm irq wired up on a ds1337 or ds1339, and you want to use that, | ||
29 | * then look at the rtc-rs5c372 driver for code to steal... | ||
30 | */ | 26 | */ |
31 | enum ds_type { | 27 | enum ds_type { |
32 | ds_1307, | 28 | ds_1307, |
@@ -67,6 +63,7 @@ enum ds_type { | |||
67 | # define DS1307_BIT_RS0 0x01 | 63 | # define DS1307_BIT_RS0 0x01 |
68 | #define DS1337_REG_CONTROL 0x0e | 64 | #define DS1337_REG_CONTROL 0x0e |
69 | # define DS1337_BIT_nEOSC 0x80 | 65 | # define DS1337_BIT_nEOSC 0x80 |
66 | # define DS1339_BIT_BBSQI 0x20 | ||
70 | # define DS1337_BIT_RS2 0x10 | 67 | # define DS1337_BIT_RS2 0x10 |
71 | # define DS1337_BIT_RS1 0x08 | 68 | # define DS1337_BIT_RS1 0x08 |
72 | # define DS1337_BIT_INTCN 0x04 | 69 | # define DS1337_BIT_INTCN 0x04 |
@@ -83,19 +80,22 @@ enum ds_type { | |||
83 | # define DS1337_BIT_OSF 0x80 | 80 | # define DS1337_BIT_OSF 0x80 |
84 | # define DS1337_BIT_A2I 0x02 | 81 | # define DS1337_BIT_A2I 0x02 |
85 | # define DS1337_BIT_A1I 0x01 | 82 | # define DS1337_BIT_A1I 0x01 |
83 | #define DS1339_REG_ALARM1_SECS 0x07 | ||
86 | #define DS1339_REG_TRICKLE 0x10 | 84 | #define DS1339_REG_TRICKLE 0x10 |
87 | 85 | ||
88 | 86 | ||
89 | 87 | ||
90 | struct ds1307 { | 88 | struct ds1307 { |
91 | u8 reg_addr; | 89 | u8 reg_addr; |
92 | bool has_nvram; | 90 | u8 regs[11]; |
93 | u8 regs[8]; | ||
94 | enum ds_type type; | 91 | enum ds_type type; |
92 | unsigned long flags; | ||
93 | #define HAS_NVRAM 0 /* bit 0 == sysfs file active */ | ||
94 | #define HAS_ALARM 1 /* bit 1 == irq claimed */ | ||
95 | struct i2c_msg msg[2]; | 95 | struct i2c_msg msg[2]; |
96 | struct i2c_client *client; | 96 | struct i2c_client *client; |
97 | struct i2c_client dev; | ||
98 | struct rtc_device *rtc; | 97 | struct rtc_device *rtc; |
98 | struct work_struct work; | ||
99 | }; | 99 | }; |
100 | 100 | ||
101 | struct chip_desc { | 101 | struct chip_desc { |
@@ -132,12 +132,79 @@ static const struct i2c_device_id ds1307_id[] = { | |||
132 | }; | 132 | }; |
133 | MODULE_DEVICE_TABLE(i2c, ds1307_id); | 133 | MODULE_DEVICE_TABLE(i2c, ds1307_id); |
134 | 134 | ||
135 | /*----------------------------------------------------------------------*/ | ||
136 | |||
137 | /* | ||
138 | * The IRQ logic includes a "real" handler running in IRQ context just | ||
139 | * long enough to schedule this workqueue entry. We need a task context | ||
140 | * to talk to the RTC, since I2C I/O calls require that; and disable the | ||
141 | * IRQ until we clear its status on the chip, so that this handler can | ||
142 | * work with any type of triggering (not just falling edge). | ||
143 | * | ||
144 | * The ds1337 and ds1339 both have two alarms, but we only use the first | ||
145 | * one (with a "seconds" field). For ds1337 we expect nINTA is our alarm | ||
146 | * signal; ds1339 chips have only one alarm signal. | ||
147 | */ | ||
148 | static void ds1307_work(struct work_struct *work) | ||
149 | { | ||
150 | struct ds1307 *ds1307; | ||
151 | struct i2c_client *client; | ||
152 | struct mutex *lock; | ||
153 | int stat, control; | ||
154 | |||
155 | ds1307 = container_of(work, struct ds1307, work); | ||
156 | client = ds1307->client; | ||
157 | lock = &ds1307->rtc->ops_lock; | ||
158 | |||
159 | mutex_lock(lock); | ||
160 | stat = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS); | ||
161 | if (stat < 0) | ||
162 | goto out; | ||
163 | |||
164 | if (stat & DS1337_BIT_A1I) { | ||
165 | stat &= ~DS1337_BIT_A1I; | ||
166 | i2c_smbus_write_byte_data(client, DS1337_REG_STATUS, stat); | ||
167 | |||
168 | control = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL); | ||
169 | if (control < 0) | ||
170 | goto out; | ||
171 | |||
172 | control &= ~DS1337_BIT_A1IE; | ||
173 | i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, control); | ||
174 | |||
175 | /* rtc_update_irq() assumes that it is called | ||
176 | * from IRQ-disabled context. | ||
177 | */ | ||
178 | local_irq_disable(); | ||
179 | rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF); | ||
180 | local_irq_enable(); | ||
181 | } | ||
182 | |||
183 | out: | ||
184 | if (test_bit(HAS_ALARM, &ds1307->flags)) | ||
185 | enable_irq(client->irq); | ||
186 | mutex_unlock(lock); | ||
187 | } | ||
188 | |||
189 | static irqreturn_t ds1307_irq(int irq, void *dev_id) | ||
190 | { | ||
191 | struct i2c_client *client = dev_id; | ||
192 | struct ds1307 *ds1307 = i2c_get_clientdata(client); | ||
193 | |||
194 | disable_irq_nosync(irq); | ||
195 | schedule_work(&ds1307->work); | ||
196 | return IRQ_HANDLED; | ||
197 | } | ||
198 | |||
199 | /*----------------------------------------------------------------------*/ | ||
200 | |||
135 | static int ds1307_get_time(struct device *dev, struct rtc_time *t) | 201 | static int ds1307_get_time(struct device *dev, struct rtc_time *t) |
136 | { | 202 | { |
137 | struct ds1307 *ds1307 = dev_get_drvdata(dev); | 203 | struct ds1307 *ds1307 = dev_get_drvdata(dev); |
138 | int tmp; | 204 | int tmp; |
139 | 205 | ||
140 | /* read the RTC date and time registers all at once */ | 206 | /* read the RTC date and time registers all at once */ |
207 | ds1307->reg_addr = 0; | ||
141 | ds1307->msg[1].flags = I2C_M_RD; | 208 | ds1307->msg[1].flags = I2C_M_RD; |
142 | ds1307->msg[1].len = 7; | 209 | ds1307->msg[1].len = 7; |
143 | 210 | ||
@@ -231,9 +298,186 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t) | |||
231 | return 0; | 298 | return 0; |
232 | } | 299 | } |
233 | 300 | ||
301 | static int ds1307_read_alarm(struct device *dev, struct rtc_wkalrm *t) | ||
302 | { | ||
303 | struct i2c_client *client = to_i2c_client(dev); | ||
304 | struct ds1307 *ds1307 = i2c_get_clientdata(client); | ||
305 | int ret; | ||
306 | |||
307 | if (!test_bit(HAS_ALARM, &ds1307->flags)) | ||
308 | return -EINVAL; | ||
309 | |||
310 | /* read all ALARM1, ALARM2, and status registers at once */ | ||
311 | ds1307->reg_addr = DS1339_REG_ALARM1_SECS; | ||
312 | ds1307->msg[1].flags = I2C_M_RD; | ||
313 | ds1307->msg[1].len = 9; | ||
314 | |||
315 | ret = i2c_transfer(to_i2c_adapter(client->dev.parent), | ||
316 | ds1307->msg, 2); | ||
317 | if (ret != 2) { | ||
318 | dev_err(dev, "%s error %d\n", "alarm read", ret); | ||
319 | return -EIO; | ||
320 | } | ||
321 | |||
322 | dev_dbg(dev, "%s: %02x %02x %02x %02x, %02x %02x %02x, %02x %02x\n", | ||
323 | "alarm read", | ||
324 | ds1307->regs[0], ds1307->regs[1], | ||
325 | ds1307->regs[2], ds1307->regs[3], | ||
326 | ds1307->regs[4], ds1307->regs[5], | ||
327 | ds1307->regs[6], ds1307->regs[7], | ||
328 | ds1307->regs[8]); | ||
329 | |||
330 | /* report alarm time (ALARM1); assume 24 hour and day-of-month modes, | ||
331 | * and that all four fields are checked matches | ||
332 | */ | ||
333 | t->time.tm_sec = bcd2bin(ds1307->regs[0] & 0x7f); | ||
334 | t->time.tm_min = bcd2bin(ds1307->regs[1] & 0x7f); | ||
335 | t->time.tm_hour = bcd2bin(ds1307->regs[2] & 0x3f); | ||
336 | t->time.tm_mday = bcd2bin(ds1307->regs[3] & 0x3f); | ||
337 | t->time.tm_mon = -1; | ||
338 | t->time.tm_year = -1; | ||
339 | t->time.tm_wday = -1; | ||
340 | t->time.tm_yday = -1; | ||
341 | t->time.tm_isdst = -1; | ||
342 | |||
343 | /* ... and status */ | ||
344 | t->enabled = !!(ds1307->regs[7] & DS1337_BIT_A1IE); | ||
345 | t->pending = !!(ds1307->regs[8] & DS1337_BIT_A1I); | ||
346 | |||
347 | dev_dbg(dev, "%s secs=%d, mins=%d, " | ||
348 | "hours=%d, mday=%d, enabled=%d, pending=%d\n", | ||
349 | "alarm read", t->time.tm_sec, t->time.tm_min, | ||
350 | t->time.tm_hour, t->time.tm_mday, | ||
351 | t->enabled, t->pending); | ||
352 | |||
353 | return 0; | ||
354 | } | ||
355 | |||
356 | static int ds1307_set_alarm(struct device *dev, struct rtc_wkalrm *t) | ||
357 | { | ||
358 | struct i2c_client *client = to_i2c_client(dev); | ||
359 | struct ds1307 *ds1307 = i2c_get_clientdata(client); | ||
360 | unsigned char *buf = ds1307->regs; | ||
361 | u8 control, status; | ||
362 | int ret; | ||
363 | |||
364 | if (!test_bit(HAS_ALARM, &ds1307->flags)) | ||
365 | return -EINVAL; | ||
366 | |||
367 | dev_dbg(dev, "%s secs=%d, mins=%d, " | ||
368 | "hours=%d, mday=%d, enabled=%d, pending=%d\n", | ||
369 | "alarm set", t->time.tm_sec, t->time.tm_min, | ||
370 | t->time.tm_hour, t->time.tm_mday, | ||
371 | t->enabled, t->pending); | ||
372 | |||
373 | /* read current status of both alarms and the chip */ | ||
374 | ds1307->reg_addr = DS1339_REG_ALARM1_SECS; | ||
375 | ds1307->msg[1].flags = I2C_M_RD; | ||
376 | ds1307->msg[1].len = 9; | ||
377 | |||
378 | ret = i2c_transfer(to_i2c_adapter(client->dev.parent), | ||
379 | ds1307->msg, 2); | ||
380 | if (ret != 2) { | ||
381 | dev_err(dev, "%s error %d\n", "alarm write", ret); | ||
382 | return -EIO; | ||
383 | } | ||
384 | control = ds1307->regs[7]; | ||
385 | status = ds1307->regs[8]; | ||
386 | |||
387 | dev_dbg(dev, "%s: %02x %02x %02x %02x, %02x %02x %02x, %02x %02x\n", | ||
388 | "alarm set (old status)", | ||
389 | ds1307->regs[0], ds1307->regs[1], | ||
390 | ds1307->regs[2], ds1307->regs[3], | ||
391 | ds1307->regs[4], ds1307->regs[5], | ||
392 | ds1307->regs[6], control, status); | ||
393 | |||
394 | /* set ALARM1, using 24 hour and day-of-month modes */ | ||
395 | *buf++ = DS1339_REG_ALARM1_SECS; /* first register addr */ | ||
396 | buf[0] = bin2bcd(t->time.tm_sec); | ||
397 | buf[1] = bin2bcd(t->time.tm_min); | ||
398 | buf[2] = bin2bcd(t->time.tm_hour); | ||
399 | buf[3] = bin2bcd(t->time.tm_mday); | ||
400 | |||
401 | /* set ALARM2 to non-garbage */ | ||
402 | buf[4] = 0; | ||
403 | buf[5] = 0; | ||
404 | buf[6] = 0; | ||
405 | |||
406 | /* optionally enable ALARM1 */ | ||
407 | buf[7] = control & ~(DS1337_BIT_A1IE | DS1337_BIT_A2IE); | ||
408 | if (t->enabled) { | ||
409 | dev_dbg(dev, "alarm IRQ armed\n"); | ||
410 | buf[7] |= DS1337_BIT_A1IE; /* only ALARM1 is used */ | ||
411 | } | ||
412 | buf[8] = status & ~(DS1337_BIT_A1I | DS1337_BIT_A2I); | ||
413 | |||
414 | ds1307->msg[1].flags = 0; | ||
415 | ds1307->msg[1].len = 10; | ||
416 | |||
417 | ret = i2c_transfer(to_i2c_adapter(client->dev.parent), | ||
418 | &ds1307->msg[1], 1); | ||
419 | if (ret != 1) { | ||
420 | dev_err(dev, "can't set alarm time\n"); | ||
421 | return -EIO; | ||
422 | } | ||
423 | |||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | static int ds1307_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | ||
428 | { | ||
429 | struct i2c_client *client = to_i2c_client(dev); | ||
430 | struct ds1307 *ds1307 = i2c_get_clientdata(client); | ||
431 | int ret; | ||
432 | |||
433 | switch (cmd) { | ||
434 | case RTC_AIE_OFF: | ||
435 | if (!test_bit(HAS_ALARM, &ds1307->flags)) | ||
436 | return -ENOTTY; | ||
437 | |||
438 | ret = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL); | ||
439 | if (ret < 0) | ||
440 | return ret; | ||
441 | |||
442 | ret &= ~DS1337_BIT_A1IE; | ||
443 | |||
444 | ret = i2c_smbus_write_byte_data(client, | ||
445 | DS1337_REG_CONTROL, ret); | ||
446 | if (ret < 0) | ||
447 | return ret; | ||
448 | |||
449 | break; | ||
450 | |||
451 | case RTC_AIE_ON: | ||
452 | if (!test_bit(HAS_ALARM, &ds1307->flags)) | ||
453 | return -ENOTTY; | ||
454 | |||
455 | ret = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL); | ||
456 | if (ret < 0) | ||
457 | return ret; | ||
458 | |||
459 | ret |= DS1337_BIT_A1IE; | ||
460 | |||
461 | ret = i2c_smbus_write_byte_data(client, | ||
462 | DS1337_REG_CONTROL, ret); | ||
463 | if (ret < 0) | ||
464 | return ret; | ||
465 | |||
466 | break; | ||
467 | |||
468 | default: | ||
469 | return -ENOIOCTLCMD; | ||
470 | } | ||
471 | |||
472 | return 0; | ||
473 | } | ||
474 | |||
234 | static const struct rtc_class_ops ds13xx_rtc_ops = { | 475 | static const struct rtc_class_ops ds13xx_rtc_ops = { |
235 | .read_time = ds1307_get_time, | 476 | .read_time = ds1307_get_time, |
236 | .set_time = ds1307_set_time, | 477 | .set_time = ds1307_set_time, |
478 | .read_alarm = ds1307_read_alarm, | ||
479 | .set_alarm = ds1307_set_alarm, | ||
480 | .ioctl = ds1307_ioctl, | ||
237 | }; | 481 | }; |
238 | 482 | ||
239 | /*----------------------------------------------------------------------*/ | 483 | /*----------------------------------------------------------------------*/ |
@@ -327,6 +571,7 @@ static int __devinit ds1307_probe(struct i2c_client *client, | |||
327 | int tmp; | 571 | int tmp; |
328 | const struct chip_desc *chip = &chips[id->driver_data]; | 572 | const struct chip_desc *chip = &chips[id->driver_data]; |
329 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 573 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
574 | int want_irq = false; | ||
330 | 575 | ||
331 | if (!i2c_check_functionality(adapter, | 576 | if (!i2c_check_functionality(adapter, |
332 | I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) | 577 | I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) |
@@ -353,6 +598,12 @@ static int __devinit ds1307_probe(struct i2c_client *client, | |||
353 | switch (ds1307->type) { | 598 | switch (ds1307->type) { |
354 | case ds_1337: | 599 | case ds_1337: |
355 | case ds_1339: | 600 | case ds_1339: |
601 | /* has IRQ? */ | ||
602 | if (ds1307->client->irq > 0 && chip->alarm) { | ||
603 | INIT_WORK(&ds1307->work, ds1307_work); | ||
604 | want_irq = true; | ||
605 | } | ||
606 | |||
356 | ds1307->reg_addr = DS1337_REG_CONTROL; | 607 | ds1307->reg_addr = DS1337_REG_CONTROL; |
357 | ds1307->msg[1].len = 2; | 608 | ds1307->msg[1].len = 2; |
358 | 609 | ||
@@ -369,8 +620,20 @@ static int __devinit ds1307_probe(struct i2c_client *client, | |||
369 | 620 | ||
370 | /* oscillator off? turn it on, so clock can tick. */ | 621 | /* oscillator off? turn it on, so clock can tick. */ |
371 | if (ds1307->regs[0] & DS1337_BIT_nEOSC) | 622 | if (ds1307->regs[0] & DS1337_BIT_nEOSC) |
372 | i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, | 623 | ds1307->regs[0] &= ~DS1337_BIT_nEOSC; |
373 | ds1307->regs[0] & ~DS1337_BIT_nEOSC); | 624 | |
625 | /* Using IRQ? Disable the square wave and both alarms. | ||
626 | * For ds1339, be sure alarms can trigger when we're | ||
627 | * running on Vbackup (BBSQI); we assume ds1337 will | ||
628 | * ignore that bit | ||
629 | */ | ||
630 | if (want_irq) { | ||
631 | ds1307->regs[0] |= DS1337_BIT_INTCN | DS1339_BIT_BBSQI; | ||
632 | ds1307->regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE); | ||
633 | } | ||
634 | |||
635 | i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, | ||
636 | ds1307->regs[0]); | ||
374 | 637 | ||
375 | /* oscillator fault? clear flag, and warn */ | 638 | /* oscillator fault? clear flag, and warn */ |
376 | if (ds1307->regs[1] & DS1337_BIT_OSF) { | 639 | if (ds1307->regs[1] & DS1337_BIT_OSF) { |
@@ -495,10 +758,22 @@ read_rtc: | |||
495 | goto exit_free; | 758 | goto exit_free; |
496 | } | 759 | } |
497 | 760 | ||
761 | if (want_irq) { | ||
762 | err = request_irq(client->irq, ds1307_irq, 0, | ||
763 | ds1307->rtc->name, client); | ||
764 | if (err) { | ||
765 | dev_err(&client->dev, | ||
766 | "unable to request IRQ!\n"); | ||
767 | goto exit_irq; | ||
768 | } | ||
769 | set_bit(HAS_ALARM, &ds1307->flags); | ||
770 | dev_dbg(&client->dev, "got IRQ %d\n", client->irq); | ||
771 | } | ||
772 | |||
498 | if (chip->nvram56) { | 773 | if (chip->nvram56) { |
499 | err = sysfs_create_bin_file(&client->dev.kobj, &nvram); | 774 | err = sysfs_create_bin_file(&client->dev.kobj, &nvram); |
500 | if (err == 0) { | 775 | if (err == 0) { |
501 | ds1307->has_nvram = true; | 776 | set_bit(HAS_NVRAM, &ds1307->flags); |
502 | dev_info(&client->dev, "56 bytes nvram\n"); | 777 | dev_info(&client->dev, "56 bytes nvram\n"); |
503 | } | 778 | } |
504 | } | 779 | } |
@@ -512,7 +787,9 @@ exit_bad: | |||
512 | ds1307->regs[2], ds1307->regs[3], | 787 | ds1307->regs[2], ds1307->regs[3], |
513 | ds1307->regs[4], ds1307->regs[5], | 788 | ds1307->regs[4], ds1307->regs[5], |
514 | ds1307->regs[6]); | 789 | ds1307->regs[6]); |
515 | 790 | exit_irq: | |
791 | if (ds1307->rtc) | ||
792 | rtc_device_unregister(ds1307->rtc); | ||
516 | exit_free: | 793 | exit_free: |
517 | kfree(ds1307); | 794 | kfree(ds1307); |
518 | return err; | 795 | return err; |
@@ -520,9 +797,14 @@ exit_free: | |||
520 | 797 | ||
521 | static int __devexit ds1307_remove(struct i2c_client *client) | 798 | static int __devexit ds1307_remove(struct i2c_client *client) |
522 | { | 799 | { |
523 | struct ds1307 *ds1307 = i2c_get_clientdata(client); | 800 | struct ds1307 *ds1307 = i2c_get_clientdata(client); |
801 | |||
802 | if (test_and_clear_bit(HAS_ALARM, &ds1307->flags)) { | ||
803 | free_irq(client->irq, client); | ||
804 | cancel_work_sync(&ds1307->work); | ||
805 | } | ||
524 | 806 | ||
525 | if (ds1307->has_nvram) | 807 | if (test_and_clear_bit(HAS_NVRAM, &ds1307->flags)) |
526 | sysfs_remove_bin_file(&client->dev.kobj, &nvram); | 808 | sysfs_remove_bin_file(&client->dev.kobj, &nvram); |
527 | 809 | ||
528 | rtc_device_unregister(ds1307->rtc); | 810 | rtc_device_unregister(ds1307->rtc); |
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index a150418fba76..a5b0fc09f0c6 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c | |||
@@ -429,12 +429,33 @@ static int __devexit ds1374_remove(struct i2c_client *client) | |||
429 | return 0; | 429 | return 0; |
430 | } | 430 | } |
431 | 431 | ||
432 | #ifdef CONFIG_PM | ||
433 | static int ds1374_suspend(struct i2c_client *client, pm_message_t state) | ||
434 | { | ||
435 | if (client->irq >= 0 && device_may_wakeup(&client->dev)) | ||
436 | enable_irq_wake(client->irq); | ||
437 | return 0; | ||
438 | } | ||
439 | |||
440 | static int ds1374_resume(struct i2c_client *client) | ||
441 | { | ||
442 | if (client->irq >= 0 && device_may_wakeup(&client->dev)) | ||
443 | disable_irq_wake(client->irq); | ||
444 | return 0; | ||
445 | } | ||
446 | #else | ||
447 | #define ds1374_suspend NULL | ||
448 | #define ds1374_resume NULL | ||
449 | #endif | ||
450 | |||
432 | static struct i2c_driver ds1374_driver = { | 451 | static struct i2c_driver ds1374_driver = { |
433 | .driver = { | 452 | .driver = { |
434 | .name = "rtc-ds1374", | 453 | .name = "rtc-ds1374", |
435 | .owner = THIS_MODULE, | 454 | .owner = THIS_MODULE, |
436 | }, | 455 | }, |
437 | .probe = ds1374_probe, | 456 | .probe = ds1374_probe, |
457 | .suspend = ds1374_suspend, | ||
458 | .resume = ds1374_resume, | ||
438 | .remove = __devexit_p(ds1374_remove), | 459 | .remove = __devexit_p(ds1374_remove), |
439 | .id_table = ds1374_id, | 460 | .id_table = ds1374_id, |
440 | }; | 461 | }; |
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index 0f0d27d1c4ca..86981d34fbb6 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c | |||
@@ -379,18 +379,6 @@ ds1511_interrupt(int irq, void *dev_id) | |||
379 | return IRQ_HANDLED; | 379 | return IRQ_HANDLED; |
380 | } | 380 | } |
381 | 381 | ||
382 | static void | ||
383 | ds1511_rtc_release(struct device *dev) | ||
384 | { | ||
385 | struct platform_device *pdev = to_platform_device(dev); | ||
386 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
387 | |||
388 | if (pdata->irq >= 0) { | ||
389 | pdata->irqen = 0; | ||
390 | ds1511_rtc_update_alarm(pdata); | ||
391 | } | ||
392 | } | ||
393 | |||
394 | static int | 382 | static int |
395 | ds1511_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 383 | ds1511_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) |
396 | { | 384 | { |
@@ -428,7 +416,6 @@ static const struct rtc_class_ops ds1511_rtc_ops = { | |||
428 | .set_time = ds1511_rtc_set_time, | 416 | .set_time = ds1511_rtc_set_time, |
429 | .read_alarm = ds1511_rtc_read_alarm, | 417 | .read_alarm = ds1511_rtc_read_alarm, |
430 | .set_alarm = ds1511_rtc_set_alarm, | 418 | .set_alarm = ds1511_rtc_set_alarm, |
431 | .release = ds1511_rtc_release, | ||
432 | .ioctl = ds1511_rtc_ioctl, | 419 | .ioctl = ds1511_rtc_ioctl, |
433 | }; | 420 | }; |
434 | 421 | ||
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index a19f11415540..4ef59285b489 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c | |||
@@ -207,17 +207,6 @@ static irqreturn_t ds1553_rtc_interrupt(int irq, void *dev_id) | |||
207 | return IRQ_HANDLED; | 207 | return IRQ_HANDLED; |
208 | } | 208 | } |
209 | 209 | ||
210 | static void ds1553_rtc_release(struct device *dev) | ||
211 | { | ||
212 | struct platform_device *pdev = to_platform_device(dev); | ||
213 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
214 | |||
215 | if (pdata->irq >= 0) { | ||
216 | pdata->irqen = 0; | ||
217 | ds1553_rtc_update_alarm(pdata); | ||
218 | } | ||
219 | } | ||
220 | |||
221 | static int ds1553_rtc_ioctl(struct device *dev, unsigned int cmd, | 210 | static int ds1553_rtc_ioctl(struct device *dev, unsigned int cmd, |
222 | unsigned long arg) | 211 | unsigned long arg) |
223 | { | 212 | { |
@@ -254,7 +243,6 @@ static const struct rtc_class_ops ds1553_rtc_ops = { | |||
254 | .set_time = ds1553_rtc_set_time, | 243 | .set_time = ds1553_rtc_set_time, |
255 | .read_alarm = ds1553_rtc_read_alarm, | 244 | .read_alarm = ds1553_rtc_read_alarm, |
256 | .set_alarm = ds1553_rtc_set_alarm, | 245 | .set_alarm = ds1553_rtc_set_alarm, |
257 | .release = ds1553_rtc_release, | ||
258 | .ioctl = ds1553_rtc_ioctl, | 246 | .ioctl = ds1553_rtc_ioctl, |
259 | }; | 247 | }; |
260 | 248 | ||
diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c index 6fa4556f5f5c..341d7a5b45a2 100644 --- a/drivers/rtc/rtc-ds1672.c +++ b/drivers/rtc/rtc-ds1672.c | |||
@@ -9,17 +9,10 @@ | |||
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/i2c.h> | 12 | #include <linux/i2c.h> |
14 | #include <linux/rtc.h> | 13 | #include <linux/rtc.h> |
15 | 14 | ||
16 | #define DRV_VERSION "0.3" | 15 | #define DRV_VERSION "0.4" |
17 | |||
18 | /* Addresses to scan: none. This chip cannot be detected. */ | ||
19 | static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; | ||
20 | |||
21 | /* Insmod parameters */ | ||
22 | I2C_CLIENT_INSMOD; | ||
23 | 16 | ||
24 | /* Registers */ | 17 | /* Registers */ |
25 | 18 | ||
@@ -29,8 +22,7 @@ I2C_CLIENT_INSMOD; | |||
29 | 22 | ||
30 | #define DS1672_REG_CONTROL_EOSC 0x80 | 23 | #define DS1672_REG_CONTROL_EOSC 0x80 |
31 | 24 | ||
32 | /* Prototypes */ | 25 | static struct i2c_driver ds1672_driver; |
33 | static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind); | ||
34 | 26 | ||
35 | /* | 27 | /* |
36 | * In the routines that deal directly with the ds1672 hardware, we use | 28 | * In the routines that deal directly with the ds1672 hardware, we use |
@@ -44,8 +36,8 @@ static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
44 | unsigned char buf[4]; | 36 | unsigned char buf[4]; |
45 | 37 | ||
46 | struct i2c_msg msgs[] = { | 38 | struct i2c_msg msgs[] = { |
47 | { client->addr, 0, 1, &addr }, /* setup read ptr */ | 39 | {client->addr, 0, 1, &addr}, /* setup read ptr */ |
48 | { client->addr, I2C_M_RD, 4, buf }, /* read date */ | 40 | {client->addr, I2C_M_RD, 4, buf}, /* read date */ |
49 | }; | 41 | }; |
50 | 42 | ||
51 | /* read date registers */ | 43 | /* read date registers */ |
@@ -80,7 +72,7 @@ static int ds1672_set_mmss(struct i2c_client *client, unsigned long secs) | |||
80 | buf[2] = (secs & 0x0000FF00) >> 8; | 72 | buf[2] = (secs & 0x0000FF00) >> 8; |
81 | buf[3] = (secs & 0x00FF0000) >> 16; | 73 | buf[3] = (secs & 0x00FF0000) >> 16; |
82 | buf[4] = (secs & 0xFF000000) >> 24; | 74 | buf[4] = (secs & 0xFF000000) >> 24; |
83 | buf[5] = 0; /* set control reg to enable counting */ | 75 | buf[5] = 0; /* set control reg to enable counting */ |
84 | 76 | ||
85 | xfer = i2c_master_send(client, buf, 6); | 77 | xfer = i2c_master_send(client, buf, 6); |
86 | if (xfer != 6) { | 78 | if (xfer != 6) { |
@@ -127,8 +119,8 @@ static int ds1672_get_control(struct i2c_client *client, u8 *status) | |||
127 | unsigned char addr = DS1672_REG_CONTROL; | 119 | unsigned char addr = DS1672_REG_CONTROL; |
128 | 120 | ||
129 | struct i2c_msg msgs[] = { | 121 | struct i2c_msg msgs[] = { |
130 | { client->addr, 0, 1, &addr }, /* setup read ptr */ | 122 | {client->addr, 0, 1, &addr}, /* setup read ptr */ |
131 | { client->addr, I2C_M_RD, 1, status }, /* read control */ | 123 | {client->addr, I2C_M_RD, 1, status}, /* read control */ |
132 | }; | 124 | }; |
133 | 125 | ||
134 | /* read control register */ | 126 | /* read control register */ |
@@ -141,7 +133,8 @@ static int ds1672_get_control(struct i2c_client *client, u8 *status) | |||
141 | } | 133 | } |
142 | 134 | ||
143 | /* following are the sysfs callback functions */ | 135 | /* following are the sysfs callback functions */ |
144 | static ssize_t show_control(struct device *dev, struct device_attribute *attr, char *buf) | 136 | static ssize_t show_control(struct device *dev, struct device_attribute *attr, |
137 | char *buf) | ||
145 | { | 138 | { |
146 | struct i2c_client *client = to_i2c_client(dev); | 139 | struct i2c_client *client = to_i2c_client(dev); |
147 | u8 control; | 140 | u8 control; |
@@ -152,85 +145,46 @@ static ssize_t show_control(struct device *dev, struct device_attribute *attr, c | |||
152 | return err; | 145 | return err; |
153 | 146 | ||
154 | return sprintf(buf, "%s\n", (control & DS1672_REG_CONTROL_EOSC) | 147 | return sprintf(buf, "%s\n", (control & DS1672_REG_CONTROL_EOSC) |
155 | ? "disabled" : "enabled"); | 148 | ? "disabled" : "enabled"); |
156 | } | 149 | } |
150 | |||
157 | static DEVICE_ATTR(control, S_IRUGO, show_control, NULL); | 151 | static DEVICE_ATTR(control, S_IRUGO, show_control, NULL); |
158 | 152 | ||
159 | static const struct rtc_class_ops ds1672_rtc_ops = { | 153 | static const struct rtc_class_ops ds1672_rtc_ops = { |
160 | .read_time = ds1672_rtc_read_time, | 154 | .read_time = ds1672_rtc_read_time, |
161 | .set_time = ds1672_rtc_set_time, | 155 | .set_time = ds1672_rtc_set_time, |
162 | .set_mmss = ds1672_rtc_set_mmss, | 156 | .set_mmss = ds1672_rtc_set_mmss, |
163 | }; | 157 | }; |
164 | 158 | ||
165 | static int ds1672_attach(struct i2c_adapter *adapter) | 159 | static int ds1672_remove(struct i2c_client *client) |
166 | { | 160 | { |
167 | return i2c_probe(adapter, &addr_data, ds1672_probe); | ||
168 | } | ||
169 | |||
170 | static int ds1672_detach(struct i2c_client *client) | ||
171 | { | ||
172 | int err; | ||
173 | struct rtc_device *rtc = i2c_get_clientdata(client); | 161 | struct rtc_device *rtc = i2c_get_clientdata(client); |
174 | 162 | ||
175 | if (rtc) | 163 | if (rtc) |
176 | rtc_device_unregister(rtc); | 164 | rtc_device_unregister(rtc); |
177 | 165 | ||
178 | if ((err = i2c_detach_client(client))) | ||
179 | return err; | ||
180 | |||
181 | kfree(client); | ||
182 | |||
183 | return 0; | 166 | return 0; |
184 | } | 167 | } |
185 | 168 | ||
186 | static struct i2c_driver ds1672_driver = { | 169 | static int ds1672_probe(struct i2c_client *client, |
187 | .driver = { | 170 | const struct i2c_device_id *id) |
188 | .name = "ds1672", | ||
189 | }, | ||
190 | .id = I2C_DRIVERID_DS1672, | ||
191 | .attach_adapter = &ds1672_attach, | ||
192 | .detach_client = &ds1672_detach, | ||
193 | }; | ||
194 | |||
195 | static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind) | ||
196 | { | 171 | { |
197 | int err = 0; | 172 | int err = 0; |
198 | u8 control; | 173 | u8 control; |
199 | struct i2c_client *client; | ||
200 | struct rtc_device *rtc; | 174 | struct rtc_device *rtc; |
201 | 175 | ||
202 | dev_dbg(&adapter->dev, "%s\n", __func__); | 176 | dev_dbg(&client->dev, "%s\n", __func__); |
203 | 177 | ||
204 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { | 178 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) |
205 | err = -ENODEV; | 179 | return -ENODEV; |
206 | goto exit; | ||
207 | } | ||
208 | |||
209 | if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { | ||
210 | err = -ENOMEM; | ||
211 | goto exit; | ||
212 | } | ||
213 | |||
214 | /* I2C client */ | ||
215 | client->addr = address; | ||
216 | client->driver = &ds1672_driver; | ||
217 | client->adapter = adapter; | ||
218 | |||
219 | strlcpy(client->name, ds1672_driver.driver.name, I2C_NAME_SIZE); | ||
220 | |||
221 | /* Inform the i2c layer */ | ||
222 | if ((err = i2c_attach_client(client))) | ||
223 | goto exit_kfree; | ||
224 | 180 | ||
225 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); | 181 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); |
226 | 182 | ||
227 | rtc = rtc_device_register(ds1672_driver.driver.name, &client->dev, | 183 | rtc = rtc_device_register(ds1672_driver.driver.name, &client->dev, |
228 | &ds1672_rtc_ops, THIS_MODULE); | 184 | &ds1672_rtc_ops, THIS_MODULE); |
229 | 185 | ||
230 | if (IS_ERR(rtc)) { | 186 | if (IS_ERR(rtc)) |
231 | err = PTR_ERR(rtc); | 187 | return PTR_ERR(rtc); |
232 | goto exit_detach; | ||
233 | } | ||
234 | 188 | ||
235 | i2c_set_clientdata(client, rtc); | 189 | i2c_set_clientdata(client, rtc); |
236 | 190 | ||
@@ -241,7 +195,7 @@ static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind) | |||
241 | 195 | ||
242 | if (control & DS1672_REG_CONTROL_EOSC) | 196 | if (control & DS1672_REG_CONTROL_EOSC) |
243 | dev_warn(&client->dev, "Oscillator not enabled. " | 197 | dev_warn(&client->dev, "Oscillator not enabled. " |
244 | "Set time to enable.\n"); | 198 | "Set time to enable.\n"); |
245 | 199 | ||
246 | /* Register sysfs hooks */ | 200 | /* Register sysfs hooks */ |
247 | err = device_create_file(&client->dev, &dev_attr_control); | 201 | err = device_create_file(&client->dev, &dev_attr_control); |
@@ -250,19 +204,19 @@ static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind) | |||
250 | 204 | ||
251 | return 0; | 205 | return 0; |
252 | 206 | ||
253 | exit_devreg: | 207 | exit_devreg: |
254 | rtc_device_unregister(rtc); | 208 | rtc_device_unregister(rtc); |
255 | |||
256 | exit_detach: | ||
257 | i2c_detach_client(client); | ||
258 | |||
259 | exit_kfree: | ||
260 | kfree(client); | ||
261 | |||
262 | exit: | ||
263 | return err; | 209 | return err; |
264 | } | 210 | } |
265 | 211 | ||
212 | static struct i2c_driver ds1672_driver = { | ||
213 | .driver = { | ||
214 | .name = "rtc-ds1672", | ||
215 | }, | ||
216 | .probe = &ds1672_probe, | ||
217 | .remove = &ds1672_remove, | ||
218 | }; | ||
219 | |||
266 | static int __init ds1672_init(void) | 220 | static int __init ds1672_init(void) |
267 | { | 221 | { |
268 | return i2c_add_driver(&ds1672_driver); | 222 | return i2c_add_driver(&ds1672_driver); |
diff --git a/drivers/rtc/rtc-ds3234.c b/drivers/rtc/rtc-ds3234.c new file mode 100644 index 000000000000..37d131d03f33 --- /dev/null +++ b/drivers/rtc/rtc-ds3234.c | |||
@@ -0,0 +1,290 @@ | |||
1 | /* drivers/rtc/rtc-ds3234.c | ||
2 | * | ||
3 | * Driver for Dallas Semiconductor (DS3234) SPI RTC with Integrated Crystal | ||
4 | * and SRAM. | ||
5 | * | ||
6 | * Copyright (C) 2008 MIMOMax Wireless Ltd. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * Changelog: | ||
13 | * | ||
14 | * 07-May-2008: Dennis Aberilla <denzzzhome@yahoo.com> | ||
15 | * - Created based on the max6902 code. Only implements the | ||
16 | * date/time keeping functions; no SRAM yet. | ||
17 | */ | ||
18 | |||
19 | #include <linux/device.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/rtc.h> | ||
22 | #include <linux/spi/spi.h> | ||
23 | #include <linux/bcd.h> | ||
24 | |||
25 | #define DS3234_REG_SECONDS 0x00 | ||
26 | #define DS3234_REG_MINUTES 0x01 | ||
27 | #define DS3234_REG_HOURS 0x02 | ||
28 | #define DS3234_REG_DAY 0x03 | ||
29 | #define DS3234_REG_DATE 0x04 | ||
30 | #define DS3234_REG_MONTH 0x05 | ||
31 | #define DS3234_REG_YEAR 0x06 | ||
32 | #define DS3234_REG_CENTURY (1 << 7) /* Bit 7 of the Month register */ | ||
33 | |||
34 | #define DS3234_REG_CONTROL 0x0E | ||
35 | #define DS3234_REG_CONT_STAT 0x0F | ||
36 | |||
37 | #undef DS3234_DEBUG | ||
38 | |||
39 | struct ds3234 { | ||
40 | struct rtc_device *rtc; | ||
41 | u8 buf[8]; /* Burst read: addr + 7 regs */ | ||
42 | u8 tx_buf[2]; | ||
43 | u8 rx_buf[2]; | ||
44 | }; | ||
45 | |||
46 | static void ds3234_set_reg(struct device *dev, unsigned char address, | ||
47 | unsigned char data) | ||
48 | { | ||
49 | struct spi_device *spi = to_spi_device(dev); | ||
50 | unsigned char buf[2]; | ||
51 | |||
52 | /* MSB must be '1' to indicate write */ | ||
53 | buf[0] = address | 0x80; | ||
54 | buf[1] = data; | ||
55 | |||
56 | spi_write(spi, buf, 2); | ||
57 | } | ||
58 | |||
59 | static int ds3234_get_reg(struct device *dev, unsigned char address, | ||
60 | unsigned char *data) | ||
61 | { | ||
62 | struct spi_device *spi = to_spi_device(dev); | ||
63 | struct ds3234 *chip = dev_get_drvdata(dev); | ||
64 | struct spi_message message; | ||
65 | struct spi_transfer xfer; | ||
66 | int status; | ||
67 | |||
68 | if (!data) | ||
69 | return -EINVAL; | ||
70 | |||
71 | /* Build our spi message */ | ||
72 | spi_message_init(&message); | ||
73 | memset(&xfer, 0, sizeof(xfer)); | ||
74 | |||
75 | /* Address + dummy tx byte */ | ||
76 | xfer.len = 2; | ||
77 | xfer.tx_buf = chip->tx_buf; | ||
78 | xfer.rx_buf = chip->rx_buf; | ||
79 | |||
80 | chip->tx_buf[0] = address; | ||
81 | chip->tx_buf[1] = 0xff; | ||
82 | |||
83 | spi_message_add_tail(&xfer, &message); | ||
84 | |||
85 | /* do the i/o */ | ||
86 | status = spi_sync(spi, &message); | ||
87 | if (status == 0) | ||
88 | status = message.status; | ||
89 | else | ||
90 | return status; | ||
91 | |||
92 | *data = chip->rx_buf[1]; | ||
93 | |||
94 | return status; | ||
95 | } | ||
96 | |||
97 | static int ds3234_get_datetime(struct device *dev, struct rtc_time *dt) | ||
98 | { | ||
99 | struct spi_device *spi = to_spi_device(dev); | ||
100 | struct ds3234 *chip = dev_get_drvdata(dev); | ||
101 | struct spi_message message; | ||
102 | struct spi_transfer xfer; | ||
103 | int status; | ||
104 | |||
105 | /* build the message */ | ||
106 | spi_message_init(&message); | ||
107 | memset(&xfer, 0, sizeof(xfer)); | ||
108 | xfer.len = 1 + 7; /* Addr + 7 registers */ | ||
109 | xfer.tx_buf = chip->buf; | ||
110 | xfer.rx_buf = chip->buf; | ||
111 | chip->buf[0] = 0x00; /* Start address */ | ||
112 | spi_message_add_tail(&xfer, &message); | ||
113 | |||
114 | /* do the i/o */ | ||
115 | status = spi_sync(spi, &message); | ||
116 | if (status == 0) | ||
117 | status = message.status; | ||
118 | else | ||
119 | return status; | ||
120 | |||
121 | /* Seconds, Minutes, Hours, Day, Date, Month, Year */ | ||
122 | dt->tm_sec = bcd2bin(chip->buf[1]); | ||
123 | dt->tm_min = bcd2bin(chip->buf[2]); | ||
124 | dt->tm_hour = bcd2bin(chip->buf[3] & 0x3f); | ||
125 | dt->tm_wday = bcd2bin(chip->buf[4]) - 1; /* 0 = Sun */ | ||
126 | dt->tm_mday = bcd2bin(chip->buf[5]); | ||
127 | dt->tm_mon = bcd2bin(chip->buf[6] & 0x1f) - 1; /* 0 = Jan */ | ||
128 | dt->tm_year = bcd2bin(chip->buf[7] & 0xff) + 100; /* Assume 20YY */ | ||
129 | |||
130 | #ifdef DS3234_DEBUG | ||
131 | dev_dbg(dev, "\n%s : Read RTC values\n", __func__); | ||
132 | dev_dbg(dev, "tm_hour: %i\n", dt->tm_hour); | ||
133 | dev_dbg(dev, "tm_min : %i\n", dt->tm_min); | ||
134 | dev_dbg(dev, "tm_sec : %i\n", dt->tm_sec); | ||
135 | dev_dbg(dev, "tm_wday: %i\n", dt->tm_wday); | ||
136 | dev_dbg(dev, "tm_mday: %i\n", dt->tm_mday); | ||
137 | dev_dbg(dev, "tm_mon : %i\n", dt->tm_mon); | ||
138 | dev_dbg(dev, "tm_year: %i\n", dt->tm_year); | ||
139 | #endif | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static int ds3234_set_datetime(struct device *dev, struct rtc_time *dt) | ||
145 | { | ||
146 | #ifdef DS3234_DEBUG | ||
147 | dev_dbg(dev, "\n%s : Setting RTC values\n", __func__); | ||
148 | dev_dbg(dev, "tm_sec : %i\n", dt->tm_sec); | ||
149 | dev_dbg(dev, "tm_min : %i\n", dt->tm_min); | ||
150 | dev_dbg(dev, "tm_hour: %i\n", dt->tm_hour); | ||
151 | dev_dbg(dev, "tm_wday: %i\n", dt->tm_wday); | ||
152 | dev_dbg(dev, "tm_mday: %i\n", dt->tm_mday); | ||
153 | dev_dbg(dev, "tm_mon : %i\n", dt->tm_mon); | ||
154 | dev_dbg(dev, "tm_year: %i\n", dt->tm_year); | ||
155 | #endif | ||
156 | |||
157 | ds3234_set_reg(dev, DS3234_REG_SECONDS, bin2bcd(dt->tm_sec)); | ||
158 | ds3234_set_reg(dev, DS3234_REG_MINUTES, bin2bcd(dt->tm_min)); | ||
159 | ds3234_set_reg(dev, DS3234_REG_HOURS, bin2bcd(dt->tm_hour) & 0x3f); | ||
160 | |||
161 | /* 0 = Sun */ | ||
162 | ds3234_set_reg(dev, DS3234_REG_DAY, bin2bcd(dt->tm_wday + 1)); | ||
163 | ds3234_set_reg(dev, DS3234_REG_DATE, bin2bcd(dt->tm_mday)); | ||
164 | |||
165 | /* 0 = Jan */ | ||
166 | ds3234_set_reg(dev, DS3234_REG_MONTH, bin2bcd(dt->tm_mon + 1)); | ||
167 | |||
168 | /* Assume 20YY although we just want to make sure not to go negative. */ | ||
169 | if (dt->tm_year > 100) | ||
170 | dt->tm_year -= 100; | ||
171 | |||
172 | ds3234_set_reg(dev, DS3234_REG_YEAR, bin2bcd(dt->tm_year)); | ||
173 | |||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | static int ds3234_read_time(struct device *dev, struct rtc_time *tm) | ||
178 | { | ||
179 | return ds3234_get_datetime(dev, tm); | ||
180 | } | ||
181 | |||
182 | static int ds3234_set_time(struct device *dev, struct rtc_time *tm) | ||
183 | { | ||
184 | return ds3234_set_datetime(dev, tm); | ||
185 | } | ||
186 | |||
187 | static const struct rtc_class_ops ds3234_rtc_ops = { | ||
188 | .read_time = ds3234_read_time, | ||
189 | .set_time = ds3234_set_time, | ||
190 | }; | ||
191 | |||
192 | static int ds3234_probe(struct spi_device *spi) | ||
193 | { | ||
194 | struct rtc_device *rtc; | ||
195 | unsigned char tmp; | ||
196 | struct ds3234 *chip; | ||
197 | int res; | ||
198 | |||
199 | rtc = rtc_device_register("ds3234", | ||
200 | &spi->dev, &ds3234_rtc_ops, THIS_MODULE); | ||
201 | if (IS_ERR(rtc)) | ||
202 | return PTR_ERR(rtc); | ||
203 | |||
204 | spi->mode = SPI_MODE_3; | ||
205 | spi->bits_per_word = 8; | ||
206 | spi_setup(spi); | ||
207 | |||
208 | chip = kzalloc(sizeof(struct ds3234), GFP_KERNEL); | ||
209 | if (!chip) { | ||
210 | rtc_device_unregister(rtc); | ||
211 | return -ENOMEM; | ||
212 | } | ||
213 | chip->rtc = rtc; | ||
214 | dev_set_drvdata(&spi->dev, chip); | ||
215 | |||
216 | res = ds3234_get_reg(&spi->dev, DS3234_REG_SECONDS, &tmp); | ||
217 | if (res) { | ||
218 | rtc_device_unregister(rtc); | ||
219 | return res; | ||
220 | } | ||
221 | |||
222 | /* Control settings | ||
223 | * | ||
224 | * CONTROL_REG | ||
225 | * BIT 7 6 5 4 3 2 1 0 | ||
226 | * EOSC BBSQW CONV RS2 RS1 INTCN A2IE A1IE | ||
227 | * | ||
228 | * 0 0 0 1 1 1 0 0 | ||
229 | * | ||
230 | * CONTROL_STAT_REG | ||
231 | * BIT 7 6 5 4 3 2 1 0 | ||
232 | * OSF BB32kHz CRATE1 CRATE0 EN32kHz BSY A2F A1F | ||
233 | * | ||
234 | * 1 0 0 0 1 0 0 0 | ||
235 | */ | ||
236 | ds3234_get_reg(&spi->dev, DS3234_REG_CONTROL, &tmp); | ||
237 | ds3234_set_reg(&spi->dev, DS3234_REG_CONTROL, tmp & 0x1c); | ||
238 | |||
239 | ds3234_get_reg(&spi->dev, DS3234_REG_CONT_STAT, &tmp); | ||
240 | ds3234_set_reg(&spi->dev, DS3234_REG_CONT_STAT, tmp & 0x88); | ||
241 | |||
242 | /* Print our settings */ | ||
243 | ds3234_get_reg(&spi->dev, DS3234_REG_CONTROL, &tmp); | ||
244 | dev_info(&spi->dev, "Control Reg: 0x%02x\n", tmp); | ||
245 | |||
246 | ds3234_get_reg(&spi->dev, DS3234_REG_CONT_STAT, &tmp); | ||
247 | dev_info(&spi->dev, "Ctrl/Stat Reg: 0x%02x\n", tmp); | ||
248 | |||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | static int __exit ds3234_remove(struct spi_device *spi) | ||
253 | { | ||
254 | struct ds3234 *chip = platform_get_drvdata(spi); | ||
255 | struct rtc_device *rtc = chip->rtc; | ||
256 | |||
257 | if (rtc) | ||
258 | rtc_device_unregister(rtc); | ||
259 | |||
260 | kfree(chip); | ||
261 | |||
262 | return 0; | ||
263 | } | ||
264 | |||
265 | static struct spi_driver ds3234_driver = { | ||
266 | .driver = { | ||
267 | .name = "ds3234", | ||
268 | .bus = &spi_bus_type, | ||
269 | .owner = THIS_MODULE, | ||
270 | }, | ||
271 | .probe = ds3234_probe, | ||
272 | .remove = __devexit_p(ds3234_remove), | ||
273 | }; | ||
274 | |||
275 | static __init int ds3234_init(void) | ||
276 | { | ||
277 | printk(KERN_INFO "DS3234 SPI RTC Driver\n"); | ||
278 | return spi_register_driver(&ds3234_driver); | ||
279 | } | ||
280 | module_init(ds3234_init); | ||
281 | |||
282 | static __exit void ds3234_exit(void) | ||
283 | { | ||
284 | spi_unregister_driver(&ds3234_driver); | ||
285 | } | ||
286 | module_exit(ds3234_exit); | ||
287 | |||
288 | MODULE_DESCRIPTION("DS3234 SPI RTC driver"); | ||
289 | MODULE_AUTHOR("Dennis Aberilla <denzzzhome@yahoo.com>"); | ||
290 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index 24bc1689fc74..470fb2d29545 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c | |||
@@ -56,21 +56,27 @@ | |||
56 | #define M41T80_ALHOUR_HT (1 << 6) /* HT: Halt Update Bit */ | 56 | #define M41T80_ALHOUR_HT (1 << 6) /* HT: Halt Update Bit */ |
57 | #define M41T80_FLAGS_AF (1 << 6) /* AF: Alarm Flag Bit */ | 57 | #define M41T80_FLAGS_AF (1 << 6) /* AF: Alarm Flag Bit */ |
58 | #define M41T80_FLAGS_BATT_LOW (1 << 4) /* BL: Battery Low Bit */ | 58 | #define M41T80_FLAGS_BATT_LOW (1 << 4) /* BL: Battery Low Bit */ |
59 | #define M41T80_WATCHDOG_RB2 (1 << 7) /* RB: Watchdog resolution */ | ||
60 | #define M41T80_WATCHDOG_RB1 (1 << 1) /* RB: Watchdog resolution */ | ||
61 | #define M41T80_WATCHDOG_RB0 (1 << 0) /* RB: Watchdog resolution */ | ||
59 | 62 | ||
60 | #define M41T80_FEATURE_HT (1 << 0) | 63 | #define M41T80_FEATURE_HT (1 << 0) /* Halt feature */ |
61 | #define M41T80_FEATURE_BL (1 << 1) | 64 | #define M41T80_FEATURE_BL (1 << 1) /* Battery low indicator */ |
65 | #define M41T80_FEATURE_SQ (1 << 2) /* Squarewave feature */ | ||
66 | #define M41T80_FEATURE_WD (1 << 3) /* Extra watchdog resolution */ | ||
62 | 67 | ||
63 | #define DRV_VERSION "0.05" | 68 | #define DRV_VERSION "0.05" |
64 | 69 | ||
65 | static const struct i2c_device_id m41t80_id[] = { | 70 | static const struct i2c_device_id m41t80_id[] = { |
66 | { "m41t80", 0 }, | 71 | { "m41t65", M41T80_FEATURE_HT | M41T80_FEATURE_WD }, |
67 | { "m41t81", M41T80_FEATURE_HT }, | 72 | { "m41t80", M41T80_FEATURE_SQ }, |
68 | { "m41t81s", M41T80_FEATURE_HT | M41T80_FEATURE_BL }, | 73 | { "m41t81", M41T80_FEATURE_HT | M41T80_FEATURE_SQ}, |
69 | { "m41t82", M41T80_FEATURE_HT | M41T80_FEATURE_BL }, | 74 | { "m41t81s", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ }, |
70 | { "m41t83", M41T80_FEATURE_HT | M41T80_FEATURE_BL }, | 75 | { "m41t82", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ }, |
71 | { "m41st84", M41T80_FEATURE_HT | M41T80_FEATURE_BL }, | 76 | { "m41t83", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ }, |
72 | { "m41st85", M41T80_FEATURE_HT | M41T80_FEATURE_BL }, | 77 | { "m41st84", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ }, |
73 | { "m41st87", M41T80_FEATURE_HT | M41T80_FEATURE_BL }, | 78 | { "m41st85", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ }, |
79 | { "m41st87", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ }, | ||
74 | { } | 80 | { } |
75 | }; | 81 | }; |
76 | MODULE_DEVICE_TABLE(i2c, m41t80_id); | 82 | MODULE_DEVICE_TABLE(i2c, m41t80_id); |
@@ -386,8 +392,12 @@ static ssize_t m41t80_sysfs_show_sqwfreq(struct device *dev, | |||
386 | struct device_attribute *attr, char *buf) | 392 | struct device_attribute *attr, char *buf) |
387 | { | 393 | { |
388 | struct i2c_client *client = to_i2c_client(dev); | 394 | struct i2c_client *client = to_i2c_client(dev); |
395 | struct m41t80_data *clientdata = i2c_get_clientdata(client); | ||
389 | int val; | 396 | int val; |
390 | 397 | ||
398 | if (!(clientdata->features & M41T80_FEATURE_SQ)) | ||
399 | return -EINVAL; | ||
400 | |||
391 | val = i2c_smbus_read_byte_data(client, M41T80_REG_SQW); | 401 | val = i2c_smbus_read_byte_data(client, M41T80_REG_SQW); |
392 | if (val < 0) | 402 | if (val < 0) |
393 | return -EIO; | 403 | return -EIO; |
@@ -408,9 +418,13 @@ static ssize_t m41t80_sysfs_set_sqwfreq(struct device *dev, | |||
408 | const char *buf, size_t count) | 418 | const char *buf, size_t count) |
409 | { | 419 | { |
410 | struct i2c_client *client = to_i2c_client(dev); | 420 | struct i2c_client *client = to_i2c_client(dev); |
421 | struct m41t80_data *clientdata = i2c_get_clientdata(client); | ||
411 | int almon, sqw; | 422 | int almon, sqw; |
412 | int val = simple_strtoul(buf, NULL, 0); | 423 | int val = simple_strtoul(buf, NULL, 0); |
413 | 424 | ||
425 | if (!(clientdata->features & M41T80_FEATURE_SQ)) | ||
426 | return -EINVAL; | ||
427 | |||
414 | if (val) { | 428 | if (val) { |
415 | if (!is_power_of_2(val)) | 429 | if (!is_power_of_2(val)) |
416 | return -EINVAL; | 430 | return -EINVAL; |
@@ -499,6 +513,8 @@ static void wdt_ping(void) | |||
499 | .buf = i2c_data, | 513 | .buf = i2c_data, |
500 | }, | 514 | }, |
501 | }; | 515 | }; |
516 | struct m41t80_data *clientdata = i2c_get_clientdata(save_client); | ||
517 | |||
502 | i2c_data[0] = 0x09; /* watchdog register */ | 518 | i2c_data[0] = 0x09; /* watchdog register */ |
503 | 519 | ||
504 | if (wdt_margin > 31) | 520 | if (wdt_margin > 31) |
@@ -509,6 +525,13 @@ static void wdt_ping(void) | |||
509 | */ | 525 | */ |
510 | i2c_data[1] = wdt_margin<<2 | 0x82; | 526 | i2c_data[1] = wdt_margin<<2 | 0x82; |
511 | 527 | ||
528 | /* | ||
529 | * M41T65 has three bits for watchdog resolution. Don't set bit 7, as | ||
530 | * that would be an invalid resolution. | ||
531 | */ | ||
532 | if (clientdata->features & M41T80_FEATURE_WD) | ||
533 | i2c_data[1] &= ~M41T80_WATCHDOG_RB2; | ||
534 | |||
512 | i2c_transfer(save_client->adapter, msgs1, 1); | 535 | i2c_transfer(save_client->adapter, msgs1, 1); |
513 | } | 536 | } |
514 | 537 | ||
diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c index b9c1fe4a198e..0b2197559940 100644 --- a/drivers/rtc/rtc-m48t35.c +++ b/drivers/rtc/rtc-m48t35.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/rtc.h> | 18 | #include <linux/rtc.h> |
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/bcd.h> | 20 | #include <linux/bcd.h> |
21 | #include <linux/io.h> | ||
21 | 22 | ||
22 | #define DRV_VERSION "1.0" | 23 | #define DRV_VERSION "1.0" |
23 | 24 | ||
diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c index ded3c0abad83..12c9cd25cad8 100644 --- a/drivers/rtc/rtc-max6900.c +++ b/drivers/rtc/rtc-max6900.c | |||
@@ -17,19 +17,18 @@ | |||
17 | #include <linux/rtc.h> | 17 | #include <linux/rtc.h> |
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | 19 | ||
20 | #define DRV_NAME "max6900" | 20 | #define DRV_VERSION "0.2" |
21 | #define DRV_VERSION "0.1" | ||
22 | 21 | ||
23 | /* | 22 | /* |
24 | * register indices | 23 | * register indices |
25 | */ | 24 | */ |
26 | #define MAX6900_REG_SC 0 /* seconds 00-59 */ | 25 | #define MAX6900_REG_SC 0 /* seconds 00-59 */ |
27 | #define MAX6900_REG_MN 1 /* minutes 00-59 */ | 26 | #define MAX6900_REG_MN 1 /* minutes 00-59 */ |
28 | #define MAX6900_REG_HR 2 /* hours 00-23 */ | 27 | #define MAX6900_REG_HR 2 /* hours 00-23 */ |
29 | #define MAX6900_REG_DT 3 /* day of month 00-31 */ | 28 | #define MAX6900_REG_DT 3 /* day of month 00-31 */ |
30 | #define MAX6900_REG_MO 4 /* month 01-12 */ | 29 | #define MAX6900_REG_MO 4 /* month 01-12 */ |
31 | #define MAX6900_REG_DW 5 /* day of week 1-7 */ | 30 | #define MAX6900_REG_DW 5 /* day of week 1-7 */ |
32 | #define MAX6900_REG_YR 6 /* year 00-99 */ | 31 | #define MAX6900_REG_YR 6 /* year 00-99 */ |
33 | #define MAX6900_REG_CT 7 /* control */ | 32 | #define MAX6900_REG_CT 7 /* control */ |
34 | /* register 8 is undocumented */ | 33 | /* register 8 is undocumented */ |
35 | #define MAX6900_REG_CENTURY 9 /* century */ | 34 | #define MAX6900_REG_CENTURY 9 /* century */ |
@@ -39,7 +38,6 @@ | |||
39 | 38 | ||
40 | #define MAX6900_REG_CT_WP (1 << 7) /* Write Protect */ | 39 | #define MAX6900_REG_CT_WP (1 << 7) /* Write Protect */ |
41 | 40 | ||
42 | |||
43 | /* | 41 | /* |
44 | * register read/write commands | 42 | * register read/write commands |
45 | */ | 43 | */ |
@@ -52,16 +50,7 @@ | |||
52 | 50 | ||
53 | #define MAX6900_IDLE_TIME_AFTER_WRITE 3 /* specification says 2.5 mS */ | 51 | #define MAX6900_IDLE_TIME_AFTER_WRITE 3 /* specification says 2.5 mS */ |
54 | 52 | ||
55 | #define MAX6900_I2C_ADDR 0xa0 | 53 | static struct i2c_driver max6900_driver; |
56 | |||
57 | static const unsigned short normal_i2c[] = { | ||
58 | MAX6900_I2C_ADDR >> 1, | ||
59 | I2C_CLIENT_END | ||
60 | }; | ||
61 | |||
62 | I2C_CLIENT_INSMOD; /* defines addr_data */ | ||
63 | |||
64 | static int max6900_probe(struct i2c_adapter *adapter, int addr, int kind); | ||
65 | 54 | ||
66 | static int max6900_i2c_read_regs(struct i2c_client *client, u8 *buf) | 55 | static int max6900_i2c_read_regs(struct i2c_client *client, u8 *buf) |
67 | { | 56 | { |
@@ -69,36 +58,35 @@ static int max6900_i2c_read_regs(struct i2c_client *client, u8 *buf) | |||
69 | u8 reg_century_read[1] = { MAX6900_REG_CENTURY_READ }; | 58 | u8 reg_century_read[1] = { MAX6900_REG_CENTURY_READ }; |
70 | struct i2c_msg msgs[4] = { | 59 | struct i2c_msg msgs[4] = { |
71 | { | 60 | { |
72 | .addr = client->addr, | 61 | .addr = client->addr, |
73 | .flags = 0, /* write */ | 62 | .flags = 0, /* write */ |
74 | .len = sizeof(reg_burst_read), | 63 | .len = sizeof(reg_burst_read), |
75 | .buf = reg_burst_read | 64 | .buf = reg_burst_read} |
76 | }, | 65 | , |
77 | { | 66 | { |
78 | .addr = client->addr, | 67 | .addr = client->addr, |
79 | .flags = I2C_M_RD, | 68 | .flags = I2C_M_RD, |
80 | .len = MAX6900_BURST_LEN, | 69 | .len = MAX6900_BURST_LEN, |
81 | .buf = buf | 70 | .buf = buf} |
82 | }, | 71 | , |
83 | { | 72 | { |
84 | .addr = client->addr, | 73 | .addr = client->addr, |
85 | .flags = 0, /* write */ | 74 | .flags = 0, /* write */ |
86 | .len = sizeof(reg_century_read), | 75 | .len = sizeof(reg_century_read), |
87 | .buf = reg_century_read | 76 | .buf = reg_century_read} |
88 | }, | 77 | , |
89 | { | 78 | { |
90 | .addr = client->addr, | 79 | .addr = client->addr, |
91 | .flags = I2C_M_RD, | 80 | .flags = I2C_M_RD, |
92 | .len = sizeof(buf[MAX6900_REG_CENTURY]), | 81 | .len = sizeof(buf[MAX6900_REG_CENTURY]), |
93 | .buf = &buf[MAX6900_REG_CENTURY] | 82 | .buf = &buf[MAX6900_REG_CENTURY] |
94 | } | 83 | } |
95 | }; | 84 | }; |
96 | int rc; | 85 | int rc; |
97 | 86 | ||
98 | rc = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | 87 | rc = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); |
99 | if (rc != ARRAY_SIZE(msgs)) { | 88 | if (rc != ARRAY_SIZE(msgs)) { |
100 | dev_err(&client->dev, "%s: register read failed\n", | 89 | dev_err(&client->dev, "%s: register read failed\n", __func__); |
101 | __func__); | ||
102 | return -EIO; | 90 | return -EIO; |
103 | } | 91 | } |
104 | return 0; | 92 | return 0; |
@@ -109,20 +97,18 @@ static int max6900_i2c_write_regs(struct i2c_client *client, u8 const *buf) | |||
109 | u8 i2c_century_buf[1 + 1] = { MAX6900_REG_CENTURY_WRITE }; | 97 | u8 i2c_century_buf[1 + 1] = { MAX6900_REG_CENTURY_WRITE }; |
110 | struct i2c_msg century_msgs[1] = { | 98 | struct i2c_msg century_msgs[1] = { |
111 | { | 99 | { |
112 | .addr = client->addr, | 100 | .addr = client->addr, |
113 | .flags = 0, /* write */ | 101 | .flags = 0, /* write */ |
114 | .len = sizeof(i2c_century_buf), | 102 | .len = sizeof(i2c_century_buf), |
115 | .buf = i2c_century_buf | 103 | .buf = i2c_century_buf} |
116 | } | ||
117 | }; | 104 | }; |
118 | u8 i2c_burst_buf[MAX6900_BURST_LEN + 1] = { MAX6900_REG_BURST_WRITE }; | 105 | u8 i2c_burst_buf[MAX6900_BURST_LEN + 1] = { MAX6900_REG_BURST_WRITE }; |
119 | struct i2c_msg burst_msgs[1] = { | 106 | struct i2c_msg burst_msgs[1] = { |
120 | { | 107 | { |
121 | .addr = client->addr, | 108 | .addr = client->addr, |
122 | .flags = 0, /* write */ | 109 | .flags = 0, /* write */ |
123 | .len = sizeof(i2c_burst_buf), | 110 | .len = sizeof(i2c_burst_buf), |
124 | .buf = i2c_burst_buf | 111 | .buf = i2c_burst_buf} |
125 | } | ||
126 | }; | 112 | }; |
127 | int rc; | 113 | int rc; |
128 | 114 | ||
@@ -133,10 +119,12 @@ static int max6900_i2c_write_regs(struct i2c_client *client, u8 const *buf) | |||
133 | * bit as part of the burst write. | 119 | * bit as part of the burst write. |
134 | */ | 120 | */ |
135 | i2c_century_buf[1] = buf[MAX6900_REG_CENTURY]; | 121 | i2c_century_buf[1] = buf[MAX6900_REG_CENTURY]; |
122 | |||
136 | rc = i2c_transfer(client->adapter, century_msgs, | 123 | rc = i2c_transfer(client->adapter, century_msgs, |
137 | ARRAY_SIZE(century_msgs)); | 124 | ARRAY_SIZE(century_msgs)); |
138 | if (rc != ARRAY_SIZE(century_msgs)) | 125 | if (rc != ARRAY_SIZE(century_msgs)) |
139 | goto write_failed; | 126 | goto write_failed; |
127 | |||
140 | msleep(MAX6900_IDLE_TIME_AFTER_WRITE); | 128 | msleep(MAX6900_IDLE_TIME_AFTER_WRITE); |
141 | 129 | ||
142 | memcpy(&i2c_burst_buf[1], buf, MAX6900_BURST_LEN); | 130 | memcpy(&i2c_burst_buf[1], buf, MAX6900_BURST_LEN); |
@@ -148,45 +136,11 @@ static int max6900_i2c_write_regs(struct i2c_client *client, u8 const *buf) | |||
148 | 136 | ||
149 | return 0; | 137 | return 0; |
150 | 138 | ||
151 | write_failed: | 139 | write_failed: |
152 | dev_err(&client->dev, "%s: register write failed\n", | 140 | dev_err(&client->dev, "%s: register write failed\n", __func__); |
153 | __func__); | ||
154 | return -EIO; | 141 | return -EIO; |
155 | } | 142 | } |
156 | 143 | ||
157 | static int max6900_i2c_validate_client(struct i2c_client *client) | ||
158 | { | ||
159 | u8 regs[MAX6900_REG_LEN]; | ||
160 | u8 zero_mask[] = { | ||
161 | 0x80, /* seconds */ | ||
162 | 0x80, /* minutes */ | ||
163 | 0x40, /* hours */ | ||
164 | 0xc0, /* day of month */ | ||
165 | 0xe0, /* month */ | ||
166 | 0xf8, /* day of week */ | ||
167 | 0x00, /* year */ | ||
168 | 0x7f, /* control */ | ||
169 | }; | ||
170 | int i; | ||
171 | int rc; | ||
172 | int reserved; | ||
173 | |||
174 | reserved = i2c_smbus_read_byte_data(client, MAX6900_REG_RESERVED_READ); | ||
175 | if (reserved != 0x07) | ||
176 | return -ENODEV; | ||
177 | |||
178 | rc = max6900_i2c_read_regs(client, regs); | ||
179 | if (rc < 0) | ||
180 | return rc; | ||
181 | |||
182 | for (i = 0; i < ARRAY_SIZE(zero_mask); ++i) { | ||
183 | if (regs[i] & zero_mask[i]) | ||
184 | return -ENODEV; | ||
185 | } | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) | 144 | static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) |
191 | { | 145 | { |
192 | int rc; | 146 | int rc; |
@@ -202,7 +156,7 @@ static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) | |||
202 | tm->tm_mday = BCD2BIN(regs[MAX6900_REG_DT]); | 156 | tm->tm_mday = BCD2BIN(regs[MAX6900_REG_DT]); |
203 | tm->tm_mon = BCD2BIN(regs[MAX6900_REG_MO]) - 1; | 157 | tm->tm_mon = BCD2BIN(regs[MAX6900_REG_MO]) - 1; |
204 | tm->tm_year = BCD2BIN(regs[MAX6900_REG_YR]) + | 158 | tm->tm_year = BCD2BIN(regs[MAX6900_REG_YR]) + |
205 | BCD2BIN(regs[MAX6900_REG_CENTURY]) * 100 - 1900; | 159 | BCD2BIN(regs[MAX6900_REG_CENTURY]) * 100 - 1900; |
206 | tm->tm_wday = BCD2BIN(regs[MAX6900_REG_DW]); | 160 | tm->tm_wday = BCD2BIN(regs[MAX6900_REG_DW]); |
207 | 161 | ||
208 | return 0; | 162 | return 0; |
@@ -211,7 +165,7 @@ static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) | |||
211 | static int max6900_i2c_clear_write_protect(struct i2c_client *client) | 165 | static int max6900_i2c_clear_write_protect(struct i2c_client *client) |
212 | { | 166 | { |
213 | int rc; | 167 | int rc; |
214 | rc = i2c_smbus_write_byte_data (client, MAX6900_REG_CONTROL_WRITE, 0); | 168 | rc = i2c_smbus_write_byte_data(client, MAX6900_REG_CONTROL_WRITE, 0); |
215 | if (rc < 0) { | 169 | if (rc < 0) { |
216 | dev_err(&client->dev, "%s: control register write failed\n", | 170 | dev_err(&client->dev, "%s: control register write failed\n", |
217 | __func__); | 171 | __func__); |
@@ -220,8 +174,8 @@ static int max6900_i2c_clear_write_protect(struct i2c_client *client) | |||
220 | return 0; | 174 | return 0; |
221 | } | 175 | } |
222 | 176 | ||
223 | static int max6900_i2c_set_time(struct i2c_client *client, | 177 | static int |
224 | struct rtc_time const *tm) | 178 | max6900_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm) |
225 | { | 179 | { |
226 | u8 regs[MAX6900_REG_LEN]; | 180 | u8 regs[MAX6900_REG_LEN]; |
227 | int rc; | 181 | int rc; |
@@ -258,89 +212,49 @@ static int max6900_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
258 | return max6900_i2c_set_time(to_i2c_client(dev), tm); | 212 | return max6900_i2c_set_time(to_i2c_client(dev), tm); |
259 | } | 213 | } |
260 | 214 | ||
261 | static int max6900_attach_adapter(struct i2c_adapter *adapter) | 215 | static int max6900_remove(struct i2c_client *client) |
262 | { | ||
263 | return i2c_probe(adapter, &addr_data, max6900_probe); | ||
264 | } | ||
265 | |||
266 | static int max6900_detach_client(struct i2c_client *client) | ||
267 | { | 216 | { |
268 | struct rtc_device *const rtc = i2c_get_clientdata(client); | 217 | struct rtc_device *rtc = i2c_get_clientdata(client); |
269 | 218 | ||
270 | if (rtc) | 219 | if (rtc) |
271 | rtc_device_unregister(rtc); | 220 | rtc_device_unregister(rtc); |
272 | 221 | ||
273 | return i2c_detach_client(client); | 222 | return 0; |
274 | } | 223 | } |
275 | 224 | ||
276 | static struct i2c_driver max6900_driver = { | ||
277 | .driver = { | ||
278 | .name = DRV_NAME, | ||
279 | }, | ||
280 | .id = I2C_DRIVERID_MAX6900, | ||
281 | .attach_adapter = max6900_attach_adapter, | ||
282 | .detach_client = max6900_detach_client, | ||
283 | }; | ||
284 | |||
285 | static const struct rtc_class_ops max6900_rtc_ops = { | 225 | static const struct rtc_class_ops max6900_rtc_ops = { |
286 | .read_time = max6900_rtc_read_time, | 226 | .read_time = max6900_rtc_read_time, |
287 | .set_time = max6900_rtc_set_time, | 227 | .set_time = max6900_rtc_set_time, |
288 | }; | 228 | }; |
289 | 229 | ||
290 | static int max6900_probe(struct i2c_adapter *adapter, int addr, int kind) | 230 | static int |
231 | max6900_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||
291 | { | 232 | { |
292 | int rc = 0; | 233 | struct rtc_device *rtc; |
293 | struct i2c_client *client = NULL; | ||
294 | struct rtc_device *rtc = NULL; | ||
295 | |||
296 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { | ||
297 | rc = -ENODEV; | ||
298 | goto failout; | ||
299 | } | ||
300 | |||
301 | client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
302 | if (client == NULL) { | ||
303 | rc = -ENOMEM; | ||
304 | goto failout; | ||
305 | } | ||
306 | |||
307 | client->addr = addr; | ||
308 | client->adapter = adapter; | ||
309 | client->driver = &max6900_driver; | ||
310 | strlcpy(client->name, DRV_NAME, I2C_NAME_SIZE); | ||
311 | |||
312 | if (kind < 0) { | ||
313 | rc = max6900_i2c_validate_client(client); | ||
314 | if (rc < 0) | ||
315 | goto failout; | ||
316 | } | ||
317 | 234 | ||
318 | rc = i2c_attach_client(client); | 235 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) |
319 | if (rc < 0) | 236 | return -ENODEV; |
320 | goto failout; | ||
321 | 237 | ||
322 | dev_info(&client->dev, | 238 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); |
323 | "chip found, driver version " DRV_VERSION "\n"); | ||
324 | 239 | ||
325 | rtc = rtc_device_register(max6900_driver.driver.name, | 240 | rtc = rtc_device_register(max6900_driver.driver.name, |
326 | &client->dev, | 241 | &client->dev, &max6900_rtc_ops, THIS_MODULE); |
327 | &max6900_rtc_ops, THIS_MODULE); | 242 | if (IS_ERR(rtc)) |
328 | if (IS_ERR(rtc)) { | 243 | return PTR_ERR(rtc); |
329 | rc = PTR_ERR(rtc); | ||
330 | goto failout_detach; | ||
331 | } | ||
332 | 244 | ||
333 | i2c_set_clientdata(client, rtc); | 245 | i2c_set_clientdata(client, rtc); |
334 | 246 | ||
335 | return 0; | 247 | return 0; |
336 | |||
337 | failout_detach: | ||
338 | i2c_detach_client(client); | ||
339 | failout: | ||
340 | kfree(client); | ||
341 | return rc; | ||
342 | } | 248 | } |
343 | 249 | ||
250 | static struct i2c_driver max6900_driver = { | ||
251 | .driver = { | ||
252 | .name = "rtc-max6900", | ||
253 | }, | ||
254 | .probe = max6900_probe, | ||
255 | .remove = max6900_remove, | ||
256 | }; | ||
257 | |||
344 | static int __init max6900_init(void) | 258 | static int __init max6900_init(void) |
345 | { | 259 | { |
346 | return i2c_add_driver(&max6900_driver); | 260 | return i2c_add_driver(&max6900_driver); |
@@ -352,6 +266,7 @@ static void __exit max6900_exit(void) | |||
352 | } | 266 | } |
353 | 267 | ||
354 | MODULE_DESCRIPTION("Maxim MAX6900 RTC driver"); | 268 | MODULE_DESCRIPTION("Maxim MAX6900 RTC driver"); |
269 | MODULE_AUTHOR("Dale Farnsworth <dale@farnsworth.org>"); | ||
355 | MODULE_LICENSE("GPL"); | 270 | MODULE_LICENSE("GPL"); |
356 | MODULE_VERSION(DRV_VERSION); | 271 | MODULE_VERSION(DRV_VERSION); |
357 | 272 | ||
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 748a502a6355..a829f20ad6d6 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c | |||
@@ -179,58 +179,6 @@ struct pcf8563_limit | |||
179 | unsigned char max; | 179 | unsigned char max; |
180 | }; | 180 | }; |
181 | 181 | ||
182 | static int pcf8563_validate_client(struct i2c_client *client) | ||
183 | { | ||
184 | int i; | ||
185 | |||
186 | static const struct pcf8563_limit pattern[] = { | ||
187 | /* register, mask, min, max */ | ||
188 | { PCF8563_REG_SC, 0x7F, 0, 59 }, | ||
189 | { PCF8563_REG_MN, 0x7F, 0, 59 }, | ||
190 | { PCF8563_REG_HR, 0x3F, 0, 23 }, | ||
191 | { PCF8563_REG_DM, 0x3F, 0, 31 }, | ||
192 | { PCF8563_REG_MO, 0x1F, 0, 12 }, | ||
193 | }; | ||
194 | |||
195 | /* check limits (only registers with bcd values) */ | ||
196 | for (i = 0; i < ARRAY_SIZE(pattern); i++) { | ||
197 | int xfer; | ||
198 | unsigned char value; | ||
199 | unsigned char buf = pattern[i].reg; | ||
200 | |||
201 | struct i2c_msg msgs[] = { | ||
202 | { client->addr, 0, 1, &buf }, | ||
203 | { client->addr, I2C_M_RD, 1, &buf }, | ||
204 | }; | ||
205 | |||
206 | xfer = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
207 | |||
208 | if (xfer != ARRAY_SIZE(msgs)) { | ||
209 | dev_err(&client->dev, | ||
210 | "%s: could not read register 0x%02X\n", | ||
211 | __func__, pattern[i].reg); | ||
212 | |||
213 | return -EIO; | ||
214 | } | ||
215 | |||
216 | value = BCD2BIN(buf & pattern[i].mask); | ||
217 | |||
218 | if (value > pattern[i].max || | ||
219 | value < pattern[i].min) { | ||
220 | dev_dbg(&client->dev, | ||
221 | "%s: pattern=%d, reg=%x, mask=0x%02x, min=%d, " | ||
222 | "max=%d, value=%d, raw=0x%02X\n", | ||
223 | __func__, i, pattern[i].reg, pattern[i].mask, | ||
224 | pattern[i].min, pattern[i].max, | ||
225 | value, buf); | ||
226 | |||
227 | return -ENODEV; | ||
228 | } | ||
229 | } | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm) | 182 | static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm) |
235 | { | 183 | { |
236 | return pcf8563_get_datetime(to_i2c_client(dev), tm); | 184 | return pcf8563_get_datetime(to_i2c_client(dev), tm); |
@@ -262,12 +210,6 @@ static int pcf8563_probe(struct i2c_client *client, | |||
262 | if (!pcf8563) | 210 | if (!pcf8563) |
263 | return -ENOMEM; | 211 | return -ENOMEM; |
264 | 212 | ||
265 | /* Verify the chip is really an PCF8563 */ | ||
266 | if (pcf8563_validate_client(client) < 0) { | ||
267 | err = -ENODEV; | ||
268 | goto exit_kfree; | ||
269 | } | ||
270 | |||
271 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); | 213 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); |
272 | 214 | ||
273 | pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name, | 215 | pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name, |
diff --git a/drivers/rtc/rtc-pl030.c b/drivers/rtc/rtc-pl030.c index 8448eeb9d675..826153552157 100644 --- a/drivers/rtc/rtc-pl030.c +++ b/drivers/rtc/rtc-pl030.c | |||
@@ -34,15 +34,6 @@ static irqreturn_t pl030_interrupt(int irq, void *dev_id) | |||
34 | return IRQ_HANDLED; | 34 | return IRQ_HANDLED; |
35 | } | 35 | } |
36 | 36 | ||
37 | static int pl030_open(struct device *dev) | ||
38 | { | ||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | static void pl030_release(struct device *dev) | ||
43 | { | ||
44 | } | ||
45 | |||
46 | static int pl030_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 37 | static int pl030_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) |
47 | { | 38 | { |
48 | return -ENOIOCTLCMD; | 39 | return -ENOIOCTLCMD; |
@@ -104,8 +95,6 @@ static int pl030_set_time(struct device *dev, struct rtc_time *tm) | |||
104 | } | 95 | } |
105 | 96 | ||
106 | static const struct rtc_class_ops pl030_ops = { | 97 | static const struct rtc_class_ops pl030_ops = { |
107 | .open = pl030_open, | ||
108 | .release = pl030_release, | ||
109 | .ioctl = pl030_ioctl, | 98 | .ioctl = pl030_ioctl, |
110 | .read_time = pl030_read_time, | 99 | .read_time = pl030_read_time, |
111 | .set_time = pl030_set_time, | 100 | .set_time = pl030_set_time, |
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 08b4610ec5a6..333eec689d2f 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c | |||
@@ -45,18 +45,6 @@ static irqreturn_t pl031_interrupt(int irq, void *dev_id) | |||
45 | return IRQ_HANDLED; | 45 | return IRQ_HANDLED; |
46 | } | 46 | } |
47 | 47 | ||
48 | static int pl031_open(struct device *dev) | ||
49 | { | ||
50 | /* | ||
51 | * We request IRQ in pl031_probe, so nothing to do here... | ||
52 | */ | ||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | static void pl031_release(struct device *dev) | ||
57 | { | ||
58 | } | ||
59 | |||
60 | static int pl031_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 48 | static int pl031_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) |
61 | { | 49 | { |
62 | struct pl031_local *ldata = dev_get_drvdata(dev); | 50 | struct pl031_local *ldata = dev_get_drvdata(dev); |
@@ -118,8 +106,6 @@ static int pl031_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
118 | } | 106 | } |
119 | 107 | ||
120 | static const struct rtc_class_ops pl031_ops = { | 108 | static const struct rtc_class_ops pl031_ops = { |
121 | .open = pl031_open, | ||
122 | .release = pl031_release, | ||
123 | .ioctl = pl031_ioctl, | 109 | .ioctl = pl031_ioctl, |
124 | .read_time = pl031_read_time, | 110 | .read_time = pl031_read_time, |
125 | .set_time = pl031_set_time, | 111 | .set_time = pl031_set_time, |
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index 56caf6b2c3e5..8b561958fb1e 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c | |||
@@ -1,8 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * An I2C driver for Ricoh RS5C372 and RV5C38[67] RTCs | 2 | * An I2C driver for Ricoh RS5C372, R2025S/D and RV5C38[67] RTCs |
3 | * | 3 | * |
4 | * Copyright (C) 2005 Pavel Mironchik <pmironchik@optifacio.net> | 4 | * Copyright (C) 2005 Pavel Mironchik <pmironchik@optifacio.net> |
5 | * Copyright (C) 2006 Tower Technologies | 5 | * Copyright (C) 2006 Tower Technologies |
6 | * Copyright (C) 2008 Paul Mundt | ||
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
@@ -13,7 +14,7 @@ | |||
13 | #include <linux/rtc.h> | 14 | #include <linux/rtc.h> |
14 | #include <linux/bcd.h> | 15 | #include <linux/bcd.h> |
15 | 16 | ||
16 | #define DRV_VERSION "0.5" | 17 | #define DRV_VERSION "0.6" |
17 | 18 | ||
18 | 19 | ||
19 | /* | 20 | /* |
@@ -51,7 +52,8 @@ | |||
51 | # define RS5C_CTRL1_CT4 (4 << 0) /* 1 Hz level irq */ | 52 | # define RS5C_CTRL1_CT4 (4 << 0) /* 1 Hz level irq */ |
52 | #define RS5C_REG_CTRL2 15 | 53 | #define RS5C_REG_CTRL2 15 |
53 | # define RS5C372_CTRL2_24 (1 << 5) | 54 | # define RS5C372_CTRL2_24 (1 << 5) |
54 | # define RS5C_CTRL2_XSTP (1 << 4) | 55 | # define R2025_CTRL2_XST (1 << 5) |
56 | # define RS5C_CTRL2_XSTP (1 << 4) /* only if !R2025S/D */ | ||
55 | # define RS5C_CTRL2_CTFG (1 << 2) | 57 | # define RS5C_CTRL2_CTFG (1 << 2) |
56 | # define RS5C_CTRL2_AAFG (1 << 1) /* or WAFG */ | 58 | # define RS5C_CTRL2_AAFG (1 << 1) /* or WAFG */ |
57 | # define RS5C_CTRL2_BAFG (1 << 0) /* or DAFG */ | 59 | # define RS5C_CTRL2_BAFG (1 << 0) /* or DAFG */ |
@@ -63,6 +65,7 @@ | |||
63 | 65 | ||
64 | enum rtc_type { | 66 | enum rtc_type { |
65 | rtc_undef = 0, | 67 | rtc_undef = 0, |
68 | rtc_r2025sd, | ||
66 | rtc_rs5c372a, | 69 | rtc_rs5c372a, |
67 | rtc_rs5c372b, | 70 | rtc_rs5c372b, |
68 | rtc_rv5c386, | 71 | rtc_rv5c386, |
@@ -70,6 +73,7 @@ enum rtc_type { | |||
70 | }; | 73 | }; |
71 | 74 | ||
72 | static const struct i2c_device_id rs5c372_id[] = { | 75 | static const struct i2c_device_id rs5c372_id[] = { |
76 | { "r2025sd", rtc_r2025sd }, | ||
73 | { "rs5c372a", rtc_rs5c372a }, | 77 | { "rs5c372a", rtc_rs5c372a }, |
74 | { "rs5c372b", rtc_rs5c372b }, | 78 | { "rs5c372b", rtc_rs5c372b }, |
75 | { "rv5c386", rtc_rv5c386 }, | 79 | { "rv5c386", rtc_rv5c386 }, |
@@ -89,6 +93,7 @@ struct rs5c372 { | |||
89 | enum rtc_type type; | 93 | enum rtc_type type; |
90 | unsigned time24:1; | 94 | unsigned time24:1; |
91 | unsigned has_irq:1; | 95 | unsigned has_irq:1; |
96 | unsigned smbus:1; | ||
92 | char buf[17]; | 97 | char buf[17]; |
93 | char *regs; | 98 | char *regs; |
94 | }; | 99 | }; |
@@ -106,10 +111,25 @@ static int rs5c_get_regs(struct rs5c372 *rs5c) | |||
106 | * | 111 | * |
107 | * The first method doesn't work with the iop3xx adapter driver, on at | 112 | * The first method doesn't work with the iop3xx adapter driver, on at |
108 | * least 80219 chips; this works around that bug. | 113 | * least 80219 chips; this works around that bug. |
114 | * | ||
115 | * The third method on the other hand doesn't work for the SMBus-only | ||
116 | * configurations, so we use the the first method there, stripping off | ||
117 | * the extra register in the process. | ||
109 | */ | 118 | */ |
110 | if ((i2c_transfer(client->adapter, msgs, 1)) != 1) { | 119 | if (rs5c->smbus) { |
111 | dev_warn(&client->dev, "can't read registers\n"); | 120 | int addr = RS5C_ADDR(RS5C372_REG_SECS); |
112 | return -EIO; | 121 | int size = sizeof(rs5c->buf) - 1; |
122 | |||
123 | if (i2c_smbus_read_i2c_block_data(client, addr, size, | ||
124 | rs5c->buf + 1) != size) { | ||
125 | dev_warn(&client->dev, "can't read registers\n"); | ||
126 | return -EIO; | ||
127 | } | ||
128 | } else { | ||
129 | if ((i2c_transfer(client->adapter, msgs, 1)) != 1) { | ||
130 | dev_warn(&client->dev, "can't read registers\n"); | ||
131 | return -EIO; | ||
132 | } | ||
113 | } | 133 | } |
114 | 134 | ||
115 | dev_dbg(&client->dev, | 135 | dev_dbg(&client->dev, |
@@ -187,6 +207,7 @@ static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
187 | { | 207 | { |
188 | struct rs5c372 *rs5c = i2c_get_clientdata(client); | 208 | struct rs5c372 *rs5c = i2c_get_clientdata(client); |
189 | unsigned char buf[8]; | 209 | unsigned char buf[8]; |
210 | int addr; | ||
190 | 211 | ||
191 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d " | 212 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d " |
192 | "mday=%d, mon=%d, year=%d, wday=%d\n", | 213 | "mday=%d, mon=%d, year=%d, wday=%d\n", |
@@ -194,16 +215,16 @@ static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
194 | tm->tm_sec, tm->tm_min, tm->tm_hour, | 215 | tm->tm_sec, tm->tm_min, tm->tm_hour, |
195 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | 216 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); |
196 | 217 | ||
197 | buf[0] = RS5C_ADDR(RS5C372_REG_SECS); | 218 | addr = RS5C_ADDR(RS5C372_REG_SECS); |
198 | buf[1] = BIN2BCD(tm->tm_sec); | 219 | buf[0] = BIN2BCD(tm->tm_sec); |
199 | buf[2] = BIN2BCD(tm->tm_min); | 220 | buf[1] = BIN2BCD(tm->tm_min); |
200 | buf[3] = rs5c_hr2reg(rs5c, tm->tm_hour); | 221 | buf[2] = rs5c_hr2reg(rs5c, tm->tm_hour); |
201 | buf[4] = BIN2BCD(tm->tm_wday); | 222 | buf[3] = BIN2BCD(tm->tm_wday); |
202 | buf[5] = BIN2BCD(tm->tm_mday); | 223 | buf[4] = BIN2BCD(tm->tm_mday); |
203 | buf[6] = BIN2BCD(tm->tm_mon + 1); | 224 | buf[5] = BIN2BCD(tm->tm_mon + 1); |
204 | buf[7] = BIN2BCD(tm->tm_year - 100); | 225 | buf[6] = BIN2BCD(tm->tm_year - 100); |
205 | 226 | ||
206 | if ((i2c_master_send(client, buf, 8)) != 8) { | 227 | if (i2c_smbus_write_i2c_block_data(client, addr, sizeof(buf), buf) < 0) { |
207 | dev_err(&client->dev, "%s: write error\n", __func__); | 228 | dev_err(&client->dev, "%s: write error\n", __func__); |
208 | return -EIO; | 229 | return -EIO; |
209 | } | 230 | } |
@@ -266,16 +287,16 @@ rs5c_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
266 | { | 287 | { |
267 | struct i2c_client *client = to_i2c_client(dev); | 288 | struct i2c_client *client = to_i2c_client(dev); |
268 | struct rs5c372 *rs5c = i2c_get_clientdata(client); | 289 | struct rs5c372 *rs5c = i2c_get_clientdata(client); |
269 | unsigned char buf[2]; | 290 | unsigned char buf; |
270 | int status; | 291 | int status, addr; |
271 | 292 | ||
272 | buf[1] = rs5c->regs[RS5C_REG_CTRL1]; | 293 | buf = rs5c->regs[RS5C_REG_CTRL1]; |
273 | switch (cmd) { | 294 | switch (cmd) { |
274 | case RTC_UIE_OFF: | 295 | case RTC_UIE_OFF: |
275 | case RTC_UIE_ON: | 296 | case RTC_UIE_ON: |
276 | /* some 327a modes use a different IRQ pin for 1Hz irqs */ | 297 | /* some 327a modes use a different IRQ pin for 1Hz irqs */ |
277 | if (rs5c->type == rtc_rs5c372a | 298 | if (rs5c->type == rtc_rs5c372a |
278 | && (buf[1] & RS5C372A_CTRL1_SL1)) | 299 | && (buf & RS5C372A_CTRL1_SL1)) |
279 | return -ENOIOCTLCMD; | 300 | return -ENOIOCTLCMD; |
280 | case RTC_AIE_OFF: | 301 | case RTC_AIE_OFF: |
281 | case RTC_AIE_ON: | 302 | case RTC_AIE_ON: |
@@ -293,28 +314,30 @@ rs5c_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
293 | if (status < 0) | 314 | if (status < 0) |
294 | return status; | 315 | return status; |
295 | 316 | ||
296 | buf[0] = RS5C_ADDR(RS5C_REG_CTRL1); | 317 | addr = RS5C_ADDR(RS5C_REG_CTRL1); |
297 | switch (cmd) { | 318 | switch (cmd) { |
298 | case RTC_AIE_OFF: /* alarm off */ | 319 | case RTC_AIE_OFF: /* alarm off */ |
299 | buf[1] &= ~RS5C_CTRL1_AALE; | 320 | buf &= ~RS5C_CTRL1_AALE; |
300 | break; | 321 | break; |
301 | case RTC_AIE_ON: /* alarm on */ | 322 | case RTC_AIE_ON: /* alarm on */ |
302 | buf[1] |= RS5C_CTRL1_AALE; | 323 | buf |= RS5C_CTRL1_AALE; |
303 | break; | 324 | break; |
304 | case RTC_UIE_OFF: /* update off */ | 325 | case RTC_UIE_OFF: /* update off */ |
305 | buf[1] &= ~RS5C_CTRL1_CT_MASK; | 326 | buf &= ~RS5C_CTRL1_CT_MASK; |
306 | break; | 327 | break; |
307 | case RTC_UIE_ON: /* update on */ | 328 | case RTC_UIE_ON: /* update on */ |
308 | buf[1] &= ~RS5C_CTRL1_CT_MASK; | 329 | buf &= ~RS5C_CTRL1_CT_MASK; |
309 | buf[1] |= RS5C_CTRL1_CT4; | 330 | buf |= RS5C_CTRL1_CT4; |
310 | break; | 331 | break; |
311 | } | 332 | } |
312 | if ((i2c_master_send(client, buf, 2)) != 2) { | 333 | |
334 | if (i2c_smbus_write_byte_data(client, addr, buf) < 0) { | ||
313 | printk(KERN_WARNING "%s: can't update alarm\n", | 335 | printk(KERN_WARNING "%s: can't update alarm\n", |
314 | rs5c->rtc->name); | 336 | rs5c->rtc->name); |
315 | status = -EIO; | 337 | status = -EIO; |
316 | } else | 338 | } else |
317 | rs5c->regs[RS5C_REG_CTRL1] = buf[1]; | 339 | rs5c->regs[RS5C_REG_CTRL1] = buf; |
340 | |||
318 | return status; | 341 | return status; |
319 | } | 342 | } |
320 | 343 | ||
@@ -364,8 +387,8 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
364 | { | 387 | { |
365 | struct i2c_client *client = to_i2c_client(dev); | 388 | struct i2c_client *client = to_i2c_client(dev); |
366 | struct rs5c372 *rs5c = i2c_get_clientdata(client); | 389 | struct rs5c372 *rs5c = i2c_get_clientdata(client); |
367 | int status; | 390 | int status, addr, i; |
368 | unsigned char buf[4]; | 391 | unsigned char buf[3]; |
369 | 392 | ||
370 | /* only handle up to 24 hours in the future, like RTC_ALM_SET */ | 393 | /* only handle up to 24 hours in the future, like RTC_ALM_SET */ |
371 | if (t->time.tm_mday != -1 | 394 | if (t->time.tm_mday != -1 |
@@ -380,33 +403,36 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
380 | if (status < 0) | 403 | if (status < 0) |
381 | return status; | 404 | return status; |
382 | if (rs5c->regs[RS5C_REG_CTRL1] & RS5C_CTRL1_AALE) { | 405 | if (rs5c->regs[RS5C_REG_CTRL1] & RS5C_CTRL1_AALE) { |
383 | buf[0] = RS5C_ADDR(RS5C_REG_CTRL1); | 406 | addr = RS5C_ADDR(RS5C_REG_CTRL1); |
384 | buf[1] = rs5c->regs[RS5C_REG_CTRL1] & ~RS5C_CTRL1_AALE; | 407 | buf[0] = rs5c->regs[RS5C_REG_CTRL1] & ~RS5C_CTRL1_AALE; |
385 | if (i2c_master_send(client, buf, 2) != 2) { | 408 | if (i2c_smbus_write_byte_data(client, addr, buf[0]) < 0) { |
386 | pr_debug("%s: can't disable alarm\n", rs5c->rtc->name); | 409 | pr_debug("%s: can't disable alarm\n", rs5c->rtc->name); |
387 | return -EIO; | 410 | return -EIO; |
388 | } | 411 | } |
389 | rs5c->regs[RS5C_REG_CTRL1] = buf[1]; | 412 | rs5c->regs[RS5C_REG_CTRL1] = buf[0]; |
390 | } | 413 | } |
391 | 414 | ||
392 | /* set alarm */ | 415 | /* set alarm */ |
393 | buf[0] = RS5C_ADDR(RS5C_REG_ALARM_A_MIN); | 416 | buf[0] = BIN2BCD(t->time.tm_min); |
394 | buf[1] = BIN2BCD(t->time.tm_min); | 417 | buf[1] = rs5c_hr2reg(rs5c, t->time.tm_hour); |
395 | buf[2] = rs5c_hr2reg(rs5c, t->time.tm_hour); | 418 | buf[2] = 0x7f; /* any/all days */ |
396 | buf[3] = 0x7f; /* any/all days */ | 419 | |
397 | if ((i2c_master_send(client, buf, 4)) != 4) { | 420 | for (i = 0; i < sizeof(buf); i++) { |
398 | pr_debug("%s: can't set alarm time\n", rs5c->rtc->name); | 421 | addr = RS5C_ADDR(RS5C_REG_ALARM_A_MIN + i); |
399 | return -EIO; | 422 | if (i2c_smbus_write_byte_data(client, addr, buf[i]) < 0) { |
423 | pr_debug("%s: can't set alarm time\n", rs5c->rtc->name); | ||
424 | return -EIO; | ||
425 | } | ||
400 | } | 426 | } |
401 | 427 | ||
402 | /* ... and maybe enable its irq */ | 428 | /* ... and maybe enable its irq */ |
403 | if (t->enabled) { | 429 | if (t->enabled) { |
404 | buf[0] = RS5C_ADDR(RS5C_REG_CTRL1); | 430 | addr = RS5C_ADDR(RS5C_REG_CTRL1); |
405 | buf[1] = rs5c->regs[RS5C_REG_CTRL1] | RS5C_CTRL1_AALE; | 431 | buf[0] = rs5c->regs[RS5C_REG_CTRL1] | RS5C_CTRL1_AALE; |
406 | if ((i2c_master_send(client, buf, 2)) != 2) | 432 | if (i2c_smbus_write_byte_data(client, addr, buf[0]) < 0) |
407 | printk(KERN_WARNING "%s: can't enable alarm\n", | 433 | printk(KERN_WARNING "%s: can't enable alarm\n", |
408 | rs5c->rtc->name); | 434 | rs5c->rtc->name); |
409 | rs5c->regs[RS5C_REG_CTRL1] = buf[1]; | 435 | rs5c->regs[RS5C_REG_CTRL1] = buf[0]; |
410 | } | 436 | } |
411 | 437 | ||
412 | return 0; | 438 | return 0; |
@@ -503,18 +529,81 @@ static void rs5c_sysfs_unregister(struct device *dev) | |||
503 | 529 | ||
504 | static struct i2c_driver rs5c372_driver; | 530 | static struct i2c_driver rs5c372_driver; |
505 | 531 | ||
532 | static int rs5c_oscillator_setup(struct rs5c372 *rs5c372) | ||
533 | { | ||
534 | unsigned char buf[2]; | ||
535 | int addr, i, ret = 0; | ||
536 | |||
537 | if (rs5c372->type == rtc_r2025sd) { | ||
538 | if (!(rs5c372->regs[RS5C_REG_CTRL2] & R2025_CTRL2_XST)) | ||
539 | return ret; | ||
540 | rs5c372->regs[RS5C_REG_CTRL2] &= ~R2025_CTRL2_XST; | ||
541 | } else { | ||
542 | if (!(rs5c372->regs[RS5C_REG_CTRL2] & RS5C_CTRL2_XSTP)) | ||
543 | return ret; | ||
544 | rs5c372->regs[RS5C_REG_CTRL2] &= ~RS5C_CTRL2_XSTP; | ||
545 | } | ||
546 | |||
547 | addr = RS5C_ADDR(RS5C_REG_CTRL1); | ||
548 | buf[0] = rs5c372->regs[RS5C_REG_CTRL1]; | ||
549 | buf[1] = rs5c372->regs[RS5C_REG_CTRL2]; | ||
550 | |||
551 | /* use 24hr mode */ | ||
552 | switch (rs5c372->type) { | ||
553 | case rtc_rs5c372a: | ||
554 | case rtc_rs5c372b: | ||
555 | buf[1] |= RS5C372_CTRL2_24; | ||
556 | rs5c372->time24 = 1; | ||
557 | break; | ||
558 | case rtc_r2025sd: | ||
559 | case rtc_rv5c386: | ||
560 | case rtc_rv5c387a: | ||
561 | buf[0] |= RV5C387_CTRL1_24; | ||
562 | rs5c372->time24 = 1; | ||
563 | break; | ||
564 | default: | ||
565 | /* impossible */ | ||
566 | break; | ||
567 | } | ||
568 | |||
569 | for (i = 0; i < sizeof(buf); i++) { | ||
570 | addr = RS5C_ADDR(RS5C_REG_CTRL1 + i); | ||
571 | ret = i2c_smbus_write_byte_data(rs5c372->client, addr, buf[i]); | ||
572 | if (unlikely(ret < 0)) | ||
573 | return ret; | ||
574 | } | ||
575 | |||
576 | rs5c372->regs[RS5C_REG_CTRL1] = buf[0]; | ||
577 | rs5c372->regs[RS5C_REG_CTRL2] = buf[1]; | ||
578 | |||
579 | return 0; | ||
580 | } | ||
581 | |||
506 | static int rs5c372_probe(struct i2c_client *client, | 582 | static int rs5c372_probe(struct i2c_client *client, |
507 | const struct i2c_device_id *id) | 583 | const struct i2c_device_id *id) |
508 | { | 584 | { |
509 | int err = 0; | 585 | int err = 0; |
586 | int smbus_mode = 0; | ||
510 | struct rs5c372 *rs5c372; | 587 | struct rs5c372 *rs5c372; |
511 | struct rtc_time tm; | 588 | struct rtc_time tm; |
512 | 589 | ||
513 | dev_dbg(&client->dev, "%s\n", __func__); | 590 | dev_dbg(&client->dev, "%s\n", __func__); |
514 | 591 | ||
515 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | 592 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C | |
516 | err = -ENODEV; | 593 | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK)) { |
517 | goto exit; | 594 | /* |
595 | * If we don't have any master mode adapter, try breaking | ||
596 | * it down in to the barest of capabilities. | ||
597 | */ | ||
598 | if (i2c_check_functionality(client->adapter, | ||
599 | I2C_FUNC_SMBUS_BYTE_DATA | | ||
600 | I2C_FUNC_SMBUS_I2C_BLOCK)) | ||
601 | smbus_mode = 1; | ||
602 | else { | ||
603 | /* Still no good, give up */ | ||
604 | err = -ENODEV; | ||
605 | goto exit; | ||
606 | } | ||
518 | } | 607 | } |
519 | 608 | ||
520 | if (!(rs5c372 = kzalloc(sizeof(struct rs5c372), GFP_KERNEL))) { | 609 | if (!(rs5c372 = kzalloc(sizeof(struct rs5c372), GFP_KERNEL))) { |
@@ -528,6 +617,7 @@ static int rs5c372_probe(struct i2c_client *client, | |||
528 | 617 | ||
529 | /* we read registers 0x0f then 0x00-0x0f; skip the first one */ | 618 | /* we read registers 0x0f then 0x00-0x0f; skip the first one */ |
530 | rs5c372->regs = &rs5c372->buf[1]; | 619 | rs5c372->regs = &rs5c372->buf[1]; |
620 | rs5c372->smbus = smbus_mode; | ||
531 | 621 | ||
532 | err = rs5c_get_regs(rs5c372); | 622 | err = rs5c_get_regs(rs5c372); |
533 | if (err < 0) | 623 | if (err < 0) |
@@ -543,6 +633,7 @@ static int rs5c372_probe(struct i2c_client *client, | |||
543 | if (rs5c372->regs[RS5C_REG_CTRL2] & RS5C372_CTRL2_24) | 633 | if (rs5c372->regs[RS5C_REG_CTRL2] & RS5C372_CTRL2_24) |
544 | rs5c372->time24 = 1; | 634 | rs5c372->time24 = 1; |
545 | break; | 635 | break; |
636 | case rtc_r2025sd: | ||
546 | case rtc_rv5c386: | 637 | case rtc_rv5c386: |
547 | case rtc_rv5c387a: | 638 | case rtc_rv5c387a: |
548 | if (rs5c372->regs[RS5C_REG_CTRL1] & RV5C387_CTRL1_24) | 639 | if (rs5c372->regs[RS5C_REG_CTRL1] & RV5C387_CTRL1_24) |
@@ -558,39 +649,14 @@ static int rs5c372_probe(struct i2c_client *client, | |||
558 | 649 | ||
559 | /* if the oscillator lost power and no other software (like | 650 | /* if the oscillator lost power and no other software (like |
560 | * the bootloader) set it up, do it here. | 651 | * the bootloader) set it up, do it here. |
652 | * | ||
653 | * The R2025S/D does this a little differently than the other | ||
654 | * parts, so we special case that.. | ||
561 | */ | 655 | */ |
562 | if (rs5c372->regs[RS5C_REG_CTRL2] & RS5C_CTRL2_XSTP) { | 656 | err = rs5c_oscillator_setup(rs5c372); |
563 | unsigned char buf[3]; | 657 | if (unlikely(err < 0)) { |
564 | 658 | dev_err(&client->dev, "setup error\n"); | |
565 | rs5c372->regs[RS5C_REG_CTRL2] &= ~RS5C_CTRL2_XSTP; | 659 | goto exit_kfree; |
566 | |||
567 | buf[0] = RS5C_ADDR(RS5C_REG_CTRL1); | ||
568 | buf[1] = rs5c372->regs[RS5C_REG_CTRL1]; | ||
569 | buf[2] = rs5c372->regs[RS5C_REG_CTRL2]; | ||
570 | |||
571 | /* use 24hr mode */ | ||
572 | switch (rs5c372->type) { | ||
573 | case rtc_rs5c372a: | ||
574 | case rtc_rs5c372b: | ||
575 | buf[2] |= RS5C372_CTRL2_24; | ||
576 | rs5c372->time24 = 1; | ||
577 | break; | ||
578 | case rtc_rv5c386: | ||
579 | case rtc_rv5c387a: | ||
580 | buf[1] |= RV5C387_CTRL1_24; | ||
581 | rs5c372->time24 = 1; | ||
582 | break; | ||
583 | default: | ||
584 | /* impossible */ | ||
585 | break; | ||
586 | } | ||
587 | |||
588 | if ((i2c_master_send(client, buf, 3)) != 3) { | ||
589 | dev_err(&client->dev, "setup error\n"); | ||
590 | goto exit_kfree; | ||
591 | } | ||
592 | rs5c372->regs[RS5C_REG_CTRL1] = buf[1]; | ||
593 | rs5c372->regs[RS5C_REG_CTRL2] = buf[2]; | ||
594 | } | 660 | } |
595 | 661 | ||
596 | if (rs5c372_get_datetime(client, &tm) < 0) | 662 | if (rs5c372_get_datetime(client, &tm) < 0) |
@@ -598,6 +664,7 @@ static int rs5c372_probe(struct i2c_client *client, | |||
598 | 664 | ||
599 | dev_info(&client->dev, "%s found, %s, driver version " DRV_VERSION "\n", | 665 | dev_info(&client->dev, "%s found, %s, driver version " DRV_VERSION "\n", |
600 | ({ char *s; switch (rs5c372->type) { | 666 | ({ char *s; switch (rs5c372->type) { |
667 | case rtc_r2025sd: s = "r2025sd"; break; | ||
601 | case rtc_rs5c372a: s = "rs5c372a"; break; | 668 | case rtc_rs5c372a: s = "rs5c372a"; break; |
602 | case rtc_rs5c372b: s = "rs5c372b"; break; | 669 | case rtc_rs5c372b: s = "rs5c372b"; break; |
603 | case rtc_rv5c386: s = "rv5c386"; break; | 670 | case rtc_rv5c386: s = "rv5c386"; break; |
@@ -667,7 +734,8 @@ module_exit(rs5c372_exit); | |||
667 | 734 | ||
668 | MODULE_AUTHOR( | 735 | MODULE_AUTHOR( |
669 | "Pavel Mironchik <pmironchik@optifacio.net>, " | 736 | "Pavel Mironchik <pmironchik@optifacio.net>, " |
670 | "Alessandro Zummo <a.zummo@towertech.it>"); | 737 | "Alessandro Zummo <a.zummo@towertech.it>, " |
738 | "Paul Mundt <lethal@linux-sh.org>"); | ||
671 | MODULE_DESCRIPTION("Ricoh RS5C372 RTC driver"); | 739 | MODULE_DESCRIPTION("Ricoh RS5C372 RTC driver"); |
672 | MODULE_LICENSE("GPL"); | 740 | MODULE_LICENSE("GPL"); |
673 | MODULE_VERSION(DRV_VERSION); | 741 | MODULE_VERSION(DRV_VERSION); |
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 1f88e9e914ec..fcead4c4cd1f 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c | |||
@@ -257,12 +257,6 @@ static inline void sh_rtc_setaie(struct device *dev, unsigned int enable) | |||
257 | spin_unlock_irq(&rtc->lock); | 257 | spin_unlock_irq(&rtc->lock); |
258 | } | 258 | } |
259 | 259 | ||
260 | static void sh_rtc_release(struct device *dev) | ||
261 | { | ||
262 | sh_rtc_setpie(dev, 0); | ||
263 | sh_rtc_setaie(dev, 0); | ||
264 | } | ||
265 | |||
266 | static int sh_rtc_proc(struct device *dev, struct seq_file *seq) | 260 | static int sh_rtc_proc(struct device *dev, struct seq_file *seq) |
267 | { | 261 | { |
268 | struct sh_rtc *rtc = dev_get_drvdata(dev); | 262 | struct sh_rtc *rtc = dev_get_drvdata(dev); |
@@ -559,7 +553,6 @@ static int sh_rtc_irq_set_freq(struct device *dev, int freq) | |||
559 | } | 553 | } |
560 | 554 | ||
561 | static struct rtc_class_ops sh_rtc_ops = { | 555 | static struct rtc_class_ops sh_rtc_ops = { |
562 | .release = sh_rtc_release, | ||
563 | .ioctl = sh_rtc_ioctl, | 556 | .ioctl = sh_rtc_ioctl, |
564 | .read_time = sh_rtc_read_time, | 557 | .read_time = sh_rtc_read_time, |
565 | .set_time = sh_rtc_set_time, | 558 | .set_time = sh_rtc_set_time, |
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index 31d3c8c28588..9a7e920315fa 100644 --- a/drivers/rtc/rtc-stk17ta8.c +++ b/drivers/rtc/rtc-stk17ta8.c | |||
@@ -215,17 +215,6 @@ static irqreturn_t stk17ta8_rtc_interrupt(int irq, void *dev_id) | |||
215 | return IRQ_HANDLED; | 215 | return IRQ_HANDLED; |
216 | } | 216 | } |
217 | 217 | ||
218 | static void stk17ta8_rtc_release(struct device *dev) | ||
219 | { | ||
220 | struct platform_device *pdev = to_platform_device(dev); | ||
221 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
222 | |||
223 | if (pdata->irq >= 0) { | ||
224 | pdata->irqen = 0; | ||
225 | stk17ta8_rtc_update_alarm(pdata); | ||
226 | } | ||
227 | } | ||
228 | |||
229 | static int stk17ta8_rtc_ioctl(struct device *dev, unsigned int cmd, | 218 | static int stk17ta8_rtc_ioctl(struct device *dev, unsigned int cmd, |
230 | unsigned long arg) | 219 | unsigned long arg) |
231 | { | 220 | { |
@@ -254,7 +243,6 @@ static const struct rtc_class_ops stk17ta8_rtc_ops = { | |||
254 | .set_time = stk17ta8_rtc_set_time, | 243 | .set_time = stk17ta8_rtc_set_time, |
255 | .read_alarm = stk17ta8_rtc_read_alarm, | 244 | .read_alarm = stk17ta8_rtc_read_alarm, |
256 | .set_alarm = stk17ta8_rtc_set_alarm, | 245 | .set_alarm = stk17ta8_rtc_set_alarm, |
257 | .release = stk17ta8_rtc_release, | ||
258 | .ioctl = stk17ta8_rtc_ioctl, | 246 | .ioctl = stk17ta8_rtc_ioctl, |
259 | }; | 247 | }; |
260 | 248 | ||
diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c index cbe470493bf0..19f5d5ed85e0 100644 --- a/drivers/s390/net/ctcm_mpc.c +++ b/drivers/s390/net/ctcm_mpc.c | |||
@@ -1673,7 +1673,7 @@ static int mpc_validate_xid(struct mpcg_info *mpcginfo) | |||
1673 | 1673 | ||
1674 | done: | 1674 | done: |
1675 | if (rc) { | 1675 | if (rc) { |
1676 | ctcm_pr_info("ctcmpc : %s() failed\n", __FUNCTION__); | 1676 | ctcm_pr_info("ctcmpc : %s() failed\n", __func__); |
1677 | priv->xid->xid2_flag2 = 0x40; | 1677 | priv->xid->xid2_flag2 = 0x40; |
1678 | grp->saved_xid2->xid2_flag2 = 0x40; | 1678 | grp->saved_xid2->xid2_flag2 = 0x40; |
1679 | } | 1679 | } |
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index d3ca7d32abe0..1528de23a650 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -2223,9 +2223,9 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, | |||
2223 | serial_outp(up, UART_EFR, efr); | 2223 | serial_outp(up, UART_EFR, efr); |
2224 | } | 2224 | } |
2225 | 2225 | ||
2226 | #ifdef CONFIG_ARCH_OMAP15XX | 2226 | #ifdef CONFIG_ARCH_OMAP |
2227 | /* Workaround to enable 115200 baud on OMAP1510 internal ports */ | 2227 | /* Workaround to enable 115200 baud on OMAP1510 internal ports */ |
2228 | if (cpu_is_omap1510() && is_omap_port((unsigned int)up->port.membase)) { | 2228 | if (cpu_is_omap1510() && is_omap_port(up)) { |
2229 | if (baud == 115200) { | 2229 | if (baud == 115200) { |
2230 | quot = 1; | 2230 | quot = 1; |
2231 | serial_out(up, UART_OMAP_OSC_12M_SEL, 1); | 2231 | serial_out(up, UART_OMAP_OSC_12M_SEL, 1); |
@@ -2278,18 +2278,27 @@ serial8250_pm(struct uart_port *port, unsigned int state, | |||
2278 | p->pm(port, state, oldstate); | 2278 | p->pm(port, state, oldstate); |
2279 | } | 2279 | } |
2280 | 2280 | ||
2281 | static unsigned int serial8250_port_size(struct uart_8250_port *pt) | ||
2282 | { | ||
2283 | if (pt->port.iotype == UPIO_AU) | ||
2284 | return 0x100000; | ||
2285 | #ifdef CONFIG_ARCH_OMAP | ||
2286 | if (is_omap_port(pt)) | ||
2287 | return 0x16 << pt->port.regshift; | ||
2288 | #endif | ||
2289 | return 8 << pt->port.regshift; | ||
2290 | } | ||
2291 | |||
2281 | /* | 2292 | /* |
2282 | * Resource handling. | 2293 | * Resource handling. |
2283 | */ | 2294 | */ |
2284 | static int serial8250_request_std_resource(struct uart_8250_port *up) | 2295 | static int serial8250_request_std_resource(struct uart_8250_port *up) |
2285 | { | 2296 | { |
2286 | unsigned int size = 8 << up->port.regshift; | 2297 | unsigned int size = serial8250_port_size(up); |
2287 | int ret = 0; | 2298 | int ret = 0; |
2288 | 2299 | ||
2289 | switch (up->port.iotype) { | 2300 | switch (up->port.iotype) { |
2290 | case UPIO_AU: | 2301 | case UPIO_AU: |
2291 | size = 0x100000; | ||
2292 | /* fall thru */ | ||
2293 | case UPIO_TSI: | 2302 | case UPIO_TSI: |
2294 | case UPIO_MEM32: | 2303 | case UPIO_MEM32: |
2295 | case UPIO_MEM: | 2304 | case UPIO_MEM: |
@@ -2323,12 +2332,10 @@ static int serial8250_request_std_resource(struct uart_8250_port *up) | |||
2323 | 2332 | ||
2324 | static void serial8250_release_std_resource(struct uart_8250_port *up) | 2333 | static void serial8250_release_std_resource(struct uart_8250_port *up) |
2325 | { | 2334 | { |
2326 | unsigned int size = 8 << up->port.regshift; | 2335 | unsigned int size = serial8250_port_size(up); |
2327 | 2336 | ||
2328 | switch (up->port.iotype) { | 2337 | switch (up->port.iotype) { |
2329 | case UPIO_AU: | 2338 | case UPIO_AU: |
2330 | size = 0x100000; | ||
2331 | /* fall thru */ | ||
2332 | case UPIO_TSI: | 2339 | case UPIO_TSI: |
2333 | case UPIO_MEM32: | 2340 | case UPIO_MEM32: |
2334 | case UPIO_MEM: | 2341 | case UPIO_MEM: |
diff --git a/drivers/serial/s3c2400.c b/drivers/serial/s3c2400.c index c8b4266ac35f..4873f2978bd2 100644 --- a/drivers/serial/s3c2400.c +++ b/drivers/serial/s3c2400.c | |||
@@ -19,7 +19,7 @@ | |||
19 | 19 | ||
20 | #include <mach/hardware.h> | 20 | #include <mach/hardware.h> |
21 | 21 | ||
22 | #include <asm/plat-s3c/regs-serial.h> | 22 | #include <plat/regs-serial.h> |
23 | #include <mach/regs-gpio.h> | 23 | #include <mach/regs-gpio.h> |
24 | 24 | ||
25 | #include "samsung.h" | 25 | #include "samsung.h" |
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index 40a2531b5541..87c182ef71b8 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <asm/irq.h> | 21 | #include <asm/irq.h> |
22 | #include <mach/hardware.h> | 22 | #include <mach/hardware.h> |
23 | 23 | ||
24 | #include <asm/plat-s3c/regs-serial.h> | 24 | #include <plat/regs-serial.h> |
25 | #include <mach/regs-gpio.h> | 25 | #include <mach/regs-gpio.h> |
26 | 26 | ||
27 | #include "samsung.h" | 27 | #include "samsung.h" |
diff --git a/drivers/serial/s3c2412.c b/drivers/serial/s3c2412.c index d0170319c729..fd017b375568 100644 --- a/drivers/serial/s3c2412.c +++ b/drivers/serial/s3c2412.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <asm/irq.h> | 21 | #include <asm/irq.h> |
22 | #include <mach/hardware.h> | 22 | #include <mach/hardware.h> |
23 | 23 | ||
24 | #include <asm/plat-s3c/regs-serial.h> | 24 | #include <plat/regs-serial.h> |
25 | #include <mach/regs-gpio.h> | 25 | #include <mach/regs-gpio.h> |
26 | 26 | ||
27 | #include "samsung.h" | 27 | #include "samsung.h" |
diff --git a/drivers/serial/s3c2440.c b/drivers/serial/s3c2440.c index d4a2b17b2498..317d239ab740 100644 --- a/drivers/serial/s3c2440.c +++ b/drivers/serial/s3c2440.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <asm/irq.h> | 21 | #include <asm/irq.h> |
22 | #include <mach/hardware.h> | 22 | #include <mach/hardware.h> |
23 | 23 | ||
24 | #include <asm/plat-s3c/regs-serial.h> | 24 | #include <plat/regs-serial.h> |
25 | #include <mach/regs-gpio.h> | 25 | #include <mach/regs-gpio.h> |
26 | 26 | ||
27 | #include "samsung.h" | 27 | #include "samsung.h" |
diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c index 5a88b3f9fe9b..1e219d3d0352 100644 --- a/drivers/serial/samsung.c +++ b/drivers/serial/samsung.c | |||
@@ -47,7 +47,7 @@ | |||
47 | 47 | ||
48 | #include <mach/hardware.h> | 48 | #include <mach/hardware.h> |
49 | 49 | ||
50 | #include <asm/plat-s3c/regs-serial.h> | 50 | #include <plat/regs-serial.h> |
51 | #include <mach/regs-gpio.h> | 51 | #include <mach/regs-gpio.h> |
52 | 52 | ||
53 | #include "samsung.h" | 53 | #include "samsung.h" |
diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c index cdb3d3191719..0debe11b67b4 100644 --- a/drivers/spi/mpc52xx_psc_spi.c +++ b/drivers/spi/mpc52xx_psc_spi.c | |||
@@ -15,13 +15,7 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | |||
19 | #if defined(CONFIG_PPC_MERGE) | ||
20 | #include <linux/of_platform.h> | 18 | #include <linux/of_platform.h> |
21 | #else | ||
22 | #include <linux/platform_device.h> | ||
23 | #endif | ||
24 | |||
25 | #include <linux/workqueue.h> | 19 | #include <linux/workqueue.h> |
26 | #include <linux/completion.h> | 20 | #include <linux/completion.h> |
27 | #include <linux/io.h> | 21 | #include <linux/io.h> |
@@ -471,53 +465,6 @@ static int __exit mpc52xx_psc_spi_do_remove(struct device *dev) | |||
471 | return 0; | 465 | return 0; |
472 | } | 466 | } |
473 | 467 | ||
474 | #if !defined(CONFIG_PPC_MERGE) | ||
475 | static int __init mpc52xx_psc_spi_probe(struct platform_device *dev) | ||
476 | { | ||
477 | switch(dev->id) { | ||
478 | case 1: | ||
479 | case 2: | ||
480 | case 3: | ||
481 | case 6: | ||
482 | return mpc52xx_psc_spi_do_probe(&dev->dev, | ||
483 | MPC52xx_PA(MPC52xx_PSCx_OFFSET(dev->id)), | ||
484 | MPC52xx_PSC_SIZE, platform_get_irq(dev, 0), dev->id); | ||
485 | default: | ||
486 | return -EINVAL; | ||
487 | } | ||
488 | } | ||
489 | |||
490 | static int __exit mpc52xx_psc_spi_remove(struct platform_device *dev) | ||
491 | { | ||
492 | return mpc52xx_psc_spi_do_remove(&dev->dev); | ||
493 | } | ||
494 | |||
495 | /* work with hotplug and coldplug */ | ||
496 | MODULE_ALIAS("platform:mpc52xx-psc-spi"); | ||
497 | |||
498 | static struct platform_driver mpc52xx_psc_spi_platform_driver = { | ||
499 | .remove = __exit_p(mpc52xx_psc_spi_remove), | ||
500 | .driver = { | ||
501 | .name = "mpc52xx-psc-spi", | ||
502 | .owner = THIS_MODULE, | ||
503 | }, | ||
504 | }; | ||
505 | |||
506 | static int __init mpc52xx_psc_spi_init(void) | ||
507 | { | ||
508 | return platform_driver_probe(&mpc52xx_psc_spi_platform_driver, | ||
509 | mpc52xx_psc_spi_probe); | ||
510 | } | ||
511 | module_init(mpc52xx_psc_spi_init); | ||
512 | |||
513 | static void __exit mpc52xx_psc_spi_exit(void) | ||
514 | { | ||
515 | platform_driver_unregister(&mpc52xx_psc_spi_platform_driver); | ||
516 | } | ||
517 | module_exit(mpc52xx_psc_spi_exit); | ||
518 | |||
519 | #else /* defined(CONFIG_PPC_MERGE) */ | ||
520 | |||
521 | static int __init mpc52xx_psc_spi_of_probe(struct of_device *op, | 468 | static int __init mpc52xx_psc_spi_of_probe(struct of_device *op, |
522 | const struct of_device_id *match) | 469 | const struct of_device_id *match) |
523 | { | 470 | { |
@@ -586,8 +533,6 @@ static void __exit mpc52xx_psc_spi_exit(void) | |||
586 | } | 533 | } |
587 | module_exit(mpc52xx_psc_spi_exit); | 534 | module_exit(mpc52xx_psc_spi_exit); |
588 | 535 | ||
589 | #endif /* defined(CONFIG_PPC_MERGE) */ | ||
590 | |||
591 | MODULE_AUTHOR("Dragos Carp"); | 536 | MODULE_AUTHOR("Dragos Carp"); |
592 | MODULE_DESCRIPTION("MPC52xx PSC SPI Driver"); | 537 | MODULE_DESCRIPTION("MPC52xx PSC SPI Driver"); |
593 | MODULE_LICENSE("GPL"); | 538 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c index 9d2186fd74aa..454a2712e629 100644 --- a/drivers/spi/omap2_mcspi.c +++ b/drivers/spi/omap2_mcspi.c | |||
@@ -119,12 +119,14 @@ struct omap2_mcspi { | |||
119 | struct clk *fck; | 119 | struct clk *fck; |
120 | /* Virtual base address of the controller */ | 120 | /* Virtual base address of the controller */ |
121 | void __iomem *base; | 121 | void __iomem *base; |
122 | unsigned long phys; | ||
122 | /* SPI1 has 4 channels, while SPI2 has 2 */ | 123 | /* SPI1 has 4 channels, while SPI2 has 2 */ |
123 | struct omap2_mcspi_dma *dma_channels; | 124 | struct omap2_mcspi_dma *dma_channels; |
124 | }; | 125 | }; |
125 | 126 | ||
126 | struct omap2_mcspi_cs { | 127 | struct omap2_mcspi_cs { |
127 | void __iomem *base; | 128 | void __iomem *base; |
129 | unsigned long phys; | ||
128 | int word_len; | 130 | int word_len; |
129 | }; | 131 | }; |
130 | 132 | ||
@@ -233,7 +235,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) | |||
233 | c = count; | 235 | c = count; |
234 | word_len = cs->word_len; | 236 | word_len = cs->word_len; |
235 | 237 | ||
236 | base = (unsigned long) io_v2p(cs->base); | 238 | base = cs->phys; |
237 | tx_reg = base + OMAP2_MCSPI_TX0; | 239 | tx_reg = base + OMAP2_MCSPI_TX0; |
238 | rx_reg = base + OMAP2_MCSPI_RX0; | 240 | rx_reg = base + OMAP2_MCSPI_RX0; |
239 | rx = xfer->rx_buf; | 241 | rx = xfer->rx_buf; |
@@ -633,6 +635,7 @@ static int omap2_mcspi_setup(struct spi_device *spi) | |||
633 | if (!cs) | 635 | if (!cs) |
634 | return -ENOMEM; | 636 | return -ENOMEM; |
635 | cs->base = mcspi->base + spi->chip_select * 0x14; | 637 | cs->base = mcspi->base + spi->chip_select * 0x14; |
638 | cs->phys = mcspi->phys + spi->chip_select * 0x14; | ||
636 | spi->controller_state = cs; | 639 | spi->controller_state = cs; |
637 | } | 640 | } |
638 | 641 | ||
@@ -1005,7 +1008,13 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev) | |||
1005 | goto err1; | 1008 | goto err1; |
1006 | } | 1009 | } |
1007 | 1010 | ||
1008 | mcspi->base = (void __iomem *) io_p2v(r->start); | 1011 | mcspi->phys = r->start; |
1012 | mcspi->base = ioremap(r->start, r->end - r->start + 1); | ||
1013 | if (!mcspi->base) { | ||
1014 | dev_dbg(&pdev->dev, "can't ioremap MCSPI\n"); | ||
1015 | status = -ENOMEM; | ||
1016 | goto err1aa; | ||
1017 | } | ||
1009 | 1018 | ||
1010 | INIT_WORK(&mcspi->work, omap2_mcspi_work); | 1019 | INIT_WORK(&mcspi->work, omap2_mcspi_work); |
1011 | 1020 | ||
@@ -1055,6 +1064,8 @@ err3: | |||
1055 | err2: | 1064 | err2: |
1056 | clk_put(mcspi->ick); | 1065 | clk_put(mcspi->ick); |
1057 | err1a: | 1066 | err1a: |
1067 | iounmap(mcspi->base); | ||
1068 | err1aa: | ||
1058 | release_mem_region(r->start, (r->end - r->start) + 1); | 1069 | release_mem_region(r->start, (r->end - r->start) + 1); |
1059 | err1: | 1070 | err1: |
1060 | spi_master_put(master); | 1071 | spi_master_put(master); |
@@ -1067,6 +1078,7 @@ static int __exit omap2_mcspi_remove(struct platform_device *pdev) | |||
1067 | struct omap2_mcspi *mcspi; | 1078 | struct omap2_mcspi *mcspi; |
1068 | struct omap2_mcspi_dma *dma_channels; | 1079 | struct omap2_mcspi_dma *dma_channels; |
1069 | struct resource *r; | 1080 | struct resource *r; |
1081 | void __iomem *base; | ||
1070 | 1082 | ||
1071 | master = dev_get_drvdata(&pdev->dev); | 1083 | master = dev_get_drvdata(&pdev->dev); |
1072 | mcspi = spi_master_get_devdata(master); | 1084 | mcspi = spi_master_get_devdata(master); |
@@ -1078,7 +1090,9 @@ static int __exit omap2_mcspi_remove(struct platform_device *pdev) | |||
1078 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1090 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1079 | release_mem_region(r->start, (r->end - r->start) + 1); | 1091 | release_mem_region(r->start, (r->end - r->start) + 1); |
1080 | 1092 | ||
1093 | base = mcspi->base; | ||
1081 | spi_unregister_master(master); | 1094 | spi_unregister_master(master); |
1095 | iounmap(base); | ||
1082 | kfree(dma_channels); | 1096 | kfree(dma_channels); |
1083 | 1097 | ||
1084 | return 0; | 1098 | return 0; |
diff --git a/drivers/spi/omap_uwire.c b/drivers/spi/omap_uwire.c index 5515eb97d7c5..bab6ff061e91 100644 --- a/drivers/spi/omap_uwire.c +++ b/drivers/spi/omap_uwire.c | |||
@@ -59,7 +59,6 @@ | |||
59 | * and irqs should show there too... | 59 | * and irqs should show there too... |
60 | */ | 60 | */ |
61 | #define UWIRE_BASE_PHYS 0xFFFB3000 | 61 | #define UWIRE_BASE_PHYS 0xFFFB3000 |
62 | #define UWIRE_BASE ((void *__iomem)IO_ADDRESS(UWIRE_BASE_PHYS)) | ||
63 | 62 | ||
64 | /* uWire Registers: */ | 63 | /* uWire Registers: */ |
65 | #define UWIRE_IO_SIZE 0x20 | 64 | #define UWIRE_IO_SIZE 0x20 |
@@ -103,16 +102,21 @@ struct uwire_state { | |||
103 | }; | 102 | }; |
104 | 103 | ||
105 | /* REVISIT compile time constant for idx_shift? */ | 104 | /* REVISIT compile time constant for idx_shift? */ |
105 | /* | ||
106 | * Or, put it in a structure which is used throughout the driver; | ||
107 | * that avoids having to issue two loads for each bit of static data. | ||
108 | */ | ||
106 | static unsigned int uwire_idx_shift; | 109 | static unsigned int uwire_idx_shift; |
110 | static void __iomem *uwire_base; | ||
107 | 111 | ||
108 | static inline void uwire_write_reg(int idx, u16 val) | 112 | static inline void uwire_write_reg(int idx, u16 val) |
109 | { | 113 | { |
110 | __raw_writew(val, UWIRE_BASE + (idx << uwire_idx_shift)); | 114 | __raw_writew(val, uwire_base + (idx << uwire_idx_shift)); |
111 | } | 115 | } |
112 | 116 | ||
113 | static inline u16 uwire_read_reg(int idx) | 117 | static inline u16 uwire_read_reg(int idx) |
114 | { | 118 | { |
115 | return __raw_readw(UWIRE_BASE + (idx << uwire_idx_shift)); | 119 | return __raw_readw(uwire_base + (idx << uwire_idx_shift)); |
116 | } | 120 | } |
117 | 121 | ||
118 | static inline void omap_uwire_configure_mode(u8 cs, unsigned long flags) | 122 | static inline void omap_uwire_configure_mode(u8 cs, unsigned long flags) |
@@ -492,6 +496,14 @@ static int __init uwire_probe(struct platform_device *pdev) | |||
492 | return -ENODEV; | 496 | return -ENODEV; |
493 | 497 | ||
494 | uwire = spi_master_get_devdata(master); | 498 | uwire = spi_master_get_devdata(master); |
499 | |||
500 | uwire_base = ioremap(UWIRE_BASE_PHYS, UWIRE_IO_SIZE); | ||
501 | if (!uwire_base) { | ||
502 | dev_dbg(&pdev->dev, "can't ioremap UWIRE\n"); | ||
503 | spi_master_put(master); | ||
504 | return -ENOMEM; | ||
505 | } | ||
506 | |||
495 | dev_set_drvdata(&pdev->dev, uwire); | 507 | dev_set_drvdata(&pdev->dev, uwire); |
496 | 508 | ||
497 | uwire->ck = clk_get(&pdev->dev, "armxor_ck"); | 509 | uwire->ck = clk_get(&pdev->dev, "armxor_ck"); |
@@ -520,8 +532,10 @@ static int __init uwire_probe(struct platform_device *pdev) | |||
520 | uwire->bitbang.txrx_bufs = uwire_txrx; | 532 | uwire->bitbang.txrx_bufs = uwire_txrx; |
521 | 533 | ||
522 | status = spi_bitbang_start(&uwire->bitbang); | 534 | status = spi_bitbang_start(&uwire->bitbang); |
523 | if (status < 0) | 535 | if (status < 0) { |
524 | uwire_off(uwire); | 536 | uwire_off(uwire); |
537 | iounmap(uwire_base); | ||
538 | } | ||
525 | return status; | 539 | return status; |
526 | } | 540 | } |
527 | 541 | ||
@@ -534,6 +548,7 @@ static int __exit uwire_remove(struct platform_device *pdev) | |||
534 | 548 | ||
535 | status = spi_bitbang_stop(&uwire->bitbang); | 549 | status = spi_bitbang_stop(&uwire->bitbang); |
536 | uwire_off(uwire); | 550 | uwire_off(uwire); |
551 | iounmap(uwire_base); | ||
537 | return status; | 552 | return status; |
538 | } | 553 | } |
539 | 554 | ||
diff --git a/drivers/spi/orion_spi.c b/drivers/spi/orion_spi.c index b872bfaf4bd2..014becb7d530 100644 --- a/drivers/spi/orion_spi.c +++ b/drivers/spi/orion_spi.c | |||
@@ -364,6 +364,11 @@ static int orion_spi_setup(struct spi_device *spi) | |||
364 | return -EINVAL; | 364 | return -EINVAL; |
365 | } | 365 | } |
366 | 366 | ||
367 | /* Fix ac timing if required. */ | ||
368 | if (orion_spi->spi_info->enable_clock_fix) | ||
369 | orion_spi_setbits(orion_spi, ORION_SPI_IF_CONFIG_REG, | ||
370 | (1 << 14)); | ||
371 | |||
367 | if (spi->bits_per_word == 0) | 372 | if (spi->bits_per_word == 0) |
368 | spi->bits_per_word = 8; | 373 | spi->bits_per_word = 8; |
369 | 374 | ||
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index d47d3636227f..dae87b1a4c6e 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c | |||
@@ -47,6 +47,10 @@ MODULE_ALIAS("platform:pxa2xx-spi"); | |||
47 | 47 | ||
48 | #define MAX_BUSES 3 | 48 | #define MAX_BUSES 3 |
49 | 49 | ||
50 | #define RX_THRESH_DFLT 8 | ||
51 | #define TX_THRESH_DFLT 8 | ||
52 | #define TIMOUT_DFLT 1000 | ||
53 | |||
50 | #define DMA_INT_MASK (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR) | 54 | #define DMA_INT_MASK (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR) |
51 | #define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK) | 55 | #define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK) |
52 | #define IS_DMA_ALIGNED(x) ((((u32)(x)) & 0x07) == 0) | 56 | #define IS_DMA_ALIGNED(x) ((((u32)(x)) & 0x07) == 0) |
@@ -1171,6 +1175,8 @@ static int setup(struct spi_device *spi) | |||
1171 | struct driver_data *drv_data = spi_master_get_devdata(spi->master); | 1175 | struct driver_data *drv_data = spi_master_get_devdata(spi->master); |
1172 | struct ssp_device *ssp = drv_data->ssp; | 1176 | struct ssp_device *ssp = drv_data->ssp; |
1173 | unsigned int clk_div; | 1177 | unsigned int clk_div; |
1178 | uint tx_thres = TX_THRESH_DFLT; | ||
1179 | uint rx_thres = RX_THRESH_DFLT; | ||
1174 | 1180 | ||
1175 | if (!spi->bits_per_word) | 1181 | if (!spi->bits_per_word) |
1176 | spi->bits_per_word = 8; | 1182 | spi->bits_per_word = 8; |
@@ -1209,8 +1215,7 @@ static int setup(struct spi_device *spi) | |||
1209 | 1215 | ||
1210 | chip->cs_control = null_cs_control; | 1216 | chip->cs_control = null_cs_control; |
1211 | chip->enable_dma = 0; | 1217 | chip->enable_dma = 0; |
1212 | chip->timeout = 1000; | 1218 | chip->timeout = TIMOUT_DFLT; |
1213 | chip->threshold = SSCR1_RxTresh(1) | SSCR1_TxTresh(1); | ||
1214 | chip->dma_burst_size = drv_data->master_info->enable_dma ? | 1219 | chip->dma_burst_size = drv_data->master_info->enable_dma ? |
1215 | DCMD_BURST8 : 0; | 1220 | DCMD_BURST8 : 0; |
1216 | } | 1221 | } |
@@ -1224,22 +1229,21 @@ static int setup(struct spi_device *spi) | |||
1224 | if (chip_info) { | 1229 | if (chip_info) { |
1225 | if (chip_info->cs_control) | 1230 | if (chip_info->cs_control) |
1226 | chip->cs_control = chip_info->cs_control; | 1231 | chip->cs_control = chip_info->cs_control; |
1227 | 1232 | if (chip_info->timeout) | |
1228 | chip->timeout = chip_info->timeout; | 1233 | chip->timeout = chip_info->timeout; |
1229 | 1234 | if (chip_info->tx_threshold) | |
1230 | chip->threshold = (SSCR1_RxTresh(chip_info->rx_threshold) & | 1235 | tx_thres = chip_info->tx_threshold; |
1231 | SSCR1_RFT) | | 1236 | if (chip_info->rx_threshold) |
1232 | (SSCR1_TxTresh(chip_info->tx_threshold) & | 1237 | rx_thres = chip_info->rx_threshold; |
1233 | SSCR1_TFT); | 1238 | chip->enable_dma = drv_data->master_info->enable_dma; |
1234 | |||
1235 | chip->enable_dma = chip_info->dma_burst_size != 0 | ||
1236 | && drv_data->master_info->enable_dma; | ||
1237 | chip->dma_threshold = 0; | 1239 | chip->dma_threshold = 0; |
1238 | |||
1239 | if (chip_info->enable_loopback) | 1240 | if (chip_info->enable_loopback) |
1240 | chip->cr1 = SSCR1_LBM; | 1241 | chip->cr1 = SSCR1_LBM; |
1241 | } | 1242 | } |
1242 | 1243 | ||
1244 | chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) | | ||
1245 | (SSCR1_TxTresh(tx_thres) & SSCR1_TFT); | ||
1246 | |||
1243 | /* set dma burst and threshold outside of chip_info path so that if | 1247 | /* set dma burst and threshold outside of chip_info path so that if |
1244 | * chip_info goes away after setting chip->enable_dma, the | 1248 | * chip_info goes away after setting chip->enable_dma, the |
1245 | * burst and threshold can still respond to changes in bits_per_word */ | 1249 | * burst and threshold can still respond to changes in bits_per_word */ |
@@ -1268,17 +1272,19 @@ static int setup(struct spi_device *spi) | |||
1268 | 1272 | ||
1269 | /* NOTE: PXA25x_SSP _could_ use external clocking ... */ | 1273 | /* NOTE: PXA25x_SSP _could_ use external clocking ... */ |
1270 | if (drv_data->ssp_type != PXA25x_SSP) | 1274 | if (drv_data->ssp_type != PXA25x_SSP) |
1271 | dev_dbg(&spi->dev, "%d bits/word, %ld Hz, mode %d\n", | 1275 | dev_dbg(&spi->dev, "%d bits/word, %ld Hz, mode %d, %s\n", |
1272 | spi->bits_per_word, | 1276 | spi->bits_per_word, |
1273 | clk_get_rate(ssp->clk) | 1277 | clk_get_rate(ssp->clk) |
1274 | / (1 + ((chip->cr0 & SSCR0_SCR) >> 8)), | 1278 | / (1 + ((chip->cr0 & SSCR0_SCR) >> 8)), |
1275 | spi->mode & 0x3); | 1279 | spi->mode & 0x3, |
1280 | chip->enable_dma ? "DMA" : "PIO"); | ||
1276 | else | 1281 | else |
1277 | dev_dbg(&spi->dev, "%d bits/word, %ld Hz, mode %d\n", | 1282 | dev_dbg(&spi->dev, "%d bits/word, %ld Hz, mode %d, %s\n", |
1278 | spi->bits_per_word, | 1283 | spi->bits_per_word, |
1279 | clk_get_rate(ssp->clk) | 1284 | clk_get_rate(ssp->clk) / 2 |
1280 | / (1 + ((chip->cr0 & SSCR0_SCR) >> 8)), | 1285 | / (1 + ((chip->cr0 & SSCR0_SCR) >> 8)), |
1281 | spi->mode & 0x3); | 1286 | spi->mode & 0x3, |
1287 | chip->enable_dma ? "DMA" : "PIO"); | ||
1282 | 1288 | ||
1283 | if (spi->bits_per_word <= 8) { | 1289 | if (spi->bits_per_word <= 8) { |
1284 | chip->n_bytes = 1; | 1290 | chip->n_bytes = 1; |
@@ -1407,9 +1413,9 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) | |||
1407 | struct device *dev = &pdev->dev; | 1413 | struct device *dev = &pdev->dev; |
1408 | struct pxa2xx_spi_master *platform_info; | 1414 | struct pxa2xx_spi_master *platform_info; |
1409 | struct spi_master *master; | 1415 | struct spi_master *master; |
1410 | struct driver_data *drv_data = NULL; | 1416 | struct driver_data *drv_data; |
1411 | struct ssp_device *ssp; | 1417 | struct ssp_device *ssp; |
1412 | int status = 0; | 1418 | int status; |
1413 | 1419 | ||
1414 | platform_info = dev->platform_data; | 1420 | platform_info = dev->platform_data; |
1415 | 1421 | ||
@@ -1422,7 +1428,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) | |||
1422 | /* Allocate master with space for drv_data and null dma buffer */ | 1428 | /* Allocate master with space for drv_data and null dma buffer */ |
1423 | master = spi_alloc_master(dev, sizeof(struct driver_data) + 16); | 1429 | master = spi_alloc_master(dev, sizeof(struct driver_data) + 16); |
1424 | if (!master) { | 1430 | if (!master) { |
1425 | dev_err(&pdev->dev, "can not alloc spi_master\n"); | 1431 | dev_err(&pdev->dev, "cannot alloc spi_master\n"); |
1426 | ssp_free(ssp); | 1432 | ssp_free(ssp); |
1427 | return -ENOMEM; | 1433 | return -ENOMEM; |
1428 | } | 1434 | } |
@@ -1458,7 +1464,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) | |||
1458 | 1464 | ||
1459 | status = request_irq(ssp->irq, ssp_int, 0, dev->bus_id, drv_data); | 1465 | status = request_irq(ssp->irq, ssp_int, 0, dev->bus_id, drv_data); |
1460 | if (status < 0) { | 1466 | if (status < 0) { |
1461 | dev_err(&pdev->dev, "can not get IRQ\n"); | 1467 | dev_err(&pdev->dev, "cannot get IRQ %d\n", ssp->irq); |
1462 | goto out_error_master_alloc; | 1468 | goto out_error_master_alloc; |
1463 | } | 1469 | } |
1464 | 1470 | ||
@@ -1498,7 +1504,9 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) | |||
1498 | 1504 | ||
1499 | /* Load default SSP configuration */ | 1505 | /* Load default SSP configuration */ |
1500 | write_SSCR0(0, drv_data->ioaddr); | 1506 | write_SSCR0(0, drv_data->ioaddr); |
1501 | write_SSCR1(SSCR1_RxTresh(4) | SSCR1_TxTresh(12), drv_data->ioaddr); | 1507 | write_SSCR1(SSCR1_RxTresh(RX_THRESH_DFLT) | |
1508 | SSCR1_TxTresh(TX_THRESH_DFLT), | ||
1509 | drv_data->ioaddr); | ||
1502 | write_SSCR0(SSCR0_SerClkDiv(2) | 1510 | write_SSCR0(SSCR0_SerClkDiv(2) |
1503 | | SSCR0_Motorola | 1511 | | SSCR0_Motorola |
1504 | | SSCR0_DataSize(8), | 1512 | | SSCR0_DataSize(8), |
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 75e86865234c..3734dc9708e1 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
@@ -660,7 +660,7 @@ int spi_write_then_read(struct spi_device *spi, | |||
660 | 660 | ||
661 | int status; | 661 | int status; |
662 | struct spi_message message; | 662 | struct spi_message message; |
663 | struct spi_transfer x[2]; | 663 | struct spi_transfer x; |
664 | u8 *local_buf; | 664 | u8 *local_buf; |
665 | 665 | ||
666 | /* Use preallocated DMA-safe buffer. We can't avoid copying here, | 666 | /* Use preallocated DMA-safe buffer. We can't avoid copying here, |
@@ -671,15 +671,9 @@ int spi_write_then_read(struct spi_device *spi, | |||
671 | return -EINVAL; | 671 | return -EINVAL; |
672 | 672 | ||
673 | spi_message_init(&message); | 673 | spi_message_init(&message); |
674 | memset(x, 0, sizeof x); | 674 | memset(&x, 0, sizeof x); |
675 | if (n_tx) { | 675 | x.len = n_tx + n_rx; |
676 | x[0].len = n_tx; | 676 | spi_message_add_tail(&x, &message); |
677 | spi_message_add_tail(&x[0], &message); | ||
678 | } | ||
679 | if (n_rx) { | ||
680 | x[1].len = n_rx; | ||
681 | spi_message_add_tail(&x[1], &message); | ||
682 | } | ||
683 | 677 | ||
684 | /* ... unless someone else is using the pre-allocated buffer */ | 678 | /* ... unless someone else is using the pre-allocated buffer */ |
685 | if (!mutex_trylock(&lock)) { | 679 | if (!mutex_trylock(&lock)) { |
@@ -690,15 +684,15 @@ int spi_write_then_read(struct spi_device *spi, | |||
690 | local_buf = buf; | 684 | local_buf = buf; |
691 | 685 | ||
692 | memcpy(local_buf, txbuf, n_tx); | 686 | memcpy(local_buf, txbuf, n_tx); |
693 | x[0].tx_buf = local_buf; | 687 | x.tx_buf = local_buf; |
694 | x[1].rx_buf = local_buf + n_tx; | 688 | x.rx_buf = local_buf; |
695 | 689 | ||
696 | /* do the i/o */ | 690 | /* do the i/o */ |
697 | status = spi_sync(spi, &message); | 691 | status = spi_sync(spi, &message); |
698 | if (status == 0) | 692 | if (status == 0) |
699 | memcpy(rxbuf, x[1].rx_buf, n_rx); | 693 | memcpy(rxbuf, x.rx_buf + n_tx, n_rx); |
700 | 694 | ||
701 | if (x[0].tx_buf == buf) | 695 | if (x.tx_buf == buf) |
702 | mutex_unlock(&lock); | 696 | mutex_unlock(&lock); |
703 | else | 697 | else |
704 | kfree(local_buf); | 698 | kfree(local_buf); |
@@ -744,5 +738,5 @@ err0: | |||
744 | * driver registration) _could_ be dynamically linked (modular) ... costs | 738 | * driver registration) _could_ be dynamically linked (modular) ... costs |
745 | * include needing to have boardinfo data structures be much more public. | 739 | * include needing to have boardinfo data structures be much more public. |
746 | */ | 740 | */ |
747 | subsys_initcall(spi_init); | 741 | postcore_initcall(spi_init); |
748 | 742 | ||
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c index 3eb414b84a9d..c252cbac00f1 100644 --- a/drivers/spi/spi_s3c24xx.c +++ b/drivers/spi/spi_s3c24xx.c | |||
@@ -247,6 +247,9 @@ static void s3c24xx_spi_initialsetup(struct s3c24xx_spi *hw) | |||
247 | writeb(0xff, hw->regs + S3C2410_SPPRE); | 247 | writeb(0xff, hw->regs + S3C2410_SPPRE); |
248 | writeb(SPPIN_DEFAULT, hw->regs + S3C2410_SPPIN); | 248 | writeb(SPPIN_DEFAULT, hw->regs + S3C2410_SPPIN); |
249 | writeb(SPCON_DEFAULT, hw->regs + S3C2410_SPCON); | 249 | writeb(SPCON_DEFAULT, hw->regs + S3C2410_SPCON); |
250 | |||
251 | if (hw->pdata && hw->pdata->gpio_setup) | ||
252 | hw->pdata->gpio_setup(hw->pdata, 1); | ||
250 | } | 253 | } |
251 | 254 | ||
252 | static int __init s3c24xx_spi_probe(struct platform_device *pdev) | 255 | static int __init s3c24xx_spi_probe(struct platform_device *pdev) |
@@ -412,6 +415,9 @@ static int s3c24xx_spi_suspend(struct platform_device *pdev, pm_message_t msg) | |||
412 | { | 415 | { |
413 | struct s3c24xx_spi *hw = platform_get_drvdata(pdev); | 416 | struct s3c24xx_spi *hw = platform_get_drvdata(pdev); |
414 | 417 | ||
418 | if (hw->pdata && hw->pdata->gpio_setup) | ||
419 | hw->pdata->gpio_setup(hw->pdata, 0); | ||
420 | |||
415 | clk_disable(hw->clk); | 421 | clk_disable(hw->clk); |
416 | return 0; | 422 | return 0; |
417 | } | 423 | } |
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c index ec7aeb502d15..41b6530b8f25 100644 --- a/drivers/telephony/ixj.c +++ b/drivers/telephony/ixj.c | |||
@@ -42,8 +42,6 @@ | |||
42 | ***************************************************************************/ | 42 | ***************************************************************************/ |
43 | 43 | ||
44 | /* | 44 | /* |
45 | * $Log: ixj.c,v $ | ||
46 | * | ||
47 | * Revision 4.8 2003/07/09 19:39:00 Daniele Bellucci | 45 | * Revision 4.8 2003/07/09 19:39:00 Daniele Bellucci |
48 | * Audit some copy_*_user and minor cleanup. | 46 | * Audit some copy_*_user and minor cleanup. |
49 | * | 47 | * |
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 95b3ec89c126..522185629624 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c | |||
@@ -344,7 +344,12 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver, | |||
344 | goto err1; | 344 | goto err1; |
345 | } | 345 | } |
346 | 346 | ||
347 | hcd->regs = (void __iomem *) (int) IO_ADDRESS(hcd->rsrc_start); | 347 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); |
348 | if (!hcd->regs) { | ||
349 | dev_err(&pdev->dev, "can't ioremap OHCI HCD\n"); | ||
350 | retval = -ENOMEM; | ||
351 | goto err2; | ||
352 | } | ||
348 | 353 | ||
349 | ohci = hcd_to_ohci(hcd); | 354 | ohci = hcd_to_ohci(hcd); |
350 | ohci_hcd_init(ohci); | 355 | ohci_hcd_init(ohci); |
@@ -355,11 +360,11 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver, | |||
355 | irq = platform_get_irq(pdev, 0); | 360 | irq = platform_get_irq(pdev, 0); |
356 | if (irq < 0) { | 361 | if (irq < 0) { |
357 | retval = -ENXIO; | 362 | retval = -ENXIO; |
358 | goto err2; | 363 | goto err3; |
359 | } | 364 | } |
360 | retval = usb_add_hcd(hcd, irq, IRQF_DISABLED); | 365 | retval = usb_add_hcd(hcd, irq, IRQF_DISABLED); |
361 | if (retval) | 366 | if (retval) |
362 | goto err2; | 367 | goto err3; |
363 | 368 | ||
364 | host_initialized = 1; | 369 | host_initialized = 1; |
365 | 370 | ||
@@ -367,6 +372,8 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver, | |||
367 | omap_ohci_clock_power(0); | 372 | omap_ohci_clock_power(0); |
368 | 373 | ||
369 | return 0; | 374 | return 0; |
375 | err3: | ||
376 | iounmap(hcd->regs); | ||
370 | err2: | 377 | err2: |
371 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 378 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
372 | err1: | 379 | err1: |
@@ -401,6 +408,7 @@ usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev) | |||
401 | } | 408 | } |
402 | if (machine_is_omap_osk()) | 409 | if (machine_is_omap_osk()) |
403 | omap_free_gpio(9); | 410 | omap_free_gpio(9); |
411 | iounmap(hcd->regs); | ||
404 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 412 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
405 | usb_put_hcd(hcd); | 413 | usb_put_hcd(hcd); |
406 | clk_put(usb_dc_ck); | 414 | clk_put(usb_dc_ck); |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index f79c2040758b..0f13448c6f79 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -76,6 +76,14 @@ config FB_DDC | |||
76 | select I2C | 76 | select I2C |
77 | default n | 77 | default n |
78 | 78 | ||
79 | config FB_BOOT_VESA_SUPPORT | ||
80 | bool | ||
81 | depends on FB | ||
82 | default n | ||
83 | ---help--- | ||
84 | If true, at least one selected framebuffer driver can take advantage | ||
85 | of VESA video modes set at an early boot stage via the vga= parameter. | ||
86 | |||
79 | config FB_CFB_FILLRECT | 87 | config FB_CFB_FILLRECT |
80 | tristate | 88 | tristate |
81 | depends on FB | 89 | depends on FB |
@@ -254,16 +262,24 @@ config FB_PM2 | |||
254 | select FB_CFB_COPYAREA | 262 | select FB_CFB_COPYAREA |
255 | select FB_CFB_IMAGEBLIT | 263 | select FB_CFB_IMAGEBLIT |
256 | help | 264 | help |
257 | This is the frame buffer device driver for the Permedia2 AGP frame | 265 | This is the frame buffer device driver for cards based on |
258 | buffer card from ASK, aka `Graphic Blaster Exxtreme'. There is a | 266 | the 3D Labs Permedia, Permedia 2 and Permedia 2V chips. |
259 | product page at | 267 | The driver was tested on the following cards: |
260 | <http://www.ask.com.hk/product/Permedia%202/permedia2.htm>. | 268 | Diamond FireGL 1000 PRO AGP |
269 | ELSA Gloria Synergy PCI | ||
270 | Appian Jeronimo PRO (both heads) PCI | ||
271 | 3DLabs Oxygen ACX aka EONtronics Picasso P2 PCI | ||
272 | Techsource Raptor GFX-8P (aka Sun PGX-32) on SPARC | ||
273 | ASK Graphic Blaster Exxtreme AGP | ||
274 | |||
275 | To compile this driver as a module, choose M here: the | ||
276 | module will be called pm2fb. | ||
261 | 277 | ||
262 | config FB_PM2_FIFO_DISCONNECT | 278 | config FB_PM2_FIFO_DISCONNECT |
263 | bool "enable FIFO disconnect feature" | 279 | bool "enable FIFO disconnect feature" |
264 | depends on FB_PM2 && PCI | 280 | depends on FB_PM2 && PCI |
265 | help | 281 | help |
266 | Support the Permedia2 FIFO disconnect feature (see CONFIG_FB_PM2). | 282 | Support the Permedia2 FIFO disconnect feature. |
267 | 283 | ||
268 | config FB_ARMCLCD | 284 | config FB_ARMCLCD |
269 | tristate "ARM PrimeCell PL110 support" | 285 | tristate "ARM PrimeCell PL110 support" |
@@ -673,6 +689,7 @@ config FB_VESA | |||
673 | select FB_CFB_FILLRECT | 689 | select FB_CFB_FILLRECT |
674 | select FB_CFB_COPYAREA | 690 | select FB_CFB_COPYAREA |
675 | select FB_CFB_IMAGEBLIT | 691 | select FB_CFB_IMAGEBLIT |
692 | select FB_BOOT_VESA_SUPPORT | ||
676 | help | 693 | help |
677 | This is the frame buffer device driver for generic VESA 2.0 | 694 | This is the frame buffer device driver for generic VESA 2.0 |
678 | compliant graphic cards. The older VESA 1.2 cards are not supported. | 695 | compliant graphic cards. The older VESA 1.2 cards are not supported. |
@@ -681,23 +698,14 @@ config FB_VESA | |||
681 | 698 | ||
682 | config FB_EFI | 699 | config FB_EFI |
683 | bool "EFI-based Framebuffer Support" | 700 | bool "EFI-based Framebuffer Support" |
684 | depends on (FB = y) && X86 | ||
685 | select FB_CFB_FILLRECT | ||
686 | select FB_CFB_COPYAREA | ||
687 | select FB_CFB_IMAGEBLIT | ||
688 | help | ||
689 | This is the EFI frame buffer device driver. If the firmware on | ||
690 | your platform is UEFI2.0, select Y to add support for | ||
691 | Graphics Output Protocol for early console messages to appear. | ||
692 | |||
693 | config FB_IMAC | ||
694 | bool "Intel-based Macintosh Framebuffer Support" | ||
695 | depends on (FB = y) && X86 && EFI | 701 | depends on (FB = y) && X86 && EFI |
696 | select FB_CFB_FILLRECT | 702 | select FB_CFB_FILLRECT |
697 | select FB_CFB_COPYAREA | 703 | select FB_CFB_COPYAREA |
698 | select FB_CFB_IMAGEBLIT | 704 | select FB_CFB_IMAGEBLIT |
699 | help | 705 | help |
700 | This is the frame buffer device driver for the Intel-based Macintosh | 706 | This is the EFI frame buffer device driver. If the firmware on |
707 | your platform is EFI 1.10 or UEFI 2.0, select Y to add support for | ||
708 | using the EFI framebuffer as your console. | ||
701 | 709 | ||
702 | config FB_N411 | 710 | config FB_N411 |
703 | tristate "N411 Apollo/Hecuba devkit support" | 711 | tristate "N411 Apollo/Hecuba devkit support" |
@@ -1118,6 +1126,7 @@ config FB_INTEL | |||
1118 | select FB_CFB_FILLRECT | 1126 | select FB_CFB_FILLRECT |
1119 | select FB_CFB_COPYAREA | 1127 | select FB_CFB_COPYAREA |
1120 | select FB_CFB_IMAGEBLIT | 1128 | select FB_CFB_IMAGEBLIT |
1129 | select FB_BOOT_VESA_SUPPORT | ||
1121 | help | 1130 | help |
1122 | This driver supports the on-board graphics built in to the Intel | 1131 | This driver supports the on-board graphics built in to the Intel |
1123 | 830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM chipsets. | 1132 | 830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM chipsets. |
@@ -1470,6 +1479,7 @@ config FB_SIS | |||
1470 | select FB_CFB_FILLRECT | 1479 | select FB_CFB_FILLRECT |
1471 | select FB_CFB_COPYAREA | 1480 | select FB_CFB_COPYAREA |
1472 | select FB_CFB_IMAGEBLIT | 1481 | select FB_CFB_IMAGEBLIT |
1482 | select FB_BOOT_VESA_SUPPORT | ||
1473 | help | 1483 | help |
1474 | This is the frame buffer device driver for the SiS 300, 315, 330 | 1484 | This is the frame buffer device driver for the SiS 300, 315, 330 |
1475 | and 340 series as well as XGI V3XT, V5, V8, Z7 graphics chipsets. | 1485 | and 340 series as well as XGI V3XT, V5, V8, Z7 graphics chipsets. |
@@ -1492,6 +1502,24 @@ config FB_SIS_315 | |||
1492 | (315/H/PRO, 55x, 650, 651, 740, 330, 661, 741, 760, 761) as well | 1502 | (315/H/PRO, 55x, 650, 651, 740, 330, 661, 741, 760, 761) as well |
1493 | as XGI V3XT, V5, V8 and Z7. | 1503 | as XGI V3XT, V5, V8 and Z7. |
1494 | 1504 | ||
1505 | config FB_VIA | ||
1506 | tristate "VIA UniChrome (Pro) and Chrome9 display support" | ||
1507 | depends on FB && PCI | ||
1508 | select FB_CFB_FILLRECT | ||
1509 | select FB_CFB_COPYAREA | ||
1510 | select FB_CFB_IMAGEBLIT | ||
1511 | select FB_SOFT_CURSOR | ||
1512 | select I2C_ALGOBIT | ||
1513 | select I2C | ||
1514 | help | ||
1515 | This is the frame buffer device driver for Graphics chips of VIA | ||
1516 | UniChrome (Pro) Family (CLE266,PM800/CN400,P4M800CE/P4M800Pro/ | ||
1517 | CN700/VN800,CX700/VX700,P4M890) and Chrome9 Family (K8M890,CN896 | ||
1518 | /P4M900,VX800) | ||
1519 | Say Y if you have a VIA UniChrome graphics board. | ||
1520 | |||
1521 | To compile this driver as a module, choose M here: the | ||
1522 | module will be called viafb. | ||
1495 | config FB_NEOMAGIC | 1523 | config FB_NEOMAGIC |
1496 | tristate "NeoMagic display support" | 1524 | tristate "NeoMagic display support" |
1497 | depends on FB && PCI | 1525 | depends on FB && PCI |
@@ -1521,25 +1549,25 @@ config FB_KYRO | |||
1521 | module will be called kyrofb. | 1549 | module will be called kyrofb. |
1522 | 1550 | ||
1523 | config FB_3DFX | 1551 | config FB_3DFX |
1524 | tristate "3Dfx Banshee/Voodoo3 display support" | 1552 | tristate "3Dfx Banshee/Voodoo3/Voodoo5 display support" |
1525 | depends on FB && PCI | 1553 | depends on FB && PCI |
1526 | select FB_CFB_IMAGEBLIT | 1554 | select FB_CFB_IMAGEBLIT |
1527 | select FB_CFB_FILLRECT | 1555 | select FB_CFB_FILLRECT |
1528 | select FB_CFB_COPYAREA | 1556 | select FB_CFB_COPYAREA |
1529 | help | 1557 | help |
1530 | This driver supports graphics boards with the 3Dfx Banshee/Voodoo3 | 1558 | This driver supports graphics boards with the 3Dfx Banshee, |
1531 | chips. Say Y if you have such a graphics board. | 1559 | Voodoo3 or VSA-100 (aka Voodoo4/5) chips. Say Y if you have |
1560 | such a graphics board. | ||
1532 | 1561 | ||
1533 | To compile this driver as a module, choose M here: the | 1562 | To compile this driver as a module, choose M here: the |
1534 | module will be called tdfxfb. | 1563 | module will be called tdfxfb. |
1535 | 1564 | ||
1536 | config FB_3DFX_ACCEL | 1565 | config FB_3DFX_ACCEL |
1537 | bool "3Dfx Banshee/Voodoo3 Acceleration functions (EXPERIMENTAL)" | 1566 | bool "3Dfx Acceleration functions (EXPERIMENTAL)" |
1538 | depends on FB_3DFX && EXPERIMENTAL | 1567 | depends on FB_3DFX && EXPERIMENTAL |
1539 | ---help--- | 1568 | ---help--- |
1540 | This will compile the 3Dfx Banshee/Voodoo3 frame buffer device | 1569 | This will compile the 3Dfx Banshee/Voodoo3/VSA-100 frame buffer |
1541 | with acceleration functions. | 1570 | device driver with acceleration functions. |
1542 | |||
1543 | 1571 | ||
1544 | config FB_VOODOO1 | 1572 | config FB_VOODOO1 |
1545 | tristate "3Dfx Voodoo Graphics (sst1) support" | 1573 | tristate "3Dfx Voodoo Graphics (sst1) support" |
@@ -1604,17 +1632,16 @@ config FB_TRIDENT | |||
1604 | select FB_CFB_COPYAREA | 1632 | select FB_CFB_COPYAREA |
1605 | select FB_CFB_IMAGEBLIT | 1633 | select FB_CFB_IMAGEBLIT |
1606 | ---help--- | 1634 | ---help--- |
1607 | This driver is supposed to support graphics boards with the | 1635 | This is the frame buffer device driver for Trident PCI/AGP chipsets. |
1608 | Trident CyberXXXX/Image/CyberBlade chips mostly found in laptops | 1636 | Supported chipset families are TGUI 9440/96XX, 3DImage, Blade3D |
1637 | and Blade XP. | ||
1638 | There are also integrated versions of these chips called CyberXXXX, | ||
1639 | CyberImage or CyberBlade. These chips are mostly found in laptops | ||
1609 | but also on some motherboards. For more information, read | 1640 | but also on some motherboards. For more information, read |
1610 | <file:Documentation/fb/tridentfb.txt> | 1641 | <file:Documentation/fb/tridentfb.txt> |
1611 | 1642 | ||
1612 | Cyberblade/i1 support will be removed soon, use the cyblafb driver | ||
1613 | instead. | ||
1614 | |||
1615 | Say Y if you have such a graphics board. | 1643 | Say Y if you have such a graphics board. |
1616 | 1644 | ||
1617 | |||
1618 | To compile this driver as a module, choose M here: the | 1645 | To compile this driver as a module, choose M here: the |
1619 | module will be called tridentfb. | 1646 | module will be called tridentfb. |
1620 | 1647 | ||
@@ -1869,6 +1896,28 @@ config FB_SH_MOBILE_LCDC | |||
1869 | ---help--- | 1896 | ---help--- |
1870 | Frame buffer driver for the on-chip SH-Mobile LCD controller. | 1897 | Frame buffer driver for the on-chip SH-Mobile LCD controller. |
1871 | 1898 | ||
1899 | config FB_TMIO | ||
1900 | tristate "Toshiba Mobile IO FrameBuffer support" | ||
1901 | depends on FB && MFD_CORE | ||
1902 | select FB_CFB_FILLRECT | ||
1903 | select FB_CFB_COPYAREA | ||
1904 | select FB_CFB_IMAGEBLIT | ||
1905 | ---help--- | ||
1906 | Frame buffer driver for the Toshiba Mobile IO integrated as found | ||
1907 | on the Sharp SL-6000 series | ||
1908 | |||
1909 | This driver is also available as a module ( = code which can be | ||
1910 | inserted and removed from the running kernel whenever you want). The | ||
1911 | module will be called tmiofb. If you want to compile it as a module, | ||
1912 | say M here and read <file:Documentation/kbuild/modules.txt>. | ||
1913 | |||
1914 | If unsure, say N. | ||
1915 | |||
1916 | config FB_TMIO_ACCELL | ||
1917 | bool "tmiofb acceleration" | ||
1918 | depends on FB_TMIO | ||
1919 | default y | ||
1920 | |||
1872 | config FB_S3C2410 | 1921 | config FB_S3C2410 |
1873 | tristate "S3C2410 LCD framebuffer support" | 1922 | tristate "S3C2410 LCD framebuffer support" |
1874 | depends on FB && ARCH_S3C2410 | 1923 | depends on FB && ARCH_S3C2410 |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index ad0330bf9be3..248bddc8d0b0 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
@@ -42,6 +42,7 @@ obj-$(CONFIG_FB_ATY) += aty/ macmodes.o | |||
42 | obj-$(CONFIG_FB_ATY128) += aty/ macmodes.o | 42 | obj-$(CONFIG_FB_ATY128) += aty/ macmodes.o |
43 | obj-$(CONFIG_FB_RADEON) += aty/ | 43 | obj-$(CONFIG_FB_RADEON) += aty/ |
44 | obj-$(CONFIG_FB_SIS) += sis/ | 44 | obj-$(CONFIG_FB_SIS) += sis/ |
45 | obj-$(CONFIG_FB_VIA) += via/ | ||
45 | obj-$(CONFIG_FB_KYRO) += kyro/ | 46 | obj-$(CONFIG_FB_KYRO) += kyro/ |
46 | obj-$(CONFIG_FB_SAVAGE) += savage/ | 47 | obj-$(CONFIG_FB_SAVAGE) += savage/ |
47 | obj-$(CONFIG_FB_GEODE) += geode/ | 48 | obj-$(CONFIG_FB_GEODE) += geode/ |
@@ -97,6 +98,7 @@ obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o | |||
97 | obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o | 98 | obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o |
98 | obj-$(CONFIG_FB_PXA) += pxafb.o | 99 | obj-$(CONFIG_FB_PXA) += pxafb.o |
99 | obj-$(CONFIG_FB_W100) += w100fb.o | 100 | obj-$(CONFIG_FB_W100) += w100fb.o |
101 | obj-$(CONFIG_FB_TMIO) += tmiofb.o | ||
100 | obj-$(CONFIG_FB_AU1100) += au1100fb.o | 102 | obj-$(CONFIG_FB_AU1100) += au1100fb.o |
101 | obj-$(CONFIG_FB_AU1200) += au1200fb.o | 103 | obj-$(CONFIG_FB_AU1200) += au1200fb.o |
102 | obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o | 104 | obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o |
@@ -124,7 +126,6 @@ obj-$(CONFIG_FB_CARMINE) += carminefb.o | |||
124 | # Platform or fallback drivers go here | 126 | # Platform or fallback drivers go here |
125 | obj-$(CONFIG_FB_UVESA) += uvesafb.o | 127 | obj-$(CONFIG_FB_UVESA) += uvesafb.o |
126 | obj-$(CONFIG_FB_VESA) += vesafb.o | 128 | obj-$(CONFIG_FB_VESA) += vesafb.o |
127 | obj-$(CONFIG_FB_IMAC) += imacfb.o | ||
128 | obj-$(CONFIG_FB_EFI) += efifb.o | 129 | obj-$(CONFIG_FB_EFI) += efifb.o |
129 | obj-$(CONFIG_FB_VGA16) += vga16fb.o | 130 | obj-$(CONFIG_FB_VGA16) += vga16fb.o |
130 | obj-$(CONFIG_FB_OF) += offb.o | 131 | obj-$(CONFIG_FB_OF) += offb.o |
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index d38fd5217422..f8d0a57a07cb 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c | |||
@@ -372,6 +372,13 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, | |||
372 | var->transp.offset = var->transp.length = 0; | 372 | var->transp.offset = var->transp.length = 0; |
373 | var->xoffset = var->yoffset = 0; | 373 | var->xoffset = var->yoffset = 0; |
374 | 374 | ||
375 | if (info->fix.smem_len) { | ||
376 | unsigned int smem_len = (var->xres_virtual * var->yres_virtual | ||
377 | * ((var->bits_per_pixel + 7) / 8)); | ||
378 | if (smem_len > info->fix.smem_len) | ||
379 | return -EINVAL; | ||
380 | } | ||
381 | |||
375 | /* Saturate vertical and horizontal timings at maximum values */ | 382 | /* Saturate vertical and horizontal timings at maximum values */ |
376 | var->vsync_len = min_t(u32, var->vsync_len, | 383 | var->vsync_len = min_t(u32, var->vsync_len, |
377 | (ATMEL_LCDC_VPW >> ATMEL_LCDC_VPW_OFFSET) + 1); | 384 | (ATMEL_LCDC_VPW >> ATMEL_LCDC_VPW_OFFSET) + 1); |
diff --git a/drivers/video/aty/radeon_accel.c b/drivers/video/aty/radeon_accel.c index aa95f8350242..8718f7349d6b 100644 --- a/drivers/video/aty/radeon_accel.c +++ b/drivers/video/aty/radeon_accel.c | |||
@@ -5,61 +5,61 @@ | |||
5 | * --dte | 5 | * --dte |
6 | */ | 6 | */ |
7 | 7 | ||
8 | static void radeon_fixup_offset(struct radeonfb_info *rinfo) | 8 | #define FLUSH_CACHE_WORKAROUND 1 |
9 | |||
10 | void radeon_fifo_update_and_wait(struct radeonfb_info *rinfo, int entries) | ||
9 | { | 11 | { |
10 | u32 local_base; | 12 | int i; |
11 | |||
12 | /* *** Ugly workaround *** */ | ||
13 | /* | ||
14 | * On some platforms, the video memory is mapped at 0 in radeon chip space | ||
15 | * (like PPCs) by the firmware. X will always move it up so that it's seen | ||
16 | * by the chip to be at the same address as the PCI BAR. | ||
17 | * That means that when switching back from X, there is a mismatch between | ||
18 | * the offsets programmed into the engine. This means that potentially, | ||
19 | * accel operations done before radeonfb has a chance to re-init the engine | ||
20 | * will have incorrect offsets, and potentially trash system memory ! | ||
21 | * | ||
22 | * The correct fix is for fbcon to never call any accel op before the engine | ||
23 | * has properly been re-initialized (by a call to set_var), but this is a | ||
24 | * complex fix. This workaround in the meantime, called before every accel | ||
25 | * operation, makes sure the offsets are in sync. | ||
26 | */ | ||
27 | 13 | ||
28 | radeon_fifo_wait (1); | 14 | for (i=0; i<2000000; i++) { |
29 | local_base = INREG(MC_FB_LOCATION) << 16; | 15 | rinfo->fifo_free = INREG(RBBM_STATUS) & 0x7f; |
30 | if (local_base == rinfo->fb_local_base) | 16 | if (rinfo->fifo_free >= entries) |
31 | return; | 17 | return; |
18 | udelay(10); | ||
19 | } | ||
20 | printk(KERN_ERR "radeonfb: FIFO Timeout !\n"); | ||
21 | /* XXX Todo: attempt to reset the engine */ | ||
22 | } | ||
32 | 23 | ||
33 | rinfo->fb_local_base = local_base; | 24 | static inline void radeon_fifo_wait(struct radeonfb_info *rinfo, int entries) |
25 | { | ||
26 | if (entries <= rinfo->fifo_free) | ||
27 | rinfo->fifo_free -= entries; | ||
28 | else | ||
29 | radeon_fifo_update_and_wait(rinfo, entries); | ||
30 | } | ||
34 | 31 | ||
35 | radeon_fifo_wait (3); | 32 | static inline void radeonfb_set_creg(struct radeonfb_info *rinfo, u32 reg, |
36 | OUTREG(DEFAULT_PITCH_OFFSET, (rinfo->pitch << 0x16) | | 33 | u32 *cache, u32 new_val) |
37 | (rinfo->fb_local_base >> 10)); | 34 | { |
38 | OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); | 35 | if (new_val == *cache) |
39 | OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); | 36 | return; |
37 | *cache = new_val; | ||
38 | radeon_fifo_wait(rinfo, 1); | ||
39 | OUTREG(reg, new_val); | ||
40 | } | 40 | } |
41 | 41 | ||
42 | static void radeonfb_prim_fillrect(struct radeonfb_info *rinfo, | 42 | static void radeonfb_prim_fillrect(struct radeonfb_info *rinfo, |
43 | const struct fb_fillrect *region) | 43 | const struct fb_fillrect *region) |
44 | { | 44 | { |
45 | radeon_fifo_wait(4); | 45 | radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache, |
46 | 46 | rinfo->dp_gui_mc_base | GMC_BRUSH_SOLID_COLOR | ROP3_P); | |
47 | OUTREG(DP_GUI_MASTER_CNTL, | 47 | radeonfb_set_creg(rinfo, DP_CNTL, &rinfo->dp_cntl_cache, |
48 | rinfo->dp_gui_master_cntl /* contains, like GMC_DST_32BPP */ | 48 | DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM); |
49 | | GMC_BRUSH_SOLID_COLOR | 49 | radeonfb_set_creg(rinfo, DP_BRUSH_FRGD_CLR, &rinfo->dp_brush_fg_cache, |
50 | | ROP3_P); | 50 | region->color); |
51 | if (radeon_get_dstbpp(rinfo->depth) != DST_8BPP) | 51 | |
52 | OUTREG(DP_BRUSH_FRGD_CLR, rinfo->pseudo_palette[region->color]); | 52 | /* Ensure the dst cache is flushed and the engine idle before |
53 | else | 53 | * issuing the operation. |
54 | OUTREG(DP_BRUSH_FRGD_CLR, region->color); | 54 | * |
55 | OUTREG(DP_WRITE_MSK, 0xffffffff); | 55 | * This works around engine lockups on some cards |
56 | OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM)); | 56 | */ |
57 | 57 | #if FLUSH_CACHE_WORKAROUND | |
58 | radeon_fifo_wait(2); | 58 | radeon_fifo_wait(rinfo, 2); |
59 | OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL); | 59 | OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL); |
60 | OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE)); | 60 | OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE)); |
61 | 61 | #endif | |
62 | radeon_fifo_wait(2); | 62 | radeon_fifo_wait(rinfo, 2); |
63 | OUTREG(DST_Y_X, (region->dy << 16) | region->dx); | 63 | OUTREG(DST_Y_X, (region->dy << 16) | region->dx); |
64 | OUTREG(DST_WIDTH_HEIGHT, (region->width << 16) | region->height); | 64 | OUTREG(DST_WIDTH_HEIGHT, (region->width << 16) | region->height); |
65 | } | 65 | } |
@@ -70,15 +70,14 @@ void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region) | |||
70 | struct fb_fillrect modded; | 70 | struct fb_fillrect modded; |
71 | int vxres, vyres; | 71 | int vxres, vyres; |
72 | 72 | ||
73 | if (info->state != FBINFO_STATE_RUNNING) | 73 | WARN_ON(rinfo->gfx_mode); |
74 | if (info->state != FBINFO_STATE_RUNNING || rinfo->gfx_mode) | ||
74 | return; | 75 | return; |
75 | if (info->flags & FBINFO_HWACCEL_DISABLED) { | 76 | if (info->flags & FBINFO_HWACCEL_DISABLED) { |
76 | cfb_fillrect(info, region); | 77 | cfb_fillrect(info, region); |
77 | return; | 78 | return; |
78 | } | 79 | } |
79 | 80 | ||
80 | radeon_fixup_offset(rinfo); | ||
81 | |||
82 | vxres = info->var.xres_virtual; | 81 | vxres = info->var.xres_virtual; |
83 | vyres = info->var.yres_virtual; | 82 | vyres = info->var.yres_virtual; |
84 | 83 | ||
@@ -91,6 +90,10 @@ void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region) | |||
91 | if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx; | 90 | if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx; |
92 | if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy; | 91 | if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy; |
93 | 92 | ||
93 | if (info->fix.visual == FB_VISUAL_TRUECOLOR || | ||
94 | info->fix.visual == FB_VISUAL_DIRECTCOLOR ) | ||
95 | modded.color = ((u32 *) (info->pseudo_palette))[region->color]; | ||
96 | |||
94 | radeonfb_prim_fillrect(rinfo, &modded); | 97 | radeonfb_prim_fillrect(rinfo, &modded); |
95 | } | 98 | } |
96 | 99 | ||
@@ -109,22 +112,22 @@ static void radeonfb_prim_copyarea(struct radeonfb_info *rinfo, | |||
109 | if ( xdir < 0 ) { sx += w-1; dx += w-1; } | 112 | if ( xdir < 0 ) { sx += w-1; dx += w-1; } |
110 | if ( ydir < 0 ) { sy += h-1; dy += h-1; } | 113 | if ( ydir < 0 ) { sy += h-1; dy += h-1; } |
111 | 114 | ||
112 | radeon_fifo_wait(3); | 115 | radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache, |
113 | OUTREG(DP_GUI_MASTER_CNTL, | 116 | rinfo->dp_gui_mc_base | |
114 | rinfo->dp_gui_master_cntl /* i.e. GMC_DST_32BPP */ | 117 | GMC_BRUSH_NONE | |
115 | | GMC_BRUSH_NONE | 118 | GMC_SRC_DATATYPE_COLOR | |
116 | | GMC_SRC_DSTCOLOR | 119 | ROP3_S | |
117 | | ROP3_S | 120 | DP_SRC_SOURCE_MEMORY); |
118 | | DP_SRC_SOURCE_MEMORY ); | 121 | radeonfb_set_creg(rinfo, DP_CNTL, &rinfo->dp_cntl_cache, |
119 | OUTREG(DP_WRITE_MSK, 0xffffffff); | 122 | (xdir>=0 ? DST_X_LEFT_TO_RIGHT : 0) | |
120 | OUTREG(DP_CNTL, (xdir>=0 ? DST_X_LEFT_TO_RIGHT : 0) | 123 | (ydir>=0 ? DST_Y_TOP_TO_BOTTOM : 0)); |
121 | | (ydir>=0 ? DST_Y_TOP_TO_BOTTOM : 0)); | 124 | |
122 | 125 | #if FLUSH_CACHE_WORKAROUND | |
123 | radeon_fifo_wait(2); | 126 | radeon_fifo_wait(rinfo, 2); |
124 | OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL); | 127 | OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL); |
125 | OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE)); | 128 | OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE)); |
126 | 129 | #endif | |
127 | radeon_fifo_wait(3); | 130 | radeon_fifo_wait(rinfo, 3); |
128 | OUTREG(SRC_Y_X, (sy << 16) | sx); | 131 | OUTREG(SRC_Y_X, (sy << 16) | sx); |
129 | OUTREG(DST_Y_X, (dy << 16) | dx); | 132 | OUTREG(DST_Y_X, (dy << 16) | dx); |
130 | OUTREG(DST_HEIGHT_WIDTH, (h << 16) | w); | 133 | OUTREG(DST_HEIGHT_WIDTH, (h << 16) | w); |
@@ -143,15 +146,14 @@ void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) | |||
143 | modded.width = area->width; | 146 | modded.width = area->width; |
144 | modded.height = area->height; | 147 | modded.height = area->height; |
145 | 148 | ||
146 | if (info->state != FBINFO_STATE_RUNNING) | 149 | WARN_ON(rinfo->gfx_mode); |
150 | if (info->state != FBINFO_STATE_RUNNING || rinfo->gfx_mode) | ||
147 | return; | 151 | return; |
148 | if (info->flags & FBINFO_HWACCEL_DISABLED) { | 152 | if (info->flags & FBINFO_HWACCEL_DISABLED) { |
149 | cfb_copyarea(info, area); | 153 | cfb_copyarea(info, area); |
150 | return; | 154 | return; |
151 | } | 155 | } |
152 | 156 | ||
153 | radeon_fixup_offset(rinfo); | ||
154 | |||
155 | vxres = info->var.xres_virtual; | 157 | vxres = info->var.xres_virtual; |
156 | vyres = info->var.yres_virtual; | 158 | vyres = info->var.yres_virtual; |
157 | 159 | ||
@@ -168,13 +170,112 @@ void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) | |||
168 | radeonfb_prim_copyarea(rinfo, &modded); | 170 | radeonfb_prim_copyarea(rinfo, &modded); |
169 | } | 171 | } |
170 | 172 | ||
173 | static void radeonfb_prim_imageblit(struct radeonfb_info *rinfo, | ||
174 | const struct fb_image *image, | ||
175 | u32 fg, u32 bg) | ||
176 | { | ||
177 | unsigned int src_bytes, dwords; | ||
178 | u32 *bits; | ||
179 | |||
180 | radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache, | ||
181 | rinfo->dp_gui_mc_base | | ||
182 | GMC_BRUSH_NONE | | ||
183 | GMC_SRC_DATATYPE_MONO_FG_BG | | ||
184 | ROP3_S | | ||
185 | GMC_BYTE_ORDER_MSB_TO_LSB | | ||
186 | DP_SRC_SOURCE_HOST_DATA); | ||
187 | radeonfb_set_creg(rinfo, DP_CNTL, &rinfo->dp_cntl_cache, | ||
188 | DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM); | ||
189 | radeonfb_set_creg(rinfo, DP_SRC_FRGD_CLR, &rinfo->dp_src_fg_cache, fg); | ||
190 | radeonfb_set_creg(rinfo, DP_SRC_BKGD_CLR, &rinfo->dp_src_bg_cache, bg); | ||
191 | |||
192 | radeon_fifo_wait(rinfo, 1); | ||
193 | OUTREG(DST_Y_X, (image->dy << 16) | image->dx); | ||
194 | |||
195 | /* Ensure the dst cache is flushed and the engine idle before | ||
196 | * issuing the operation. | ||
197 | * | ||
198 | * This works around engine lockups on some cards | ||
199 | */ | ||
200 | #if FLUSH_CACHE_WORKAROUND | ||
201 | radeon_fifo_wait(rinfo, 2); | ||
202 | OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL); | ||
203 | OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE)); | ||
204 | #endif | ||
205 | |||
206 | /* X here pads width to a multiple of 32 and uses the clipper to | ||
207 | * adjust the result. Is that really necessary ? Things seem to | ||
208 | * work ok for me without that and the doco doesn't seem to imply | ||
209 | * there is such a restriction. | ||
210 | */ | ||
211 | OUTREG(DST_WIDTH_HEIGHT, (image->width << 16) | image->height); | ||
212 | |||
213 | src_bytes = (((image->width * image->depth) + 7) / 8) * image->height; | ||
214 | dwords = (src_bytes + 3) / 4; | ||
215 | bits = (u32*)(image->data); | ||
216 | |||
217 | while(dwords >= 8) { | ||
218 | radeon_fifo_wait(rinfo, 8); | ||
219 | #if BITS_PER_LONG == 64 | ||
220 | __raw_writeq(*((u64 *)(bits)), rinfo->mmio_base + HOST_DATA0); | ||
221 | __raw_writeq(*((u64 *)(bits+2)), rinfo->mmio_base + HOST_DATA2); | ||
222 | __raw_writeq(*((u64 *)(bits+4)), rinfo->mmio_base + HOST_DATA4); | ||
223 | __raw_writeq(*((u64 *)(bits+6)), rinfo->mmio_base + HOST_DATA6); | ||
224 | bits += 8; | ||
225 | #else | ||
226 | __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA0); | ||
227 | __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA1); | ||
228 | __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA2); | ||
229 | __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA3); | ||
230 | __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA4); | ||
231 | __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA5); | ||
232 | __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA6); | ||
233 | __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA7); | ||
234 | #endif | ||
235 | dwords -= 8; | ||
236 | } | ||
237 | while(dwords--) { | ||
238 | radeon_fifo_wait(rinfo, 1); | ||
239 | __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA0); | ||
240 | } | ||
241 | } | ||
242 | |||
171 | void radeonfb_imageblit(struct fb_info *info, const struct fb_image *image) | 243 | void radeonfb_imageblit(struct fb_info *info, const struct fb_image *image) |
172 | { | 244 | { |
173 | struct radeonfb_info *rinfo = info->par; | 245 | struct radeonfb_info *rinfo = info->par; |
246 | u32 fg, bg; | ||
174 | 247 | ||
175 | if (info->state != FBINFO_STATE_RUNNING) | 248 | WARN_ON(rinfo->gfx_mode); |
249 | if (info->state != FBINFO_STATE_RUNNING || rinfo->gfx_mode) | ||
250 | return; | ||
251 | |||
252 | if (!image->width || !image->height) | ||
176 | return; | 253 | return; |
177 | radeon_engine_idle(); | 254 | |
255 | /* We only do 1 bpp color expansion for now */ | ||
256 | if (info->flags & FBINFO_HWACCEL_DISABLED || image->depth != 1) | ||
257 | goto fallback; | ||
258 | |||
259 | /* Fallback if running out of the screen. We may do clipping | ||
260 | * in the future */ | ||
261 | if ((image->dx + image->width) > info->var.xres_virtual || | ||
262 | (image->dy + image->height) > info->var.yres_virtual) | ||
263 | goto fallback; | ||
264 | |||
265 | if (info->fix.visual == FB_VISUAL_TRUECOLOR || | ||
266 | info->fix.visual == FB_VISUAL_DIRECTCOLOR) { | ||
267 | fg = ((u32*)(info->pseudo_palette))[image->fg_color]; | ||
268 | bg = ((u32*)(info->pseudo_palette))[image->bg_color]; | ||
269 | } else { | ||
270 | fg = image->fg_color; | ||
271 | bg = image->bg_color; | ||
272 | } | ||
273 | |||
274 | radeonfb_prim_imageblit(rinfo, image, fg, bg); | ||
275 | return; | ||
276 | |||
277 | fallback: | ||
278 | radeon_engine_idle(rinfo); | ||
178 | 279 | ||
179 | cfb_imageblit(info, image); | 280 | cfb_imageblit(info, image); |
180 | } | 281 | } |
@@ -185,7 +286,8 @@ int radeonfb_sync(struct fb_info *info) | |||
185 | 286 | ||
186 | if (info->state != FBINFO_STATE_RUNNING) | 287 | if (info->state != FBINFO_STATE_RUNNING) |
187 | return 0; | 288 | return 0; |
188 | radeon_engine_idle(); | 289 | |
290 | radeon_engine_idle(rinfo); | ||
189 | 291 | ||
190 | return 0; | 292 | return 0; |
191 | } | 293 | } |
@@ -211,9 +313,7 @@ void radeonfb_engine_reset(struct radeonfb_info *rinfo) | |||
211 | host_path_cntl = INREG(HOST_PATH_CNTL); | 313 | host_path_cntl = INREG(HOST_PATH_CNTL); |
212 | rbbm_soft_reset = INREG(RBBM_SOFT_RESET); | 314 | rbbm_soft_reset = INREG(RBBM_SOFT_RESET); |
213 | 315 | ||
214 | if (rinfo->family == CHIP_FAMILY_R300 || | 316 | if (IS_R300_VARIANT(rinfo)) { |
215 | rinfo->family == CHIP_FAMILY_R350 || | ||
216 | rinfo->family == CHIP_FAMILY_RV350) { | ||
217 | u32 tmp; | 317 | u32 tmp; |
218 | 318 | ||
219 | OUTREG(RBBM_SOFT_RESET, (rbbm_soft_reset | | 319 | OUTREG(RBBM_SOFT_RESET, (rbbm_soft_reset | |
@@ -249,9 +349,7 @@ void radeonfb_engine_reset(struct radeonfb_info *rinfo) | |||
249 | INREG(HOST_PATH_CNTL); | 349 | INREG(HOST_PATH_CNTL); |
250 | OUTREG(HOST_PATH_CNTL, host_path_cntl); | 350 | OUTREG(HOST_PATH_CNTL, host_path_cntl); |
251 | 351 | ||
252 | if (rinfo->family != CHIP_FAMILY_R300 && | 352 | if (!IS_R300_VARIANT(rinfo)) |
253 | rinfo->family != CHIP_FAMILY_R350 && | ||
254 | rinfo->family != CHIP_FAMILY_RV350) | ||
255 | OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset); | 353 | OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset); |
256 | 354 | ||
257 | OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index); | 355 | OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index); |
@@ -265,15 +363,24 @@ void radeonfb_engine_init (struct radeonfb_info *rinfo) | |||
265 | /* disable 3D engine */ | 363 | /* disable 3D engine */ |
266 | OUTREG(RB3D_CNTL, 0); | 364 | OUTREG(RB3D_CNTL, 0); |
267 | 365 | ||
366 | rinfo->fifo_free = 0; | ||
268 | radeonfb_engine_reset(rinfo); | 367 | radeonfb_engine_reset(rinfo); |
269 | 368 | ||
270 | radeon_fifo_wait (1); | 369 | radeon_fifo_wait(rinfo, 1); |
271 | if ((rinfo->family != CHIP_FAMILY_R300) && | 370 | if (IS_R300_VARIANT(rinfo)) { |
272 | (rinfo->family != CHIP_FAMILY_R350) && | 371 | OUTREG(RB2D_DSTCACHE_MODE, INREG(RB2D_DSTCACHE_MODE) | |
273 | (rinfo->family != CHIP_FAMILY_RV350)) | 372 | RB2D_DC_AUTOFLUSH_ENABLE | |
373 | RB2D_DC_DC_DISABLE_IGNORE_PE); | ||
374 | } else { | ||
375 | /* This needs to be double checked with ATI. Latest X driver | ||
376 | * completely "forgets" to set this register on < r3xx, and | ||
377 | * we used to just write 0 there... I'll keep the 0 and update | ||
378 | * that when we have sorted things out on X side. | ||
379 | */ | ||
274 | OUTREG(RB2D_DSTCACHE_MODE, 0); | 380 | OUTREG(RB2D_DSTCACHE_MODE, 0); |
381 | } | ||
275 | 382 | ||
276 | radeon_fifo_wait (3); | 383 | radeon_fifo_wait(rinfo, 3); |
277 | /* We re-read MC_FB_LOCATION from card as it can have been | 384 | /* We re-read MC_FB_LOCATION from card as it can have been |
278 | * modified by XFree drivers (ouch !) | 385 | * modified by XFree drivers (ouch !) |
279 | */ | 386 | */ |
@@ -284,41 +391,57 @@ void radeonfb_engine_init (struct radeonfb_info *rinfo) | |||
284 | OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); | 391 | OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); |
285 | OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); | 392 | OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); |
286 | 393 | ||
287 | radeon_fifo_wait (1); | 394 | radeon_fifo_wait(rinfo, 1); |
288 | #if defined(__BIG_ENDIAN) | 395 | #ifdef __BIG_ENDIAN |
289 | OUTREGP(DP_DATATYPE, HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN); | 396 | OUTREGP(DP_DATATYPE, HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN); |
290 | #else | 397 | #else |
291 | OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN); | 398 | OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN); |
292 | #endif | 399 | #endif |
293 | radeon_fifo_wait (2); | 400 | radeon_fifo_wait(rinfo, 2); |
294 | OUTREG(DEFAULT_SC_TOP_LEFT, 0); | 401 | OUTREG(DEFAULT_SC_TOP_LEFT, 0); |
295 | OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX | | 402 | OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX | |
296 | DEFAULT_SC_BOTTOM_MAX)); | 403 | DEFAULT_SC_BOTTOM_MAX)); |
297 | 404 | ||
405 | /* set default DP_GUI_MASTER_CNTL */ | ||
298 | temp = radeon_get_dstbpp(rinfo->depth); | 406 | temp = radeon_get_dstbpp(rinfo->depth); |
299 | rinfo->dp_gui_master_cntl = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS); | 407 | rinfo->dp_gui_mc_base = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS); |
300 | 408 | ||
301 | radeon_fifo_wait (1); | 409 | rinfo->dp_gui_mc_cache = rinfo->dp_gui_mc_base | |
302 | OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl | | 410 | GMC_BRUSH_SOLID_COLOR | |
303 | GMC_BRUSH_SOLID_COLOR | | 411 | GMC_SRC_DATATYPE_COLOR; |
304 | GMC_SRC_DATATYPE_COLOR)); | 412 | radeon_fifo_wait(rinfo, 1); |
413 | OUTREG(DP_GUI_MASTER_CNTL, rinfo->dp_gui_mc_cache); | ||
305 | 414 | ||
306 | radeon_fifo_wait (7); | ||
307 | 415 | ||
308 | /* clear line drawing regs */ | 416 | /* clear line drawing regs */ |
417 | radeon_fifo_wait(rinfo, 2); | ||
309 | OUTREG(DST_LINE_START, 0); | 418 | OUTREG(DST_LINE_START, 0); |
310 | OUTREG(DST_LINE_END, 0); | 419 | OUTREG(DST_LINE_END, 0); |
311 | 420 | ||
312 | /* set brush color regs */ | 421 | /* set brush and source color regs */ |
313 | OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff); | 422 | rinfo->dp_brush_fg_cache = 0xffffffff; |
314 | OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000); | 423 | rinfo->dp_brush_bg_cache = 0x00000000; |
315 | 424 | rinfo->dp_src_fg_cache = 0xffffffff; | |
316 | /* set source color regs */ | 425 | rinfo->dp_src_bg_cache = 0x00000000; |
317 | OUTREG(DP_SRC_FRGD_CLR, 0xffffffff); | 426 | radeon_fifo_wait(rinfo, 4); |
318 | OUTREG(DP_SRC_BKGD_CLR, 0x00000000); | 427 | OUTREG(DP_BRUSH_FRGD_CLR, rinfo->dp_brush_fg_cache); |
428 | OUTREG(DP_BRUSH_BKGD_CLR, rinfo->dp_brush_bg_cache); | ||
429 | OUTREG(DP_SRC_FRGD_CLR, rinfo->dp_src_fg_cache); | ||
430 | OUTREG(DP_SRC_BKGD_CLR, rinfo->dp_src_bg_cache); | ||
431 | |||
432 | /* Default direction */ | ||
433 | rinfo->dp_cntl_cache = DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM; | ||
434 | radeon_fifo_wait(rinfo, 1); | ||
435 | OUTREG(DP_CNTL, rinfo->dp_cntl_cache); | ||
319 | 436 | ||
320 | /* default write mask */ | 437 | /* default write mask */ |
438 | radeon_fifo_wait(rinfo, 1); | ||
321 | OUTREG(DP_WRITE_MSK, 0xffffffff); | 439 | OUTREG(DP_WRITE_MSK, 0xffffffff); |
322 | 440 | ||
323 | radeon_engine_idle (); | 441 | /* Default to no swapping of host data */ |
442 | radeon_fifo_wait(rinfo, 1); | ||
443 | OUTREG(RBBM_GUICNTL, RBBM_GUICNTL_HOST_DATA_SWAP_NONE); | ||
444 | |||
445 | /* Make sure it's settled */ | ||
446 | radeon_engine_idle(rinfo); | ||
324 | } | 447 | } |
diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c index 1a056adb61c8..f343ba83f0ae 100644 --- a/drivers/video/aty/radeon_backlight.c +++ b/drivers/video/aty/radeon_backlight.c | |||
@@ -66,7 +66,7 @@ static int radeon_bl_update_status(struct backlight_device *bd) | |||
66 | level = bd->props.brightness; | 66 | level = bd->props.brightness; |
67 | 67 | ||
68 | del_timer_sync(&rinfo->lvds_timer); | 68 | del_timer_sync(&rinfo->lvds_timer); |
69 | radeon_engine_idle(); | 69 | radeon_engine_idle(rinfo); |
70 | 70 | ||
71 | lvds_gen_cntl = INREG(LVDS_GEN_CNTL); | 71 | lvds_gen_cntl = INREG(LVDS_GEN_CNTL); |
72 | if (level > 0) { | 72 | if (level > 0) { |
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 652273e9f5f9..9a5821c65ebf 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c | |||
@@ -852,7 +852,6 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var, | |||
852 | if (rinfo->asleep) | 852 | if (rinfo->asleep) |
853 | return 0; | 853 | return 0; |
854 | 854 | ||
855 | radeon_fifo_wait(2); | ||
856 | OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset) | 855 | OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset) |
857 | * var->bits_per_pixel / 8) & ~7); | 856 | * var->bits_per_pixel / 8) & ~7); |
858 | return 0; | 857 | return 0; |
@@ -882,7 +881,6 @@ static int radeonfb_ioctl (struct fb_info *info, unsigned int cmd, | |||
882 | if (rc) | 881 | if (rc) |
883 | return rc; | 882 | return rc; |
884 | 883 | ||
885 | radeon_fifo_wait(2); | ||
886 | if (value & 0x01) { | 884 | if (value & 0x01) { |
887 | tmp = INREG(LVDS_GEN_CNTL); | 885 | tmp = INREG(LVDS_GEN_CNTL); |
888 | 886 | ||
@@ -940,7 +938,7 @@ int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch) | |||
940 | if (rinfo->lock_blank) | 938 | if (rinfo->lock_blank) |
941 | return 0; | 939 | return 0; |
942 | 940 | ||
943 | radeon_engine_idle(); | 941 | radeon_engine_idle(rinfo); |
944 | 942 | ||
945 | val = INREG(CRTC_EXT_CNTL); | 943 | val = INREG(CRTC_EXT_CNTL); |
946 | val &= ~(CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS | | 944 | val &= ~(CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS | |
@@ -1048,7 +1046,7 @@ static int radeonfb_blank (int blank, struct fb_info *info) | |||
1048 | 1046 | ||
1049 | if (rinfo->asleep) | 1047 | if (rinfo->asleep) |
1050 | return 0; | 1048 | return 0; |
1051 | 1049 | ||
1052 | return radeon_screen_blank(rinfo, blank, 0); | 1050 | return radeon_screen_blank(rinfo, blank, 0); |
1053 | } | 1051 | } |
1054 | 1052 | ||
@@ -1074,8 +1072,6 @@ static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green, | |||
1074 | pindex = regno; | 1072 | pindex = regno; |
1075 | 1073 | ||
1076 | if (!rinfo->asleep) { | 1074 | if (!rinfo->asleep) { |
1077 | radeon_fifo_wait(9); | ||
1078 | |||
1079 | if (rinfo->bpp == 16) { | 1075 | if (rinfo->bpp == 16) { |
1080 | pindex = regno * 8; | 1076 | pindex = regno * 8; |
1081 | 1077 | ||
@@ -1244,8 +1240,6 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg | |||
1244 | { | 1240 | { |
1245 | int i; | 1241 | int i; |
1246 | 1242 | ||
1247 | radeon_fifo_wait(20); | ||
1248 | |||
1249 | /* Workaround from XFree */ | 1243 | /* Workaround from XFree */ |
1250 | if (rinfo->is_mobility) { | 1244 | if (rinfo->is_mobility) { |
1251 | /* A temporal workaround for the occational blanking on certain laptop | 1245 | /* A temporal workaround for the occational blanking on certain laptop |
@@ -1286,11 +1280,10 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg | |||
1286 | radeon_pll_errata_after_data(rinfo); | 1280 | radeon_pll_errata_after_data(rinfo); |
1287 | 1281 | ||
1288 | /* Set PPLL ref. div */ | 1282 | /* Set PPLL ref. div */ |
1289 | if (rinfo->family == CHIP_FAMILY_R300 || | 1283 | if (IS_R300_VARIANT(rinfo) || |
1290 | rinfo->family == CHIP_FAMILY_RS300 || | 1284 | rinfo->family == CHIP_FAMILY_RS300 || |
1291 | rinfo->family == CHIP_FAMILY_R350 || | 1285 | rinfo->family == CHIP_FAMILY_RS400 || |
1292 | rinfo->family == CHIP_FAMILY_RV350 || | 1286 | rinfo->family == CHIP_FAMILY_RS480) { |
1293 | rinfo->family == CHIP_FAMILY_RV380 ) { | ||
1294 | if (mode->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) { | 1287 | if (mode->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) { |
1295 | /* When restoring console mode, use saved PPLL_REF_DIV | 1288 | /* When restoring console mode, use saved PPLL_REF_DIV |
1296 | * setting. | 1289 | * setting. |
@@ -1342,7 +1335,7 @@ static void radeon_lvds_timer_func(unsigned long data) | |||
1342 | { | 1335 | { |
1343 | struct radeonfb_info *rinfo = (struct radeonfb_info *)data; | 1336 | struct radeonfb_info *rinfo = (struct radeonfb_info *)data; |
1344 | 1337 | ||
1345 | radeon_engine_idle(); | 1338 | radeon_engine_idle(rinfo); |
1346 | 1339 | ||
1347 | OUTREG(LVDS_GEN_CNTL, rinfo->pending_lvds_gen_cntl); | 1340 | OUTREG(LVDS_GEN_CNTL, rinfo->pending_lvds_gen_cntl); |
1348 | } | 1341 | } |
@@ -1360,10 +1353,11 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode, | |||
1360 | if (nomodeset) | 1353 | if (nomodeset) |
1361 | return; | 1354 | return; |
1362 | 1355 | ||
1356 | radeon_engine_idle(rinfo); | ||
1357 | |||
1363 | if (!regs_only) | 1358 | if (!regs_only) |
1364 | radeon_screen_blank(rinfo, FB_BLANK_NORMAL, 0); | 1359 | radeon_screen_blank(rinfo, FB_BLANK_NORMAL, 0); |
1365 | 1360 | ||
1366 | radeon_fifo_wait(31); | ||
1367 | for (i=0; i<10; i++) | 1361 | for (i=0; i<10; i++) |
1368 | OUTREG(common_regs[i].reg, common_regs[i].val); | 1362 | OUTREG(common_regs[i].reg, common_regs[i].val); |
1369 | 1363 | ||
@@ -1391,7 +1385,6 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode, | |||
1391 | radeon_write_pll_regs(rinfo, mode); | 1385 | radeon_write_pll_regs(rinfo, mode); |
1392 | 1386 | ||
1393 | if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) { | 1387 | if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) { |
1394 | radeon_fifo_wait(10); | ||
1395 | OUTREG(FP_CRTC_H_TOTAL_DISP, mode->fp_crtc_h_total_disp); | 1388 | OUTREG(FP_CRTC_H_TOTAL_DISP, mode->fp_crtc_h_total_disp); |
1396 | OUTREG(FP_CRTC_V_TOTAL_DISP, mode->fp_crtc_v_total_disp); | 1389 | OUTREG(FP_CRTC_V_TOTAL_DISP, mode->fp_crtc_v_total_disp); |
1397 | OUTREG(FP_H_SYNC_STRT_WID, mode->fp_h_sync_strt_wid); | 1390 | OUTREG(FP_H_SYNC_STRT_WID, mode->fp_h_sync_strt_wid); |
@@ -1406,7 +1399,6 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode, | |||
1406 | if (!regs_only) | 1399 | if (!regs_only) |
1407 | radeon_screen_blank(rinfo, FB_BLANK_UNBLANK, 0); | 1400 | radeon_screen_blank(rinfo, FB_BLANK_UNBLANK, 0); |
1408 | 1401 | ||
1409 | radeon_fifo_wait(2); | ||
1410 | OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl); | 1402 | OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl); |
1411 | 1403 | ||
1412 | return; | 1404 | return; |
@@ -1461,10 +1453,7 @@ static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs | |||
1461 | /* Not all chip revs have the same format for this register, | 1453 | /* Not all chip revs have the same format for this register, |
1462 | * extract the source selection | 1454 | * extract the source selection |
1463 | */ | 1455 | */ |
1464 | if (rinfo->family == CHIP_FAMILY_R200 || | 1456 | if (rinfo->family == CHIP_FAMILY_R200 || IS_R300_VARIANT(rinfo)) { |
1465 | rinfo->family == CHIP_FAMILY_R300 || | ||
1466 | rinfo->family == CHIP_FAMILY_R350 || | ||
1467 | rinfo->family == CHIP_FAMILY_RV350) { | ||
1468 | source = (fp2_gen_cntl >> 10) & 0x3; | 1457 | source = (fp2_gen_cntl >> 10) & 0x3; |
1469 | /* sourced from transform unit, check for transform unit | 1458 | /* sourced from transform unit, check for transform unit |
1470 | * own source | 1459 | * own source |
@@ -1560,7 +1549,7 @@ static int radeonfb_set_par(struct fb_info *info) | |||
1560 | /* We always want engine to be idle on a mode switch, even | 1549 | /* We always want engine to be idle on a mode switch, even |
1561 | * if we won't actually change the mode | 1550 | * if we won't actually change the mode |
1562 | */ | 1551 | */ |
1563 | radeon_engine_idle(); | 1552 | radeon_engine_idle(rinfo); |
1564 | 1553 | ||
1565 | hSyncStart = mode->xres + mode->right_margin; | 1554 | hSyncStart = mode->xres + mode->right_margin; |
1566 | hSyncEnd = hSyncStart + mode->hsync_len; | 1555 | hSyncEnd = hSyncStart + mode->hsync_len; |
@@ -1855,7 +1844,6 @@ static int radeonfb_set_par(struct fb_info *info) | |||
1855 | return 0; | 1844 | return 0; |
1856 | } | 1845 | } |
1857 | 1846 | ||
1858 | |||
1859 | static struct fb_ops radeonfb_ops = { | 1847 | static struct fb_ops radeonfb_ops = { |
1860 | .owner = THIS_MODULE, | 1848 | .owner = THIS_MODULE, |
1861 | .fb_check_var = radeonfb_check_var, | 1849 | .fb_check_var = radeonfb_check_var, |
@@ -1879,6 +1867,7 @@ static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo) | |||
1879 | info->par = rinfo; | 1867 | info->par = rinfo; |
1880 | info->pseudo_palette = rinfo->pseudo_palette; | 1868 | info->pseudo_palette = rinfo->pseudo_palette; |
1881 | info->flags = FBINFO_DEFAULT | 1869 | info->flags = FBINFO_DEFAULT |
1870 | | FBINFO_HWACCEL_IMAGEBLIT | ||
1882 | | FBINFO_HWACCEL_COPYAREA | 1871 | | FBINFO_HWACCEL_COPYAREA |
1883 | | FBINFO_HWACCEL_FILLRECT | 1872 | | FBINFO_HWACCEL_FILLRECT |
1884 | | FBINFO_HWACCEL_XPAN | 1873 | | FBINFO_HWACCEL_XPAN |
@@ -2005,11 +1994,11 @@ static void radeon_identify_vram(struct radeonfb_info *rinfo) | |||
2005 | (rinfo->family == CHIP_FAMILY_RS200) || | 1994 | (rinfo->family == CHIP_FAMILY_RS200) || |
2006 | (rinfo->family == CHIP_FAMILY_RS300) || | 1995 | (rinfo->family == CHIP_FAMILY_RS300) || |
2007 | (rinfo->family == CHIP_FAMILY_RC410) || | 1996 | (rinfo->family == CHIP_FAMILY_RC410) || |
1997 | (rinfo->family == CHIP_FAMILY_RS400) || | ||
2008 | (rinfo->family == CHIP_FAMILY_RS480) ) { | 1998 | (rinfo->family == CHIP_FAMILY_RS480) ) { |
2009 | u32 tom = INREG(NB_TOM); | 1999 | u32 tom = INREG(NB_TOM); |
2010 | tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024); | 2000 | tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024); |
2011 | 2001 | ||
2012 | radeon_fifo_wait(6); | ||
2013 | OUTREG(MC_FB_LOCATION, tom); | 2002 | OUTREG(MC_FB_LOCATION, tom); |
2014 | OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16); | 2003 | OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16); |
2015 | OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16); | 2004 | OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16); |
diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c index 8c8fa35f1b7c..2c5567175dca 100644 --- a/drivers/video/aty/radeon_i2c.c +++ b/drivers/video/aty/radeon_i2c.c | |||
@@ -139,12 +139,8 @@ void radeon_delete_i2c_busses(struct radeonfb_info *rinfo) | |||
139 | int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, | 139 | int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, |
140 | u8 **out_edid) | 140 | u8 **out_edid) |
141 | { | 141 | { |
142 | u32 reg = rinfo->i2c[conn-1].ddc_reg; | ||
143 | u8 *edid; | 142 | u8 *edid; |
144 | 143 | ||
145 | OUTREG(reg, INREG(reg) & | ||
146 | ~(VGA_DDC_DATA_OUTPUT | VGA_DDC_CLK_OUTPUT)); | ||
147 | |||
148 | edid = fb_ddc_read(&rinfo->i2c[conn-1].adapter); | 144 | edid = fb_ddc_read(&rinfo->i2c[conn-1].adapter); |
149 | 145 | ||
150 | if (out_edid) | 146 | if (out_edid) |
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index 675abdafc2d8..3df5015f1d13 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c | |||
@@ -2653,9 +2653,9 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) | |||
2653 | 2653 | ||
2654 | if (!(info->flags & FBINFO_HWACCEL_DISABLED)) { | 2654 | if (!(info->flags & FBINFO_HWACCEL_DISABLED)) { |
2655 | /* Make sure engine is reset */ | 2655 | /* Make sure engine is reset */ |
2656 | radeon_engine_idle(); | 2656 | radeon_engine_idle(rinfo); |
2657 | radeonfb_engine_reset(rinfo); | 2657 | radeonfb_engine_reset(rinfo); |
2658 | radeon_engine_idle(); | 2658 | radeon_engine_idle(rinfo); |
2659 | } | 2659 | } |
2660 | 2660 | ||
2661 | /* Blank display and LCD */ | 2661 | /* Blank display and LCD */ |
@@ -2767,7 +2767,7 @@ int radeonfb_pci_resume(struct pci_dev *pdev) | |||
2767 | 2767 | ||
2768 | rinfo->asleep = 0; | 2768 | rinfo->asleep = 0; |
2769 | } else | 2769 | } else |
2770 | radeon_engine_idle(); | 2770 | radeon_engine_idle(rinfo); |
2771 | 2771 | ||
2772 | /* Restore display & engine */ | 2772 | /* Restore display & engine */ |
2773 | radeon_write_mode (rinfo, &rinfo->state, 1); | 2773 | radeon_write_mode (rinfo, &rinfo->state, 1); |
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h index ccbfffd12805..ea0b5b47acaf 100644 --- a/drivers/video/aty/radeonfb.h +++ b/drivers/video/aty/radeonfb.h | |||
@@ -53,6 +53,7 @@ enum radeon_family { | |||
53 | CHIP_FAMILY_RV380, /* RV370/RV380/M22/M24 */ | 53 | CHIP_FAMILY_RV380, /* RV370/RV380/M22/M24 */ |
54 | CHIP_FAMILY_R420, /* R420/R423/M18 */ | 54 | CHIP_FAMILY_R420, /* R420/R423/M18 */ |
55 | CHIP_FAMILY_RC410, | 55 | CHIP_FAMILY_RC410, |
56 | CHIP_FAMILY_RS400, | ||
56 | CHIP_FAMILY_RS480, | 57 | CHIP_FAMILY_RS480, |
57 | CHIP_FAMILY_LAST, | 58 | CHIP_FAMILY_LAST, |
58 | }; | 59 | }; |
@@ -335,7 +336,15 @@ struct radeonfb_info { | |||
335 | int mon2_type; | 336 | int mon2_type; |
336 | u8 *mon2_EDID; | 337 | u8 *mon2_EDID; |
337 | 338 | ||
338 | u32 dp_gui_master_cntl; | 339 | /* accel bits */ |
340 | u32 dp_gui_mc_base; | ||
341 | u32 dp_gui_mc_cache; | ||
342 | u32 dp_cntl_cache; | ||
343 | u32 dp_brush_fg_cache; | ||
344 | u32 dp_brush_bg_cache; | ||
345 | u32 dp_src_fg_cache; | ||
346 | u32 dp_src_bg_cache; | ||
347 | u32 fifo_free; | ||
339 | 348 | ||
340 | struct pll_info pll; | 349 | struct pll_info pll; |
341 | 350 | ||
@@ -347,6 +356,7 @@ struct radeonfb_info { | |||
347 | int lock_blank; | 356 | int lock_blank; |
348 | int dynclk; | 357 | int dynclk; |
349 | int no_schedule; | 358 | int no_schedule; |
359 | int gfx_mode; | ||
350 | enum radeon_pm_mode pm_mode; | 360 | enum radeon_pm_mode pm_mode; |
351 | reinit_function_ptr reinit_func; | 361 | reinit_function_ptr reinit_func; |
352 | 362 | ||
@@ -391,8 +401,14 @@ static inline void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms) | |||
391 | #define OUTREG8(addr,val) writeb(val, (rinfo->mmio_base)+addr) | 401 | #define OUTREG8(addr,val) writeb(val, (rinfo->mmio_base)+addr) |
392 | #define INREG16(addr) readw((rinfo->mmio_base)+addr) | 402 | #define INREG16(addr) readw((rinfo->mmio_base)+addr) |
393 | #define OUTREG16(addr,val) writew(val, (rinfo->mmio_base)+addr) | 403 | #define OUTREG16(addr,val) writew(val, (rinfo->mmio_base)+addr) |
404 | |||
405 | #ifdef CONFIG_PPC | ||
406 | #define INREG(addr) ({ eieio(); ld_le32(rinfo->mmio_base+(addr)); }) | ||
407 | #define OUTREG(addr,val) do { eieio(); st_le32(rinfo->mmio_base+(addr),(val)); } while(0) | ||
408 | #else | ||
394 | #define INREG(addr) readl((rinfo->mmio_base)+addr) | 409 | #define INREG(addr) readl((rinfo->mmio_base)+addr) |
395 | #define OUTREG(addr,val) writel(val, (rinfo->mmio_base)+addr) | 410 | #define OUTREG(addr,val) writel(val, (rinfo->mmio_base)+addr) |
411 | #endif | ||
396 | 412 | ||
397 | static inline void _OUTREGP(struct radeonfb_info *rinfo, u32 addr, | 413 | static inline void _OUTREGP(struct radeonfb_info *rinfo, u32 addr, |
398 | u32 val, u32 mask) | 414 | u32 val, u32 mask) |
@@ -533,16 +549,25 @@ static inline u32 radeon_get_dstbpp(u16 depth) | |||
533 | /* | 549 | /* |
534 | * 2D Engine helper routines | 550 | * 2D Engine helper routines |
535 | */ | 551 | */ |
552 | |||
553 | extern void radeon_fifo_update_and_wait(struct radeonfb_info *rinfo, int entries); | ||
554 | |||
536 | static inline void radeon_engine_flush (struct radeonfb_info *rinfo) | 555 | static inline void radeon_engine_flush (struct radeonfb_info *rinfo) |
537 | { | 556 | { |
538 | int i; | 557 | int i; |
539 | 558 | ||
540 | /* initiate flush */ | 559 | /* Initiate flush */ |
541 | OUTREGP(RB2D_DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL, | 560 | OUTREGP(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL, |
542 | ~RB2D_DC_FLUSH_ALL); | 561 | ~RB2D_DC_FLUSH_ALL); |
543 | 562 | ||
563 | /* Ensure FIFO is empty, ie, make sure the flush commands | ||
564 | * has reached the cache | ||
565 | */ | ||
566 | radeon_fifo_update_and_wait(rinfo, 64); | ||
567 | |||
568 | /* Wait for the flush to complete */ | ||
544 | for (i=0; i < 2000000; i++) { | 569 | for (i=0; i < 2000000; i++) { |
545 | if (!(INREG(RB2D_DSTCACHE_CTLSTAT) & RB2D_DC_BUSY)) | 570 | if (!(INREG(DSTCACHE_CTLSTAT) & RB2D_DC_BUSY)) |
546 | return; | 571 | return; |
547 | udelay(1); | 572 | udelay(1); |
548 | } | 573 | } |
@@ -550,25 +575,12 @@ static inline void radeon_engine_flush (struct radeonfb_info *rinfo) | |||
550 | } | 575 | } |
551 | 576 | ||
552 | 577 | ||
553 | static inline void _radeon_fifo_wait(struct radeonfb_info *rinfo, int entries) | 578 | static inline void radeon_engine_idle(struct radeonfb_info *rinfo) |
554 | { | ||
555 | int i; | ||
556 | |||
557 | for (i=0; i<2000000; i++) { | ||
558 | if ((INREG(RBBM_STATUS) & 0x7f) >= entries) | ||
559 | return; | ||
560 | udelay(1); | ||
561 | } | ||
562 | printk(KERN_ERR "radeonfb: FIFO Timeout !\n"); | ||
563 | } | ||
564 | |||
565 | |||
566 | static inline void _radeon_engine_idle(struct radeonfb_info *rinfo) | ||
567 | { | 579 | { |
568 | int i; | 580 | int i; |
569 | 581 | ||
570 | /* ensure FIFO is empty before waiting for idle */ | 582 | /* ensure FIFO is empty before waiting for idle */ |
571 | _radeon_fifo_wait (rinfo, 64); | 583 | radeon_fifo_update_and_wait (rinfo, 64); |
572 | 584 | ||
573 | for (i=0; i<2000000; i++) { | 585 | for (i=0; i<2000000; i++) { |
574 | if (((INREG(RBBM_STATUS) & GUI_ACTIVE)) == 0) { | 586 | if (((INREG(RBBM_STATUS) & GUI_ACTIVE)) == 0) { |
@@ -581,8 +593,6 @@ static inline void _radeon_engine_idle(struct radeonfb_info *rinfo) | |||
581 | } | 593 | } |
582 | 594 | ||
583 | 595 | ||
584 | #define radeon_engine_idle() _radeon_engine_idle(rinfo) | ||
585 | #define radeon_fifo_wait(entries) _radeon_fifo_wait(rinfo,entries) | ||
586 | #define radeon_msleep(ms) _radeon_msleep(rinfo,ms) | 596 | #define radeon_msleep(ms) _radeon_msleep(rinfo,ms) |
587 | 597 | ||
588 | 598 | ||
@@ -612,6 +622,7 @@ extern void radeonfb_imageblit(struct fb_info *p, const struct fb_image *image); | |||
612 | extern int radeonfb_sync(struct fb_info *info); | 622 | extern int radeonfb_sync(struct fb_info *info); |
613 | extern void radeonfb_engine_init (struct radeonfb_info *rinfo); | 623 | extern void radeonfb_engine_init (struct radeonfb_info *rinfo); |
614 | extern void radeonfb_engine_reset(struct radeonfb_info *rinfo); | 624 | extern void radeonfb_engine_reset(struct radeonfb_info *rinfo); |
625 | extern void radeon_fixup_mem_offset(struct radeonfb_info *rinfo); | ||
615 | 626 | ||
616 | /* Other functions */ | 627 | /* Other functions */ |
617 | extern int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch); | 628 | extern int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch); |
diff --git a/drivers/video/carminefb.c b/drivers/video/carminefb.c index e15bb447440a..c9b191319a9a 100644 --- a/drivers/video/carminefb.c +++ b/drivers/video/carminefb.c | |||
@@ -535,7 +535,7 @@ static struct fb_ops carminefb_ops = { | |||
535 | .fb_setcolreg = carmine_setcolreg, | 535 | .fb_setcolreg = carmine_setcolreg, |
536 | }; | 536 | }; |
537 | 537 | ||
538 | static int alloc_carmine_fb(void __iomem *regs, void __iomem *smem_base, | 538 | static int __devinit alloc_carmine_fb(void __iomem *regs, void __iomem *smem_base, |
539 | int smem_offset, struct device *device, struct fb_info **rinfo) | 539 | int smem_offset, struct device *device, struct fb_info **rinfo) |
540 | { | 540 | { |
541 | int ret; | 541 | int ret; |
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index e729fb279645..048b139f0e50 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c | |||
@@ -327,29 +327,7 @@ static const struct { | |||
327 | #endif /* CONFIG_ZORRO */ | 327 | #endif /* CONFIG_ZORRO */ |
328 | 328 | ||
329 | struct cirrusfb_regs { | 329 | struct cirrusfb_regs { |
330 | long freq; | 330 | int multiplexing; |
331 | long nom; | ||
332 | long den; | ||
333 | long div; | ||
334 | long multiplexing; | ||
335 | long mclk; | ||
336 | long divMCLK; | ||
337 | |||
338 | long HorizRes; /* The x resolution in pixel */ | ||
339 | long HorizTotal; | ||
340 | long HorizDispEnd; | ||
341 | long HorizBlankStart; | ||
342 | long HorizBlankEnd; | ||
343 | long HorizSyncStart; | ||
344 | long HorizSyncEnd; | ||
345 | |||
346 | long VertRes; /* the physical y resolution in scanlines */ | ||
347 | long VertTotal; | ||
348 | long VertDispEnd; | ||
349 | long VertSyncStart; | ||
350 | long VertSyncEnd; | ||
351 | long VertBlankStart; | ||
352 | long VertBlankEnd; | ||
353 | }; | 331 | }; |
354 | 332 | ||
355 | #ifdef CIRRUSFB_DEBUG | 333 | #ifdef CIRRUSFB_DEBUG |
@@ -367,110 +345,13 @@ struct cirrusfb_info { | |||
367 | 345 | ||
368 | struct cirrusfb_regs currentmode; | 346 | struct cirrusfb_regs currentmode; |
369 | int blank_mode; | 347 | int blank_mode; |
348 | u32 pseudo_palette[16]; | ||
370 | 349 | ||
371 | u32 pseudo_palette[16]; | ||
372 | |||
373 | #ifdef CONFIG_ZORRO | ||
374 | struct zorro_dev *zdev; | ||
375 | #endif | ||
376 | #ifdef CONFIG_PCI | ||
377 | struct pci_dev *pdev; | ||
378 | #endif | ||
379 | void (*unmap)(struct fb_info *info); | 350 | void (*unmap)(struct fb_info *info); |
380 | }; | 351 | }; |
381 | 352 | ||
382 | static unsigned cirrusfb_def_mode = 1; | 353 | static int noaccel __devinitdata; |
383 | static int noaccel; | 354 | static char *mode_option __devinitdata = "640x480@60"; |
384 | |||
385 | /* | ||
386 | * Predefined Video Modes | ||
387 | */ | ||
388 | |||
389 | static const struct { | ||
390 | const char *name; | ||
391 | struct fb_var_screeninfo var; | ||
392 | } cirrusfb_predefined[] = { | ||
393 | { | ||
394 | /* autodetect mode */ | ||
395 | .name = "Autodetect", | ||
396 | }, { | ||
397 | /* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */ | ||
398 | .name = "640x480", | ||
399 | .var = { | ||
400 | .xres = 640, | ||
401 | .yres = 480, | ||
402 | .xres_virtual = 640, | ||
403 | .yres_virtual = 480, | ||
404 | .bits_per_pixel = 8, | ||
405 | .red = { .length = 8 }, | ||
406 | .green = { .length = 8 }, | ||
407 | .blue = { .length = 8 }, | ||
408 | .width = -1, | ||
409 | .height = -1, | ||
410 | .pixclock = 40000, | ||
411 | .left_margin = 48, | ||
412 | .right_margin = 16, | ||
413 | .upper_margin = 32, | ||
414 | .lower_margin = 8, | ||
415 | .hsync_len = 96, | ||
416 | .vsync_len = 4, | ||
417 | .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
418 | .vmode = FB_VMODE_NONINTERLACED | ||
419 | } | ||
420 | }, { | ||
421 | /* 800x600, 48 kHz, 76 Hz, 50 MHz PixClock */ | ||
422 | .name = "800x600", | ||
423 | .var = { | ||
424 | .xres = 800, | ||
425 | .yres = 600, | ||
426 | .xres_virtual = 800, | ||
427 | .yres_virtual = 600, | ||
428 | .bits_per_pixel = 8, | ||
429 | .red = { .length = 8 }, | ||
430 | .green = { .length = 8 }, | ||
431 | .blue = { .length = 8 }, | ||
432 | .width = -1, | ||
433 | .height = -1, | ||
434 | .pixclock = 20000, | ||
435 | .left_margin = 128, | ||
436 | .right_margin = 16, | ||
437 | .upper_margin = 24, | ||
438 | .lower_margin = 2, | ||
439 | .hsync_len = 96, | ||
440 | .vsync_len = 6, | ||
441 | .vmode = FB_VMODE_NONINTERLACED | ||
442 | } | ||
443 | }, { | ||
444 | /* | ||
445 | * Modeline from XF86Config: | ||
446 | * Mode "1024x768" 80 1024 1136 1340 1432 768 770 774 805 | ||
447 | */ | ||
448 | /* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */ | ||
449 | .name = "1024x768", | ||
450 | .var = { | ||
451 | .xres = 1024, | ||
452 | .yres = 768, | ||
453 | .xres_virtual = 1024, | ||
454 | .yres_virtual = 768, | ||
455 | .bits_per_pixel = 8, | ||
456 | .red = { .length = 8 }, | ||
457 | .green = { .length = 8 }, | ||
458 | .blue = { .length = 8 }, | ||
459 | .width = -1, | ||
460 | .height = -1, | ||
461 | .pixclock = 12500, | ||
462 | .left_margin = 144, | ||
463 | .right_margin = 32, | ||
464 | .upper_margin = 30, | ||
465 | .lower_margin = 2, | ||
466 | .hsync_len = 192, | ||
467 | .vsync_len = 6, | ||
468 | .vmode = FB_VMODE_NONINTERLACED | ||
469 | } | ||
470 | } | ||
471 | }; | ||
472 | |||
473 | #define NUM_TOTAL_MODES ARRAY_SIZE(cirrusfb_predefined) | ||
474 | 355 | ||
475 | /****************************************************************************/ | 356 | /****************************************************************************/ |
476 | /**** BEGIN PROTOTYPES ******************************************************/ | 357 | /**** BEGIN PROTOTYPES ******************************************************/ |
@@ -514,10 +395,6 @@ static struct fb_ops cirrusfb_ops = { | |||
514 | .fb_imageblit = cirrusfb_imageblit, | 395 | .fb_imageblit = cirrusfb_imageblit, |
515 | }; | 396 | }; |
516 | 397 | ||
517 | /*--- Hardware Specific Routines -------------------------------------------*/ | ||
518 | static int cirrusfb_decode_var(const struct fb_var_screeninfo *var, | ||
519 | struct cirrusfb_regs *regs, | ||
520 | struct fb_info *info); | ||
521 | /*--- Internal routines ----------------------------------------------------*/ | 398 | /*--- Internal routines ----------------------------------------------------*/ |
522 | static void init_vgachip(struct fb_info *info); | 399 | static void init_vgachip(struct fb_info *info); |
523 | static void switch_monitor(struct cirrusfb_info *cinfo, int on); | 400 | static void switch_monitor(struct cirrusfb_info *cinfo, int on); |
@@ -546,9 +423,7 @@ static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel, | |||
546 | u_short width, u_short height, | 423 | u_short width, u_short height, |
547 | u_char color, u_short line_length); | 424 | u_char color, u_short line_length); |
548 | 425 | ||
549 | static void bestclock(long freq, long *best, | 426 | static void bestclock(long freq, int *nom, int *den, int *div); |
550 | long *nom, long *den, | ||
551 | long *div, long maxfreq); | ||
552 | 427 | ||
553 | #ifdef CIRRUSFB_DEBUG | 428 | #ifdef CIRRUSFB_DEBUG |
554 | static void cirrusfb_dump(void); | 429 | static void cirrusfb_dump(void); |
@@ -584,45 +459,28 @@ static int cirrusfb_release(struct fb_info *info, int user) | |||
584 | /****************************************************************************/ | 459 | /****************************************************************************/ |
585 | /**** BEGIN Hardware specific Routines **************************************/ | 460 | /**** BEGIN Hardware specific Routines **************************************/ |
586 | 461 | ||
587 | /* Get a good MCLK value */ | 462 | /* Check if the MCLK is not a better clock source */ |
588 | static long cirrusfb_get_mclk(long freq, int bpp, long *div) | 463 | static int cirrusfb_check_mclk(struct cirrusfb_info *cinfo, long freq) |
589 | { | 464 | { |
590 | long mclk; | 465 | long mclk = vga_rseq(cinfo->regbase, CL_SEQR1F) & 0x3f; |
591 | 466 | ||
592 | assert(div != NULL); | 467 | /* Read MCLK value */ |
593 | 468 | mclk = (14318 * mclk) >> 3; | |
594 | /* Calculate MCLK, in case VCLK is high enough to require > 50MHz. | 469 | DPRINTK("Read MCLK of %ld kHz\n", mclk); |
595 | * Assume a 64-bit data path for now. The formula is: | ||
596 | * ((B * PCLK * 2)/W) * 1.2 | ||
597 | * B = bytes per pixel, PCLK = pixclock, W = data width in bytes */ | ||
598 | mclk = ((bpp / 8) * freq * 2) / 4; | ||
599 | mclk = (mclk * 12) / 10; | ||
600 | if (mclk < 50000) | ||
601 | mclk = 50000; | ||
602 | DPRINTK("Use MCLK of %ld kHz\n", mclk); | ||
603 | |||
604 | /* Calculate value for SR1F. Multiply by 2 so we can round up. */ | ||
605 | mclk = ((mclk * 16) / 14318); | ||
606 | mclk = (mclk + 1) / 2; | ||
607 | DPRINTK("Set SR1F[5:0] to 0x%lx\n", mclk); | ||
608 | 470 | ||
609 | /* Determine if we should use MCLK instead of VCLK, and if so, what we | 471 | /* Determine if we should use MCLK instead of VCLK, and if so, what we |
610 | * should divide it by to get VCLK */ | 472 | * should divide it by to get VCLK |
611 | switch (freq) { | 473 | */ |
612 | case 24751 ... 25249: | 474 | |
613 | *div = 2; | 475 | if (abs(freq - mclk) < 250) { |
614 | DPRINTK("Using VCLK = MCLK/2\n"); | ||
615 | break; | ||
616 | case 49501 ... 50499: | ||
617 | *div = 1; | ||
618 | DPRINTK("Using VCLK = MCLK\n"); | 476 | DPRINTK("Using VCLK = MCLK\n"); |
619 | break; | 477 | return 1; |
620 | default: | 478 | } else if (abs(freq - (mclk / 2)) < 250) { |
621 | *div = 0; | 479 | DPRINTK("Using VCLK = MCLK/2\n"); |
622 | break; | 480 | return 2; |
623 | } | 481 | } |
624 | 482 | ||
625 | return mclk; | 483 | return 0; |
626 | } | 484 | } |
627 | 485 | ||
628 | static int cirrusfb_check_var(struct fb_var_screeninfo *var, | 486 | static int cirrusfb_check_var(struct fb_var_screeninfo *var, |
@@ -638,7 +496,6 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var, | |||
638 | break; /* 8 pixel per byte, only 1/4th of mem usable */ | 496 | break; /* 8 pixel per byte, only 1/4th of mem usable */ |
639 | case 8: | 497 | case 8: |
640 | case 16: | 498 | case 16: |
641 | case 24: | ||
642 | case 32: | 499 | case 32: |
643 | break; /* 1 pixel == 1 byte */ | 500 | break; /* 1 pixel == 1 byte */ |
644 | default: | 501 | default: |
@@ -713,7 +570,6 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var, | |||
713 | var->blue.length = 5; | 570 | var->blue.length = 5; |
714 | break; | 571 | break; |
715 | 572 | ||
716 | case 24: | ||
717 | case 32: | 573 | case 32: |
718 | if (isPReP) { | 574 | if (isPReP) { |
719 | var->red.offset = 8; | 575 | var->red.offset = 8; |
@@ -767,8 +623,6 @@ static int cirrusfb_decode_var(const struct fb_var_screeninfo *var, | |||
767 | long maxclock; | 623 | long maxclock; |
768 | int maxclockidx = var->bits_per_pixel >> 3; | 624 | int maxclockidx = var->bits_per_pixel >> 3; |
769 | struct cirrusfb_info *cinfo = info->par; | 625 | struct cirrusfb_info *cinfo = info->par; |
770 | int xres, hfront, hsync, hback; | ||
771 | int yres, vfront, vsync, vback; | ||
772 | 626 | ||
773 | switch (var->bits_per_pixel) { | 627 | switch (var->bits_per_pixel) { |
774 | case 1: | 628 | case 1: |
@@ -782,10 +636,9 @@ static int cirrusfb_decode_var(const struct fb_var_screeninfo *var, | |||
782 | break; | 636 | break; |
783 | 637 | ||
784 | case 16: | 638 | case 16: |
785 | case 24: | ||
786 | case 32: | 639 | case 32: |
787 | info->fix.line_length = var->xres_virtual * maxclockidx; | 640 | info->fix.line_length = var->xres_virtual * maxclockidx; |
788 | info->fix.visual = FB_VISUAL_DIRECTCOLOR; | 641 | info->fix.visual = FB_VISUAL_TRUECOLOR; |
789 | break; | 642 | break; |
790 | 643 | ||
791 | default: | 644 | default: |
@@ -827,90 +680,33 @@ static int cirrusfb_decode_var(const struct fb_var_screeninfo *var, | |||
827 | switch (var->bits_per_pixel) { | 680 | switch (var->bits_per_pixel) { |
828 | case 16: | 681 | case 16: |
829 | case 32: | 682 | case 32: |
830 | if (regs->HorizRes <= 800) | 683 | if (var->xres <= 800) |
831 | /* Xbh has this type of clock for 32-bit */ | 684 | /* Xbh has this type of clock for 32-bit */ |
832 | freq /= 2; | 685 | freq /= 2; |
833 | break; | 686 | break; |
834 | } | 687 | } |
835 | #endif | 688 | #endif |
836 | |||
837 | bestclock(freq, ®s->freq, ®s->nom, ®s->den, ®s->div, | ||
838 | maxclock); | ||
839 | regs->mclk = cirrusfb_get_mclk(freq, var->bits_per_pixel, | ||
840 | ®s->divMCLK); | ||
841 | |||
842 | xres = var->xres; | ||
843 | hfront = var->right_margin; | ||
844 | hsync = var->hsync_len; | ||
845 | hback = var->left_margin; | ||
846 | |||
847 | yres = var->yres; | ||
848 | vfront = var->lower_margin; | ||
849 | vsync = var->vsync_len; | ||
850 | vback = var->upper_margin; | ||
851 | |||
852 | if (var->vmode & FB_VMODE_DOUBLE) { | ||
853 | yres *= 2; | ||
854 | vfront *= 2; | ||
855 | vsync *= 2; | ||
856 | vback *= 2; | ||
857 | } else if (var->vmode & FB_VMODE_INTERLACED) { | ||
858 | yres = (yres + 1) / 2; | ||
859 | vfront = (vfront + 1) / 2; | ||
860 | vsync = (vsync + 1) / 2; | ||
861 | vback = (vback + 1) / 2; | ||
862 | } | ||
863 | regs->HorizRes = xres; | ||
864 | regs->HorizTotal = (xres + hfront + hsync + hback) / 8 - 5; | ||
865 | regs->HorizDispEnd = xres / 8 - 1; | ||
866 | regs->HorizBlankStart = xres / 8; | ||
867 | /* does not count with "-5" */ | ||
868 | regs->HorizBlankEnd = regs->HorizTotal + 5; | ||
869 | regs->HorizSyncStart = (xres + hfront) / 8 + 1; | ||
870 | regs->HorizSyncEnd = (xres + hfront + hsync) / 8 + 1; | ||
871 | |||
872 | regs->VertRes = yres; | ||
873 | regs->VertTotal = yres + vfront + vsync + vback - 2; | ||
874 | regs->VertDispEnd = yres - 1; | ||
875 | regs->VertBlankStart = yres; | ||
876 | regs->VertBlankEnd = regs->VertTotal; | ||
877 | regs->VertSyncStart = yres + vfront - 1; | ||
878 | regs->VertSyncEnd = yres + vfront + vsync - 1; | ||
879 | |||
880 | if (regs->VertRes >= 1024) { | ||
881 | regs->VertTotal /= 2; | ||
882 | regs->VertSyncStart /= 2; | ||
883 | regs->VertSyncEnd /= 2; | ||
884 | regs->VertDispEnd /= 2; | ||
885 | } | ||
886 | if (regs->multiplexing) { | ||
887 | regs->HorizTotal /= 2; | ||
888 | regs->HorizSyncStart /= 2; | ||
889 | regs->HorizSyncEnd /= 2; | ||
890 | regs->HorizDispEnd /= 2; | ||
891 | } | ||
892 | |||
893 | return 0; | 689 | return 0; |
894 | } | 690 | } |
895 | 691 | ||
896 | static void cirrusfb_set_mclk(const struct cirrusfb_info *cinfo, int val, | 692 | static void cirrusfb_set_mclk_as_source(const struct cirrusfb_info *cinfo, |
897 | int div) | 693 | int div) |
898 | { | 694 | { |
695 | unsigned char old1f, old1e; | ||
899 | assert(cinfo != NULL); | 696 | assert(cinfo != NULL); |
697 | old1f = vga_rseq(cinfo->regbase, CL_SEQR1F) & ~0x40; | ||
900 | 698 | ||
901 | if (div == 2) { | 699 | if (div) { |
902 | /* VCLK = MCLK/2 */ | 700 | DPRINTK("Set %s as pixclock source.\n", |
903 | unsigned char old = vga_rseq(cinfo->regbase, CL_SEQR1E); | 701 | (div == 2) ? "MCLK/2" : "MCLK"); |
904 | vga_wseq(cinfo->regbase, CL_SEQR1E, old | 0x1); | 702 | old1f |= 0x40; |
905 | vga_wseq(cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f)); | 703 | old1e = vga_rseq(cinfo->regbase, CL_SEQR1E) & ~0x1; |
906 | } else if (div == 1) { | 704 | if (div == 2) |
907 | /* VCLK = MCLK */ | 705 | old1e |= 1; |
908 | unsigned char old = vga_rseq(cinfo->regbase, CL_SEQR1E); | 706 | |
909 | vga_wseq(cinfo->regbase, CL_SEQR1E, old & ~0x1); | 707 | vga_wseq(cinfo->regbase, CL_SEQR1E, old1e); |
910 | vga_wseq(cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f)); | ||
911 | } else { | ||
912 | vga_wseq(cinfo->regbase, CL_SEQR1F, val & 0x3f); | ||
913 | } | 708 | } |
709 | vga_wseq(cinfo->regbase, CL_SEQR1F, old1f); | ||
914 | } | 710 | } |
915 | 711 | ||
916 | /************************************************************************* | 712 | /************************************************************************* |
@@ -927,6 +723,10 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
927 | unsigned char tmp; | 723 | unsigned char tmp; |
928 | int offset = 0, err; | 724 | int offset = 0, err; |
929 | const struct cirrusfb_board_info_rec *bi; | 725 | const struct cirrusfb_board_info_rec *bi; |
726 | int hdispend, hsyncstart, hsyncend, htotal; | ||
727 | int yres, vdispend, vsyncstart, vsyncend, vtotal; | ||
728 | long freq; | ||
729 | int nom, den, div; | ||
930 | 730 | ||
931 | DPRINTK("ENTER\n"); | 731 | DPRINTK("ENTER\n"); |
932 | DPRINTK("Requested mode: %dx%dx%d\n", | 732 | DPRINTK("Requested mode: %dx%dx%d\n", |
@@ -944,76 +744,117 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
944 | 744 | ||
945 | bi = &cirrusfb_board_info[cinfo->btype]; | 745 | bi = &cirrusfb_board_info[cinfo->btype]; |
946 | 746 | ||
747 | hsyncstart = var->xres + var->right_margin; | ||
748 | hsyncend = hsyncstart + var->hsync_len; | ||
749 | htotal = (hsyncend + var->left_margin) / 8 - 5; | ||
750 | hdispend = var->xres / 8 - 1; | ||
751 | hsyncstart = hsyncstart / 8 + 1; | ||
752 | hsyncend = hsyncend / 8 + 1; | ||
753 | |||
754 | yres = var->yres; | ||
755 | vsyncstart = yres + var->lower_margin; | ||
756 | vsyncend = vsyncstart + var->vsync_len; | ||
757 | vtotal = vsyncend + var->upper_margin; | ||
758 | vdispend = yres - 1; | ||
759 | |||
760 | if (var->vmode & FB_VMODE_DOUBLE) { | ||
761 | yres *= 2; | ||
762 | vsyncstart *= 2; | ||
763 | vsyncend *= 2; | ||
764 | vtotal *= 2; | ||
765 | } else if (var->vmode & FB_VMODE_INTERLACED) { | ||
766 | yres = (yres + 1) / 2; | ||
767 | vsyncstart = (vsyncstart + 1) / 2; | ||
768 | vsyncend = (vsyncend + 1) / 2; | ||
769 | vtotal = (vtotal + 1) / 2; | ||
770 | } | ||
771 | |||
772 | vtotal -= 2; | ||
773 | vsyncstart -= 1; | ||
774 | vsyncend -= 1; | ||
775 | |||
776 | if (yres >= 1024) { | ||
777 | vtotal /= 2; | ||
778 | vsyncstart /= 2; | ||
779 | vsyncend /= 2; | ||
780 | vdispend /= 2; | ||
781 | } | ||
782 | if (regs.multiplexing) { | ||
783 | htotal /= 2; | ||
784 | hsyncstart /= 2; | ||
785 | hsyncend /= 2; | ||
786 | hdispend /= 2; | ||
787 | } | ||
947 | /* unlock register VGA_CRTC_H_TOTAL..CRT7 */ | 788 | /* unlock register VGA_CRTC_H_TOTAL..CRT7 */ |
948 | vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */ | 789 | vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */ |
949 | 790 | ||
950 | /* if debugging is enabled, all parameters get output before writing */ | 791 | /* if debugging is enabled, all parameters get output before writing */ |
951 | DPRINTK("CRT0: %ld\n", regs.HorizTotal); | 792 | DPRINTK("CRT0: %d\n", htotal); |
952 | vga_wcrt(regbase, VGA_CRTC_H_TOTAL, regs.HorizTotal); | 793 | vga_wcrt(regbase, VGA_CRTC_H_TOTAL, htotal); |
953 | 794 | ||
954 | DPRINTK("CRT1: %ld\n", regs.HorizDispEnd); | 795 | DPRINTK("CRT1: %d\n", hdispend); |
955 | vga_wcrt(regbase, VGA_CRTC_H_DISP, regs.HorizDispEnd); | 796 | vga_wcrt(regbase, VGA_CRTC_H_DISP, hdispend); |
956 | 797 | ||
957 | DPRINTK("CRT2: %ld\n", regs.HorizBlankStart); | 798 | DPRINTK("CRT2: %d\n", var->xres / 8); |
958 | vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, regs.HorizBlankStart); | 799 | vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, var->xres / 8); |
959 | 800 | ||
960 | /* + 128: Compatible read */ | 801 | /* + 128: Compatible read */ |
961 | DPRINTK("CRT3: 128+%ld\n", regs.HorizBlankEnd % 32); | 802 | DPRINTK("CRT3: 128+%d\n", (htotal + 5) % 32); |
962 | vga_wcrt(regbase, VGA_CRTC_H_BLANK_END, | 803 | vga_wcrt(regbase, VGA_CRTC_H_BLANK_END, |
963 | 128 + (regs.HorizBlankEnd % 32)); | 804 | 128 + ((htotal + 5) % 32)); |
964 | 805 | ||
965 | DPRINTK("CRT4: %ld\n", regs.HorizSyncStart); | 806 | DPRINTK("CRT4: %d\n", hsyncstart); |
966 | vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, regs.HorizSyncStart); | 807 | vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, hsyncstart); |
967 | 808 | ||
968 | tmp = regs.HorizSyncEnd % 32; | 809 | tmp = hsyncend % 32; |
969 | if (regs.HorizBlankEnd & 32) | 810 | if ((htotal + 5) & 32) |
970 | tmp += 128; | 811 | tmp += 128; |
971 | DPRINTK("CRT5: %d\n", tmp); | 812 | DPRINTK("CRT5: %d\n", tmp); |
972 | vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp); | 813 | vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp); |
973 | 814 | ||
974 | DPRINTK("CRT6: %ld\n", regs.VertTotal & 0xff); | 815 | DPRINTK("CRT6: %d\n", vtotal & 0xff); |
975 | vga_wcrt(regbase, VGA_CRTC_V_TOTAL, (regs.VertTotal & 0xff)); | 816 | vga_wcrt(regbase, VGA_CRTC_V_TOTAL, vtotal & 0xff); |
976 | 817 | ||
977 | tmp = 16; /* LineCompare bit #9 */ | 818 | tmp = 16; /* LineCompare bit #9 */ |
978 | if (regs.VertTotal & 256) | 819 | if (vtotal & 256) |
979 | tmp |= 1; | 820 | tmp |= 1; |
980 | if (regs.VertDispEnd & 256) | 821 | if (vdispend & 256) |
981 | tmp |= 2; | 822 | tmp |= 2; |
982 | if (regs.VertSyncStart & 256) | 823 | if (vsyncstart & 256) |
983 | tmp |= 4; | 824 | tmp |= 4; |
984 | if (regs.VertBlankStart & 256) | 825 | if ((vdispend + 1) & 256) |
985 | tmp |= 8; | 826 | tmp |= 8; |
986 | if (regs.VertTotal & 512) | 827 | if (vtotal & 512) |
987 | tmp |= 32; | 828 | tmp |= 32; |
988 | if (regs.VertDispEnd & 512) | 829 | if (vdispend & 512) |
989 | tmp |= 64; | 830 | tmp |= 64; |
990 | if (regs.VertSyncStart & 512) | 831 | if (vsyncstart & 512) |
991 | tmp |= 128; | 832 | tmp |= 128; |
992 | DPRINTK("CRT7: %d\n", tmp); | 833 | DPRINTK("CRT7: %d\n", tmp); |
993 | vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp); | 834 | vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp); |
994 | 835 | ||
995 | tmp = 0x40; /* LineCompare bit #8 */ | 836 | tmp = 0x40; /* LineCompare bit #8 */ |
996 | if (regs.VertBlankStart & 512) | 837 | if ((vdispend + 1) & 512) |
997 | tmp |= 0x20; | 838 | tmp |= 0x20; |
998 | if (var->vmode & FB_VMODE_DOUBLE) | 839 | if (var->vmode & FB_VMODE_DOUBLE) |
999 | tmp |= 0x80; | 840 | tmp |= 0x80; |
1000 | DPRINTK("CRT9: %d\n", tmp); | 841 | DPRINTK("CRT9: %d\n", tmp); |
1001 | vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp); | 842 | vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp); |
1002 | 843 | ||
1003 | DPRINTK("CRT10: %ld\n", regs.VertSyncStart & 0xff); | 844 | DPRINTK("CRT10: %d\n", vsyncstart & 0xff); |
1004 | vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, regs.VertSyncStart & 0xff); | 845 | vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, vsyncstart & 0xff); |
1005 | 846 | ||
1006 | DPRINTK("CRT11: 64+32+%ld\n", regs.VertSyncEnd % 16); | 847 | DPRINTK("CRT11: 64+32+%d\n", vsyncend % 16); |
1007 | vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, regs.VertSyncEnd % 16 + 64 + 32); | 848 | vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, vsyncend % 16 + 64 + 32); |
1008 | 849 | ||
1009 | DPRINTK("CRT12: %ld\n", regs.VertDispEnd & 0xff); | 850 | DPRINTK("CRT12: %d\n", vdispend & 0xff); |
1010 | vga_wcrt(regbase, VGA_CRTC_V_DISP_END, regs.VertDispEnd & 0xff); | 851 | vga_wcrt(regbase, VGA_CRTC_V_DISP_END, vdispend & 0xff); |
1011 | 852 | ||
1012 | DPRINTK("CRT15: %ld\n", regs.VertBlankStart & 0xff); | 853 | DPRINTK("CRT15: %d\n", (vdispend + 1) & 0xff); |
1013 | vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, regs.VertBlankStart & 0xff); | 854 | vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, (vdispend + 1) & 0xff); |
1014 | 855 | ||
1015 | DPRINTK("CRT16: %ld\n", regs.VertBlankEnd & 0xff); | 856 | DPRINTK("CRT16: %d\n", vtotal & 0xff); |
1016 | vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, regs.VertBlankEnd & 0xff); | 857 | vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, vtotal & 0xff); |
1017 | 858 | ||
1018 | DPRINTK("CRT18: 0xff\n"); | 859 | DPRINTK("CRT18: 0xff\n"); |
1019 | vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff); | 860 | vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff); |
@@ -1021,38 +862,53 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
1021 | tmp = 0; | 862 | tmp = 0; |
1022 | if (var->vmode & FB_VMODE_INTERLACED) | 863 | if (var->vmode & FB_VMODE_INTERLACED) |
1023 | tmp |= 1; | 864 | tmp |= 1; |
1024 | if (regs.HorizBlankEnd & 64) | 865 | if ((htotal + 5) & 64) |
1025 | tmp |= 16; | 866 | tmp |= 16; |
1026 | if (regs.HorizBlankEnd & 128) | 867 | if ((htotal + 5) & 128) |
1027 | tmp |= 32; | 868 | tmp |= 32; |
1028 | if (regs.VertBlankEnd & 256) | 869 | if (vtotal & 256) |
1029 | tmp |= 64; | 870 | tmp |= 64; |
1030 | if (regs.VertBlankEnd & 512) | 871 | if (vtotal & 512) |
1031 | tmp |= 128; | 872 | tmp |= 128; |
1032 | 873 | ||
1033 | DPRINTK("CRT1a: %d\n", tmp); | 874 | DPRINTK("CRT1a: %d\n", tmp); |
1034 | vga_wcrt(regbase, CL_CRT1A, tmp); | 875 | vga_wcrt(regbase, CL_CRT1A, tmp); |
1035 | 876 | ||
877 | freq = PICOS2KHZ(var->pixclock); | ||
878 | bestclock(freq, &nom, &den, &div); | ||
879 | |||
1036 | /* set VCLK0 */ | 880 | /* set VCLK0 */ |
1037 | /* hardware RefClock: 14.31818 MHz */ | 881 | /* hardware RefClock: 14.31818 MHz */ |
1038 | /* formula: VClk = (OSC * N) / (D * (1+P)) */ | 882 | /* formula: VClk = (OSC * N) / (D * (1+P)) */ |
1039 | /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */ | 883 | /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */ |
1040 | 884 | ||
1041 | vga_wseq(regbase, CL_SEQRB, regs.nom); | 885 | if (cinfo->btype == BT_ALPINE) { |
1042 | tmp = regs.den << 1; | 886 | /* if freq is close to mclk or mclk/2 select mclk |
1043 | if (regs.div != 0) | 887 | * as clock source |
1044 | tmp |= 1; | 888 | */ |
889 | int divMCLK = cirrusfb_check_mclk(cinfo, freq); | ||
890 | if (divMCLK) { | ||
891 | nom = 0; | ||
892 | cirrusfb_set_mclk_as_source(cinfo, divMCLK); | ||
893 | } | ||
894 | } | ||
895 | if (nom) { | ||
896 | vga_wseq(regbase, CL_SEQRB, nom); | ||
897 | tmp = den << 1; | ||
898 | if (div != 0) | ||
899 | tmp |= 1; | ||
1045 | 900 | ||
1046 | /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */ | 901 | /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */ |
1047 | if ((cinfo->btype == BT_SD64) || | 902 | if ((cinfo->btype == BT_SD64) || |
1048 | (cinfo->btype == BT_ALPINE) || | 903 | (cinfo->btype == BT_ALPINE) || |
1049 | (cinfo->btype == BT_GD5480)) | 904 | (cinfo->btype == BT_GD5480)) |
1050 | tmp |= 0x80; | 905 | tmp |= 0x80; |
1051 | 906 | ||
1052 | DPRINTK("CL_SEQR1B: %ld\n", (long) tmp); | 907 | DPRINTK("CL_SEQR1B: %ld\n", (long) tmp); |
1053 | vga_wseq(regbase, CL_SEQR1B, tmp); | 908 | vga_wseq(regbase, CL_SEQR1B, tmp); |
909 | } | ||
1054 | 910 | ||
1055 | if (regs.VertRes >= 1024) | 911 | if (yres >= 1024) |
1056 | /* 1280x1024 */ | 912 | /* 1280x1024 */ |
1057 | vga_wcrt(regbase, VGA_CRTC_MODE, 0xc7); | 913 | vga_wcrt(regbase, VGA_CRTC_MODE, 0xc7); |
1058 | else | 914 | else |
@@ -1066,7 +922,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
1066 | /* don't know if it would hurt to also program this if no interlaced */ | 922 | /* don't know if it would hurt to also program this if no interlaced */ |
1067 | /* mode is used, but I feel better this way.. :-) */ | 923 | /* mode is used, but I feel better this way.. :-) */ |
1068 | if (var->vmode & FB_VMODE_INTERLACED) | 924 | if (var->vmode & FB_VMODE_INTERLACED) |
1069 | vga_wcrt(regbase, VGA_CRTC_REGS, regs.HorizTotal / 2); | 925 | vga_wcrt(regbase, VGA_CRTC_REGS, htotal / 2); |
1070 | else | 926 | else |
1071 | vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */ | 927 | vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */ |
1072 | 928 | ||
@@ -1240,7 +1096,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
1240 | 1096 | ||
1241 | case BT_ALPINE: | 1097 | case BT_ALPINE: |
1242 | DPRINTK(" (for GD543x)\n"); | 1098 | DPRINTK(" (for GD543x)\n"); |
1243 | cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK); | ||
1244 | /* We already set SRF and SR1F */ | 1099 | /* We already set SRF and SR1F */ |
1245 | break; | 1100 | break; |
1246 | 1101 | ||
@@ -1312,11 +1167,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
1312 | 1167 | ||
1313 | case BT_ALPINE: | 1168 | case BT_ALPINE: |
1314 | DPRINTK(" (for GD543x)\n"); | 1169 | DPRINTK(" (for GD543x)\n"); |
1315 | if (regs.HorizRes >= 1024) | 1170 | vga_wseq(regbase, CL_SEQR7, 0xa7); |
1316 | vga_wseq(regbase, CL_SEQR7, 0xa7); | ||
1317 | else | ||
1318 | vga_wseq(regbase, CL_SEQR7, 0xa3); | ||
1319 | cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK); | ||
1320 | break; | 1171 | break; |
1321 | 1172 | ||
1322 | case BT_GD5480: | 1173 | case BT_GD5480: |
@@ -1360,7 +1211,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
1360 | */ | 1211 | */ |
1361 | 1212 | ||
1362 | else if (var->bits_per_pixel == 32) { | 1213 | else if (var->bits_per_pixel == 32) { |
1363 | DPRINTK("cirrusfb: preparing for 24/32 bit deep display\n"); | 1214 | DPRINTK("cirrusfb: preparing for 32 bit deep display\n"); |
1364 | switch (cinfo->btype) { | 1215 | switch (cinfo->btype) { |
1365 | case BT_SD64: | 1216 | case BT_SD64: |
1366 | /* Extended Sequencer Mode: 256c col. mode */ | 1217 | /* Extended Sequencer Mode: 256c col. mode */ |
@@ -1394,7 +1245,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
1394 | case BT_ALPINE: | 1245 | case BT_ALPINE: |
1395 | DPRINTK(" (for GD543x)\n"); | 1246 | DPRINTK(" (for GD543x)\n"); |
1396 | vga_wseq(regbase, CL_SEQR7, 0xa9); | 1247 | vga_wseq(regbase, CL_SEQR7, 0xa9); |
1397 | cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK); | ||
1398 | break; | 1248 | break; |
1399 | 1249 | ||
1400 | case BT_GD5480: | 1250 | case BT_GD5480: |
@@ -1949,8 +1799,6 @@ static void init_vgachip(struct fb_info *info) | |||
1949 | /* misc... */ | 1799 | /* misc... */ |
1950 | WHDR(cinfo, 0); /* Hidden DAC register: - */ | 1800 | WHDR(cinfo, 0); /* Hidden DAC register: - */ |
1951 | 1801 | ||
1952 | printk(KERN_DEBUG "cirrusfb: This board has %ld bytes of DRAM memory\n", | ||
1953 | info->screen_size); | ||
1954 | DPRINTK("EXIT\n"); | 1802 | DPRINTK("EXIT\n"); |
1955 | return; | 1803 | return; |
1956 | } | 1804 | } |
@@ -2122,7 +1970,7 @@ static int release_io_ports; | |||
2122 | * based on the DRAM bandwidth bit and DRAM bank switching bit. This | 1970 | * based on the DRAM bandwidth bit and DRAM bank switching bit. This |
2123 | * works with 1MB, 2MB and 4MB configurations (which the Motorola boards | 1971 | * works with 1MB, 2MB and 4MB configurations (which the Motorola boards |
2124 | * seem to have. */ | 1972 | * seem to have. */ |
2125 | static unsigned int cirrusfb_get_memsize(u8 __iomem *regbase) | 1973 | static unsigned int __devinit cirrusfb_get_memsize(u8 __iomem *regbase) |
2126 | { | 1974 | { |
2127 | unsigned long mem; | 1975 | unsigned long mem; |
2128 | unsigned char SRF; | 1976 | unsigned char SRF; |
@@ -2188,8 +2036,7 @@ static void get_pci_addrs(const struct pci_dev *pdev, | |||
2188 | 2036 | ||
2189 | static void cirrusfb_pci_unmap(struct fb_info *info) | 2037 | static void cirrusfb_pci_unmap(struct fb_info *info) |
2190 | { | 2038 | { |
2191 | struct cirrusfb_info *cinfo = info->par; | 2039 | struct pci_dev *pdev = to_pci_dev(info->device); |
2192 | struct pci_dev *pdev = cinfo->pdev; | ||
2193 | 2040 | ||
2194 | iounmap(info->screen_base); | 2041 | iounmap(info->screen_base); |
2195 | #if 0 /* if system didn't claim this region, we would... */ | 2042 | #if 0 /* if system didn't claim this region, we would... */ |
@@ -2205,20 +2052,22 @@ static void cirrusfb_pci_unmap(struct fb_info *info) | |||
2205 | static void __devexit cirrusfb_zorro_unmap(struct fb_info *info) | 2052 | static void __devexit cirrusfb_zorro_unmap(struct fb_info *info) |
2206 | { | 2053 | { |
2207 | struct cirrusfb_info *cinfo = info->par; | 2054 | struct cirrusfb_info *cinfo = info->par; |
2208 | zorro_release_device(cinfo->zdev); | 2055 | struct zorro_dev *zdev = to_zorro_dev(info->device); |
2056 | |||
2057 | zorro_release_device(zdev); | ||
2209 | 2058 | ||
2210 | if (cinfo->btype == BT_PICASSO4) { | 2059 | if (cinfo->btype == BT_PICASSO4) { |
2211 | cinfo->regbase -= 0x600000; | 2060 | cinfo->regbase -= 0x600000; |
2212 | iounmap((void *)cinfo->regbase); | 2061 | iounmap((void *)cinfo->regbase); |
2213 | iounmap(info->screen_base); | 2062 | iounmap(info->screen_base); |
2214 | } else { | 2063 | } else { |
2215 | if (zorro_resource_start(cinfo->zdev) > 0x01000000) | 2064 | if (zorro_resource_start(zdev) > 0x01000000) |
2216 | iounmap(info->screen_base); | 2065 | iounmap(info->screen_base); |
2217 | } | 2066 | } |
2218 | } | 2067 | } |
2219 | #endif /* CONFIG_ZORRO */ | 2068 | #endif /* CONFIG_ZORRO */ |
2220 | 2069 | ||
2221 | static int cirrusfb_set_fbinfo(struct fb_info *info) | 2070 | static int __devinit cirrusfb_set_fbinfo(struct fb_info *info) |
2222 | { | 2071 | { |
2223 | struct cirrusfb_info *cinfo = info->par; | 2072 | struct cirrusfb_info *cinfo = info->par; |
2224 | struct fb_var_screeninfo *var = &info->var; | 2073 | struct fb_var_screeninfo *var = &info->var; |
@@ -2235,7 +2084,7 @@ static int cirrusfb_set_fbinfo(struct fb_info *info) | |||
2235 | if (cinfo->btype == BT_GD5480) { | 2084 | if (cinfo->btype == BT_GD5480) { |
2236 | if (var->bits_per_pixel == 16) | 2085 | if (var->bits_per_pixel == 16) |
2237 | info->screen_base += 1 * MB_; | 2086 | info->screen_base += 1 * MB_; |
2238 | if (var->bits_per_pixel == 24 || var->bits_per_pixel == 32) | 2087 | if (var->bits_per_pixel == 32) |
2239 | info->screen_base += 2 * MB_; | 2088 | info->screen_base += 2 * MB_; |
2240 | } | 2089 | } |
2241 | 2090 | ||
@@ -2262,7 +2111,7 @@ static int cirrusfb_set_fbinfo(struct fb_info *info) | |||
2262 | return 0; | 2111 | return 0; |
2263 | } | 2112 | } |
2264 | 2113 | ||
2265 | static int cirrusfb_register(struct fb_info *info) | 2114 | static int __devinit cirrusfb_register(struct fb_info *info) |
2266 | { | 2115 | { |
2267 | struct cirrusfb_info *cinfo = info->par; | 2116 | struct cirrusfb_info *cinfo = info->par; |
2268 | int err; | 2117 | int err; |
@@ -2278,23 +2127,27 @@ static int cirrusfb_register(struct fb_info *info) | |||
2278 | /* sanity checks */ | 2127 | /* sanity checks */ |
2279 | assert(btype != BT_NONE); | 2128 | assert(btype != BT_NONE); |
2280 | 2129 | ||
2130 | /* set all the vital stuff */ | ||
2131 | cirrusfb_set_fbinfo(info); | ||
2132 | |||
2281 | DPRINTK("cirrusfb: (RAM start set to: 0x%p)\n", info->screen_base); | 2133 | DPRINTK("cirrusfb: (RAM start set to: 0x%p)\n", info->screen_base); |
2282 | 2134 | ||
2283 | /* Make pretend we've set the var so our structures are in a "good" */ | 2135 | err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8); |
2284 | /* state, even though we haven't written the mode to the hw yet... */ | 2136 | if (!err) { |
2285 | info->var = cirrusfb_predefined[cirrusfb_def_mode].var; | 2137 | DPRINTK("wrong initial video mode\n"); |
2138 | err = -EINVAL; | ||
2139 | goto err_dealloc_cmap; | ||
2140 | } | ||
2141 | |||
2286 | info->var.activate = FB_ACTIVATE_NOW; | 2142 | info->var.activate = FB_ACTIVATE_NOW; |
2287 | 2143 | ||
2288 | err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info); | 2144 | err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info); |
2289 | if (err < 0) { | 2145 | if (err < 0) { |
2290 | /* should never happen */ | 2146 | /* should never happen */ |
2291 | DPRINTK("choking on default var... umm, no good.\n"); | 2147 | DPRINTK("choking on default var... umm, no good.\n"); |
2292 | goto err_unmap_cirrusfb; | 2148 | goto err_dealloc_cmap; |
2293 | } | 2149 | } |
2294 | 2150 | ||
2295 | /* set all the vital stuff */ | ||
2296 | cirrusfb_set_fbinfo(info); | ||
2297 | |||
2298 | err = register_framebuffer(info); | 2151 | err = register_framebuffer(info); |
2299 | if (err < 0) { | 2152 | if (err < 0) { |
2300 | printk(KERN_ERR "cirrusfb: could not register " | 2153 | printk(KERN_ERR "cirrusfb: could not register " |
@@ -2307,7 +2160,6 @@ static int cirrusfb_register(struct fb_info *info) | |||
2307 | 2160 | ||
2308 | err_dealloc_cmap: | 2161 | err_dealloc_cmap: |
2309 | fb_dealloc_cmap(&info->cmap); | 2162 | fb_dealloc_cmap(&info->cmap); |
2310 | err_unmap_cirrusfb: | ||
2311 | cinfo->unmap(info); | 2163 | cinfo->unmap(info); |
2312 | framebuffer_release(info); | 2164 | framebuffer_release(info); |
2313 | return err; | 2165 | return err; |
@@ -2330,8 +2182,8 @@ static void __devexit cirrusfb_cleanup(struct fb_info *info) | |||
2330 | } | 2182 | } |
2331 | 2183 | ||
2332 | #ifdef CONFIG_PCI | 2184 | #ifdef CONFIG_PCI |
2333 | static int cirrusfb_pci_register(struct pci_dev *pdev, | 2185 | static int __devinit cirrusfb_pci_register(struct pci_dev *pdev, |
2334 | const struct pci_device_id *ent) | 2186 | const struct pci_device_id *ent) |
2335 | { | 2187 | { |
2336 | struct cirrusfb_info *cinfo; | 2188 | struct cirrusfb_info *cinfo; |
2337 | struct fb_info *info; | 2189 | struct fb_info *info; |
@@ -2353,7 +2205,6 @@ static int cirrusfb_pci_register(struct pci_dev *pdev, | |||
2353 | } | 2205 | } |
2354 | 2206 | ||
2355 | cinfo = info->par; | 2207 | cinfo = info->par; |
2356 | cinfo->pdev = pdev; | ||
2357 | cinfo->btype = btype = (enum cirrus_board) ent->driver_data; | 2208 | cinfo->btype = btype = (enum cirrus_board) ent->driver_data; |
2358 | 2209 | ||
2359 | DPRINTK(" Found PCI device, base address 0 is 0x%x, btype set to %d\n", | 2210 | DPRINTK(" Found PCI device, base address 0 is 0x%x, btype set to %d\n", |
@@ -2459,8 +2310,8 @@ static struct pci_driver cirrusfb_pci_driver = { | |||
2459 | #endif /* CONFIG_PCI */ | 2310 | #endif /* CONFIG_PCI */ |
2460 | 2311 | ||
2461 | #ifdef CONFIG_ZORRO | 2312 | #ifdef CONFIG_ZORRO |
2462 | static int cirrusfb_zorro_register(struct zorro_dev *z, | 2313 | static int __devinit cirrusfb_zorro_register(struct zorro_dev *z, |
2463 | const struct zorro_device_id *ent) | 2314 | const struct zorro_device_id *ent) |
2464 | { | 2315 | { |
2465 | struct cirrusfb_info *cinfo; | 2316 | struct cirrusfb_info *cinfo; |
2466 | struct fb_info *info; | 2317 | struct fb_info *info; |
@@ -2489,7 +2340,6 @@ static int cirrusfb_zorro_register(struct zorro_dev *z, | |||
2489 | assert(z); | 2340 | assert(z); |
2490 | assert(btype != BT_NONE); | 2341 | assert(btype != BT_NONE); |
2491 | 2342 | ||
2492 | cinfo->zdev = z; | ||
2493 | board_addr = zorro_resource_start(z); | 2343 | board_addr = zorro_resource_start(z); |
2494 | board_size = zorro_resource_len(z); | 2344 | board_size = zorro_resource_len(z); |
2495 | info->screen_size = size; | 2345 | info->screen_size = size; |
@@ -2621,17 +2471,17 @@ static int __init cirrusfb_setup(char *options) { | |||
2621 | return 0; | 2471 | return 0; |
2622 | 2472 | ||
2623 | while ((this_opt = strsep(&options, ",")) != NULL) { | 2473 | while ((this_opt = strsep(&options, ",")) != NULL) { |
2624 | if (!*this_opt) continue; | 2474 | if (!*this_opt) |
2475 | continue; | ||
2625 | 2476 | ||
2626 | DPRINTK("cirrusfb_setup: option '%s'\n", this_opt); | 2477 | DPRINTK("cirrusfb_setup: option '%s'\n", this_opt); |
2627 | 2478 | ||
2628 | for (i = 0; i < NUM_TOTAL_MODES; i++) { | ||
2629 | sprintf(s, "mode:%s", cirrusfb_predefined[i].name); | ||
2630 | if (strcmp(this_opt, s) == 0) | ||
2631 | cirrusfb_def_mode = i; | ||
2632 | } | ||
2633 | if (!strcmp(this_opt, "noaccel")) | 2479 | if (!strcmp(this_opt, "noaccel")) |
2634 | noaccel = 1; | 2480 | noaccel = 1; |
2481 | else if (!strncmp(this_opt, "mode:", 5)) | ||
2482 | mode_option = this_opt + 5; | ||
2483 | else | ||
2484 | mode_option = this_opt; | ||
2635 | } | 2485 | } |
2636 | return 0; | 2486 | return 0; |
2637 | } | 2487 | } |
@@ -2657,6 +2507,11 @@ static void __exit cirrusfb_exit(void) | |||
2657 | 2507 | ||
2658 | module_init(cirrusfb_init); | 2508 | module_init(cirrusfb_init); |
2659 | 2509 | ||
2510 | module_param(mode_option, charp, 0); | ||
2511 | MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'"); | ||
2512 | module_param(noaccel, bool, 0); | ||
2513 | MODULE_PARM_DESC(noaccel, "Disable acceleration"); | ||
2514 | |||
2660 | #ifdef MODULE | 2515 | #ifdef MODULE |
2661 | module_exit(cirrusfb_exit); | 2516 | module_exit(cirrusfb_exit); |
2662 | #endif | 2517 | #endif |
@@ -3050,16 +2905,14 @@ static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel, | |||
3050 | * bestclock() - determine closest possible clock lower(?) than the | 2905 | * bestclock() - determine closest possible clock lower(?) than the |
3051 | * desired pixel clock | 2906 | * desired pixel clock |
3052 | **************************************************************************/ | 2907 | **************************************************************************/ |
3053 | static void bestclock(long freq, long *best, long *nom, | 2908 | static void bestclock(long freq, int *nom, int *den, int *div) |
3054 | long *den, long *div, long maxfreq) | ||
3055 | { | 2909 | { |
3056 | long n, h, d, f; | 2910 | int n, d; |
2911 | long h, diff; | ||
3057 | 2912 | ||
3058 | assert(best != NULL); | ||
3059 | assert(nom != NULL); | 2913 | assert(nom != NULL); |
3060 | assert(den != NULL); | 2914 | assert(den != NULL); |
3061 | assert(div != NULL); | 2915 | assert(div != NULL); |
3062 | assert(maxfreq > 0); | ||
3063 | 2916 | ||
3064 | *nom = 0; | 2917 | *nom = 0; |
3065 | *den = 0; | 2918 | *den = 0; |
@@ -3070,51 +2923,47 @@ static void bestclock(long freq, long *best, long *nom, | |||
3070 | if (freq < 8000) | 2923 | if (freq < 8000) |
3071 | freq = 8000; | 2924 | freq = 8000; |
3072 | 2925 | ||
3073 | if (freq > maxfreq) | 2926 | diff = freq; |
3074 | freq = maxfreq; | ||
3075 | |||
3076 | *best = 0; | ||
3077 | f = freq * 10; | ||
3078 | 2927 | ||
3079 | for (n = 32; n < 128; n++) { | 2928 | for (n = 32; n < 128; n++) { |
3080 | d = (143181 * n) / f; | 2929 | int s = 0; |
2930 | |||
2931 | d = (14318 * n) / freq; | ||
3081 | if ((d >= 7) && (d <= 63)) { | 2932 | if ((d >= 7) && (d <= 63)) { |
3082 | if (d > 31) | 2933 | int temp = d; |
3083 | d = (d / 2) * 2; | 2934 | |
3084 | h = (14318 * n) / d; | 2935 | if (temp > 31) { |
3085 | if (abs(h - freq) < abs(*best - freq)) { | 2936 | s = 1; |
3086 | *best = h; | 2937 | temp >>= 1; |
2938 | } | ||
2939 | h = ((14318 * n) / temp) >> s; | ||
2940 | h = h > freq ? h - freq : freq - h; | ||
2941 | if (h < diff) { | ||
2942 | diff = h; | ||
3087 | *nom = n; | 2943 | *nom = n; |
3088 | if (d < 32) { | 2944 | *den = temp; |
3089 | *den = d; | 2945 | *div = s; |
3090 | *div = 0; | ||
3091 | } else { | ||
3092 | *den = d / 2; | ||
3093 | *div = 1; | ||
3094 | } | ||
3095 | } | 2946 | } |
3096 | } | 2947 | } |
3097 | d = DIV_ROUND_UP(143181 * n, f); | 2948 | d++; |
3098 | if ((d >= 7) && (d <= 63)) { | 2949 | if ((d >= 7) && (d <= 63)) { |
3099 | if (d > 31) | 2950 | if (d > 31) { |
3100 | d = (d / 2) * 2; | 2951 | s = 1; |
3101 | h = (14318 * n) / d; | 2952 | d >>= 1; |
3102 | if (abs(h - freq) < abs(*best - freq)) { | 2953 | } |
3103 | *best = h; | 2954 | h = ((14318 * n) / d) >> s; |
2955 | h = h > freq ? h - freq : freq - h; | ||
2956 | if (h < diff) { | ||
2957 | diff = h; | ||
3104 | *nom = n; | 2958 | *nom = n; |
3105 | if (d < 32) { | 2959 | *den = d; |
3106 | *den = d; | 2960 | *div = s; |
3107 | *div = 0; | ||
3108 | } else { | ||
3109 | *den = d / 2; | ||
3110 | *div = 1; | ||
3111 | } | ||
3112 | } | 2961 | } |
3113 | } | 2962 | } |
3114 | } | 2963 | } |
3115 | 2964 | ||
3116 | DPRINTK("Best possible values for given frequency:\n"); | 2965 | DPRINTK("Best possible values for given frequency:\n"); |
3117 | DPRINTK(" best: %ld kHz nom: %ld den: %ld div: %ld\n", | 2966 | DPRINTK(" freq: %ld kHz nom: %d den: %d div: %d\n", |
3118 | freq, *nom, *den, *div); | 2967 | freq, *nom, *den, *div); |
3119 | 2968 | ||
3120 | DPRINTK("EXIT\n"); | 2969 | DPRINTK("EXIT\n"); |
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 0e0ea4215a30..64b3d30027b8 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c | |||
@@ -2977,8 +2977,8 @@ static void fbcon_set_all_vcs(struct fb_info *info) | |||
2977 | p = &fb_display[vc->vc_num]; | 2977 | p = &fb_display[vc->vc_num]; |
2978 | set_blitting_type(vc, info); | 2978 | set_blitting_type(vc, info); |
2979 | var_to_display(p, &info->var, info); | 2979 | var_to_display(p, &info->var, info); |
2980 | cols = FBCON_SWAP(p->rotate, info->var.xres, info->var.yres); | 2980 | cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); |
2981 | rows = FBCON_SWAP(p->rotate, info->var.yres, info->var.xres); | 2981 | rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); |
2982 | cols /= vc->vc_font.width; | 2982 | cols /= vc->vc_font.width; |
2983 | rows /= vc->vc_font.height; | 2983 | rows /= vc->vc_font.height; |
2984 | vc_resize(vc, cols, rows); | 2984 | vc_resize(vc, cols, rows); |
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 6df29a62d720..448d209a0bf2 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c | |||
@@ -239,8 +239,7 @@ static void vgacon_restore_screen(struct vc_data *c) | |||
239 | 239 | ||
240 | static int vgacon_scrolldelta(struct vc_data *c, int lines) | 240 | static int vgacon_scrolldelta(struct vc_data *c, int lines) |
241 | { | 241 | { |
242 | int start, end, count, soff, diff; | 242 | int start, end, count, soff; |
243 | void *d, *s; | ||
244 | 243 | ||
245 | if (!lines) { | 244 | if (!lines) { |
246 | c->vc_visible_origin = c->vc_origin; | 245 | c->vc_visible_origin = c->vc_origin; |
@@ -287,29 +286,29 @@ static int vgacon_scrolldelta(struct vc_data *c, int lines) | |||
287 | if (count > c->vc_rows) | 286 | if (count > c->vc_rows) |
288 | count = c->vc_rows; | 287 | count = c->vc_rows; |
289 | 288 | ||
290 | diff = c->vc_rows - count; | 289 | if (count) { |
290 | int copysize; | ||
291 | 291 | ||
292 | d = (void *) c->vc_origin; | 292 | int diff = c->vc_rows - count; |
293 | s = (void *) c->vc_screenbuf; | 293 | void *d = (void *) c->vc_origin; |
294 | void *s = (void *) c->vc_screenbuf; | ||
294 | 295 | ||
295 | while (count--) { | 296 | count *= c->vc_size_row; |
296 | scr_memcpyw(d, vgacon_scrollback + soff, c->vc_size_row); | 297 | /* how much memory to end of buffer left? */ |
297 | d += c->vc_size_row; | 298 | copysize = min(count, vgacon_scrollback_size - soff); |
298 | soff += c->vc_size_row; | 299 | scr_memcpyw(d, vgacon_scrollback + soff, copysize); |
300 | d += copysize; | ||
301 | count -= copysize; | ||
299 | 302 | ||
300 | if (soff >= vgacon_scrollback_size) | 303 | if (count) { |
301 | soff = 0; | 304 | scr_memcpyw(d, vgacon_scrollback, count); |
302 | } | 305 | d += count; |
306 | } | ||
303 | 307 | ||
304 | if (diff == c->vc_rows) { | 308 | if (diff) |
309 | scr_memcpyw(d, s, diff * c->vc_size_row); | ||
310 | } else | ||
305 | vgacon_cursor(c, CM_MOVE); | 311 | vgacon_cursor(c, CM_MOVE); |
306 | } else { | ||
307 | while (diff--) { | ||
308 | scr_memcpyw(d, s, c->vc_size_row); | ||
309 | d += c->vc_size_row; | ||
310 | s += c->vc_size_row; | ||
311 | } | ||
312 | } | ||
313 | 312 | ||
314 | return 1; | 313 | return 1; |
315 | } | 314 | } |
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c index bd779ae44b1e..daf9b81878a4 100644 --- a/drivers/video/efifb.c +++ b/drivers/video/efifb.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/fb.h> | 12 | #include <linux/fb.h> |
13 | #include <linux/platform_device.h> | 13 | #include <linux/platform_device.h> |
14 | #include <linux/screen_info.h> | 14 | #include <linux/screen_info.h> |
15 | #include <linux/dmi.h> | ||
15 | 16 | ||
16 | #include <video/vga.h> | 17 | #include <video/vga.h> |
17 | 18 | ||
@@ -33,6 +34,105 @@ static struct fb_fix_screeninfo efifb_fix __initdata = { | |||
33 | .visual = FB_VISUAL_TRUECOLOR, | 34 | .visual = FB_VISUAL_TRUECOLOR, |
34 | }; | 35 | }; |
35 | 36 | ||
37 | enum { | ||
38 | M_I17, /* 17-Inch iMac */ | ||
39 | M_I20, /* 20-Inch iMac */ | ||
40 | M_I20_SR, /* 20-Inch iMac (Santa Rosa) */ | ||
41 | M_I24, /* 24-Inch iMac */ | ||
42 | M_MINI, /* Mac Mini */ | ||
43 | M_MB, /* MacBook */ | ||
44 | M_MB_2, /* MacBook, 2nd rev. */ | ||
45 | M_MB_3, /* MacBook, 3rd rev. */ | ||
46 | M_MB_SR, /* MacBook, 2nd gen, (Santa Rosa) */ | ||
47 | M_MBA, /* MacBook Air */ | ||
48 | M_MBP, /* MacBook Pro */ | ||
49 | M_MBP_2, /* MacBook Pro 2nd gen */ | ||
50 | M_MBP_SR, /* MacBook Pro (Santa Rosa) */ | ||
51 | M_MBP_4, /* MacBook Pro, 4th gen */ | ||
52 | M_UNKNOWN /* placeholder */ | ||
53 | }; | ||
54 | |||
55 | static struct efifb_dmi_info { | ||
56 | char *optname; | ||
57 | unsigned long base; | ||
58 | int stride; | ||
59 | int width; | ||
60 | int height; | ||
61 | } dmi_list[] = { | ||
62 | [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900 }, | ||
63 | [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050 }, /* guess */ | ||
64 | [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050 }, | ||
65 | [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200 }, /* guess */ | ||
66 | [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768 }, | ||
67 | [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800 }, | ||
68 | [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800 }, | ||
69 | [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900 }, | ||
70 | [M_MBP_2] = { "mbp2", 0, 0, 0, 0 }, /* placeholder */ | ||
71 | [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900 }, | ||
72 | [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200 }, | ||
73 | [M_UNKNOWN] = { NULL, 0, 0, 0, 0 } | ||
74 | }; | ||
75 | |||
76 | static int set_system(const struct dmi_system_id *id); | ||
77 | |||
78 | #define EFIFB_DMI_SYSTEM_ID(vendor, name, enumid) \ | ||
79 | { set_system, name, { \ | ||
80 | DMI_MATCH(DMI_BIOS_VENDOR, vendor), \ | ||
81 | DMI_MATCH(DMI_PRODUCT_NAME, name) }, \ | ||
82 | &dmi_list[enumid] } | ||
83 | |||
84 | static struct dmi_system_id __initdata dmi_system_table[] = { | ||
85 | EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac4,1", M_I17), | ||
86 | /* At least one of these two will be right; maybe both? */ | ||
87 | EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac5,1", M_I20), | ||
88 | EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac5,1", M_I20), | ||
89 | /* At least one of these two will be right; maybe both? */ | ||
90 | EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac6,1", M_I24), | ||
91 | EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac6,1", M_I24), | ||
92 | EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac7,1", M_I20_SR), | ||
93 | EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "Macmini1,1", M_MINI), | ||
94 | EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook1,1", M_MB), | ||
95 | /* At least one of these two will be right; maybe both? */ | ||
96 | EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook2,1", M_MB), | ||
97 | EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook2,1", M_MB), | ||
98 | /* At least one of these two will be right; maybe both? */ | ||
99 | EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook3,1", M_MB), | ||
100 | EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook3,1", M_MB), | ||
101 | EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook4,1", M_MB), | ||
102 | EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA), | ||
103 | EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP), | ||
104 | EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,1", M_MBP_2), | ||
105 | EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro2,1", M_MBP_2), | ||
106 | EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro3,1", M_MBP_SR), | ||
107 | EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro3,1", M_MBP_SR), | ||
108 | EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro4,1", M_MBP_4), | ||
109 | {}, | ||
110 | }; | ||
111 | |||
112 | static int set_system(const struct dmi_system_id *id) | ||
113 | { | ||
114 | struct efifb_dmi_info *info = id->driver_data; | ||
115 | if (info->base == 0) | ||
116 | return -ENODEV; | ||
117 | |||
118 | printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p " | ||
119 | "(%dx%d, stride %d)\n", id->ident, | ||
120 | (void *)info->base, info->width, info->height, | ||
121 | info->stride); | ||
122 | |||
123 | /* Trust the bootloader over the DMI tables */ | ||
124 | if (screen_info.lfb_base == 0) | ||
125 | screen_info.lfb_base = info->base; | ||
126 | if (screen_info.lfb_linelength == 0) | ||
127 | screen_info.lfb_linelength = info->stride; | ||
128 | if (screen_info.lfb_width == 0) | ||
129 | screen_info.lfb_width = info->width; | ||
130 | if (screen_info.lfb_height == 0) | ||
131 | screen_info.lfb_height = info->height; | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | |||
36 | static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green, | 136 | static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green, |
37 | unsigned blue, unsigned transp, | 137 | unsigned blue, unsigned transp, |
38 | struct fb_info *info) | 138 | struct fb_info *info) |
@@ -67,6 +167,38 @@ static struct fb_ops efifb_ops = { | |||
67 | .fb_imageblit = cfb_imageblit, | 167 | .fb_imageblit = cfb_imageblit, |
68 | }; | 168 | }; |
69 | 169 | ||
170 | static int __init efifb_setup(char *options) | ||
171 | { | ||
172 | char *this_opt; | ||
173 | int i; | ||
174 | |||
175 | if (!options || !*options) | ||
176 | return 0; | ||
177 | |||
178 | while ((this_opt = strsep(&options, ",")) != NULL) { | ||
179 | if (!*this_opt) continue; | ||
180 | |||
181 | for (i = 0; i < M_UNKNOWN; i++) { | ||
182 | if (!strcmp(this_opt, dmi_list[i].optname) && | ||
183 | dmi_list[i].base != 0) { | ||
184 | screen_info.lfb_base = dmi_list[i].base; | ||
185 | screen_info.lfb_linelength = dmi_list[i].stride; | ||
186 | screen_info.lfb_width = dmi_list[i].width; | ||
187 | screen_info.lfb_height = dmi_list[i].height; | ||
188 | } | ||
189 | } | ||
190 | if (!strncmp(this_opt, "base:", 5)) | ||
191 | screen_info.lfb_base = simple_strtoul(this_opt+5, NULL, 0); | ||
192 | else if (!strncmp(this_opt, "stride:", 7)) | ||
193 | screen_info.lfb_linelength = simple_strtoul(this_opt+7, NULL, 0) * 4; | ||
194 | else if (!strncmp(this_opt, "height:", 7)) | ||
195 | screen_info.lfb_height = simple_strtoul(this_opt+7, NULL, 0); | ||
196 | else if (!strncmp(this_opt, "width:", 6)) | ||
197 | screen_info.lfb_width = simple_strtoul(this_opt+6, NULL, 0); | ||
198 | } | ||
199 | return 0; | ||
200 | } | ||
201 | |||
70 | static int __init efifb_probe(struct platform_device *dev) | 202 | static int __init efifb_probe(struct platform_device *dev) |
71 | { | 203 | { |
72 | struct fb_info *info; | 204 | struct fb_info *info; |
@@ -74,6 +206,26 @@ static int __init efifb_probe(struct platform_device *dev) | |||
74 | unsigned int size_vmode; | 206 | unsigned int size_vmode; |
75 | unsigned int size_remap; | 207 | unsigned int size_remap; |
76 | unsigned int size_total; | 208 | unsigned int size_total; |
209 | int request_succeeded = 0; | ||
210 | |||
211 | printk(KERN_INFO "efifb: probing for efifb\n"); | ||
212 | |||
213 | if (!screen_info.lfb_depth) | ||
214 | screen_info.lfb_depth = 32; | ||
215 | if (!screen_info.pages) | ||
216 | screen_info.pages = 1; | ||
217 | |||
218 | /* just assume they're all unset if any are */ | ||
219 | if (!screen_info.blue_size) { | ||
220 | screen_info.blue_size = 8; | ||
221 | screen_info.blue_pos = 0; | ||
222 | screen_info.green_size = 8; | ||
223 | screen_info.green_pos = 8; | ||
224 | screen_info.red_size = 8; | ||
225 | screen_info.red_pos = 16; | ||
226 | screen_info.rsvd_size = 8; | ||
227 | screen_info.rsvd_pos = 24; | ||
228 | } | ||
77 | 229 | ||
78 | efifb_fix.smem_start = screen_info.lfb_base; | 230 | efifb_fix.smem_start = screen_info.lfb_base; |
79 | efifb_defined.bits_per_pixel = screen_info.lfb_depth; | 231 | efifb_defined.bits_per_pixel = screen_info.lfb_depth; |
@@ -98,21 +250,25 @@ static int __init efifb_probe(struct platform_device *dev) | |||
98 | * option to simply use size_total as that | 250 | * option to simply use size_total as that |
99 | * wastes plenty of kernel address space. */ | 251 | * wastes plenty of kernel address space. */ |
100 | size_remap = size_vmode * 2; | 252 | size_remap = size_vmode * 2; |
101 | if (size_remap < size_vmode) | ||
102 | size_remap = size_vmode; | ||
103 | if (size_remap > size_total) | 253 | if (size_remap > size_total) |
104 | size_remap = size_total; | 254 | size_remap = size_total; |
255 | if (size_remap % PAGE_SIZE) | ||
256 | size_remap += PAGE_SIZE - (size_remap % PAGE_SIZE); | ||
105 | efifb_fix.smem_len = size_remap; | 257 | efifb_fix.smem_len = size_remap; |
106 | 258 | ||
107 | if (!request_mem_region(efifb_fix.smem_start, size_total, "efifb")) | 259 | if (request_mem_region(efifb_fix.smem_start, size_remap, "efifb")) { |
260 | request_succeeded = 1; | ||
261 | } else { | ||
108 | /* We cannot make this fatal. Sometimes this comes from magic | 262 | /* We cannot make this fatal. Sometimes this comes from magic |
109 | spaces our resource handlers simply don't know about */ | 263 | spaces our resource handlers simply don't know about */ |
110 | printk(KERN_WARNING | 264 | printk(KERN_WARNING |
111 | "efifb: cannot reserve video memory at 0x%lx\n", | 265 | "efifb: cannot reserve video memory at 0x%lx\n", |
112 | efifb_fix.smem_start); | 266 | efifb_fix.smem_start); |
267 | } | ||
113 | 268 | ||
114 | info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev); | 269 | info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev); |
115 | if (!info) { | 270 | if (!info) { |
271 | printk(KERN_ERR "efifb: cannot allocate framebuffer\n"); | ||
116 | err = -ENOMEM; | 272 | err = -ENOMEM; |
117 | goto err_release_mem; | 273 | goto err_release_mem; |
118 | } | 274 | } |
@@ -125,7 +281,7 @@ static int __init efifb_probe(struct platform_device *dev) | |||
125 | "0x%x @ 0x%lx\n", | 281 | "0x%x @ 0x%lx\n", |
126 | efifb_fix.smem_len, efifb_fix.smem_start); | 282 | efifb_fix.smem_len, efifb_fix.smem_start); |
127 | err = -EIO; | 283 | err = -EIO; |
128 | goto err_unmap; | 284 | goto err_release_fb; |
129 | } | 285 | } |
130 | 286 | ||
131 | printk(KERN_INFO "efifb: framebuffer at 0x%lx, mapped to 0x%p, " | 287 | printk(KERN_INFO "efifb: framebuffer at 0x%lx, mapped to 0x%p, " |
@@ -178,25 +334,27 @@ static int __init efifb_probe(struct platform_device *dev) | |||
178 | info->fix = efifb_fix; | 334 | info->fix = efifb_fix; |
179 | info->flags = FBINFO_FLAG_DEFAULT; | 335 | info->flags = FBINFO_FLAG_DEFAULT; |
180 | 336 | ||
181 | if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { | 337 | if ((err = fb_alloc_cmap(&info->cmap, 256, 0)) < 0) { |
182 | err = -ENOMEM; | 338 | printk(KERN_ERR "efifb: cannot allocate colormap\n"); |
183 | goto err_unmap; | 339 | goto err_unmap; |
184 | } | 340 | } |
185 | if (register_framebuffer(info) < 0) { | 341 | if ((err = register_framebuffer(info)) < 0) { |
186 | err = -EINVAL; | 342 | printk(KERN_ERR "efifb: cannot register framebuffer\n"); |
187 | goto err_fb_dealoc; | 343 | goto err_fb_dealoc; |
188 | } | 344 | } |
189 | printk(KERN_INFO "fb%d: %s frame buffer device\n", | 345 | printk(KERN_INFO "fb%d: %s frame buffer device\n", |
190 | info->node, info->fix.id); | 346 | info->node, info->fix.id); |
191 | return 0; | 347 | return 0; |
192 | 348 | ||
193 | err_fb_dealoc: | 349 | err_fb_dealoc: |
194 | fb_dealloc_cmap(&info->cmap); | 350 | fb_dealloc_cmap(&info->cmap); |
195 | err_unmap: | 351 | err_unmap: |
196 | iounmap(info->screen_base); | 352 | iounmap(info->screen_base); |
353 | err_release_fb: | ||
197 | framebuffer_release(info); | 354 | framebuffer_release(info); |
198 | err_release_mem: | 355 | err_release_mem: |
199 | release_mem_region(efifb_fix.smem_start, size_total); | 356 | if (request_succeeded) |
357 | release_mem_region(efifb_fix.smem_start, size_total); | ||
200 | return err; | 358 | return err; |
201 | } | 359 | } |
202 | 360 | ||
@@ -214,9 +372,22 @@ static struct platform_device efifb_device = { | |||
214 | static int __init efifb_init(void) | 372 | static int __init efifb_init(void) |
215 | { | 373 | { |
216 | int ret; | 374 | int ret; |
375 | char *option = NULL; | ||
217 | 376 | ||
218 | if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) | 377 | if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) |
219 | return -ENODEV; | 378 | return -ENODEV; |
379 | dmi_check_system(dmi_system_table); | ||
380 | |||
381 | if (fb_get_options("efifb", &option)) | ||
382 | return -ENODEV; | ||
383 | efifb_setup(option); | ||
384 | |||
385 | /* We don't get linelength from UGA Draw Protocol, only from | ||
386 | * EFI Graphics Protocol. So if it's not in DMI, and it's not | ||
387 | * passed in from the user, we really can't use the framebuffer. | ||
388 | */ | ||
389 | if (!screen_info.lfb_linelength) | ||
390 | return -ENODEV; | ||
220 | 391 | ||
221 | ret = platform_driver_register(&efifb_driver); | 392 | ret = platform_driver_register(&efifb_driver); |
222 | 393 | ||
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 61b36ca06997..217c5118ae9e 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
@@ -28,9 +28,7 @@ | |||
28 | #include <linux/proc_fs.h> | 28 | #include <linux/proc_fs.h> |
29 | #include <linux/seq_file.h> | 29 | #include <linux/seq_file.h> |
30 | #include <linux/console.h> | 30 | #include <linux/console.h> |
31 | #ifdef CONFIG_KMOD | ||
32 | #include <linux/kmod.h> | 31 | #include <linux/kmod.h> |
33 | #endif | ||
34 | #include <linux/err.h> | 32 | #include <linux/err.h> |
35 | #include <linux/device.h> | 33 | #include <linux/device.h> |
36 | #include <linux/efi.h> | 34 | #include <linux/efi.h> |
@@ -837,13 +835,6 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | |||
837 | return (cnt) ? cnt : err; | 835 | return (cnt) ? cnt : err; |
838 | } | 836 | } |
839 | 837 | ||
840 | #ifdef CONFIG_KMOD | ||
841 | static void try_to_load(int fb) | ||
842 | { | ||
843 | request_module("fb%d", fb); | ||
844 | } | ||
845 | #endif /* CONFIG_KMOD */ | ||
846 | |||
847 | int | 838 | int |
848 | fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var) | 839 | fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var) |
849 | { | 840 | { |
@@ -1086,10 +1077,8 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
1086 | return -EINVAL; | 1077 | return -EINVAL; |
1087 | if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) | 1078 | if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) |
1088 | return -EINVAL; | 1079 | return -EINVAL; |
1089 | #ifdef CONFIG_KMOD | ||
1090 | if (!registered_fb[con2fb.framebuffer]) | 1080 | if (!registered_fb[con2fb.framebuffer]) |
1091 | try_to_load(con2fb.framebuffer); | 1081 | request_module("fb%d", con2fb.framebuffer); |
1092 | #endif /* CONFIG_KMOD */ | ||
1093 | if (!registered_fb[con2fb.framebuffer]) | 1082 | if (!registered_fb[con2fb.framebuffer]) |
1094 | return -EINVAL; | 1083 | return -EINVAL; |
1095 | event.info = info; | 1084 | event.info = info; |
@@ -1327,10 +1316,8 @@ fb_open(struct inode *inode, struct file *file) | |||
1327 | if (fbidx >= FB_MAX) | 1316 | if (fbidx >= FB_MAX) |
1328 | return -ENODEV; | 1317 | return -ENODEV; |
1329 | lock_kernel(); | 1318 | lock_kernel(); |
1330 | #ifdef CONFIG_KMOD | ||
1331 | if (!(info = registered_fb[fbidx])) | 1319 | if (!(info = registered_fb[fbidx])) |
1332 | try_to_load(fbidx); | 1320 | request_module("fb%d", fbidx); |
1333 | #endif /* CONFIG_KMOD */ | ||
1334 | if (!(info = registered_fb[fbidx])) { | 1321 | if (!(info = registered_fb[fbidx])) { |
1335 | res = -ENODEV; | 1322 | res = -ENODEV; |
1336 | goto out; | 1323 | goto out; |
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c index 6a0aa180c266..5c1a2c01778f 100644 --- a/drivers/video/fbmon.c +++ b/drivers/video/fbmon.c | |||
@@ -564,7 +564,13 @@ static void get_detailed_timing(unsigned char *block, | |||
564 | mode->sync |= FB_SYNC_VERT_HIGH_ACT; | 564 | mode->sync |= FB_SYNC_VERT_HIGH_ACT; |
565 | mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) * | 565 | mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) * |
566 | (V_ACTIVE + V_BLANKING)); | 566 | (V_ACTIVE + V_BLANKING)); |
567 | mode->vmode = 0; | 567 | if (INTERLACED) { |
568 | mode->yres *= 2; | ||
569 | mode->upper_margin *= 2; | ||
570 | mode->lower_margin *= 2; | ||
571 | mode->vsync_len *= 2; | ||
572 | mode->vmode |= FB_VMODE_INTERLACED; | ||
573 | } | ||
568 | mode->flag = FB_MODE_IS_DETAILED; | 574 | mode->flag = FB_MODE_IS_DETAILED; |
569 | 575 | ||
570 | DPRINTK(" %d MHz ", PIXEL_CLOCK/1000000); | 576 | DPRINTK(" %d MHz ", PIXEL_CLOCK/1000000); |
diff --git a/drivers/video/imacfb.c b/drivers/video/imacfb.c index 9366ef2bb5f7..e69de29bb2d1 100644 --- a/drivers/video/imacfb.c +++ b/drivers/video/imacfb.c | |||
@@ -1,376 +0,0 @@ | |||
1 | /* | ||
2 | * framebuffer driver for Intel Based Mac's | ||
3 | * | ||
4 | * (c) 2006 Edgar Hucek <gimli@dark-green.com> | ||
5 | * Original imac driver written by Gerd Knorr <kraxel@goldbach.in-berlin.de> | ||
6 | * | ||
7 | */ | ||
8 | |||
9 | #include <linux/delay.h> | ||
10 | #include <linux/errno.h> | ||
11 | #include <linux/fb.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/ioport.h> | ||
15 | #include <linux/mm.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/screen_info.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/string.h> | ||
21 | #include <linux/dmi.h> | ||
22 | #include <linux/efi.h> | ||
23 | |||
24 | #include <asm/io.h> | ||
25 | |||
26 | #include <video/vga.h> | ||
27 | |||
28 | typedef enum _MAC_TYPE { | ||
29 | M_I17, | ||
30 | M_I20, | ||
31 | M_MINI, | ||
32 | M_MACBOOK, | ||
33 | M_UNKNOWN | ||
34 | } MAC_TYPE; | ||
35 | |||
36 | /* --------------------------------------------------------------------- */ | ||
37 | |||
38 | static struct fb_var_screeninfo imacfb_defined __initdata = { | ||
39 | .activate = FB_ACTIVATE_NOW, | ||
40 | .height = -1, | ||
41 | .width = -1, | ||
42 | .right_margin = 32, | ||
43 | .upper_margin = 16, | ||
44 | .lower_margin = 4, | ||
45 | .vsync_len = 4, | ||
46 | .vmode = FB_VMODE_NONINTERLACED, | ||
47 | }; | ||
48 | |||
49 | static struct fb_fix_screeninfo imacfb_fix __initdata = { | ||
50 | .id = "IMAC VGA", | ||
51 | .type = FB_TYPE_PACKED_PIXELS, | ||
52 | .accel = FB_ACCEL_NONE, | ||
53 | .visual = FB_VISUAL_TRUECOLOR, | ||
54 | }; | ||
55 | |||
56 | static int inverse; | ||
57 | static int model = M_UNKNOWN; | ||
58 | static int manual_height; | ||
59 | static int manual_width; | ||
60 | |||
61 | static int set_system(const struct dmi_system_id *id) | ||
62 | { | ||
63 | printk(KERN_INFO "imacfb: %s detected - set system to %ld\n", | ||
64 | id->ident, (long)id->driver_data); | ||
65 | |||
66 | model = (long)id->driver_data; | ||
67 | |||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | static struct dmi_system_id __initdata dmi_system_table[] = { | ||
72 | { set_system, "iMac4,1", { | ||
73 | DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."), | ||
74 | DMI_MATCH(DMI_PRODUCT_NAME,"iMac4,1") }, (void*)M_I17}, | ||
75 | { set_system, "MacBookPro1,1", { | ||
76 | DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."), | ||
77 | DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro1,1") }, (void*)M_I17}, | ||
78 | { set_system, "MacBook1,1", { | ||
79 | DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."), | ||
80 | DMI_MATCH(DMI_PRODUCT_NAME,"MacBook1,1")}, (void *)M_MACBOOK}, | ||
81 | { set_system, "Macmini1,1", { | ||
82 | DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."), | ||
83 | DMI_MATCH(DMI_PRODUCT_NAME,"Macmini1,1")}, (void *)M_MINI}, | ||
84 | {}, | ||
85 | }; | ||
86 | |||
87 | #define DEFAULT_FB_MEM 1024*1024*16 | ||
88 | |||
89 | /* --------------------------------------------------------------------- */ | ||
90 | |||
91 | static int imacfb_setcolreg(unsigned regno, unsigned red, unsigned green, | ||
92 | unsigned blue, unsigned transp, | ||
93 | struct fb_info *info) | ||
94 | { | ||
95 | /* | ||
96 | * Set a single color register. The values supplied are | ||
97 | * already rounded down to the hardware's capabilities | ||
98 | * (according to the entries in the `var' structure). Return | ||
99 | * != 0 for invalid regno. | ||
100 | */ | ||
101 | |||
102 | if (regno >= info->cmap.len) | ||
103 | return 1; | ||
104 | |||
105 | if (regno < 16) { | ||
106 | red >>= 8; | ||
107 | green >>= 8; | ||
108 | blue >>= 8; | ||
109 | ((u32 *)(info->pseudo_palette))[regno] = | ||
110 | (red << info->var.red.offset) | | ||
111 | (green << info->var.green.offset) | | ||
112 | (blue << info->var.blue.offset); | ||
113 | } | ||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | static struct fb_ops imacfb_ops = { | ||
118 | .owner = THIS_MODULE, | ||
119 | .fb_setcolreg = imacfb_setcolreg, | ||
120 | .fb_fillrect = cfb_fillrect, | ||
121 | .fb_copyarea = cfb_copyarea, | ||
122 | .fb_imageblit = cfb_imageblit, | ||
123 | }; | ||
124 | |||
125 | static int __init imacfb_setup(char *options) | ||
126 | { | ||
127 | char *this_opt; | ||
128 | |||
129 | if (!options || !*options) | ||
130 | return 0; | ||
131 | |||
132 | while ((this_opt = strsep(&options, ",")) != NULL) { | ||
133 | if (!*this_opt) continue; | ||
134 | |||
135 | if (!strcmp(this_opt, "inverse")) | ||
136 | inverse = 1; | ||
137 | else if (!strcmp(this_opt, "i17")) | ||
138 | model = M_I17; | ||
139 | else if (!strcmp(this_opt, "i20")) | ||
140 | model = M_I20; | ||
141 | else if (!strcmp(this_opt, "mini")) | ||
142 | model = M_MINI; | ||
143 | else if (!strcmp(this_opt, "macbook")) | ||
144 | model = M_MACBOOK; | ||
145 | else if (!strncmp(this_opt, "height:", 7)) | ||
146 | manual_height = simple_strtoul(this_opt+7, NULL, 0); | ||
147 | else if (!strncmp(this_opt, "width:", 6)) | ||
148 | manual_width = simple_strtoul(this_opt+6, NULL, 0); | ||
149 | } | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static int __init imacfb_probe(struct platform_device *dev) | ||
154 | { | ||
155 | struct fb_info *info; | ||
156 | int err; | ||
157 | unsigned int size_vmode; | ||
158 | unsigned int size_remap; | ||
159 | unsigned int size_total; | ||
160 | |||
161 | screen_info.lfb_depth = 32; | ||
162 | screen_info.lfb_size = DEFAULT_FB_MEM / 0x10000; | ||
163 | screen_info.pages=1; | ||
164 | screen_info.blue_size = 8; | ||
165 | screen_info.blue_pos = 0; | ||
166 | screen_info.green_size = 8; | ||
167 | screen_info.green_pos = 8; | ||
168 | screen_info.red_size = 8; | ||
169 | screen_info.red_pos = 16; | ||
170 | screen_info.rsvd_size = 8; | ||
171 | screen_info.rsvd_pos = 24; | ||
172 | |||
173 | switch (model) { | ||
174 | case M_I17: | ||
175 | screen_info.lfb_width = 1440; | ||
176 | screen_info.lfb_height = 900; | ||
177 | screen_info.lfb_linelength = 1472 * 4; | ||
178 | screen_info.lfb_base = 0x80010000; | ||
179 | break; | ||
180 | case M_I20: | ||
181 | screen_info.lfb_width = 1680; | ||
182 | screen_info.lfb_height = 1050; | ||
183 | screen_info.lfb_linelength = 1728 * 4; | ||
184 | screen_info.lfb_base = 0x80010000; | ||
185 | break; | ||
186 | case M_MINI: | ||
187 | screen_info.lfb_width = 1024; | ||
188 | screen_info.lfb_height = 768; | ||
189 | screen_info.lfb_linelength = 2048 * 4; | ||
190 | screen_info.lfb_base = 0x80000000; | ||
191 | break; | ||
192 | case M_MACBOOK: | ||
193 | screen_info.lfb_width = 1280; | ||
194 | screen_info.lfb_height = 800; | ||
195 | screen_info.lfb_linelength = 2048 * 4; | ||
196 | screen_info.lfb_base = 0x80000000; | ||
197 | break; | ||
198 | } | ||
199 | |||
200 | /* if the user wants to manually specify height/width, | ||
201 | we will override the defaults */ | ||
202 | /* TODO: eventually get auto-detection working */ | ||
203 | if (manual_height > 0) | ||
204 | screen_info.lfb_height = manual_height; | ||
205 | if (manual_width > 0) | ||
206 | screen_info.lfb_width = manual_width; | ||
207 | |||
208 | imacfb_fix.smem_start = screen_info.lfb_base; | ||
209 | imacfb_defined.bits_per_pixel = screen_info.lfb_depth; | ||
210 | imacfb_defined.xres = screen_info.lfb_width; | ||
211 | imacfb_defined.yres = screen_info.lfb_height; | ||
212 | imacfb_fix.line_length = screen_info.lfb_linelength; | ||
213 | |||
214 | /* size_vmode -- that is the amount of memory needed for the | ||
215 | * used video mode, i.e. the minimum amount of | ||
216 | * memory we need. */ | ||
217 | size_vmode = imacfb_defined.yres * imacfb_fix.line_length; | ||
218 | |||
219 | /* size_total -- all video memory we have. Used for | ||
220 | * entries, ressource allocation and bounds | ||
221 | * checking. */ | ||
222 | size_total = screen_info.lfb_size * 65536; | ||
223 | if (size_total < size_vmode) | ||
224 | size_total = size_vmode; | ||
225 | |||
226 | /* size_remap -- the amount of video memory we are going to | ||
227 | * use for imacfb. With modern cards it is no | ||
228 | * option to simply use size_total as that | ||
229 | * wastes plenty of kernel address space. */ | ||
230 | size_remap = size_vmode * 2; | ||
231 | if (size_remap < size_vmode) | ||
232 | size_remap = size_vmode; | ||
233 | if (size_remap > size_total) | ||
234 | size_remap = size_total; | ||
235 | imacfb_fix.smem_len = size_remap; | ||
236 | |||
237 | if (!request_mem_region(imacfb_fix.smem_start, size_total, "imacfb")) { | ||
238 | printk(KERN_WARNING | ||
239 | "imacfb: cannot reserve video memory at 0x%lx\n", | ||
240 | imacfb_fix.smem_start); | ||
241 | /* We cannot make this fatal. Sometimes this comes from magic | ||
242 | spaces our resource handlers simply don't know about */ | ||
243 | } | ||
244 | |||
245 | info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev); | ||
246 | if (!info) { | ||
247 | err = -ENOMEM; | ||
248 | goto err_release_mem; | ||
249 | } | ||
250 | info->pseudo_palette = info->par; | ||
251 | info->par = NULL; | ||
252 | |||
253 | info->screen_base = ioremap(imacfb_fix.smem_start, imacfb_fix.smem_len); | ||
254 | if (!info->screen_base) { | ||
255 | printk(KERN_ERR "imacfb: abort, cannot ioremap video memory " | ||
256 | "0x%x @ 0x%lx\n", | ||
257 | imacfb_fix.smem_len, imacfb_fix.smem_start); | ||
258 | err = -EIO; | ||
259 | goto err_unmap; | ||
260 | } | ||
261 | |||
262 | printk(KERN_INFO "imacfb: framebuffer at 0x%lx, mapped to 0x%p, " | ||
263 | "using %dk, total %dk\n", | ||
264 | imacfb_fix.smem_start, info->screen_base, | ||
265 | size_remap/1024, size_total/1024); | ||
266 | printk(KERN_INFO "imacfb: mode is %dx%dx%d, linelength=%d, pages=%d\n", | ||
267 | imacfb_defined.xres, imacfb_defined.yres, | ||
268 | imacfb_defined.bits_per_pixel, imacfb_fix.line_length, | ||
269 | screen_info.pages); | ||
270 | |||
271 | imacfb_defined.xres_virtual = imacfb_defined.xres; | ||
272 | imacfb_defined.yres_virtual = imacfb_fix.smem_len / | ||
273 | imacfb_fix.line_length; | ||
274 | printk(KERN_INFO "imacfb: scrolling: redraw\n"); | ||
275 | imacfb_defined.yres_virtual = imacfb_defined.yres; | ||
276 | |||
277 | /* some dummy values for timing to make fbset happy */ | ||
278 | imacfb_defined.pixclock = 10000000 / imacfb_defined.xres * | ||
279 | 1000 / imacfb_defined.yres; | ||
280 | imacfb_defined.left_margin = (imacfb_defined.xres / 8) & 0xf8; | ||
281 | imacfb_defined.hsync_len = (imacfb_defined.xres / 8) & 0xf8; | ||
282 | |||
283 | imacfb_defined.red.offset = screen_info.red_pos; | ||
284 | imacfb_defined.red.length = screen_info.red_size; | ||
285 | imacfb_defined.green.offset = screen_info.green_pos; | ||
286 | imacfb_defined.green.length = screen_info.green_size; | ||
287 | imacfb_defined.blue.offset = screen_info.blue_pos; | ||
288 | imacfb_defined.blue.length = screen_info.blue_size; | ||
289 | imacfb_defined.transp.offset = screen_info.rsvd_pos; | ||
290 | imacfb_defined.transp.length = screen_info.rsvd_size; | ||
291 | |||
292 | printk(KERN_INFO "imacfb: %s: " | ||
293 | "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n", | ||
294 | "Truecolor", | ||
295 | screen_info.rsvd_size, | ||
296 | screen_info.red_size, | ||
297 | screen_info.green_size, | ||
298 | screen_info.blue_size, | ||
299 | screen_info.rsvd_pos, | ||
300 | screen_info.red_pos, | ||
301 | screen_info.green_pos, | ||
302 | screen_info.blue_pos); | ||
303 | |||
304 | imacfb_fix.ypanstep = 0; | ||
305 | imacfb_fix.ywrapstep = 0; | ||
306 | |||
307 | /* request failure does not faze us, as vgacon probably has this | ||
308 | * region already (FIXME) */ | ||
309 | request_region(0x3c0, 32, "imacfb"); | ||
310 | |||
311 | info->fbops = &imacfb_ops; | ||
312 | info->var = imacfb_defined; | ||
313 | info->fix = imacfb_fix; | ||
314 | info->flags = FBINFO_FLAG_DEFAULT; | ||
315 | |||
316 | if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { | ||
317 | err = -ENOMEM; | ||
318 | goto err_unmap; | ||
319 | } | ||
320 | if (register_framebuffer(info)<0) { | ||
321 | err = -EINVAL; | ||
322 | goto err_fb_dealoc; | ||
323 | } | ||
324 | printk(KERN_INFO "fb%d: %s frame buffer device\n", | ||
325 | info->node, info->fix.id); | ||
326 | return 0; | ||
327 | |||
328 | err_fb_dealoc: | ||
329 | fb_dealloc_cmap(&info->cmap); | ||
330 | err_unmap: | ||
331 | iounmap(info->screen_base); | ||
332 | framebuffer_release(info); | ||
333 | err_release_mem: | ||
334 | release_mem_region(imacfb_fix.smem_start, size_total); | ||
335 | return err; | ||
336 | } | ||
337 | |||
338 | static struct platform_driver imacfb_driver = { | ||
339 | .probe = imacfb_probe, | ||
340 | .driver = { | ||
341 | .name = "imacfb", | ||
342 | }, | ||
343 | }; | ||
344 | |||
345 | static struct platform_device imacfb_device = { | ||
346 | .name = "imacfb", | ||
347 | }; | ||
348 | |||
349 | static int __init imacfb_init(void) | ||
350 | { | ||
351 | int ret; | ||
352 | char *option = NULL; | ||
353 | |||
354 | if (!efi_enabled) | ||
355 | return -ENODEV; | ||
356 | if (!dmi_check_system(dmi_system_table)) | ||
357 | return -ENODEV; | ||
358 | if (model == M_UNKNOWN) | ||
359 | return -ENODEV; | ||
360 | |||
361 | if (fb_get_options("imacfb", &option)) | ||
362 | return -ENODEV; | ||
363 | |||
364 | imacfb_setup(option); | ||
365 | ret = platform_driver_register(&imacfb_driver); | ||
366 | |||
367 | if (!ret) { | ||
368 | ret = platform_device_register(&imacfb_device); | ||
369 | if (ret) | ||
370 | platform_driver_unregister(&imacfb_driver); | ||
371 | } | ||
372 | return ret; | ||
373 | } | ||
374 | module_init(imacfb_init); | ||
375 | |||
376 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h index 3325fbd68ab3..a50bea614804 100644 --- a/drivers/video/intelfb/intelfb.h +++ b/drivers/video/intelfb/intelfb.h | |||
@@ -12,9 +12,9 @@ | |||
12 | #endif | 12 | #endif |
13 | 13 | ||
14 | /*** Version/name ***/ | 14 | /*** Version/name ***/ |
15 | #define INTELFB_VERSION "0.9.5" | 15 | #define INTELFB_VERSION "0.9.6" |
16 | #define INTELFB_MODULE_NAME "intelfb" | 16 | #define INTELFB_MODULE_NAME "intelfb" |
17 | #define SUPPORTED_CHIPSETS "830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM" | 17 | #define SUPPORTED_CHIPSETS "830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/945GME/965G/965GM" |
18 | 18 | ||
19 | 19 | ||
20 | /*** Debug/feature defines ***/ | 20 | /*** Debug/feature defines ***/ |
@@ -58,6 +58,7 @@ | |||
58 | #define PCI_DEVICE_ID_INTEL_915GM 0x2592 | 58 | #define PCI_DEVICE_ID_INTEL_915GM 0x2592 |
59 | #define PCI_DEVICE_ID_INTEL_945G 0x2772 | 59 | #define PCI_DEVICE_ID_INTEL_945G 0x2772 |
60 | #define PCI_DEVICE_ID_INTEL_945GM 0x27A2 | 60 | #define PCI_DEVICE_ID_INTEL_945GM 0x27A2 |
61 | #define PCI_DEVICE_ID_INTEL_945GME 0x27AE | ||
61 | #define PCI_DEVICE_ID_INTEL_965G 0x29A2 | 62 | #define PCI_DEVICE_ID_INTEL_965G 0x29A2 |
62 | #define PCI_DEVICE_ID_INTEL_965GM 0x2A02 | 63 | #define PCI_DEVICE_ID_INTEL_965GM 0x2A02 |
63 | 64 | ||
@@ -160,6 +161,7 @@ enum intel_chips { | |||
160 | INTEL_915GM, | 161 | INTEL_915GM, |
161 | INTEL_945G, | 162 | INTEL_945G, |
162 | INTEL_945GM, | 163 | INTEL_945GM, |
164 | INTEL_945GME, | ||
163 | INTEL_965G, | 165 | INTEL_965G, |
164 | INTEL_965GM, | 166 | INTEL_965GM, |
165 | }; | 167 | }; |
@@ -363,6 +365,7 @@ struct intelfb_info { | |||
363 | ((dinfo)->chipset == INTEL_915GM) || \ | 365 | ((dinfo)->chipset == INTEL_915GM) || \ |
364 | ((dinfo)->chipset == INTEL_945G) || \ | 366 | ((dinfo)->chipset == INTEL_945G) || \ |
365 | ((dinfo)->chipset == INTEL_945GM) || \ | 367 | ((dinfo)->chipset == INTEL_945GM) || \ |
368 | ((dinfo)->chipset == INTEL_945GME) || \ | ||
366 | ((dinfo)->chipset == INTEL_965G) || \ | 369 | ((dinfo)->chipset == INTEL_965G) || \ |
367 | ((dinfo)->chipset == INTEL_965GM)) | 370 | ((dinfo)->chipset == INTEL_965GM)) |
368 | 371 | ||
diff --git a/drivers/video/intelfb/intelfb_i2c.c b/drivers/video/intelfb/intelfb_i2c.c index fcf9fadbf572..5d896b81f4e0 100644 --- a/drivers/video/intelfb/intelfb_i2c.c +++ b/drivers/video/intelfb/intelfb_i2c.c | |||
@@ -171,6 +171,7 @@ void intelfb_create_i2c_busses(struct intelfb_info *dinfo) | |||
171 | /* has some LVDS + tv-out */ | 171 | /* has some LVDS + tv-out */ |
172 | case INTEL_945G: | 172 | case INTEL_945G: |
173 | case INTEL_945GM: | 173 | case INTEL_945GM: |
174 | case INTEL_945GME: | ||
174 | case INTEL_965G: | 175 | case INTEL_965G: |
175 | case INTEL_965GM: | 176 | case INTEL_965GM: |
176 | /* SDVO ports have a single control bus - 2 devices */ | 177 | /* SDVO ports have a single control bus - 2 devices */ |
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c index e44303f9bc52..a09e23649357 100644 --- a/drivers/video/intelfb/intelfbdrv.c +++ b/drivers/video/intelfb/intelfbdrv.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * intelfb | 2 | * intelfb |
3 | * | 3 | * |
4 | * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM/ | 4 | * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM/ |
5 | * 945G/945GM/965G/965GM integrated graphics chips. | 5 | * 945G/945GM/945GME/965G/965GM integrated graphics chips. |
6 | * | 6 | * |
7 | * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org> | 7 | * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org> |
8 | * 2004 Sylvain Meyer | 8 | * 2004 Sylvain Meyer |
@@ -102,6 +102,9 @@ | |||
102 | * | 102 | * |
103 | * 04/2008 - Version 0.9.5 | 103 | * 04/2008 - Version 0.9.5 |
104 | * Add support for 965G/965GM. (Maik Broemme <mbroemme@plusserver.de>) | 104 | * Add support for 965G/965GM. (Maik Broemme <mbroemme@plusserver.de>) |
105 | * | ||
106 | * 08/2008 - Version 0.9.6 | ||
107 | * Add support for 945GME. (Phil Endecott <spam_from_intelfb@chezphil.org>) | ||
105 | */ | 108 | */ |
106 | 109 | ||
107 | #include <linux/module.h> | 110 | #include <linux/module.h> |
@@ -183,6 +186,7 @@ static struct pci_device_id intelfb_pci_table[] __devinitdata = { | |||
183 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915GM }, | 186 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915GM }, |
184 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945G }, | 187 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945G }, |
185 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GM }, | 188 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GM }, |
189 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GME, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GME }, | ||
186 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965G }, | 190 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965G }, |
187 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965GM }, | 191 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965GM }, |
188 | { 0, } | 192 | { 0, } |
@@ -555,6 +559,7 @@ static int __devinit intelfb_pci_register(struct pci_dev *pdev, | |||
555 | (ent->device == PCI_DEVICE_ID_INTEL_915GM) || | 559 | (ent->device == PCI_DEVICE_ID_INTEL_915GM) || |
556 | (ent->device == PCI_DEVICE_ID_INTEL_945G) || | 560 | (ent->device == PCI_DEVICE_ID_INTEL_945G) || |
557 | (ent->device == PCI_DEVICE_ID_INTEL_945GM) || | 561 | (ent->device == PCI_DEVICE_ID_INTEL_945GM) || |
562 | (ent->device == PCI_DEVICE_ID_INTEL_945GME) || | ||
558 | (ent->device == PCI_DEVICE_ID_INTEL_965G) || | 563 | (ent->device == PCI_DEVICE_ID_INTEL_965G) || |
559 | (ent->device == PCI_DEVICE_ID_INTEL_965GM)) { | 564 | (ent->device == PCI_DEVICE_ID_INTEL_965GM)) { |
560 | 565 | ||
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c index 8e6d6a4db0ad..8b26b27c2db6 100644 --- a/drivers/video/intelfb/intelfbhw.c +++ b/drivers/video/intelfb/intelfbhw.c | |||
@@ -143,6 +143,12 @@ int intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo) | |||
143 | dinfo->mobile = 1; | 143 | dinfo->mobile = 1; |
144 | dinfo->pll_index = PLLS_I9xx; | 144 | dinfo->pll_index = PLLS_I9xx; |
145 | return 0; | 145 | return 0; |
146 | case PCI_DEVICE_ID_INTEL_945GME: | ||
147 | dinfo->name = "Intel(R) 945GME"; | ||
148 | dinfo->chipset = INTEL_945GME; | ||
149 | dinfo->mobile = 1; | ||
150 | dinfo->pll_index = PLLS_I9xx; | ||
151 | return 0; | ||
146 | case PCI_DEVICE_ID_INTEL_965G: | 152 | case PCI_DEVICE_ID_INTEL_965G: |
147 | dinfo->name = "Intel(R) 965G"; | 153 | dinfo->name = "Intel(R) 965G"; |
148 | dinfo->chipset = INTEL_965G; | 154 | dinfo->chipset = INTEL_965G; |
@@ -186,6 +192,7 @@ int intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size, | |||
186 | case PCI_DEVICE_ID_INTEL_915GM: | 192 | case PCI_DEVICE_ID_INTEL_915GM: |
187 | case PCI_DEVICE_ID_INTEL_945G: | 193 | case PCI_DEVICE_ID_INTEL_945G: |
188 | case PCI_DEVICE_ID_INTEL_945GM: | 194 | case PCI_DEVICE_ID_INTEL_945GM: |
195 | case PCI_DEVICE_ID_INTEL_945GME: | ||
189 | case PCI_DEVICE_ID_INTEL_965G: | 196 | case PCI_DEVICE_ID_INTEL_965G: |
190 | case PCI_DEVICE_ID_INTEL_965GM: | 197 | case PCI_DEVICE_ID_INTEL_965GM: |
191 | /* 915, 945 and 965 chipsets support a 256MB aperture. | 198 | /* 915, 945 and 965 chipsets support a 256MB aperture. |
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index c02136202792..8e7a275df50c 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c | |||
@@ -1453,6 +1453,13 @@ static struct board { | |||
1453 | MGA_G100, | 1453 | MGA_G100, |
1454 | &vbG100, | 1454 | &vbG100, |
1455 | "MGA-G100 (AGP)"}, | 1455 | "MGA-G100 (AGP)"}, |
1456 | {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200EV_PCI, 0xFF, | ||
1457 | 0, 0, | ||
1458 | DEVF_G200, | ||
1459 | 230000, | ||
1460 | MGA_G200, | ||
1461 | &vbG200, | ||
1462 | "MGA-G200eV (PCI)"}, | ||
1456 | {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_PCI, 0xFF, | 1463 | {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_PCI, 0xFF, |
1457 | 0, 0, | 1464 | 0, 0, |
1458 | DEVF_G200, | 1465 | DEVF_G200, |
@@ -2118,6 +2125,8 @@ static struct pci_device_id matroxfb_devices[] = { | |||
2118 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 2125 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
2119 | {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, | 2126 | {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, |
2120 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 2127 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
2128 | {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200EV_PCI, | ||
2129 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
2121 | {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_PCI, | 2130 | {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_PCI, |
2122 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 2131 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
2123 | {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, | 2132 | {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, |
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index 25172b2a2a94..bfb802d26d5a 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c | |||
@@ -426,11 +426,11 @@ static void vgaHWProtect(int on) | |||
426 | { | 426 | { |
427 | unsigned char tmp; | 427 | unsigned char tmp; |
428 | 428 | ||
429 | tmp = vga_rseq(NULL, 0x01); | ||
429 | if (on) { | 430 | if (on) { |
430 | /* | 431 | /* |
431 | * Turn off screen and disable sequencer. | 432 | * Turn off screen and disable sequencer. |
432 | */ | 433 | */ |
433 | tmp = vga_rseq(NULL, 0x01); | ||
434 | vga_wseq(NULL, 0x00, 0x01); /* Synchronous Reset */ | 434 | vga_wseq(NULL, 0x00, 0x01); /* Synchronous Reset */ |
435 | vga_wseq(NULL, 0x01, tmp | 0x20); /* disable the display */ | 435 | vga_wseq(NULL, 0x01, tmp | 0x20); /* disable the display */ |
436 | 436 | ||
@@ -439,7 +439,6 @@ static void vgaHWProtect(int on) | |||
439 | /* | 439 | /* |
440 | * Reenable sequencer, then turn on screen. | 440 | * Reenable sequencer, then turn on screen. |
441 | */ | 441 | */ |
442 | tmp = vga_rseq(NULL, 0x01); | ||
443 | vga_wseq(NULL, 0x01, tmp & ~0x20); /* reenable display */ | 442 | vga_wseq(NULL, 0x01, tmp & ~0x20); /* reenable display */ |
444 | vga_wseq(NULL, 0x00, 0x03); /* clear synchronousreset */ | 443 | vga_wseq(NULL, 0x00, 0x03); /* clear synchronousreset */ |
445 | 444 | ||
@@ -558,14 +557,12 @@ neofb_open(struct fb_info *info, int user) | |||
558 | { | 557 | { |
559 | struct neofb_par *par = info->par; | 558 | struct neofb_par *par = info->par; |
560 | 559 | ||
561 | mutex_lock(&par->open_lock); | ||
562 | if (!par->ref_count) { | 560 | if (!par->ref_count) { |
563 | memset(&par->state, 0, sizeof(struct vgastate)); | 561 | memset(&par->state, 0, sizeof(struct vgastate)); |
564 | par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS; | 562 | par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS; |
565 | save_vga(&par->state); | 563 | save_vga(&par->state); |
566 | } | 564 | } |
567 | par->ref_count++; | 565 | par->ref_count++; |
568 | mutex_unlock(&par->open_lock); | ||
569 | 566 | ||
570 | return 0; | 567 | return 0; |
571 | } | 568 | } |
@@ -575,16 +572,13 @@ neofb_release(struct fb_info *info, int user) | |||
575 | { | 572 | { |
576 | struct neofb_par *par = info->par; | 573 | struct neofb_par *par = info->par; |
577 | 574 | ||
578 | mutex_lock(&par->open_lock); | 575 | if (!par->ref_count) |
579 | if (!par->ref_count) { | ||
580 | mutex_unlock(&par->open_lock); | ||
581 | return -EINVAL; | 576 | return -EINVAL; |
582 | } | 577 | |
583 | if (par->ref_count == 1) { | 578 | if (par->ref_count == 1) { |
584 | restore_vga(&par->state); | 579 | restore_vga(&par->state); |
585 | } | 580 | } |
586 | par->ref_count--; | 581 | par->ref_count--; |
587 | mutex_unlock(&par->open_lock); | ||
588 | 582 | ||
589 | return 0; | 583 | return 0; |
590 | } | 584 | } |
@@ -648,10 +642,10 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
648 | var->blue.msb_right = 0; | 642 | var->blue.msb_right = 0; |
649 | var->transp.msb_right = 0; | 643 | var->transp.msb_right = 0; |
650 | 644 | ||
645 | var->transp.offset = 0; | ||
646 | var->transp.length = 0; | ||
651 | switch (var->bits_per_pixel) { | 647 | switch (var->bits_per_pixel) { |
652 | case 8: /* PSEUDOCOLOUR, 256 */ | 648 | case 8: /* PSEUDOCOLOUR, 256 */ |
653 | var->transp.offset = 0; | ||
654 | var->transp.length = 0; | ||
655 | var->red.offset = 0; | 649 | var->red.offset = 0; |
656 | var->red.length = 8; | 650 | var->red.length = 8; |
657 | var->green.offset = 0; | 651 | var->green.offset = 0; |
@@ -661,8 +655,6 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
661 | break; | 655 | break; |
662 | 656 | ||
663 | case 16: /* DIRECTCOLOUR, 64k */ | 657 | case 16: /* DIRECTCOLOUR, 64k */ |
664 | var->transp.offset = 0; | ||
665 | var->transp.length = 0; | ||
666 | var->red.offset = 11; | 658 | var->red.offset = 11; |
667 | var->red.length = 5; | 659 | var->red.length = 5; |
668 | var->green.offset = 5; | 660 | var->green.offset = 5; |
@@ -672,8 +664,6 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
672 | break; | 664 | break; |
673 | 665 | ||
674 | case 24: /* TRUECOLOUR, 16m */ | 666 | case 24: /* TRUECOLOUR, 16m */ |
675 | var->transp.offset = 0; | ||
676 | var->transp.length = 0; | ||
677 | var->red.offset = 16; | 667 | var->red.offset = 16; |
678 | var->red.length = 8; | 668 | var->red.length = 8; |
679 | var->green.offset = 8; | 669 | var->green.offset = 8; |
@@ -704,8 +694,6 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
704 | if (vramlen > 4 * 1024 * 1024) | 694 | if (vramlen > 4 * 1024 * 1024) |
705 | vramlen = 4 * 1024 * 1024; | 695 | vramlen = 4 * 1024 * 1024; |
706 | 696 | ||
707 | if (var->yres_virtual < var->yres) | ||
708 | var->yres_virtual = var->yres; | ||
709 | if (var->xres_virtual < var->xres) | 697 | if (var->xres_virtual < var->xres) |
710 | var->xres_virtual = var->xres; | 698 | var->xres_virtual = var->xres; |
711 | 699 | ||
@@ -722,8 +710,6 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
722 | if it was possible. We should return -EINVAL, but I disagree */ | 710 | if it was possible. We should return -EINVAL, but I disagree */ |
723 | if (var->yres_virtual < var->yres) | 711 | if (var->yres_virtual < var->yres) |
724 | var->yres = var->yres_virtual; | 712 | var->yres = var->yres_virtual; |
725 | if (var->xres_virtual < var->xres) | ||
726 | var->xres = var->xres_virtual; | ||
727 | if (var->xoffset + var->xres > var->xres_virtual) | 713 | if (var->xoffset + var->xres > var->xres_virtual) |
728 | var->xoffset = var->xres_virtual - var->xres; | 714 | var->xoffset = var->xres_virtual - var->xres; |
729 | if (var->yoffset + var->yres > var->yres_virtual) | 715 | if (var->yoffset + var->yres > var->yres_virtual) |
@@ -1186,8 +1172,11 @@ static int neofb_set_par(struct fb_info *info) | |||
1186 | return 0; | 1172 | return 0; |
1187 | } | 1173 | } |
1188 | 1174 | ||
1189 | static void neofb_update_start(struct fb_info *info, | 1175 | /* |
1190 | struct fb_var_screeninfo *var) | 1176 | * Pan or Wrap the Display |
1177 | */ | ||
1178 | static int neofb_pan_display(struct fb_var_screeninfo *var, | ||
1179 | struct fb_info *info) | ||
1191 | { | 1180 | { |
1192 | struct neofb_par *par = info->par; | 1181 | struct neofb_par *par = info->par; |
1193 | struct vgastate *state = &par->state; | 1182 | struct vgastate *state = &par->state; |
@@ -1216,35 +1205,7 @@ static void neofb_update_start(struct fb_info *info, | |||
1216 | vga_wgfx(state->vgabase, 0x0E, (((Base >> 16) & 0x0f) | (oldExtCRTDispAddr & 0xf0))); | 1205 | vga_wgfx(state->vgabase, 0x0E, (((Base >> 16) & 0x0f) | (oldExtCRTDispAddr & 0xf0))); |
1217 | 1206 | ||
1218 | neoLock(state); | 1207 | neoLock(state); |
1219 | } | ||
1220 | |||
1221 | /* | ||
1222 | * Pan or Wrap the Display | ||
1223 | */ | ||
1224 | static int neofb_pan_display(struct fb_var_screeninfo *var, | ||
1225 | struct fb_info *info) | ||
1226 | { | ||
1227 | u_int y_bottom; | ||
1228 | |||
1229 | y_bottom = var->yoffset; | ||
1230 | |||
1231 | if (!(var->vmode & FB_VMODE_YWRAP)) | ||
1232 | y_bottom += var->yres; | ||
1233 | 1208 | ||
1234 | if (var->xoffset > (var->xres_virtual - var->xres)) | ||
1235 | return -EINVAL; | ||
1236 | if (y_bottom > info->var.yres_virtual) | ||
1237 | return -EINVAL; | ||
1238 | |||
1239 | neofb_update_start(info, var); | ||
1240 | |||
1241 | info->var.xoffset = var->xoffset; | ||
1242 | info->var.yoffset = var->yoffset; | ||
1243 | |||
1244 | if (var->vmode & FB_VMODE_YWRAP) | ||
1245 | info->var.vmode |= FB_VMODE_YWRAP; | ||
1246 | else | ||
1247 | info->var.vmode &= ~FB_VMODE_YWRAP; | ||
1248 | return 0; | 1209 | return 0; |
1249 | } | 1210 | } |
1250 | 1211 | ||
@@ -1992,7 +1953,6 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st | |||
1992 | 1953 | ||
1993 | info->fix.accel = id->driver_data; | 1954 | info->fix.accel = id->driver_data; |
1994 | 1955 | ||
1995 | mutex_init(&par->open_lock); | ||
1996 | par->pci_burst = !nopciburst; | 1956 | par->pci_burst = !nopciburst; |
1997 | par->lcd_stretch = !nostretch; | 1957 | par->lcd_stretch = !nostretch; |
1998 | par->libretto = libretto; | 1958 | par->libretto = libretto; |
diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c index 6efcf89e7fbe..dfb72f5e4c96 100644 --- a/drivers/video/omap/dispc.c +++ b/drivers/video/omap/dispc.c | |||
@@ -156,7 +156,7 @@ struct resmap { | |||
156 | }; | 156 | }; |
157 | 157 | ||
158 | static struct { | 158 | static struct { |
159 | u32 base; | 159 | void __iomem *base; |
160 | 160 | ||
161 | struct omapfb_mem_desc mem_desc; | 161 | struct omapfb_mem_desc mem_desc; |
162 | struct resmap *res_map[DISPC_MEMTYPE_NUM]; | 162 | struct resmap *res_map[DISPC_MEMTYPE_NUM]; |
@@ -212,9 +212,9 @@ static void enable_rfbi_mode(int enable) | |||
212 | dispc_write_reg(DISPC_CONTROL, l); | 212 | dispc_write_reg(DISPC_CONTROL, l); |
213 | 213 | ||
214 | /* Set bypass mode in RFBI module */ | 214 | /* Set bypass mode in RFBI module */ |
215 | l = __raw_readl(io_p2v(RFBI_CONTROL)); | 215 | l = __raw_readl(IO_ADDRESS(RFBI_CONTROL)); |
216 | l |= enable ? 0 : (1 << 1); | 216 | l |= enable ? 0 : (1 << 1); |
217 | __raw_writel(l, io_p2v(RFBI_CONTROL)); | 217 | __raw_writel(l, IO_ADDRESS(RFBI_CONTROL)); |
218 | } | 218 | } |
219 | 219 | ||
220 | static void set_lcd_data_lines(int data_lines) | 220 | static void set_lcd_data_lines(int data_lines) |
@@ -1349,14 +1349,19 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode, | |||
1349 | 1349 | ||
1350 | memset(&dispc, 0, sizeof(dispc)); | 1350 | memset(&dispc, 0, sizeof(dispc)); |
1351 | 1351 | ||
1352 | dispc.base = io_p2v(DISPC_BASE); | 1352 | dispc.base = ioremap(DISPC_BASE, SZ_1K); |
1353 | if (!dispc.base) { | ||
1354 | dev_err(fbdev->dev, "can't ioremap DISPC\n"); | ||
1355 | return -ENOMEM; | ||
1356 | } | ||
1357 | |||
1353 | dispc.fbdev = fbdev; | 1358 | dispc.fbdev = fbdev; |
1354 | dispc.ext_mode = ext_mode; | 1359 | dispc.ext_mode = ext_mode; |
1355 | 1360 | ||
1356 | init_completion(&dispc.frame_done); | 1361 | init_completion(&dispc.frame_done); |
1357 | 1362 | ||
1358 | if ((r = get_dss_clocks()) < 0) | 1363 | if ((r = get_dss_clocks()) < 0) |
1359 | return r; | 1364 | goto fail0; |
1360 | 1365 | ||
1361 | enable_interface_clocks(1); | 1366 | enable_interface_clocks(1); |
1362 | enable_lcd_clocks(1); | 1367 | enable_lcd_clocks(1); |
@@ -1414,7 +1419,7 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode, | |||
1414 | } | 1419 | } |
1415 | 1420 | ||
1416 | /* L3 firewall setting: enable access to OCM RAM */ | 1421 | /* L3 firewall setting: enable access to OCM RAM */ |
1417 | __raw_writel(0x402000b0, io_p2v(0x680050a0)); | 1422 | __raw_writel(0x402000b0, IO_ADDRESS(0x680050a0)); |
1418 | 1423 | ||
1419 | if ((r = alloc_palette_ram()) < 0) | 1424 | if ((r = alloc_palette_ram()) < 0) |
1420 | goto fail2; | 1425 | goto fail2; |
@@ -1464,7 +1469,8 @@ fail1: | |||
1464 | enable_lcd_clocks(0); | 1469 | enable_lcd_clocks(0); |
1465 | enable_interface_clocks(0); | 1470 | enable_interface_clocks(0); |
1466 | put_dss_clocks(); | 1471 | put_dss_clocks(); |
1467 | 1472 | fail0: | |
1473 | iounmap(dispc.base); | ||
1468 | return r; | 1474 | return r; |
1469 | } | 1475 | } |
1470 | 1476 | ||
@@ -1481,6 +1487,7 @@ static void omap_dispc_cleanup(void) | |||
1481 | free_irq(INT_24XX_DSS_IRQ, dispc.fbdev); | 1487 | free_irq(INT_24XX_DSS_IRQ, dispc.fbdev); |
1482 | enable_interface_clocks(0); | 1488 | enable_interface_clocks(0); |
1483 | put_dss_clocks(); | 1489 | put_dss_clocks(); |
1490 | iounmap(dispc.base); | ||
1484 | } | 1491 | } |
1485 | 1492 | ||
1486 | const struct lcd_ctrl omap2_int_ctrl = { | 1493 | const struct lcd_ctrl omap2_int_ctrl = { |
diff --git a/drivers/video/omap/dispc.h b/drivers/video/omap/dispc.h index eb1512b56ce8..ef720a78f6d5 100644 --- a/drivers/video/omap/dispc.h +++ b/drivers/video/omap/dispc.h | |||
@@ -40,4 +40,6 @@ extern void omap_dispc_enable_digit_out(int enable); | |||
40 | extern int omap_dispc_request_irq(void (*callback)(void *data), void *data); | 40 | extern int omap_dispc_request_irq(void (*callback)(void *data), void *data); |
41 | extern void omap_dispc_free_irq(void); | 41 | extern void omap_dispc_free_irq(void); |
42 | 42 | ||
43 | extern const struct lcd_ctrl omap2_int_ctrl; | ||
44 | |||
43 | #endif | 45 | #endif |
diff --git a/drivers/video/omap/lcd_h4.c b/drivers/video/omap/lcd_h4.c index 88c19d424ef7..6ff56430341b 100644 --- a/drivers/video/omap/lcd_h4.c +++ b/drivers/video/omap/lcd_h4.c | |||
@@ -47,7 +47,7 @@ static unsigned long h4_panel_get_caps(struct lcd_panel *panel) | |||
47 | return 0; | 47 | return 0; |
48 | } | 48 | } |
49 | 49 | ||
50 | struct lcd_panel h4_panel = { | 50 | static struct lcd_panel h4_panel = { |
51 | .name = "h4", | 51 | .name = "h4", |
52 | .config = OMAP_LCDC_PANEL_TFT, | 52 | .config = OMAP_LCDC_PANEL_TFT, |
53 | 53 | ||
@@ -91,7 +91,7 @@ static int h4_panel_resume(struct platform_device *pdev) | |||
91 | return 0; | 91 | return 0; |
92 | } | 92 | } |
93 | 93 | ||
94 | struct platform_driver h4_panel_driver = { | 94 | static struct platform_driver h4_panel_driver = { |
95 | .probe = h4_panel_probe, | 95 | .probe = h4_panel_probe, |
96 | .remove = h4_panel_remove, | 96 | .remove = h4_panel_remove, |
97 | .suspend = h4_panel_suspend, | 97 | .suspend = h4_panel_suspend, |
diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c index 6a42c6a0cd99..4c4f7ee6d733 100644 --- a/drivers/video/omap/lcd_inn1610.c +++ b/drivers/video/omap/lcd_inn1610.c | |||
@@ -32,43 +32,43 @@ static int innovator1610_panel_init(struct lcd_panel *panel, | |||
32 | { | 32 | { |
33 | int r = 0; | 33 | int r = 0; |
34 | 34 | ||
35 | if (omap_request_gpio(14)) { | 35 | if (gpio_request(14, "lcd_en0")) { |
36 | pr_err(MODULE_NAME ": can't request GPIO 14\n"); | 36 | pr_err(MODULE_NAME ": can't request GPIO 14\n"); |
37 | r = -1; | 37 | r = -1; |
38 | goto exit; | 38 | goto exit; |
39 | } | 39 | } |
40 | if (omap_request_gpio(15)) { | 40 | if (gpio_request(15, "lcd_en1")) { |
41 | pr_err(MODULE_NAME ": can't request GPIO 15\n"); | 41 | pr_err(MODULE_NAME ": can't request GPIO 15\n"); |
42 | omap_free_gpio(14); | 42 | gpio_free(14); |
43 | r = -1; | 43 | r = -1; |
44 | goto exit; | 44 | goto exit; |
45 | } | 45 | } |
46 | /* configure GPIO(14, 15) as outputs */ | 46 | /* configure GPIO(14, 15) as outputs */ |
47 | omap_set_gpio_direction(14, 0); | 47 | gpio_direction_output(14, 0); |
48 | omap_set_gpio_direction(15, 0); | 48 | gpio_direction_output(15, 0); |
49 | exit: | 49 | exit: |
50 | return r; | 50 | return r; |
51 | } | 51 | } |
52 | 52 | ||
53 | static void innovator1610_panel_cleanup(struct lcd_panel *panel) | 53 | static void innovator1610_panel_cleanup(struct lcd_panel *panel) |
54 | { | 54 | { |
55 | omap_free_gpio(15); | 55 | gpio_free(15); |
56 | omap_free_gpio(14); | 56 | gpio_free(14); |
57 | } | 57 | } |
58 | 58 | ||
59 | static int innovator1610_panel_enable(struct lcd_panel *panel) | 59 | static int innovator1610_panel_enable(struct lcd_panel *panel) |
60 | { | 60 | { |
61 | /* set GPIO14 and GPIO15 high */ | 61 | /* set GPIO14 and GPIO15 high */ |
62 | omap_set_gpio_dataout(14, 1); | 62 | gpio_set_value(14, 1); |
63 | omap_set_gpio_dataout(15, 1); | 63 | gpio_set_value(15, 1); |
64 | return 0; | 64 | return 0; |
65 | } | 65 | } |
66 | 66 | ||
67 | static void innovator1610_panel_disable(struct lcd_panel *panel) | 67 | static void innovator1610_panel_disable(struct lcd_panel *panel) |
68 | { | 68 | { |
69 | /* set GPIO13, GPIO14 and GPIO15 low */ | 69 | /* set GPIO13, GPIO14 and GPIO15 low */ |
70 | omap_set_gpio_dataout(14, 0); | 70 | gpio_set_value(14, 0); |
71 | omap_set_gpio_dataout(15, 0); | 71 | gpio_set_value(15, 0); |
72 | } | 72 | } |
73 | 73 | ||
74 | static unsigned long innovator1610_panel_get_caps(struct lcd_panel *panel) | 74 | static unsigned long innovator1610_panel_get_caps(struct lcd_panel *panel) |
diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/omap/lcd_osk.c index a4a725f427a4..379c96d36da5 100644 --- a/drivers/video/omap/lcd_osk.c +++ b/drivers/video/omap/lcd_osk.c | |||
@@ -29,6 +29,7 @@ | |||
29 | 29 | ||
30 | static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) | 30 | static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) |
31 | { | 31 | { |
32 | /* gpio2 was allocated in board init */ | ||
32 | return 0; | 33 | return 0; |
33 | } | 34 | } |
34 | 35 | ||
@@ -47,11 +48,8 @@ static int osk_panel_enable(struct lcd_panel *panel) | |||
47 | /* Set PWL level */ | 48 | /* Set PWL level */ |
48 | omap_writeb(0xFF, OMAP_PWL_ENABLE); | 49 | omap_writeb(0xFF, OMAP_PWL_ENABLE); |
49 | 50 | ||
50 | /* configure GPIO2 as output */ | 51 | /* set GPIO2 high (lcd power enabled) */ |
51 | omap_set_gpio_direction(2, 0); | 52 | gpio_set_value(2, 1); |
52 | |||
53 | /* set GPIO2 high */ | ||
54 | omap_set_gpio_dataout(2, 1); | ||
55 | 53 | ||
56 | return 0; | 54 | return 0; |
57 | } | 55 | } |
@@ -65,7 +63,7 @@ static void osk_panel_disable(struct lcd_panel *panel) | |||
65 | omap_writeb(0x00, OMAP_PWL_CLK_ENABLE); | 63 | omap_writeb(0x00, OMAP_PWL_CLK_ENABLE); |
66 | 64 | ||
67 | /* set GPIO2 low */ | 65 | /* set GPIO2 low */ |
68 | omap_set_gpio_dataout(2, 0); | 66 | gpio_set_value(2, 0); |
69 | } | 67 | } |
70 | 68 | ||
71 | static unsigned long osk_panel_get_caps(struct lcd_panel *panel) | 69 | static unsigned long osk_panel_get_caps(struct lcd_panel *panel) |
diff --git a/drivers/video/omap/lcd_sx1.c b/drivers/video/omap/lcd_sx1.c index caa6a896cb8b..e55de201b8ff 100644 --- a/drivers/video/omap/lcd_sx1.c +++ b/drivers/video/omap/lcd_sx1.c | |||
@@ -81,21 +81,21 @@ static void epson_sendbyte(int flag, unsigned char byte) | |||
81 | int i, shifter = 0x80; | 81 | int i, shifter = 0x80; |
82 | 82 | ||
83 | if (!flag) | 83 | if (!flag) |
84 | omap_set_gpio_dataout(_A_LCD_SSC_A0, 0); | 84 | gpio_set_value(_A_LCD_SSC_A0, 0); |
85 | mdelay(2); | 85 | mdelay(2); |
86 | omap_set_gpio_dataout(A_LCD_SSC_RD, 1); | 86 | gpio_set_value(A_LCD_SSC_RD, 1); |
87 | 87 | ||
88 | omap_set_gpio_dataout(A_LCD_SSC_SD, flag); | 88 | gpio_set_value(A_LCD_SSC_SD, flag); |
89 | 89 | ||
90 | OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200); | 90 | OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200); |
91 | OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202); | 91 | OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202); |
92 | for (i = 0; i < 8; i++) { | 92 | for (i = 0; i < 8; i++) { |
93 | OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200); | 93 | OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200); |
94 | omap_set_gpio_dataout(A_LCD_SSC_SD, shifter & byte); | 94 | gpio_set_value(A_LCD_SSC_SD, shifter & byte); |
95 | OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202); | 95 | OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202); |
96 | shifter >>= 1; | 96 | shifter >>= 1; |
97 | } | 97 | } |
98 | omap_set_gpio_dataout(_A_LCD_SSC_A0, 1); | 98 | gpio_set_value(_A_LCD_SSC_A0, 1); |
99 | } | 99 | } |
100 | 100 | ||
101 | static void init_system(void) | 101 | static void init_system(void) |
@@ -107,25 +107,18 @@ static void init_system(void) | |||
107 | static void setup_GPIO(void) | 107 | static void setup_GPIO(void) |
108 | { | 108 | { |
109 | /* new wave */ | 109 | /* new wave */ |
110 | omap_request_gpio(A_LCD_SSC_RD); | 110 | gpio_request(A_LCD_SSC_RD, "lcd_ssc_rd"); |
111 | omap_request_gpio(A_LCD_SSC_SD); | 111 | gpio_request(A_LCD_SSC_SD, "lcd_ssc_sd"); |
112 | omap_request_gpio(_A_LCD_RESET); | 112 | gpio_request(_A_LCD_RESET, "lcd_reset"); |
113 | omap_request_gpio(_A_LCD_SSC_CS); | 113 | gpio_request(_A_LCD_SSC_CS, "lcd_ssc_cs"); |
114 | omap_request_gpio(_A_LCD_SSC_A0); | 114 | gpio_request(_A_LCD_SSC_A0, "lcd_ssc_a0"); |
115 | 115 | ||
116 | /* set all GPIOs to output */ | 116 | /* set GPIOs to output, with initial data */ |
117 | omap_set_gpio_direction(A_LCD_SSC_RD, 0); | 117 | gpio_direction_output(A_LCD_SSC_RD, 1); |
118 | omap_set_gpio_direction(A_LCD_SSC_SD, 0); | 118 | gpio_direction_output(A_LCD_SSC_SD, 0); |
119 | omap_set_gpio_direction(_A_LCD_RESET, 0); | 119 | gpio_direction_output(_A_LCD_RESET, 0); |
120 | omap_set_gpio_direction(_A_LCD_SSC_CS, 0); | 120 | gpio_direction_output(_A_LCD_SSC_CS, 1); |
121 | omap_set_gpio_direction(_A_LCD_SSC_A0, 0); | 121 | gpio_direction_output(_A_LCD_SSC_A0, 1); |
122 | |||
123 | /* set GPIO data */ | ||
124 | omap_set_gpio_dataout(A_LCD_SSC_RD, 1); | ||
125 | omap_set_gpio_dataout(A_LCD_SSC_SD, 0); | ||
126 | omap_set_gpio_dataout(_A_LCD_RESET, 0); | ||
127 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); | ||
128 | omap_set_gpio_dataout(_A_LCD_SSC_A0, 1); | ||
129 | } | 122 | } |
130 | 123 | ||
131 | static void display_init(void) | 124 | static void display_init(void) |
@@ -139,61 +132,61 @@ static void display_init(void) | |||
139 | mdelay(2); | 132 | mdelay(2); |
140 | 133 | ||
141 | /* reset LCD */ | 134 | /* reset LCD */ |
142 | omap_set_gpio_dataout(A_LCD_SSC_SD, 1); | 135 | gpio_set_value(A_LCD_SSC_SD, 1); |
143 | epson_sendbyte(0, 0x25); | 136 | epson_sendbyte(0, 0x25); |
144 | 137 | ||
145 | omap_set_gpio_dataout(_A_LCD_RESET, 0); | 138 | gpio_set_value(_A_LCD_RESET, 0); |
146 | mdelay(10); | 139 | mdelay(10); |
147 | omap_set_gpio_dataout(_A_LCD_RESET, 1); | 140 | gpio_set_value(_A_LCD_RESET, 1); |
148 | 141 | ||
149 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); | 142 | gpio_set_value(_A_LCD_SSC_CS, 1); |
150 | mdelay(2); | 143 | mdelay(2); |
151 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 0); | 144 | gpio_set_value(_A_LCD_SSC_CS, 0); |
152 | 145 | ||
153 | /* init LCD, phase 1 */ | 146 | /* init LCD, phase 1 */ |
154 | epson_sendbyte(0, 0xCA); | 147 | epson_sendbyte(0, 0xCA); |
155 | for (i = 0; i < 10; i++) | 148 | for (i = 0; i < 10; i++) |
156 | epson_sendbyte(1, INIT_1[i]); | 149 | epson_sendbyte(1, INIT_1[i]); |
157 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); | 150 | gpio_set_value(_A_LCD_SSC_CS, 1); |
158 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 0); | 151 | gpio_set_value(_A_LCD_SSC_CS, 0); |
159 | 152 | ||
160 | /* init LCD phase 2 */ | 153 | /* init LCD phase 2 */ |
161 | epson_sendbyte(0, 0xCB); | 154 | epson_sendbyte(0, 0xCB); |
162 | for (i = 0; i < 125; i++) | 155 | for (i = 0; i < 125; i++) |
163 | epson_sendbyte(1, INIT_2[i]); | 156 | epson_sendbyte(1, INIT_2[i]); |
164 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); | 157 | gpio_set_value(_A_LCD_SSC_CS, 1); |
165 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 0); | 158 | gpio_set_value(_A_LCD_SSC_CS, 0); |
166 | 159 | ||
167 | /* init LCD phase 2a */ | 160 | /* init LCD phase 2a */ |
168 | epson_sendbyte(0, 0xCC); | 161 | epson_sendbyte(0, 0xCC); |
169 | for (i = 0; i < 14; i++) | 162 | for (i = 0; i < 14; i++) |
170 | epson_sendbyte(1, INIT_3[i]); | 163 | epson_sendbyte(1, INIT_3[i]); |
171 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); | 164 | gpio_set_value(_A_LCD_SSC_CS, 1); |
172 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 0); | 165 | gpio_set_value(_A_LCD_SSC_CS, 0); |
173 | 166 | ||
174 | /* init LCD phase 3 */ | 167 | /* init LCD phase 3 */ |
175 | epson_sendbyte(0, 0xBC); | 168 | epson_sendbyte(0, 0xBC); |
176 | epson_sendbyte(1, 0x08); | 169 | epson_sendbyte(1, 0x08); |
177 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); | 170 | gpio_set_value(_A_LCD_SSC_CS, 1); |
178 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 0); | 171 | gpio_set_value(_A_LCD_SSC_CS, 0); |
179 | 172 | ||
180 | /* init LCD phase 4 */ | 173 | /* init LCD phase 4 */ |
181 | epson_sendbyte(0, 0x07); | 174 | epson_sendbyte(0, 0x07); |
182 | epson_sendbyte(1, 0x05); | 175 | epson_sendbyte(1, 0x05); |
183 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); | 176 | gpio_set_value(_A_LCD_SSC_CS, 1); |
184 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 0); | 177 | gpio_set_value(_A_LCD_SSC_CS, 0); |
185 | 178 | ||
186 | /* init LCD phase 5 */ | 179 | /* init LCD phase 5 */ |
187 | epson_sendbyte(0, 0x94); | 180 | epson_sendbyte(0, 0x94); |
188 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); | 181 | gpio_set_value(_A_LCD_SSC_CS, 1); |
189 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 0); | 182 | gpio_set_value(_A_LCD_SSC_CS, 0); |
190 | 183 | ||
191 | /* init LCD phase 6 */ | 184 | /* init LCD phase 6 */ |
192 | epson_sendbyte(0, 0xC6); | 185 | epson_sendbyte(0, 0xC6); |
193 | epson_sendbyte(1, 0x80); | 186 | epson_sendbyte(1, 0x80); |
194 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); | 187 | gpio_set_value(_A_LCD_SSC_CS, 1); |
195 | mdelay(100); /* used to be 1000 */ | 188 | mdelay(100); /* used to be 1000 */ |
196 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 0); | 189 | gpio_set_value(_A_LCD_SSC_CS, 0); |
197 | 190 | ||
198 | /* init LCD phase 7 */ | 191 | /* init LCD phase 7 */ |
199 | epson_sendbyte(0, 0x16); | 192 | epson_sendbyte(0, 0x16); |
@@ -201,8 +194,8 @@ static void display_init(void) | |||
201 | epson_sendbyte(1, 0x00); | 194 | epson_sendbyte(1, 0x00); |
202 | epson_sendbyte(1, 0xB1); | 195 | epson_sendbyte(1, 0xB1); |
203 | epson_sendbyte(1, 0x00); | 196 | epson_sendbyte(1, 0x00); |
204 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); | 197 | gpio_set_value(_A_LCD_SSC_CS, 1); |
205 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 0); | 198 | gpio_set_value(_A_LCD_SSC_CS, 0); |
206 | 199 | ||
207 | /* init LCD phase 8 */ | 200 | /* init LCD phase 8 */ |
208 | epson_sendbyte(0, 0x76); | 201 | epson_sendbyte(0, 0x76); |
@@ -210,12 +203,12 @@ static void display_init(void) | |||
210 | epson_sendbyte(1, 0x00); | 203 | epson_sendbyte(1, 0x00); |
211 | epson_sendbyte(1, 0xDB); | 204 | epson_sendbyte(1, 0xDB); |
212 | epson_sendbyte(1, 0x00); | 205 | epson_sendbyte(1, 0x00); |
213 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); | 206 | gpio_set_value(_A_LCD_SSC_CS, 1); |
214 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 0); | 207 | gpio_set_value(_A_LCD_SSC_CS, 0); |
215 | 208 | ||
216 | /* init LCD phase 9 */ | 209 | /* init LCD phase 9 */ |
217 | epson_sendbyte(0, 0xAF); | 210 | epson_sendbyte(0, 0xAF); |
218 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); | 211 | gpio_set_value(_A_LCD_SSC_CS, 1); |
219 | } | 212 | } |
220 | 213 | ||
221 | static int sx1_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) | 214 | static int sx1_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) |
@@ -231,18 +224,18 @@ static void sx1_panel_disable(struct lcd_panel *panel) | |||
231 | { | 224 | { |
232 | printk(KERN_INFO "SX1: LCD panel disable\n"); | 225 | printk(KERN_INFO "SX1: LCD panel disable\n"); |
233 | sx1_setmmipower(0); | 226 | sx1_setmmipower(0); |
234 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); | 227 | gpio_set_value(_A_LCD_SSC_CS, 1); |
235 | 228 | ||
236 | epson_sendbyte(0, 0x25); | 229 | epson_sendbyte(0, 0x25); |
237 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 0); | 230 | gpio_set_value(_A_LCD_SSC_CS, 0); |
238 | 231 | ||
239 | epson_sendbyte(0, 0xAE); | 232 | epson_sendbyte(0, 0xAE); |
240 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); | 233 | gpio_set_value(_A_LCD_SSC_CS, 1); |
241 | mdelay(100); | 234 | mdelay(100); |
242 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 0); | 235 | gpio_set_value(_A_LCD_SSC_CS, 0); |
243 | 236 | ||
244 | epson_sendbyte(0, 0x95); | 237 | epson_sendbyte(0, 0x95); |
245 | omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); | 238 | gpio_set_value(_A_LCD_SSC_CS, 1); |
246 | } | 239 | } |
247 | 240 | ||
248 | static int sx1_panel_enable(struct lcd_panel *panel) | 241 | static int sx1_panel_enable(struct lcd_panel *panel) |
diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c index 83514f066712..6e2ea7518761 100644 --- a/drivers/video/omap/lcdc.c +++ b/drivers/video/omap/lcdc.c | |||
@@ -34,6 +34,8 @@ | |||
34 | 34 | ||
35 | #include <asm/mach-types.h> | 35 | #include <asm/mach-types.h> |
36 | 36 | ||
37 | #include "lcdc.h" | ||
38 | |||
37 | #define MODULE_NAME "lcdc" | 39 | #define MODULE_NAME "lcdc" |
38 | 40 | ||
39 | #define OMAP_LCDC_BASE 0xfffec000 | 41 | #define OMAP_LCDC_BASE 0xfffec000 |
diff --git a/drivers/video/omap/lcdc.h b/drivers/video/omap/lcdc.h index adb731e5314a..845222270db3 100644 --- a/drivers/video/omap/lcdc.h +++ b/drivers/video/omap/lcdc.h | |||
@@ -4,4 +4,6 @@ | |||
4 | int omap_lcdc_set_dma_callback(void (*callback)(void *data), void *data); | 4 | int omap_lcdc_set_dma_callback(void (*callback)(void *data), void *data); |
5 | void omap_lcdc_free_dma_callback(void); | 5 | void omap_lcdc_free_dma_callback(void); |
6 | 6 | ||
7 | extern const struct lcd_ctrl omap1_int_ctrl; | ||
8 | |||
7 | #endif | 9 | #endif |
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c index 51a138bd113c..5a5e407dc45f 100644 --- a/drivers/video/omap/omapfb_main.c +++ b/drivers/video/omap/omapfb_main.c | |||
@@ -31,11 +31,14 @@ | |||
31 | #include <mach/dma.h> | 31 | #include <mach/dma.h> |
32 | #include <mach/omapfb.h> | 32 | #include <mach/omapfb.h> |
33 | 33 | ||
34 | #include "lcdc.h" | ||
35 | #include "dispc.h" | ||
36 | |||
34 | #define MODULE_NAME "omapfb" | 37 | #define MODULE_NAME "omapfb" |
35 | 38 | ||
36 | static unsigned int def_accel; | 39 | static unsigned int def_accel; |
37 | static unsigned long def_vram[OMAPFB_PLANE_NUM]; | 40 | static unsigned long def_vram[OMAPFB_PLANE_NUM]; |
38 | static int def_vram_cnt; | 41 | static unsigned int def_vram_cnt; |
39 | static unsigned long def_vxres; | 42 | static unsigned long def_vxres; |
40 | static unsigned long def_vyres; | 43 | static unsigned long def_vyres; |
41 | static unsigned int def_rotate; | 44 | static unsigned int def_rotate; |
@@ -84,12 +87,10 @@ static struct caps_table_struct color_caps[] = { | |||
84 | * LCD panel | 87 | * LCD panel |
85 | * --------------------------------------------------------------------------- | 88 | * --------------------------------------------------------------------------- |
86 | */ | 89 | */ |
87 | extern struct lcd_ctrl omap1_int_ctrl; | ||
88 | extern struct lcd_ctrl omap2_int_ctrl; | ||
89 | extern struct lcd_ctrl hwa742_ctrl; | 90 | extern struct lcd_ctrl hwa742_ctrl; |
90 | extern struct lcd_ctrl blizzard_ctrl; | 91 | extern struct lcd_ctrl blizzard_ctrl; |
91 | 92 | ||
92 | static struct lcd_ctrl *ctrls[] = { | 93 | static const struct lcd_ctrl *ctrls[] = { |
93 | #ifdef CONFIG_ARCH_OMAP1 | 94 | #ifdef CONFIG_ARCH_OMAP1 |
94 | &omap1_int_ctrl, | 95 | &omap1_int_ctrl, |
95 | #else | 96 | #else |
@@ -740,7 +741,7 @@ static int omapfb_update_win(struct fb_info *fbi, | |||
740 | int ret; | 741 | int ret; |
741 | 742 | ||
742 | omapfb_rqueue_lock(plane->fbdev); | 743 | omapfb_rqueue_lock(plane->fbdev); |
743 | ret = omapfb_update_window_async(fbi, win, NULL, 0); | 744 | ret = omapfb_update_window_async(fbi, win, NULL, NULL); |
744 | omapfb_rqueue_unlock(plane->fbdev); | 745 | omapfb_rqueue_unlock(plane->fbdev); |
745 | 746 | ||
746 | return ret; | 747 | return ret; |
@@ -768,7 +769,7 @@ static int omapfb_update_full_screen(struct fb_info *fbi) | |||
768 | win.format = 0; | 769 | win.format = 0; |
769 | 770 | ||
770 | omapfb_rqueue_lock(fbdev); | 771 | omapfb_rqueue_lock(fbdev); |
771 | r = fbdev->ctrl->update_window(fbi, &win, NULL, 0); | 772 | r = fbdev->ctrl->update_window(fbi, &win, NULL, NULL); |
772 | omapfb_rqueue_unlock(fbdev); | 773 | omapfb_rqueue_unlock(fbdev); |
773 | 774 | ||
774 | return r; | 775 | return r; |
@@ -1047,7 +1048,7 @@ void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval) | |||
1047 | win.height = 2; | 1048 | win.height = 2; |
1048 | win.out_width = 2; | 1049 | win.out_width = 2; |
1049 | win.out_height = 2; | 1050 | win.out_height = 2; |
1050 | fbdev->ctrl->update_window(fbdev->fb_info[0], &win, NULL, 0); | 1051 | fbdev->ctrl->update_window(fbdev->fb_info[0], &win, NULL, NULL); |
1051 | } | 1052 | } |
1052 | omapfb_rqueue_unlock(fbdev); | 1053 | omapfb_rqueue_unlock(fbdev); |
1053 | } | 1054 | } |
diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c index 4a6f13d3facf..a13c8dcad2a8 100644 --- a/drivers/video/omap/rfbi.c +++ b/drivers/video/omap/rfbi.c | |||
@@ -59,7 +59,7 @@ | |||
59 | #define DISPC_CONTROL 0x0040 | 59 | #define DISPC_CONTROL 0x0040 |
60 | 60 | ||
61 | static struct { | 61 | static struct { |
62 | u32 base; | 62 | void __iomem *base; |
63 | void (*lcdc_callback)(void *data); | 63 | void (*lcdc_callback)(void *data); |
64 | void *lcdc_callback_data; | 64 | void *lcdc_callback_data; |
65 | unsigned long l4_khz; | 65 | unsigned long l4_khz; |
@@ -518,7 +518,11 @@ static int rfbi_init(struct omapfb_device *fbdev) | |||
518 | int r; | 518 | int r; |
519 | 519 | ||
520 | rfbi.fbdev = fbdev; | 520 | rfbi.fbdev = fbdev; |
521 | rfbi.base = io_p2v(RFBI_BASE); | 521 | rfbi.base = ioremap(RFBI_BASE, SZ_1K); |
522 | if (!rfbi.base) { | ||
523 | dev_err(fbdev->dev, "can't ioremap RFBI\n"); | ||
524 | return -ENOMEM; | ||
525 | } | ||
522 | 526 | ||
523 | if ((r = rfbi_get_clocks()) < 0) | 527 | if ((r = rfbi_get_clocks()) < 0) |
524 | return r; | 528 | return r; |
@@ -566,6 +570,7 @@ static void rfbi_cleanup(void) | |||
566 | { | 570 | { |
567 | omap_dispc_free_irq(); | 571 | omap_dispc_free_irq(); |
568 | rfbi_put_clocks(); | 572 | rfbi_put_clocks(); |
573 | iounmap(rfbi.base); | ||
569 | } | 574 | } |
570 | 575 | ||
571 | const struct lcd_ctrl_extif omap2_ext_if = { | 576 | const struct lcd_ctrl_extif omap2_ext_if = { |
diff --git a/drivers/video/omap/sossi.c b/drivers/video/omap/sossi.c index 6359353c2c67..a76946220249 100644 --- a/drivers/video/omap/sossi.c +++ b/drivers/video/omap/sossi.c | |||
@@ -574,7 +574,12 @@ static int sossi_init(struct omapfb_device *fbdev) | |||
574 | struct clk *dpll1out_ck; | 574 | struct clk *dpll1out_ck; |
575 | int r; | 575 | int r; |
576 | 576 | ||
577 | sossi.base = (void __iomem *)IO_ADDRESS(OMAP_SOSSI_BASE); | 577 | sossi.base = ioremap(OMAP_SOSSI_BASE, SZ_1K); |
578 | if (!sossi.base) { | ||
579 | dev_err(fbdev->dev, "can't ioremap SoSSI\n"); | ||
580 | return -ENOMEM; | ||
581 | } | ||
582 | |||
578 | sossi.fbdev = fbdev; | 583 | sossi.fbdev = fbdev; |
579 | spin_lock_init(&sossi.lock); | 584 | spin_lock_init(&sossi.lock); |
580 | 585 | ||
@@ -665,6 +670,7 @@ static void sossi_cleanup(void) | |||
665 | { | 670 | { |
666 | omap_lcdc_free_dma_callback(); | 671 | omap_lcdc_free_dma_callback(); |
667 | clk_put(sossi.fck); | 672 | clk_put(sossi.fck); |
673 | iounmap(sossi.base); | ||
668 | } | 674 | } |
669 | 675 | ||
670 | struct lcd_ctrl_extif omap1_ext_if = { | 676 | struct lcd_ctrl_extif omap1_ext_if = { |
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c index b829dc7c5edf..a7b01d2724b5 100644 --- a/drivers/video/s1d13xxxfb.c +++ b/drivers/video/s1d13xxxfb.c | |||
@@ -50,6 +50,11 @@ | |||
50 | #define dbg(fmt, args...) do { } while (0) | 50 | #define dbg(fmt, args...) do { } while (0) |
51 | #endif | 51 | #endif |
52 | 52 | ||
53 | static const int __devinitconst s1d13xxxfb_revisions[] = { | ||
54 | S1D13506_CHIP_REV, /* Rev.4 on HP Jornada 7xx S1D13506 */ | ||
55 | S1D13806_CHIP_REV, /* Rev.7 on .. */ | ||
56 | }; | ||
57 | |||
53 | /* | 58 | /* |
54 | * Here we define the default struct fb_fix_screeninfo | 59 | * Here we define the default struct fb_fix_screeninfo |
55 | */ | 60 | */ |
@@ -538,6 +543,7 @@ s1d13xxxfb_probe(struct platform_device *pdev) | |||
538 | struct fb_info *info; | 543 | struct fb_info *info; |
539 | struct s1d13xxxfb_pdata *pdata = NULL; | 544 | struct s1d13xxxfb_pdata *pdata = NULL; |
540 | int ret = 0; | 545 | int ret = 0; |
546 | int i; | ||
541 | u8 revision; | 547 | u8 revision; |
542 | 548 | ||
543 | dbg("probe called: device is %p\n", pdev); | 549 | dbg("probe called: device is %p\n", pdev); |
@@ -607,10 +613,19 @@ s1d13xxxfb_probe(struct platform_device *pdev) | |||
607 | goto bail; | 613 | goto bail; |
608 | } | 614 | } |
609 | 615 | ||
610 | revision = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE); | 616 | revision = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE) >> 2; |
611 | if ((revision >> 2) != S1D_CHIP_REV) { | 617 | |
612 | printk(KERN_INFO PFX "chip not found: %i\n", (revision >> 2)); | 618 | ret = -ENODEV; |
613 | ret = -ENODEV; | 619 | |
620 | for (i = 0; i < ARRAY_SIZE(s1d13xxxfb_revisions); i++) { | ||
621 | if (revision == s1d13xxxfb_revisions[i]) | ||
622 | ret = 0; | ||
623 | } | ||
624 | |||
625 | if (!ret) | ||
626 | printk(KERN_INFO PFX "chip revision %i\n", revision); | ||
627 | else { | ||
628 | printk(KERN_INFO PFX "unknown chip revision %i\n", revision); | ||
614 | goto bail; | 629 | goto bail; |
615 | } | 630 | } |
616 | 631 | ||
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c index 4599a4385bc9..14bd3f3680b8 100644 --- a/drivers/video/tdfxfb.c +++ b/drivers/video/tdfxfb.c | |||
@@ -1195,57 +1195,58 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev, | |||
1195 | return -ENOMEM; | 1195 | return -ENOMEM; |
1196 | 1196 | ||
1197 | default_par = info->par; | 1197 | default_par = info->par; |
1198 | info->fix = tdfx_fix; | ||
1198 | 1199 | ||
1199 | /* Configure the default fb_fix_screeninfo first */ | 1200 | /* Configure the default fb_fix_screeninfo first */ |
1200 | switch (pdev->device) { | 1201 | switch (pdev->device) { |
1201 | case PCI_DEVICE_ID_3DFX_BANSHEE: | 1202 | case PCI_DEVICE_ID_3DFX_BANSHEE: |
1202 | strcpy(tdfx_fix.id, "3Dfx Banshee"); | 1203 | strcpy(info->fix.id, "3Dfx Banshee"); |
1203 | default_par->max_pixclock = BANSHEE_MAX_PIXCLOCK; | 1204 | default_par->max_pixclock = BANSHEE_MAX_PIXCLOCK; |
1204 | break; | 1205 | break; |
1205 | case PCI_DEVICE_ID_3DFX_VOODOO3: | 1206 | case PCI_DEVICE_ID_3DFX_VOODOO3: |
1206 | strcpy(tdfx_fix.id, "3Dfx Voodoo3"); | 1207 | strcpy(info->fix.id, "3Dfx Voodoo3"); |
1207 | default_par->max_pixclock = VOODOO3_MAX_PIXCLOCK; | 1208 | default_par->max_pixclock = VOODOO3_MAX_PIXCLOCK; |
1208 | break; | 1209 | break; |
1209 | case PCI_DEVICE_ID_3DFX_VOODOO5: | 1210 | case PCI_DEVICE_ID_3DFX_VOODOO5: |
1210 | strcpy(tdfx_fix.id, "3Dfx Voodoo5"); | 1211 | strcpy(info->fix.id, "3Dfx Voodoo5"); |
1211 | default_par->max_pixclock = VOODOO5_MAX_PIXCLOCK; | 1212 | default_par->max_pixclock = VOODOO5_MAX_PIXCLOCK; |
1212 | break; | 1213 | break; |
1213 | } | 1214 | } |
1214 | 1215 | ||
1215 | tdfx_fix.mmio_start = pci_resource_start(pdev, 0); | 1216 | info->fix.mmio_start = pci_resource_start(pdev, 0); |
1216 | tdfx_fix.mmio_len = pci_resource_len(pdev, 0); | 1217 | info->fix.mmio_len = pci_resource_len(pdev, 0); |
1217 | if (!request_mem_region(tdfx_fix.mmio_start, tdfx_fix.mmio_len, | 1218 | if (!request_mem_region(info->fix.mmio_start, info->fix.mmio_len, |
1218 | "tdfx regbase")) { | 1219 | "tdfx regbase")) { |
1219 | printk(KERN_ERR "tdfxfb: Can't reserve regbase\n"); | 1220 | printk(KERN_ERR "tdfxfb: Can't reserve regbase\n"); |
1220 | goto out_err; | 1221 | goto out_err; |
1221 | } | 1222 | } |
1222 | 1223 | ||
1223 | default_par->regbase_virt = | 1224 | default_par->regbase_virt = |
1224 | ioremap_nocache(tdfx_fix.mmio_start, tdfx_fix.mmio_len); | 1225 | ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len); |
1225 | if (!default_par->regbase_virt) { | 1226 | if (!default_par->regbase_virt) { |
1226 | printk(KERN_ERR "fb: Can't remap %s register area.\n", | 1227 | printk(KERN_ERR "fb: Can't remap %s register area.\n", |
1227 | tdfx_fix.id); | 1228 | info->fix.id); |
1228 | goto out_err_regbase; | 1229 | goto out_err_regbase; |
1229 | } | 1230 | } |
1230 | 1231 | ||
1231 | tdfx_fix.smem_start = pci_resource_start(pdev, 1); | 1232 | info->fix.smem_start = pci_resource_start(pdev, 1); |
1232 | tdfx_fix.smem_len = do_lfb_size(default_par, pdev->device); | 1233 | info->fix.smem_len = do_lfb_size(default_par, pdev->device); |
1233 | if (!tdfx_fix.smem_len) { | 1234 | if (!info->fix.smem_len) { |
1234 | printk(KERN_ERR "fb: Can't count %s memory.\n", tdfx_fix.id); | 1235 | printk(KERN_ERR "fb: Can't count %s memory.\n", info->fix.id); |
1235 | goto out_err_regbase; | 1236 | goto out_err_regbase; |
1236 | } | 1237 | } |
1237 | 1238 | ||
1238 | if (!request_mem_region(tdfx_fix.smem_start, | 1239 | if (!request_mem_region(info->fix.smem_start, |
1239 | pci_resource_len(pdev, 1), "tdfx smem")) { | 1240 | pci_resource_len(pdev, 1), "tdfx smem")) { |
1240 | printk(KERN_ERR "tdfxfb: Can't reserve smem\n"); | 1241 | printk(KERN_ERR "tdfxfb: Can't reserve smem\n"); |
1241 | goto out_err_regbase; | 1242 | goto out_err_regbase; |
1242 | } | 1243 | } |
1243 | 1244 | ||
1244 | info->screen_base = ioremap_nocache(tdfx_fix.smem_start, | 1245 | info->screen_base = ioremap_nocache(info->fix.smem_start, |
1245 | tdfx_fix.smem_len); | 1246 | info->fix.smem_len); |
1246 | if (!info->screen_base) { | 1247 | if (!info->screen_base) { |
1247 | printk(KERN_ERR "fb: Can't remap %s framebuffer.\n", | 1248 | printk(KERN_ERR "fb: Can't remap %s framebuffer.\n", |
1248 | tdfx_fix.id); | 1249 | info->fix.id); |
1249 | goto out_err_screenbase; | 1250 | goto out_err_screenbase; |
1250 | } | 1251 | } |
1251 | 1252 | ||
@@ -1257,20 +1258,19 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev, | |||
1257 | goto out_err_screenbase; | 1258 | goto out_err_screenbase; |
1258 | } | 1259 | } |
1259 | 1260 | ||
1260 | printk(KERN_INFO "fb: %s memory = %dK\n", tdfx_fix.id, | 1261 | printk(KERN_INFO "fb: %s memory = %dK\n", info->fix.id, |
1261 | tdfx_fix.smem_len >> 10); | 1262 | info->fix.smem_len >> 10); |
1262 | 1263 | ||
1263 | default_par->mtrr_handle = -1; | 1264 | default_par->mtrr_handle = -1; |
1264 | if (!nomtrr) | 1265 | if (!nomtrr) |
1265 | default_par->mtrr_handle = | 1266 | default_par->mtrr_handle = |
1266 | mtrr_add(tdfx_fix.smem_start, tdfx_fix.smem_len, | 1267 | mtrr_add(info->fix.smem_start, info->fix.smem_len, |
1267 | MTRR_TYPE_WRCOMB, 1); | 1268 | MTRR_TYPE_WRCOMB, 1); |
1268 | 1269 | ||
1269 | tdfx_fix.ypanstep = nopan ? 0 : 1; | 1270 | info->fix.ypanstep = nopan ? 0 : 1; |
1270 | tdfx_fix.ywrapstep = nowrap ? 0 : 1; | 1271 | info->fix.ywrapstep = nowrap ? 0 : 1; |
1271 | 1272 | ||
1272 | info->fbops = &tdfxfb_ops; | 1273 | info->fbops = &tdfxfb_ops; |
1273 | info->fix = tdfx_fix; | ||
1274 | info->pseudo_palette = default_par->palette; | 1274 | info->pseudo_palette = default_par->palette; |
1275 | info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; | 1275 | info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; |
1276 | #ifdef CONFIG_FB_3DFX_ACCEL | 1276 | #ifdef CONFIG_FB_3DFX_ACCEL |
@@ -1323,14 +1323,14 @@ out_err_iobase: | |||
1323 | out_err_screenbase: | 1323 | out_err_screenbase: |
1324 | if (info->screen_base) | 1324 | if (info->screen_base) |
1325 | iounmap(info->screen_base); | 1325 | iounmap(info->screen_base); |
1326 | release_mem_region(tdfx_fix.smem_start, pci_resource_len(pdev, 1)); | 1326 | release_mem_region(info->fix.smem_start, pci_resource_len(pdev, 1)); |
1327 | out_err_regbase: | 1327 | out_err_regbase: |
1328 | /* | 1328 | /* |
1329 | * Cleanup after anything that was remapped/allocated. | 1329 | * Cleanup after anything that was remapped/allocated. |
1330 | */ | 1330 | */ |
1331 | if (default_par->regbase_virt) | 1331 | if (default_par->regbase_virt) |
1332 | iounmap(default_par->regbase_virt); | 1332 | iounmap(default_par->regbase_virt); |
1333 | release_mem_region(tdfx_fix.mmio_start, tdfx_fix.mmio_len); | 1333 | release_mem_region(info->fix.mmio_start, info->fix.mmio_len); |
1334 | out_err: | 1334 | out_err: |
1335 | framebuffer_release(info); | 1335 | framebuffer_release(info); |
1336 | return -ENXIO; | 1336 | return -ENXIO; |
diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c new file mode 100644 index 000000000000..2a380011e9ba --- /dev/null +++ b/drivers/video/tmiofb.c | |||
@@ -0,0 +1,1050 @@ | |||
1 | /* | ||
2 | * Frame Buffer Device for Toshiba Mobile IO(TMIO) controller | ||
3 | * | ||
4 | * Copyright(C) 2005-2006 Chris Humbert | ||
5 | * Copyright(C) 2005 Dirk Opfer | ||
6 | * Copytight(C) 2007,2008 Dmitry Baryshkov | ||
7 | * | ||
8 | * Based on: | ||
9 | * drivers/video/w100fb.c | ||
10 | * code written by Sharp/Lineo for 2.4 kernels | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2 | ||
14 | * as published by the Free Software Foundation; | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | */ | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/fb.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/delay.h> | ||
28 | /* Why should fb driver call console functions? because acquire_console_sem() */ | ||
29 | #include <linux/console.h> | ||
30 | #include <linux/mfd/core.h> | ||
31 | #include <linux/mfd/tmio.h> | ||
32 | #include <linux/uaccess.h> | ||
33 | |||
34 | /* | ||
35 | * accelerator commands | ||
36 | */ | ||
37 | #define TMIOFB_ACC_CSADR(x) (0x00000000 | ((x) & 0x001ffffe)) | ||
38 | #define TMIOFB_ACC_CHPIX(x) (0x01000000 | ((x) & 0x000003ff)) | ||
39 | #define TMIOFB_ACC_CVPIX(x) (0x02000000 | ((x) & 0x000003ff)) | ||
40 | #define TMIOFB_ACC_PSADR(x) (0x03000000 | ((x) & 0x00fffffe)) | ||
41 | #define TMIOFB_ACC_PHPIX(x) (0x04000000 | ((x) & 0x000003ff)) | ||
42 | #define TMIOFB_ACC_PVPIX(x) (0x05000000 | ((x) & 0x000003ff)) | ||
43 | #define TMIOFB_ACC_PHOFS(x) (0x06000000 | ((x) & 0x000003ff)) | ||
44 | #define TMIOFB_ACC_PVOFS(x) (0x07000000 | ((x) & 0x000003ff)) | ||
45 | #define TMIOFB_ACC_POADR(x) (0x08000000 | ((x) & 0x00fffffe)) | ||
46 | #define TMIOFB_ACC_RSTR(x) (0x09000000 | ((x) & 0x000000ff)) | ||
47 | #define TMIOFB_ACC_TCLOR(x) (0x0A000000 | ((x) & 0x0000ffff)) | ||
48 | #define TMIOFB_ACC_FILL(x) (0x0B000000 | ((x) & 0x0000ffff)) | ||
49 | #define TMIOFB_ACC_DSADR(x) (0x0C000000 | ((x) & 0x00fffffe)) | ||
50 | #define TMIOFB_ACC_SSADR(x) (0x0D000000 | ((x) & 0x00fffffe)) | ||
51 | #define TMIOFB_ACC_DHPIX(x) (0x0E000000 | ((x) & 0x000003ff)) | ||
52 | #define TMIOFB_ACC_DVPIX(x) (0x0F000000 | ((x) & 0x000003ff)) | ||
53 | #define TMIOFB_ACC_SHPIX(x) (0x10000000 | ((x) & 0x000003ff)) | ||
54 | #define TMIOFB_ACC_SVPIX(x) (0x11000000 | ((x) & 0x000003ff)) | ||
55 | #define TMIOFB_ACC_LBINI(x) (0x12000000 | ((x) & 0x0000ffff)) | ||
56 | #define TMIOFB_ACC_LBK2(x) (0x13000000 | ((x) & 0x0000ffff)) | ||
57 | #define TMIOFB_ACC_SHBINI(x) (0x14000000 | ((x) & 0x0000ffff)) | ||
58 | #define TMIOFB_ACC_SHBK2(x) (0x15000000 | ((x) & 0x0000ffff)) | ||
59 | #define TMIOFB_ACC_SVBINI(x) (0x16000000 | ((x) & 0x0000ffff)) | ||
60 | #define TMIOFB_ACC_SVBK2(x) (0x17000000 | ((x) & 0x0000ffff)) | ||
61 | |||
62 | #define TMIOFB_ACC_CMGO 0x20000000 | ||
63 | #define TMIOFB_ACC_CMGO_CEND 0x00000001 | ||
64 | #define TMIOFB_ACC_CMGO_INT 0x00000002 | ||
65 | #define TMIOFB_ACC_CMGO_CMOD 0x00000010 | ||
66 | #define TMIOFB_ACC_CMGO_CDVRV 0x00000020 | ||
67 | #define TMIOFB_ACC_CMGO_CDHRV 0x00000040 | ||
68 | #define TMIOFB_ACC_CMGO_RUND 0x00008000 | ||
69 | #define TMIOFB_ACC_SCGO 0x21000000 | ||
70 | #define TMIOFB_ACC_SCGO_CEND 0x00000001 | ||
71 | #define TMIOFB_ACC_SCGO_INT 0x00000002 | ||
72 | #define TMIOFB_ACC_SCGO_ROP3 0x00000004 | ||
73 | #define TMIOFB_ACC_SCGO_TRNS 0x00000008 | ||
74 | #define TMIOFB_ACC_SCGO_DVRV 0x00000010 | ||
75 | #define TMIOFB_ACC_SCGO_DHRV 0x00000020 | ||
76 | #define TMIOFB_ACC_SCGO_SVRV 0x00000040 | ||
77 | #define TMIOFB_ACC_SCGO_SHRV 0x00000080 | ||
78 | #define TMIOFB_ACC_SCGO_DSTXY 0x00008000 | ||
79 | #define TMIOFB_ACC_SBGO 0x22000000 | ||
80 | #define TMIOFB_ACC_SBGO_CEND 0x00000001 | ||
81 | #define TMIOFB_ACC_SBGO_INT 0x00000002 | ||
82 | #define TMIOFB_ACC_SBGO_DVRV 0x00000010 | ||
83 | #define TMIOFB_ACC_SBGO_DHRV 0x00000020 | ||
84 | #define TMIOFB_ACC_SBGO_SVRV 0x00000040 | ||
85 | #define TMIOFB_ACC_SBGO_SHRV 0x00000080 | ||
86 | #define TMIOFB_ACC_SBGO_SBMD 0x00000100 | ||
87 | #define TMIOFB_ACC_FLGO 0x23000000 | ||
88 | #define TMIOFB_ACC_FLGO_CEND 0x00000001 | ||
89 | #define TMIOFB_ACC_FLGO_INT 0x00000002 | ||
90 | #define TMIOFB_ACC_FLGO_ROP3 0x00000004 | ||
91 | #define TMIOFB_ACC_LDGO 0x24000000 | ||
92 | #define TMIOFB_ACC_LDGO_CEND 0x00000001 | ||
93 | #define TMIOFB_ACC_LDGO_INT 0x00000002 | ||
94 | #define TMIOFB_ACC_LDGO_ROP3 0x00000004 | ||
95 | #define TMIOFB_ACC_LDGO_ENDPX 0x00000008 | ||
96 | #define TMIOFB_ACC_LDGO_LVRV 0x00000010 | ||
97 | #define TMIOFB_ACC_LDGO_LHRV 0x00000020 | ||
98 | #define TMIOFB_ACC_LDGO_LDMOD 0x00000040 | ||
99 | |||
100 | /* a FIFO is always allocated, even if acceleration is not used */ | ||
101 | #define TMIOFB_FIFO_SIZE 512 | ||
102 | |||
103 | /* | ||
104 | * LCD Host Controller Configuration Register | ||
105 | * | ||
106 | * This iomem area supports only 16-bit IO. | ||
107 | */ | ||
108 | #define CCR_CMD 0x04 /* Command */ | ||
109 | #define CCR_REVID 0x08 /* Revision ID */ | ||
110 | #define CCR_BASEL 0x10 /* LCD Control Reg Base Addr Low */ | ||
111 | #define CCR_BASEH 0x12 /* LCD Control Reg Base Addr High */ | ||
112 | #define CCR_UGCC 0x40 /* Unified Gated Clock Control */ | ||
113 | #define CCR_GCC 0x42 /* Gated Clock Control */ | ||
114 | #define CCR_USC 0x50 /* Unified Software Clear */ | ||
115 | #define CCR_VRAMRTC 0x60 /* VRAM Timing Control */ | ||
116 | /* 0x61 VRAM Refresh Control */ | ||
117 | #define CCR_VRAMSAC 0x62 /* VRAM Access Control */ | ||
118 | /* 0x63 VRAM Status */ | ||
119 | #define CCR_VRAMBC 0x64 /* VRAM Block Control */ | ||
120 | |||
121 | /* | ||
122 | * LCD Control Register | ||
123 | * | ||
124 | * This iomem area supports only 16-bit IO. | ||
125 | */ | ||
126 | #define LCR_UIS 0x000 /* Unified Interrupt Status */ | ||
127 | #define LCR_VHPN 0x008 /* VRAM Horizontal Pixel Number */ | ||
128 | #define LCR_CFSAL 0x00a /* Command FIFO Start Address Low */ | ||
129 | #define LCR_CFSAH 0x00c /* Command FIFO Start Address High */ | ||
130 | #define LCR_CFS 0x00e /* Command FIFO Size */ | ||
131 | #define LCR_CFWS 0x010 /* Command FIFO Writeable Size */ | ||
132 | #define LCR_BBIE 0x012 /* BitBLT Interrupt Enable */ | ||
133 | #define LCR_BBISC 0x014 /* BitBLT Interrupt Status and Clear */ | ||
134 | #define LCR_CCS 0x016 /* Command Count Status */ | ||
135 | #define LCR_BBES 0x018 /* BitBLT Execution Status */ | ||
136 | #define LCR_CMDL 0x01c /* Command Low */ | ||
137 | #define LCR_CMDH 0x01e /* Command High */ | ||
138 | #define LCR_CFC 0x022 /* Command FIFO Clear */ | ||
139 | #define LCR_CCIFC 0x024 /* CMOS Camera IF Control */ | ||
140 | #define LCR_HWT 0x026 /* Hardware Test */ | ||
141 | #define LCR_LCDCCRC 0x100 /* LCDC Clock and Reset Control */ | ||
142 | #define LCR_LCDCC 0x102 /* LCDC Control */ | ||
143 | #define LCR_LCDCOPC 0x104 /* LCDC Output Pin Control */ | ||
144 | #define LCR_LCDIS 0x108 /* LCD Interrupt Status */ | ||
145 | #define LCR_LCDIM 0x10a /* LCD Interrupt Mask */ | ||
146 | #define LCR_LCDIE 0x10c /* LCD Interrupt Enable */ | ||
147 | #define LCR_GDSAL 0x122 /* Graphics Display Start Address Low */ | ||
148 | #define LCR_GDSAH 0x124 /* Graphics Display Start Address High */ | ||
149 | #define LCR_VHPCL 0x12a /* VRAM Horizontal Pixel Count Low */ | ||
150 | #define LCR_VHPCH 0x12c /* VRAM Horizontal Pixel Count High */ | ||
151 | #define LCR_GM 0x12e /* Graphic Mode(VRAM access enable) */ | ||
152 | #define LCR_HT 0x140 /* Horizontal Total */ | ||
153 | #define LCR_HDS 0x142 /* Horizontal Display Start */ | ||
154 | #define LCR_HSS 0x144 /* H-Sync Start */ | ||
155 | #define LCR_HSE 0x146 /* H-Sync End */ | ||
156 | #define LCR_HNP 0x14c /* Horizontal Number of Pixels */ | ||
157 | #define LCR_VT 0x150 /* Vertical Total */ | ||
158 | #define LCR_VDS 0x152 /* Vertical Display Start */ | ||
159 | #define LCR_VSS 0x154 /* V-Sync Start */ | ||
160 | #define LCR_VSE 0x156 /* V-Sync End */ | ||
161 | #define LCR_CDLN 0x160 /* Current Display Line Number */ | ||
162 | #define LCR_ILN 0x162 /* Interrupt Line Number */ | ||
163 | #define LCR_SP 0x164 /* Sync Polarity */ | ||
164 | #define LCR_MISC 0x166 /* MISC(RGB565 mode) */ | ||
165 | #define LCR_VIHSS 0x16a /* Video Interface H-Sync Start */ | ||
166 | #define LCR_VIVS 0x16c /* Video Interface Vertical Start */ | ||
167 | #define LCR_VIVE 0x16e /* Video Interface Vertical End */ | ||
168 | #define LCR_VIVSS 0x170 /* Video Interface V-Sync Start */ | ||
169 | #define LCR_VCCIS 0x17e /* Video / CMOS Camera Interface Select */ | ||
170 | #define LCR_VIDWSAL 0x180 /* VI Data Write Start Address Low */ | ||
171 | #define LCR_VIDWSAH 0x182 /* VI Data Write Start Address High */ | ||
172 | #define LCR_VIDRSAL 0x184 /* VI Data Read Start Address Low */ | ||
173 | #define LCR_VIDRSAH 0x186 /* VI Data Read Start Address High */ | ||
174 | #define LCR_VIPDDST 0x188 /* VI Picture Data Display Start Timing */ | ||
175 | #define LCR_VIPDDET 0x186 /* VI Picture Data Display End Timing */ | ||
176 | #define LCR_VIE 0x18c /* Video Interface Enable */ | ||
177 | #define LCR_VCS 0x18e /* Video/Camera Select */ | ||
178 | #define LCR_VPHWC 0x194 /* Video Picture Horizontal Wait Count */ | ||
179 | #define LCR_VPHS 0x196 /* Video Picture Horizontal Size */ | ||
180 | #define LCR_VPVWC 0x198 /* Video Picture Vertical Wait Count */ | ||
181 | #define LCR_VPVS 0x19a /* Video Picture Vertical Size */ | ||
182 | #define LCR_PLHPIX 0x1a0 /* PLHPIX */ | ||
183 | #define LCR_XS 0x1a2 /* XStart */ | ||
184 | #define LCR_XCKHW 0x1a4 /* XCK High Width */ | ||
185 | #define LCR_STHS 0x1a8 /* STH Start */ | ||
186 | #define LCR_VT2 0x1aa /* Vertical Total */ | ||
187 | #define LCR_YCKSW 0x1ac /* YCK Start Wait */ | ||
188 | #define LCR_YSTS 0x1ae /* YST Start */ | ||
189 | #define LCR_PPOLS 0x1b0 /* #PPOL Start */ | ||
190 | #define LCR_PRECW 0x1b2 /* PREC Width */ | ||
191 | #define LCR_VCLKHW 0x1b4 /* VCLK High Width */ | ||
192 | #define LCR_OC 0x1b6 /* Output Control */ | ||
193 | |||
194 | static char *mode_option __devinitdata; | ||
195 | |||
196 | struct tmiofb_par { | ||
197 | u32 pseudo_palette[16]; | ||
198 | |||
199 | #ifdef CONFIG_FB_TMIO_ACCELL | ||
200 | wait_queue_head_t wait_acc; | ||
201 | bool use_polling; | ||
202 | #endif | ||
203 | |||
204 | void __iomem *ccr; | ||
205 | void __iomem *lcr; | ||
206 | }; | ||
207 | |||
208 | /*--------------------------------------------------------------------------*/ | ||
209 | |||
210 | /* | ||
211 | * reasons for an interrupt: | ||
212 | * uis bbisc lcdis | ||
213 | * 0100 0001 accelerator command completed | ||
214 | * 2000 0001 vsync start | ||
215 | * 2000 0002 display start | ||
216 | * 2000 0004 line number match(0x1ff mask???) | ||
217 | */ | ||
218 | static irqreturn_t tmiofb_irq(int irq, void *__info) | ||
219 | { | ||
220 | struct fb_info *info = __info; | ||
221 | struct tmiofb_par *par = info->par; | ||
222 | unsigned int bbisc = tmio_ioread16(par->lcr + LCR_BBISC); | ||
223 | |||
224 | |||
225 | /* | ||
226 | * We were in polling mode and now we got correct irq. | ||
227 | * Switch back to IRQ-based sync of command FIFO | ||
228 | */ | ||
229 | if (unlikely(par->use_polling && irq != -1)) { | ||
230 | printk(KERN_INFO "tmiofb: switching to waitq\n"); | ||
231 | par->use_polling = false; | ||
232 | } | ||
233 | |||
234 | tmio_iowrite16(bbisc, par->lcr + LCR_BBISC); | ||
235 | |||
236 | #ifdef CONFIG_FB_TMIO_ACCELL | ||
237 | if (bbisc & 1) | ||
238 | wake_up(&par->wait_acc); | ||
239 | #endif | ||
240 | |||
241 | return IRQ_HANDLED; | ||
242 | } | ||
243 | |||
244 | |||
245 | /*--------------------------------------------------------------------------*/ | ||
246 | |||
247 | |||
248 | /* | ||
249 | * Turns off the LCD controller and LCD host controller. | ||
250 | */ | ||
251 | static int tmiofb_hw_stop(struct platform_device *dev) | ||
252 | { | ||
253 | struct mfd_cell *cell = dev->dev.platform_data; | ||
254 | struct tmio_fb_data *data = cell->driver_data; | ||
255 | struct fb_info *info = platform_get_drvdata(dev); | ||
256 | struct tmiofb_par *par = info->par; | ||
257 | |||
258 | tmio_iowrite16(0, par->ccr + CCR_UGCC); | ||
259 | tmio_iowrite16(0, par->lcr + LCR_GM); | ||
260 | data->lcd_set_power(dev, 0); | ||
261 | tmio_iowrite16(0x0010, par->lcr + LCR_LCDCCRC); | ||
262 | |||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | /* | ||
267 | * Initializes the LCD host controller. | ||
268 | */ | ||
269 | static int tmiofb_hw_init(struct platform_device *dev) | ||
270 | { | ||
271 | struct mfd_cell *cell = dev->dev.platform_data; | ||
272 | struct fb_info *info = platform_get_drvdata(dev); | ||
273 | struct tmiofb_par *par = info->par; | ||
274 | const struct resource *nlcr = &cell->resources[0]; | ||
275 | const struct resource *vram = &cell->resources[2]; | ||
276 | unsigned long base; | ||
277 | |||
278 | if (nlcr == NULL || vram == NULL) | ||
279 | return -EINVAL; | ||
280 | |||
281 | base = nlcr->start; | ||
282 | |||
283 | tmio_iowrite16(0x003a, par->ccr + CCR_UGCC); | ||
284 | tmio_iowrite16(0x003a, par->ccr + CCR_GCC); | ||
285 | tmio_iowrite16(0x3f00, par->ccr + CCR_USC); | ||
286 | |||
287 | msleep(2); /* wait for device to settle */ | ||
288 | |||
289 | tmio_iowrite16(0x0000, par->ccr + CCR_USC); | ||
290 | tmio_iowrite16(base >> 16, par->ccr + CCR_BASEH); | ||
291 | tmio_iowrite16(base, par->ccr + CCR_BASEL); | ||
292 | tmio_iowrite16(0x0002, par->ccr + CCR_CMD); /* base address enable */ | ||
293 | tmio_iowrite16(0x40a8, par->ccr + CCR_VRAMRTC); /* VRAMRC, VRAMTC */ | ||
294 | tmio_iowrite16(0x0018, par->ccr + CCR_VRAMSAC); /* VRAMSTS, VRAMAC */ | ||
295 | tmio_iowrite16(0x0002, par->ccr + CCR_VRAMBC); | ||
296 | msleep(2); /* wait for device to settle */ | ||
297 | tmio_iowrite16(0x000b, par->ccr + CCR_VRAMBC); | ||
298 | |||
299 | base = vram->start + info->screen_size; | ||
300 | tmio_iowrite16(base >> 16, par->lcr + LCR_CFSAH); | ||
301 | tmio_iowrite16(base, par->lcr + LCR_CFSAL); | ||
302 | tmio_iowrite16(TMIOFB_FIFO_SIZE - 1, par->lcr + LCR_CFS); | ||
303 | tmio_iowrite16(1, par->lcr + LCR_CFC); | ||
304 | tmio_iowrite16(1, par->lcr + LCR_BBIE); | ||
305 | tmio_iowrite16(0, par->lcr + LCR_CFWS); | ||
306 | |||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | /* | ||
311 | * Sets the LCD controller's output resolution and pixel clock | ||
312 | */ | ||
313 | static void tmiofb_hw_mode(struct platform_device *dev) | ||
314 | { | ||
315 | struct mfd_cell *cell = dev->dev.platform_data; | ||
316 | struct tmio_fb_data *data = cell->driver_data; | ||
317 | struct fb_info *info = platform_get_drvdata(dev); | ||
318 | struct fb_videomode *mode = info->mode; | ||
319 | struct tmiofb_par *par = info->par; | ||
320 | unsigned int i; | ||
321 | |||
322 | tmio_iowrite16(0, par->lcr + LCR_GM); | ||
323 | data->lcd_set_power(dev, 0); | ||
324 | tmio_iowrite16(0x0010, par->lcr + LCR_LCDCCRC); | ||
325 | data->lcd_mode(dev, mode); | ||
326 | data->lcd_set_power(dev, 1); | ||
327 | |||
328 | tmio_iowrite16(info->fix.line_length, par->lcr + LCR_VHPN); | ||
329 | tmio_iowrite16(0, par->lcr + LCR_GDSAH); | ||
330 | tmio_iowrite16(0, par->lcr + LCR_GDSAL); | ||
331 | tmio_iowrite16(info->fix.line_length >> 16, par->lcr + LCR_VHPCH); | ||
332 | tmio_iowrite16(info->fix.line_length, par->lcr + LCR_VHPCL); | ||
333 | tmio_iowrite16(i = 0, par->lcr + LCR_HSS); | ||
334 | tmio_iowrite16(i += mode->hsync_len, par->lcr + LCR_HSE); | ||
335 | tmio_iowrite16(i += mode->left_margin, par->lcr + LCR_HDS); | ||
336 | tmio_iowrite16(i += mode->xres + mode->right_margin, par->lcr + LCR_HT); | ||
337 | tmio_iowrite16(mode->xres, par->lcr + LCR_HNP); | ||
338 | tmio_iowrite16(i = 0, par->lcr + LCR_VSS); | ||
339 | tmio_iowrite16(i += mode->vsync_len, par->lcr + LCR_VSE); | ||
340 | tmio_iowrite16(i += mode->upper_margin, par->lcr + LCR_VDS); | ||
341 | tmio_iowrite16(i += mode->yres, par->lcr + LCR_ILN); | ||
342 | tmio_iowrite16(i += mode->lower_margin, par->lcr + LCR_VT); | ||
343 | tmio_iowrite16(3, par->lcr + LCR_MISC); /* RGB565 mode */ | ||
344 | tmio_iowrite16(1, par->lcr + LCR_GM); /* VRAM enable */ | ||
345 | tmio_iowrite16(0x4007, par->lcr + LCR_LCDCC); | ||
346 | tmio_iowrite16(3, par->lcr + LCR_SP); /* sync polarity */ | ||
347 | |||
348 | tmio_iowrite16(0x0010, par->lcr + LCR_LCDCCRC); | ||
349 | msleep(5); /* wait for device to settle */ | ||
350 | tmio_iowrite16(0x0014, par->lcr + LCR_LCDCCRC); /* STOP_CKP */ | ||
351 | msleep(5); /* wait for device to settle */ | ||
352 | tmio_iowrite16(0x0015, par->lcr + LCR_LCDCCRC); /* STOP_CKP|SOFT_RESET*/ | ||
353 | tmio_iowrite16(0xfffa, par->lcr + LCR_VCS); | ||
354 | } | ||
355 | |||
356 | /*--------------------------------------------------------------------------*/ | ||
357 | |||
358 | #ifdef CONFIG_FB_TMIO_ACCELL | ||
359 | static int __must_check | ||
360 | tmiofb_acc_wait(struct fb_info *info, unsigned int ccs) | ||
361 | { | ||
362 | struct tmiofb_par *par = info->par; | ||
363 | /* | ||
364 | * This code can be called whith interrupts disabled. | ||
365 | * So instead of relaying on irq to trigger the event, | ||
366 | * poll the state till the necessary command is executed. | ||
367 | */ | ||
368 | if (irqs_disabled() || par->use_polling) { | ||
369 | int i = 0; | ||
370 | while (tmio_ioread16(par->lcr + LCR_CCS) > ccs) { | ||
371 | udelay(1); | ||
372 | i++; | ||
373 | if (i > 10000) { | ||
374 | pr_err("tmiofb: timeout waiting for %d\n", | ||
375 | ccs); | ||
376 | return -ETIMEDOUT; | ||
377 | } | ||
378 | tmiofb_irq(-1, info); | ||
379 | } | ||
380 | } else { | ||
381 | if (!wait_event_interruptible_timeout(par->wait_acc, | ||
382 | tmio_ioread16(par->lcr + LCR_CCS) <= ccs, | ||
383 | 1000)) { | ||
384 | pr_err("tmiofb: timeout waiting for %d\n", ccs); | ||
385 | return -ETIMEDOUT; | ||
386 | } | ||
387 | } | ||
388 | |||
389 | return 0; | ||
390 | } | ||
391 | |||
392 | /* | ||
393 | * Writes an accelerator command to the accelerator's FIFO. | ||
394 | */ | ||
395 | static int | ||
396 | tmiofb_acc_write(struct fb_info *info, const u32 *cmd, unsigned int count) | ||
397 | { | ||
398 | struct tmiofb_par *par = info->par; | ||
399 | int ret; | ||
400 | |||
401 | ret = tmiofb_acc_wait(info, TMIOFB_FIFO_SIZE - count); | ||
402 | if (ret) | ||
403 | return ret; | ||
404 | |||
405 | for (; count; count--, cmd++) { | ||
406 | tmio_iowrite16(*cmd >> 16, par->lcr + LCR_CMDH); | ||
407 | tmio_iowrite16(*cmd, par->lcr + LCR_CMDL); | ||
408 | } | ||
409 | |||
410 | return ret; | ||
411 | } | ||
412 | |||
413 | /* | ||
414 | * Wait for the accelerator to finish its operations before writing | ||
415 | * to the framebuffer for consistent display output. | ||
416 | */ | ||
417 | static int tmiofb_sync(struct fb_info *fbi) | ||
418 | { | ||
419 | struct tmiofb_par *par = fbi->par; | ||
420 | |||
421 | int ret; | ||
422 | int i = 0; | ||
423 | |||
424 | ret = tmiofb_acc_wait(fbi, 0); | ||
425 | |||
426 | while (tmio_ioread16(par->lcr + LCR_BBES) & 2) { /* blit active */ | ||
427 | udelay(1); | ||
428 | i++ ; | ||
429 | if (i > 10000) { | ||
430 | printk(KERN_ERR "timeout waiting for blit to end!\n"); | ||
431 | return -ETIMEDOUT; | ||
432 | } | ||
433 | } | ||
434 | |||
435 | return ret; | ||
436 | } | ||
437 | |||
438 | static void | ||
439 | tmiofb_fillrect(struct fb_info *fbi, const struct fb_fillrect *rect) | ||
440 | { | ||
441 | const u32 cmd[] = { | ||
442 | TMIOFB_ACC_DSADR((rect->dy * fbi->mode->xres + rect->dx) * 2), | ||
443 | TMIOFB_ACC_DHPIX(rect->width - 1), | ||
444 | TMIOFB_ACC_DVPIX(rect->height - 1), | ||
445 | TMIOFB_ACC_FILL(rect->color), | ||
446 | TMIOFB_ACC_FLGO, | ||
447 | }; | ||
448 | |||
449 | if (fbi->state != FBINFO_STATE_RUNNING || | ||
450 | fbi->flags & FBINFO_HWACCEL_DISABLED) { | ||
451 | cfb_fillrect(fbi, rect); | ||
452 | return; | ||
453 | } | ||
454 | |||
455 | tmiofb_acc_write(fbi, cmd, ARRAY_SIZE(cmd)); | ||
456 | } | ||
457 | |||
458 | static void | ||
459 | tmiofb_copyarea(struct fb_info *fbi, const struct fb_copyarea *area) | ||
460 | { | ||
461 | const u32 cmd[] = { | ||
462 | TMIOFB_ACC_DSADR((area->dy * fbi->mode->xres + area->dx) * 2), | ||
463 | TMIOFB_ACC_DHPIX(area->width - 1), | ||
464 | TMIOFB_ACC_DVPIX(area->height - 1), | ||
465 | TMIOFB_ACC_SSADR((area->sy * fbi->mode->xres + area->sx) * 2), | ||
466 | TMIOFB_ACC_SCGO, | ||
467 | }; | ||
468 | |||
469 | if (fbi->state != FBINFO_STATE_RUNNING || | ||
470 | fbi->flags & FBINFO_HWACCEL_DISABLED) { | ||
471 | cfb_copyarea(fbi, area); | ||
472 | return; | ||
473 | } | ||
474 | |||
475 | tmiofb_acc_write(fbi, cmd, ARRAY_SIZE(cmd)); | ||
476 | } | ||
477 | #endif | ||
478 | |||
479 | static void tmiofb_clearscreen(struct fb_info *info) | ||
480 | { | ||
481 | const struct fb_fillrect rect = { | ||
482 | .dx = 0, | ||
483 | .dy = 0, | ||
484 | .width = info->mode->xres, | ||
485 | .height = info->mode->yres, | ||
486 | .color = 0, | ||
487 | .rop = ROP_COPY, | ||
488 | }; | ||
489 | |||
490 | info->fbops->fb_fillrect(info, &rect); | ||
491 | } | ||
492 | |||
493 | static int tmiofb_vblank(struct fb_info *fbi, struct fb_vblank *vblank) | ||
494 | { | ||
495 | struct tmiofb_par *par = fbi->par; | ||
496 | struct fb_videomode *mode = fbi->mode; | ||
497 | unsigned int vcount = tmio_ioread16(par->lcr + LCR_CDLN); | ||
498 | unsigned int vds = mode->vsync_len + mode->upper_margin; | ||
499 | |||
500 | vblank->vcount = vcount; | ||
501 | vblank->flags = FB_VBLANK_HAVE_VBLANK | FB_VBLANK_HAVE_VCOUNT | ||
502 | | FB_VBLANK_HAVE_VSYNC; | ||
503 | |||
504 | if (vcount < mode->vsync_len) | ||
505 | vblank->flags |= FB_VBLANK_VSYNCING; | ||
506 | |||
507 | if (vcount < vds || vcount > vds + mode->yres) | ||
508 | vblank->flags |= FB_VBLANK_VBLANKING; | ||
509 | |||
510 | return 0; | ||
511 | } | ||
512 | |||
513 | |||
514 | static int tmiofb_ioctl(struct fb_info *fbi, | ||
515 | unsigned int cmd, unsigned long arg) | ||
516 | { | ||
517 | switch (cmd) { | ||
518 | case FBIOGET_VBLANK: { | ||
519 | struct fb_vblank vblank = {0}; | ||
520 | void __user *argp = (void __user *) arg; | ||
521 | |||
522 | tmiofb_vblank(fbi, &vblank); | ||
523 | if (copy_to_user(argp, &vblank, sizeof vblank)) | ||
524 | return -EFAULT; | ||
525 | return 0; | ||
526 | } | ||
527 | |||
528 | #ifdef CONFIG_FB_TMIO_ACCELL | ||
529 | case FBIO_TMIO_ACC_SYNC: | ||
530 | tmiofb_sync(fbi); | ||
531 | return 0; | ||
532 | |||
533 | case FBIO_TMIO_ACC_WRITE: { | ||
534 | u32 __user *argp = (void __user *) arg; | ||
535 | u32 len; | ||
536 | u32 acc[16]; | ||
537 | |||
538 | if (get_user(len, argp)) | ||
539 | return -EFAULT; | ||
540 | if (len > ARRAY_SIZE(acc)) | ||
541 | return -EINVAL; | ||
542 | if (copy_from_user(acc, argp + 1, sizeof(u32) * len)) | ||
543 | return -EFAULT; | ||
544 | |||
545 | return tmiofb_acc_write(fbi, acc, len); | ||
546 | } | ||
547 | #endif | ||
548 | } | ||
549 | |||
550 | return -ENOTTY; | ||
551 | } | ||
552 | |||
553 | /*--------------------------------------------------------------------------*/ | ||
554 | |||
555 | /* Select the smallest mode that allows the desired resolution to be | ||
556 | * displayed. If desired, the x and y parameters can be rounded up to | ||
557 | * match the selected mode. | ||
558 | */ | ||
559 | static struct fb_videomode * | ||
560 | tmiofb_find_mode(struct fb_info *info, struct fb_var_screeninfo *var) | ||
561 | { | ||
562 | struct mfd_cell *cell = | ||
563 | info->device->platform_data; | ||
564 | struct tmio_fb_data *data = cell->driver_data; | ||
565 | struct fb_videomode *best = NULL; | ||
566 | int i; | ||
567 | |||
568 | for (i = 0; i < data->num_modes; i++) { | ||
569 | struct fb_videomode *mode = data->modes + i; | ||
570 | |||
571 | if (mode->xres >= var->xres && mode->yres >= var->yres | ||
572 | && (!best || (mode->xres < best->xres | ||
573 | && mode->yres < best->yres))) | ||
574 | best = mode; | ||
575 | } | ||
576 | |||
577 | return best; | ||
578 | } | ||
579 | |||
580 | static int tmiofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | ||
581 | { | ||
582 | |||
583 | struct fb_videomode *mode; | ||
584 | struct mfd_cell *cell = | ||
585 | info->device->platform_data; | ||
586 | struct tmio_fb_data *data = cell->driver_data; | ||
587 | |||
588 | mode = tmiofb_find_mode(info, var); | ||
589 | if (!mode || var->bits_per_pixel > 16) | ||
590 | return -EINVAL; | ||
591 | |||
592 | fb_videomode_to_var(var, mode); | ||
593 | |||
594 | var->xres_virtual = mode->xres; | ||
595 | var->yres_virtual = info->screen_size / (mode->xres * 2); | ||
596 | |||
597 | if (var->yres_virtual < var->yres) | ||
598 | return -EINVAL; | ||
599 | |||
600 | var->xoffset = 0; | ||
601 | var->yoffset = 0; | ||
602 | var->bits_per_pixel = 16; | ||
603 | var->grayscale = 0; | ||
604 | var->red.offset = 11; | ||
605 | var->red.length = 5; | ||
606 | var->green.offset = 5; | ||
607 | var->green.length = 6; | ||
608 | var->blue.offset = 0; | ||
609 | var->blue.length = 5; | ||
610 | var->transp.offset = 0; | ||
611 | var->transp.length = 0; | ||
612 | var->nonstd = 0; | ||
613 | var->height = data->height; /* mm */ | ||
614 | var->width = data->width; /* mm */ | ||
615 | var->rotate = 0; | ||
616 | return 0; | ||
617 | } | ||
618 | |||
619 | static int tmiofb_set_par(struct fb_info *info) | ||
620 | { | ||
621 | struct fb_var_screeninfo *var = &info->var; | ||
622 | struct fb_videomode *mode; | ||
623 | |||
624 | mode = tmiofb_find_mode(info, var); | ||
625 | if (!mode) | ||
626 | return -EINVAL; | ||
627 | |||
628 | info->mode = mode; | ||
629 | info->fix.line_length = info->mode->xres * | ||
630 | var->bits_per_pixel / 8; | ||
631 | |||
632 | tmiofb_hw_mode(to_platform_device(info->device)); | ||
633 | tmiofb_clearscreen(info); | ||
634 | return 0; | ||
635 | } | ||
636 | |||
637 | static int tmiofb_setcolreg(unsigned regno, unsigned red, unsigned green, | ||
638 | unsigned blue, unsigned transp, | ||
639 | struct fb_info *info) | ||
640 | { | ||
641 | struct tmiofb_par *par = info->par; | ||
642 | |||
643 | if (regno < ARRAY_SIZE(par->pseudo_palette)) { | ||
644 | par->pseudo_palette[regno] = | ||
645 | ((red & 0xf800)) | | ||
646 | ((green & 0xfc00) >> 5) | | ||
647 | ((blue & 0xf800) >> 11); | ||
648 | return 0; | ||
649 | } | ||
650 | |||
651 | return -EINVAL; | ||
652 | } | ||
653 | |||
654 | static int tmiofb_blank(int blank, struct fb_info *info) | ||
655 | { | ||
656 | /* | ||
657 | * everything is done in lcd/bl drivers. | ||
658 | * this is purely to make sysfs happy and work. | ||
659 | */ | ||
660 | return 0; | ||
661 | } | ||
662 | |||
663 | static struct fb_ops tmiofb_ops = { | ||
664 | .owner = THIS_MODULE, | ||
665 | |||
666 | .fb_ioctl = tmiofb_ioctl, | ||
667 | .fb_check_var = tmiofb_check_var, | ||
668 | .fb_set_par = tmiofb_set_par, | ||
669 | .fb_setcolreg = tmiofb_setcolreg, | ||
670 | .fb_blank = tmiofb_blank, | ||
671 | .fb_imageblit = cfb_imageblit, | ||
672 | #ifdef CONFIG_FB_TMIO_ACCELL | ||
673 | .fb_sync = tmiofb_sync, | ||
674 | .fb_fillrect = tmiofb_fillrect, | ||
675 | .fb_copyarea = tmiofb_copyarea, | ||
676 | #else | ||
677 | .fb_fillrect = cfb_fillrect, | ||
678 | .fb_copyarea = cfb_copyarea, | ||
679 | #endif | ||
680 | }; | ||
681 | |||
682 | /*--------------------------------------------------------------------------*/ | ||
683 | |||
684 | static int __devinit tmiofb_probe(struct platform_device *dev) | ||
685 | { | ||
686 | struct mfd_cell *cell = dev->dev.platform_data; | ||
687 | struct tmio_fb_data *data = cell->driver_data; | ||
688 | struct resource *ccr = platform_get_resource(dev, IORESOURCE_MEM, 1); | ||
689 | struct resource *lcr = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
690 | struct resource *vram = platform_get_resource(dev, IORESOURCE_MEM, 2); | ||
691 | int irq = platform_get_irq(dev, 0); | ||
692 | struct fb_info *info; | ||
693 | struct tmiofb_par *par; | ||
694 | int retval; | ||
695 | |||
696 | /* | ||
697 | * This is the only way ATM to disable the fb | ||
698 | */ | ||
699 | if (data == NULL) { | ||
700 | dev_err(&dev->dev, "NULL platform data!\n"); | ||
701 | return -EINVAL; | ||
702 | } | ||
703 | |||
704 | info = framebuffer_alloc(sizeof(struct tmiofb_par), &dev->dev); | ||
705 | |||
706 | if (!info) | ||
707 | return -ENOMEM; | ||
708 | |||
709 | par = info->par; | ||
710 | |||
711 | #ifdef CONFIG_FB_TMIO_ACCELL | ||
712 | init_waitqueue_head(&par->wait_acc); | ||
713 | |||
714 | par->use_polling = true; | ||
715 | |||
716 | info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA | ||
717 | | FBINFO_HWACCEL_FILLRECT; | ||
718 | #else | ||
719 | info->flags = FBINFO_DEFAULT; | ||
720 | #endif | ||
721 | |||
722 | info->fbops = &tmiofb_ops; | ||
723 | |||
724 | strcpy(info->fix.id, "tmio-fb"); | ||
725 | info->fix.smem_start = vram->start; | ||
726 | info->fix.smem_len = resource_size(vram); | ||
727 | info->fix.type = FB_TYPE_PACKED_PIXELS; | ||
728 | info->fix.visual = FB_VISUAL_TRUECOLOR; | ||
729 | info->fix.mmio_start = lcr->start; | ||
730 | info->fix.mmio_len = resource_size(lcr); | ||
731 | info->fix.accel = FB_ACCEL_NONE; | ||
732 | info->screen_size = info->fix.smem_len - (4 * TMIOFB_FIFO_SIZE); | ||
733 | info->pseudo_palette = par->pseudo_palette; | ||
734 | |||
735 | par->ccr = ioremap(ccr->start, resource_size(ccr)); | ||
736 | if (!par->ccr) { | ||
737 | retval = -ENOMEM; | ||
738 | goto err_ioremap_ccr; | ||
739 | } | ||
740 | |||
741 | par->lcr = ioremap(info->fix.mmio_start, info->fix.mmio_len); | ||
742 | if (!par->lcr) { | ||
743 | retval = -ENOMEM; | ||
744 | goto err_ioremap_lcr; | ||
745 | } | ||
746 | |||
747 | info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); | ||
748 | if (!info->screen_base) { | ||
749 | retval = -ENOMEM; | ||
750 | goto err_ioremap_vram; | ||
751 | } | ||
752 | |||
753 | retval = request_irq(irq, &tmiofb_irq, IRQF_DISABLED, | ||
754 | dev->dev.bus_id, info); | ||
755 | |||
756 | if (retval) | ||
757 | goto err_request_irq; | ||
758 | |||
759 | platform_set_drvdata(dev, info); | ||
760 | |||
761 | retval = fb_find_mode(&info->var, info, mode_option, | ||
762 | data->modes, data->num_modes, | ||
763 | data->modes, 16); | ||
764 | if (!retval) { | ||
765 | retval = -EINVAL; | ||
766 | goto err_find_mode; | ||
767 | } | ||
768 | |||
769 | if (cell->enable) { | ||
770 | retval = cell->enable(dev); | ||
771 | if (retval) | ||
772 | goto err_enable; | ||
773 | } | ||
774 | |||
775 | retval = tmiofb_hw_init(dev); | ||
776 | if (retval) | ||
777 | goto err_hw_init; | ||
778 | |||
779 | fb_videomode_to_modelist(data->modes, data->num_modes, | ||
780 | &info->modelist); | ||
781 | |||
782 | retval = register_framebuffer(info); | ||
783 | if (retval < 0) | ||
784 | goto err_register_framebuffer; | ||
785 | |||
786 | printk(KERN_INFO "fb%d: %s frame buffer device\n", | ||
787 | info->node, info->fix.id); | ||
788 | |||
789 | return 0; | ||
790 | |||
791 | err_register_framebuffer: | ||
792 | /*err_set_par:*/ | ||
793 | tmiofb_hw_stop(dev); | ||
794 | err_hw_init: | ||
795 | if (cell->disable) | ||
796 | cell->disable(dev); | ||
797 | err_enable: | ||
798 | err_find_mode: | ||
799 | platform_set_drvdata(dev, NULL); | ||
800 | free_irq(irq, info); | ||
801 | err_request_irq: | ||
802 | iounmap(info->screen_base); | ||
803 | err_ioremap_vram: | ||
804 | iounmap(par->lcr); | ||
805 | err_ioremap_lcr: | ||
806 | iounmap(par->ccr); | ||
807 | err_ioremap_ccr: | ||
808 | framebuffer_release(info); | ||
809 | return retval; | ||
810 | } | ||
811 | |||
812 | static int __devexit tmiofb_remove(struct platform_device *dev) | ||
813 | { | ||
814 | struct mfd_cell *cell = dev->dev.platform_data; | ||
815 | struct fb_info *info = platform_get_drvdata(dev); | ||
816 | int irq = platform_get_irq(dev, 0); | ||
817 | struct tmiofb_par *par; | ||
818 | |||
819 | if (info) { | ||
820 | par = info->par; | ||
821 | unregister_framebuffer(info); | ||
822 | |||
823 | tmiofb_hw_stop(dev); | ||
824 | |||
825 | if (cell->disable) | ||
826 | cell->disable(dev); | ||
827 | |||
828 | platform_set_drvdata(dev, NULL); | ||
829 | |||
830 | free_irq(irq, info); | ||
831 | |||
832 | iounmap(info->screen_base); | ||
833 | iounmap(par->lcr); | ||
834 | iounmap(par->ccr); | ||
835 | |||
836 | framebuffer_release(info); | ||
837 | } | ||
838 | |||
839 | return 0; | ||
840 | } | ||
841 | |||
842 | #ifdef DEBUG | ||
843 | static void tmiofb_dump_regs(struct platform_device *dev) | ||
844 | { | ||
845 | struct fb_info *info = platform_get_drvdata(dev); | ||
846 | struct tmiofb_par *par = info->par; | ||
847 | |||
848 | printk(KERN_DEBUG "lhccr:\n"); | ||
849 | #define CCR_PR(n) printk(KERN_DEBUG "\t" #n " = \t%04x\n",\ | ||
850 | tmio_ioread16(par->ccr + CCR_ ## n)); | ||
851 | CCR_PR(CMD); | ||
852 | CCR_PR(REVID); | ||
853 | CCR_PR(BASEL); | ||
854 | CCR_PR(BASEH); | ||
855 | CCR_PR(UGCC); | ||
856 | CCR_PR(GCC); | ||
857 | CCR_PR(USC); | ||
858 | CCR_PR(VRAMRTC); | ||
859 | CCR_PR(VRAMSAC); | ||
860 | CCR_PR(VRAMBC); | ||
861 | #undef CCR_PR | ||
862 | |||
863 | printk(KERN_DEBUG "lcr: \n"); | ||
864 | #define LCR_PR(n) printk(KERN_DEBUG "\t" #n " = \t%04x\n",\ | ||
865 | tmio_ioread16(par->lcr + LCR_ ## n)); | ||
866 | LCR_PR(UIS); | ||
867 | LCR_PR(VHPN); | ||
868 | LCR_PR(CFSAL); | ||
869 | LCR_PR(CFSAH); | ||
870 | LCR_PR(CFS); | ||
871 | LCR_PR(CFWS); | ||
872 | LCR_PR(BBIE); | ||
873 | LCR_PR(BBISC); | ||
874 | LCR_PR(CCS); | ||
875 | LCR_PR(BBES); | ||
876 | LCR_PR(CMDL); | ||
877 | LCR_PR(CMDH); | ||
878 | LCR_PR(CFC); | ||
879 | LCR_PR(CCIFC); | ||
880 | LCR_PR(HWT); | ||
881 | LCR_PR(LCDCCRC); | ||
882 | LCR_PR(LCDCC); | ||
883 | LCR_PR(LCDCOPC); | ||
884 | LCR_PR(LCDIS); | ||
885 | LCR_PR(LCDIM); | ||
886 | LCR_PR(LCDIE); | ||
887 | LCR_PR(GDSAL); | ||
888 | LCR_PR(GDSAH); | ||
889 | LCR_PR(VHPCL); | ||
890 | LCR_PR(VHPCH); | ||
891 | LCR_PR(GM); | ||
892 | LCR_PR(HT); | ||
893 | LCR_PR(HDS); | ||
894 | LCR_PR(HSS); | ||
895 | LCR_PR(HSE); | ||
896 | LCR_PR(HNP); | ||
897 | LCR_PR(VT); | ||
898 | LCR_PR(VDS); | ||
899 | LCR_PR(VSS); | ||
900 | LCR_PR(VSE); | ||
901 | LCR_PR(CDLN); | ||
902 | LCR_PR(ILN); | ||
903 | LCR_PR(SP); | ||
904 | LCR_PR(MISC); | ||
905 | LCR_PR(VIHSS); | ||
906 | LCR_PR(VIVS); | ||
907 | LCR_PR(VIVE); | ||
908 | LCR_PR(VIVSS); | ||
909 | LCR_PR(VCCIS); | ||
910 | LCR_PR(VIDWSAL); | ||
911 | LCR_PR(VIDWSAH); | ||
912 | LCR_PR(VIDRSAL); | ||
913 | LCR_PR(VIDRSAH); | ||
914 | LCR_PR(VIPDDST); | ||
915 | LCR_PR(VIPDDET); | ||
916 | LCR_PR(VIE); | ||
917 | LCR_PR(VCS); | ||
918 | LCR_PR(VPHWC); | ||
919 | LCR_PR(VPHS); | ||
920 | LCR_PR(VPVWC); | ||
921 | LCR_PR(VPVS); | ||
922 | LCR_PR(PLHPIX); | ||
923 | LCR_PR(XS); | ||
924 | LCR_PR(XCKHW); | ||
925 | LCR_PR(STHS); | ||
926 | LCR_PR(VT2); | ||
927 | LCR_PR(YCKSW); | ||
928 | LCR_PR(YSTS); | ||
929 | LCR_PR(PPOLS); | ||
930 | LCR_PR(PRECW); | ||
931 | LCR_PR(VCLKHW); | ||
932 | LCR_PR(OC); | ||
933 | #undef LCR_PR | ||
934 | } | ||
935 | #endif | ||
936 | |||
937 | #ifdef CONFIG_PM | ||
938 | static int tmiofb_suspend(struct platform_device *dev, pm_message_t state) | ||
939 | { | ||
940 | struct fb_info *info = platform_get_drvdata(dev); | ||
941 | struct tmiofb_par *par = info->par; | ||
942 | struct mfd_cell *cell = dev->dev.platform_data; | ||
943 | int retval = 0; | ||
944 | |||
945 | acquire_console_sem(); | ||
946 | |||
947 | fb_set_suspend(info, 1); | ||
948 | |||
949 | if (info->fbops->fb_sync) | ||
950 | info->fbops->fb_sync(info); | ||
951 | |||
952 | |||
953 | /* | ||
954 | * The fb should be usable even if interrupts are disabled (and they are | ||
955 | * during suspend/resume). Switch temporary to forced polling. | ||
956 | */ | ||
957 | printk(KERN_INFO "tmiofb: switching to polling\n"); | ||
958 | par->use_polling = true; | ||
959 | tmiofb_hw_stop(dev); | ||
960 | |||
961 | if (cell->suspend) | ||
962 | retval = cell->suspend(dev); | ||
963 | |||
964 | release_console_sem(); | ||
965 | |||
966 | return retval; | ||
967 | } | ||
968 | |||
969 | static int tmiofb_resume(struct platform_device *dev) | ||
970 | { | ||
971 | struct fb_info *info = platform_get_drvdata(dev); | ||
972 | struct mfd_cell *cell = dev->dev.platform_data; | ||
973 | int retval; | ||
974 | |||
975 | acquire_console_sem(); | ||
976 | |||
977 | if (cell->resume) { | ||
978 | retval = cell->resume(dev); | ||
979 | if (retval) | ||
980 | goto out; | ||
981 | } | ||
982 | |||
983 | tmiofb_irq(-1, info); | ||
984 | |||
985 | tmiofb_hw_init(dev); | ||
986 | |||
987 | tmiofb_hw_mode(dev); | ||
988 | |||
989 | fb_set_suspend(info, 0); | ||
990 | out: | ||
991 | release_console_sem(); | ||
992 | return retval; | ||
993 | } | ||
994 | #else | ||
995 | #define tmiofb_suspend NULL | ||
996 | #define tmiofb_resume NULL | ||
997 | #endif | ||
998 | |||
999 | static struct platform_driver tmiofb_driver = { | ||
1000 | .driver.name = "tmio-fb", | ||
1001 | .driver.owner = THIS_MODULE, | ||
1002 | .probe = tmiofb_probe, | ||
1003 | .remove = __devexit_p(tmiofb_remove), | ||
1004 | .suspend = tmiofb_suspend, | ||
1005 | .resume = tmiofb_resume, | ||
1006 | }; | ||
1007 | |||
1008 | /*--------------------------------------------------------------------------*/ | ||
1009 | |||
1010 | #ifndef MODULE | ||
1011 | static void __init tmiofb_setup(char *options) | ||
1012 | { | ||
1013 | char *this_opt; | ||
1014 | |||
1015 | if (!options || !*options) | ||
1016 | return; | ||
1017 | |||
1018 | while ((this_opt = strsep(&options, ",")) != NULL) { | ||
1019 | if (!*this_opt) | ||
1020 | continue; | ||
1021 | /* | ||
1022 | * FIXME | ||
1023 | */ | ||
1024 | } | ||
1025 | } | ||
1026 | #endif | ||
1027 | |||
1028 | static int __init tmiofb_init(void) | ||
1029 | { | ||
1030 | #ifndef MODULE | ||
1031 | char *option = NULL; | ||
1032 | |||
1033 | if (fb_get_options("tmiofb", &option)) | ||
1034 | return -ENODEV; | ||
1035 | tmiofb_setup(option); | ||
1036 | #endif | ||
1037 | return platform_driver_register(&tmiofb_driver); | ||
1038 | } | ||
1039 | |||
1040 | static void __exit tmiofb_cleanup(void) | ||
1041 | { | ||
1042 | platform_driver_unregister(&tmiofb_driver); | ||
1043 | } | ||
1044 | |||
1045 | module_init(tmiofb_init); | ||
1046 | module_exit(tmiofb_cleanup); | ||
1047 | |||
1048 | MODULE_DESCRIPTION("TMIO framebuffer driver"); | ||
1049 | MODULE_AUTHOR("Chris Humbert, Dirk Opfer, Dmitry Baryshkov"); | ||
1050 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c index 50744229c7a9..6c2d37fdd3b9 100644 --- a/drivers/video/uvesafb.c +++ b/drivers/video/uvesafb.c | |||
@@ -516,10 +516,12 @@ static int __devinit uvesafb_vbe_getmodes(struct uvesafb_ktask *task, | |||
516 | 516 | ||
517 | err = uvesafb_exec(task); | 517 | err = uvesafb_exec(task); |
518 | if (err || (task->t.regs.eax & 0xffff) != 0x004f) { | 518 | if (err || (task->t.regs.eax & 0xffff) != 0x004f) { |
519 | printk(KERN_ERR "uvesafb: Getting mode info block " | 519 | printk(KERN_WARNING "uvesafb: Getting mode info block " |
520 | "for mode 0x%x failed (eax=0x%x, err=%d)\n", | 520 | "for mode 0x%x failed (eax=0x%x, err=%d)\n", |
521 | *mode, (u32)task->t.regs.eax, err); | 521 | *mode, (u32)task->t.regs.eax, err); |
522 | return -EINVAL; | 522 | mode++; |
523 | par->vbe_modes_cnt--; | ||
524 | continue; | ||
523 | } | 525 | } |
524 | 526 | ||
525 | mib = task->buf; | 527 | mib = task->buf; |
@@ -548,7 +550,10 @@ static int __devinit uvesafb_vbe_getmodes(struct uvesafb_ktask *task, | |||
548 | mib->depth = mib->bits_per_pixel; | 550 | mib->depth = mib->bits_per_pixel; |
549 | } | 551 | } |
550 | 552 | ||
551 | return 0; | 553 | if (par->vbe_modes_cnt > 0) |
554 | return 0; | ||
555 | else | ||
556 | return -EINVAL; | ||
552 | } | 557 | } |
553 | 558 | ||
554 | /* | 559 | /* |
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index e31bca8a0cb2..5b2938903ac2 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c | |||
@@ -58,7 +58,6 @@ struct vga16fb_par { | |||
58 | unsigned char ClockingMode; /* Seq-Controller:01h */ | 58 | unsigned char ClockingMode; /* Seq-Controller:01h */ |
59 | } vga_state; | 59 | } vga_state; |
60 | struct vgastate state; | 60 | struct vgastate state; |
61 | struct mutex open_lock; | ||
62 | unsigned int ref_count; | 61 | unsigned int ref_count; |
63 | int palette_blanked, vesa_blanked, mode, isVGA; | 62 | int palette_blanked, vesa_blanked, mode, isVGA; |
64 | u8 misc, pel_msk, vss, clkdiv; | 63 | u8 misc, pel_msk, vss, clkdiv; |
@@ -286,7 +285,6 @@ static int vga16fb_open(struct fb_info *info, int user) | |||
286 | { | 285 | { |
287 | struct vga16fb_par *par = info->par; | 286 | struct vga16fb_par *par = info->par; |
288 | 287 | ||
289 | mutex_lock(&par->open_lock); | ||
290 | if (!par->ref_count) { | 288 | if (!par->ref_count) { |
291 | memset(&par->state, 0, sizeof(struct vgastate)); | 289 | memset(&par->state, 0, sizeof(struct vgastate)); |
292 | par->state.flags = VGA_SAVE_FONTS | VGA_SAVE_MODE | | 290 | par->state.flags = VGA_SAVE_FONTS | VGA_SAVE_MODE | |
@@ -294,7 +292,6 @@ static int vga16fb_open(struct fb_info *info, int user) | |||
294 | save_vga(&par->state); | 292 | save_vga(&par->state); |
295 | } | 293 | } |
296 | par->ref_count++; | 294 | par->ref_count++; |
297 | mutex_unlock(&par->open_lock); | ||
298 | 295 | ||
299 | return 0; | 296 | return 0; |
300 | } | 297 | } |
@@ -303,15 +300,12 @@ static int vga16fb_release(struct fb_info *info, int user) | |||
303 | { | 300 | { |
304 | struct vga16fb_par *par = info->par; | 301 | struct vga16fb_par *par = info->par; |
305 | 302 | ||
306 | mutex_lock(&par->open_lock); | 303 | if (!par->ref_count) |
307 | if (!par->ref_count) { | ||
308 | mutex_unlock(&par->open_lock); | ||
309 | return -EINVAL; | 304 | return -EINVAL; |
310 | } | 305 | |
311 | if (par->ref_count == 1) | 306 | if (par->ref_count == 1) |
312 | restore_vga(&par->state); | 307 | restore_vga(&par->state); |
313 | par->ref_count--; | 308 | par->ref_count--; |
314 | mutex_unlock(&par->open_lock); | ||
315 | 309 | ||
316 | return 0; | 310 | return 0; |
317 | } | 311 | } |
@@ -1326,7 +1320,6 @@ static int __init vga16fb_probe(struct platform_device *dev) | |||
1326 | printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base); | 1320 | printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base); |
1327 | par = info->par; | 1321 | par = info->par; |
1328 | 1322 | ||
1329 | mutex_init(&par->open_lock); | ||
1330 | par->isVGA = screen_info.orig_video_isVGA; | 1323 | par->isVGA = screen_info.orig_video_isVGA; |
1331 | par->palette_blanked = 0; | 1324 | par->palette_blanked = 0; |
1332 | par->vesa_blanked = 0; | 1325 | par->vesa_blanked = 0; |
diff --git a/drivers/video/via/Makefile b/drivers/video/via/Makefile new file mode 100644 index 000000000000..e533b4b6aba4 --- /dev/null +++ b/drivers/video/via/Makefile | |||
@@ -0,0 +1,7 @@ | |||
1 | # | ||
2 | # Makefile for the VIA framebuffer driver (for Linux Kernel 2.6) | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_FB_VIA) += viafb.o | ||
6 | |||
7 | viafb-y :=viafbdev.o hw.o iface.o via_i2c.o dvi.o lcd.o ioctl.o accel.o via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o | ||
diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c new file mode 100644 index 000000000000..632523ff1fb7 --- /dev/null +++ b/drivers/video/via/accel.c | |||
@@ -0,0 +1,279 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | #include "global.h" | ||
22 | |||
23 | void viafb_init_accel(void) | ||
24 | { | ||
25 | viaparinfo->fbmem_free -= CURSOR_SIZE; | ||
26 | viaparinfo->cursor_start = viaparinfo->fbmem_free; | ||
27 | viaparinfo->fbmem_used += CURSOR_SIZE; | ||
28 | |||
29 | /* Reverse 8*1024 memory space for cursor image */ | ||
30 | viaparinfo->fbmem_free -= (CURSOR_SIZE + VQ_SIZE); | ||
31 | viaparinfo->VQ_start = viaparinfo->fbmem_free; | ||
32 | viaparinfo->VQ_end = viaparinfo->VQ_start + VQ_SIZE - 1; | ||
33 | viaparinfo->fbmem_used += (CURSOR_SIZE + VQ_SIZE); } | ||
34 | |||
35 | void viafb_init_2d_engine(void) | ||
36 | { | ||
37 | u32 dwVQStartAddr, dwVQEndAddr; | ||
38 | u32 dwVQLen, dwVQStartL, dwVQEndL, dwVQStartEndH; | ||
39 | |||
40 | /* init 2D engine regs to reset 2D engine */ | ||
41 | writel(0x0, viaparinfo->io_virt + VIA_REG_GEMODE); | ||
42 | writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS); | ||
43 | writel(0x0, viaparinfo->io_virt + VIA_REG_DSTPOS); | ||
44 | writel(0x0, viaparinfo->io_virt + VIA_REG_DIMENSION); | ||
45 | writel(0x0, viaparinfo->io_virt + VIA_REG_PATADDR); | ||
46 | writel(0x0, viaparinfo->io_virt + VIA_REG_FGCOLOR); | ||
47 | writel(0x0, viaparinfo->io_virt + VIA_REG_BGCOLOR); | ||
48 | writel(0x0, viaparinfo->io_virt + VIA_REG_CLIPTL); | ||
49 | writel(0x0, viaparinfo->io_virt + VIA_REG_CLIPBR); | ||
50 | writel(0x0, viaparinfo->io_virt + VIA_REG_OFFSET); | ||
51 | writel(0x0, viaparinfo->io_virt + VIA_REG_KEYCONTROL); | ||
52 | writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE); | ||
53 | writel(0x0, viaparinfo->io_virt + VIA_REG_DSTBASE); | ||
54 | writel(0x0, viaparinfo->io_virt + VIA_REG_PITCH); | ||
55 | writel(0x0, viaparinfo->io_virt + VIA_REG_MONOPAT1); | ||
56 | |||
57 | /* Init AGP and VQ regs */ | ||
58 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
59 | case UNICHROME_K8M890: | ||
60 | case UNICHROME_P4M900: | ||
61 | writel(0x00100000, viaparinfo->io_virt + VIA_REG_CR_TRANSET); | ||
62 | writel(0x680A0000, viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); | ||
63 | writel(0x02000000, viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); | ||
64 | break; | ||
65 | |||
66 | default: | ||
67 | writel(0x00100000, viaparinfo->io_virt + VIA_REG_TRANSET); | ||
68 | writel(0x00000000, viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
69 | writel(0x00333004, viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
70 | writel(0x60000000, viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
71 | writel(0x61000000, viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
72 | writel(0x62000000, viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
73 | writel(0x63000000, viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
74 | writel(0x64000000, viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
75 | writel(0x7D000000, viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
76 | |||
77 | writel(0xFE020000, viaparinfo->io_virt + VIA_REG_TRANSET); | ||
78 | writel(0x00000000, viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
79 | break; | ||
80 | } | ||
81 | if (viaparinfo->VQ_start != 0) { | ||
82 | /* Enable VQ */ | ||
83 | dwVQStartAddr = viaparinfo->VQ_start; | ||
84 | dwVQEndAddr = viaparinfo->VQ_end; | ||
85 | |||
86 | dwVQStartL = 0x50000000 | (dwVQStartAddr & 0xFFFFFF); | ||
87 | dwVQEndL = 0x51000000 | (dwVQEndAddr & 0xFFFFFF); | ||
88 | dwVQStartEndH = 0x52000000 | | ||
89 | ((dwVQStartAddr & 0xFF000000) >> 24) | | ||
90 | ((dwVQEndAddr & 0xFF000000) >> 16); | ||
91 | dwVQLen = 0x53000000 | (VQ_SIZE >> 3); | ||
92 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
93 | case UNICHROME_K8M890: | ||
94 | case UNICHROME_P4M900: | ||
95 | dwVQStartL |= 0x20000000; | ||
96 | dwVQEndL |= 0x20000000; | ||
97 | dwVQStartEndH |= 0x20000000; | ||
98 | dwVQLen |= 0x20000000; | ||
99 | break; | ||
100 | default: | ||
101 | break; | ||
102 | } | ||
103 | |||
104 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
105 | case UNICHROME_K8M890: | ||
106 | case UNICHROME_P4M900: | ||
107 | writel(0x00100000, | ||
108 | viaparinfo->io_virt + VIA_REG_CR_TRANSET); | ||
109 | writel(dwVQStartEndH, | ||
110 | viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); | ||
111 | writel(dwVQStartL, | ||
112 | viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); | ||
113 | writel(dwVQEndL, | ||
114 | viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); | ||
115 | writel(dwVQLen, | ||
116 | viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); | ||
117 | writel(0x74301001, | ||
118 | viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); | ||
119 | writel(0x00000000, | ||
120 | viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); | ||
121 | break; | ||
122 | default: | ||
123 | writel(0x00FE0000, | ||
124 | viaparinfo->io_virt + VIA_REG_TRANSET); | ||
125 | writel(0x080003FE, | ||
126 | viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
127 | writel(0x0A00027C, | ||
128 | viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
129 | writel(0x0B000260, | ||
130 | viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
131 | writel(0x0C000274, | ||
132 | viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
133 | writel(0x0D000264, | ||
134 | viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
135 | writel(0x0E000000, | ||
136 | viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
137 | writel(0x0F000020, | ||
138 | viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
139 | writel(0x1000027E, | ||
140 | viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
141 | writel(0x110002FE, | ||
142 | viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
143 | writel(0x200F0060, | ||
144 | viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
145 | |||
146 | writel(0x00000006, | ||
147 | viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
148 | writel(0x40008C0F, | ||
149 | viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
150 | writel(0x44000000, | ||
151 | viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
152 | writel(0x45080C04, | ||
153 | viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
154 | writel(0x46800408, | ||
155 | viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
156 | |||
157 | writel(dwVQStartEndH, | ||
158 | viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
159 | writel(dwVQStartL, | ||
160 | viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
161 | writel(dwVQEndL, | ||
162 | viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
163 | writel(dwVQLen, | ||
164 | viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
165 | break; | ||
166 | } | ||
167 | } else { | ||
168 | /* Disable VQ */ | ||
169 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
170 | case UNICHROME_K8M890: | ||
171 | case UNICHROME_P4M900: | ||
172 | writel(0x00100000, | ||
173 | viaparinfo->io_virt + VIA_REG_CR_TRANSET); | ||
174 | writel(0x74301000, | ||
175 | viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); | ||
176 | break; | ||
177 | default: | ||
178 | writel(0x00FE0000, | ||
179 | viaparinfo->io_virt + VIA_REG_TRANSET); | ||
180 | writel(0x00000004, | ||
181 | viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
182 | writel(0x40008C0F, | ||
183 | viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
184 | writel(0x44000000, | ||
185 | viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
186 | writel(0x45080C04, | ||
187 | viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
188 | writel(0x46800408, | ||
189 | viaparinfo->io_virt + VIA_REG_TRANSPACE); | ||
190 | break; | ||
191 | } | ||
192 | } | ||
193 | |||
194 | viafb_set_2d_color_depth(viaparinfo->bpp); | ||
195 | |||
196 | writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE); | ||
197 | writel(0x0, viaparinfo->io_virt + VIA_REG_DSTBASE); | ||
198 | |||
199 | writel(VIA_PITCH_ENABLE | | ||
200 | (((viaparinfo->hres * | ||
201 | viaparinfo->bpp >> 3) >> 3) | (((viaparinfo->hres * | ||
202 | viaparinfo-> | ||
203 | bpp >> 3) >> 3) << 16)), | ||
204 | viaparinfo->io_virt + VIA_REG_PITCH); | ||
205 | } | ||
206 | |||
207 | void viafb_set_2d_color_depth(int bpp) | ||
208 | { | ||
209 | u32 dwGEMode; | ||
210 | |||
211 | dwGEMode = readl(viaparinfo->io_virt + 0x04) & 0xFFFFFCFF; | ||
212 | |||
213 | switch (bpp) { | ||
214 | case 16: | ||
215 | dwGEMode |= VIA_GEM_16bpp; | ||
216 | break; | ||
217 | case 32: | ||
218 | dwGEMode |= VIA_GEM_32bpp; | ||
219 | break; | ||
220 | default: | ||
221 | dwGEMode |= VIA_GEM_8bpp; | ||
222 | break; | ||
223 | } | ||
224 | |||
225 | /* Set BPP and Pitch */ | ||
226 | writel(dwGEMode, viaparinfo->io_virt + VIA_REG_GEMODE); | ||
227 | } | ||
228 | |||
229 | void viafb_hw_cursor_init(void) | ||
230 | { | ||
231 | /* Set Cursor Image Base Address */ | ||
232 | writel(viaparinfo->cursor_start, | ||
233 | viaparinfo->io_virt + VIA_REG_CURSOR_MODE); | ||
234 | writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_POS); | ||
235 | writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_ORG); | ||
236 | writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_BG); | ||
237 | writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_FG); | ||
238 | } | ||
239 | |||
240 | void viafb_show_hw_cursor(struct fb_info *info, int Status) | ||
241 | { | ||
242 | u32 temp; | ||
243 | u32 iga_path = ((struct viafb_par *)(info->par))->iga_path; | ||
244 | |||
245 | temp = readl(viaparinfo->io_virt + VIA_REG_CURSOR_MODE); | ||
246 | switch (Status) { | ||
247 | case HW_Cursor_ON: | ||
248 | temp |= 0x1; | ||
249 | break; | ||
250 | case HW_Cursor_OFF: | ||
251 | temp &= 0xFFFFFFFE; | ||
252 | break; | ||
253 | } | ||
254 | switch (iga_path) { | ||
255 | case IGA2: | ||
256 | temp |= 0x80000000; | ||
257 | break; | ||
258 | case IGA1: | ||
259 | default: | ||
260 | temp &= 0x7FFFFFFF; | ||
261 | } | ||
262 | writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_MODE); | ||
263 | } | ||
264 | |||
265 | int viafb_wait_engine_idle(void) | ||
266 | { | ||
267 | int loop = 0; | ||
268 | |||
269 | while (!(readl(viaparinfo->io_virt + VIA_REG_STATUS) & | ||
270 | VIA_VR_QUEUE_BUSY) && (loop++ < MAXLOOP)) | ||
271 | cpu_relax(); | ||
272 | |||
273 | while ((readl(viaparinfo->io_virt + VIA_REG_STATUS) & | ||
274 | (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY)) && | ||
275 | (loop++ < MAXLOOP)) | ||
276 | cpu_relax(); | ||
277 | |||
278 | return loop >= MAXLOOP; | ||
279 | } | ||
diff --git a/drivers/video/via/accel.h b/drivers/video/via/accel.h new file mode 100644 index 000000000000..29bf854e8ccf --- /dev/null +++ b/drivers/video/via/accel.h | |||
@@ -0,0 +1,169 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef __ACCEL_H__ | ||
23 | #define __ACCEL_H__ | ||
24 | |||
25 | #define FB_ACCEL_VIA_UNICHROME 50 | ||
26 | |||
27 | /* MMIO Base Address Definition */ | ||
28 | #define MMIO_VGABASE 0x8000 | ||
29 | #define MMIO_CR_READ (MMIO_VGABASE + 0x3D4) | ||
30 | #define MMIO_CR_WRITE (MMIO_VGABASE + 0x3D5) | ||
31 | #define MMIO_SR_READ (MMIO_VGABASE + 0x3C4) | ||
32 | #define MMIO_SR_WRITE (MMIO_VGABASE + 0x3C5) | ||
33 | |||
34 | /* HW Cursor Status Define */ | ||
35 | #define HW_Cursor_ON 0 | ||
36 | #define HW_Cursor_OFF 1 | ||
37 | |||
38 | #define CURSOR_SIZE (8 * 1024) | ||
39 | #define VQ_SIZE (256 * 1024) | ||
40 | |||
41 | #define VIA_MMIO_BLTBASE 0x200000 | ||
42 | #define VIA_MMIO_BLTSIZE 0x200000 | ||
43 | |||
44 | /* Defines for 2D registers */ | ||
45 | #define VIA_REG_GECMD 0x000 | ||
46 | #define VIA_REG_GEMODE 0x004 | ||
47 | #define VIA_REG_SRCPOS 0x008 | ||
48 | #define VIA_REG_DSTPOS 0x00C | ||
49 | /* width and height */ | ||
50 | #define VIA_REG_DIMENSION 0x010 | ||
51 | #define VIA_REG_PATADDR 0x014 | ||
52 | #define VIA_REG_FGCOLOR 0x018 | ||
53 | #define VIA_REG_BGCOLOR 0x01C | ||
54 | /* top and left of clipping */ | ||
55 | #define VIA_REG_CLIPTL 0x020 | ||
56 | /* bottom and right of clipping */ | ||
57 | #define VIA_REG_CLIPBR 0x024 | ||
58 | #define VIA_REG_OFFSET 0x028 | ||
59 | /* color key control */ | ||
60 | #define VIA_REG_KEYCONTROL 0x02C | ||
61 | #define VIA_REG_SRCBASE 0x030 | ||
62 | #define VIA_REG_DSTBASE 0x034 | ||
63 | /* pitch of src and dst */ | ||
64 | #define VIA_REG_PITCH 0x038 | ||
65 | #define VIA_REG_MONOPAT0 0x03C | ||
66 | #define VIA_REG_MONOPAT1 0x040 | ||
67 | /* from 0x100 to 0x1ff */ | ||
68 | #define VIA_REG_COLORPAT 0x100 | ||
69 | |||
70 | /* VIA_REG_PITCH(0x38): Pitch Setting */ | ||
71 | #define VIA_PITCH_ENABLE 0x80000000 | ||
72 | |||
73 | /* defines for VIA HW cursor registers */ | ||
74 | #define VIA_REG_CURSOR_MODE 0x2D0 | ||
75 | #define VIA_REG_CURSOR_POS 0x2D4 | ||
76 | #define VIA_REG_CURSOR_ORG 0x2D8 | ||
77 | #define VIA_REG_CURSOR_BG 0x2DC | ||
78 | #define VIA_REG_CURSOR_FG 0x2E0 | ||
79 | |||
80 | /* VIA_REG_GEMODE(0x04): GE mode */ | ||
81 | #define VIA_GEM_8bpp 0x00000000 | ||
82 | #define VIA_GEM_16bpp 0x00000100 | ||
83 | #define VIA_GEM_32bpp 0x00000300 | ||
84 | |||
85 | /* VIA_REG_GECMD(0x00): 2D Engine Command */ | ||
86 | #define VIA_GEC_NOOP 0x00000000 | ||
87 | #define VIA_GEC_BLT 0x00000001 | ||
88 | #define VIA_GEC_LINE 0x00000005 | ||
89 | |||
90 | /* Rotate Command */ | ||
91 | #define VIA_GEC_ROT 0x00000008 | ||
92 | |||
93 | #define VIA_GEC_SRC_XY 0x00000000 | ||
94 | #define VIA_GEC_SRC_LINEAR 0x00000010 | ||
95 | #define VIA_GEC_DST_XY 0x00000000 | ||
96 | #define VIA_GEC_DST_LINRAT 0x00000020 | ||
97 | |||
98 | #define VIA_GEC_SRC_FB 0x00000000 | ||
99 | #define VIA_GEC_SRC_SYS 0x00000040 | ||
100 | #define VIA_GEC_DST_FB 0x00000000 | ||
101 | #define VIA_GEC_DST_SYS 0x00000080 | ||
102 | |||
103 | /* source is mono */ | ||
104 | #define VIA_GEC_SRC_MONO 0x00000100 | ||
105 | /* pattern is mono */ | ||
106 | #define VIA_GEC_PAT_MONO 0x00000200 | ||
107 | /* mono src is opaque */ | ||
108 | #define VIA_GEC_MSRC_OPAQUE 0x00000000 | ||
109 | /* mono src is transparent */ | ||
110 | #define VIA_GEC_MSRC_TRANS 0x00000400 | ||
111 | /* pattern is in frame buffer */ | ||
112 | #define VIA_GEC_PAT_FB 0x00000000 | ||
113 | /* pattern is from reg setting */ | ||
114 | #define VIA_GEC_PAT_REG 0x00000800 | ||
115 | |||
116 | #define VIA_GEC_CLIP_DISABLE 0x00000000 | ||
117 | #define VIA_GEC_CLIP_ENABLE 0x00001000 | ||
118 | |||
119 | #define VIA_GEC_FIXCOLOR_PAT 0x00002000 | ||
120 | |||
121 | #define VIA_GEC_INCX 0x00000000 | ||
122 | #define VIA_GEC_DECY 0x00004000 | ||
123 | #define VIA_GEC_INCY 0x00000000 | ||
124 | #define VIA_GEC_DECX 0x00008000 | ||
125 | /* mono pattern is opaque */ | ||
126 | #define VIA_GEC_MPAT_OPAQUE 0x00000000 | ||
127 | /* mono pattern is transparent */ | ||
128 | #define VIA_GEC_MPAT_TRANS 0x00010000 | ||
129 | |||
130 | #define VIA_GEC_MONO_UNPACK 0x00000000 | ||
131 | #define VIA_GEC_MONO_PACK 0x00020000 | ||
132 | #define VIA_GEC_MONO_DWORD 0x00000000 | ||
133 | #define VIA_GEC_MONO_WORD 0x00040000 | ||
134 | #define VIA_GEC_MONO_BYTE 0x00080000 | ||
135 | |||
136 | #define VIA_GEC_LASTPIXEL_ON 0x00000000 | ||
137 | #define VIA_GEC_LASTPIXEL_OFF 0x00100000 | ||
138 | #define VIA_GEC_X_MAJOR 0x00000000 | ||
139 | #define VIA_GEC_Y_MAJOR 0x00200000 | ||
140 | #define VIA_GEC_QUICK_START 0x00800000 | ||
141 | |||
142 | /* defines for VIA 3D registers */ | ||
143 | #define VIA_REG_STATUS 0x400 | ||
144 | #define VIA_REG_CR_TRANSET 0x41C | ||
145 | #define VIA_REG_CR_TRANSPACE 0x420 | ||
146 | #define VIA_REG_TRANSET 0x43C | ||
147 | #define VIA_REG_TRANSPACE 0x440 | ||
148 | |||
149 | /* VIA_REG_STATUS(0x400): Engine Status */ | ||
150 | |||
151 | /* Command Regulator is busy */ | ||
152 | #define VIA_CMD_RGTR_BUSY 0x00000080 | ||
153 | /* 2D Engine is busy */ | ||
154 | #define VIA_2D_ENG_BUSY 0x00000002 | ||
155 | /* 3D Engine is busy */ | ||
156 | #define VIA_3D_ENG_BUSY 0x00000001 | ||
157 | /* Virtual Queue is busy */ | ||
158 | #define VIA_VR_QUEUE_BUSY 0x00020000 | ||
159 | |||
160 | #define MAXLOOP 0xFFFFFF | ||
161 | |||
162 | void viafb_init_accel(void); | ||
163 | void viafb_init_2d_engine(void); | ||
164 | void set_2d_color_depth(int); | ||
165 | void viafb_hw_cursor_init(void); | ||
166 | void viafb_show_hw_cursor(struct fb_info *info, int Status); int | ||
167 | viafb_wait_engine_idle(void); void viafb_set_2d_color_depth(int bpp); | ||
168 | |||
169 | #endif /* __ACCEL_H__ */ | ||
diff --git a/drivers/video/via/chip.h b/drivers/video/via/chip.h new file mode 100644 index 000000000000..dde95edc387a --- /dev/null +++ b/drivers/video/via/chip.h | |||
@@ -0,0 +1,190 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | #ifndef __CHIP_H__ | ||
22 | #define __CHIP_H__ | ||
23 | |||
24 | #include "global.h" | ||
25 | |||
26 | /***************************************/ | ||
27 | /* Definition Graphic Chip Information */ | ||
28 | /***************************************/ | ||
29 | |||
30 | #define PCI_VIA_VENDOR_ID 0x1106 | ||
31 | |||
32 | /* Define VIA Graphic Chip Name */ | ||
33 | #define UNICHROME_CLE266 1 | ||
34 | #define UNICHROME_CLE266_DID 0x3122 | ||
35 | #define CLE266_REVISION_AX 0x0A | ||
36 | #define CLE266_REVISION_CX 0x0C | ||
37 | |||
38 | #define UNICHROME_K400 2 | ||
39 | #define UNICHROME_K400_DID 0x7205 | ||
40 | |||
41 | #define UNICHROME_K800 3 | ||
42 | #define UNICHROME_K800_DID 0x3108 | ||
43 | |||
44 | #define UNICHROME_PM800 4 | ||
45 | #define UNICHROME_PM800_DID 0x3118 | ||
46 | |||
47 | #define UNICHROME_CN700 5 | ||
48 | #define UNICHROME_CN700_DID 0x3344 | ||
49 | |||
50 | #define UNICHROME_CX700 6 | ||
51 | #define UNICHROME_CX700_DID 0x3157 | ||
52 | #define CX700_REVISION_700 0x0 | ||
53 | #define CX700_REVISION_700M 0x1 | ||
54 | #define CX700_REVISION_700M2 0x2 | ||
55 | |||
56 | #define UNICHROME_CN750 7 | ||
57 | #define UNICHROME_CN750_DID 0x3225 | ||
58 | |||
59 | #define UNICHROME_K8M890 8 | ||
60 | #define UNICHROME_K8M890_DID 0x3230 | ||
61 | |||
62 | #define UNICHROME_P4M890 9 | ||
63 | #define UNICHROME_P4M890_DID 0x3343 | ||
64 | |||
65 | #define UNICHROME_P4M900 10 | ||
66 | #define UNICHROME_P4M900_DID 0x3371 | ||
67 | |||
68 | #define UNICHROME_VX800 11 | ||
69 | #define UNICHROME_VX800_DID 0x1122 | ||
70 | |||
71 | /**************************************************/ | ||
72 | /* Definition TMDS Trasmitter Information */ | ||
73 | /**************************************************/ | ||
74 | |||
75 | /* Definition TMDS Trasmitter Index */ | ||
76 | #define NON_TMDS_TRANSMITTER 0x00 | ||
77 | #define VT1632_TMDS 0x01 | ||
78 | #define INTEGRATED_TMDS 0x42 | ||
79 | |||
80 | /* Definition TMDS Trasmitter I2C Slave Address */ | ||
81 | #define VT1632_TMDS_I2C_ADDR 0x10 | ||
82 | |||
83 | /**************************************************/ | ||
84 | /* Definition LVDS Trasmitter Information */ | ||
85 | /**************************************************/ | ||
86 | |||
87 | /* Definition LVDS Trasmitter Index */ | ||
88 | #define NON_LVDS_TRANSMITTER 0x00 | ||
89 | #define VT1631_LVDS 0x01 | ||
90 | #define VT1636_LVDS 0x0E | ||
91 | #define INTEGRATED_LVDS 0x41 | ||
92 | |||
93 | /* Definition Digital Transmitter Mode */ | ||
94 | #define TX_DATA_12_BITS 0x01 | ||
95 | #define TX_DATA_24_BITS 0x02 | ||
96 | #define TX_DATA_DDR_MODE 0x04 | ||
97 | #define TX_DATA_SDR_MODE 0x08 | ||
98 | |||
99 | /* Definition LVDS Trasmitter I2C Slave Address */ | ||
100 | #define VT1631_LVDS_I2C_ADDR 0x70 | ||
101 | #define VT3271_LVDS_I2C_ADDR 0x80 | ||
102 | #define VT1636_LVDS_I2C_ADDR 0x80 | ||
103 | |||
104 | struct tmds_chip_information { | ||
105 | int tmds_chip_name; | ||
106 | int tmds_chip_slave_addr; | ||
107 | int dvi_panel_id; | ||
108 | int data_mode; | ||
109 | int output_interface; | ||
110 | int i2c_port; | ||
111 | int device_type; | ||
112 | }; | ||
113 | |||
114 | struct lvds_chip_information { | ||
115 | int lvds_chip_name; | ||
116 | int lvds_chip_slave_addr; | ||
117 | int data_mode; | ||
118 | int output_interface; | ||
119 | int i2c_port; | ||
120 | }; | ||
121 | |||
122 | struct chip_information { | ||
123 | int gfx_chip_name; | ||
124 | int gfx_chip_revision; | ||
125 | int chip_on_slot; | ||
126 | struct tmds_chip_information tmds_chip_info; | ||
127 | struct lvds_chip_information lvds_chip_info; | ||
128 | struct lvds_chip_information lvds_chip_info2; | ||
129 | }; | ||
130 | |||
131 | struct crt_setting_information { | ||
132 | int iga_path; | ||
133 | int h_active; | ||
134 | int v_active; | ||
135 | int bpp; | ||
136 | int refresh_rate; | ||
137 | }; | ||
138 | |||
139 | struct tmds_setting_information { | ||
140 | int iga_path; | ||
141 | int h_active; | ||
142 | int v_active; | ||
143 | int bpp; | ||
144 | int refresh_rate; | ||
145 | int get_dvi_size_method; | ||
146 | int max_pixel_clock; | ||
147 | int dvi_panel_size; | ||
148 | int dvi_panel_hres; | ||
149 | int dvi_panel_vres; | ||
150 | int native_size; | ||
151 | }; | ||
152 | |||
153 | struct lvds_setting_information { | ||
154 | int iga_path; | ||
155 | int h_active; | ||
156 | int v_active; | ||
157 | int bpp; | ||
158 | int refresh_rate; | ||
159 | int get_lcd_size_method; | ||
160 | int lcd_panel_id; | ||
161 | int lcd_panel_size; | ||
162 | int lcd_panel_hres; | ||
163 | int lcd_panel_vres; | ||
164 | int display_method; | ||
165 | int device_lcd_dualedge; | ||
166 | int LCDDithering; | ||
167 | int lcd_mode; | ||
168 | u32 vclk; /*panel mode clock value */ | ||
169 | }; | ||
170 | |||
171 | struct GFX_DPA_SETTING { | ||
172 | int ClkRangeIndex; | ||
173 | u8 DVP0; /* CR96[3:0] */ | ||
174 | u8 DVP0DataDri_S1; /* SR2A[5] */ | ||
175 | u8 DVP0DataDri_S; /* SR1B[1] */ | ||
176 | u8 DVP0ClockDri_S1; /* SR2A[4] */ | ||
177 | u8 DVP0ClockDri_S; /* SR1E[2] */ | ||
178 | u8 DVP1; /* CR9B[3:0] */ | ||
179 | u8 DVP1Driving; /* SR65[3:0], Data and Clock driving */ | ||
180 | u8 DFPHigh; /* CR97[3:0] */ | ||
181 | u8 DFPLow; /* CR99[3:0] */ | ||
182 | |||
183 | }; | ||
184 | |||
185 | struct VT1636_DPA_SETTING { | ||
186 | int PanelSizeID; | ||
187 | u8 CLK_SEL_ST1; | ||
188 | u8 CLK_SEL_ST2; | ||
189 | }; | ||
190 | #endif /* __CHIP_H__ */ | ||
diff --git a/drivers/video/via/debug.h b/drivers/video/via/debug.h new file mode 100644 index 000000000000..86eacc2017f3 --- /dev/null +++ b/drivers/video/via/debug.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | #ifndef __DEBUG_H__ | ||
22 | #define __DEBUG_H__ | ||
23 | |||
24 | #ifndef VIAFB_DEBUG | ||
25 | #define VIAFB_DEBUG 0 | ||
26 | #endif | ||
27 | |||
28 | #if VIAFB_DEBUG | ||
29 | #define DEBUG_MSG(f, a...) printk(f, ## a) | ||
30 | #else | ||
31 | #define DEBUG_MSG(f, a...) | ||
32 | #endif | ||
33 | |||
34 | #define VIAFB_WARN 0 | ||
35 | #if VIAFB_WARN | ||
36 | #define WARN_MSG(f, a...) printk(f, ## a) | ||
37 | #else | ||
38 | #define WARN_MSG(f, a...) | ||
39 | #endif | ||
40 | |||
41 | #endif /* __DEBUG_H__ */ | ||
diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c new file mode 100644 index 000000000000..d6965447ca69 --- /dev/null +++ b/drivers/video/via/dvi.c | |||
@@ -0,0 +1,682 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | #include "global.h" | ||
22 | |||
23 | static void tmds_register_write(int index, u8 data); | ||
24 | static int tmds_register_read(int index); | ||
25 | static int tmds_register_read_bytes(int index, u8 *buff, int buff_len); | ||
26 | static int check_reduce_blanking_mode(int mode_index, | ||
27 | int refresh_rate); | ||
28 | static int dvi_get_panel_size_from_DDCv1(void); | ||
29 | static int dvi_get_panel_size_from_DDCv2(void); | ||
30 | static unsigned char dvi_get_panel_info(void); | ||
31 | static int viafb_dvi_query_EDID(void); | ||
32 | |||
33 | static int check_tmds_chip(int device_id_subaddr, int device_id) | ||
34 | { | ||
35 | if (tmds_register_read(device_id_subaddr) == device_id) | ||
36 | return OK; | ||
37 | else | ||
38 | return FAIL; | ||
39 | } | ||
40 | |||
41 | void viafb_init_dvi_size(void) | ||
42 | { | ||
43 | DEBUG_MSG(KERN_INFO "viafb_init_dvi_size()\n"); | ||
44 | DEBUG_MSG(KERN_INFO | ||
45 | "viaparinfo->tmds_setting_info->get_dvi_size_method %d\n", | ||
46 | viaparinfo->tmds_setting_info->get_dvi_size_method); | ||
47 | |||
48 | switch (viaparinfo->tmds_setting_info->get_dvi_size_method) { | ||
49 | case GET_DVI_SIZE_BY_SYSTEM_BIOS: | ||
50 | break; | ||
51 | case GET_DVI_SZIE_BY_HW_STRAPPING: | ||
52 | break; | ||
53 | case GET_DVI_SIZE_BY_VGA_BIOS: | ||
54 | default: | ||
55 | dvi_get_panel_info(); | ||
56 | break; | ||
57 | } | ||
58 | return; | ||
59 | } | ||
60 | |||
61 | int viafb_tmds_trasmitter_identify(void) | ||
62 | { | ||
63 | unsigned char sr2a = 0, sr1e = 0, sr3e = 0; | ||
64 | |||
65 | /* Turn on ouputting pad */ | ||
66 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
67 | case UNICHROME_K8M890: | ||
68 | /*=* DFP Low Pad on *=*/ | ||
69 | sr2a = viafb_read_reg(VIASR, SR2A); | ||
70 | viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1); | ||
71 | break; | ||
72 | |||
73 | case UNICHROME_P4M900: | ||
74 | case UNICHROME_P4M890: | ||
75 | /* DFP Low Pad on */ | ||
76 | sr2a = viafb_read_reg(VIASR, SR2A); | ||
77 | viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1); | ||
78 | /* DVP0 Pad on */ | ||
79 | sr1e = viafb_read_reg(VIASR, SR1E); | ||
80 | viafb_write_reg_mask(SR1E, VIASR, 0xC0, BIT6 + BIT7); | ||
81 | break; | ||
82 | |||
83 | default: | ||
84 | /* DVP0/DVP1 Pad on */ | ||
85 | sr1e = viafb_read_reg(VIASR, SR1E); | ||
86 | viafb_write_reg_mask(SR1E, VIASR, 0xF0, BIT4 + | ||
87 | BIT5 + BIT6 + BIT7); | ||
88 | /* SR3E[1]Multi-function selection: | ||
89 | 0 = Emulate I2C and DDC bus by GPIO2/3/4. */ | ||
90 | sr3e = viafb_read_reg(VIASR, SR3E); | ||
91 | viafb_write_reg_mask(SR3E, VIASR, 0x0, BIT5); | ||
92 | break; | ||
93 | } | ||
94 | |||
95 | /* Check for VT1632: */ | ||
96 | viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = VT1632_TMDS; | ||
97 | viaparinfo->chip_info-> | ||
98 | tmds_chip_info.tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR; | ||
99 | viaparinfo->chip_info->tmds_chip_info.i2c_port = I2CPORTINDEX; | ||
100 | if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID) != FAIL) { | ||
101 | /* | ||
102 | * Currently only support 12bits,dual edge,add 24bits mode later | ||
103 | */ | ||
104 | tmds_register_write(0x08, 0x3b); | ||
105 | |||
106 | DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n"); | ||
107 | DEBUG_MSG(KERN_INFO "\n %2d", | ||
108 | viaparinfo->chip_info->tmds_chip_info.tmds_chip_name); | ||
109 | DEBUG_MSG(KERN_INFO "\n %2d", | ||
110 | viaparinfo->chip_info->tmds_chip_info.i2c_port); | ||
111 | return OK; | ||
112 | } else { | ||
113 | viaparinfo->chip_info->tmds_chip_info.i2c_port = GPIOPORTINDEX; | ||
114 | if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID) | ||
115 | != FAIL) { | ||
116 | tmds_register_write(0x08, 0x3b); | ||
117 | DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n"); | ||
118 | DEBUG_MSG(KERN_INFO "\n %2d", | ||
119 | viaparinfo->chip_info-> | ||
120 | tmds_chip_info.tmds_chip_name); | ||
121 | DEBUG_MSG(KERN_INFO "\n %2d", | ||
122 | viaparinfo->chip_info-> | ||
123 | tmds_chip_info.i2c_port); | ||
124 | return OK; | ||
125 | } | ||
126 | } | ||
127 | |||
128 | viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = INTEGRATED_TMDS; | ||
129 | |||
130 | if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) && | ||
131 | ((viafb_display_hardware_layout == HW_LAYOUT_DVI_ONLY) || | ||
132 | (viafb_display_hardware_layout == HW_LAYOUT_LCD_DVI))) { | ||
133 | DEBUG_MSG(KERN_INFO "\n Integrated TMDS ! \n"); | ||
134 | return OK; | ||
135 | } | ||
136 | |||
137 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
138 | case UNICHROME_K8M890: | ||
139 | viafb_write_reg(SR2A, VIASR, sr2a); | ||
140 | break; | ||
141 | |||
142 | case UNICHROME_P4M900: | ||
143 | case UNICHROME_P4M890: | ||
144 | viafb_write_reg(SR2A, VIASR, sr2a); | ||
145 | viafb_write_reg(SR1E, VIASR, sr1e); | ||
146 | break; | ||
147 | |||
148 | default: | ||
149 | viafb_write_reg(SR1E, VIASR, sr1e); | ||
150 | viafb_write_reg(SR3E, VIASR, sr3e); | ||
151 | break; | ||
152 | } | ||
153 | |||
154 | viaparinfo->chip_info-> | ||
155 | tmds_chip_info.tmds_chip_name = NON_TMDS_TRANSMITTER; | ||
156 | viaparinfo->chip_info->tmds_chip_info. | ||
157 | tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR; | ||
158 | return FAIL; | ||
159 | } | ||
160 | |||
161 | static void tmds_register_write(int index, u8 data) | ||
162 | { | ||
163 | viaparinfo->i2c_stuff.i2c_port = | ||
164 | viaparinfo->chip_info->tmds_chip_info.i2c_port; | ||
165 | |||
166 | viafb_i2c_writebyte(viaparinfo->chip_info->tmds_chip_info. | ||
167 | tmds_chip_slave_addr, index, | ||
168 | data); | ||
169 | } | ||
170 | |||
171 | static int tmds_register_read(int index) | ||
172 | { | ||
173 | u8 data; | ||
174 | |||
175 | viaparinfo->i2c_stuff.i2c_port = | ||
176 | viaparinfo->chip_info->tmds_chip_info.i2c_port; | ||
177 | viafb_i2c_readbyte((u8) viaparinfo->chip_info-> | ||
178 | tmds_chip_info.tmds_chip_slave_addr, | ||
179 | (u8) index, &data); | ||
180 | return data; | ||
181 | } | ||
182 | |||
183 | static int tmds_register_read_bytes(int index, u8 *buff, int buff_len) | ||
184 | { | ||
185 | viaparinfo->i2c_stuff.i2c_port = | ||
186 | viaparinfo->chip_info->tmds_chip_info.i2c_port; | ||
187 | viafb_i2c_readbytes((u8) viaparinfo->chip_info->tmds_chip_info. | ||
188 | tmds_chip_slave_addr, (u8) index, buff, buff_len); | ||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static int check_reduce_blanking_mode(int mode_index, | ||
193 | int refresh_rate) | ||
194 | { | ||
195 | if (refresh_rate != 60) | ||
196 | return false; | ||
197 | |||
198 | switch (mode_index) { | ||
199 | /* Following modes have reduce blanking mode. */ | ||
200 | case VIA_RES_1360X768: | ||
201 | case VIA_RES_1400X1050: | ||
202 | case VIA_RES_1440X900: | ||
203 | case VIA_RES_1600X900: | ||
204 | case VIA_RES_1680X1050: | ||
205 | case VIA_RES_1920X1080: | ||
206 | case VIA_RES_1920X1200: | ||
207 | break; | ||
208 | |||
209 | default: | ||
210 | DEBUG_MSG(KERN_INFO | ||
211 | "This dvi mode %d have no reduce blanking mode!\n", | ||
212 | mode_index); | ||
213 | return false; | ||
214 | } | ||
215 | |||
216 | return true; | ||
217 | } | ||
218 | |||
219 | /* DVI Set Mode */ | ||
220 | void viafb_dvi_set_mode(int video_index, int mode_bpp, int set_iga) | ||
221 | { | ||
222 | struct VideoModeTable *videoMode = NULL; | ||
223 | struct crt_mode_table *pDviTiming; | ||
224 | unsigned long desirePixelClock, maxPixelClock; | ||
225 | int status = 0; | ||
226 | videoMode = viafb_get_modetbl_pointer(video_index); | ||
227 | pDviTiming = videoMode->crtc; | ||
228 | desirePixelClock = pDviTiming->clk / 1000000; | ||
229 | maxPixelClock = (unsigned long)viaparinfo-> | ||
230 | tmds_setting_info->max_pixel_clock; | ||
231 | |||
232 | DEBUG_MSG(KERN_INFO "\nDVI_set_mode!!\n"); | ||
233 | |||
234 | if ((maxPixelClock != 0) && (desirePixelClock > maxPixelClock)) { | ||
235 | /*Check if reduce-blanking mode is exist */ | ||
236 | status = | ||
237 | check_reduce_blanking_mode(video_index, | ||
238 | pDviTiming->refresh_rate); | ||
239 | if (status) { | ||
240 | video_index += 100; /*Use reduce-blanking mode */ | ||
241 | videoMode = viafb_get_modetbl_pointer(video_index); | ||
242 | pDviTiming = videoMode->crtc; | ||
243 | DEBUG_MSG(KERN_INFO | ||
244 | "DVI use reduce blanking mode %d!!\n", | ||
245 | video_index); | ||
246 | } | ||
247 | } | ||
248 | viafb_fill_crtc_timing(pDviTiming, video_index, mode_bpp / 8, set_iga); | ||
249 | viafb_set_output_path(DEVICE_DVI, set_iga, | ||
250 | viaparinfo->chip_info->tmds_chip_info.output_interface); | ||
251 | } | ||
252 | |||
253 | /* Sense DVI Connector */ | ||
254 | int viafb_dvi_sense(void) | ||
255 | { | ||
256 | u8 RegSR1E = 0, RegSR3E = 0, RegCR6B = 0, RegCR91 = 0, | ||
257 | RegCR93 = 0, RegCR9B = 0, data; | ||
258 | int ret = false; | ||
259 | |||
260 | DEBUG_MSG(KERN_INFO "viafb_dvi_sense!!\n"); | ||
261 | |||
262 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) { | ||
263 | /* DI1 Pad on */ | ||
264 | RegSR1E = viafb_read_reg(VIASR, SR1E); | ||
265 | viafb_write_reg(SR1E, VIASR, RegSR1E | 0x30); | ||
266 | |||
267 | /* CR6B[0]VCK Input Selection: 1 = External clock. */ | ||
268 | RegCR6B = viafb_read_reg(VIACR, CR6B); | ||
269 | viafb_write_reg(CR6B, VIACR, RegCR6B | 0x08); | ||
270 | |||
271 | /* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off | ||
272 | [0] Software Control Power Sequence */ | ||
273 | RegCR91 = viafb_read_reg(VIACR, CR91); | ||
274 | viafb_write_reg(CR91, VIACR, 0x1D); | ||
275 | |||
276 | /* CR93[7] DI1 Data Source Selection: 1 = DSP2. | ||
277 | CR93[5] DI1 Clock Source: 1 = internal. | ||
278 | CR93[4] DI1 Clock Polarity. | ||
279 | CR93[3:1] DI1 Clock Adjust. CR93[0] DI1 enable */ | ||
280 | RegCR93 = viafb_read_reg(VIACR, CR93); | ||
281 | viafb_write_reg(CR93, VIACR, 0x01); | ||
282 | } else { | ||
283 | /* DVP0/DVP1 Pad on */ | ||
284 | RegSR1E = viafb_read_reg(VIASR, SR1E); | ||
285 | viafb_write_reg(SR1E, VIASR, RegSR1E | 0xF0); | ||
286 | |||
287 | /* SR3E[1]Multi-function selection: | ||
288 | 0 = Emulate I2C and DDC bus by GPIO2/3/4. */ | ||
289 | RegSR3E = viafb_read_reg(VIASR, SR3E); | ||
290 | viafb_write_reg(SR3E, VIASR, RegSR3E & (~0x20)); | ||
291 | |||
292 | /* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off | ||
293 | [0] Software Control Power Sequence */ | ||
294 | RegCR91 = viafb_read_reg(VIACR, CR91); | ||
295 | viafb_write_reg(CR91, VIACR, 0x1D); | ||
296 | |||
297 | /*CR9B[4] DVP1 Data Source Selection: 1 = From secondary | ||
298 | display.CR9B[2:0] DVP1 Clock Adjust */ | ||
299 | RegCR9B = viafb_read_reg(VIACR, CR9B); | ||
300 | viafb_write_reg(CR9B, VIACR, 0x01); | ||
301 | } | ||
302 | |||
303 | data = (u8) tmds_register_read(0x09); | ||
304 | if (data & 0x04) | ||
305 | ret = true; | ||
306 | |||
307 | if (ret == false) { | ||
308 | if (viafb_dvi_query_EDID()) | ||
309 | ret = true; | ||
310 | } | ||
311 | |||
312 | /* Restore status */ | ||
313 | viafb_write_reg(SR1E, VIASR, RegSR1E); | ||
314 | viafb_write_reg(CR91, VIACR, RegCR91); | ||
315 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) { | ||
316 | viafb_write_reg(CR6B, VIACR, RegCR6B); | ||
317 | viafb_write_reg(CR93, VIACR, RegCR93); | ||
318 | } else { | ||
319 | viafb_write_reg(SR3E, VIASR, RegSR3E); | ||
320 | viafb_write_reg(CR9B, VIACR, RegCR9B); | ||
321 | } | ||
322 | |||
323 | return ret; | ||
324 | } | ||
325 | |||
326 | /* Query Flat Panel's EDID Table Version Through DVI Connector */ | ||
327 | static int viafb_dvi_query_EDID(void) | ||
328 | { | ||
329 | u8 data0, data1; | ||
330 | int restore; | ||
331 | |||
332 | DEBUG_MSG(KERN_INFO "viafb_dvi_query_EDID!!\n"); | ||
333 | |||
334 | restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr; | ||
335 | viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA0; | ||
336 | |||
337 | data0 = (u8) tmds_register_read(0x00); | ||
338 | data1 = (u8) tmds_register_read(0x01); | ||
339 | if ((data0 == 0) && (data1 == 0xFF)) { | ||
340 | viaparinfo->chip_info-> | ||
341 | tmds_chip_info.tmds_chip_slave_addr = restore; | ||
342 | return EDID_VERSION_1; /* Found EDID1 Table */ | ||
343 | } | ||
344 | |||
345 | data0 = (u8) tmds_register_read(0x00); | ||
346 | viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore; | ||
347 | if (data0 == 0x20) | ||
348 | return EDID_VERSION_2; /* Found EDID2 Table */ | ||
349 | else | ||
350 | return false; | ||
351 | } | ||
352 | |||
353 | /* | ||
354 | * | ||
355 | * int dvi_get_panel_size_from_DDCv1(void) | ||
356 | * | ||
357 | * - Get Panel Size Using EDID1 Table | ||
358 | * | ||
359 | * Return Type: int | ||
360 | * | ||
361 | */ | ||
362 | static int dvi_get_panel_size_from_DDCv1(void) | ||
363 | { | ||
364 | int i, max_h = 0, max_v = 0, tmp, restore; | ||
365 | unsigned char rData; | ||
366 | unsigned char EDID_DATA[18]; | ||
367 | |||
368 | DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv1 \n"); | ||
369 | |||
370 | restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr; | ||
371 | viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA0; | ||
372 | |||
373 | rData = tmds_register_read(0x23); | ||
374 | if (rData & 0x3C) | ||
375 | max_h = 640; | ||
376 | if (rData & 0xC0) | ||
377 | max_h = 720; | ||
378 | if (rData & 0x03) | ||
379 | max_h = 800; | ||
380 | |||
381 | rData = tmds_register_read(0x24); | ||
382 | if (rData & 0xC0) | ||
383 | max_h = 800; | ||
384 | if (rData & 0x1E) | ||
385 | max_h = 1024; | ||
386 | if (rData & 0x01) | ||
387 | max_h = 1280; | ||
388 | |||
389 | for (i = 0x25; i < 0x6D; i++) { | ||
390 | switch (i) { | ||
391 | case 0x26: | ||
392 | case 0x28: | ||
393 | case 0x2A: | ||
394 | case 0x2C: | ||
395 | case 0x2E: | ||
396 | case 0x30: | ||
397 | case 0x32: | ||
398 | case 0x34: | ||
399 | rData = tmds_register_read(i); | ||
400 | if (rData == 1) | ||
401 | break; | ||
402 | /* data = (data + 31) * 8 */ | ||
403 | tmp = (rData + 31) << 3; | ||
404 | if (tmp > max_h) | ||
405 | max_h = tmp; | ||
406 | break; | ||
407 | |||
408 | case 0x36: | ||
409 | case 0x48: | ||
410 | case 0x5A: | ||
411 | case 0x6C: | ||
412 | tmds_register_read_bytes(i, EDID_DATA, 10); | ||
413 | if (!(EDID_DATA[0] || EDID_DATA[1])) { | ||
414 | /* The first two byte must be zero. */ | ||
415 | if (EDID_DATA[3] == 0xFD) { | ||
416 | /* To get max pixel clock. */ | ||
417 | viaparinfo->tmds_setting_info-> | ||
418 | max_pixel_clock = EDID_DATA[9] * 10; | ||
419 | } | ||
420 | } | ||
421 | break; | ||
422 | |||
423 | default: | ||
424 | break; | ||
425 | } | ||
426 | } | ||
427 | |||
428 | switch (max_h) { | ||
429 | case 640: | ||
430 | viaparinfo->tmds_setting_info->dvi_panel_size = | ||
431 | VIA_RES_640X480; | ||
432 | break; | ||
433 | case 800: | ||
434 | viaparinfo->tmds_setting_info->dvi_panel_size = | ||
435 | VIA_RES_800X600; | ||
436 | break; | ||
437 | case 1024: | ||
438 | viaparinfo->tmds_setting_info->dvi_panel_size = | ||
439 | VIA_RES_1024X768; | ||
440 | break; | ||
441 | case 1280: | ||
442 | viaparinfo->tmds_setting_info->dvi_panel_size = | ||
443 | VIA_RES_1280X1024; | ||
444 | break; | ||
445 | case 1400: | ||
446 | viaparinfo->tmds_setting_info->dvi_panel_size = | ||
447 | VIA_RES_1400X1050; | ||
448 | break; | ||
449 | case 1440: | ||
450 | viaparinfo->tmds_setting_info->dvi_panel_size = | ||
451 | VIA_RES_1440X1050; | ||
452 | break; | ||
453 | case 1600: | ||
454 | viaparinfo->tmds_setting_info->dvi_panel_size = | ||
455 | VIA_RES_1600X1200; | ||
456 | break; | ||
457 | case 1920: | ||
458 | if (max_v == 1200) { | ||
459 | viaparinfo->tmds_setting_info->dvi_panel_size = | ||
460 | VIA_RES_1920X1200; | ||
461 | } else { | ||
462 | viaparinfo->tmds_setting_info->dvi_panel_size = | ||
463 | VIA_RES_1920X1080; | ||
464 | } | ||
465 | |||
466 | break; | ||
467 | default: | ||
468 | viaparinfo->tmds_setting_info->dvi_panel_size = | ||
469 | VIA_RES_1024X768; | ||
470 | DEBUG_MSG(KERN_INFO "Unknow panel size max resolution = %d !\ | ||
471 | set default panel size.\n", max_h); | ||
472 | break; | ||
473 | } | ||
474 | |||
475 | DEBUG_MSG(KERN_INFO "DVI max pixelclock = %d\n", | ||
476 | viaparinfo->tmds_setting_info->max_pixel_clock); | ||
477 | viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore; | ||
478 | return viaparinfo->tmds_setting_info->dvi_panel_size; | ||
479 | } | ||
480 | |||
481 | /* | ||
482 | * | ||
483 | * int dvi_get_panel_size_from_DDCv2(void) | ||
484 | * | ||
485 | * - Get Panel Size Using EDID2 Table | ||
486 | * | ||
487 | * Return Type: int | ||
488 | * | ||
489 | */ | ||
490 | static int dvi_get_panel_size_from_DDCv2(void) | ||
491 | { | ||
492 | int HSize = 0, restore; | ||
493 | unsigned char R_Buffer[2]; | ||
494 | |||
495 | DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv2 \n"); | ||
496 | |||
497 | restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr; | ||
498 | viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA2; | ||
499 | |||
500 | /* Horizontal: 0x76, 0x77 */ | ||
501 | tmds_register_read_bytes(0x76, R_Buffer, 2); | ||
502 | HSize = R_Buffer[0]; | ||
503 | HSize += R_Buffer[1] << 8; | ||
504 | |||
505 | switch (HSize) { | ||
506 | case 640: | ||
507 | viaparinfo->tmds_setting_info->dvi_panel_size = | ||
508 | VIA_RES_640X480; | ||
509 | break; | ||
510 | case 800: | ||
511 | viaparinfo->tmds_setting_info->dvi_panel_size = | ||
512 | VIA_RES_800X600; | ||
513 | break; | ||
514 | case 1024: | ||
515 | viaparinfo->tmds_setting_info->dvi_panel_size = | ||
516 | VIA_RES_1024X768; | ||
517 | break; | ||
518 | case 1280: | ||
519 | viaparinfo->tmds_setting_info->dvi_panel_size = | ||
520 | VIA_RES_1280X1024; | ||
521 | break; | ||
522 | case 1400: | ||
523 | viaparinfo->tmds_setting_info->dvi_panel_size = | ||
524 | VIA_RES_1400X1050; | ||
525 | break; | ||
526 | case 1440: | ||
527 | viaparinfo->tmds_setting_info->dvi_panel_size = | ||
528 | VIA_RES_1440X1050; | ||
529 | break; | ||
530 | case 1600: | ||
531 | viaparinfo->tmds_setting_info->dvi_panel_size = | ||
532 | VIA_RES_1600X1200; | ||
533 | break; | ||
534 | default: | ||
535 | viaparinfo->tmds_setting_info->dvi_panel_size = | ||
536 | VIA_RES_1024X768; | ||
537 | DEBUG_MSG(KERN_INFO "Unknow panel size max resolution = %d!\ | ||
538 | set default panel size.\n", HSize); | ||
539 | break; | ||
540 | } | ||
541 | |||
542 | viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore; | ||
543 | return viaparinfo->tmds_setting_info->dvi_panel_size; | ||
544 | } | ||
545 | |||
546 | /* | ||
547 | * | ||
548 | * unsigned char dvi_get_panel_info(void) | ||
549 | * | ||
550 | * - Get Panel Size | ||
551 | * | ||
552 | * Return Type: unsigned char | ||
553 | */ | ||
554 | static unsigned char dvi_get_panel_info(void) | ||
555 | { | ||
556 | unsigned char dvipanelsize; | ||
557 | DEBUG_MSG(KERN_INFO "dvi_get_panel_info! \n"); | ||
558 | |||
559 | viafb_dvi_sense(); | ||
560 | switch (viafb_dvi_query_EDID()) { | ||
561 | case 1: | ||
562 | dvi_get_panel_size_from_DDCv1(); | ||
563 | break; | ||
564 | case 2: | ||
565 | dvi_get_panel_size_from_DDCv2(); | ||
566 | break; | ||
567 | default: | ||
568 | break; | ||
569 | } | ||
570 | |||
571 | DEBUG_MSG(KERN_INFO "dvi panel size is %2d \n", | ||
572 | viaparinfo->tmds_setting_info->dvi_panel_size); | ||
573 | dvipanelsize = (unsigned char)(viaparinfo-> | ||
574 | tmds_setting_info->dvi_panel_size); | ||
575 | return dvipanelsize; | ||
576 | } | ||
577 | |||
578 | /* If Disable DVI, turn off pad */ | ||
579 | void viafb_dvi_disable(void) | ||
580 | { | ||
581 | if (viaparinfo->chip_info-> | ||
582 | tmds_chip_info.output_interface == INTERFACE_DVP0) | ||
583 | viafb_write_reg(SR1E, VIASR, | ||
584 | viafb_read_reg(VIASR, SR1E) & (~0xC0)); | ||
585 | |||
586 | if (viaparinfo->chip_info-> | ||
587 | tmds_chip_info.output_interface == INTERFACE_DVP1) | ||
588 | viafb_write_reg(SR1E, VIASR, | ||
589 | viafb_read_reg(VIASR, SR1E) & (~0x30)); | ||
590 | |||
591 | if (viaparinfo->chip_info-> | ||
592 | tmds_chip_info.output_interface == INTERFACE_DFP_HIGH) | ||
593 | viafb_write_reg(SR2A, VIASR, | ||
594 | viafb_read_reg(VIASR, SR2A) & (~0x0C)); | ||
595 | |||
596 | if (viaparinfo->chip_info-> | ||
597 | tmds_chip_info.output_interface == INTERFACE_DFP_LOW) | ||
598 | viafb_write_reg(SR2A, VIASR, | ||
599 | viafb_read_reg(VIASR, SR2A) & (~0x03)); | ||
600 | |||
601 | if (viaparinfo->chip_info-> | ||
602 | tmds_chip_info.output_interface == INTERFACE_TMDS) | ||
603 | /* Turn off TMDS power. */ | ||
604 | viafb_write_reg(CRD2, VIACR, | ||
605 | viafb_read_reg(VIACR, CRD2) | 0x08); | ||
606 | } | ||
607 | |||
608 | /* If Enable DVI, turn off pad */ | ||
609 | void viafb_dvi_enable(void) | ||
610 | { | ||
611 | u8 data; | ||
612 | |||
613 | if (viaparinfo->chip_info-> | ||
614 | tmds_chip_info.output_interface == INTERFACE_DVP0) { | ||
615 | viafb_write_reg(SR1E, VIASR, | ||
616 | viafb_read_reg(VIASR, SR1E) | 0xC0); | ||
617 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) | ||
618 | tmds_register_write(0x88, 0x3b); | ||
619 | else | ||
620 | /*clear CR91[5] to direct on display period | ||
621 | in the secondary diplay path */ | ||
622 | viafb_write_reg(CR91, VIACR, | ||
623 | viafb_read_reg(VIACR, CR91) & 0xDF); | ||
624 | } | ||
625 | |||
626 | if (viaparinfo->chip_info-> | ||
627 | tmds_chip_info.output_interface == INTERFACE_DVP1) { | ||
628 | viafb_write_reg(SR1E, VIASR, | ||
629 | viafb_read_reg(VIASR, SR1E) | 0x30); | ||
630 | |||
631 | /*fix dvi cann't be enabled with MB VT5718C4 - Al Zhang */ | ||
632 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) { | ||
633 | tmds_register_write(0x88, 0x3b); | ||
634 | } else { | ||
635 | /*clear CR91[5] to direct on display period | ||
636 | in the secondary diplay path */ | ||
637 | viafb_write_reg(CR91, VIACR, | ||
638 | viafb_read_reg(VIACR, CR91) & 0xDF); | ||
639 | } | ||
640 | |||
641 | /*fix DVI cannot enable on EPIA-M board */ | ||
642 | if (viafb_platform_epia_dvi == 1) { | ||
643 | viafb_write_reg_mask(CR91, VIACR, 0x1f, 0x1f); | ||
644 | viafb_write_reg_mask(CR88, VIACR, 0x00, BIT6 + BIT0); | ||
645 | if (viafb_bus_width == 24) { | ||
646 | if (viafb_device_lcd_dualedge == 1) | ||
647 | data = 0x3F; | ||
648 | else | ||
649 | data = 0x37; | ||
650 | viafb_i2c_writebyte(viaparinfo->chip_info-> | ||
651 | tmds_chip_info. | ||
652 | tmds_chip_slave_addr, | ||
653 | 0x08, data); | ||
654 | } | ||
655 | } | ||
656 | } | ||
657 | |||
658 | if (viaparinfo->chip_info-> | ||
659 | tmds_chip_info.output_interface == INTERFACE_DFP_HIGH) { | ||
660 | viafb_write_reg(SR2A, VIASR, | ||
661 | viafb_read_reg(VIASR, SR2A) | 0x0C); | ||
662 | viafb_write_reg(CR91, VIACR, | ||
663 | viafb_read_reg(VIACR, CR91) & 0xDF); | ||
664 | } | ||
665 | |||
666 | if (viaparinfo->chip_info-> | ||
667 | tmds_chip_info.output_interface == INTERFACE_DFP_LOW) { | ||
668 | viafb_write_reg(SR2A, VIASR, | ||
669 | viafb_read_reg(VIASR, SR2A) | 0x03); | ||
670 | viafb_write_reg(CR91, VIACR, | ||
671 | viafb_read_reg(VIACR, CR91) & 0xDF); | ||
672 | } | ||
673 | if (viaparinfo->chip_info-> | ||
674 | tmds_chip_info.output_interface == INTERFACE_TMDS) { | ||
675 | /* Turn on Display period in the panel path. */ | ||
676 | viafb_write_reg_mask(CR91, VIACR, 0, BIT7); | ||
677 | |||
678 | /* Turn on TMDS power. */ | ||
679 | viafb_write_reg_mask(CRD2, VIACR, 0, BIT3); | ||
680 | } | ||
681 | } | ||
682 | |||
diff --git a/drivers/video/via/dvi.h b/drivers/video/via/dvi.h new file mode 100644 index 000000000000..e1ec37fb0dc3 --- /dev/null +++ b/drivers/video/via/dvi.h | |||
@@ -0,0 +1,64 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef __DVI_H__ | ||
23 | #define __DVI_H__ | ||
24 | |||
25 | /*Definition TMDS Device ID register*/ | ||
26 | #define VT1632_DEVICE_ID_REG 0x02 | ||
27 | #define VT1632_DEVICE_ID 0x92 | ||
28 | |||
29 | #define GET_DVI_SIZE_BY_SYSTEM_BIOS 0x01 | ||
30 | #define GET_DVI_SIZE_BY_VGA_BIOS 0x02 | ||
31 | #define GET_DVI_SZIE_BY_HW_STRAPPING 0x03 | ||
32 | |||
33 | /* Definition DVI Panel ID*/ | ||
34 | /* Resolution: 640x480, Channel: single, Dithering: Enable */ | ||
35 | #define DVI_PANEL_ID0_640X480 0x00 | ||
36 | /* Resolution: 800x600, Channel: single, Dithering: Enable */ | ||
37 | #define DVI_PANEL_ID1_800x600 0x01 | ||
38 | /* Resolution: 1024x768, Channel: single, Dithering: Enable */ | ||
39 | #define DVI_PANEL_ID1_1024x768 0x02 | ||
40 | /* Resolution: 1280x768, Channel: single, Dithering: Enable */ | ||
41 | #define DVI_PANEL_ID1_1280x768 0x03 | ||
42 | /* Resolution: 1280x1024, Channel: dual, Dithering: Enable */ | ||
43 | #define DVI_PANEL_ID1_1280x1024 0x04 | ||
44 | /* Resolution: 1400x1050, Channel: dual, Dithering: Enable */ | ||
45 | #define DVI_PANEL_ID1_1400x1050 0x05 | ||
46 | /* Resolution: 1600x1200, Channel: dual, Dithering: Enable */ | ||
47 | #define DVI_PANEL_ID1_1600x1200 0x06 | ||
48 | |||
49 | /* Define the version of EDID*/ | ||
50 | #define EDID_VERSION_1 1 | ||
51 | #define EDID_VERSION_2 2 | ||
52 | |||
53 | #define DEV_CONNECT_DVI 0x01 | ||
54 | #define DEV_CONNECT_HDMI 0x02 | ||
55 | |||
56 | struct VideoModeTable *viafb_get_cea_mode_tbl_pointer(int Index); | ||
57 | int viafb_dvi_sense(void); | ||
58 | void viafb_dvi_disable(void); | ||
59 | void viafb_dvi_enable(void); | ||
60 | int viafb_tmds_trasmitter_identify(void); | ||
61 | void viafb_init_dvi_size(void); | ||
62 | void viafb_dvi_set_mode(int video_index, int mode_bpp, int set_iga); | ||
63 | |||
64 | #endif /* __DVI_H__ */ | ||
diff --git a/drivers/video/via/global.c b/drivers/video/via/global.c new file mode 100644 index 000000000000..468be2425af3 --- /dev/null +++ b/drivers/video/via/global.c | |||
@@ -0,0 +1,60 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | #include "global.h" | ||
22 | int viafb_platform_epia_dvi = STATE_OFF; | ||
23 | int viafb_device_lcd_dualedge = STATE_OFF; | ||
24 | int viafb_bus_width = 12; | ||
25 | int viafb_display_hardware_layout = HW_LAYOUT_LCD_DVI; | ||
26 | int viafb_memsize; | ||
27 | int viafb_DeviceStatus = CRT_Device; | ||
28 | int viafb_hotplug; | ||
29 | int viafb_refresh = 60; | ||
30 | int viafb_refresh1 = 60; | ||
31 | int viafb_lcd_dsp_method = LCD_EXPANDSION; | ||
32 | int viafb_lcd_mode = LCD_OPENLDI; | ||
33 | int viafb_bpp = 32; | ||
34 | int viafb_bpp1 = 32; | ||
35 | int viafb_accel = 1; | ||
36 | int viafb_CRT_ON = 1; | ||
37 | int viafb_DVI_ON; | ||
38 | int viafb_LCD_ON ; | ||
39 | int viafb_LCD2_ON; | ||
40 | int viafb_SAMM_ON; | ||
41 | int viafb_dual_fb; | ||
42 | int viafb_hotplug_Xres = 640; | ||
43 | int viafb_hotplug_Yres = 480; | ||
44 | int viafb_hotplug_bpp = 32; | ||
45 | int viafb_hotplug_refresh = 60; | ||
46 | unsigned int viafb_second_offset; | ||
47 | int viafb_second_size; | ||
48 | int viafb_primary_dev = None_Device; | ||
49 | void __iomem *viafb_FB_MM; | ||
50 | unsigned int viafb_second_xres = 640; | ||
51 | unsigned int viafb_second_yres = 480; | ||
52 | unsigned int viafb_second_virtual_xres; | ||
53 | unsigned int viafb_second_virtual_yres; | ||
54 | int viafb_lcd_panel_id = LCD_PANEL_ID_MAXIMUM + 1; | ||
55 | struct fb_cursor viacursor; | ||
56 | struct fb_info *viafbinfo; | ||
57 | struct fb_info *viafbinfo1; | ||
58 | struct viafb_par *viaparinfo; | ||
59 | struct viafb_par *viaparinfo1; | ||
60 | |||
diff --git a/drivers/video/via/global.h b/drivers/video/via/global.h new file mode 100644 index 000000000000..8e5263c5b812 --- /dev/null +++ b/drivers/video/via/global.h | |||
@@ -0,0 +1,90 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef __GLOBAL_H__ | ||
23 | #define __GLOBAL_H__ | ||
24 | |||
25 | #include <linux/fb.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/ioport.h> | ||
28 | #include <linux/pci.h> | ||
29 | #include <linux/io.h> | ||
30 | #include <linux/uaccess.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/proc_fs.h> | ||
33 | #include <linux/console.h> | ||
34 | #include <linux/timer.h> | ||
35 | |||
36 | #include "debug.h" | ||
37 | |||
38 | #include "iface.h" | ||
39 | #include "viafbdev.h" | ||
40 | #include "chip.h" | ||
41 | #include "debug.h" | ||
42 | #include "accel.h" | ||
43 | #include "share.h" | ||
44 | #include "dvi.h" | ||
45 | #include "viamode.h" | ||
46 | #include "via_i2c.h" | ||
47 | #include "hw.h" | ||
48 | |||
49 | #include "lcd.h" | ||
50 | #include "ioctl.h" | ||
51 | #include "viamode.h" | ||
52 | #include "via_utility.h" | ||
53 | #include "vt1636.h" | ||
54 | #include "tblDPASetting.h" | ||
55 | #include "tbl1636.h" | ||
56 | #include "viafbdev.h" | ||
57 | |||
58 | /* External struct*/ | ||
59 | |||
60 | extern int viafb_platform_epia_dvi; | ||
61 | extern int viafb_device_lcd_dualedge; | ||
62 | extern int viafb_bus_width; | ||
63 | extern int viafb_display_hardware_layout; | ||
64 | extern struct offset offset_reg; | ||
65 | extern struct viafb_par *viaparinfo; | ||
66 | extern struct viafb_par *viaparinfo1; | ||
67 | extern struct fb_info *viafbinfo; | ||
68 | extern struct fb_info *viafbinfo1; | ||
69 | extern int viafb_DeviceStatus; | ||
70 | extern int viafb_refresh; | ||
71 | extern int viafb_refresh1; | ||
72 | extern int viafb_lcd_dsp_method; | ||
73 | extern int viafb_lcd_mode; | ||
74 | extern int viafb_bpp; | ||
75 | extern int viafb_bpp1; | ||
76 | |||
77 | extern int viafb_CRT_ON; | ||
78 | extern int viafb_hotplug_Xres; | ||
79 | extern int viafb_hotplug_Yres; | ||
80 | extern int viafb_hotplug_bpp; | ||
81 | extern int viafb_hotplug_refresh; | ||
82 | extern int viafb_primary_dev; | ||
83 | extern void __iomem *viafb_FB_MM; | ||
84 | extern struct fb_cursor viacursor; | ||
85 | |||
86 | extern unsigned int viafb_second_xres; | ||
87 | extern unsigned int viafb_second_yres; | ||
88 | extern int viafb_lcd_panel_id; | ||
89 | |||
90 | #endif /* __GLOBAL_H__ */ | ||
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c new file mode 100644 index 000000000000..fcd53ceb88fa --- /dev/null +++ b/drivers/video/via/hw.c | |||
@@ -0,0 +1,2865 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #include "global.h" | ||
23 | |||
24 | static const struct pci_device_id_info pciidlist[] = { | ||
25 | {PCI_VIA_VENDOR_ID, UNICHROME_CLE266_DID, UNICHROME_CLE266}, | ||
26 | {PCI_VIA_VENDOR_ID, UNICHROME_PM800_DID, UNICHROME_PM800}, | ||
27 | {PCI_VIA_VENDOR_ID, UNICHROME_K400_DID, UNICHROME_K400}, | ||
28 | {PCI_VIA_VENDOR_ID, UNICHROME_K800_DID, UNICHROME_K800}, | ||
29 | {PCI_VIA_VENDOR_ID, UNICHROME_CN700_DID, UNICHROME_CN700}, | ||
30 | {PCI_VIA_VENDOR_ID, UNICHROME_P4M890_DID, UNICHROME_P4M890}, | ||
31 | {PCI_VIA_VENDOR_ID, UNICHROME_K8M890_DID, UNICHROME_K8M890}, | ||
32 | {PCI_VIA_VENDOR_ID, UNICHROME_CX700_DID, UNICHROME_CX700}, | ||
33 | {PCI_VIA_VENDOR_ID, UNICHROME_P4M900_DID, UNICHROME_P4M900}, | ||
34 | {PCI_VIA_VENDOR_ID, UNICHROME_CN750_DID, UNICHROME_CN750}, | ||
35 | {PCI_VIA_VENDOR_ID, UNICHROME_VX800_DID, UNICHROME_VX800}, | ||
36 | {0, 0, 0} | ||
37 | }; | ||
38 | |||
39 | struct offset offset_reg = { | ||
40 | /* IGA1 Offset Register */ | ||
41 | {IGA1_OFFSET_REG_NUM, {{CR13, 0, 7}, {CR35, 5, 7} } }, | ||
42 | /* IGA2 Offset Register */ | ||
43 | {IGA2_OFFSET_REG_NUM, {{CR66, 0, 7}, {CR67, 0, 1} } } | ||
44 | }; | ||
45 | |||
46 | static struct pll_map pll_value[] = { | ||
47 | {CLK_25_175M, CLE266_PLL_25_175M, K800_PLL_25_175M, CX700_25_175M}, | ||
48 | {CLK_29_581M, CLE266_PLL_29_581M, K800_PLL_29_581M, CX700_29_581M}, | ||
49 | {CLK_26_880M, CLE266_PLL_26_880M, K800_PLL_26_880M, CX700_26_880M}, | ||
50 | {CLK_31_490M, CLE266_PLL_31_490M, K800_PLL_31_490M, CX700_31_490M}, | ||
51 | {CLK_31_500M, CLE266_PLL_31_500M, K800_PLL_31_500M, CX700_31_500M}, | ||
52 | {CLK_31_728M, CLE266_PLL_31_728M, K800_PLL_31_728M, CX700_31_728M}, | ||
53 | {CLK_32_668M, CLE266_PLL_32_668M, K800_PLL_32_668M, CX700_32_668M}, | ||
54 | {CLK_36_000M, CLE266_PLL_36_000M, K800_PLL_36_000M, CX700_36_000M}, | ||
55 | {CLK_40_000M, CLE266_PLL_40_000M, K800_PLL_40_000M, CX700_40_000M}, | ||
56 | {CLK_41_291M, CLE266_PLL_41_291M, K800_PLL_41_291M, CX700_41_291M}, | ||
57 | {CLK_43_163M, CLE266_PLL_43_163M, K800_PLL_43_163M, CX700_43_163M}, | ||
58 | {CLK_45_250M, CLE266_PLL_45_250M, K800_PLL_45_250M, CX700_45_250M}, | ||
59 | {CLK_46_000M, CLE266_PLL_46_000M, K800_PLL_46_000M, CX700_46_000M}, | ||
60 | {CLK_46_996M, CLE266_PLL_46_996M, K800_PLL_46_996M, CX700_46_996M}, | ||
61 | {CLK_48_000M, CLE266_PLL_48_000M, K800_PLL_48_000M, CX700_48_000M}, | ||
62 | {CLK_48_875M, CLE266_PLL_48_875M, K800_PLL_48_875M, CX700_48_875M}, | ||
63 | {CLK_49_500M, CLE266_PLL_49_500M, K800_PLL_49_500M, CX700_49_500M}, | ||
64 | {CLK_52_406M, CLE266_PLL_52_406M, K800_PLL_52_406M, CX700_52_406M}, | ||
65 | {CLK_52_977M, CLE266_PLL_52_977M, K800_PLL_52_977M, CX700_52_977M}, | ||
66 | {CLK_56_250M, CLE266_PLL_56_250M, K800_PLL_56_250M, CX700_56_250M}, | ||
67 | {CLK_60_466M, CLE266_PLL_60_466M, K800_PLL_60_466M, CX700_60_466M}, | ||
68 | {CLK_61_500M, CLE266_PLL_61_500M, K800_PLL_61_500M, CX700_61_500M}, | ||
69 | {CLK_65_000M, CLE266_PLL_65_000M, K800_PLL_65_000M, CX700_65_000M}, | ||
70 | {CLK_65_178M, CLE266_PLL_65_178M, K800_PLL_65_178M, CX700_65_178M}, | ||
71 | {CLK_66_750M, CLE266_PLL_66_750M, K800_PLL_66_750M, CX700_66_750M}, | ||
72 | {CLK_68_179M, CLE266_PLL_68_179M, K800_PLL_68_179M, CX700_68_179M}, | ||
73 | {CLK_69_924M, CLE266_PLL_69_924M, K800_PLL_69_924M, CX700_69_924M}, | ||
74 | {CLK_70_159M, CLE266_PLL_70_159M, K800_PLL_70_159M, CX700_70_159M}, | ||
75 | {CLK_72_000M, CLE266_PLL_72_000M, K800_PLL_72_000M, CX700_72_000M}, | ||
76 | {CLK_78_750M, CLE266_PLL_78_750M, K800_PLL_78_750M, CX700_78_750M}, | ||
77 | {CLK_80_136M, CLE266_PLL_80_136M, K800_PLL_80_136M, CX700_80_136M}, | ||
78 | {CLK_83_375M, CLE266_PLL_83_375M, K800_PLL_83_375M, CX700_83_375M}, | ||
79 | {CLK_83_950M, CLE266_PLL_83_950M, K800_PLL_83_950M, CX700_83_950M}, | ||
80 | {CLK_84_750M, CLE266_PLL_84_750M, K800_PLL_84_750M, CX700_84_750M}, | ||
81 | {CLK_85_860M, CLE266_PLL_85_860M, K800_PLL_85_860M, CX700_85_860M}, | ||
82 | {CLK_88_750M, CLE266_PLL_88_750M, K800_PLL_88_750M, CX700_88_750M}, | ||
83 | {CLK_94_500M, CLE266_PLL_94_500M, K800_PLL_94_500M, CX700_94_500M}, | ||
84 | {CLK_97_750M, CLE266_PLL_97_750M, K800_PLL_97_750M, CX700_97_750M}, | ||
85 | {CLK_101_000M, CLE266_PLL_101_000M, K800_PLL_101_000M, | ||
86 | CX700_101_000M}, | ||
87 | {CLK_106_500M, CLE266_PLL_106_500M, K800_PLL_106_500M, | ||
88 | CX700_106_500M}, | ||
89 | {CLK_108_000M, CLE266_PLL_108_000M, K800_PLL_108_000M, | ||
90 | CX700_108_000M}, | ||
91 | {CLK_113_309M, CLE266_PLL_113_309M, K800_PLL_113_309M, | ||
92 | CX700_113_309M}, | ||
93 | {CLK_118_840M, CLE266_PLL_118_840M, K800_PLL_118_840M, | ||
94 | CX700_118_840M}, | ||
95 | {CLK_119_000M, CLE266_PLL_119_000M, K800_PLL_119_000M, | ||
96 | CX700_119_000M}, | ||
97 | {CLK_121_750M, CLE266_PLL_121_750M, K800_PLL_121_750M, | ||
98 | CX700_121_750M}, | ||
99 | {CLK_125_104M, CLE266_PLL_125_104M, K800_PLL_125_104M, | ||
100 | CX700_125_104M}, | ||
101 | {CLK_133_308M, CLE266_PLL_133_308M, K800_PLL_133_308M, | ||
102 | CX700_133_308M}, | ||
103 | {CLK_135_000M, CLE266_PLL_135_000M, K800_PLL_135_000M, | ||
104 | CX700_135_000M}, | ||
105 | {CLK_136_700M, CLE266_PLL_136_700M, K800_PLL_136_700M, | ||
106 | CX700_136_700M}, | ||
107 | {CLK_138_400M, CLE266_PLL_138_400M, K800_PLL_138_400M, | ||
108 | CX700_138_400M}, | ||
109 | {CLK_146_760M, CLE266_PLL_146_760M, K800_PLL_146_760M, | ||
110 | CX700_146_760M}, | ||
111 | {CLK_153_920M, CLE266_PLL_153_920M, K800_PLL_153_920M, | ||
112 | CX700_153_920M}, | ||
113 | {CLK_156_000M, CLE266_PLL_156_000M, K800_PLL_156_000M, | ||
114 | CX700_156_000M}, | ||
115 | {CLK_157_500M, CLE266_PLL_157_500M, K800_PLL_157_500M, | ||
116 | CX700_157_500M}, | ||
117 | {CLK_162_000M, CLE266_PLL_162_000M, K800_PLL_162_000M, | ||
118 | CX700_162_000M}, | ||
119 | {CLK_187_000M, CLE266_PLL_187_000M, K800_PLL_187_000M, | ||
120 | CX700_187_000M}, | ||
121 | {CLK_193_295M, CLE266_PLL_193_295M, K800_PLL_193_295M, | ||
122 | CX700_193_295M}, | ||
123 | {CLK_202_500M, CLE266_PLL_202_500M, K800_PLL_202_500M, | ||
124 | CX700_202_500M}, | ||
125 | {CLK_204_000M, CLE266_PLL_204_000M, K800_PLL_204_000M, | ||
126 | CX700_204_000M}, | ||
127 | {CLK_218_500M, CLE266_PLL_218_500M, K800_PLL_218_500M, | ||
128 | CX700_218_500M}, | ||
129 | {CLK_234_000M, CLE266_PLL_234_000M, K800_PLL_234_000M, | ||
130 | CX700_234_000M}, | ||
131 | {CLK_267_250M, CLE266_PLL_267_250M, K800_PLL_267_250M, | ||
132 | CX700_267_250M}, | ||
133 | {CLK_297_500M, CLE266_PLL_297_500M, K800_PLL_297_500M, | ||
134 | CX700_297_500M}, | ||
135 | {CLK_74_481M, CLE266_PLL_74_481M, K800_PLL_74_481M, CX700_74_481M}, | ||
136 | {CLK_172_798M, CLE266_PLL_172_798M, K800_PLL_172_798M, | ||
137 | CX700_172_798M}, | ||
138 | {CLK_122_614M, CLE266_PLL_122_614M, K800_PLL_122_614M, | ||
139 | CX700_122_614M}, | ||
140 | {CLK_74_270M, CLE266_PLL_74_270M, K800_PLL_74_270M, CX700_74_270M}, | ||
141 | {CLK_148_500M, CLE266_PLL_148_500M, K800_PLL_148_500M, | ||
142 | CX700_148_500M} | ||
143 | }; | ||
144 | |||
145 | static struct fifo_depth_select display_fifo_depth_reg = { | ||
146 | /* IGA1 FIFO Depth_Select */ | ||
147 | {IGA1_FIFO_DEPTH_SELECT_REG_NUM, {{SR17, 0, 7} } }, | ||
148 | /* IGA2 FIFO Depth_Select */ | ||
149 | {IGA2_FIFO_DEPTH_SELECT_REG_NUM, | ||
150 | {{CR68, 4, 7}, {CR94, 7, 7}, {CR95, 7, 7} } } | ||
151 | }; | ||
152 | |||
153 | static struct fifo_threshold_select fifo_threshold_select_reg = { | ||
154 | /* IGA1 FIFO Threshold Select */ | ||
155 | {IGA1_FIFO_THRESHOLD_REG_NUM, {{SR16, 0, 5}, {SR16, 7, 7} } }, | ||
156 | /* IGA2 FIFO Threshold Select */ | ||
157 | {IGA2_FIFO_THRESHOLD_REG_NUM, {{CR68, 0, 3}, {CR95, 4, 6} } } | ||
158 | }; | ||
159 | |||
160 | static struct fifo_high_threshold_select fifo_high_threshold_select_reg = { | ||
161 | /* IGA1 FIFO High Threshold Select */ | ||
162 | {IGA1_FIFO_HIGH_THRESHOLD_REG_NUM, {{SR18, 0, 5}, {SR18, 7, 7} } }, | ||
163 | /* IGA2 FIFO High Threshold Select */ | ||
164 | {IGA2_FIFO_HIGH_THRESHOLD_REG_NUM, {{CR92, 0, 3}, {CR95, 0, 2} } } | ||
165 | }; | ||
166 | |||
167 | static struct display_queue_expire_num display_queue_expire_num_reg = { | ||
168 | /* IGA1 Display Queue Expire Num */ | ||
169 | {IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM, {{SR22, 0, 4} } }, | ||
170 | /* IGA2 Display Queue Expire Num */ | ||
171 | {IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM, {{CR94, 0, 6} } } | ||
172 | }; | ||
173 | |||
174 | /* Definition Fetch Count Registers*/ | ||
175 | static struct fetch_count fetch_count_reg = { | ||
176 | /* IGA1 Fetch Count Register */ | ||
177 | {IGA1_FETCH_COUNT_REG_NUM, {{SR1C, 0, 7}, {SR1D, 0, 1} } }, | ||
178 | /* IGA2 Fetch Count Register */ | ||
179 | {IGA2_FETCH_COUNT_REG_NUM, {{CR65, 0, 7}, {CR67, 2, 3} } } | ||
180 | }; | ||
181 | |||
182 | static struct iga1_crtc_timing iga1_crtc_reg = { | ||
183 | /* IGA1 Horizontal Total */ | ||
184 | {IGA1_HOR_TOTAL_REG_NUM, {{CR00, 0, 7}, {CR36, 3, 3} } }, | ||
185 | /* IGA1 Horizontal Addressable Video */ | ||
186 | {IGA1_HOR_ADDR_REG_NUM, {{CR01, 0, 7} } }, | ||
187 | /* IGA1 Horizontal Blank Start */ | ||
188 | {IGA1_HOR_BLANK_START_REG_NUM, {{CR02, 0, 7} } }, | ||
189 | /* IGA1 Horizontal Blank End */ | ||
190 | {IGA1_HOR_BLANK_END_REG_NUM, | ||
191 | {{CR03, 0, 4}, {CR05, 7, 7}, {CR33, 5, 5} } }, | ||
192 | /* IGA1 Horizontal Sync Start */ | ||
193 | {IGA1_HOR_SYNC_START_REG_NUM, {{CR04, 0, 7}, {CR33, 4, 4} } }, | ||
194 | /* IGA1 Horizontal Sync End */ | ||
195 | {IGA1_HOR_SYNC_END_REG_NUM, {{CR05, 0, 4} } }, | ||
196 | /* IGA1 Vertical Total */ | ||
197 | {IGA1_VER_TOTAL_REG_NUM, | ||
198 | {{CR06, 0, 7}, {CR07, 0, 0}, {CR07, 5, 5}, {CR35, 0, 0} } }, | ||
199 | /* IGA1 Vertical Addressable Video */ | ||
200 | {IGA1_VER_ADDR_REG_NUM, | ||
201 | {{CR12, 0, 7}, {CR07, 1, 1}, {CR07, 6, 6}, {CR35, 2, 2} } }, | ||
202 | /* IGA1 Vertical Blank Start */ | ||
203 | {IGA1_VER_BLANK_START_REG_NUM, | ||
204 | {{CR15, 0, 7}, {CR07, 3, 3}, {CR09, 5, 5}, {CR35, 3, 3} } }, | ||
205 | /* IGA1 Vertical Blank End */ | ||
206 | {IGA1_VER_BLANK_END_REG_NUM, {{CR16, 0, 7} } }, | ||
207 | /* IGA1 Vertical Sync Start */ | ||
208 | {IGA1_VER_SYNC_START_REG_NUM, | ||
209 | {{CR10, 0, 7}, {CR07, 2, 2}, {CR07, 7, 7}, {CR35, 1, 1} } }, | ||
210 | /* IGA1 Vertical Sync End */ | ||
211 | {IGA1_VER_SYNC_END_REG_NUM, {{CR11, 0, 3} } } | ||
212 | }; | ||
213 | |||
214 | static struct iga2_crtc_timing iga2_crtc_reg = { | ||
215 | /* IGA2 Horizontal Total */ | ||
216 | {IGA2_HOR_TOTAL_REG_NUM, {{CR50, 0, 7}, {CR55, 0, 3} } }, | ||
217 | /* IGA2 Horizontal Addressable Video */ | ||
218 | {IGA2_HOR_ADDR_REG_NUM, {{CR51, 0, 7}, {CR55, 4, 6} } }, | ||
219 | /* IGA2 Horizontal Blank Start */ | ||
220 | {IGA2_HOR_BLANK_START_REG_NUM, {{CR52, 0, 7}, {CR54, 0, 2} } }, | ||
221 | /* IGA2 Horizontal Blank End */ | ||
222 | {IGA2_HOR_BLANK_END_REG_NUM, | ||
223 | {{CR53, 0, 7}, {CR54, 3, 5}, {CR5D, 6, 6} } }, | ||
224 | /* IGA2 Horizontal Sync Start */ | ||
225 | {IGA2_HOR_SYNC_START_REG_NUM, | ||
226 | {{CR56, 0, 7}, {CR54, 6, 7}, {CR5C, 7, 7}, {CR5D, 7, 7} } }, | ||
227 | /* IGA2 Horizontal Sync End */ | ||
228 | {IGA2_HOR_SYNC_END_REG_NUM, {{CR57, 0, 7}, {CR5C, 6, 6} } }, | ||
229 | /* IGA2 Vertical Total */ | ||
230 | {IGA2_VER_TOTAL_REG_NUM, {{CR58, 0, 7}, {CR5D, 0, 2} } }, | ||
231 | /* IGA2 Vertical Addressable Video */ | ||
232 | {IGA2_VER_ADDR_REG_NUM, {{CR59, 0, 7}, {CR5D, 3, 5} } }, | ||
233 | /* IGA2 Vertical Blank Start */ | ||
234 | {IGA2_VER_BLANK_START_REG_NUM, {{CR5A, 0, 7}, {CR5C, 0, 2} } }, | ||
235 | /* IGA2 Vertical Blank End */ | ||
236 | {IGA2_VER_BLANK_END_REG_NUM, {{CR5B, 0, 7}, {CR5C, 3, 5} } }, | ||
237 | /* IGA2 Vertical Sync Start */ | ||
238 | {IGA2_VER_SYNC_START_REG_NUM, {{CR5E, 0, 7}, {CR5F, 5, 7} } }, | ||
239 | /* IGA2 Vertical Sync End */ | ||
240 | {IGA2_VER_SYNC_END_REG_NUM, {{CR5F, 0, 4} } } | ||
241 | }; | ||
242 | |||
243 | static struct rgbLUT palLUT_table[] = { | ||
244 | /* {R,G,B} */ | ||
245 | /* Index 0x00~0x03 */ | ||
246 | {0x00, 0x00, 0x00}, {0x00, 0x00, 0x2A}, {0x00, 0x2A, 0x00}, {0x00, | ||
247 | 0x2A, | ||
248 | 0x2A}, | ||
249 | /* Index 0x04~0x07 */ | ||
250 | {0x2A, 0x00, 0x00}, {0x2A, 0x00, 0x2A}, {0x2A, 0x15, 0x00}, {0x2A, | ||
251 | 0x2A, | ||
252 | 0x2A}, | ||
253 | /* Index 0x08~0x0B */ | ||
254 | {0x15, 0x15, 0x15}, {0x15, 0x15, 0x3F}, {0x15, 0x3F, 0x15}, {0x15, | ||
255 | 0x3F, | ||
256 | 0x3F}, | ||
257 | /* Index 0x0C~0x0F */ | ||
258 | {0x3F, 0x15, 0x15}, {0x3F, 0x15, 0x3F}, {0x3F, 0x3F, 0x15}, {0x3F, | ||
259 | 0x3F, | ||
260 | 0x3F}, | ||
261 | /* Index 0x10~0x13 */ | ||
262 | {0x00, 0x00, 0x00}, {0x05, 0x05, 0x05}, {0x08, 0x08, 0x08}, {0x0B, | ||
263 | 0x0B, | ||
264 | 0x0B}, | ||
265 | /* Index 0x14~0x17 */ | ||
266 | {0x0E, 0x0E, 0x0E}, {0x11, 0x11, 0x11}, {0x14, 0x14, 0x14}, {0x18, | ||
267 | 0x18, | ||
268 | 0x18}, | ||
269 | /* Index 0x18~0x1B */ | ||
270 | {0x1C, 0x1C, 0x1C}, {0x20, 0x20, 0x20}, {0x24, 0x24, 0x24}, {0x28, | ||
271 | 0x28, | ||
272 | 0x28}, | ||
273 | /* Index 0x1C~0x1F */ | ||
274 | {0x2D, 0x2D, 0x2D}, {0x32, 0x32, 0x32}, {0x38, 0x38, 0x38}, {0x3F, | ||
275 | 0x3F, | ||
276 | 0x3F}, | ||
277 | /* Index 0x20~0x23 */ | ||
278 | {0x00, 0x00, 0x3F}, {0x10, 0x00, 0x3F}, {0x1F, 0x00, 0x3F}, {0x2F, | ||
279 | 0x00, | ||
280 | 0x3F}, | ||
281 | /* Index 0x24~0x27 */ | ||
282 | {0x3F, 0x00, 0x3F}, {0x3F, 0x00, 0x2F}, {0x3F, 0x00, 0x1F}, {0x3F, | ||
283 | 0x00, | ||
284 | 0x10}, | ||
285 | /* Index 0x28~0x2B */ | ||
286 | {0x3F, 0x00, 0x00}, {0x3F, 0x10, 0x00}, {0x3F, 0x1F, 0x00}, {0x3F, | ||
287 | 0x2F, | ||
288 | 0x00}, | ||
289 | /* Index 0x2C~0x2F */ | ||
290 | {0x3F, 0x3F, 0x00}, {0x2F, 0x3F, 0x00}, {0x1F, 0x3F, 0x00}, {0x10, | ||
291 | 0x3F, | ||
292 | 0x00}, | ||
293 | /* Index 0x30~0x33 */ | ||
294 | {0x00, 0x3F, 0x00}, {0x00, 0x3F, 0x10}, {0x00, 0x3F, 0x1F}, {0x00, | ||
295 | 0x3F, | ||
296 | 0x2F}, | ||
297 | /* Index 0x34~0x37 */ | ||
298 | {0x00, 0x3F, 0x3F}, {0x00, 0x2F, 0x3F}, {0x00, 0x1F, 0x3F}, {0x00, | ||
299 | 0x10, | ||
300 | 0x3F}, | ||
301 | /* Index 0x38~0x3B */ | ||
302 | {0x1F, 0x1F, 0x3F}, {0x27, 0x1F, 0x3F}, {0x2F, 0x1F, 0x3F}, {0x37, | ||
303 | 0x1F, | ||
304 | 0x3F}, | ||
305 | /* Index 0x3C~0x3F */ | ||
306 | {0x3F, 0x1F, 0x3F}, {0x3F, 0x1F, 0x37}, {0x3F, 0x1F, 0x2F}, {0x3F, | ||
307 | 0x1F, | ||
308 | 0x27}, | ||
309 | /* Index 0x40~0x43 */ | ||
310 | {0x3F, 0x1F, 0x1F}, {0x3F, 0x27, 0x1F}, {0x3F, 0x2F, 0x1F}, {0x3F, | ||
311 | 0x3F, | ||
312 | 0x1F}, | ||
313 | /* Index 0x44~0x47 */ | ||
314 | {0x3F, 0x3F, 0x1F}, {0x37, 0x3F, 0x1F}, {0x2F, 0x3F, 0x1F}, {0x27, | ||
315 | 0x3F, | ||
316 | 0x1F}, | ||
317 | /* Index 0x48~0x4B */ | ||
318 | {0x1F, 0x3F, 0x1F}, {0x1F, 0x3F, 0x27}, {0x1F, 0x3F, 0x2F}, {0x1F, | ||
319 | 0x3F, | ||
320 | 0x37}, | ||
321 | /* Index 0x4C~0x4F */ | ||
322 | {0x1F, 0x3F, 0x3F}, {0x1F, 0x37, 0x3F}, {0x1F, 0x2F, 0x3F}, {0x1F, | ||
323 | 0x27, | ||
324 | 0x3F}, | ||
325 | /* Index 0x50~0x53 */ | ||
326 | {0x2D, 0x2D, 0x3F}, {0x31, 0x2D, 0x3F}, {0x36, 0x2D, 0x3F}, {0x3A, | ||
327 | 0x2D, | ||
328 | 0x3F}, | ||
329 | /* Index 0x54~0x57 */ | ||
330 | {0x3F, 0x2D, 0x3F}, {0x3F, 0x2D, 0x3A}, {0x3F, 0x2D, 0x36}, {0x3F, | ||
331 | 0x2D, | ||
332 | 0x31}, | ||
333 | /* Index 0x58~0x5B */ | ||
334 | {0x3F, 0x2D, 0x2D}, {0x3F, 0x31, 0x2D}, {0x3F, 0x36, 0x2D}, {0x3F, | ||
335 | 0x3A, | ||
336 | 0x2D}, | ||
337 | /* Index 0x5C~0x5F */ | ||
338 | {0x3F, 0x3F, 0x2D}, {0x3A, 0x3F, 0x2D}, {0x36, 0x3F, 0x2D}, {0x31, | ||
339 | 0x3F, | ||
340 | 0x2D}, | ||
341 | /* Index 0x60~0x63 */ | ||
342 | {0x2D, 0x3F, 0x2D}, {0x2D, 0x3F, 0x31}, {0x2D, 0x3F, 0x36}, {0x2D, | ||
343 | 0x3F, | ||
344 | 0x3A}, | ||
345 | /* Index 0x64~0x67 */ | ||
346 | {0x2D, 0x3F, 0x3F}, {0x2D, 0x3A, 0x3F}, {0x2D, 0x36, 0x3F}, {0x2D, | ||
347 | 0x31, | ||
348 | 0x3F}, | ||
349 | /* Index 0x68~0x6B */ | ||
350 | {0x00, 0x00, 0x1C}, {0x07, 0x00, 0x1C}, {0x0E, 0x00, 0x1C}, {0x15, | ||
351 | 0x00, | ||
352 | 0x1C}, | ||
353 | /* Index 0x6C~0x6F */ | ||
354 | {0x1C, 0x00, 0x1C}, {0x1C, 0x00, 0x15}, {0x1C, 0x00, 0x0E}, {0x1C, | ||
355 | 0x00, | ||
356 | 0x07}, | ||
357 | /* Index 0x70~0x73 */ | ||
358 | {0x1C, 0x00, 0x00}, {0x1C, 0x07, 0x00}, {0x1C, 0x0E, 0x00}, {0x1C, | ||
359 | 0x15, | ||
360 | 0x00}, | ||
361 | /* Index 0x74~0x77 */ | ||
362 | {0x1C, 0x1C, 0x00}, {0x15, 0x1C, 0x00}, {0x0E, 0x1C, 0x00}, {0x07, | ||
363 | 0x1C, | ||
364 | 0x00}, | ||
365 | /* Index 0x78~0x7B */ | ||
366 | {0x00, 0x1C, 0x00}, {0x00, 0x1C, 0x07}, {0x00, 0x1C, 0x0E}, {0x00, | ||
367 | 0x1C, | ||
368 | 0x15}, | ||
369 | /* Index 0x7C~0x7F */ | ||
370 | {0x00, 0x1C, 0x1C}, {0x00, 0x15, 0x1C}, {0x00, 0x0E, 0x1C}, {0x00, | ||
371 | 0x07, | ||
372 | 0x1C}, | ||
373 | /* Index 0x80~0x83 */ | ||
374 | {0x0E, 0x0E, 0x1C}, {0x11, 0x0E, 0x1C}, {0x15, 0x0E, 0x1C}, {0x18, | ||
375 | 0x0E, | ||
376 | 0x1C}, | ||
377 | /* Index 0x84~0x87 */ | ||
378 | {0x1C, 0x0E, 0x1C}, {0x1C, 0x0E, 0x18}, {0x1C, 0x0E, 0x15}, {0x1C, | ||
379 | 0x0E, | ||
380 | 0x11}, | ||
381 | /* Index 0x88~0x8B */ | ||
382 | {0x1C, 0x0E, 0x0E}, {0x1C, 0x11, 0x0E}, {0x1C, 0x15, 0x0E}, {0x1C, | ||
383 | 0x18, | ||
384 | 0x0E}, | ||
385 | /* Index 0x8C~0x8F */ | ||
386 | {0x1C, 0x1C, 0x0E}, {0x18, 0x1C, 0x0E}, {0x15, 0x1C, 0x0E}, {0x11, | ||
387 | 0x1C, | ||
388 | 0x0E}, | ||
389 | /* Index 0x90~0x93 */ | ||
390 | {0x0E, 0x1C, 0x0E}, {0x0E, 0x1C, 0x11}, {0x0E, 0x1C, 0x15}, {0x0E, | ||
391 | 0x1C, | ||
392 | 0x18}, | ||
393 | /* Index 0x94~0x97 */ | ||
394 | {0x0E, 0x1C, 0x1C}, {0x0E, 0x18, 0x1C}, {0x0E, 0x15, 0x1C}, {0x0E, | ||
395 | 0x11, | ||
396 | 0x1C}, | ||
397 | /* Index 0x98~0x9B */ | ||
398 | {0x14, 0x14, 0x1C}, {0x16, 0x14, 0x1C}, {0x18, 0x14, 0x1C}, {0x1A, | ||
399 | 0x14, | ||
400 | 0x1C}, | ||
401 | /* Index 0x9C~0x9F */ | ||
402 | {0x1C, 0x14, 0x1C}, {0x1C, 0x14, 0x1A}, {0x1C, 0x14, 0x18}, {0x1C, | ||
403 | 0x14, | ||
404 | 0x16}, | ||
405 | /* Index 0xA0~0xA3 */ | ||
406 | {0x1C, 0x14, 0x14}, {0x1C, 0x16, 0x14}, {0x1C, 0x18, 0x14}, {0x1C, | ||
407 | 0x1A, | ||
408 | 0x14}, | ||
409 | /* Index 0xA4~0xA7 */ | ||
410 | {0x1C, 0x1C, 0x14}, {0x1A, 0x1C, 0x14}, {0x18, 0x1C, 0x14}, {0x16, | ||
411 | 0x1C, | ||
412 | 0x14}, | ||
413 | /* Index 0xA8~0xAB */ | ||
414 | {0x14, 0x1C, 0x14}, {0x14, 0x1C, 0x16}, {0x14, 0x1C, 0x18}, {0x14, | ||
415 | 0x1C, | ||
416 | 0x1A}, | ||
417 | /* Index 0xAC~0xAF */ | ||
418 | {0x14, 0x1C, 0x1C}, {0x14, 0x1A, 0x1C}, {0x14, 0x18, 0x1C}, {0x14, | ||
419 | 0x16, | ||
420 | 0x1C}, | ||
421 | /* Index 0xB0~0xB3 */ | ||
422 | {0x00, 0x00, 0x10}, {0x04, 0x00, 0x10}, {0x08, 0x00, 0x10}, {0x0C, | ||
423 | 0x00, | ||
424 | 0x10}, | ||
425 | /* Index 0xB4~0xB7 */ | ||
426 | {0x10, 0x00, 0x10}, {0x10, 0x00, 0x0C}, {0x10, 0x00, 0x08}, {0x10, | ||
427 | 0x00, | ||
428 | 0x04}, | ||
429 | /* Index 0xB8~0xBB */ | ||
430 | {0x10, 0x00, 0x00}, {0x10, 0x04, 0x00}, {0x10, 0x08, 0x00}, {0x10, | ||
431 | 0x0C, | ||
432 | 0x00}, | ||
433 | /* Index 0xBC~0xBF */ | ||
434 | {0x10, 0x10, 0x00}, {0x0C, 0x10, 0x00}, {0x08, 0x10, 0x00}, {0x04, | ||
435 | 0x10, | ||
436 | 0x00}, | ||
437 | /* Index 0xC0~0xC3 */ | ||
438 | {0x00, 0x10, 0x00}, {0x00, 0x10, 0x04}, {0x00, 0x10, 0x08}, {0x00, | ||
439 | 0x10, | ||
440 | 0x0C}, | ||
441 | /* Index 0xC4~0xC7 */ | ||
442 | {0x00, 0x10, 0x10}, {0x00, 0x0C, 0x10}, {0x00, 0x08, 0x10}, {0x00, | ||
443 | 0x04, | ||
444 | 0x10}, | ||
445 | /* Index 0xC8~0xCB */ | ||
446 | {0x08, 0x08, 0x10}, {0x0A, 0x08, 0x10}, {0x0C, 0x08, 0x10}, {0x0E, | ||
447 | 0x08, | ||
448 | 0x10}, | ||
449 | /* Index 0xCC~0xCF */ | ||
450 | {0x10, 0x08, 0x10}, {0x10, 0x08, 0x0E}, {0x10, 0x08, 0x0C}, {0x10, | ||
451 | 0x08, | ||
452 | 0x0A}, | ||
453 | /* Index 0xD0~0xD3 */ | ||
454 | {0x10, 0x08, 0x08}, {0x10, 0x0A, 0x08}, {0x10, 0x0C, 0x08}, {0x10, | ||
455 | 0x0E, | ||
456 | 0x08}, | ||
457 | /* Index 0xD4~0xD7 */ | ||
458 | {0x10, 0x10, 0x08}, {0x0E, 0x10, 0x08}, {0x0C, 0x10, 0x08}, {0x0A, | ||
459 | 0x10, | ||
460 | 0x08}, | ||
461 | /* Index 0xD8~0xDB */ | ||
462 | {0x08, 0x10, 0x08}, {0x08, 0x10, 0x0A}, {0x08, 0x10, 0x0C}, {0x08, | ||
463 | 0x10, | ||
464 | 0x0E}, | ||
465 | /* Index 0xDC~0xDF */ | ||
466 | {0x08, 0x10, 0x10}, {0x08, 0x0E, 0x10}, {0x08, 0x0C, 0x10}, {0x08, | ||
467 | 0x0A, | ||
468 | 0x10}, | ||
469 | /* Index 0xE0~0xE3 */ | ||
470 | {0x0B, 0x0B, 0x10}, {0x0C, 0x0B, 0x10}, {0x0D, 0x0B, 0x10}, {0x0F, | ||
471 | 0x0B, | ||
472 | 0x10}, | ||
473 | /* Index 0xE4~0xE7 */ | ||
474 | {0x10, 0x0B, 0x10}, {0x10, 0x0B, 0x0F}, {0x10, 0x0B, 0x0D}, {0x10, | ||
475 | 0x0B, | ||
476 | 0x0C}, | ||
477 | /* Index 0xE8~0xEB */ | ||
478 | {0x10, 0x0B, 0x0B}, {0x10, 0x0C, 0x0B}, {0x10, 0x0D, 0x0B}, {0x10, | ||
479 | 0x0F, | ||
480 | 0x0B}, | ||
481 | /* Index 0xEC~0xEF */ | ||
482 | {0x10, 0x10, 0x0B}, {0x0F, 0x10, 0x0B}, {0x0D, 0x10, 0x0B}, {0x0C, | ||
483 | 0x10, | ||
484 | 0x0B}, | ||
485 | /* Index 0xF0~0xF3 */ | ||
486 | {0x0B, 0x10, 0x0B}, {0x0B, 0x10, 0x0C}, {0x0B, 0x10, 0x0D}, {0x0B, | ||
487 | 0x10, | ||
488 | 0x0F}, | ||
489 | /* Index 0xF4~0xF7 */ | ||
490 | {0x0B, 0x10, 0x10}, {0x0B, 0x0F, 0x10}, {0x0B, 0x0D, 0x10}, {0x0B, | ||
491 | 0x0C, | ||
492 | 0x10}, | ||
493 | /* Index 0xF8~0xFB */ | ||
494 | {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, | ||
495 | 0x00, | ||
496 | 0x00}, | ||
497 | /* Index 0xFC~0xFF */ | ||
498 | {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, | ||
499 | 0x00, | ||
500 | 0x00} | ||
501 | }; | ||
502 | |||
503 | static void set_crt_output_path(int set_iga); | ||
504 | static void dvi_patch_skew_dvp0(void); | ||
505 | static void dvi_patch_skew_dvp1(void); | ||
506 | static void dvi_patch_skew_dvp_low(void); | ||
507 | static void set_dvi_output_path(int set_iga, int output_interface); | ||
508 | static void set_lcd_output_path(int set_iga, int output_interface); | ||
509 | static int search_mode_setting(int ModeInfoIndex); | ||
510 | static void load_fix_bit_crtc_reg(void); | ||
511 | static void init_gfx_chip_info(void); | ||
512 | static void init_tmds_chip_info(void); | ||
513 | static void init_lvds_chip_info(void); | ||
514 | static void device_screen_off(void); | ||
515 | static void device_screen_on(void); | ||
516 | static void set_display_channel(void); | ||
517 | static void device_off(void); | ||
518 | static void device_on(void); | ||
519 | static void enable_second_display_channel(void); | ||
520 | static void disable_second_display_channel(void); | ||
521 | static int get_fb_size_from_pci(void); | ||
522 | |||
523 | void viafb_write_reg(u8 index, u16 io_port, u8 data) | ||
524 | { | ||
525 | outb(index, io_port); | ||
526 | outb(data, io_port + 1); | ||
527 | /*DEBUG_MSG(KERN_INFO "\nIndex=%2d Value=%2d", index, data); */ | ||
528 | } | ||
529 | u8 viafb_read_reg(int io_port, u8 index) | ||
530 | { | ||
531 | outb(index, io_port); | ||
532 | return inb(io_port + 1); | ||
533 | } | ||
534 | |||
535 | void viafb_lock_crt(void) | ||
536 | { | ||
537 | viafb_write_reg_mask(CR11, VIACR, BIT7, BIT7); | ||
538 | } | ||
539 | |||
540 | void viafb_unlock_crt(void) | ||
541 | { | ||
542 | viafb_write_reg_mask(CR11, VIACR, 0, BIT7); | ||
543 | viafb_write_reg_mask(CR47, VIACR, 0, BIT0); | ||
544 | } | ||
545 | |||
546 | void viafb_write_reg_mask(u8 index, int io_port, u8 data, u8 mask) | ||
547 | { | ||
548 | u8 tmp; | ||
549 | |||
550 | outb(index, io_port); | ||
551 | tmp = inb(io_port + 1); | ||
552 | outb((data & mask) | (tmp & (~mask)), io_port + 1); | ||
553 | /*DEBUG_MSG(KERN_INFO "\nIndex=%2d Value=%2d", index, tmp); */ | ||
554 | } | ||
555 | |||
556 | void write_dac_reg(u8 index, u8 r, u8 g, u8 b) | ||
557 | { | ||
558 | outb(index, LUT_INDEX_WRITE); | ||
559 | outb(r, LUT_DATA); | ||
560 | outb(g, LUT_DATA); | ||
561 | outb(b, LUT_DATA); | ||
562 | } | ||
563 | |||
564 | /*Set IGA path for each device*/ | ||
565 | void viafb_set_iga_path(void) | ||
566 | { | ||
567 | |||
568 | if (viafb_SAMM_ON == 1) { | ||
569 | if (viafb_CRT_ON) { | ||
570 | if (viafb_primary_dev == CRT_Device) | ||
571 | viaparinfo->crt_setting_info->iga_path = IGA1; | ||
572 | else | ||
573 | viaparinfo->crt_setting_info->iga_path = IGA2; | ||
574 | } | ||
575 | |||
576 | if (viafb_DVI_ON) { | ||
577 | if (viafb_primary_dev == DVI_Device) | ||
578 | viaparinfo->tmds_setting_info->iga_path = IGA1; | ||
579 | else | ||
580 | viaparinfo->tmds_setting_info->iga_path = IGA2; | ||
581 | } | ||
582 | |||
583 | if (viafb_LCD_ON) { | ||
584 | if (viafb_primary_dev == LCD_Device) { | ||
585 | if (viafb_dual_fb && | ||
586 | (viaparinfo->chip_info->gfx_chip_name == | ||
587 | UNICHROME_CLE266)) { | ||
588 | viaparinfo-> | ||
589 | lvds_setting_info->iga_path = IGA2; | ||
590 | viaparinfo-> | ||
591 | crt_setting_info->iga_path = IGA1; | ||
592 | viaparinfo-> | ||
593 | tmds_setting_info->iga_path = IGA1; | ||
594 | } else | ||
595 | viaparinfo-> | ||
596 | lvds_setting_info->iga_path = IGA1; | ||
597 | } else { | ||
598 | viaparinfo->lvds_setting_info->iga_path = IGA2; | ||
599 | } | ||
600 | } | ||
601 | if (viafb_LCD2_ON) { | ||
602 | if (LCD2_Device == viafb_primary_dev) | ||
603 | viaparinfo->lvds_setting_info2->iga_path = IGA1; | ||
604 | else | ||
605 | viaparinfo->lvds_setting_info2->iga_path = IGA2; | ||
606 | } | ||
607 | } else { | ||
608 | viafb_SAMM_ON = 0; | ||
609 | |||
610 | if (viafb_CRT_ON && viafb_LCD_ON) { | ||
611 | viaparinfo->crt_setting_info->iga_path = IGA1; | ||
612 | viaparinfo->lvds_setting_info->iga_path = IGA2; | ||
613 | } else if (viafb_CRT_ON && viafb_DVI_ON) { | ||
614 | viaparinfo->crt_setting_info->iga_path = IGA1; | ||
615 | viaparinfo->tmds_setting_info->iga_path = IGA2; | ||
616 | } else if (viafb_LCD_ON && viafb_DVI_ON) { | ||
617 | viaparinfo->tmds_setting_info->iga_path = IGA1; | ||
618 | viaparinfo->lvds_setting_info->iga_path = IGA2; | ||
619 | } else if (viafb_LCD_ON && viafb_LCD2_ON) { | ||
620 | viaparinfo->lvds_setting_info->iga_path = IGA2; | ||
621 | viaparinfo->lvds_setting_info2->iga_path = IGA2; | ||
622 | } else if (viafb_CRT_ON) { | ||
623 | viaparinfo->crt_setting_info->iga_path = IGA1; | ||
624 | } else if (viafb_LCD_ON) { | ||
625 | viaparinfo->lvds_setting_info->iga_path = IGA2; | ||
626 | } else if (viafb_DVI_ON) { | ||
627 | viaparinfo->tmds_setting_info->iga_path = IGA1; | ||
628 | } | ||
629 | } | ||
630 | } | ||
631 | |||
632 | void viafb_set_start_addr(void) | ||
633 | { | ||
634 | unsigned long offset = 0, tmp = 0, size = 0; | ||
635 | unsigned long length; | ||
636 | |||
637 | DEBUG_MSG(KERN_INFO "viafb_set_start_addr!\n"); | ||
638 | viafb_unlock_crt(); | ||
639 | /* update starting address of IGA1 */ | ||
640 | viafb_write_reg(CR0C, VIACR, 0x00); /*initial starting address */ | ||
641 | viafb_write_reg(CR0D, VIACR, 0x00); | ||
642 | viafb_write_reg(CR34, VIACR, 0x00); | ||
643 | viafb_write_reg_mask(CR48, VIACR, 0x00, 0x1F); | ||
644 | |||
645 | if (viafb_dual_fb) { | ||
646 | viaparinfo->iga_path = IGA1; | ||
647 | viaparinfo1->iga_path = IGA2; | ||
648 | } | ||
649 | |||
650 | if (viafb_SAMM_ON == 1) { | ||
651 | if (!viafb_dual_fb) { | ||
652 | if (viafb_second_size) | ||
653 | size = viafb_second_size * 1024 * 1024; | ||
654 | else | ||
655 | size = 8 * 1024 * 1024; | ||
656 | } else { | ||
657 | |||
658 | size = viaparinfo1->memsize; | ||
659 | } | ||
660 | offset = viafb_second_offset; | ||
661 | DEBUG_MSG(KERN_INFO | ||
662 | "viafb_second_size=%lx, second start_adddress=%lx\n", | ||
663 | size, offset); | ||
664 | } | ||
665 | if (viafb_SAMM_ON == 1) { | ||
666 | offset = offset >> 3; | ||
667 | |||
668 | tmp = viafb_read_reg(VIACR, 0x62) & 0x01; | ||
669 | tmp |= (offset & 0x7F) << 1; | ||
670 | viafb_write_reg(CR62, VIACR, tmp); | ||
671 | viafb_write_reg(CR63, VIACR, ((offset & 0x7F80) >> 7)); | ||
672 | viafb_write_reg(CR64, VIACR, ((offset & 0x7F8000) >> 15)); | ||
673 | viafb_write_reg(CRA3, VIACR, ((offset & 0x3800000) >> 23)); | ||
674 | } else { | ||
675 | /* update starting address */ | ||
676 | viafb_write_reg(CR62, VIACR, 0x00); | ||
677 | viafb_write_reg(CR63, VIACR, 0x00); | ||
678 | viafb_write_reg(CR64, VIACR, 0x00); | ||
679 | viafb_write_reg(CRA3, VIACR, 0x00); | ||
680 | } | ||
681 | |||
682 | if (viafb_SAMM_ON == 1) { | ||
683 | if (viafb_accel) { | ||
684 | if (!viafb_dual_fb) | ||
685 | length = size - viaparinfo->fbmem_used; | ||
686 | else | ||
687 | length = size - viaparinfo1->fbmem_used; | ||
688 | } else | ||
689 | length = size; | ||
690 | offset = (unsigned long)(void *)viafb_FB_MM + | ||
691 | viafb_second_offset; | ||
692 | memset((void *)offset, 0, length); | ||
693 | } | ||
694 | |||
695 | viafb_lock_crt(); | ||
696 | } | ||
697 | |||
698 | void viafb_set_output_path(int device, int set_iga, int output_interface) | ||
699 | { | ||
700 | switch (device) { | ||
701 | case DEVICE_CRT: | ||
702 | set_crt_output_path(set_iga); | ||
703 | break; | ||
704 | case DEVICE_DVI: | ||
705 | set_dvi_output_path(set_iga, output_interface); | ||
706 | break; | ||
707 | case DEVICE_LCD: | ||
708 | set_lcd_output_path(set_iga, output_interface); | ||
709 | break; | ||
710 | } | ||
711 | } | ||
712 | |||
713 | static void set_crt_output_path(int set_iga) | ||
714 | { | ||
715 | viafb_write_reg_mask(CR36, VIACR, 0x00, BIT4 + BIT5); | ||
716 | |||
717 | switch (set_iga) { | ||
718 | case IGA1: | ||
719 | viafb_write_reg_mask(SR16, VIASR, 0x00, BIT6); | ||
720 | break; | ||
721 | case IGA2: | ||
722 | case IGA1_IGA2: | ||
723 | viafb_write_reg_mask(CR6A, VIACR, 0xC0, BIT6 + BIT7); | ||
724 | viafb_write_reg_mask(SR16, VIASR, 0x40, BIT6); | ||
725 | if (set_iga == IGA1_IGA2) | ||
726 | viafb_write_reg_mask(CR6B, VIACR, 0x08, BIT3); | ||
727 | break; | ||
728 | } | ||
729 | } | ||
730 | |||
731 | static void dvi_patch_skew_dvp0(void) | ||
732 | { | ||
733 | /* Reset data driving first: */ | ||
734 | viafb_write_reg_mask(SR1B, VIASR, 0, BIT1); | ||
735 | viafb_write_reg_mask(SR2A, VIASR, 0, BIT4); | ||
736 | |||
737 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
738 | case UNICHROME_P4M890: | ||
739 | { | ||
740 | if ((viaparinfo->tmds_setting_info->h_active == 1600) && | ||
741 | (viaparinfo->tmds_setting_info->v_active == | ||
742 | 1200)) | ||
743 | viafb_write_reg_mask(CR96, VIACR, 0x03, | ||
744 | BIT0 + BIT1 + BIT2); | ||
745 | else | ||
746 | viafb_write_reg_mask(CR96, VIACR, 0x07, | ||
747 | BIT0 + BIT1 + BIT2); | ||
748 | break; | ||
749 | } | ||
750 | |||
751 | case UNICHROME_P4M900: | ||
752 | { | ||
753 | viafb_write_reg_mask(CR96, VIACR, 0x07, | ||
754 | BIT0 + BIT1 + BIT2 + BIT3); | ||
755 | viafb_write_reg_mask(SR1B, VIASR, 0x02, BIT1); | ||
756 | viafb_write_reg_mask(SR2A, VIASR, 0x10, BIT4); | ||
757 | break; | ||
758 | } | ||
759 | |||
760 | default: | ||
761 | { | ||
762 | break; | ||
763 | } | ||
764 | } | ||
765 | } | ||
766 | |||
767 | static void dvi_patch_skew_dvp1(void) | ||
768 | { | ||
769 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
770 | case UNICHROME_CX700: | ||
771 | { | ||
772 | break; | ||
773 | } | ||
774 | |||
775 | default: | ||
776 | { | ||
777 | break; | ||
778 | } | ||
779 | } | ||
780 | } | ||
781 | |||
782 | static void dvi_patch_skew_dvp_low(void) | ||
783 | { | ||
784 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
785 | case UNICHROME_K8M890: | ||
786 | { | ||
787 | viafb_write_reg_mask(CR99, VIACR, 0x03, BIT0 + BIT1); | ||
788 | break; | ||
789 | } | ||
790 | |||
791 | case UNICHROME_P4M900: | ||
792 | { | ||
793 | viafb_write_reg_mask(CR99, VIACR, 0x08, | ||
794 | BIT0 + BIT1 + BIT2 + BIT3); | ||
795 | break; | ||
796 | } | ||
797 | |||
798 | case UNICHROME_P4M890: | ||
799 | { | ||
800 | viafb_write_reg_mask(CR99, VIACR, 0x0F, | ||
801 | BIT0 + BIT1 + BIT2 + BIT3); | ||
802 | break; | ||
803 | } | ||
804 | |||
805 | default: | ||
806 | { | ||
807 | break; | ||
808 | } | ||
809 | } | ||
810 | } | ||
811 | |||
812 | static void set_dvi_output_path(int set_iga, int output_interface) | ||
813 | { | ||
814 | switch (output_interface) { | ||
815 | case INTERFACE_DVP0: | ||
816 | viafb_write_reg_mask(CR6B, VIACR, 0x01, BIT0); | ||
817 | |||
818 | if (set_iga == IGA1) { | ||
819 | viafb_write_reg_mask(CR96, VIACR, 0x00, BIT4); | ||
820 | viafb_write_reg_mask(CR6C, VIACR, 0x21, BIT0 + | ||
821 | BIT5 + BIT7); | ||
822 | } else { | ||
823 | viafb_write_reg_mask(CR96, VIACR, 0x10, BIT4); | ||
824 | viafb_write_reg_mask(CR6C, VIACR, 0xA1, BIT0 + | ||
825 | BIT5 + BIT7); | ||
826 | } | ||
827 | |||
828 | viafb_write_reg_mask(SR1E, VIASR, 0xC0, BIT7 + BIT6); | ||
829 | |||
830 | dvi_patch_skew_dvp0(); | ||
831 | break; | ||
832 | |||
833 | case INTERFACE_DVP1: | ||
834 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) { | ||
835 | if (set_iga == IGA1) | ||
836 | viafb_write_reg_mask(CR93, VIACR, 0x21, | ||
837 | BIT0 + BIT5 + BIT7); | ||
838 | else | ||
839 | viafb_write_reg_mask(CR93, VIACR, 0xA1, | ||
840 | BIT0 + BIT5 + BIT7); | ||
841 | } else { | ||
842 | if (set_iga == IGA1) | ||
843 | viafb_write_reg_mask(CR9B, VIACR, 0x00, BIT4); | ||
844 | else | ||
845 | viafb_write_reg_mask(CR9B, VIACR, 0x10, BIT4); | ||
846 | } | ||
847 | |||
848 | viafb_write_reg_mask(SR1E, VIASR, 0x30, BIT4 + BIT5); | ||
849 | dvi_patch_skew_dvp1(); | ||
850 | break; | ||
851 | case INTERFACE_DFP_HIGH: | ||
852 | if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266) { | ||
853 | if (set_iga == IGA1) { | ||
854 | viafb_write_reg_mask(CR96, VIACR, 0x00, BIT4); | ||
855 | viafb_write_reg_mask(CR97, VIACR, 0x03, | ||
856 | BIT0 + BIT1 + BIT4); | ||
857 | } else { | ||
858 | viafb_write_reg_mask(CR96, VIACR, 0x10, BIT4); | ||
859 | viafb_write_reg_mask(CR97, VIACR, 0x13, | ||
860 | BIT0 + BIT1 + BIT4); | ||
861 | } | ||
862 | } | ||
863 | viafb_write_reg_mask(SR2A, VIASR, 0x0C, BIT2 + BIT3); | ||
864 | break; | ||
865 | |||
866 | case INTERFACE_DFP_LOW: | ||
867 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) | ||
868 | break; | ||
869 | |||
870 | if (set_iga == IGA1) { | ||
871 | viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4); | ||
872 | viafb_write_reg_mask(CR9B, VIACR, 0x00, BIT4); | ||
873 | } else { | ||
874 | viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4); | ||
875 | viafb_write_reg_mask(CR9B, VIACR, 0x10, BIT4); | ||
876 | } | ||
877 | |||
878 | viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1); | ||
879 | dvi_patch_skew_dvp_low(); | ||
880 | break; | ||
881 | |||
882 | case INTERFACE_TMDS: | ||
883 | if (set_iga == IGA1) | ||
884 | viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4); | ||
885 | else | ||
886 | viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4); | ||
887 | break; | ||
888 | } | ||
889 | |||
890 | if (set_iga == IGA2) { | ||
891 | enable_second_display_channel(); | ||
892 | /* Disable LCD Scaling */ | ||
893 | viafb_write_reg_mask(CR79, VIACR, 0x00, BIT0); | ||
894 | } | ||
895 | } | ||
896 | |||
897 | static void set_lcd_output_path(int set_iga, int output_interface) | ||
898 | { | ||
899 | DEBUG_MSG(KERN_INFO | ||
900 | "set_lcd_output_path, iga:%d,out_interface:%d\n", | ||
901 | set_iga, output_interface); | ||
902 | switch (set_iga) { | ||
903 | case IGA1: | ||
904 | viafb_write_reg_mask(CR6B, VIACR, 0x00, BIT3); | ||
905 | viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3); | ||
906 | |||
907 | disable_second_display_channel(); | ||
908 | break; | ||
909 | |||
910 | case IGA2: | ||
911 | viafb_write_reg_mask(CR6B, VIACR, 0x00, BIT3); | ||
912 | viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3); | ||
913 | |||
914 | enable_second_display_channel(); | ||
915 | break; | ||
916 | |||
917 | case IGA1_IGA2: | ||
918 | viafb_write_reg_mask(CR6B, VIACR, 0x08, BIT3); | ||
919 | viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3); | ||
920 | |||
921 | disable_second_display_channel(); | ||
922 | break; | ||
923 | } | ||
924 | |||
925 | switch (output_interface) { | ||
926 | case INTERFACE_DVP0: | ||
927 | if (set_iga == IGA1) { | ||
928 | viafb_write_reg_mask(CR96, VIACR, 0x00, BIT4); | ||
929 | } else { | ||
930 | viafb_write_reg(CR91, VIACR, 0x00); | ||
931 | viafb_write_reg_mask(CR96, VIACR, 0x10, BIT4); | ||
932 | } | ||
933 | break; | ||
934 | |||
935 | case INTERFACE_DVP1: | ||
936 | if (set_iga == IGA1) | ||
937 | viafb_write_reg_mask(CR9B, VIACR, 0x00, BIT4); | ||
938 | else { | ||
939 | viafb_write_reg(CR91, VIACR, 0x00); | ||
940 | viafb_write_reg_mask(CR9B, VIACR, 0x10, BIT4); | ||
941 | } | ||
942 | break; | ||
943 | |||
944 | case INTERFACE_DFP_HIGH: | ||
945 | if (set_iga == IGA1) | ||
946 | viafb_write_reg_mask(CR97, VIACR, 0x00, BIT4); | ||
947 | else { | ||
948 | viafb_write_reg(CR91, VIACR, 0x00); | ||
949 | viafb_write_reg_mask(CR97, VIACR, 0x10, BIT4); | ||
950 | viafb_write_reg_mask(CR96, VIACR, 0x10, BIT4); | ||
951 | } | ||
952 | break; | ||
953 | |||
954 | case INTERFACE_DFP_LOW: | ||
955 | if (set_iga == IGA1) | ||
956 | viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4); | ||
957 | else { | ||
958 | viafb_write_reg(CR91, VIACR, 0x00); | ||
959 | viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4); | ||
960 | viafb_write_reg_mask(CR9B, VIACR, 0x10, BIT4); | ||
961 | } | ||
962 | |||
963 | break; | ||
964 | |||
965 | case INTERFACE_DFP: | ||
966 | if ((UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name) | ||
967 | || (UNICHROME_P4M890 == | ||
968 | viaparinfo->chip_info->gfx_chip_name)) | ||
969 | viafb_write_reg_mask(CR97, VIACR, 0x84, | ||
970 | BIT7 + BIT2 + BIT1 + BIT0); | ||
971 | if (set_iga == IGA1) { | ||
972 | viafb_write_reg_mask(CR97, VIACR, 0x00, BIT4); | ||
973 | viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4); | ||
974 | } else { | ||
975 | viafb_write_reg(CR91, VIACR, 0x00); | ||
976 | viafb_write_reg_mask(CR97, VIACR, 0x10, BIT4); | ||
977 | viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4); | ||
978 | } | ||
979 | break; | ||
980 | |||
981 | case INTERFACE_LVDS0: | ||
982 | case INTERFACE_LVDS0LVDS1: | ||
983 | if (set_iga == IGA1) | ||
984 | viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4); | ||
985 | else | ||
986 | viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4); | ||
987 | |||
988 | break; | ||
989 | |||
990 | case INTERFACE_LVDS1: | ||
991 | if (set_iga == IGA1) | ||
992 | viafb_write_reg_mask(CR97, VIACR, 0x00, BIT4); | ||
993 | else | ||
994 | viafb_write_reg_mask(CR97, VIACR, 0x10, BIT4); | ||
995 | break; | ||
996 | } | ||
997 | } | ||
998 | |||
999 | /* Search Mode Index */ | ||
1000 | static int search_mode_setting(int ModeInfoIndex) | ||
1001 | { | ||
1002 | int i = 0; | ||
1003 | |||
1004 | while ((i < NUM_TOTAL_MODETABLE) && | ||
1005 | (ModeInfoIndex != CLE266Modes[i].ModeIndex)) | ||
1006 | i++; | ||
1007 | if (i >= NUM_TOTAL_MODETABLE) | ||
1008 | i = 0; | ||
1009 | return i; | ||
1010 | |||
1011 | } | ||
1012 | |||
1013 | struct VideoModeTable *viafb_get_modetbl_pointer(int Index) | ||
1014 | { | ||
1015 | struct VideoModeTable *TmpTbl = NULL; | ||
1016 | TmpTbl = &CLE266Modes[search_mode_setting(Index)]; | ||
1017 | return TmpTbl; | ||
1018 | } | ||
1019 | |||
1020 | struct VideoModeTable *viafb_get_cea_mode_tbl_pointer(int Index) | ||
1021 | { | ||
1022 | struct VideoModeTable *TmpTbl = NULL; | ||
1023 | int i = 0; | ||
1024 | while ((i < NUM_TOTAL_CEA_MODES) && | ||
1025 | (Index != CEA_HDMI_Modes[i].ModeIndex)) | ||
1026 | i++; | ||
1027 | if ((i < NUM_TOTAL_CEA_MODES)) | ||
1028 | TmpTbl = &CEA_HDMI_Modes[i]; | ||
1029 | else { | ||
1030 | /*Still use general timing if don't find CEA timing */ | ||
1031 | i = 0; | ||
1032 | while ((i < NUM_TOTAL_MODETABLE) && | ||
1033 | (Index != CLE266Modes[i].ModeIndex)) | ||
1034 | i++; | ||
1035 | if (i >= NUM_TOTAL_MODETABLE) | ||
1036 | i = 0; | ||
1037 | TmpTbl = &CLE266Modes[i]; | ||
1038 | } | ||
1039 | return TmpTbl; | ||
1040 | } | ||
1041 | |||
1042 | static void load_fix_bit_crtc_reg(void) | ||
1043 | { | ||
1044 | /* always set to 1 */ | ||
1045 | viafb_write_reg_mask(CR03, VIACR, 0x80, BIT7); | ||
1046 | /* line compare should set all bits = 1 (extend modes) */ | ||
1047 | viafb_write_reg(CR18, VIACR, 0xff); | ||
1048 | /* line compare should set all bits = 1 (extend modes) */ | ||
1049 | viafb_write_reg_mask(CR07, VIACR, 0x10, BIT4); | ||
1050 | /* line compare should set all bits = 1 (extend modes) */ | ||
1051 | viafb_write_reg_mask(CR09, VIACR, 0x40, BIT6); | ||
1052 | /* line compare should set all bits = 1 (extend modes) */ | ||
1053 | viafb_write_reg_mask(CR35, VIACR, 0x10, BIT4); | ||
1054 | /* line compare should set all bits = 1 (extend modes) */ | ||
1055 | viafb_write_reg_mask(CR33, VIACR, 0x06, BIT0 + BIT1 + BIT2); | ||
1056 | /*viafb_write_reg_mask(CR32, VIACR, 0x01, BIT0); */ | ||
1057 | /* extend mode always set to e3h */ | ||
1058 | viafb_write_reg(CR17, VIACR, 0xe3); | ||
1059 | /* extend mode always set to 0h */ | ||
1060 | viafb_write_reg(CR08, VIACR, 0x00); | ||
1061 | /* extend mode always set to 0h */ | ||
1062 | viafb_write_reg(CR14, VIACR, 0x00); | ||
1063 | |||
1064 | /* If K8M800, enable Prefetch Mode. */ | ||
1065 | if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) | ||
1066 | || (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890)) | ||
1067 | viafb_write_reg_mask(CR33, VIACR, 0x08, BIT3); | ||
1068 | if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) | ||
1069 | && (viaparinfo->chip_info->gfx_chip_revision == CLE266_REVISION_AX)) | ||
1070 | viafb_write_reg_mask(SR1A, VIASR, 0x02, BIT1); | ||
1071 | |||
1072 | } | ||
1073 | |||
1074 | void viafb_load_reg(int timing_value, int viafb_load_reg_num, | ||
1075 | struct io_register *reg, | ||
1076 | int io_type) | ||
1077 | { | ||
1078 | int reg_mask; | ||
1079 | int bit_num = 0; | ||
1080 | int data; | ||
1081 | int i, j; | ||
1082 | int shift_next_reg; | ||
1083 | int start_index, end_index, cr_index; | ||
1084 | u16 get_bit; | ||
1085 | |||
1086 | for (i = 0; i < viafb_load_reg_num; i++) { | ||
1087 | reg_mask = 0; | ||
1088 | data = 0; | ||
1089 | start_index = reg[i].start_bit; | ||
1090 | end_index = reg[i].end_bit; | ||
1091 | cr_index = reg[i].io_addr; | ||
1092 | |||
1093 | shift_next_reg = bit_num; | ||
1094 | for (j = start_index; j <= end_index; j++) { | ||
1095 | /*if (bit_num==8) timing_value = timing_value >>8; */ | ||
1096 | reg_mask = reg_mask | (BIT0 << j); | ||
1097 | get_bit = (timing_value & (BIT0 << bit_num)); | ||
1098 | data = | ||
1099 | data | ((get_bit >> shift_next_reg) << start_index); | ||
1100 | bit_num++; | ||
1101 | } | ||
1102 | if (io_type == VIACR) | ||
1103 | viafb_write_reg_mask(cr_index, VIACR, data, reg_mask); | ||
1104 | else | ||
1105 | viafb_write_reg_mask(cr_index, VIASR, data, reg_mask); | ||
1106 | } | ||
1107 | |||
1108 | } | ||
1109 | |||
1110 | /* Write Registers */ | ||
1111 | void viafb_write_regx(struct io_reg RegTable[], int ItemNum) | ||
1112 | { | ||
1113 | int i; | ||
1114 | unsigned char RegTemp; | ||
1115 | |||
1116 | /*DEBUG_MSG(KERN_INFO "Table Size : %x!!\n",ItemNum ); */ | ||
1117 | |||
1118 | for (i = 0; i < ItemNum; i++) { | ||
1119 | outb(RegTable[i].index, RegTable[i].port); | ||
1120 | RegTemp = inb(RegTable[i].port + 1); | ||
1121 | RegTemp = (RegTemp & (~RegTable[i].mask)) | RegTable[i].value; | ||
1122 | outb(RegTemp, RegTable[i].port + 1); | ||
1123 | } | ||
1124 | } | ||
1125 | |||
1126 | void viafb_load_offset_reg(int h_addr, int bpp_byte, int set_iga) | ||
1127 | { | ||
1128 | int reg_value; | ||
1129 | int viafb_load_reg_num; | ||
1130 | struct io_register *reg; | ||
1131 | |||
1132 | switch (set_iga) { | ||
1133 | case IGA1_IGA2: | ||
1134 | case IGA1: | ||
1135 | reg_value = IGA1_OFFSET_FORMULA(h_addr, bpp_byte); | ||
1136 | viafb_load_reg_num = offset_reg.iga1_offset_reg.reg_num; | ||
1137 | reg = offset_reg.iga1_offset_reg.reg; | ||
1138 | viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR); | ||
1139 | if (set_iga == IGA1) | ||
1140 | break; | ||
1141 | case IGA2: | ||
1142 | reg_value = IGA2_OFFSET_FORMULA(h_addr, bpp_byte); | ||
1143 | viafb_load_reg_num = offset_reg.iga2_offset_reg.reg_num; | ||
1144 | reg = offset_reg.iga2_offset_reg.reg; | ||
1145 | viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR); | ||
1146 | break; | ||
1147 | } | ||
1148 | } | ||
1149 | |||
1150 | void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga) | ||
1151 | { | ||
1152 | int reg_value; | ||
1153 | int viafb_load_reg_num; | ||
1154 | struct io_register *reg = NULL; | ||
1155 | |||
1156 | switch (set_iga) { | ||
1157 | case IGA1_IGA2: | ||
1158 | case IGA1: | ||
1159 | reg_value = IGA1_FETCH_COUNT_FORMULA(h_addr, bpp_byte); | ||
1160 | viafb_load_reg_num = fetch_count_reg. | ||
1161 | iga1_fetch_count_reg.reg_num; | ||
1162 | reg = fetch_count_reg.iga1_fetch_count_reg.reg; | ||
1163 | viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR); | ||
1164 | if (set_iga == IGA1) | ||
1165 | break; | ||
1166 | case IGA2: | ||
1167 | reg_value = IGA2_FETCH_COUNT_FORMULA(h_addr, bpp_byte); | ||
1168 | viafb_load_reg_num = fetch_count_reg. | ||
1169 | iga2_fetch_count_reg.reg_num; | ||
1170 | reg = fetch_count_reg.iga2_fetch_count_reg.reg; | ||
1171 | viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR); | ||
1172 | break; | ||
1173 | } | ||
1174 | |||
1175 | } | ||
1176 | |||
1177 | void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active) | ||
1178 | { | ||
1179 | int reg_value; | ||
1180 | int viafb_load_reg_num; | ||
1181 | struct io_register *reg = NULL; | ||
1182 | int iga1_fifo_max_depth = 0, iga1_fifo_threshold = | ||
1183 | 0, iga1_fifo_high_threshold = 0, iga1_display_queue_expire_num = 0; | ||
1184 | int iga2_fifo_max_depth = 0, iga2_fifo_threshold = | ||
1185 | 0, iga2_fifo_high_threshold = 0, iga2_display_queue_expire_num = 0; | ||
1186 | |||
1187 | if (set_iga == IGA1) { | ||
1188 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) { | ||
1189 | iga1_fifo_max_depth = K800_IGA1_FIFO_MAX_DEPTH; | ||
1190 | iga1_fifo_threshold = K800_IGA1_FIFO_THRESHOLD; | ||
1191 | iga1_fifo_high_threshold = | ||
1192 | K800_IGA1_FIFO_HIGH_THRESHOLD; | ||
1193 | /* If resolution > 1280x1024, expire length = 64, else | ||
1194 | expire length = 128 */ | ||
1195 | if ((hor_active > 1280) && (ver_active > 1024)) | ||
1196 | iga1_display_queue_expire_num = 16; | ||
1197 | else | ||
1198 | iga1_display_queue_expire_num = | ||
1199 | K800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1200 | |||
1201 | } | ||
1202 | |||
1203 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_PM800) { | ||
1204 | iga1_fifo_max_depth = P880_IGA1_FIFO_MAX_DEPTH; | ||
1205 | iga1_fifo_threshold = P880_IGA1_FIFO_THRESHOLD; | ||
1206 | iga1_fifo_high_threshold = | ||
1207 | P880_IGA1_FIFO_HIGH_THRESHOLD; | ||
1208 | iga1_display_queue_expire_num = | ||
1209 | P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1210 | |||
1211 | /* If resolution > 1280x1024, expire length = 64, else | ||
1212 | expire length = 128 */ | ||
1213 | if ((hor_active > 1280) && (ver_active > 1024)) | ||
1214 | iga1_display_queue_expire_num = 16; | ||
1215 | else | ||
1216 | iga1_display_queue_expire_num = | ||
1217 | P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1218 | } | ||
1219 | |||
1220 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CN700) { | ||
1221 | iga1_fifo_max_depth = CN700_IGA1_FIFO_MAX_DEPTH; | ||
1222 | iga1_fifo_threshold = CN700_IGA1_FIFO_THRESHOLD; | ||
1223 | iga1_fifo_high_threshold = | ||
1224 | CN700_IGA1_FIFO_HIGH_THRESHOLD; | ||
1225 | |||
1226 | /* If resolution > 1280x1024, expire length = 64, | ||
1227 | else expire length = 128 */ | ||
1228 | if ((hor_active > 1280) && (ver_active > 1024)) | ||
1229 | iga1_display_queue_expire_num = 16; | ||
1230 | else | ||
1231 | iga1_display_queue_expire_num = | ||
1232 | CN700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1233 | } | ||
1234 | |||
1235 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) { | ||
1236 | iga1_fifo_max_depth = CX700_IGA1_FIFO_MAX_DEPTH; | ||
1237 | iga1_fifo_threshold = CX700_IGA1_FIFO_THRESHOLD; | ||
1238 | iga1_fifo_high_threshold = | ||
1239 | CX700_IGA1_FIFO_HIGH_THRESHOLD; | ||
1240 | iga1_display_queue_expire_num = | ||
1241 | CX700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1242 | } | ||
1243 | |||
1244 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890) { | ||
1245 | iga1_fifo_max_depth = K8M890_IGA1_FIFO_MAX_DEPTH; | ||
1246 | iga1_fifo_threshold = K8M890_IGA1_FIFO_THRESHOLD; | ||
1247 | iga1_fifo_high_threshold = | ||
1248 | K8M890_IGA1_FIFO_HIGH_THRESHOLD; | ||
1249 | iga1_display_queue_expire_num = | ||
1250 | K8M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1251 | } | ||
1252 | |||
1253 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M890) { | ||
1254 | iga1_fifo_max_depth = P4M890_IGA1_FIFO_MAX_DEPTH; | ||
1255 | iga1_fifo_threshold = P4M890_IGA1_FIFO_THRESHOLD; | ||
1256 | iga1_fifo_high_threshold = | ||
1257 | P4M890_IGA1_FIFO_HIGH_THRESHOLD; | ||
1258 | iga1_display_queue_expire_num = | ||
1259 | P4M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1260 | } | ||
1261 | |||
1262 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M900) { | ||
1263 | iga1_fifo_max_depth = P4M900_IGA1_FIFO_MAX_DEPTH; | ||
1264 | iga1_fifo_threshold = P4M900_IGA1_FIFO_THRESHOLD; | ||
1265 | iga1_fifo_high_threshold = | ||
1266 | P4M900_IGA1_FIFO_HIGH_THRESHOLD; | ||
1267 | iga1_display_queue_expire_num = | ||
1268 | P4M900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1269 | } | ||
1270 | |||
1271 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX800) { | ||
1272 | iga1_fifo_max_depth = VX800_IGA1_FIFO_MAX_DEPTH; | ||
1273 | iga1_fifo_threshold = VX800_IGA1_FIFO_THRESHOLD; | ||
1274 | iga1_fifo_high_threshold = | ||
1275 | VX800_IGA1_FIFO_HIGH_THRESHOLD; | ||
1276 | iga1_display_queue_expire_num = | ||
1277 | VX800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1278 | } | ||
1279 | |||
1280 | /* Set Display FIFO Depath Select */ | ||
1281 | reg_value = IGA1_FIFO_DEPTH_SELECT_FORMULA(iga1_fifo_max_depth); | ||
1282 | viafb_load_reg_num = | ||
1283 | display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg_num; | ||
1284 | reg = display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg; | ||
1285 | viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR); | ||
1286 | |||
1287 | /* Set Display FIFO Threshold Select */ | ||
1288 | reg_value = IGA1_FIFO_THRESHOLD_FORMULA(iga1_fifo_threshold); | ||
1289 | viafb_load_reg_num = | ||
1290 | fifo_threshold_select_reg. | ||
1291 | iga1_fifo_threshold_select_reg.reg_num; | ||
1292 | reg = | ||
1293 | fifo_threshold_select_reg. | ||
1294 | iga1_fifo_threshold_select_reg.reg; | ||
1295 | viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR); | ||
1296 | |||
1297 | /* Set FIFO High Threshold Select */ | ||
1298 | reg_value = | ||
1299 | IGA1_FIFO_HIGH_THRESHOLD_FORMULA(iga1_fifo_high_threshold); | ||
1300 | viafb_load_reg_num = | ||
1301 | fifo_high_threshold_select_reg. | ||
1302 | iga1_fifo_high_threshold_select_reg.reg_num; | ||
1303 | reg = | ||
1304 | fifo_high_threshold_select_reg. | ||
1305 | iga1_fifo_high_threshold_select_reg.reg; | ||
1306 | viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR); | ||
1307 | |||
1308 | /* Set Display Queue Expire Num */ | ||
1309 | reg_value = | ||
1310 | IGA1_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA | ||
1311 | (iga1_display_queue_expire_num); | ||
1312 | viafb_load_reg_num = | ||
1313 | display_queue_expire_num_reg. | ||
1314 | iga1_display_queue_expire_num_reg.reg_num; | ||
1315 | reg = | ||
1316 | display_queue_expire_num_reg. | ||
1317 | iga1_display_queue_expire_num_reg.reg; | ||
1318 | viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR); | ||
1319 | |||
1320 | } else { | ||
1321 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) { | ||
1322 | iga2_fifo_max_depth = K800_IGA2_FIFO_MAX_DEPTH; | ||
1323 | iga2_fifo_threshold = K800_IGA2_FIFO_THRESHOLD; | ||
1324 | iga2_fifo_high_threshold = | ||
1325 | K800_IGA2_FIFO_HIGH_THRESHOLD; | ||
1326 | |||
1327 | /* If resolution > 1280x1024, expire length = 64, | ||
1328 | else expire length = 128 */ | ||
1329 | if ((hor_active > 1280) && (ver_active > 1024)) | ||
1330 | iga2_display_queue_expire_num = 16; | ||
1331 | else | ||
1332 | iga2_display_queue_expire_num = | ||
1333 | K800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1334 | } | ||
1335 | |||
1336 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_PM800) { | ||
1337 | iga2_fifo_max_depth = P880_IGA2_FIFO_MAX_DEPTH; | ||
1338 | iga2_fifo_threshold = P880_IGA2_FIFO_THRESHOLD; | ||
1339 | iga2_fifo_high_threshold = | ||
1340 | P880_IGA2_FIFO_HIGH_THRESHOLD; | ||
1341 | |||
1342 | /* If resolution > 1280x1024, expire length = 64, | ||
1343 | else expire length = 128 */ | ||
1344 | if ((hor_active > 1280) && (ver_active > 1024)) | ||
1345 | iga2_display_queue_expire_num = 16; | ||
1346 | else | ||
1347 | iga2_display_queue_expire_num = | ||
1348 | P880_IGA2_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1349 | } | ||
1350 | |||
1351 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CN700) { | ||
1352 | iga2_fifo_max_depth = CN700_IGA2_FIFO_MAX_DEPTH; | ||
1353 | iga2_fifo_threshold = CN700_IGA2_FIFO_THRESHOLD; | ||
1354 | iga2_fifo_high_threshold = | ||
1355 | CN700_IGA2_FIFO_HIGH_THRESHOLD; | ||
1356 | |||
1357 | /* If resolution > 1280x1024, expire length = 64, | ||
1358 | else expire length = 128 */ | ||
1359 | if ((hor_active > 1280) && (ver_active > 1024)) | ||
1360 | iga2_display_queue_expire_num = 16; | ||
1361 | else | ||
1362 | iga2_display_queue_expire_num = | ||
1363 | CN700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1364 | } | ||
1365 | |||
1366 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) { | ||
1367 | iga2_fifo_max_depth = CX700_IGA2_FIFO_MAX_DEPTH; | ||
1368 | iga2_fifo_threshold = CX700_IGA2_FIFO_THRESHOLD; | ||
1369 | iga2_fifo_high_threshold = | ||
1370 | CX700_IGA2_FIFO_HIGH_THRESHOLD; | ||
1371 | iga2_display_queue_expire_num = | ||
1372 | CX700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1373 | } | ||
1374 | |||
1375 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890) { | ||
1376 | iga2_fifo_max_depth = K8M890_IGA2_FIFO_MAX_DEPTH; | ||
1377 | iga2_fifo_threshold = K8M890_IGA2_FIFO_THRESHOLD; | ||
1378 | iga2_fifo_high_threshold = | ||
1379 | K8M890_IGA2_FIFO_HIGH_THRESHOLD; | ||
1380 | iga2_display_queue_expire_num = | ||
1381 | K8M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1382 | } | ||
1383 | |||
1384 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M890) { | ||
1385 | iga2_fifo_max_depth = P4M890_IGA2_FIFO_MAX_DEPTH; | ||
1386 | iga2_fifo_threshold = P4M890_IGA2_FIFO_THRESHOLD; | ||
1387 | iga2_fifo_high_threshold = | ||
1388 | P4M890_IGA2_FIFO_HIGH_THRESHOLD; | ||
1389 | iga2_display_queue_expire_num = | ||
1390 | P4M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1391 | } | ||
1392 | |||
1393 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M900) { | ||
1394 | iga2_fifo_max_depth = P4M900_IGA2_FIFO_MAX_DEPTH; | ||
1395 | iga2_fifo_threshold = P4M900_IGA2_FIFO_THRESHOLD; | ||
1396 | iga2_fifo_high_threshold = | ||
1397 | P4M900_IGA2_FIFO_HIGH_THRESHOLD; | ||
1398 | iga2_display_queue_expire_num = | ||
1399 | P4M900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1400 | } | ||
1401 | |||
1402 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX800) { | ||
1403 | iga2_fifo_max_depth = VX800_IGA2_FIFO_MAX_DEPTH; | ||
1404 | iga2_fifo_threshold = VX800_IGA2_FIFO_THRESHOLD; | ||
1405 | iga2_fifo_high_threshold = | ||
1406 | VX800_IGA2_FIFO_HIGH_THRESHOLD; | ||
1407 | iga2_display_queue_expire_num = | ||
1408 | VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1409 | } | ||
1410 | |||
1411 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) { | ||
1412 | /* Set Display FIFO Depath Select */ | ||
1413 | reg_value = | ||
1414 | IGA2_FIFO_DEPTH_SELECT_FORMULA(iga2_fifo_max_depth) | ||
1415 | - 1; | ||
1416 | /* Patch LCD in IGA2 case */ | ||
1417 | viafb_load_reg_num = | ||
1418 | display_fifo_depth_reg. | ||
1419 | iga2_fifo_depth_select_reg.reg_num; | ||
1420 | reg = | ||
1421 | display_fifo_depth_reg. | ||
1422 | iga2_fifo_depth_select_reg.reg; | ||
1423 | viafb_load_reg(reg_value, | ||
1424 | viafb_load_reg_num, reg, VIACR); | ||
1425 | } else { | ||
1426 | |||
1427 | /* Set Display FIFO Depath Select */ | ||
1428 | reg_value = | ||
1429 | IGA2_FIFO_DEPTH_SELECT_FORMULA(iga2_fifo_max_depth); | ||
1430 | viafb_load_reg_num = | ||
1431 | display_fifo_depth_reg. | ||
1432 | iga2_fifo_depth_select_reg.reg_num; | ||
1433 | reg = | ||
1434 | display_fifo_depth_reg. | ||
1435 | iga2_fifo_depth_select_reg.reg; | ||
1436 | viafb_load_reg(reg_value, | ||
1437 | viafb_load_reg_num, reg, VIACR); | ||
1438 | } | ||
1439 | |||
1440 | /* Set Display FIFO Threshold Select */ | ||
1441 | reg_value = IGA2_FIFO_THRESHOLD_FORMULA(iga2_fifo_threshold); | ||
1442 | viafb_load_reg_num = | ||
1443 | fifo_threshold_select_reg. | ||
1444 | iga2_fifo_threshold_select_reg.reg_num; | ||
1445 | reg = | ||
1446 | fifo_threshold_select_reg. | ||
1447 | iga2_fifo_threshold_select_reg.reg; | ||
1448 | viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR); | ||
1449 | |||
1450 | /* Set FIFO High Threshold Select */ | ||
1451 | reg_value = | ||
1452 | IGA2_FIFO_HIGH_THRESHOLD_FORMULA(iga2_fifo_high_threshold); | ||
1453 | viafb_load_reg_num = | ||
1454 | fifo_high_threshold_select_reg. | ||
1455 | iga2_fifo_high_threshold_select_reg.reg_num; | ||
1456 | reg = | ||
1457 | fifo_high_threshold_select_reg. | ||
1458 | iga2_fifo_high_threshold_select_reg.reg; | ||
1459 | viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR); | ||
1460 | |||
1461 | /* Set Display Queue Expire Num */ | ||
1462 | reg_value = | ||
1463 | IGA2_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA | ||
1464 | (iga2_display_queue_expire_num); | ||
1465 | viafb_load_reg_num = | ||
1466 | display_queue_expire_num_reg. | ||
1467 | iga2_display_queue_expire_num_reg.reg_num; | ||
1468 | reg = | ||
1469 | display_queue_expire_num_reg. | ||
1470 | iga2_display_queue_expire_num_reg.reg; | ||
1471 | viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR); | ||
1472 | |||
1473 | } | ||
1474 | |||
1475 | } | ||
1476 | |||
1477 | u32 viafb_get_clk_value(int clk) | ||
1478 | { | ||
1479 | int i; | ||
1480 | |||
1481 | for (i = 0; i < NUM_TOTAL_PLL_TABLE; i++) { | ||
1482 | if (clk == pll_value[i].clk) { | ||
1483 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
1484 | case UNICHROME_CLE266: | ||
1485 | case UNICHROME_K400: | ||
1486 | return pll_value[i].cle266_pll; | ||
1487 | |||
1488 | case UNICHROME_K800: | ||
1489 | case UNICHROME_PM800: | ||
1490 | case UNICHROME_CN700: | ||
1491 | return pll_value[i].k800_pll; | ||
1492 | |||
1493 | case UNICHROME_CX700: | ||
1494 | case UNICHROME_K8M890: | ||
1495 | case UNICHROME_P4M890: | ||
1496 | case UNICHROME_P4M900: | ||
1497 | case UNICHROME_VX800: | ||
1498 | return pll_value[i].cx700_pll; | ||
1499 | } | ||
1500 | } | ||
1501 | } | ||
1502 | |||
1503 | DEBUG_MSG(KERN_INFO "Can't find match PLL value\n\n"); | ||
1504 | return 0; | ||
1505 | } | ||
1506 | |||
1507 | /* Set VCLK*/ | ||
1508 | void viafb_set_vclock(u32 CLK, int set_iga) | ||
1509 | { | ||
1510 | unsigned char RegTemp; | ||
1511 | |||
1512 | /* H.W. Reset : ON */ | ||
1513 | viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7); | ||
1514 | |||
1515 | if ((set_iga == IGA1) || (set_iga == IGA1_IGA2)) { | ||
1516 | /* Change D,N FOR VCLK */ | ||
1517 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
1518 | case UNICHROME_CLE266: | ||
1519 | case UNICHROME_K400: | ||
1520 | viafb_write_reg(SR46, VIASR, CLK / 0x100); | ||
1521 | viafb_write_reg(SR47, VIASR, CLK % 0x100); | ||
1522 | break; | ||
1523 | |||
1524 | case UNICHROME_K800: | ||
1525 | case UNICHROME_PM800: | ||
1526 | case UNICHROME_CN700: | ||
1527 | case UNICHROME_CX700: | ||
1528 | case UNICHROME_K8M890: | ||
1529 | case UNICHROME_P4M890: | ||
1530 | case UNICHROME_P4M900: | ||
1531 | case UNICHROME_VX800: | ||
1532 | viafb_write_reg(SR44, VIASR, CLK / 0x10000); | ||
1533 | DEBUG_MSG(KERN_INFO "\nSR44=%x", CLK / 0x10000); | ||
1534 | viafb_write_reg(SR45, VIASR, (CLK & 0xFFFF) / 0x100); | ||
1535 | DEBUG_MSG(KERN_INFO "\nSR45=%x", | ||
1536 | (CLK & 0xFFFF) / 0x100); | ||
1537 | viafb_write_reg(SR46, VIASR, CLK % 0x100); | ||
1538 | DEBUG_MSG(KERN_INFO "\nSR46=%x", CLK % 0x100); | ||
1539 | break; | ||
1540 | } | ||
1541 | } | ||
1542 | |||
1543 | if ((set_iga == IGA2) || (set_iga == IGA1_IGA2)) { | ||
1544 | /* Change D,N FOR LCK */ | ||
1545 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
1546 | case UNICHROME_CLE266: | ||
1547 | case UNICHROME_K400: | ||
1548 | viafb_write_reg(SR44, VIASR, CLK / 0x100); | ||
1549 | viafb_write_reg(SR45, VIASR, CLK % 0x100); | ||
1550 | break; | ||
1551 | |||
1552 | case UNICHROME_K800: | ||
1553 | case UNICHROME_PM800: | ||
1554 | case UNICHROME_CN700: | ||
1555 | case UNICHROME_CX700: | ||
1556 | case UNICHROME_K8M890: | ||
1557 | case UNICHROME_P4M890: | ||
1558 | case UNICHROME_P4M900: | ||
1559 | case UNICHROME_VX800: | ||
1560 | viafb_write_reg(SR4A, VIASR, CLK / 0x10000); | ||
1561 | viafb_write_reg(SR4B, VIASR, (CLK & 0xFFFF) / 0x100); | ||
1562 | viafb_write_reg(SR4C, VIASR, CLK % 0x100); | ||
1563 | break; | ||
1564 | } | ||
1565 | } | ||
1566 | |||
1567 | /* H.W. Reset : OFF */ | ||
1568 | viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7); | ||
1569 | |||
1570 | /* Reset PLL */ | ||
1571 | if ((set_iga == IGA1) || (set_iga == IGA1_IGA2)) { | ||
1572 | viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1); | ||
1573 | viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1); | ||
1574 | } | ||
1575 | |||
1576 | if ((set_iga == IGA2) || (set_iga == IGA1_IGA2)) { | ||
1577 | viafb_write_reg_mask(SR40, VIASR, 0x01, BIT0); | ||
1578 | viafb_write_reg_mask(SR40, VIASR, 0x00, BIT0); | ||
1579 | } | ||
1580 | |||
1581 | /* Fire! */ | ||
1582 | RegTemp = inb(VIARMisc); | ||
1583 | outb(RegTemp | (BIT2 + BIT3), VIAWMisc); | ||
1584 | } | ||
1585 | |||
1586 | void viafb_load_crtc_timing(struct display_timing device_timing, | ||
1587 | int set_iga) | ||
1588 | { | ||
1589 | int i; | ||
1590 | int viafb_load_reg_num = 0; | ||
1591 | int reg_value = 0; | ||
1592 | struct io_register *reg = NULL; | ||
1593 | |||
1594 | viafb_unlock_crt(); | ||
1595 | |||
1596 | for (i = 0; i < 12; i++) { | ||
1597 | if (set_iga == IGA1) { | ||
1598 | switch (i) { | ||
1599 | case H_TOTAL_INDEX: | ||
1600 | reg_value = | ||
1601 | IGA1_HOR_TOTAL_FORMULA(device_timing. | ||
1602 | hor_total); | ||
1603 | viafb_load_reg_num = | ||
1604 | iga1_crtc_reg.hor_total.reg_num; | ||
1605 | reg = iga1_crtc_reg.hor_total.reg; | ||
1606 | break; | ||
1607 | case H_ADDR_INDEX: | ||
1608 | reg_value = | ||
1609 | IGA1_HOR_ADDR_FORMULA(device_timing. | ||
1610 | hor_addr); | ||
1611 | viafb_load_reg_num = | ||
1612 | iga1_crtc_reg.hor_addr.reg_num; | ||
1613 | reg = iga1_crtc_reg.hor_addr.reg; | ||
1614 | break; | ||
1615 | case H_BLANK_START_INDEX: | ||
1616 | reg_value = | ||
1617 | IGA1_HOR_BLANK_START_FORMULA | ||
1618 | (device_timing.hor_blank_start); | ||
1619 | viafb_load_reg_num = | ||
1620 | iga1_crtc_reg.hor_blank_start.reg_num; | ||
1621 | reg = iga1_crtc_reg.hor_blank_start.reg; | ||
1622 | break; | ||
1623 | case H_BLANK_END_INDEX: | ||
1624 | reg_value = | ||
1625 | IGA1_HOR_BLANK_END_FORMULA | ||
1626 | (device_timing.hor_blank_start, | ||
1627 | device_timing.hor_blank_end); | ||
1628 | viafb_load_reg_num = | ||
1629 | iga1_crtc_reg.hor_blank_end.reg_num; | ||
1630 | reg = iga1_crtc_reg.hor_blank_end.reg; | ||
1631 | break; | ||
1632 | case H_SYNC_START_INDEX: | ||
1633 | reg_value = | ||
1634 | IGA1_HOR_SYNC_START_FORMULA | ||
1635 | (device_timing.hor_sync_start); | ||
1636 | viafb_load_reg_num = | ||
1637 | iga1_crtc_reg.hor_sync_start.reg_num; | ||
1638 | reg = iga1_crtc_reg.hor_sync_start.reg; | ||
1639 | break; | ||
1640 | case H_SYNC_END_INDEX: | ||
1641 | reg_value = | ||
1642 | IGA1_HOR_SYNC_END_FORMULA | ||
1643 | (device_timing.hor_sync_start, | ||
1644 | device_timing.hor_sync_end); | ||
1645 | viafb_load_reg_num = | ||
1646 | iga1_crtc_reg.hor_sync_end.reg_num; | ||
1647 | reg = iga1_crtc_reg.hor_sync_end.reg; | ||
1648 | break; | ||
1649 | case V_TOTAL_INDEX: | ||
1650 | reg_value = | ||
1651 | IGA1_VER_TOTAL_FORMULA(device_timing. | ||
1652 | ver_total); | ||
1653 | viafb_load_reg_num = | ||
1654 | iga1_crtc_reg.ver_total.reg_num; | ||
1655 | reg = iga1_crtc_reg.ver_total.reg; | ||
1656 | break; | ||
1657 | case V_ADDR_INDEX: | ||
1658 | reg_value = | ||
1659 | IGA1_VER_ADDR_FORMULA(device_timing. | ||
1660 | ver_addr); | ||
1661 | viafb_load_reg_num = | ||
1662 | iga1_crtc_reg.ver_addr.reg_num; | ||
1663 | reg = iga1_crtc_reg.ver_addr.reg; | ||
1664 | break; | ||
1665 | case V_BLANK_START_INDEX: | ||
1666 | reg_value = | ||
1667 | IGA1_VER_BLANK_START_FORMULA | ||
1668 | (device_timing.ver_blank_start); | ||
1669 | viafb_load_reg_num = | ||
1670 | iga1_crtc_reg.ver_blank_start.reg_num; | ||
1671 | reg = iga1_crtc_reg.ver_blank_start.reg; | ||
1672 | break; | ||
1673 | case V_BLANK_END_INDEX: | ||
1674 | reg_value = | ||
1675 | IGA1_VER_BLANK_END_FORMULA | ||
1676 | (device_timing.ver_blank_start, | ||
1677 | device_timing.ver_blank_end); | ||
1678 | viafb_load_reg_num = | ||
1679 | iga1_crtc_reg.ver_blank_end.reg_num; | ||
1680 | reg = iga1_crtc_reg.ver_blank_end.reg; | ||
1681 | break; | ||
1682 | case V_SYNC_START_INDEX: | ||
1683 | reg_value = | ||
1684 | IGA1_VER_SYNC_START_FORMULA | ||
1685 | (device_timing.ver_sync_start); | ||
1686 | viafb_load_reg_num = | ||
1687 | iga1_crtc_reg.ver_sync_start.reg_num; | ||
1688 | reg = iga1_crtc_reg.ver_sync_start.reg; | ||
1689 | break; | ||
1690 | case V_SYNC_END_INDEX: | ||
1691 | reg_value = | ||
1692 | IGA1_VER_SYNC_END_FORMULA | ||
1693 | (device_timing.ver_sync_start, | ||
1694 | device_timing.ver_sync_end); | ||
1695 | viafb_load_reg_num = | ||
1696 | iga1_crtc_reg.ver_sync_end.reg_num; | ||
1697 | reg = iga1_crtc_reg.ver_sync_end.reg; | ||
1698 | break; | ||
1699 | |||
1700 | } | ||
1701 | } | ||
1702 | |||
1703 | if (set_iga == IGA2) { | ||
1704 | switch (i) { | ||
1705 | case H_TOTAL_INDEX: | ||
1706 | reg_value = | ||
1707 | IGA2_HOR_TOTAL_FORMULA(device_timing. | ||
1708 | hor_total); | ||
1709 | viafb_load_reg_num = | ||
1710 | iga2_crtc_reg.hor_total.reg_num; | ||
1711 | reg = iga2_crtc_reg.hor_total.reg; | ||
1712 | break; | ||
1713 | case H_ADDR_INDEX: | ||
1714 | reg_value = | ||
1715 | IGA2_HOR_ADDR_FORMULA(device_timing. | ||
1716 | hor_addr); | ||
1717 | viafb_load_reg_num = | ||
1718 | iga2_crtc_reg.hor_addr.reg_num; | ||
1719 | reg = iga2_crtc_reg.hor_addr.reg; | ||
1720 | break; | ||
1721 | case H_BLANK_START_INDEX: | ||
1722 | reg_value = | ||
1723 | IGA2_HOR_BLANK_START_FORMULA | ||
1724 | (device_timing.hor_blank_start); | ||
1725 | viafb_load_reg_num = | ||
1726 | iga2_crtc_reg.hor_blank_start.reg_num; | ||
1727 | reg = iga2_crtc_reg.hor_blank_start.reg; | ||
1728 | break; | ||
1729 | case H_BLANK_END_INDEX: | ||
1730 | reg_value = | ||
1731 | IGA2_HOR_BLANK_END_FORMULA | ||
1732 | (device_timing.hor_blank_start, | ||
1733 | device_timing.hor_blank_end); | ||
1734 | viafb_load_reg_num = | ||
1735 | iga2_crtc_reg.hor_blank_end.reg_num; | ||
1736 | reg = iga2_crtc_reg.hor_blank_end.reg; | ||
1737 | break; | ||
1738 | case H_SYNC_START_INDEX: | ||
1739 | reg_value = | ||
1740 | IGA2_HOR_SYNC_START_FORMULA | ||
1741 | (device_timing.hor_sync_start); | ||
1742 | if (UNICHROME_CN700 <= | ||
1743 | viaparinfo->chip_info->gfx_chip_name) | ||
1744 | viafb_load_reg_num = | ||
1745 | iga2_crtc_reg.hor_sync_start. | ||
1746 | reg_num; | ||
1747 | else | ||
1748 | viafb_load_reg_num = 3; | ||
1749 | reg = iga2_crtc_reg.hor_sync_start.reg; | ||
1750 | break; | ||
1751 | case H_SYNC_END_INDEX: | ||
1752 | reg_value = | ||
1753 | IGA2_HOR_SYNC_END_FORMULA | ||
1754 | (device_timing.hor_sync_start, | ||
1755 | device_timing.hor_sync_end); | ||
1756 | viafb_load_reg_num = | ||
1757 | iga2_crtc_reg.hor_sync_end.reg_num; | ||
1758 | reg = iga2_crtc_reg.hor_sync_end.reg; | ||
1759 | break; | ||
1760 | case V_TOTAL_INDEX: | ||
1761 | reg_value = | ||
1762 | IGA2_VER_TOTAL_FORMULA(device_timing. | ||
1763 | ver_total); | ||
1764 | viafb_load_reg_num = | ||
1765 | iga2_crtc_reg.ver_total.reg_num; | ||
1766 | reg = iga2_crtc_reg.ver_total.reg; | ||
1767 | break; | ||
1768 | case V_ADDR_INDEX: | ||
1769 | reg_value = | ||
1770 | IGA2_VER_ADDR_FORMULA(device_timing. | ||
1771 | ver_addr); | ||
1772 | viafb_load_reg_num = | ||
1773 | iga2_crtc_reg.ver_addr.reg_num; | ||
1774 | reg = iga2_crtc_reg.ver_addr.reg; | ||
1775 | break; | ||
1776 | case V_BLANK_START_INDEX: | ||
1777 | reg_value = | ||
1778 | IGA2_VER_BLANK_START_FORMULA | ||
1779 | (device_timing.ver_blank_start); | ||
1780 | viafb_load_reg_num = | ||
1781 | iga2_crtc_reg.ver_blank_start.reg_num; | ||
1782 | reg = iga2_crtc_reg.ver_blank_start.reg; | ||
1783 | break; | ||
1784 | case V_BLANK_END_INDEX: | ||
1785 | reg_value = | ||
1786 | IGA2_VER_BLANK_END_FORMULA | ||
1787 | (device_timing.ver_blank_start, | ||
1788 | device_timing.ver_blank_end); | ||
1789 | viafb_load_reg_num = | ||
1790 | iga2_crtc_reg.ver_blank_end.reg_num; | ||
1791 | reg = iga2_crtc_reg.ver_blank_end.reg; | ||
1792 | break; | ||
1793 | case V_SYNC_START_INDEX: | ||
1794 | reg_value = | ||
1795 | IGA2_VER_SYNC_START_FORMULA | ||
1796 | (device_timing.ver_sync_start); | ||
1797 | viafb_load_reg_num = | ||
1798 | iga2_crtc_reg.ver_sync_start.reg_num; | ||
1799 | reg = iga2_crtc_reg.ver_sync_start.reg; | ||
1800 | break; | ||
1801 | case V_SYNC_END_INDEX: | ||
1802 | reg_value = | ||
1803 | IGA2_VER_SYNC_END_FORMULA | ||
1804 | (device_timing.ver_sync_start, | ||
1805 | device_timing.ver_sync_end); | ||
1806 | viafb_load_reg_num = | ||
1807 | iga2_crtc_reg.ver_sync_end.reg_num; | ||
1808 | reg = iga2_crtc_reg.ver_sync_end.reg; | ||
1809 | break; | ||
1810 | |||
1811 | } | ||
1812 | } | ||
1813 | viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR); | ||
1814 | } | ||
1815 | |||
1816 | viafb_lock_crt(); | ||
1817 | } | ||
1818 | |||
1819 | void viafb_set_color_depth(int bpp_byte, int set_iga) | ||
1820 | { | ||
1821 | if (set_iga == IGA1) { | ||
1822 | switch (bpp_byte) { | ||
1823 | case MODE_8BPP: | ||
1824 | viafb_write_reg_mask(SR15, VIASR, 0x22, 0x7E); | ||
1825 | break; | ||
1826 | case MODE_16BPP: | ||
1827 | viafb_write_reg_mask(SR15, VIASR, 0xB6, 0xFE); | ||
1828 | break; | ||
1829 | case MODE_32BPP: | ||
1830 | viafb_write_reg_mask(SR15, VIASR, 0xAE, 0xFE); | ||
1831 | break; | ||
1832 | } | ||
1833 | } else { | ||
1834 | switch (bpp_byte) { | ||
1835 | case MODE_8BPP: | ||
1836 | viafb_write_reg_mask(CR67, VIACR, 0x00, BIT6 + BIT7); | ||
1837 | break; | ||
1838 | case MODE_16BPP: | ||
1839 | viafb_write_reg_mask(CR67, VIACR, 0x40, BIT6 + BIT7); | ||
1840 | break; | ||
1841 | case MODE_32BPP: | ||
1842 | viafb_write_reg_mask(CR67, VIACR, 0xC0, BIT6 + BIT7); | ||
1843 | break; | ||
1844 | } | ||
1845 | } | ||
1846 | } | ||
1847 | |||
1848 | void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, | ||
1849 | int mode_index, int bpp_byte, int set_iga) | ||
1850 | { | ||
1851 | struct VideoModeTable *video_mode; | ||
1852 | struct display_timing crt_reg; | ||
1853 | int i; | ||
1854 | int index = 0; | ||
1855 | int h_addr, v_addr; | ||
1856 | u32 pll_D_N; | ||
1857 | |||
1858 | video_mode = &CLE266Modes[search_mode_setting(mode_index)]; | ||
1859 | |||
1860 | for (i = 0; i < video_mode->mode_array; i++) { | ||
1861 | index = i; | ||
1862 | |||
1863 | if (crt_table[i].refresh_rate == viaparinfo-> | ||
1864 | crt_setting_info->refresh_rate) | ||
1865 | break; | ||
1866 | } | ||
1867 | |||
1868 | crt_reg = crt_table[index].crtc; | ||
1869 | |||
1870 | /* Mode 640x480 has border, but LCD/DFP didn't have border. */ | ||
1871 | /* So we would delete border. */ | ||
1872 | if ((viafb_LCD_ON | viafb_DVI_ON) && (mode_index == VIA_RES_640X480) | ||
1873 | && (viaparinfo->crt_setting_info->refresh_rate == 60)) { | ||
1874 | /* The border is 8 pixels. */ | ||
1875 | crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8; | ||
1876 | |||
1877 | /* Blanking time should add left and right borders. */ | ||
1878 | crt_reg.hor_blank_end = crt_reg.hor_blank_end + 16; | ||
1879 | } | ||
1880 | |||
1881 | h_addr = crt_reg.hor_addr; | ||
1882 | v_addr = crt_reg.ver_addr; | ||
1883 | |||
1884 | /* update polarity for CRT timing */ | ||
1885 | if (crt_table[index].h_sync_polarity == NEGATIVE) { | ||
1886 | if (crt_table[index].v_sync_polarity == NEGATIVE) | ||
1887 | outb((inb(VIARMisc) & (~(BIT6 + BIT7))) | | ||
1888 | (BIT6 + BIT7), VIAWMisc); | ||
1889 | else | ||
1890 | outb((inb(VIARMisc) & (~(BIT6 + BIT7))) | (BIT6), | ||
1891 | VIAWMisc); | ||
1892 | } else { | ||
1893 | if (crt_table[index].v_sync_polarity == NEGATIVE) | ||
1894 | outb((inb(VIARMisc) & (~(BIT6 + BIT7))) | (BIT7), | ||
1895 | VIAWMisc); | ||
1896 | else | ||
1897 | outb((inb(VIARMisc) & (~(BIT6 + BIT7))), VIAWMisc); | ||
1898 | } | ||
1899 | |||
1900 | if (set_iga == IGA1) { | ||
1901 | viafb_unlock_crt(); | ||
1902 | viafb_write_reg(CR09, VIACR, 0x00); /*initial CR09=0 */ | ||
1903 | viafb_write_reg_mask(CR11, VIACR, 0x00, BIT4 + BIT5 + BIT6); | ||
1904 | viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7); | ||
1905 | } | ||
1906 | |||
1907 | switch (set_iga) { | ||
1908 | case IGA1: | ||
1909 | viafb_load_crtc_timing(crt_reg, IGA1); | ||
1910 | break; | ||
1911 | case IGA2: | ||
1912 | viafb_load_crtc_timing(crt_reg, IGA2); | ||
1913 | break; | ||
1914 | } | ||
1915 | |||
1916 | load_fix_bit_crtc_reg(); | ||
1917 | viafb_lock_crt(); | ||
1918 | viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7); | ||
1919 | viafb_load_offset_reg(h_addr, bpp_byte, set_iga); | ||
1920 | viafb_load_fetch_count_reg(h_addr, bpp_byte, set_iga); | ||
1921 | |||
1922 | /* load FIFO */ | ||
1923 | if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266) | ||
1924 | && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)) | ||
1925 | viafb_load_FIFO_reg(set_iga, h_addr, v_addr); | ||
1926 | |||
1927 | /* load SR Register About Memory and Color part */ | ||
1928 | viafb_set_color_depth(bpp_byte, set_iga); | ||
1929 | |||
1930 | pll_D_N = viafb_get_clk_value(crt_table[index].clk); | ||
1931 | DEBUG_MSG(KERN_INFO "PLL=%x", pll_D_N); | ||
1932 | viafb_set_vclock(pll_D_N, set_iga); | ||
1933 | |||
1934 | } | ||
1935 | |||
1936 | void viafb_init_chip_info(void) | ||
1937 | { | ||
1938 | init_gfx_chip_info(); | ||
1939 | init_tmds_chip_info(); | ||
1940 | init_lvds_chip_info(); | ||
1941 | |||
1942 | viaparinfo->crt_setting_info->iga_path = IGA1; | ||
1943 | viaparinfo->crt_setting_info->refresh_rate = viafb_refresh; | ||
1944 | |||
1945 | /*Set IGA path for each device */ | ||
1946 | viafb_set_iga_path(); | ||
1947 | |||
1948 | viaparinfo->lvds_setting_info->display_method = viafb_lcd_dsp_method; | ||
1949 | viaparinfo->lvds_setting_info->get_lcd_size_method = | ||
1950 | GET_LCD_SIZE_BY_USER_SETTING; | ||
1951 | viaparinfo->lvds_setting_info->lcd_mode = viafb_lcd_mode; | ||
1952 | viaparinfo->lvds_setting_info2->display_method = | ||
1953 | viaparinfo->lvds_setting_info->display_method; | ||
1954 | viaparinfo->lvds_setting_info2->lcd_mode = | ||
1955 | viaparinfo->lvds_setting_info->lcd_mode; | ||
1956 | } | ||
1957 | |||
1958 | void viafb_update_device_setting(int hres, int vres, | ||
1959 | int bpp, int vmode_refresh, int flag) | ||
1960 | { | ||
1961 | if (flag == 0) { | ||
1962 | viaparinfo->crt_setting_info->h_active = hres; | ||
1963 | viaparinfo->crt_setting_info->v_active = vres; | ||
1964 | viaparinfo->crt_setting_info->bpp = bpp; | ||
1965 | viaparinfo->crt_setting_info->refresh_rate = | ||
1966 | vmode_refresh; | ||
1967 | |||
1968 | viaparinfo->tmds_setting_info->h_active = hres; | ||
1969 | viaparinfo->tmds_setting_info->v_active = vres; | ||
1970 | viaparinfo->tmds_setting_info->bpp = bpp; | ||
1971 | viaparinfo->tmds_setting_info->refresh_rate = | ||
1972 | vmode_refresh; | ||
1973 | |||
1974 | viaparinfo->lvds_setting_info->h_active = hres; | ||
1975 | viaparinfo->lvds_setting_info->v_active = vres; | ||
1976 | viaparinfo->lvds_setting_info->bpp = bpp; | ||
1977 | viaparinfo->lvds_setting_info->refresh_rate = | ||
1978 | vmode_refresh; | ||
1979 | viaparinfo->lvds_setting_info2->h_active = hres; | ||
1980 | viaparinfo->lvds_setting_info2->v_active = vres; | ||
1981 | viaparinfo->lvds_setting_info2->bpp = bpp; | ||
1982 | viaparinfo->lvds_setting_info2->refresh_rate = | ||
1983 | vmode_refresh; | ||
1984 | } else { | ||
1985 | |||
1986 | if (viaparinfo->tmds_setting_info->iga_path == IGA2) { | ||
1987 | viaparinfo->tmds_setting_info->h_active = hres; | ||
1988 | viaparinfo->tmds_setting_info->v_active = vres; | ||
1989 | viaparinfo->tmds_setting_info->bpp = bpp; | ||
1990 | viaparinfo->tmds_setting_info->refresh_rate = | ||
1991 | vmode_refresh; | ||
1992 | } | ||
1993 | |||
1994 | if (viaparinfo->lvds_setting_info->iga_path == IGA2) { | ||
1995 | viaparinfo->lvds_setting_info->h_active = hres; | ||
1996 | viaparinfo->lvds_setting_info->v_active = vres; | ||
1997 | viaparinfo->lvds_setting_info->bpp = bpp; | ||
1998 | viaparinfo->lvds_setting_info->refresh_rate = | ||
1999 | vmode_refresh; | ||
2000 | } | ||
2001 | if (IGA2 == viaparinfo->lvds_setting_info2->iga_path) { | ||
2002 | viaparinfo->lvds_setting_info2->h_active = hres; | ||
2003 | viaparinfo->lvds_setting_info2->v_active = vres; | ||
2004 | viaparinfo->lvds_setting_info2->bpp = bpp; | ||
2005 | viaparinfo->lvds_setting_info2->refresh_rate = | ||
2006 | vmode_refresh; | ||
2007 | } | ||
2008 | } | ||
2009 | } | ||
2010 | |||
2011 | static void init_gfx_chip_info(void) | ||
2012 | { | ||
2013 | struct pci_dev *pdev = NULL; | ||
2014 | u32 i; | ||
2015 | u8 tmp; | ||
2016 | |||
2017 | /* Indentify GFX Chip Name */ | ||
2018 | for (i = 0; pciidlist[i].vendor != 0; i++) { | ||
2019 | pdev = pci_get_device(pciidlist[i].vendor, | ||
2020 | pciidlist[i].device, 0); | ||
2021 | if (pdev) | ||
2022 | break; | ||
2023 | } | ||
2024 | |||
2025 | if (!pciidlist[i].vendor) | ||
2026 | return ; | ||
2027 | |||
2028 | viaparinfo->chip_info->gfx_chip_name = pciidlist[i].chip_index; | ||
2029 | |||
2030 | /* Check revision of CLE266 Chip */ | ||
2031 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) { | ||
2032 | /* CR4F only define in CLE266.CX chip */ | ||
2033 | tmp = viafb_read_reg(VIACR, CR4F); | ||
2034 | viafb_write_reg(CR4F, VIACR, 0x55); | ||
2035 | if (viafb_read_reg(VIACR, CR4F) != 0x55) | ||
2036 | viaparinfo->chip_info->gfx_chip_revision = | ||
2037 | CLE266_REVISION_AX; | ||
2038 | else | ||
2039 | viaparinfo->chip_info->gfx_chip_revision = | ||
2040 | CLE266_REVISION_CX; | ||
2041 | /* restore orignal CR4F value */ | ||
2042 | viafb_write_reg(CR4F, VIACR, tmp); | ||
2043 | } | ||
2044 | |||
2045 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) { | ||
2046 | tmp = viafb_read_reg(VIASR, SR43); | ||
2047 | DEBUG_MSG(KERN_INFO "SR43:%X\n", tmp); | ||
2048 | if (tmp & 0x02) { | ||
2049 | viaparinfo->chip_info->gfx_chip_revision = | ||
2050 | CX700_REVISION_700M2; | ||
2051 | } else if (tmp & 0x40) { | ||
2052 | viaparinfo->chip_info->gfx_chip_revision = | ||
2053 | CX700_REVISION_700M; | ||
2054 | } else { | ||
2055 | viaparinfo->chip_info->gfx_chip_revision = | ||
2056 | CX700_REVISION_700; | ||
2057 | } | ||
2058 | } | ||
2059 | |||
2060 | pci_dev_put(pdev); | ||
2061 | } | ||
2062 | |||
2063 | static void init_tmds_chip_info(void) | ||
2064 | { | ||
2065 | viafb_tmds_trasmitter_identify(); | ||
2066 | |||
2067 | if (INTERFACE_NONE == viaparinfo->chip_info->tmds_chip_info. | ||
2068 | output_interface) { | ||
2069 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
2070 | case UNICHROME_CX700: | ||
2071 | { | ||
2072 | /* we should check support by hardware layout.*/ | ||
2073 | if ((viafb_display_hardware_layout == | ||
2074 | HW_LAYOUT_DVI_ONLY) | ||
2075 | || (viafb_display_hardware_layout == | ||
2076 | HW_LAYOUT_LCD_DVI)) { | ||
2077 | viaparinfo->chip_info->tmds_chip_info. | ||
2078 | output_interface = INTERFACE_TMDS; | ||
2079 | } else { | ||
2080 | viaparinfo->chip_info->tmds_chip_info. | ||
2081 | output_interface = | ||
2082 | INTERFACE_NONE; | ||
2083 | } | ||
2084 | break; | ||
2085 | } | ||
2086 | case UNICHROME_K8M890: | ||
2087 | case UNICHROME_P4M900: | ||
2088 | case UNICHROME_P4M890: | ||
2089 | /* TMDS on PCIE, we set DFPLOW as default. */ | ||
2090 | viaparinfo->chip_info->tmds_chip_info.output_interface = | ||
2091 | INTERFACE_DFP_LOW; | ||
2092 | break; | ||
2093 | default: | ||
2094 | { | ||
2095 | /* set DVP1 default for DVI */ | ||
2096 | viaparinfo->chip_info->tmds_chip_info | ||
2097 | .output_interface = INTERFACE_DVP1; | ||
2098 | } | ||
2099 | } | ||
2100 | } | ||
2101 | |||
2102 | DEBUG_MSG(KERN_INFO "TMDS Chip = %d\n", | ||
2103 | viaparinfo->chip_info->tmds_chip_info.tmds_chip_name); | ||
2104 | viaparinfo->tmds_setting_info->get_dvi_size_method = | ||
2105 | GET_DVI_SIZE_BY_VGA_BIOS; | ||
2106 | viafb_init_dvi_size(); | ||
2107 | } | ||
2108 | |||
2109 | static void init_lvds_chip_info(void) | ||
2110 | { | ||
2111 | if (viafb_lcd_panel_id > LCD_PANEL_ID_MAXIMUM) | ||
2112 | viaparinfo->lvds_setting_info->get_lcd_size_method = | ||
2113 | GET_LCD_SIZE_BY_VGA_BIOS; | ||
2114 | else | ||
2115 | viaparinfo->lvds_setting_info->get_lcd_size_method = | ||
2116 | GET_LCD_SIZE_BY_USER_SETTING; | ||
2117 | |||
2118 | viafb_lvds_trasmitter_identify(); | ||
2119 | viafb_init_lcd_size(); | ||
2120 | viafb_init_lvds_output_interface(&viaparinfo->chip_info->lvds_chip_info, | ||
2121 | viaparinfo->lvds_setting_info); | ||
2122 | if (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) { | ||
2123 | viafb_init_lvds_output_interface(&viaparinfo->chip_info-> | ||
2124 | lvds_chip_info2, viaparinfo->lvds_setting_info2); | ||
2125 | } | ||
2126 | /*If CX700,two singel LCD, we need to reassign | ||
2127 | LCD interface to different LVDS port */ | ||
2128 | if ((UNICHROME_CX700 == viaparinfo->chip_info->gfx_chip_name) | ||
2129 | && (HW_LAYOUT_LCD1_LCD2 == viafb_display_hardware_layout)) { | ||
2130 | if ((INTEGRATED_LVDS == viaparinfo->chip_info->lvds_chip_info. | ||
2131 | lvds_chip_name) && (INTEGRATED_LVDS == | ||
2132 | viaparinfo->chip_info-> | ||
2133 | lvds_chip_info2.lvds_chip_name)) { | ||
2134 | viaparinfo->chip_info->lvds_chip_info.output_interface = | ||
2135 | INTERFACE_LVDS0; | ||
2136 | viaparinfo->chip_info->lvds_chip_info2. | ||
2137 | output_interface = | ||
2138 | INTERFACE_LVDS1; | ||
2139 | } | ||
2140 | } | ||
2141 | |||
2142 | DEBUG_MSG(KERN_INFO "LVDS Chip = %d\n", | ||
2143 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name); | ||
2144 | DEBUG_MSG(KERN_INFO "LVDS1 output_interface = %d\n", | ||
2145 | viaparinfo->chip_info->lvds_chip_info.output_interface); | ||
2146 | DEBUG_MSG(KERN_INFO "LVDS2 output_interface = %d\n", | ||
2147 | viaparinfo->chip_info->lvds_chip_info.output_interface); | ||
2148 | } | ||
2149 | |||
2150 | void viafb_init_dac(int set_iga) | ||
2151 | { | ||
2152 | int i; | ||
2153 | u8 tmp; | ||
2154 | |||
2155 | if (set_iga == IGA1) { | ||
2156 | /* access Primary Display's LUT */ | ||
2157 | viafb_write_reg_mask(SR1A, VIASR, 0x00, BIT0); | ||
2158 | /* turn off LCK */ | ||
2159 | viafb_write_reg_mask(SR1B, VIASR, 0x00, BIT7 + BIT6); | ||
2160 | for (i = 0; i < 256; i++) { | ||
2161 | write_dac_reg(i, palLUT_table[i].red, | ||
2162 | palLUT_table[i].green, | ||
2163 | palLUT_table[i].blue); | ||
2164 | } | ||
2165 | /* turn on LCK */ | ||
2166 | viafb_write_reg_mask(SR1B, VIASR, 0xC0, BIT7 + BIT6); | ||
2167 | } else { | ||
2168 | tmp = viafb_read_reg(VIACR, CR6A); | ||
2169 | /* access Secondary Display's LUT */ | ||
2170 | viafb_write_reg_mask(CR6A, VIACR, 0x40, BIT6); | ||
2171 | viafb_write_reg_mask(SR1A, VIASR, 0x01, BIT0); | ||
2172 | for (i = 0; i < 256; i++) { | ||
2173 | write_dac_reg(i, palLUT_table[i].red, | ||
2174 | palLUT_table[i].green, | ||
2175 | palLUT_table[i].blue); | ||
2176 | } | ||
2177 | /* set IGA1 DAC for default */ | ||
2178 | viafb_write_reg_mask(SR1A, VIASR, 0x00, BIT0); | ||
2179 | viafb_write_reg(CR6A, VIACR, tmp); | ||
2180 | } | ||
2181 | } | ||
2182 | |||
2183 | static void device_screen_off(void) | ||
2184 | { | ||
2185 | /* turn off CRT screen (IGA1) */ | ||
2186 | viafb_write_reg_mask(SR01, VIASR, 0x20, BIT5); | ||
2187 | } | ||
2188 | |||
2189 | static void device_screen_on(void) | ||
2190 | { | ||
2191 | /* turn on CRT screen (IGA1) */ | ||
2192 | viafb_write_reg_mask(SR01, VIASR, 0x00, BIT5); | ||
2193 | } | ||
2194 | |||
2195 | static void set_display_channel(void) | ||
2196 | { | ||
2197 | /*If viafb_LCD2_ON, on cx700, internal lvds's information | ||
2198 | is keeped on lvds_setting_info2 */ | ||
2199 | if (viafb_LCD2_ON && | ||
2200 | viaparinfo->lvds_setting_info2->device_lcd_dualedge) { | ||
2201 | /* For dual channel LCD: */ | ||
2202 | /* Set to Dual LVDS channel. */ | ||
2203 | viafb_write_reg_mask(CRD2, VIACR, 0x20, BIT4 + BIT5); | ||
2204 | } else if (viafb_LCD_ON && viafb_DVI_ON) { | ||
2205 | /* For LCD+DFP: */ | ||
2206 | /* Set to LVDS1 + TMDS channel. */ | ||
2207 | viafb_write_reg_mask(CRD2, VIACR, 0x10, BIT4 + BIT5); | ||
2208 | } else if (viafb_DVI_ON) { | ||
2209 | /* Set to single TMDS channel. */ | ||
2210 | viafb_write_reg_mask(CRD2, VIACR, 0x30, BIT4 + BIT5); | ||
2211 | } else if (viafb_LCD_ON) { | ||
2212 | if (viaparinfo->lvds_setting_info->device_lcd_dualedge) { | ||
2213 | /* For dual channel LCD: */ | ||
2214 | /* Set to Dual LVDS channel. */ | ||
2215 | viafb_write_reg_mask(CRD2, VIACR, 0x20, BIT4 + BIT5); | ||
2216 | } else { | ||
2217 | /* Set to LVDS0 + LVDS1 channel. */ | ||
2218 | viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT4 + BIT5); | ||
2219 | } | ||
2220 | } | ||
2221 | } | ||
2222 | |||
2223 | int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, | ||
2224 | int vmode_index1, int hor_res1, int ver_res1, int video_bpp1) | ||
2225 | { | ||
2226 | int i, j; | ||
2227 | int port; | ||
2228 | u8 value, index, mask; | ||
2229 | struct VideoModeTable *vmode_tbl; | ||
2230 | struct crt_mode_table *crt_timing; | ||
2231 | struct VideoModeTable *vmode_tbl1 = NULL; | ||
2232 | struct crt_mode_table *crt_timing1 = NULL; | ||
2233 | |||
2234 | DEBUG_MSG(KERN_INFO "Set Mode!!\n"); | ||
2235 | DEBUG_MSG(KERN_INFO | ||
2236 | "vmode_index=%d hor_res=%d ver_res=%d video_bpp=%d\n", | ||
2237 | vmode_index, hor_res, ver_res, video_bpp); | ||
2238 | |||
2239 | device_screen_off(); | ||
2240 | vmode_tbl = &CLE266Modes[search_mode_setting(vmode_index)]; | ||
2241 | crt_timing = vmode_tbl->crtc; | ||
2242 | |||
2243 | if (viafb_SAMM_ON == 1) { | ||
2244 | vmode_tbl1 = &CLE266Modes[search_mode_setting(vmode_index1)]; | ||
2245 | crt_timing1 = vmode_tbl1->crtc; | ||
2246 | } | ||
2247 | |||
2248 | inb(VIAStatus); | ||
2249 | outb(0x00, VIAAR); | ||
2250 | |||
2251 | /* Write Common Setting for Video Mode */ | ||
2252 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
2253 | case UNICHROME_CLE266: | ||
2254 | viafb_write_regx(CLE266_ModeXregs, NUM_TOTAL_CLE266_ModeXregs); | ||
2255 | break; | ||
2256 | |||
2257 | case UNICHROME_K400: | ||
2258 | viafb_write_regx(KM400_ModeXregs, NUM_TOTAL_KM400_ModeXregs); | ||
2259 | break; | ||
2260 | |||
2261 | case UNICHROME_K800: | ||
2262 | case UNICHROME_PM800: | ||
2263 | viafb_write_regx(CN400_ModeXregs, NUM_TOTAL_CN400_ModeXregs); | ||
2264 | break; | ||
2265 | |||
2266 | case UNICHROME_CN700: | ||
2267 | case UNICHROME_K8M890: | ||
2268 | case UNICHROME_P4M890: | ||
2269 | case UNICHROME_P4M900: | ||
2270 | viafb_write_regx(CN700_ModeXregs, NUM_TOTAL_CN700_ModeXregs); | ||
2271 | break; | ||
2272 | |||
2273 | case UNICHROME_CX700: | ||
2274 | viafb_write_regx(CX700_ModeXregs, NUM_TOTAL_CX700_ModeXregs); | ||
2275 | |||
2276 | case UNICHROME_VX800: | ||
2277 | viafb_write_regx(VX800_ModeXregs, NUM_TOTAL_VX800_ModeXregs); | ||
2278 | |||
2279 | break; | ||
2280 | } | ||
2281 | |||
2282 | device_off(); | ||
2283 | |||
2284 | /* Fill VPIT Parameters */ | ||
2285 | /* Write Misc Register */ | ||
2286 | outb(VPIT.Misc, VIAWMisc); | ||
2287 | |||
2288 | /* Write Sequencer */ | ||
2289 | for (i = 1; i <= StdSR; i++) { | ||
2290 | outb(i, VIASR); | ||
2291 | outb(VPIT.SR[i - 1], VIASR + 1); | ||
2292 | } | ||
2293 | |||
2294 | viafb_set_start_addr(); | ||
2295 | viafb_set_iga_path(); | ||
2296 | |||
2297 | /* Write CRTC */ | ||
2298 | viafb_fill_crtc_timing(crt_timing, vmode_index, video_bpp / 8, IGA1); | ||
2299 | |||
2300 | /* Write Graphic Controller */ | ||
2301 | for (i = 0; i < StdGR; i++) { | ||
2302 | outb(i, VIAGR); | ||
2303 | outb(VPIT.GR[i], VIAGR + 1); | ||
2304 | } | ||
2305 | |||
2306 | /* Write Attribute Controller */ | ||
2307 | for (i = 0; i < StdAR; i++) { | ||
2308 | inb(VIAStatus); | ||
2309 | outb(i, VIAAR); | ||
2310 | outb(VPIT.AR[i], VIAAR); | ||
2311 | } | ||
2312 | |||
2313 | inb(VIAStatus); | ||
2314 | outb(0x20, VIAAR); | ||
2315 | |||
2316 | /* Update Patch Register */ | ||
2317 | |||
2318 | if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) | ||
2319 | || (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400)) { | ||
2320 | for (i = 0; i < NUM_TOTAL_PATCH_MODE; i++) { | ||
2321 | if (res_patch_table[i].mode_index == vmode_index) { | ||
2322 | for (j = 0; | ||
2323 | j < res_patch_table[i].table_length; j++) { | ||
2324 | index = | ||
2325 | res_patch_table[i]. | ||
2326 | io_reg_table[j].index; | ||
2327 | port = | ||
2328 | res_patch_table[i]. | ||
2329 | io_reg_table[j].port; | ||
2330 | value = | ||
2331 | res_patch_table[i]. | ||
2332 | io_reg_table[j].value; | ||
2333 | mask = | ||
2334 | res_patch_table[i]. | ||
2335 | io_reg_table[j].mask; | ||
2336 | viafb_write_reg_mask(index, port, value, | ||
2337 | mask); | ||
2338 | } | ||
2339 | } | ||
2340 | } | ||
2341 | } | ||
2342 | |||
2343 | if (viafb_SAMM_ON == 1) { | ||
2344 | if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) | ||
2345 | || (viaparinfo->chip_info->gfx_chip_name == | ||
2346 | UNICHROME_K400)) { | ||
2347 | for (i = 0; i < NUM_TOTAL_PATCH_MODE; i++) { | ||
2348 | if (res_patch_table[i].mode_index == | ||
2349 | vmode_index1) { | ||
2350 | for (j = 0; | ||
2351 | j < | ||
2352 | res_patch_table[i]. | ||
2353 | table_length; j++) { | ||
2354 | index = | ||
2355 | res_patch_table[i]. | ||
2356 | io_reg_table[j].index; | ||
2357 | port = | ||
2358 | res_patch_table[i]. | ||
2359 | io_reg_table[j].port; | ||
2360 | value = | ||
2361 | res_patch_table[i]. | ||
2362 | io_reg_table[j].value; | ||
2363 | mask = | ||
2364 | res_patch_table[i]. | ||
2365 | io_reg_table[j].mask; | ||
2366 | viafb_write_reg_mask(index, | ||
2367 | port, value, mask); | ||
2368 | } | ||
2369 | } | ||
2370 | } | ||
2371 | } | ||
2372 | } | ||
2373 | |||
2374 | /* Update Refresh Rate Setting */ | ||
2375 | |||
2376 | /* Clear On Screen */ | ||
2377 | |||
2378 | /* CRT set mode */ | ||
2379 | if (viafb_CRT_ON) { | ||
2380 | if (viafb_SAMM_ON && (viaparinfo->crt_setting_info->iga_path == | ||
2381 | IGA2)) { | ||
2382 | viafb_fill_crtc_timing(crt_timing1, vmode_index1, | ||
2383 | video_bpp1 / 8, | ||
2384 | viaparinfo->crt_setting_info->iga_path); | ||
2385 | } else { | ||
2386 | viafb_fill_crtc_timing(crt_timing, vmode_index, | ||
2387 | video_bpp / 8, | ||
2388 | viaparinfo->crt_setting_info->iga_path); | ||
2389 | } | ||
2390 | |||
2391 | set_crt_output_path(viaparinfo->crt_setting_info->iga_path); | ||
2392 | |||
2393 | /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode | ||
2394 | to 8 alignment (1368),there is several pixels (2 pixels) | ||
2395 | on right side of screen. */ | ||
2396 | if (hor_res % 8) { | ||
2397 | viafb_unlock_crt(); | ||
2398 | viafb_write_reg(CR02, VIACR, | ||
2399 | viafb_read_reg(VIACR, CR02) - 1); | ||
2400 | viafb_lock_crt(); | ||
2401 | } | ||
2402 | } | ||
2403 | |||
2404 | if (viafb_DVI_ON) { | ||
2405 | if (viafb_SAMM_ON && | ||
2406 | (viaparinfo->tmds_setting_info->iga_path == IGA2)) { | ||
2407 | viafb_dvi_set_mode(viafb_get_mode_index | ||
2408 | (viaparinfo->tmds_setting_info->h_active, | ||
2409 | viaparinfo->tmds_setting_info-> | ||
2410 | v_active, 1), | ||
2411 | video_bpp1, viaparinfo-> | ||
2412 | tmds_setting_info->iga_path); | ||
2413 | } else { | ||
2414 | viafb_dvi_set_mode(viafb_get_mode_index | ||
2415 | (viaparinfo->tmds_setting_info->h_active, | ||
2416 | viaparinfo-> | ||
2417 | tmds_setting_info->v_active, 0), | ||
2418 | video_bpp, viaparinfo-> | ||
2419 | tmds_setting_info->iga_path); | ||
2420 | } | ||
2421 | } | ||
2422 | |||
2423 | if (viafb_LCD_ON) { | ||
2424 | if (viafb_SAMM_ON && | ||
2425 | (viaparinfo->lvds_setting_info->iga_path == IGA2)) { | ||
2426 | viaparinfo->lvds_setting_info->bpp = video_bpp1; | ||
2427 | viafb_lcd_set_mode(crt_timing1, viaparinfo-> | ||
2428 | lvds_setting_info, | ||
2429 | &viaparinfo->chip_info->lvds_chip_info); | ||
2430 | } else { | ||
2431 | /* IGA1 doesn't have LCD scaling, so set it center. */ | ||
2432 | if (viaparinfo->lvds_setting_info->iga_path == IGA1) { | ||
2433 | viaparinfo->lvds_setting_info->display_method = | ||
2434 | LCD_CENTERING; | ||
2435 | } | ||
2436 | viaparinfo->lvds_setting_info->bpp = video_bpp; | ||
2437 | viafb_lcd_set_mode(crt_timing, viaparinfo-> | ||
2438 | lvds_setting_info, | ||
2439 | &viaparinfo->chip_info->lvds_chip_info); | ||
2440 | } | ||
2441 | } | ||
2442 | if (viafb_LCD2_ON) { | ||
2443 | if (viafb_SAMM_ON && | ||
2444 | (viaparinfo->lvds_setting_info2->iga_path == IGA2)) { | ||
2445 | viaparinfo->lvds_setting_info2->bpp = video_bpp1; | ||
2446 | viafb_lcd_set_mode(crt_timing1, viaparinfo-> | ||
2447 | lvds_setting_info2, | ||
2448 | &viaparinfo->chip_info->lvds_chip_info2); | ||
2449 | } else { | ||
2450 | /* IGA1 doesn't have LCD scaling, so set it center. */ | ||
2451 | if (viaparinfo->lvds_setting_info2->iga_path == IGA1) { | ||
2452 | viaparinfo->lvds_setting_info2->display_method = | ||
2453 | LCD_CENTERING; | ||
2454 | } | ||
2455 | viaparinfo->lvds_setting_info2->bpp = video_bpp; | ||
2456 | viafb_lcd_set_mode(crt_timing, viaparinfo-> | ||
2457 | lvds_setting_info2, | ||
2458 | &viaparinfo->chip_info->lvds_chip_info2); | ||
2459 | } | ||
2460 | } | ||
2461 | |||
2462 | if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) | ||
2463 | && (viafb_LCD_ON || viafb_DVI_ON)) | ||
2464 | set_display_channel(); | ||
2465 | |||
2466 | /* If set mode normally, save resolution information for hot-plug . */ | ||
2467 | if (!viafb_hotplug) { | ||
2468 | viafb_hotplug_Xres = hor_res; | ||
2469 | viafb_hotplug_Yres = ver_res; | ||
2470 | viafb_hotplug_bpp = video_bpp; | ||
2471 | viafb_hotplug_refresh = viafb_refresh; | ||
2472 | |||
2473 | if (viafb_DVI_ON) | ||
2474 | viafb_DeviceStatus = DVI_Device; | ||
2475 | else | ||
2476 | viafb_DeviceStatus = CRT_Device; | ||
2477 | } | ||
2478 | device_on(); | ||
2479 | |||
2480 | if (viafb_SAMM_ON == 1) | ||
2481 | viafb_write_reg_mask(CR6A, VIACR, 0xC0, BIT6 + BIT7); | ||
2482 | |||
2483 | device_screen_on(); | ||
2484 | return 1; | ||
2485 | } | ||
2486 | |||
2487 | int viafb_get_pixclock(int hres, int vres, int vmode_refresh) | ||
2488 | { | ||
2489 | int i; | ||
2490 | |||
2491 | for (i = 0; i < NUM_TOTAL_RES_MAP_REFRESH; i++) { | ||
2492 | if ((hres == res_map_refresh_tbl[i].hres) | ||
2493 | && (vres == res_map_refresh_tbl[i].vres) | ||
2494 | && (vmode_refresh == res_map_refresh_tbl[i].vmode_refresh)) | ||
2495 | return res_map_refresh_tbl[i].pixclock; | ||
2496 | } | ||
2497 | return RES_640X480_60HZ_PIXCLOCK; | ||
2498 | |||
2499 | } | ||
2500 | |||
2501 | int viafb_get_refresh(int hres, int vres, u32 long_refresh) | ||
2502 | { | ||
2503 | #define REFRESH_TOLERANCE 3 | ||
2504 | int i, nearest = -1, diff = REFRESH_TOLERANCE; | ||
2505 | for (i = 0; i < NUM_TOTAL_RES_MAP_REFRESH; i++) { | ||
2506 | if ((hres == res_map_refresh_tbl[i].hres) | ||
2507 | && (vres == res_map_refresh_tbl[i].vres) | ||
2508 | && (diff > (abs(long_refresh - | ||
2509 | res_map_refresh_tbl[i].vmode_refresh)))) { | ||
2510 | diff = abs(long_refresh - res_map_refresh_tbl[i]. | ||
2511 | vmode_refresh); | ||
2512 | nearest = i; | ||
2513 | } | ||
2514 | } | ||
2515 | #undef REFRESH_TOLERANCE | ||
2516 | if (nearest > 0) | ||
2517 | return res_map_refresh_tbl[nearest].vmode_refresh; | ||
2518 | return 60; | ||
2519 | } | ||
2520 | |||
2521 | static void device_off(void) | ||
2522 | { | ||
2523 | viafb_crt_disable(); | ||
2524 | viafb_dvi_disable(); | ||
2525 | viafb_lcd_disable(); | ||
2526 | } | ||
2527 | |||
2528 | static void device_on(void) | ||
2529 | { | ||
2530 | if (viafb_CRT_ON == 1) | ||
2531 | viafb_crt_enable(); | ||
2532 | if (viafb_DVI_ON == 1) | ||
2533 | viafb_dvi_enable(); | ||
2534 | if (viafb_LCD_ON == 1) | ||
2535 | viafb_lcd_enable(); | ||
2536 | } | ||
2537 | |||
2538 | void viafb_crt_disable(void) | ||
2539 | { | ||
2540 | viafb_write_reg_mask(CR36, VIACR, BIT5 + BIT4, BIT5 + BIT4); | ||
2541 | } | ||
2542 | |||
2543 | void viafb_crt_enable(void) | ||
2544 | { | ||
2545 | viafb_write_reg_mask(CR36, VIACR, 0x0, BIT5 + BIT4); | ||
2546 | } | ||
2547 | |||
2548 | void viafb_get_mmio_info(unsigned long *mmio_base, | ||
2549 | unsigned long *mmio_len) | ||
2550 | { | ||
2551 | struct pci_dev *pdev = NULL; | ||
2552 | u32 vendor, device; | ||
2553 | u32 i; | ||
2554 | |||
2555 | for (i = 0; pciidlist[i].vendor != 0; i++) | ||
2556 | if (viaparinfo->chip_info->gfx_chip_name == | ||
2557 | pciidlist[i].chip_index) | ||
2558 | break; | ||
2559 | |||
2560 | if (!pciidlist[i].vendor) | ||
2561 | return ; | ||
2562 | |||
2563 | vendor = pciidlist[i].vendor; | ||
2564 | device = pciidlist[i].device; | ||
2565 | |||
2566 | pdev = pci_get_device(vendor, device, NULL); | ||
2567 | |||
2568 | if (!pdev) { | ||
2569 | *mmio_base = 0; | ||
2570 | *mmio_len = 0; | ||
2571 | return ; | ||
2572 | } | ||
2573 | |||
2574 | *mmio_base = pci_resource_start(pdev, 1); | ||
2575 | *mmio_len = pci_resource_len(pdev, 1); | ||
2576 | |||
2577 | pci_dev_put(pdev); | ||
2578 | } | ||
2579 | |||
2580 | static void enable_second_display_channel(void) | ||
2581 | { | ||
2582 | /* to enable second display channel. */ | ||
2583 | viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT6); | ||
2584 | viafb_write_reg_mask(CR6A, VIACR, BIT7, BIT7); | ||
2585 | viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6); | ||
2586 | } | ||
2587 | |||
2588 | static void disable_second_display_channel(void) | ||
2589 | { | ||
2590 | /* to disable second display channel. */ | ||
2591 | viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT6); | ||
2592 | viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT7); | ||
2593 | viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6); | ||
2594 | } | ||
2595 | |||
2596 | void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len) | ||
2597 | { | ||
2598 | struct pci_dev *pdev = NULL; | ||
2599 | u32 vendor, device; | ||
2600 | u32 i; | ||
2601 | |||
2602 | for (i = 0; pciidlist[i].vendor != 0; i++) | ||
2603 | if (viaparinfo->chip_info->gfx_chip_name == | ||
2604 | pciidlist[i].chip_index) | ||
2605 | break; | ||
2606 | |||
2607 | if (!pciidlist[i].vendor) | ||
2608 | return ; | ||
2609 | |||
2610 | vendor = pciidlist[i].vendor; | ||
2611 | device = pciidlist[i].device; | ||
2612 | |||
2613 | pdev = pci_get_device(vendor, device, NULL); | ||
2614 | |||
2615 | if (!pdev) { | ||
2616 | *fb_base = viafb_read_reg(VIASR, SR30) << 24; | ||
2617 | *fb_len = viafb_get_memsize(); | ||
2618 | DEBUG_MSG(KERN_INFO "Get FB info from SR30!\n"); | ||
2619 | DEBUG_MSG(KERN_INFO "fb_base = %08x\n", *fb_base); | ||
2620 | DEBUG_MSG(KERN_INFO "fb_len = %08x\n", *fb_len); | ||
2621 | return ; | ||
2622 | } | ||
2623 | |||
2624 | *fb_base = (unsigned int)pci_resource_start(pdev, 0); | ||
2625 | *fb_len = get_fb_size_from_pci(); | ||
2626 | DEBUG_MSG(KERN_INFO "Get FB info from PCI system!\n"); | ||
2627 | DEBUG_MSG(KERN_INFO "fb_base = %08x\n", *fb_base); | ||
2628 | DEBUG_MSG(KERN_INFO "fb_len = %08x\n", *fb_len); | ||
2629 | |||
2630 | pci_dev_put(pdev); | ||
2631 | } | ||
2632 | |||
2633 | static int get_fb_size_from_pci(void) | ||
2634 | { | ||
2635 | unsigned long configid, deviceid, FBSize = 0; | ||
2636 | int VideoMemSize; | ||
2637 | int DeviceFound = false; | ||
2638 | |||
2639 | for (configid = 0x80000000; configid < 0x80010800; configid += 0x100) { | ||
2640 | outl(configid, (unsigned long)0xCF8); | ||
2641 | deviceid = (inl((unsigned long)0xCFC) >> 16) & 0xffff; | ||
2642 | |||
2643 | switch (deviceid) { | ||
2644 | case CLE266: | ||
2645 | case KM400: | ||
2646 | outl(configid + 0xE0, (unsigned long)0xCF8); | ||
2647 | FBSize = inl((unsigned long)0xCFC); | ||
2648 | DeviceFound = true; /* Found device id */ | ||
2649 | break; | ||
2650 | |||
2651 | case CN400_FUNCTION3: | ||
2652 | case CN700_FUNCTION3: | ||
2653 | case CX700_FUNCTION3: | ||
2654 | case KM800_FUNCTION3: | ||
2655 | case KM890_FUNCTION3: | ||
2656 | case P4M890_FUNCTION3: | ||
2657 | case P4M900_FUNCTION3: | ||
2658 | case VX800_FUNCTION3: | ||
2659 | /*case CN750_FUNCTION3: */ | ||
2660 | outl(configid + 0xA0, (unsigned long)0xCF8); | ||
2661 | FBSize = inl((unsigned long)0xCFC); | ||
2662 | DeviceFound = true; /* Found device id */ | ||
2663 | break; | ||
2664 | |||
2665 | default: | ||
2666 | break; | ||
2667 | } | ||
2668 | |||
2669 | if (DeviceFound) | ||
2670 | break; | ||
2671 | } | ||
2672 | |||
2673 | DEBUG_MSG(KERN_INFO "Device ID = %lx\n", deviceid); | ||
2674 | |||
2675 | FBSize = FBSize & 0x00007000; | ||
2676 | DEBUG_MSG(KERN_INFO "FB Size = %x\n", FBSize); | ||
2677 | |||
2678 | if (viaparinfo->chip_info->gfx_chip_name < UNICHROME_CX700) { | ||
2679 | switch (FBSize) { | ||
2680 | case 0x00004000: | ||
2681 | VideoMemSize = (16 << 20); /*16M */ | ||
2682 | break; | ||
2683 | |||
2684 | case 0x00005000: | ||
2685 | VideoMemSize = (32 << 20); /*32M */ | ||
2686 | break; | ||
2687 | |||
2688 | case 0x00006000: | ||
2689 | VideoMemSize = (64 << 20); /*64M */ | ||
2690 | break; | ||
2691 | |||
2692 | default: | ||
2693 | VideoMemSize = (32 << 20); /*32M */ | ||
2694 | break; | ||
2695 | } | ||
2696 | } else { | ||
2697 | switch (FBSize) { | ||
2698 | case 0x00001000: | ||
2699 | VideoMemSize = (8 << 20); /*8M */ | ||
2700 | break; | ||
2701 | |||
2702 | case 0x00002000: | ||
2703 | VideoMemSize = (16 << 20); /*16M */ | ||
2704 | break; | ||
2705 | |||
2706 | case 0x00003000: | ||
2707 | VideoMemSize = (32 << 20); /*32M */ | ||
2708 | break; | ||
2709 | |||
2710 | case 0x00004000: | ||
2711 | VideoMemSize = (64 << 20); /*64M */ | ||
2712 | break; | ||
2713 | |||
2714 | case 0x00005000: | ||
2715 | VideoMemSize = (128 << 20); /*128M */ | ||
2716 | break; | ||
2717 | |||
2718 | case 0x00006000: | ||
2719 | VideoMemSize = (256 << 20); /*256M */ | ||
2720 | break; | ||
2721 | |||
2722 | default: | ||
2723 | VideoMemSize = (32 << 20); /*32M */ | ||
2724 | break; | ||
2725 | } | ||
2726 | } | ||
2727 | |||
2728 | return VideoMemSize; | ||
2729 | } | ||
2730 | |||
2731 | void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ | ||
2732 | *p_gfx_dpa_setting) | ||
2733 | { | ||
2734 | switch (output_interface) { | ||
2735 | case INTERFACE_DVP0: | ||
2736 | { | ||
2737 | /* DVP0 Clock Polarity and Adjust: */ | ||
2738 | viafb_write_reg_mask(CR96, VIACR, | ||
2739 | p_gfx_dpa_setting->DVP0, 0x0F); | ||
2740 | |||
2741 | /* DVP0 Clock and Data Pads Driving: */ | ||
2742 | viafb_write_reg_mask(SR1E, VIASR, | ||
2743 | p_gfx_dpa_setting->DVP0ClockDri_S, BIT2); | ||
2744 | viafb_write_reg_mask(SR2A, VIASR, | ||
2745 | p_gfx_dpa_setting->DVP0ClockDri_S1, | ||
2746 | BIT4); | ||
2747 | viafb_write_reg_mask(SR1B, VIASR, | ||
2748 | p_gfx_dpa_setting->DVP0DataDri_S, BIT1); | ||
2749 | viafb_write_reg_mask(SR2A, VIASR, | ||
2750 | p_gfx_dpa_setting->DVP0DataDri_S1, BIT5); | ||
2751 | break; | ||
2752 | } | ||
2753 | |||
2754 | case INTERFACE_DVP1: | ||
2755 | { | ||
2756 | /* DVP1 Clock Polarity and Adjust: */ | ||
2757 | viafb_write_reg_mask(CR9B, VIACR, | ||
2758 | p_gfx_dpa_setting->DVP1, 0x0F); | ||
2759 | |||
2760 | /* DVP1 Clock and Data Pads Driving: */ | ||
2761 | viafb_write_reg_mask(SR65, VIASR, | ||
2762 | p_gfx_dpa_setting->DVP1Driving, 0x0F); | ||
2763 | break; | ||
2764 | } | ||
2765 | |||
2766 | case INTERFACE_DFP_HIGH: | ||
2767 | { | ||
2768 | viafb_write_reg_mask(CR97, VIACR, | ||
2769 | p_gfx_dpa_setting->DFPHigh, 0x0F); | ||
2770 | break; | ||
2771 | } | ||
2772 | |||
2773 | case INTERFACE_DFP_LOW: | ||
2774 | { | ||
2775 | viafb_write_reg_mask(CR99, VIACR, | ||
2776 | p_gfx_dpa_setting->DFPLow, 0x0F); | ||
2777 | break; | ||
2778 | } | ||
2779 | |||
2780 | case INTERFACE_DFP: | ||
2781 | { | ||
2782 | viafb_write_reg_mask(CR97, VIACR, | ||
2783 | p_gfx_dpa_setting->DFPHigh, 0x0F); | ||
2784 | viafb_write_reg_mask(CR99, VIACR, | ||
2785 | p_gfx_dpa_setting->DFPLow, 0x0F); | ||
2786 | break; | ||
2787 | } | ||
2788 | } | ||
2789 | } | ||
2790 | |||
2791 | void viafb_memory_pitch_patch(struct fb_info *info) | ||
2792 | { | ||
2793 | if (info->var.xres != info->var.xres_virtual) { | ||
2794 | viafb_load_offset_reg(info->var.xres_virtual, | ||
2795 | info->var.bits_per_pixel >> 3, IGA1); | ||
2796 | |||
2797 | if (viafb_SAMM_ON) { | ||
2798 | viafb_load_offset_reg(viafb_second_virtual_xres, | ||
2799 | viafb_bpp1 >> 3, | ||
2800 | IGA2); | ||
2801 | } else { | ||
2802 | viafb_load_offset_reg(info->var.xres_virtual, | ||
2803 | info->var.bits_per_pixel >> 3, IGA2); | ||
2804 | } | ||
2805 | |||
2806 | } | ||
2807 | } | ||
2808 | |||
2809 | /*According var's xres, yres fill var's other timing information*/ | ||
2810 | void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, | ||
2811 | int mode_index) | ||
2812 | { | ||
2813 | struct VideoModeTable *vmode_tbl = NULL; | ||
2814 | struct crt_mode_table *crt_timing = NULL; | ||
2815 | struct display_timing crt_reg; | ||
2816 | int i = 0, index = 0; | ||
2817 | vmode_tbl = &CLE266Modes[search_mode_setting(mode_index)]; | ||
2818 | crt_timing = vmode_tbl->crtc; | ||
2819 | for (i = 0; i < vmode_tbl->mode_array; i++) { | ||
2820 | index = i; | ||
2821 | if (crt_timing[i].refresh_rate == refresh) | ||
2822 | break; | ||
2823 | } | ||
2824 | |||
2825 | crt_reg = crt_timing[index].crtc; | ||
2826 | switch (var->bits_per_pixel) { | ||
2827 | case 8: | ||
2828 | var->red.offset = 0; | ||
2829 | var->green.offset = 0; | ||
2830 | var->blue.offset = 0; | ||
2831 | var->red.length = 6; | ||
2832 | var->green.length = 6; | ||
2833 | var->blue.length = 6; | ||
2834 | break; | ||
2835 | case 16: | ||
2836 | var->red.offset = 11; | ||
2837 | var->green.offset = 5; | ||
2838 | var->blue.offset = 0; | ||
2839 | var->red.length = 5; | ||
2840 | var->green.length = 6; | ||
2841 | var->blue.length = 5; | ||
2842 | break; | ||
2843 | case 32: | ||
2844 | var->red.offset = 16; | ||
2845 | var->green.offset = 8; | ||
2846 | var->blue.offset = 0; | ||
2847 | var->red.length = 8; | ||
2848 | var->green.length = 8; | ||
2849 | var->blue.length = 8; | ||
2850 | break; | ||
2851 | default: | ||
2852 | /* never happed, put here to keep consistent */ | ||
2853 | break; | ||
2854 | } | ||
2855 | |||
2856 | var->pixclock = viafb_get_pixclock(var->xres, var->yres, refresh); | ||
2857 | var->left_margin = | ||
2858 | crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end); | ||
2859 | var->right_margin = crt_reg.hor_sync_start - crt_reg.hor_addr; | ||
2860 | var->hsync_len = crt_reg.hor_sync_end; | ||
2861 | var->upper_margin = | ||
2862 | crt_reg.ver_total - (crt_reg.ver_sync_start + crt_reg.ver_sync_end); | ||
2863 | var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr; | ||
2864 | var->vsync_len = crt_reg.ver_sync_end; | ||
2865 | } | ||
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h new file mode 100644 index 000000000000..6ff38fa8569a --- /dev/null +++ b/drivers/video/via/hw.h | |||
@@ -0,0 +1,933 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef __HW_H__ | ||
23 | #define __HW_H__ | ||
24 | |||
25 | #include "global.h" | ||
26 | |||
27 | /*************************************************** | ||
28 | * Definition IGA1 Design Method of CRTC Registers * | ||
29 | ****************************************************/ | ||
30 | #define IGA1_HOR_TOTAL_FORMULA(x) (((x)/8)-5) | ||
31 | #define IGA1_HOR_ADDR_FORMULA(x) (((x)/8)-1) | ||
32 | #define IGA1_HOR_BLANK_START_FORMULA(x) (((x)/8)-1) | ||
33 | #define IGA1_HOR_BLANK_END_FORMULA(x, y) (((x+y)/8)-1) | ||
34 | #define IGA1_HOR_SYNC_START_FORMULA(x) ((x)/8) | ||
35 | #define IGA1_HOR_SYNC_END_FORMULA(x, y) ((x+y)/8) | ||
36 | |||
37 | #define IGA1_VER_TOTAL_FORMULA(x) ((x)-2) | ||
38 | #define IGA1_VER_ADDR_FORMULA(x) ((x)-1) | ||
39 | #define IGA1_VER_BLANK_START_FORMULA(x) ((x)-1) | ||
40 | #define IGA1_VER_BLANK_END_FORMULA(x, y) ((x+y)-1) | ||
41 | #define IGA1_VER_SYNC_START_FORMULA(x) ((x)-1) | ||
42 | #define IGA1_VER_SYNC_END_FORMULA(x, y) ((x+y)-1) | ||
43 | |||
44 | /*************************************************** | ||
45 | ** Definition IGA2 Design Method of CRTC Registers * | ||
46 | ****************************************************/ | ||
47 | #define IGA2_HOR_TOTAL_FORMULA(x) ((x)-1) | ||
48 | #define IGA2_HOR_ADDR_FORMULA(x) ((x)-1) | ||
49 | #define IGA2_HOR_BLANK_START_FORMULA(x) ((x)-1) | ||
50 | #define IGA2_HOR_BLANK_END_FORMULA(x, y) ((x+y)-1) | ||
51 | #define IGA2_HOR_SYNC_START_FORMULA(x) ((x)-1) | ||
52 | #define IGA2_HOR_SYNC_END_FORMULA(x, y) ((x+y)-1) | ||
53 | |||
54 | #define IGA2_VER_TOTAL_FORMULA(x) ((x)-1) | ||
55 | #define IGA2_VER_ADDR_FORMULA(x) ((x)-1) | ||
56 | #define IGA2_VER_BLANK_START_FORMULA(x) ((x)-1) | ||
57 | #define IGA2_VER_BLANK_END_FORMULA(x, y) ((x+y)-1) | ||
58 | #define IGA2_VER_SYNC_START_FORMULA(x) ((x)-1) | ||
59 | #define IGA2_VER_SYNC_END_FORMULA(x, y) ((x+y)-1) | ||
60 | |||
61 | /**********************************************************/ | ||
62 | /* Definition IGA2 Design Method of CRTC Shadow Registers */ | ||
63 | /**********************************************************/ | ||
64 | #define IGA2_HOR_TOTAL_SHADOW_FORMULA(x) ((x/8)-5) | ||
65 | #define IGA2_HOR_BLANK_END_SHADOW_FORMULA(x, y) (((x+y)/8)-1) | ||
66 | #define IGA2_VER_TOTAL_SHADOW_FORMULA(x) ((x)-2) | ||
67 | #define IGA2_VER_ADDR_SHADOW_FORMULA(x) ((x)-1) | ||
68 | #define IGA2_VER_BLANK_START_SHADOW_FORMULA(x) ((x)-1) | ||
69 | #define IGA2_VER_BLANK_END_SHADOW_FORMULA(x, y) ((x+y)-1) | ||
70 | #define IGA2_VER_SYNC_START_SHADOW_FORMULA(x) (x) | ||
71 | #define IGA2_VER_SYNC_END_SHADOW_FORMULA(x, y) (x+y) | ||
72 | |||
73 | /* Define Register Number for IGA1 CRTC Timing */ | ||
74 | |||
75 | /* location: {CR00,0,7},{CR36,3,3} */ | ||
76 | #define IGA1_HOR_TOTAL_REG_NUM 2 | ||
77 | /* location: {CR01,0,7} */ | ||
78 | #define IGA1_HOR_ADDR_REG_NUM 1 | ||
79 | /* location: {CR02,0,7} */ | ||
80 | #define IGA1_HOR_BLANK_START_REG_NUM 1 | ||
81 | /* location: {CR03,0,4},{CR05,7,7},{CR33,5,5} */ | ||
82 | #define IGA1_HOR_BLANK_END_REG_NUM 3 | ||
83 | /* location: {CR04,0,7},{CR33,4,4} */ | ||
84 | #define IGA1_HOR_SYNC_START_REG_NUM 2 | ||
85 | /* location: {CR05,0,4} */ | ||
86 | #define IGA1_HOR_SYNC_END_REG_NUM 1 | ||
87 | /* location: {CR06,0,7},{CR07,0,0},{CR07,5,5},{CR35,0,0} */ | ||
88 | #define IGA1_VER_TOTAL_REG_NUM 4 | ||
89 | /* location: {CR12,0,7},{CR07,1,1},{CR07,6,6},{CR35,2,2} */ | ||
90 | #define IGA1_VER_ADDR_REG_NUM 4 | ||
91 | /* location: {CR15,0,7},{CR07,3,3},{CR09,5,5},{CR35,3,3} */ | ||
92 | #define IGA1_VER_BLANK_START_REG_NUM 4 | ||
93 | /* location: {CR16,0,7} */ | ||
94 | #define IGA1_VER_BLANK_END_REG_NUM 1 | ||
95 | /* location: {CR10,0,7},{CR07,2,2},{CR07,7,7},{CR35,1,1} */ | ||
96 | #define IGA1_VER_SYNC_START_REG_NUM 4 | ||
97 | /* location: {CR11,0,3} */ | ||
98 | #define IGA1_VER_SYNC_END_REG_NUM 1 | ||
99 | |||
100 | /* Define Register Number for IGA2 Shadow CRTC Timing */ | ||
101 | |||
102 | /* location: {CR6D,0,7},{CR71,3,3} */ | ||
103 | #define IGA2_SHADOW_HOR_TOTAL_REG_NUM 2 | ||
104 | /* location: {CR6E,0,7} */ | ||
105 | #define IGA2_SHADOW_HOR_BLANK_END_REG_NUM 1 | ||
106 | /* location: {CR6F,0,7},{CR71,0,2} */ | ||
107 | #define IGA2_SHADOW_VER_TOTAL_REG_NUM 2 | ||
108 | /* location: {CR70,0,7},{CR71,4,6} */ | ||
109 | #define IGA2_SHADOW_VER_ADDR_REG_NUM 2 | ||
110 | /* location: {CR72,0,7},{CR74,4,6} */ | ||
111 | #define IGA2_SHADOW_VER_BLANK_START_REG_NUM 2 | ||
112 | /* location: {CR73,0,7},{CR74,0,2} */ | ||
113 | #define IGA2_SHADOW_VER_BLANK_END_REG_NUM 2 | ||
114 | /* location: {CR75,0,7},{CR76,4,6} */ | ||
115 | #define IGA2_SHADOW_VER_SYNC_START_REG_NUM 2 | ||
116 | /* location: {CR76,0,3} */ | ||
117 | #define IGA2_SHADOW_VER_SYNC_END_REG_NUM 1 | ||
118 | |||
119 | /* Define Register Number for IGA2 CRTC Timing */ | ||
120 | |||
121 | /* location: {CR50,0,7},{CR55,0,3} */ | ||
122 | #define IGA2_HOR_TOTAL_REG_NUM 2 | ||
123 | /* location: {CR51,0,7},{CR55,4,6} */ | ||
124 | #define IGA2_HOR_ADDR_REG_NUM 2 | ||
125 | /* location: {CR52,0,7},{CR54,0,2} */ | ||
126 | #define IGA2_HOR_BLANK_START_REG_NUM 2 | ||
127 | /* location: CLE266: {CR53,0,7},{CR54,3,5} => CLE266's CR5D[6] | ||
128 | is reserved, so it may have problem to set 1600x1200 on IGA2. */ | ||
129 | /* Others: {CR53,0,7},{CR54,3,5},{CR5D,6,6} */ | ||
130 | #define IGA2_HOR_BLANK_END_REG_NUM 3 | ||
131 | /* location: {CR56,0,7},{CR54,6,7},{CR5C,7,7} */ | ||
132 | /* VT3314 and Later: {CR56,0,7},{CR54,6,7},{CR5C,7,7}, {CR5D,7,7} */ | ||
133 | #define IGA2_HOR_SYNC_START_REG_NUM 4 | ||
134 | |||
135 | /* location: {CR57,0,7},{CR5C,6,6} */ | ||
136 | #define IGA2_HOR_SYNC_END_REG_NUM 2 | ||
137 | /* location: {CR58,0,7},{CR5D,0,2} */ | ||
138 | #define IGA2_VER_TOTAL_REG_NUM 2 | ||
139 | /* location: {CR59,0,7},{CR5D,3,5} */ | ||
140 | #define IGA2_VER_ADDR_REG_NUM 2 | ||
141 | /* location: {CR5A,0,7},{CR5C,0,2} */ | ||
142 | #define IGA2_VER_BLANK_START_REG_NUM 2 | ||
143 | /* location: {CR5E,0,7},{CR5C,3,5} */ | ||
144 | #define IGA2_VER_BLANK_END_REG_NUM 2 | ||
145 | /* location: {CR5E,0,7},{CR5F,5,7} */ | ||
146 | #define IGA2_VER_SYNC_START_REG_NUM 2 | ||
147 | /* location: {CR5F,0,4} */ | ||
148 | #define IGA2_VER_SYNC_END_REG_NUM 1 | ||
149 | |||
150 | /* Define Offset and Fetch Count Register*/ | ||
151 | |||
152 | /* location: {CR13,0,7},{CR35,5,7} */ | ||
153 | #define IGA1_OFFSET_REG_NUM 2 | ||
154 | /* 8 bytes alignment. */ | ||
155 | #define IGA1_OFFSER_ALIGN_BYTE 8 | ||
156 | /* x: H resolution, y: color depth */ | ||
157 | #define IGA1_OFFSET_FORMULA(x, y) ((x*y)/IGA1_OFFSER_ALIGN_BYTE) | ||
158 | /* location: {SR1C,0,7},{SR1D,0,1} */ | ||
159 | #define IGA1_FETCH_COUNT_REG_NUM 2 | ||
160 | /* 16 bytes alignment. */ | ||
161 | #define IGA1_FETCH_COUNT_ALIGN_BYTE 16 | ||
162 | /* x: H resolution, y: color depth */ | ||
163 | #define IGA1_FETCH_COUNT_PATCH_VALUE 4 | ||
164 | #define IGA1_FETCH_COUNT_FORMULA(x, y) \ | ||
165 | (((x*y)/IGA1_FETCH_COUNT_ALIGN_BYTE) + IGA1_FETCH_COUNT_PATCH_VALUE) | ||
166 | |||
167 | /* location: {CR66,0,7},{CR67,0,1} */ | ||
168 | #define IGA2_OFFSET_REG_NUM 2 | ||
169 | #define IGA2_OFFSET_ALIGN_BYTE 8 | ||
170 | /* x: H resolution, y: color depth */ | ||
171 | #define IGA2_OFFSET_FORMULA(x, y) ((x*y)/IGA2_OFFSET_ALIGN_BYTE) | ||
172 | /* location: {CR65,0,7},{CR67,2,3} */ | ||
173 | #define IGA2_FETCH_COUNT_REG_NUM 2 | ||
174 | #define IGA2_FETCH_COUNT_ALIGN_BYTE 16 | ||
175 | #define IGA2_FETCH_COUNT_PATCH_VALUE 0 | ||
176 | #define IGA2_FETCH_COUNT_FORMULA(x, y) \ | ||
177 | (((x*y)/IGA2_FETCH_COUNT_ALIGN_BYTE) + IGA2_FETCH_COUNT_PATCH_VALUE) | ||
178 | |||
179 | /* Staring Address*/ | ||
180 | |||
181 | /* location: {CR0C,0,7},{CR0D,0,7},{CR34,0,7},{CR48,0,1} */ | ||
182 | #define IGA1_STARTING_ADDR_REG_NUM 4 | ||
183 | /* location: {CR62,1,7},{CR63,0,7},{CR64,0,7} */ | ||
184 | #define IGA2_STARTING_ADDR_REG_NUM 3 | ||
185 | |||
186 | /* Define Display OFFSET*/ | ||
187 | /* These value are by HW suggested value*/ | ||
188 | /* location: {SR17,0,7} */ | ||
189 | #define K800_IGA1_FIFO_MAX_DEPTH 384 | ||
190 | /* location: {SR16,0,5},{SR16,7,7} */ | ||
191 | #define K800_IGA1_FIFO_THRESHOLD 328 | ||
192 | /* location: {SR18,0,5},{SR18,7,7} */ | ||
193 | #define K800_IGA1_FIFO_HIGH_THRESHOLD 296 | ||
194 | /* location: {SR22,0,4}. (128/4) =64, K800 must be set zero, */ | ||
195 | /* because HW only 5 bits */ | ||
196 | #define K800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 0 | ||
197 | |||
198 | /* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */ | ||
199 | #define K800_IGA2_FIFO_MAX_DEPTH 384 | ||
200 | /* location: {CR68,0,3},{CR95,4,6} */ | ||
201 | #define K800_IGA2_FIFO_THRESHOLD 328 | ||
202 | /* location: {CR92,0,3},{CR95,0,2} */ | ||
203 | #define K800_IGA2_FIFO_HIGH_THRESHOLD 296 | ||
204 | /* location: {CR94,0,6} */ | ||
205 | #define K800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128 | ||
206 | |||
207 | /* location: {SR17,0,7} */ | ||
208 | #define P880_IGA1_FIFO_MAX_DEPTH 192 | ||
209 | /* location: {SR16,0,5},{SR16,7,7} */ | ||
210 | #define P880_IGA1_FIFO_THRESHOLD 128 | ||
211 | /* location: {SR18,0,5},{SR18,7,7} */ | ||
212 | #define P880_IGA1_FIFO_HIGH_THRESHOLD 64 | ||
213 | /* location: {SR22,0,4}. (128/4) =64, K800 must be set zero, */ | ||
214 | /* because HW only 5 bits */ | ||
215 | #define P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 0 | ||
216 | |||
217 | /* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */ | ||
218 | #define P880_IGA2_FIFO_MAX_DEPTH 96 | ||
219 | /* location: {CR68,0,3},{CR95,4,6} */ | ||
220 | #define P880_IGA2_FIFO_THRESHOLD 64 | ||
221 | /* location: {CR92,0,3},{CR95,0,2} */ | ||
222 | #define P880_IGA2_FIFO_HIGH_THRESHOLD 32 | ||
223 | /* location: {CR94,0,6} */ | ||
224 | #define P880_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128 | ||
225 | |||
226 | /* VT3314 chipset*/ | ||
227 | |||
228 | /* location: {SR17,0,7} */ | ||
229 | #define CN700_IGA1_FIFO_MAX_DEPTH 96 | ||
230 | /* location: {SR16,0,5},{SR16,7,7} */ | ||
231 | #define CN700_IGA1_FIFO_THRESHOLD 80 | ||
232 | /* location: {SR18,0,5},{SR18,7,7} */ | ||
233 | #define CN700_IGA1_FIFO_HIGH_THRESHOLD 64 | ||
234 | /* location: {SR22,0,4}. (128/4) =64, P800 must be set zero, | ||
235 | because HW only 5 bits */ | ||
236 | #define CN700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 0 | ||
237 | /* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */ | ||
238 | #define CN700_IGA2_FIFO_MAX_DEPTH 96 | ||
239 | /* location: {CR68,0,3},{CR95,4,6} */ | ||
240 | #define CN700_IGA2_FIFO_THRESHOLD 80 | ||
241 | /* location: {CR92,0,3},{CR95,0,2} */ | ||
242 | #define CN700_IGA2_FIFO_HIGH_THRESHOLD 32 | ||
243 | /* location: {CR94,0,6} */ | ||
244 | #define CN700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128 | ||
245 | |||
246 | /* For VT3324, these values are suggested by HW */ | ||
247 | /* location: {SR17,0,7} */ | ||
248 | #define CX700_IGA1_FIFO_MAX_DEPTH 192 | ||
249 | /* location: {SR16,0,5},{SR16,7,7} */ | ||
250 | #define CX700_IGA1_FIFO_THRESHOLD 128 | ||
251 | /* location: {SR18,0,5},{SR18,7,7} */ | ||
252 | #define CX700_IGA1_FIFO_HIGH_THRESHOLD 128 | ||
253 | /* location: {SR22,0,4} */ | ||
254 | #define CX700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 124 | ||
255 | |||
256 | /* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */ | ||
257 | #define CX700_IGA2_FIFO_MAX_DEPTH 96 | ||
258 | /* location: {CR68,0,3},{CR95,4,6} */ | ||
259 | #define CX700_IGA2_FIFO_THRESHOLD 64 | ||
260 | /* location: {CR92,0,3},{CR95,0,2} */ | ||
261 | #define CX700_IGA2_FIFO_HIGH_THRESHOLD 32 | ||
262 | /* location: {CR94,0,6} */ | ||
263 | #define CX700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128 | ||
264 | |||
265 | /* VT3336 chipset*/ | ||
266 | /* location: {SR17,0,7} */ | ||
267 | #define K8M890_IGA1_FIFO_MAX_DEPTH 360 | ||
268 | /* location: {SR16,0,5},{SR16,7,7} */ | ||
269 | #define K8M890_IGA1_FIFO_THRESHOLD 328 | ||
270 | /* location: {SR18,0,5},{SR18,7,7} */ | ||
271 | #define K8M890_IGA1_FIFO_HIGH_THRESHOLD 296 | ||
272 | /* location: {SR22,0,4}. */ | ||
273 | #define K8M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 124 | ||
274 | |||
275 | /* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */ | ||
276 | #define K8M890_IGA2_FIFO_MAX_DEPTH 360 | ||
277 | /* location: {CR68,0,3},{CR95,4,6} */ | ||
278 | #define K8M890_IGA2_FIFO_THRESHOLD 328 | ||
279 | /* location: {CR92,0,3},{CR95,0,2} */ | ||
280 | #define K8M890_IGA2_FIFO_HIGH_THRESHOLD 296 | ||
281 | /* location: {CR94,0,6} */ | ||
282 | #define K8M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 124 | ||
283 | |||
284 | /* VT3327 chipset*/ | ||
285 | /* location: {SR17,0,7} */ | ||
286 | #define P4M890_IGA1_FIFO_MAX_DEPTH 96 | ||
287 | /* location: {SR16,0,5},{SR16,7,7} */ | ||
288 | #define P4M890_IGA1_FIFO_THRESHOLD 76 | ||
289 | /* location: {SR18,0,5},{SR18,7,7} */ | ||
290 | #define P4M890_IGA1_FIFO_HIGH_THRESHOLD 64 | ||
291 | /* location: {SR22,0,4}. (32/4) =8 */ | ||
292 | #define P4M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 32 | ||
293 | /* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */ | ||
294 | #define P4M890_IGA2_FIFO_MAX_DEPTH 96 | ||
295 | /* location: {CR68,0,3},{CR95,4,6} */ | ||
296 | #define P4M890_IGA2_FIFO_THRESHOLD 76 | ||
297 | /* location: {CR92,0,3},{CR95,0,2} */ | ||
298 | #define P4M890_IGA2_FIFO_HIGH_THRESHOLD 64 | ||
299 | /* location: {CR94,0,6} */ | ||
300 | #define P4M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 32 | ||
301 | |||
302 | /* VT3364 chipset*/ | ||
303 | /* location: {SR17,0,7} */ | ||
304 | #define P4M900_IGA1_FIFO_MAX_DEPTH 96 | ||
305 | /* location: {SR16,0,5},{SR16,7,7} */ | ||
306 | #define P4M900_IGA1_FIFO_THRESHOLD 76 | ||
307 | /* location: {SR18,0,5},{SR18,7,7} */ | ||
308 | #define P4M900_IGA1_FIFO_HIGH_THRESHOLD 76 | ||
309 | /* location: {SR22,0,4}. */ | ||
310 | #define P4M900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 32 | ||
311 | /* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */ | ||
312 | #define P4M900_IGA2_FIFO_MAX_DEPTH 96 | ||
313 | /* location: {CR68,0,3},{CR95,4,6} */ | ||
314 | #define P4M900_IGA2_FIFO_THRESHOLD 76 | ||
315 | /* location: {CR92,0,3},{CR95,0,2} */ | ||
316 | #define P4M900_IGA2_FIFO_HIGH_THRESHOLD 76 | ||
317 | /* location: {CR94,0,6} */ | ||
318 | #define P4M900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 32 | ||
319 | |||
320 | /* For VT3353, these values are suggested by HW */ | ||
321 | /* location: {SR17,0,7} */ | ||
322 | #define VX800_IGA1_FIFO_MAX_DEPTH 192 | ||
323 | /* location: {SR16,0,5},{SR16,7,7} */ | ||
324 | #define VX800_IGA1_FIFO_THRESHOLD 152 | ||
325 | /* location: {SR18,0,5},{SR18,7,7} */ | ||
326 | #define VX800_IGA1_FIFO_HIGH_THRESHOLD 152 | ||
327 | /* location: {SR22,0,4} */ | ||
328 | #define VX800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 64 | ||
329 | /* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */ | ||
330 | #define VX800_IGA2_FIFO_MAX_DEPTH 96 | ||
331 | /* location: {CR68,0,3},{CR95,4,6} */ | ||
332 | #define VX800_IGA2_FIFO_THRESHOLD 64 | ||
333 | /* location: {CR92,0,3},{CR95,0,2} */ | ||
334 | #define VX800_IGA2_FIFO_HIGH_THRESHOLD 32 | ||
335 | /* location: {CR94,0,6} */ | ||
336 | #define VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128 | ||
337 | |||
338 | #define IGA1_FIFO_DEPTH_SELECT_REG_NUM 1 | ||
339 | #define IGA1_FIFO_THRESHOLD_REG_NUM 2 | ||
340 | #define IGA1_FIFO_HIGH_THRESHOLD_REG_NUM 2 | ||
341 | #define IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM 1 | ||
342 | |||
343 | #define IGA2_FIFO_DEPTH_SELECT_REG_NUM 3 | ||
344 | #define IGA2_FIFO_THRESHOLD_REG_NUM 2 | ||
345 | #define IGA2_FIFO_HIGH_THRESHOLD_REG_NUM 2 | ||
346 | #define IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM 1 | ||
347 | |||
348 | #define IGA1_FIFO_DEPTH_SELECT_FORMULA(x) ((x/2)-1) | ||
349 | #define IGA1_FIFO_THRESHOLD_FORMULA(x) (x/4) | ||
350 | #define IGA1_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA(x) (x/4) | ||
351 | #define IGA1_FIFO_HIGH_THRESHOLD_FORMULA(x) (x/4) | ||
352 | #define IGA2_FIFO_DEPTH_SELECT_FORMULA(x) (((x/2)/4)-1) | ||
353 | #define IGA2_FIFO_THRESHOLD_FORMULA(x) (x/4) | ||
354 | #define IGA2_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA(x) (x/4) | ||
355 | #define IGA2_FIFO_HIGH_THRESHOLD_FORMULA(x) (x/4) | ||
356 | |||
357 | /************************************************************************/ | ||
358 | /* LCD Timing */ | ||
359 | /************************************************************************/ | ||
360 | |||
361 | /* 500 ms = 500000 us */ | ||
362 | #define LCD_POWER_SEQ_TD0 500000 | ||
363 | /* 50 ms = 50000 us */ | ||
364 | #define LCD_POWER_SEQ_TD1 50000 | ||
365 | /* 0 us */ | ||
366 | #define LCD_POWER_SEQ_TD2 0 | ||
367 | /* 210 ms = 210000 us */ | ||
368 | #define LCD_POWER_SEQ_TD3 210000 | ||
369 | /* 2^10 * (1/14.31818M) = 71.475 us (K400.revA) */ | ||
370 | #define CLE266_POWER_SEQ_UNIT 71 | ||
371 | /* 2^11 * (1/14.31818M) = 142.95 us (K400.revB) */ | ||
372 | #define K800_POWER_SEQ_UNIT 142 | ||
373 | /* 2^13 * (1/14.31818M) = 572.1 us */ | ||
374 | #define P880_POWER_SEQ_UNIT 572 | ||
375 | |||
376 | #define CLE266_POWER_SEQ_FORMULA(x) ((x)/CLE266_POWER_SEQ_UNIT) | ||
377 | #define K800_POWER_SEQ_FORMULA(x) ((x)/K800_POWER_SEQ_UNIT) | ||
378 | #define P880_POWER_SEQ_FORMULA(x) ((x)/P880_POWER_SEQ_UNIT) | ||
379 | |||
380 | /* location: {CR8B,0,7},{CR8F,0,3} */ | ||
381 | #define LCD_POWER_SEQ_TD0_REG_NUM 2 | ||
382 | /* location: {CR8C,0,7},{CR8F,4,7} */ | ||
383 | #define LCD_POWER_SEQ_TD1_REG_NUM 2 | ||
384 | /* location: {CR8D,0,7},{CR90,0,3} */ | ||
385 | #define LCD_POWER_SEQ_TD2_REG_NUM 2 | ||
386 | /* location: {CR8E,0,7},{CR90,4,7} */ | ||
387 | #define LCD_POWER_SEQ_TD3_REG_NUM 2 | ||
388 | |||
389 | /* LCD Scaling factor*/ | ||
390 | /* x: indicate setting horizontal size*/ | ||
391 | /* y: indicate panel horizontal size*/ | ||
392 | |||
393 | /* Horizontal scaling factor 10 bits (2^10) */ | ||
394 | #define CLE266_LCD_HOR_SCF_FORMULA(x, y) (((x-1)*1024)/(y-1)) | ||
395 | /* Vertical scaling factor 10 bits (2^10) */ | ||
396 | #define CLE266_LCD_VER_SCF_FORMULA(x, y) (((x-1)*1024)/(y-1)) | ||
397 | /* Horizontal scaling factor 10 bits (2^12) */ | ||
398 | #define K800_LCD_HOR_SCF_FORMULA(x, y) (((x-1)*4096)/(y-1)) | ||
399 | /* Vertical scaling factor 10 bits (2^11) */ | ||
400 | #define K800_LCD_VER_SCF_FORMULA(x, y) (((x-1)*2048)/(y-1)) | ||
401 | |||
402 | /* location: {CR9F,0,1},{CR77,0,7},{CR79,4,5} */ | ||
403 | #define LCD_HOR_SCALING_FACTOR_REG_NUM 3 | ||
404 | /* location: {CR79,3,3},{CR78,0,7},{CR79,6,7} */ | ||
405 | #define LCD_VER_SCALING_FACTOR_REG_NUM 3 | ||
406 | /* location: {CR77,0,7},{CR79,4,5} */ | ||
407 | #define LCD_HOR_SCALING_FACTOR_REG_NUM_CLE 2 | ||
408 | /* location: {CR78,0,7},{CR79,6,7} */ | ||
409 | #define LCD_VER_SCALING_FACTOR_REG_NUM_CLE 2 | ||
410 | |||
411 | /************************************************ | ||
412 | ***** Define IGA1 Display Timing ***** | ||
413 | ************************************************/ | ||
414 | struct io_register { | ||
415 | u8 io_addr; | ||
416 | u8 start_bit; | ||
417 | u8 end_bit; | ||
418 | }; | ||
419 | |||
420 | /* IGA1 Horizontal Total */ | ||
421 | struct iga1_hor_total { | ||
422 | int reg_num; | ||
423 | struct io_register reg[IGA1_HOR_TOTAL_REG_NUM]; | ||
424 | }; | ||
425 | |||
426 | /* IGA1 Horizontal Addressable Video */ | ||
427 | struct iga1_hor_addr { | ||
428 | int reg_num; | ||
429 | struct io_register reg[IGA1_HOR_ADDR_REG_NUM]; | ||
430 | }; | ||
431 | |||
432 | /* IGA1 Horizontal Blank Start */ | ||
433 | struct iga1_hor_blank_start { | ||
434 | int reg_num; | ||
435 | struct io_register reg[IGA1_HOR_BLANK_START_REG_NUM]; | ||
436 | }; | ||
437 | |||
438 | /* IGA1 Horizontal Blank End */ | ||
439 | struct iga1_hor_blank_end { | ||
440 | int reg_num; | ||
441 | struct io_register reg[IGA1_HOR_BLANK_END_REG_NUM]; | ||
442 | }; | ||
443 | |||
444 | /* IGA1 Horizontal Sync Start */ | ||
445 | struct iga1_hor_sync_start { | ||
446 | int reg_num; | ||
447 | struct io_register reg[IGA1_HOR_SYNC_START_REG_NUM]; | ||
448 | }; | ||
449 | |||
450 | /* IGA1 Horizontal Sync End */ | ||
451 | struct iga1_hor_sync_end { | ||
452 | int reg_num; | ||
453 | struct io_register reg[IGA1_HOR_SYNC_END_REG_NUM]; | ||
454 | }; | ||
455 | |||
456 | /* IGA1 Vertical Total */ | ||
457 | struct iga1_ver_total { | ||
458 | int reg_num; | ||
459 | struct io_register reg[IGA1_VER_TOTAL_REG_NUM]; | ||
460 | }; | ||
461 | |||
462 | /* IGA1 Vertical Addressable Video */ | ||
463 | struct iga1_ver_addr { | ||
464 | int reg_num; | ||
465 | struct io_register reg[IGA1_VER_ADDR_REG_NUM]; | ||
466 | }; | ||
467 | |||
468 | /* IGA1 Vertical Blank Start */ | ||
469 | struct iga1_ver_blank_start { | ||
470 | int reg_num; | ||
471 | struct io_register reg[IGA1_VER_BLANK_START_REG_NUM]; | ||
472 | }; | ||
473 | |||
474 | /* IGA1 Vertical Blank End */ | ||
475 | struct iga1_ver_blank_end { | ||
476 | int reg_num; | ||
477 | struct io_register reg[IGA1_VER_BLANK_END_REG_NUM]; | ||
478 | }; | ||
479 | |||
480 | /* IGA1 Vertical Sync Start */ | ||
481 | struct iga1_ver_sync_start { | ||
482 | int reg_num; | ||
483 | struct io_register reg[IGA1_VER_SYNC_START_REG_NUM]; | ||
484 | }; | ||
485 | |||
486 | /* IGA1 Vertical Sync End */ | ||
487 | struct iga1_ver_sync_end { | ||
488 | int reg_num; | ||
489 | struct io_register reg[IGA1_VER_SYNC_END_REG_NUM]; | ||
490 | }; | ||
491 | |||
492 | /***************************************************** | ||
493 | ** Define IGA2 Shadow Display Timing **** | ||
494 | *****************************************************/ | ||
495 | |||
496 | /* IGA2 Shadow Horizontal Total */ | ||
497 | struct iga2_shadow_hor_total { | ||
498 | int reg_num; | ||
499 | struct io_register reg[IGA2_SHADOW_HOR_TOTAL_REG_NUM]; | ||
500 | }; | ||
501 | |||
502 | /* IGA2 Shadow Horizontal Blank End */ | ||
503 | struct iga2_shadow_hor_blank_end { | ||
504 | int reg_num; | ||
505 | struct io_register reg[IGA2_SHADOW_HOR_BLANK_END_REG_NUM]; | ||
506 | }; | ||
507 | |||
508 | /* IGA2 Shadow Vertical Total */ | ||
509 | struct iga2_shadow_ver_total { | ||
510 | int reg_num; | ||
511 | struct io_register reg[IGA2_SHADOW_VER_TOTAL_REG_NUM]; | ||
512 | }; | ||
513 | |||
514 | /* IGA2 Shadow Vertical Addressable Video */ | ||
515 | struct iga2_shadow_ver_addr { | ||
516 | int reg_num; | ||
517 | struct io_register reg[IGA2_SHADOW_VER_ADDR_REG_NUM]; | ||
518 | }; | ||
519 | |||
520 | /* IGA2 Shadow Vertical Blank Start */ | ||
521 | struct iga2_shadow_ver_blank_start { | ||
522 | int reg_num; | ||
523 | struct io_register reg[IGA2_SHADOW_VER_BLANK_START_REG_NUM]; | ||
524 | }; | ||
525 | |||
526 | /* IGA2 Shadow Vertical Blank End */ | ||
527 | struct iga2_shadow_ver_blank_end { | ||
528 | int reg_num; | ||
529 | struct io_register reg[IGA2_SHADOW_VER_BLANK_END_REG_NUM]; | ||
530 | }; | ||
531 | |||
532 | /* IGA2 Shadow Vertical Sync Start */ | ||
533 | struct iga2_shadow_ver_sync_start { | ||
534 | int reg_num; | ||
535 | struct io_register reg[IGA2_SHADOW_VER_SYNC_START_REG_NUM]; | ||
536 | }; | ||
537 | |||
538 | /* IGA2 Shadow Vertical Sync End */ | ||
539 | struct iga2_shadow_ver_sync_end { | ||
540 | int reg_num; | ||
541 | struct io_register reg[IGA2_SHADOW_VER_SYNC_END_REG_NUM]; | ||
542 | }; | ||
543 | |||
544 | /***************************************************** | ||
545 | ** Define IGA2 Display Timing **** | ||
546 | ******************************************************/ | ||
547 | |||
548 | /* IGA2 Horizontal Total */ | ||
549 | struct iga2_hor_total { | ||
550 | int reg_num; | ||
551 | struct io_register reg[IGA2_HOR_TOTAL_REG_NUM]; | ||
552 | }; | ||
553 | |||
554 | /* IGA2 Horizontal Addressable Video */ | ||
555 | struct iga2_hor_addr { | ||
556 | int reg_num; | ||
557 | struct io_register reg[IGA2_HOR_ADDR_REG_NUM]; | ||
558 | }; | ||
559 | |||
560 | /* IGA2 Horizontal Blank Start */ | ||
561 | struct iga2_hor_blank_start { | ||
562 | int reg_num; | ||
563 | struct io_register reg[IGA2_HOR_BLANK_START_REG_NUM]; | ||
564 | }; | ||
565 | |||
566 | /* IGA2 Horizontal Blank End */ | ||
567 | struct iga2_hor_blank_end { | ||
568 | int reg_num; | ||
569 | struct io_register reg[IGA2_HOR_BLANK_END_REG_NUM]; | ||
570 | }; | ||
571 | |||
572 | /* IGA2 Horizontal Sync Start */ | ||
573 | struct iga2_hor_sync_start { | ||
574 | int reg_num; | ||
575 | struct io_register reg[IGA2_HOR_SYNC_START_REG_NUM]; | ||
576 | }; | ||
577 | |||
578 | /* IGA2 Horizontal Sync End */ | ||
579 | struct iga2_hor_sync_end { | ||
580 | int reg_num; | ||
581 | struct io_register reg[IGA2_HOR_SYNC_END_REG_NUM]; | ||
582 | }; | ||
583 | |||
584 | /* IGA2 Vertical Total */ | ||
585 | struct iga2_ver_total { | ||
586 | int reg_num; | ||
587 | struct io_register reg[IGA2_VER_TOTAL_REG_NUM]; | ||
588 | }; | ||
589 | |||
590 | /* IGA2 Vertical Addressable Video */ | ||
591 | struct iga2_ver_addr { | ||
592 | int reg_num; | ||
593 | struct io_register reg[IGA2_VER_ADDR_REG_NUM]; | ||
594 | }; | ||
595 | |||
596 | /* IGA2 Vertical Blank Start */ | ||
597 | struct iga2_ver_blank_start { | ||
598 | int reg_num; | ||
599 | struct io_register reg[IGA2_VER_BLANK_START_REG_NUM]; | ||
600 | }; | ||
601 | |||
602 | /* IGA2 Vertical Blank End */ | ||
603 | struct iga2_ver_blank_end { | ||
604 | int reg_num; | ||
605 | struct io_register reg[IGA2_VER_BLANK_END_REG_NUM]; | ||
606 | }; | ||
607 | |||
608 | /* IGA2 Vertical Sync Start */ | ||
609 | struct iga2_ver_sync_start { | ||
610 | int reg_num; | ||
611 | struct io_register reg[IGA2_VER_SYNC_START_REG_NUM]; | ||
612 | }; | ||
613 | |||
614 | /* IGA2 Vertical Sync End */ | ||
615 | struct iga2_ver_sync_end { | ||
616 | int reg_num; | ||
617 | struct io_register reg[IGA2_VER_SYNC_END_REG_NUM]; | ||
618 | }; | ||
619 | |||
620 | /* IGA1 Offset Register */ | ||
621 | struct iga1_offset { | ||
622 | int reg_num; | ||
623 | struct io_register reg[IGA1_OFFSET_REG_NUM]; | ||
624 | }; | ||
625 | |||
626 | /* IGA2 Offset Register */ | ||
627 | struct iga2_offset { | ||
628 | int reg_num; | ||
629 | struct io_register reg[IGA2_OFFSET_REG_NUM]; | ||
630 | }; | ||
631 | |||
632 | struct offset { | ||
633 | struct iga1_offset iga1_offset_reg; | ||
634 | struct iga2_offset iga2_offset_reg; | ||
635 | }; | ||
636 | |||
637 | /* IGA1 Fetch Count Register */ | ||
638 | struct iga1_fetch_count { | ||
639 | int reg_num; | ||
640 | struct io_register reg[IGA1_FETCH_COUNT_REG_NUM]; | ||
641 | }; | ||
642 | |||
643 | /* IGA2 Fetch Count Register */ | ||
644 | struct iga2_fetch_count { | ||
645 | int reg_num; | ||
646 | struct io_register reg[IGA2_FETCH_COUNT_REG_NUM]; | ||
647 | }; | ||
648 | |||
649 | struct fetch_count { | ||
650 | struct iga1_fetch_count iga1_fetch_count_reg; | ||
651 | struct iga2_fetch_count iga2_fetch_count_reg; | ||
652 | }; | ||
653 | |||
654 | /* Starting Address Register */ | ||
655 | struct iga1_starting_addr { | ||
656 | int reg_num; | ||
657 | struct io_register reg[IGA1_STARTING_ADDR_REG_NUM]; | ||
658 | }; | ||
659 | |||
660 | struct iga2_starting_addr { | ||
661 | int reg_num; | ||
662 | struct io_register reg[IGA2_STARTING_ADDR_REG_NUM]; | ||
663 | }; | ||
664 | |||
665 | struct starting_addr { | ||
666 | struct iga1_starting_addr iga1_starting_addr_reg; | ||
667 | struct iga2_starting_addr iga2_starting_addr_reg; | ||
668 | }; | ||
669 | |||
670 | /* LCD Power Sequence Timer */ | ||
671 | struct lcd_pwd_seq_td0 { | ||
672 | int reg_num; | ||
673 | struct io_register reg[LCD_POWER_SEQ_TD0_REG_NUM]; | ||
674 | }; | ||
675 | |||
676 | struct lcd_pwd_seq_td1 { | ||
677 | int reg_num; | ||
678 | struct io_register reg[LCD_POWER_SEQ_TD1_REG_NUM]; | ||
679 | }; | ||
680 | |||
681 | struct lcd_pwd_seq_td2 { | ||
682 | int reg_num; | ||
683 | struct io_register reg[LCD_POWER_SEQ_TD2_REG_NUM]; | ||
684 | }; | ||
685 | |||
686 | struct lcd_pwd_seq_td3 { | ||
687 | int reg_num; | ||
688 | struct io_register reg[LCD_POWER_SEQ_TD3_REG_NUM]; | ||
689 | }; | ||
690 | |||
691 | struct _lcd_pwd_seq_timer { | ||
692 | struct lcd_pwd_seq_td0 td0; | ||
693 | struct lcd_pwd_seq_td1 td1; | ||
694 | struct lcd_pwd_seq_td2 td2; | ||
695 | struct lcd_pwd_seq_td3 td3; | ||
696 | }; | ||
697 | |||
698 | /* LCD Scaling Factor */ | ||
699 | struct _lcd_hor_scaling_factor { | ||
700 | int reg_num; | ||
701 | struct io_register reg[LCD_HOR_SCALING_FACTOR_REG_NUM]; | ||
702 | }; | ||
703 | |||
704 | struct _lcd_ver_scaling_factor { | ||
705 | int reg_num; | ||
706 | struct io_register reg[LCD_VER_SCALING_FACTOR_REG_NUM]; | ||
707 | }; | ||
708 | |||
709 | struct _lcd_scaling_factor { | ||
710 | struct _lcd_hor_scaling_factor lcd_hor_scaling_factor; | ||
711 | struct _lcd_ver_scaling_factor lcd_ver_scaling_factor; | ||
712 | }; | ||
713 | |||
714 | struct pll_map { | ||
715 | u32 clk; | ||
716 | u32 cle266_pll; | ||
717 | u32 k800_pll; | ||
718 | u32 cx700_pll; | ||
719 | }; | ||
720 | |||
721 | struct rgbLUT { | ||
722 | u8 red; | ||
723 | u8 green; | ||
724 | u8 blue; | ||
725 | }; | ||
726 | |||
727 | struct lcd_pwd_seq_timer { | ||
728 | u16 td0; | ||
729 | u16 td1; | ||
730 | u16 td2; | ||
731 | u16 td3; | ||
732 | }; | ||
733 | |||
734 | /* Display FIFO Relation Registers*/ | ||
735 | struct iga1_fifo_depth_select { | ||
736 | int reg_num; | ||
737 | struct io_register reg[IGA1_FIFO_DEPTH_SELECT_REG_NUM]; | ||
738 | }; | ||
739 | |||
740 | struct iga1_fifo_threshold_select { | ||
741 | int reg_num; | ||
742 | struct io_register reg[IGA1_FIFO_THRESHOLD_REG_NUM]; | ||
743 | }; | ||
744 | |||
745 | struct iga1_fifo_high_threshold_select { | ||
746 | int reg_num; | ||
747 | struct io_register reg[IGA1_FIFO_HIGH_THRESHOLD_REG_NUM]; | ||
748 | }; | ||
749 | |||
750 | struct iga1_display_queue_expire_num { | ||
751 | int reg_num; | ||
752 | struct io_register reg[IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM]; | ||
753 | }; | ||
754 | |||
755 | struct iga2_fifo_depth_select { | ||
756 | int reg_num; | ||
757 | struct io_register reg[IGA2_FIFO_DEPTH_SELECT_REG_NUM]; | ||
758 | }; | ||
759 | |||
760 | struct iga2_fifo_threshold_select { | ||
761 | int reg_num; | ||
762 | struct io_register reg[IGA2_FIFO_THRESHOLD_REG_NUM]; | ||
763 | }; | ||
764 | |||
765 | struct iga2_fifo_high_threshold_select { | ||
766 | int reg_num; | ||
767 | struct io_register reg[IGA2_FIFO_HIGH_THRESHOLD_REG_NUM]; | ||
768 | }; | ||
769 | |||
770 | struct iga2_display_queue_expire_num { | ||
771 | int reg_num; | ||
772 | struct io_register reg[IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM]; | ||
773 | }; | ||
774 | |||
775 | struct fifo_depth_select { | ||
776 | struct iga1_fifo_depth_select iga1_fifo_depth_select_reg; | ||
777 | struct iga2_fifo_depth_select iga2_fifo_depth_select_reg; | ||
778 | }; | ||
779 | |||
780 | struct fifo_threshold_select { | ||
781 | struct iga1_fifo_threshold_select iga1_fifo_threshold_select_reg; | ||
782 | struct iga2_fifo_threshold_select iga2_fifo_threshold_select_reg; | ||
783 | }; | ||
784 | |||
785 | struct fifo_high_threshold_select { | ||
786 | struct iga1_fifo_high_threshold_select | ||
787 | iga1_fifo_high_threshold_select_reg; | ||
788 | struct iga2_fifo_high_threshold_select | ||
789 | iga2_fifo_high_threshold_select_reg; | ||
790 | }; | ||
791 | |||
792 | struct display_queue_expire_num { | ||
793 | struct iga1_display_queue_expire_num | ||
794 | iga1_display_queue_expire_num_reg; | ||
795 | struct iga2_display_queue_expire_num | ||
796 | iga2_display_queue_expire_num_reg; | ||
797 | }; | ||
798 | |||
799 | struct iga1_crtc_timing { | ||
800 | struct iga1_hor_total hor_total; | ||
801 | struct iga1_hor_addr hor_addr; | ||
802 | struct iga1_hor_blank_start hor_blank_start; | ||
803 | struct iga1_hor_blank_end hor_blank_end; | ||
804 | struct iga1_hor_sync_start hor_sync_start; | ||
805 | struct iga1_hor_sync_end hor_sync_end; | ||
806 | struct iga1_ver_total ver_total; | ||
807 | struct iga1_ver_addr ver_addr; | ||
808 | struct iga1_ver_blank_start ver_blank_start; | ||
809 | struct iga1_ver_blank_end ver_blank_end; | ||
810 | struct iga1_ver_sync_start ver_sync_start; | ||
811 | struct iga1_ver_sync_end ver_sync_end; | ||
812 | }; | ||
813 | |||
814 | struct iga2_shadow_crtc_timing { | ||
815 | struct iga2_shadow_hor_total hor_total_shadow; | ||
816 | struct iga2_shadow_hor_blank_end hor_blank_end_shadow; | ||
817 | struct iga2_shadow_ver_total ver_total_shadow; | ||
818 | struct iga2_shadow_ver_addr ver_addr_shadow; | ||
819 | struct iga2_shadow_ver_blank_start ver_blank_start_shadow; | ||
820 | struct iga2_shadow_ver_blank_end ver_blank_end_shadow; | ||
821 | struct iga2_shadow_ver_sync_start ver_sync_start_shadow; | ||
822 | struct iga2_shadow_ver_sync_end ver_sync_end_shadow; | ||
823 | }; | ||
824 | |||
825 | struct iga2_crtc_timing { | ||
826 | struct iga2_hor_total hor_total; | ||
827 | struct iga2_hor_addr hor_addr; | ||
828 | struct iga2_hor_blank_start hor_blank_start; | ||
829 | struct iga2_hor_blank_end hor_blank_end; | ||
830 | struct iga2_hor_sync_start hor_sync_start; | ||
831 | struct iga2_hor_sync_end hor_sync_end; | ||
832 | struct iga2_ver_total ver_total; | ||
833 | struct iga2_ver_addr ver_addr; | ||
834 | struct iga2_ver_blank_start ver_blank_start; | ||
835 | struct iga2_ver_blank_end ver_blank_end; | ||
836 | struct iga2_ver_sync_start ver_sync_start; | ||
837 | struct iga2_ver_sync_end ver_sync_end; | ||
838 | }; | ||
839 | |||
840 | /* device ID */ | ||
841 | #define CLE266 0x3123 | ||
842 | #define KM400 0x3205 | ||
843 | #define CN400_FUNCTION2 0x2259 | ||
844 | #define CN400_FUNCTION3 0x3259 | ||
845 | /* support VT3314 chipset */ | ||
846 | #define CN700_FUNCTION2 0x2314 | ||
847 | #define CN700_FUNCTION3 0x3208 | ||
848 | /* VT3324 chipset */ | ||
849 | #define CX700_FUNCTION2 0x2324 | ||
850 | #define CX700_FUNCTION3 0x3324 | ||
851 | /* VT3204 chipset*/ | ||
852 | #define KM800_FUNCTION3 0x3204 | ||
853 | /* VT3336 chipset*/ | ||
854 | #define KM890_FUNCTION3 0x3336 | ||
855 | /* VT3327 chipset*/ | ||
856 | #define P4M890_FUNCTION3 0x3327 | ||
857 | /* VT3293 chipset*/ | ||
858 | #define CN750_FUNCTION3 0x3208 | ||
859 | /* VT3364 chipset*/ | ||
860 | #define P4M900_FUNCTION3 0x3364 | ||
861 | /* VT3353 chipset*/ | ||
862 | #define VX800_FUNCTION3 0x3353 | ||
863 | |||
864 | #define NUM_TOTAL_PLL_TABLE ARRAY_SIZE(pll_value) | ||
865 | |||
866 | struct IODATA { | ||
867 | u8 Index; | ||
868 | u8 Mask; | ||
869 | u8 Data; | ||
870 | }; | ||
871 | |||
872 | struct pci_device_id_info { | ||
873 | u32 vendor; | ||
874 | u32 device; | ||
875 | u32 chip_index; | ||
876 | }; | ||
877 | |||
878 | extern unsigned int viafb_second_virtual_xres; | ||
879 | extern unsigned int viafb_second_offset; | ||
880 | extern int viafb_second_size; | ||
881 | extern int viafb_SAMM_ON; | ||
882 | extern int viafb_dual_fb; | ||
883 | extern int viafb_LCD2_ON; | ||
884 | extern int viafb_LCD_ON; | ||
885 | extern int viafb_DVI_ON; | ||
886 | extern int viafb_accel; | ||
887 | extern int viafb_hotplug; | ||
888 | |||
889 | void viafb_write_reg_mask(u8 index, int io_port, u8 data, u8 mask); | ||
890 | void viafb_set_output_path(int device, int set_iga, | ||
891 | int output_interface); | ||
892 | void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, | ||
893 | int mode_index, int bpp_byte, int set_iga); | ||
894 | |||
895 | void viafb_set_vclock(u32 CLK, int set_iga); | ||
896 | void viafb_load_reg(int timing_value, int viafb_load_reg_num, | ||
897 | struct io_register *reg, | ||
898 | int io_type); | ||
899 | void viafb_crt_disable(void); | ||
900 | void viafb_crt_enable(void); | ||
901 | void init_ad9389(void); | ||
902 | /* Access I/O Function */ | ||
903 | void viafb_write_reg(u8 index, u16 io_port, u8 data); | ||
904 | u8 viafb_read_reg(int io_port, u8 index); | ||
905 | void viafb_lock_crt(void); | ||
906 | void viafb_unlock_crt(void); | ||
907 | void viafb_load_offset_reg(int h_addr, int bpp_byte, int set_iga); | ||
908 | void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga); | ||
909 | void viafb_write_regx(struct io_reg RegTable[], int ItemNum); | ||
910 | struct VideoModeTable *viafb_get_modetbl_pointer(int Index); | ||
911 | u32 viafb_get_clk_value(int clk); | ||
912 | void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active); | ||
913 | void viafb_set_color_depth(int bpp_byte, int set_iga); | ||
914 | void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ | ||
915 | *p_gfx_dpa_setting); | ||
916 | |||
917 | int viafb_setmode(int vmode_index, int hor_res, int ver_res, | ||
918 | int video_bpp, int vmode_index1, int hor_res1, | ||
919 | int ver_res1, int video_bpp1); | ||
920 | void viafb_init_chip_info(void); | ||
921 | void viafb_init_dac(int set_iga); | ||
922 | int viafb_get_pixclock(int hres, int vres, int vmode_refresh); | ||
923 | int viafb_get_refresh(int hres, int vres, u32 float_refresh); | ||
924 | void viafb_update_device_setting(int hres, int vres, int bpp, | ||
925 | int vmode_refresh, int flag); | ||
926 | void viafb_get_mmio_info(unsigned long *mmio_base, | ||
927 | unsigned long *mmio_len); | ||
928 | |||
929 | void viafb_set_iga_path(void); | ||
930 | void viafb_set_start_addr(void); | ||
931 | void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len); | ||
932 | |||
933 | #endif /* __HW_H__ */ | ||
diff --git a/drivers/video/via/iface.c b/drivers/video/via/iface.c new file mode 100644 index 000000000000..1570636c8d51 --- /dev/null +++ b/drivers/video/via/iface.c | |||
@@ -0,0 +1,78 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #include "global.h" | ||
23 | |||
24 | /* Get frame buffer size from VGA BIOS */ | ||
25 | |||
26 | unsigned int viafb_get_memsize(void) | ||
27 | { | ||
28 | unsigned int m; | ||
29 | |||
30 | /* If memory size provided by user */ | ||
31 | if (viafb_memsize) | ||
32 | m = viafb_memsize * Mb; | ||
33 | else { | ||
34 | m = (unsigned int)viafb_read_reg(VIASR, SR39); | ||
35 | m = m * (4 * Mb); | ||
36 | |||
37 | if ((m < (16 * Mb)) || (m > (64 * Mb))) | ||
38 | m = 16 * Mb; | ||
39 | } | ||
40 | DEBUG_MSG(KERN_INFO "framebuffer size = %d Mb\n", m / Mb); | ||
41 | return m; | ||
42 | } | ||
43 | |||
44 | /* Get Video Buffer Starting Physical Address(back door)*/ | ||
45 | |||
46 | unsigned long viafb_get_videobuf_addr(void) | ||
47 | { | ||
48 | struct pci_dev *pdev = NULL; | ||
49 | unsigned char sys_mem; | ||
50 | unsigned char video_mem; | ||
51 | unsigned long sys_mem_size; | ||
52 | unsigned long video_mem_size; | ||
53 | /*system memory = 256 MB, video memory 64 MB */ | ||
54 | unsigned long vmem_starting_adr = 0x0C000000; | ||
55 | |||
56 | pdev = | ||
57 | (struct pci_dev *)pci_get_device(VIA_K800_BRIDGE_VID, | ||
58 | VIA_K800_BRIDGE_DID, NULL); | ||
59 | if (pdev != NULL) { | ||
60 | pci_read_config_byte(pdev, VIA_K800_SYSTEM_MEMORY_REG, | ||
61 | &sys_mem); | ||
62 | pci_read_config_byte(pdev, VIA_K800_VIDEO_MEMORY_REG, | ||
63 | &video_mem); | ||
64 | video_mem = (video_mem & 0x70) >> 4; | ||
65 | sys_mem_size = ((unsigned long)sys_mem) << 24; | ||
66 | if (video_mem != 0) | ||
67 | video_mem_size = (1 << (video_mem)) * 1024 * 1024; | ||
68 | else | ||
69 | video_mem_size = 0; | ||
70 | |||
71 | vmem_starting_adr = sys_mem_size - video_mem_size; | ||
72 | pci_dev_put(pdev); | ||
73 | } | ||
74 | |||
75 | DEBUG_MSG(KERN_INFO "Video Memory Starting Address = %lx \n", | ||
76 | vmem_starting_adr); | ||
77 | return vmem_starting_adr; | ||
78 | } | ||
diff --git a/drivers/video/via/iface.h b/drivers/video/via/iface.h new file mode 100644 index 000000000000..790ec3e3aea2 --- /dev/null +++ b/drivers/video/via/iface.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef __IFACE_H__ | ||
23 | #define __IFACE_H__ | ||
24 | |||
25 | #define Kb (1024) | ||
26 | #define Mb (Kb*Kb) | ||
27 | |||
28 | #define VIA_K800_BRIDGE_VID 0x1106 | ||
29 | #define VIA_K800_BRIDGE_DID 0x3204 | ||
30 | |||
31 | #define VIA_K800_SYSTEM_MEMORY_REG 0x47 | ||
32 | #define VIA_K800_VIDEO_MEMORY_REG 0xA1 | ||
33 | |||
34 | extern int viafb_memsize; | ||
35 | unsigned int viafb_get_memsize(void); | ||
36 | unsigned long viafb_get_videobuf_addr(void); | ||
37 | |||
38 | #endif /* __IFACE_H__ */ | ||
diff --git a/drivers/video/via/ioctl.c b/drivers/video/via/ioctl.c new file mode 100644 index 000000000000..da03c074e32a --- /dev/null +++ b/drivers/video/via/ioctl.c | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #include "global.h" | ||
23 | |||
24 | int viafb_ioctl_get_viafb_info(u_long arg) | ||
25 | { | ||
26 | struct viafb_ioctl_info viainfo; | ||
27 | |||
28 | viainfo.viafb_id = VIAID; | ||
29 | viainfo.vendor_id = PCI_VIA_VENDOR_ID; | ||
30 | |||
31 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
32 | case UNICHROME_CLE266: | ||
33 | viainfo.device_id = UNICHROME_CLE266_DID; | ||
34 | break; | ||
35 | |||
36 | case UNICHROME_K400: | ||
37 | viainfo.device_id = UNICHROME_K400_DID; | ||
38 | break; | ||
39 | |||
40 | case UNICHROME_K800: | ||
41 | viainfo.device_id = UNICHROME_K800_DID; | ||
42 | break; | ||
43 | |||
44 | case UNICHROME_PM800: | ||
45 | viainfo.device_id = UNICHROME_PM800_DID; | ||
46 | break; | ||
47 | |||
48 | case UNICHROME_CN700: | ||
49 | viainfo.device_id = UNICHROME_CN700_DID; | ||
50 | break; | ||
51 | |||
52 | case UNICHROME_CX700: | ||
53 | viainfo.device_id = UNICHROME_CX700_DID; | ||
54 | break; | ||
55 | |||
56 | case UNICHROME_K8M890: | ||
57 | viainfo.device_id = UNICHROME_K8M890_DID; | ||
58 | break; | ||
59 | |||
60 | case UNICHROME_P4M890: | ||
61 | viainfo.device_id = UNICHROME_P4M890_DID; | ||
62 | break; | ||
63 | |||
64 | case UNICHROME_P4M900: | ||
65 | viainfo.device_id = UNICHROME_P4M900_DID; | ||
66 | break; | ||
67 | } | ||
68 | |||
69 | viainfo.version = VERSION_MAJOR; | ||
70 | viainfo.revision = VERSION_MINOR; | ||
71 | |||
72 | if (copy_to_user((void __user *)arg, &viainfo, sizeof(viainfo))) | ||
73 | return -EFAULT; | ||
74 | |||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | /* Hot-Plug Priority: DVI > CRT*/ | ||
79 | int viafb_ioctl_hotplug(int hres, int vres, int bpp) | ||
80 | { | ||
81 | int DVIsense, status = 0; | ||
82 | DEBUG_MSG(KERN_INFO "viafb_ioctl_hotplug!!\n"); | ||
83 | |||
84 | if (viaparinfo->chip_info->tmds_chip_info.tmds_chip_name != | ||
85 | NON_TMDS_TRANSMITTER) { | ||
86 | DVIsense = viafb_dvi_sense(); | ||
87 | |||
88 | if (DVIsense) { | ||
89 | DEBUG_MSG(KERN_INFO "DVI Attached...\n"); | ||
90 | if (viafb_DeviceStatus != DVI_Device) { | ||
91 | viafb_DVI_ON = 1; | ||
92 | viafb_CRT_ON = 0; | ||
93 | viafb_LCD_ON = 0; | ||
94 | viafb_DeviceStatus = DVI_Device; | ||
95 | return viafb_DeviceStatus; | ||
96 | } | ||
97 | status = 1; | ||
98 | } else | ||
99 | DEBUG_MSG(KERN_INFO "DVI De-attached...\n"); | ||
100 | } | ||
101 | |||
102 | if ((viafb_DeviceStatus != CRT_Device) && (status == 0)) { | ||
103 | viafb_CRT_ON = 1; | ||
104 | viafb_DVI_ON = 0; | ||
105 | viafb_LCD_ON = 0; | ||
106 | |||
107 | viafb_DeviceStatus = CRT_Device; | ||
108 | return viafb_DeviceStatus; | ||
109 | } | ||
110 | |||
111 | return 0; | ||
112 | } | ||
diff --git a/drivers/video/via/ioctl.h b/drivers/video/via/ioctl.h new file mode 100644 index 000000000000..842fe30b9868 --- /dev/null +++ b/drivers/video/via/ioctl.h | |||
@@ -0,0 +1,210 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef __IOCTL_H__ | ||
23 | #define __IOCTL_H__ | ||
24 | |||
25 | #ifndef __user | ||
26 | #define __user | ||
27 | #endif | ||
28 | |||
29 | /* VIAFB IOCTL definition */ | ||
30 | #define VIAFB_GET_INFO_SIZE 0x56494101 /* 'VIA\01' */ | ||
31 | #define VIAFB_GET_INFO 0x56494102 /* 'VIA\02' */ | ||
32 | #define VIAFB_HOTPLUG 0x56494103 /* 'VIA\03' */ | ||
33 | #define VIAFB_SET_HOTPLUG_FLAG 0x56494104 /* 'VIA\04' */ | ||
34 | #define VIAFB_GET_RESOLUTION 0x56494105 /* 'VIA\05' */ | ||
35 | #define VIAFB_GET_SAMM_INFO 0x56494107 /* 'VIA\07' */ | ||
36 | #define VIAFB_TURN_ON_OUTPUT_DEVICE 0x56494108 /* 'VIA\08' */ | ||
37 | #define VIAFB_TURN_OFF_OUTPUT_DEVICE 0x56494109 /* 'VIA\09' */ | ||
38 | #define VIAFB_SET_DEVICE 0x5649410A | ||
39 | #define VIAFB_GET_DEVICE 0x5649410B | ||
40 | #define VIAFB_GET_DRIVER_VERSION 0x56494112 /* 'VIA\12' */ | ||
41 | #define VIAFB_GET_CHIP_INFO 0x56494113 /* 'VIA\13' */ | ||
42 | #define VIAFB_SET_DEVICE_INFO 0x56494114 | ||
43 | #define VIAFB_GET_DEVICE_INFO 0x56494115 | ||
44 | |||
45 | #define VIAFB_GET_DEVICE_SUPPORT 0x56494118 | ||
46 | #define VIAFB_GET_DEVICE_CONNECT 0x56494119 | ||
47 | #define VIAFB_GET_PANEL_SUPPORT_EXPAND 0x5649411A | ||
48 | #define VIAFB_GET_DRIVER_NAME 0x56494122 | ||
49 | #define VIAFB_GET_DEVICE_SUPPORT_STATE 0x56494123 | ||
50 | #define VIAFB_GET_GAMMA_LUT 0x56494124 | ||
51 | #define VIAFB_SET_GAMMA_LUT 0x56494125 | ||
52 | #define VIAFB_GET_GAMMA_SUPPORT_STATE 0x56494126 | ||
53 | #define VIAFB_SET_VIDEO_DEVICE 0x56494127 | ||
54 | #define VIAFB_GET_VIDEO_DEVICE 0x56494128 | ||
55 | #define VIAFB_SET_SECOND_MODE 0x56494129 | ||
56 | #define VIAFB_SYNC_SURFACE 0x56494130 | ||
57 | #define VIAFB_GET_DRIVER_CAPS 0x56494131 | ||
58 | #define VIAFB_GET_IGA_SCALING_INFO 0x56494132 | ||
59 | #define VIAFB_GET_PANEL_MAX_SIZE 0x56494133 | ||
60 | #define VIAFB_GET_PANEL_MAX_POSITION 0x56494134 | ||
61 | #define VIAFB_SET_PANEL_SIZE 0x56494135 | ||
62 | #define VIAFB_SET_PANEL_POSITION 0x56494136 | ||
63 | #define VIAFB_GET_PANEL_POSITION 0x56494137 | ||
64 | #define VIAFB_GET_PANEL_SIZE 0x56494138 | ||
65 | |||
66 | #define None_Device 0x00 | ||
67 | #define CRT_Device 0x01 | ||
68 | #define LCD_Device 0x02 | ||
69 | #define DVI_Device 0x08 | ||
70 | #define CRT2_Device 0x10 | ||
71 | #define LCD2_Device 0x40 | ||
72 | |||
73 | #define OP_LCD_CENTERING 0x01 | ||
74 | #define OP_LCD_PANEL_ID 0x02 | ||
75 | #define OP_LCD_MODE 0x03 | ||
76 | |||
77 | /*SAMM operation flag*/ | ||
78 | #define OP_SAMM 0x80 | ||
79 | |||
80 | #define LCD_PANEL_ID_MAXIMUM 22 | ||
81 | |||
82 | #define STATE_ON 0x1 | ||
83 | #define STATE_OFF 0x0 | ||
84 | #define STATE_DEFAULT 0xFFFF | ||
85 | |||
86 | #define MAX_ACTIVE_DEV_NUM 2 | ||
87 | |||
88 | struct device_t { | ||
89 | unsigned short crt:1; | ||
90 | unsigned short dvi:1; | ||
91 | unsigned short lcd:1; | ||
92 | unsigned short samm:1; | ||
93 | unsigned short lcd_dsp_cent:1; | ||
94 | unsigned char lcd_mode:1; | ||
95 | unsigned short epia_dvi:1; | ||
96 | unsigned short lcd_dual_edge:1; | ||
97 | unsigned short lcd2:1; | ||
98 | |||
99 | unsigned short primary_dev; | ||
100 | unsigned char lcd_panel_id; | ||
101 | unsigned short xres, yres; | ||
102 | unsigned short xres1, yres1; | ||
103 | unsigned short refresh; | ||
104 | unsigned short bpp; | ||
105 | unsigned short refresh1; | ||
106 | unsigned short bpp1; | ||
107 | unsigned short sequence; | ||
108 | unsigned short bus_width; | ||
109 | }; | ||
110 | |||
111 | struct viafb_ioctl_info { | ||
112 | u32 viafb_id; /* for identifying viafb */ | ||
113 | #define VIAID 0x56494146 /* Identify myself with 'VIAF' */ | ||
114 | u16 vendor_id; | ||
115 | u16 device_id; | ||
116 | u8 version; | ||
117 | u8 revision; | ||
118 | u8 reserved[246]; /* for future use */ | ||
119 | }; | ||
120 | |||
121 | struct viafb_ioctl_mode { | ||
122 | u32 xres; | ||
123 | u32 yres; | ||
124 | u32 refresh; | ||
125 | u32 bpp; | ||
126 | u32 xres_sec; | ||
127 | u32 yres_sec; | ||
128 | u32 virtual_xres_sec; | ||
129 | u32 virtual_yres_sec; | ||
130 | u32 refresh_sec; | ||
131 | u32 bpp_sec; | ||
132 | }; | ||
133 | struct viafb_ioctl_samm { | ||
134 | u32 samm_status; | ||
135 | u32 size_prim; | ||
136 | u32 size_sec; | ||
137 | u32 mem_base; | ||
138 | u32 offset_sec; | ||
139 | }; | ||
140 | |||
141 | struct viafb_driver_version { | ||
142 | int iMajorNum; | ||
143 | int iKernelNum; | ||
144 | int iOSNum; | ||
145 | int iMinorNum; | ||
146 | }; | ||
147 | |||
148 | struct viafb_ioctl_lcd_attribute { | ||
149 | unsigned int panel_id; | ||
150 | unsigned int display_center; | ||
151 | unsigned int lcd_mode; | ||
152 | }; | ||
153 | |||
154 | struct viafb_ioctl_setting { | ||
155 | /* Enable or disable active devices */ | ||
156 | unsigned short device_flag; | ||
157 | /* Indicate which device should be turn on or turn off. */ | ||
158 | unsigned short device_status; | ||
159 | unsigned int reserved; | ||
160 | /* Indicate which LCD's attribute can be changed. */ | ||
161 | unsigned short lcd_operation_flag; | ||
162 | /* 1: SAMM ON 0: SAMM OFF */ | ||
163 | unsigned short samm_status; | ||
164 | /* horizontal resolution of first device */ | ||
165 | unsigned short first_dev_hor_res; | ||
166 | /* vertical resolution of first device */ | ||
167 | unsigned short first_dev_ver_res; | ||
168 | /* horizontal resolution of second device */ | ||
169 | unsigned short second_dev_hor_res; | ||
170 | /* vertical resolution of second device */ | ||
171 | unsigned short second_dev_ver_res; | ||
172 | /* refresh rate of first device */ | ||
173 | unsigned short first_dev_refresh; | ||
174 | /* bpp of first device */ | ||
175 | unsigned short first_dev_bpp; | ||
176 | /* refresh rate of second device */ | ||
177 | unsigned short second_dev_refresh; | ||
178 | /* bpp of second device */ | ||
179 | unsigned short second_dev_bpp; | ||
180 | /* Indicate which device are primary display device. */ | ||
181 | unsigned int primary_device; | ||
182 | /* Indicate which device will show video. only valid in duoview mode */ | ||
183 | unsigned int video_device_status; | ||
184 | unsigned int struct_reserved[34]; | ||
185 | struct viafb_ioctl_lcd_attribute lcd_attributes; | ||
186 | }; | ||
187 | |||
188 | struct _UTFunctionCaps { | ||
189 | unsigned int dw3DScalingState; | ||
190 | unsigned int reserved[31]; | ||
191 | }; | ||
192 | |||
193 | struct _POSITIONVALUE { | ||
194 | unsigned int dwX; | ||
195 | unsigned int dwY; | ||
196 | }; | ||
197 | |||
198 | struct _panel_size_pos_info { | ||
199 | unsigned int device_type; | ||
200 | int x; | ||
201 | int y; | ||
202 | }; | ||
203 | |||
204 | extern int viafb_LCD_ON; | ||
205 | extern int viafb_DVI_ON; | ||
206 | |||
207 | int viafb_ioctl_get_viafb_info(u_long arg); | ||
208 | int viafb_ioctl_hotplug(int hres, int vres, int bpp); | ||
209 | |||
210 | #endif /* __IOCTL_H__ */ | ||
diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c new file mode 100644 index 000000000000..6c7290a6a447 --- /dev/null +++ b/drivers/video/via/lcd.c | |||
@@ -0,0 +1,1821 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #include "global.h" | ||
23 | #include "lcdtbl.h" | ||
24 | |||
25 | static struct iga2_shadow_crtc_timing iga2_shadow_crtc_reg = { | ||
26 | /* IGA2 Shadow Horizontal Total */ | ||
27 | {IGA2_SHADOW_HOR_TOTAL_REG_NUM, {{CR6D, 0, 7}, {CR71, 3, 3} } }, | ||
28 | /* IGA2 Shadow Horizontal Blank End */ | ||
29 | {IGA2_SHADOW_HOR_BLANK_END_REG_NUM, {{CR6E, 0, 7} } }, | ||
30 | /* IGA2 Shadow Vertical Total */ | ||
31 | {IGA2_SHADOW_VER_TOTAL_REG_NUM, {{CR6F, 0, 7}, {CR71, 0, 2} } }, | ||
32 | /* IGA2 Shadow Vertical Addressable Video */ | ||
33 | {IGA2_SHADOW_VER_ADDR_REG_NUM, {{CR70, 0, 7}, {CR71, 4, 6} } }, | ||
34 | /* IGA2 Shadow Vertical Blank Start */ | ||
35 | {IGA2_SHADOW_VER_BLANK_START_REG_NUM, | ||
36 | {{CR72, 0, 7}, {CR74, 4, 6} } }, | ||
37 | /* IGA2 Shadow Vertical Blank End */ | ||
38 | {IGA2_SHADOW_VER_BLANK_END_REG_NUM, {{CR73, 0, 7}, {CR74, 0, 2} } }, | ||
39 | /* IGA2 Shadow Vertical Sync Start */ | ||
40 | {IGA2_SHADOW_VER_SYNC_START_REG_NUM, {{CR75, 0, 7}, {CR76, 4, 6} } }, | ||
41 | /* IGA2 Shadow Vertical Sync End */ | ||
42 | {IGA2_SHADOW_VER_SYNC_END_REG_NUM, {{CR76, 0, 3} } } | ||
43 | }; | ||
44 | |||
45 | static struct _lcd_scaling_factor lcd_scaling_factor = { | ||
46 | /* LCD Horizontal Scaling Factor Register */ | ||
47 | {LCD_HOR_SCALING_FACTOR_REG_NUM, | ||
48 | {{CR9F, 0, 1}, {CR77, 0, 7}, {CR79, 4, 5} } }, | ||
49 | /* LCD Vertical Scaling Factor Register */ | ||
50 | {LCD_VER_SCALING_FACTOR_REG_NUM, | ||
51 | {{CR79, 3, 3}, {CR78, 0, 7}, {CR79, 6, 7} } } | ||
52 | }; | ||
53 | static struct _lcd_scaling_factor lcd_scaling_factor_CLE = { | ||
54 | /* LCD Horizontal Scaling Factor Register */ | ||
55 | {LCD_HOR_SCALING_FACTOR_REG_NUM_CLE, {{CR77, 0, 7}, {CR79, 4, 5} } }, | ||
56 | /* LCD Vertical Scaling Factor Register */ | ||
57 | {LCD_VER_SCALING_FACTOR_REG_NUM_CLE, {{CR78, 0, 7}, {CR79, 6, 7} } } | ||
58 | }; | ||
59 | |||
60 | static int check_lvds_chip(int device_id_subaddr, int device_id); | ||
61 | static bool lvds_identify_integratedlvds(void); | ||
62 | static int fp_id_to_vindex(int panel_id); | ||
63 | static int lvds_register_read(int index); | ||
64 | static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres, | ||
65 | int panel_vres); | ||
66 | static void load_lcd_k400_patch_tbl(int set_hres, int set_vres, | ||
67 | int panel_id); | ||
68 | static void load_lcd_p880_patch_tbl(int set_hres, int set_vres, | ||
69 | int panel_id); | ||
70 | static void load_lcd_patch_regs(int set_hres, int set_vres, | ||
71 | int panel_id, int set_iga); | ||
72 | static void via_pitch_alignment_patch_lcd( | ||
73 | struct lvds_setting_information *plvds_setting_info, | ||
74 | struct lvds_chip_information | ||
75 | *plvds_chip_info); | ||
76 | static void lcd_patch_skew_dvp0(struct lvds_setting_information | ||
77 | *plvds_setting_info, | ||
78 | struct lvds_chip_information *plvds_chip_info); | ||
79 | static void lcd_patch_skew_dvp1(struct lvds_setting_information | ||
80 | *plvds_setting_info, | ||
81 | struct lvds_chip_information *plvds_chip_info); | ||
82 | static void lcd_patch_skew(struct lvds_setting_information | ||
83 | *plvds_setting_info, struct lvds_chip_information *plvds_chip_info); | ||
84 | |||
85 | static void integrated_lvds_disable(struct lvds_setting_information | ||
86 | *plvds_setting_info, | ||
87 | struct lvds_chip_information *plvds_chip_info); | ||
88 | static void integrated_lvds_enable(struct lvds_setting_information | ||
89 | *plvds_setting_info, | ||
90 | struct lvds_chip_information *plvds_chip_info); | ||
91 | static void lcd_powersequence_off(void); | ||
92 | static void lcd_powersequence_on(void); | ||
93 | static void fill_lcd_format(void); | ||
94 | static void check_diport_of_integrated_lvds( | ||
95 | struct lvds_chip_information *plvds_chip_info, | ||
96 | struct lvds_setting_information | ||
97 | *plvds_setting_info); | ||
98 | static struct display_timing lcd_centering_timging(struct display_timing | ||
99 | mode_crt_reg, | ||
100 | struct display_timing panel_crt_reg); | ||
101 | static void load_crtc_shadow_timing(struct display_timing mode_timing, | ||
102 | struct display_timing panel_timing); | ||
103 | static void viafb_load_scaling_factor_for_p4m900(int set_hres, | ||
104 | int set_vres, int panel_hres, int panel_vres); | ||
105 | |||
106 | static int check_lvds_chip(int device_id_subaddr, int device_id) | ||
107 | { | ||
108 | if (lvds_register_read(device_id_subaddr) == device_id) | ||
109 | return OK; | ||
110 | else | ||
111 | return FAIL; | ||
112 | } | ||
113 | |||
114 | void viafb_init_lcd_size(void) | ||
115 | { | ||
116 | DEBUG_MSG(KERN_INFO "viafb_init_lcd_size()\n"); | ||
117 | DEBUG_MSG(KERN_INFO | ||
118 | "viaparinfo->lvds_setting_info->get_lcd_size_method %d\n", | ||
119 | viaparinfo->lvds_setting_info->get_lcd_size_method); | ||
120 | |||
121 | switch (viaparinfo->lvds_setting_info->get_lcd_size_method) { | ||
122 | case GET_LCD_SIZE_BY_SYSTEM_BIOS: | ||
123 | break; | ||
124 | case GET_LCD_SZIE_BY_HW_STRAPPING: | ||
125 | break; | ||
126 | case GET_LCD_SIZE_BY_VGA_BIOS: | ||
127 | DEBUG_MSG(KERN_INFO "Get LCD Size method by VGA BIOS !!\n"); | ||
128 | viaparinfo->lvds_setting_info->lcd_panel_size = | ||
129 | fp_id_to_vindex(viafb_lcd_panel_id); | ||
130 | DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n", | ||
131 | viaparinfo->lvds_setting_info->lcd_panel_id); | ||
132 | DEBUG_MSG(KERN_INFO "LCD Panel Size = %d\n", | ||
133 | viaparinfo->lvds_setting_info->lcd_panel_size); | ||
134 | break; | ||
135 | case GET_LCD_SIZE_BY_USER_SETTING: | ||
136 | DEBUG_MSG(KERN_INFO "Get LCD Size method by user setting !!\n"); | ||
137 | viaparinfo->lvds_setting_info->lcd_panel_size = | ||
138 | fp_id_to_vindex(viafb_lcd_panel_id); | ||
139 | DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n", | ||
140 | viaparinfo->lvds_setting_info->lcd_panel_id); | ||
141 | DEBUG_MSG(KERN_INFO "LCD Panel Size = %d\n", | ||
142 | viaparinfo->lvds_setting_info->lcd_panel_size); | ||
143 | break; | ||
144 | default: | ||
145 | DEBUG_MSG(KERN_INFO "viafb_init_lcd_size fail\n"); | ||
146 | viaparinfo->lvds_setting_info->lcd_panel_id = | ||
147 | LCD_PANEL_ID1_800X600; | ||
148 | viaparinfo->lvds_setting_info->lcd_panel_size = | ||
149 | fp_id_to_vindex(LCD_PANEL_ID1_800X600); | ||
150 | } | ||
151 | viaparinfo->lvds_setting_info2->lcd_panel_id = | ||
152 | viaparinfo->lvds_setting_info->lcd_panel_id; | ||
153 | viaparinfo->lvds_setting_info2->lcd_panel_size = | ||
154 | viaparinfo->lvds_setting_info->lcd_panel_size; | ||
155 | viaparinfo->lvds_setting_info2->lcd_panel_hres = | ||
156 | viaparinfo->lvds_setting_info->lcd_panel_hres; | ||
157 | viaparinfo->lvds_setting_info2->lcd_panel_vres = | ||
158 | viaparinfo->lvds_setting_info->lcd_panel_vres; | ||
159 | viaparinfo->lvds_setting_info2->device_lcd_dualedge = | ||
160 | viaparinfo->lvds_setting_info->device_lcd_dualedge; | ||
161 | viaparinfo->lvds_setting_info2->LCDDithering = | ||
162 | viaparinfo->lvds_setting_info->LCDDithering; | ||
163 | } | ||
164 | |||
165 | static bool lvds_identify_integratedlvds(void) | ||
166 | { | ||
167 | if (viafb_display_hardware_layout == HW_LAYOUT_LCD_EXTERNAL_LCD2) { | ||
168 | /* Two dual channel LCD (Internal LVDS + External LVDS): */ | ||
169 | /* If we have an external LVDS, such as VT1636, we should | ||
170 | have its chip ID already. */ | ||
171 | if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) { | ||
172 | viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name = | ||
173 | INTEGRATED_LVDS; | ||
174 | DEBUG_MSG(KERN_INFO "Support two dual channel LVDS!\ | ||
175 | (Internal LVDS + External LVDS)\n"); | ||
176 | } else { | ||
177 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = | ||
178 | INTEGRATED_LVDS; | ||
179 | DEBUG_MSG(KERN_INFO "Not found external LVDS,\ | ||
180 | so can't support two dual channel LVDS!\n"); | ||
181 | } | ||
182 | } else if (viafb_display_hardware_layout == HW_LAYOUT_LCD1_LCD2) { | ||
183 | /* Two single channel LCD (Internal LVDS + Internal LVDS): */ | ||
184 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = | ||
185 | INTEGRATED_LVDS; | ||
186 | viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name = | ||
187 | INTEGRATED_LVDS; | ||
188 | DEBUG_MSG(KERN_INFO "Support two single channel LVDS!\ | ||
189 | (Internal LVDS + Internal LVDS)\n"); | ||
190 | } else if (viafb_display_hardware_layout != HW_LAYOUT_DVI_ONLY) { | ||
191 | /* If we have found external LVDS, just use it, | ||
192 | otherwise, we will use internal LVDS as default. */ | ||
193 | if (!viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) { | ||
194 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = | ||
195 | INTEGRATED_LVDS; | ||
196 | DEBUG_MSG(KERN_INFO "Found Integrated LVDS!\n"); | ||
197 | } | ||
198 | } else { | ||
199 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = | ||
200 | NON_LVDS_TRANSMITTER; | ||
201 | DEBUG_MSG(KERN_INFO "Do not support LVDS!\n"); | ||
202 | return false; | ||
203 | } | ||
204 | |||
205 | return true; | ||
206 | } | ||
207 | |||
208 | int viafb_lvds_trasmitter_identify(void) | ||
209 | { | ||
210 | viaparinfo->i2c_stuff.i2c_port = I2CPORTINDEX; | ||
211 | if (viafb_lvds_identify_vt1636()) { | ||
212 | viaparinfo->chip_info->lvds_chip_info.i2c_port = I2CPORTINDEX; | ||
213 | DEBUG_MSG(KERN_INFO | ||
214 | "Found VIA VT1636 LVDS on port i2c 0x31 \n"); | ||
215 | } else { | ||
216 | viaparinfo->i2c_stuff.i2c_port = GPIOPORTINDEX; | ||
217 | if (viafb_lvds_identify_vt1636()) { | ||
218 | viaparinfo->chip_info->lvds_chip_info.i2c_port = | ||
219 | GPIOPORTINDEX; | ||
220 | DEBUG_MSG(KERN_INFO | ||
221 | "Found VIA VT1636 LVDS on port gpio 0x2c \n"); | ||
222 | } | ||
223 | } | ||
224 | |||
225 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) | ||
226 | lvds_identify_integratedlvds(); | ||
227 | |||
228 | if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) | ||
229 | return true; | ||
230 | /* Check for VT1631: */ | ||
231 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = VT1631_LVDS; | ||
232 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr = | ||
233 | VT1631_LVDS_I2C_ADDR; | ||
234 | |||
235 | if (check_lvds_chip(VT1631_DEVICE_ID_REG, VT1631_DEVICE_ID) != FAIL) { | ||
236 | DEBUG_MSG(KERN_INFO "\n VT1631 LVDS ! \n"); | ||
237 | DEBUG_MSG(KERN_INFO "\n %2d", | ||
238 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name); | ||
239 | DEBUG_MSG(KERN_INFO "\n %2d", | ||
240 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name); | ||
241 | return OK; | ||
242 | } | ||
243 | |||
244 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = | ||
245 | NON_LVDS_TRANSMITTER; | ||
246 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr = | ||
247 | VT1631_LVDS_I2C_ADDR; | ||
248 | return FAIL; | ||
249 | } | ||
250 | |||
251 | static int fp_id_to_vindex(int panel_id) | ||
252 | { | ||
253 | DEBUG_MSG(KERN_INFO "fp_get_panel_id()\n"); | ||
254 | |||
255 | if (panel_id > LCD_PANEL_ID_MAXIMUM) | ||
256 | viafb_lcd_panel_id = panel_id = | ||
257 | viafb_read_reg(VIACR, CR3F) & 0x0F; | ||
258 | |||
259 | switch (panel_id) { | ||
260 | case 0x0: | ||
261 | viaparinfo->lvds_setting_info->lcd_panel_hres = 640; | ||
262 | viaparinfo->lvds_setting_info->lcd_panel_vres = 480; | ||
263 | viaparinfo->lvds_setting_info->lcd_panel_id = | ||
264 | LCD_PANEL_ID0_640X480; | ||
265 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
266 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
267 | return VIA_RES_640X480; | ||
268 | break; | ||
269 | case 0x1: | ||
270 | viaparinfo->lvds_setting_info->lcd_panel_hres = 800; | ||
271 | viaparinfo->lvds_setting_info->lcd_panel_vres = 600; | ||
272 | viaparinfo->lvds_setting_info->lcd_panel_id = | ||
273 | LCD_PANEL_ID1_800X600; | ||
274 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
275 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
276 | return VIA_RES_800X600; | ||
277 | break; | ||
278 | case 0x2: | ||
279 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; | ||
280 | viaparinfo->lvds_setting_info->lcd_panel_vres = 768; | ||
281 | viaparinfo->lvds_setting_info->lcd_panel_id = | ||
282 | LCD_PANEL_ID2_1024X768; | ||
283 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
284 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
285 | return VIA_RES_1024X768; | ||
286 | break; | ||
287 | case 0x3: | ||
288 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; | ||
289 | viaparinfo->lvds_setting_info->lcd_panel_vres = 768; | ||
290 | viaparinfo->lvds_setting_info->lcd_panel_id = | ||
291 | LCD_PANEL_ID3_1280X768; | ||
292 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
293 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
294 | return VIA_RES_1280X768; | ||
295 | break; | ||
296 | case 0x4: | ||
297 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; | ||
298 | viaparinfo->lvds_setting_info->lcd_panel_vres = 1024; | ||
299 | viaparinfo->lvds_setting_info->lcd_panel_id = | ||
300 | LCD_PANEL_ID4_1280X1024; | ||
301 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | ||
302 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
303 | return VIA_RES_1280X1024; | ||
304 | break; | ||
305 | case 0x5: | ||
306 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1400; | ||
307 | viaparinfo->lvds_setting_info->lcd_panel_vres = 1050; | ||
308 | viaparinfo->lvds_setting_info->lcd_panel_id = | ||
309 | LCD_PANEL_ID5_1400X1050; | ||
310 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | ||
311 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
312 | return VIA_RES_1400X1050; | ||
313 | break; | ||
314 | case 0x6: | ||
315 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1600; | ||
316 | viaparinfo->lvds_setting_info->lcd_panel_vres = 1200; | ||
317 | viaparinfo->lvds_setting_info->lcd_panel_id = | ||
318 | LCD_PANEL_ID6_1600X1200; | ||
319 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | ||
320 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
321 | return VIA_RES_1600X1200; | ||
322 | break; | ||
323 | case 0x8: | ||
324 | viaparinfo->lvds_setting_info->lcd_panel_hres = 800; | ||
325 | viaparinfo->lvds_setting_info->lcd_panel_vres = 480; | ||
326 | viaparinfo->lvds_setting_info->lcd_panel_id = | ||
327 | LCD_PANEL_IDA_800X480; | ||
328 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
329 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
330 | return VIA_RES_800X480; | ||
331 | break; | ||
332 | case 0x9: | ||
333 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; | ||
334 | viaparinfo->lvds_setting_info->lcd_panel_vres = 768; | ||
335 | viaparinfo->lvds_setting_info->lcd_panel_id = | ||
336 | LCD_PANEL_ID2_1024X768; | ||
337 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | ||
338 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
339 | return VIA_RES_1024X768; | ||
340 | break; | ||
341 | case 0xA: | ||
342 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; | ||
343 | viaparinfo->lvds_setting_info->lcd_panel_vres = 768; | ||
344 | viaparinfo->lvds_setting_info->lcd_panel_id = | ||
345 | LCD_PANEL_ID2_1024X768; | ||
346 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
347 | viaparinfo->lvds_setting_info->LCDDithering = 0; | ||
348 | return VIA_RES_1024X768; | ||
349 | break; | ||
350 | case 0xB: | ||
351 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; | ||
352 | viaparinfo->lvds_setting_info->lcd_panel_vres = 768; | ||
353 | viaparinfo->lvds_setting_info->lcd_panel_id = | ||
354 | LCD_PANEL_ID2_1024X768; | ||
355 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | ||
356 | viaparinfo->lvds_setting_info->LCDDithering = 0; | ||
357 | return VIA_RES_1024X768; | ||
358 | break; | ||
359 | case 0xC: | ||
360 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; | ||
361 | viaparinfo->lvds_setting_info->lcd_panel_vres = 768; | ||
362 | viaparinfo->lvds_setting_info->lcd_panel_id = | ||
363 | LCD_PANEL_ID3_1280X768; | ||
364 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
365 | viaparinfo->lvds_setting_info->LCDDithering = 0; | ||
366 | return VIA_RES_1280X768; | ||
367 | break; | ||
368 | case 0xD: | ||
369 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; | ||
370 | viaparinfo->lvds_setting_info->lcd_panel_vres = 1024; | ||
371 | viaparinfo->lvds_setting_info->lcd_panel_id = | ||
372 | LCD_PANEL_ID4_1280X1024; | ||
373 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | ||
374 | viaparinfo->lvds_setting_info->LCDDithering = 0; | ||
375 | return VIA_RES_1280X1024; | ||
376 | break; | ||
377 | case 0xE: | ||
378 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1400; | ||
379 | viaparinfo->lvds_setting_info->lcd_panel_vres = 1050; | ||
380 | viaparinfo->lvds_setting_info->lcd_panel_id = | ||
381 | LCD_PANEL_ID5_1400X1050; | ||
382 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | ||
383 | viaparinfo->lvds_setting_info->LCDDithering = 0; | ||
384 | return VIA_RES_1400X1050; | ||
385 | break; | ||
386 | case 0xF: | ||
387 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1600; | ||
388 | viaparinfo->lvds_setting_info->lcd_panel_vres = 1200; | ||
389 | viaparinfo->lvds_setting_info->lcd_panel_id = | ||
390 | LCD_PANEL_ID6_1600X1200; | ||
391 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | ||
392 | viaparinfo->lvds_setting_info->LCDDithering = 0; | ||
393 | return VIA_RES_1600X1200; | ||
394 | break; | ||
395 | case 0x10: | ||
396 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1366; | ||
397 | viaparinfo->lvds_setting_info->lcd_panel_vres = 768; | ||
398 | viaparinfo->lvds_setting_info->lcd_panel_id = | ||
399 | LCD_PANEL_ID7_1366X768; | ||
400 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
401 | viaparinfo->lvds_setting_info->LCDDithering = 0; | ||
402 | return VIA_RES_1368X768; | ||
403 | break; | ||
404 | case 0x11: | ||
405 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; | ||
406 | viaparinfo->lvds_setting_info->lcd_panel_vres = 600; | ||
407 | viaparinfo->lvds_setting_info->lcd_panel_id = | ||
408 | LCD_PANEL_ID8_1024X600; | ||
409 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
410 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
411 | return VIA_RES_1024X600; | ||
412 | break; | ||
413 | case 0x12: | ||
414 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; | ||
415 | viaparinfo->lvds_setting_info->lcd_panel_vres = 768; | ||
416 | viaparinfo->lvds_setting_info->lcd_panel_id = | ||
417 | LCD_PANEL_ID3_1280X768; | ||
418 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | ||
419 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
420 | return VIA_RES_1280X768; | ||
421 | break; | ||
422 | case 0x13: | ||
423 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; | ||
424 | viaparinfo->lvds_setting_info->lcd_panel_vres = 800; | ||
425 | viaparinfo->lvds_setting_info->lcd_panel_id = | ||
426 | LCD_PANEL_ID9_1280X800; | ||
427 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
428 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
429 | return VIA_RES_1280X800; | ||
430 | break; | ||
431 | case 0x14: | ||
432 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1360; | ||
433 | viaparinfo->lvds_setting_info->lcd_panel_vres = 768; | ||
434 | viaparinfo->lvds_setting_info->lcd_panel_id = | ||
435 | LCD_PANEL_IDB_1360X768; | ||
436 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
437 | viaparinfo->lvds_setting_info->LCDDithering = 0; | ||
438 | return VIA_RES_1360X768; | ||
439 | break; | ||
440 | case 0x15: | ||
441 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; | ||
442 | viaparinfo->lvds_setting_info->lcd_panel_vres = 768; | ||
443 | viaparinfo->lvds_setting_info->lcd_panel_id = | ||
444 | LCD_PANEL_ID3_1280X768; | ||
445 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | ||
446 | viaparinfo->lvds_setting_info->LCDDithering = 0; | ||
447 | return VIA_RES_1280X768; | ||
448 | break; | ||
449 | case 0x16: | ||
450 | viaparinfo->lvds_setting_info->lcd_panel_hres = 480; | ||
451 | viaparinfo->lvds_setting_info->lcd_panel_vres = 640; | ||
452 | viaparinfo->lvds_setting_info->lcd_panel_id = | ||
453 | LCD_PANEL_IDC_480X640; | ||
454 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
455 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
456 | return VIA_RES_480X640; | ||
457 | break; | ||
458 | default: | ||
459 | viaparinfo->lvds_setting_info->lcd_panel_hres = 800; | ||
460 | viaparinfo->lvds_setting_info->lcd_panel_vres = 600; | ||
461 | viaparinfo->lvds_setting_info->lcd_panel_id = | ||
462 | LCD_PANEL_ID1_800X600; | ||
463 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
464 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
465 | return VIA_RES_800X600; | ||
466 | } | ||
467 | } | ||
468 | |||
469 | static int lvds_register_read(int index) | ||
470 | { | ||
471 | u8 data; | ||
472 | |||
473 | viaparinfo->i2c_stuff.i2c_port = GPIOPORTINDEX; | ||
474 | viafb_i2c_readbyte((u8) viaparinfo->chip_info-> | ||
475 | lvds_chip_info.lvds_chip_slave_addr, | ||
476 | (u8) index, &data); | ||
477 | return data; | ||
478 | } | ||
479 | |||
480 | static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres, | ||
481 | int panel_vres) | ||
482 | { | ||
483 | int reg_value = 0; | ||
484 | int viafb_load_reg_num; | ||
485 | struct io_register *reg = NULL; | ||
486 | |||
487 | DEBUG_MSG(KERN_INFO "load_lcd_scaling()!!\n"); | ||
488 | |||
489 | /* LCD Scaling Enable */ | ||
490 | viafb_write_reg_mask(CR79, VIACR, 0x07, BIT0 + BIT1 + BIT2); | ||
491 | if (UNICHROME_P4M900 == viaparinfo->chip_info->gfx_chip_name) { | ||
492 | viafb_load_scaling_factor_for_p4m900(set_hres, set_vres, | ||
493 | panel_hres, panel_vres); | ||
494 | return; | ||
495 | } | ||
496 | |||
497 | /* Check if expansion for horizontal */ | ||
498 | if (set_hres != panel_hres) { | ||
499 | /* Load Horizontal Scaling Factor */ | ||
500 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
501 | case UNICHROME_CLE266: | ||
502 | case UNICHROME_K400: | ||
503 | reg_value = | ||
504 | CLE266_LCD_HOR_SCF_FORMULA(set_hres, panel_hres); | ||
505 | viafb_load_reg_num = | ||
506 | lcd_scaling_factor_CLE.lcd_hor_scaling_factor. | ||
507 | reg_num; | ||
508 | reg = lcd_scaling_factor_CLE.lcd_hor_scaling_factor.reg; | ||
509 | viafb_load_reg(reg_value, | ||
510 | viafb_load_reg_num, reg, VIACR); | ||
511 | break; | ||
512 | case UNICHROME_K800: | ||
513 | case UNICHROME_PM800: | ||
514 | case UNICHROME_CN700: | ||
515 | case UNICHROME_CX700: | ||
516 | case UNICHROME_K8M890: | ||
517 | case UNICHROME_P4M890: | ||
518 | reg_value = | ||
519 | K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres); | ||
520 | /* Horizontal scaling enabled */ | ||
521 | viafb_write_reg_mask(CRA2, VIACR, 0xC0, BIT7 + BIT6); | ||
522 | viafb_load_reg_num = | ||
523 | lcd_scaling_factor.lcd_hor_scaling_factor.reg_num; | ||
524 | reg = lcd_scaling_factor.lcd_hor_scaling_factor.reg; | ||
525 | viafb_load_reg(reg_value, | ||
526 | viafb_load_reg_num, reg, VIACR); | ||
527 | break; | ||
528 | } | ||
529 | |||
530 | DEBUG_MSG(KERN_INFO "Horizontal Scaling value = %d", reg_value); | ||
531 | } else { | ||
532 | /* Horizontal scaling disabled */ | ||
533 | viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT7); | ||
534 | } | ||
535 | |||
536 | /* Check if expansion for vertical */ | ||
537 | if (set_vres != panel_vres) { | ||
538 | /* Load Vertical Scaling Factor */ | ||
539 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
540 | case UNICHROME_CLE266: | ||
541 | case UNICHROME_K400: | ||
542 | reg_value = | ||
543 | CLE266_LCD_VER_SCF_FORMULA(set_vres, panel_vres); | ||
544 | viafb_load_reg_num = | ||
545 | lcd_scaling_factor_CLE.lcd_ver_scaling_factor. | ||
546 | reg_num; | ||
547 | reg = lcd_scaling_factor_CLE.lcd_ver_scaling_factor.reg; | ||
548 | viafb_load_reg(reg_value, | ||
549 | viafb_load_reg_num, reg, VIACR); | ||
550 | break; | ||
551 | case UNICHROME_K800: | ||
552 | case UNICHROME_PM800: | ||
553 | case UNICHROME_CN700: | ||
554 | case UNICHROME_CX700: | ||
555 | case UNICHROME_K8M890: | ||
556 | case UNICHROME_P4M890: | ||
557 | reg_value = | ||
558 | K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres); | ||
559 | /* Vertical scaling enabled */ | ||
560 | viafb_write_reg_mask(CRA2, VIACR, 0x08, BIT3); | ||
561 | viafb_load_reg_num = | ||
562 | lcd_scaling_factor.lcd_ver_scaling_factor.reg_num; | ||
563 | reg = lcd_scaling_factor.lcd_ver_scaling_factor.reg; | ||
564 | viafb_load_reg(reg_value, | ||
565 | viafb_load_reg_num, reg, VIACR); | ||
566 | break; | ||
567 | } | ||
568 | |||
569 | DEBUG_MSG(KERN_INFO "Vertical Scaling value = %d", reg_value); | ||
570 | } else { | ||
571 | /* Vertical scaling disabled */ | ||
572 | viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT3); | ||
573 | } | ||
574 | } | ||
575 | |||
576 | static void load_lcd_k400_patch_tbl(int set_hres, int set_vres, | ||
577 | int panel_id) | ||
578 | { | ||
579 | int vmode_index; | ||
580 | int reg_num = 0; | ||
581 | struct io_reg *lcd_patch_reg = NULL; | ||
582 | |||
583 | if (viaparinfo->lvds_setting_info->iga_path == IGA2) | ||
584 | vmode_index = viafb_get_mode_index(set_hres, set_vres, 1); | ||
585 | else | ||
586 | vmode_index = viafb_get_mode_index(set_hres, set_vres, 0); | ||
587 | switch (panel_id) { | ||
588 | /* LCD 800x600 */ | ||
589 | case LCD_PANEL_ID1_800X600: | ||
590 | switch (vmode_index) { | ||
591 | case VIA_RES_640X400: | ||
592 | case VIA_RES_640X480: | ||
593 | reg_num = NUM_TOTAL_K400_LCD_RES_6X4_8X6; | ||
594 | lcd_patch_reg = K400_LCD_RES_6X4_8X6; | ||
595 | break; | ||
596 | case VIA_RES_720X480: | ||
597 | case VIA_RES_720X576: | ||
598 | reg_num = NUM_TOTAL_K400_LCD_RES_7X4_8X6; | ||
599 | lcd_patch_reg = K400_LCD_RES_7X4_8X6; | ||
600 | break; | ||
601 | } | ||
602 | break; | ||
603 | |||
604 | /* LCD 1024x768 */ | ||
605 | case LCD_PANEL_ID2_1024X768: | ||
606 | switch (vmode_index) { | ||
607 | case VIA_RES_640X400: | ||
608 | case VIA_RES_640X480: | ||
609 | reg_num = NUM_TOTAL_K400_LCD_RES_6X4_10X7; | ||
610 | lcd_patch_reg = K400_LCD_RES_6X4_10X7; | ||
611 | break; | ||
612 | case VIA_RES_720X480: | ||
613 | case VIA_RES_720X576: | ||
614 | reg_num = NUM_TOTAL_K400_LCD_RES_7X4_10X7; | ||
615 | lcd_patch_reg = K400_LCD_RES_7X4_10X7; | ||
616 | break; | ||
617 | case VIA_RES_800X600: | ||
618 | reg_num = NUM_TOTAL_K400_LCD_RES_8X6_10X7; | ||
619 | lcd_patch_reg = K400_LCD_RES_8X6_10X7; | ||
620 | break; | ||
621 | } | ||
622 | break; | ||
623 | |||
624 | /* LCD 1280x1024 */ | ||
625 | case LCD_PANEL_ID4_1280X1024: | ||
626 | switch (vmode_index) { | ||
627 | case VIA_RES_640X400: | ||
628 | case VIA_RES_640X480: | ||
629 | reg_num = NUM_TOTAL_K400_LCD_RES_6X4_12X10; | ||
630 | lcd_patch_reg = K400_LCD_RES_6X4_12X10; | ||
631 | break; | ||
632 | case VIA_RES_720X480: | ||
633 | case VIA_RES_720X576: | ||
634 | reg_num = NUM_TOTAL_K400_LCD_RES_7X4_12X10; | ||
635 | lcd_patch_reg = K400_LCD_RES_7X4_12X10; | ||
636 | break; | ||
637 | case VIA_RES_800X600: | ||
638 | reg_num = NUM_TOTAL_K400_LCD_RES_8X6_12X10; | ||
639 | lcd_patch_reg = K400_LCD_RES_8X6_12X10; | ||
640 | break; | ||
641 | case VIA_RES_1024X768: | ||
642 | reg_num = NUM_TOTAL_K400_LCD_RES_10X7_12X10; | ||
643 | lcd_patch_reg = K400_LCD_RES_10X7_12X10; | ||
644 | break; | ||
645 | |||
646 | } | ||
647 | break; | ||
648 | |||
649 | /* LCD 1400x1050 */ | ||
650 | case LCD_PANEL_ID5_1400X1050: | ||
651 | switch (vmode_index) { | ||
652 | case VIA_RES_640X480: | ||
653 | reg_num = NUM_TOTAL_K400_LCD_RES_6X4_14X10; | ||
654 | lcd_patch_reg = K400_LCD_RES_6X4_14X10; | ||
655 | break; | ||
656 | case VIA_RES_800X600: | ||
657 | reg_num = NUM_TOTAL_K400_LCD_RES_8X6_14X10; | ||
658 | lcd_patch_reg = K400_LCD_RES_8X6_14X10; | ||
659 | break; | ||
660 | case VIA_RES_1024X768: | ||
661 | reg_num = NUM_TOTAL_K400_LCD_RES_10X7_14X10; | ||
662 | lcd_patch_reg = K400_LCD_RES_10X7_14X10; | ||
663 | break; | ||
664 | case VIA_RES_1280X768: | ||
665 | case VIA_RES_1280X800: | ||
666 | case VIA_RES_1280X960: | ||
667 | case VIA_RES_1280X1024: | ||
668 | reg_num = NUM_TOTAL_K400_LCD_RES_12X10_14X10; | ||
669 | lcd_patch_reg = K400_LCD_RES_12X10_14X10; | ||
670 | break; | ||
671 | } | ||
672 | break; | ||
673 | |||
674 | /* LCD 1600x1200 */ | ||
675 | case LCD_PANEL_ID6_1600X1200: | ||
676 | switch (vmode_index) { | ||
677 | case VIA_RES_640X400: | ||
678 | case VIA_RES_640X480: | ||
679 | reg_num = NUM_TOTAL_K400_LCD_RES_6X4_16X12; | ||
680 | lcd_patch_reg = K400_LCD_RES_6X4_16X12; | ||
681 | break; | ||
682 | case VIA_RES_720X480: | ||
683 | case VIA_RES_720X576: | ||
684 | reg_num = NUM_TOTAL_K400_LCD_RES_7X4_16X12; | ||
685 | lcd_patch_reg = K400_LCD_RES_7X4_16X12; | ||
686 | break; | ||
687 | case VIA_RES_800X600: | ||
688 | reg_num = NUM_TOTAL_K400_LCD_RES_8X6_16X12; | ||
689 | lcd_patch_reg = K400_LCD_RES_8X6_16X12; | ||
690 | break; | ||
691 | case VIA_RES_1024X768: | ||
692 | reg_num = NUM_TOTAL_K400_LCD_RES_10X7_16X12; | ||
693 | lcd_patch_reg = K400_LCD_RES_10X7_16X12; | ||
694 | break; | ||
695 | case VIA_RES_1280X768: | ||
696 | case VIA_RES_1280X800: | ||
697 | case VIA_RES_1280X960: | ||
698 | case VIA_RES_1280X1024: | ||
699 | reg_num = NUM_TOTAL_K400_LCD_RES_12X10_16X12; | ||
700 | lcd_patch_reg = K400_LCD_RES_12X10_16X12; | ||
701 | break; | ||
702 | } | ||
703 | break; | ||
704 | |||
705 | /* LCD 1366x768 */ | ||
706 | case LCD_PANEL_ID7_1366X768: | ||
707 | switch (vmode_index) { | ||
708 | case VIA_RES_640X480: | ||
709 | reg_num = NUM_TOTAL_K400_LCD_RES_6X4_1366X7; | ||
710 | lcd_patch_reg = K400_LCD_RES_6X4_1366X7; | ||
711 | break; | ||
712 | case VIA_RES_720X480: | ||
713 | case VIA_RES_720X576: | ||
714 | reg_num = NUM_TOTAL_K400_LCD_RES_7X4_1366X7; | ||
715 | lcd_patch_reg = K400_LCD_RES_7X4_1366X7; | ||
716 | break; | ||
717 | case VIA_RES_800X600: | ||
718 | reg_num = NUM_TOTAL_K400_LCD_RES_8X6_1366X7; | ||
719 | lcd_patch_reg = K400_LCD_RES_8X6_1366X7; | ||
720 | break; | ||
721 | case VIA_RES_1024X768: | ||
722 | reg_num = NUM_TOTAL_K400_LCD_RES_10X7_1366X7; | ||
723 | lcd_patch_reg = K400_LCD_RES_10X7_1366X7; | ||
724 | break; | ||
725 | case VIA_RES_1280X768: | ||
726 | case VIA_RES_1280X800: | ||
727 | case VIA_RES_1280X960: | ||
728 | case VIA_RES_1280X1024: | ||
729 | reg_num = NUM_TOTAL_K400_LCD_RES_12X10_1366X7; | ||
730 | lcd_patch_reg = K400_LCD_RES_12X10_1366X7; | ||
731 | break; | ||
732 | } | ||
733 | break; | ||
734 | |||
735 | /* LCD 1360x768 */ | ||
736 | case LCD_PANEL_IDB_1360X768: | ||
737 | break; | ||
738 | } | ||
739 | if (reg_num != 0) { | ||
740 | /* H.W. Reset : ON */ | ||
741 | viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7); | ||
742 | |||
743 | viafb_write_regx(lcd_patch_reg, reg_num); | ||
744 | |||
745 | /* H.W. Reset : OFF */ | ||
746 | viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7); | ||
747 | |||
748 | /* Reset PLL */ | ||
749 | viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1); | ||
750 | viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1); | ||
751 | |||
752 | /* Fire! */ | ||
753 | outb(inb(VIARMisc) | (BIT2 + BIT3), VIAWMisc); | ||
754 | } | ||
755 | } | ||
756 | |||
757 | static void load_lcd_p880_patch_tbl(int set_hres, int set_vres, | ||
758 | int panel_id) | ||
759 | { | ||
760 | int vmode_index; | ||
761 | int reg_num = 0; | ||
762 | struct io_reg *lcd_patch_reg = NULL; | ||
763 | |||
764 | if (viaparinfo->lvds_setting_info->iga_path == IGA2) | ||
765 | vmode_index = viafb_get_mode_index(set_hres, set_vres, 1); | ||
766 | else | ||
767 | vmode_index = viafb_get_mode_index(set_hres, set_vres, 0); | ||
768 | |||
769 | switch (panel_id) { | ||
770 | case LCD_PANEL_ID5_1400X1050: | ||
771 | switch (vmode_index) { | ||
772 | case VIA_RES_640X480: | ||
773 | reg_num = NUM_TOTAL_P880_LCD_RES_6X4_14X10; | ||
774 | lcd_patch_reg = P880_LCD_RES_6X4_14X10; | ||
775 | break; | ||
776 | case VIA_RES_800X600: | ||
777 | reg_num = NUM_TOTAL_P880_LCD_RES_8X6_14X10; | ||
778 | lcd_patch_reg = P880_LCD_RES_8X6_14X10; | ||
779 | break; | ||
780 | } | ||
781 | break; | ||
782 | case LCD_PANEL_ID6_1600X1200: | ||
783 | switch (vmode_index) { | ||
784 | case VIA_RES_640X400: | ||
785 | case VIA_RES_640X480: | ||
786 | reg_num = NUM_TOTAL_P880_LCD_RES_6X4_16X12; | ||
787 | lcd_patch_reg = P880_LCD_RES_6X4_16X12; | ||
788 | break; | ||
789 | case VIA_RES_720X480: | ||
790 | case VIA_RES_720X576: | ||
791 | reg_num = NUM_TOTAL_P880_LCD_RES_7X4_16X12; | ||
792 | lcd_patch_reg = P880_LCD_RES_7X4_16X12; | ||
793 | break; | ||
794 | case VIA_RES_800X600: | ||
795 | reg_num = NUM_TOTAL_P880_LCD_RES_8X6_16X12; | ||
796 | lcd_patch_reg = P880_LCD_RES_8X6_16X12; | ||
797 | break; | ||
798 | case VIA_RES_1024X768: | ||
799 | reg_num = NUM_TOTAL_P880_LCD_RES_10X7_16X12; | ||
800 | lcd_patch_reg = P880_LCD_RES_10X7_16X12; | ||
801 | break; | ||
802 | case VIA_RES_1280X768: | ||
803 | case VIA_RES_1280X960: | ||
804 | case VIA_RES_1280X1024: | ||
805 | reg_num = NUM_TOTAL_P880_LCD_RES_12X10_16X12; | ||
806 | lcd_patch_reg = P880_LCD_RES_12X10_16X12; | ||
807 | break; | ||
808 | } | ||
809 | break; | ||
810 | |||
811 | } | ||
812 | if (reg_num != 0) { | ||
813 | /* H.W. Reset : ON */ | ||
814 | viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7); | ||
815 | |||
816 | viafb_write_regx(lcd_patch_reg, reg_num); | ||
817 | |||
818 | /* H.W. Reset : OFF */ | ||
819 | viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7); | ||
820 | |||
821 | /* Reset PLL */ | ||
822 | viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1); | ||
823 | viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1); | ||
824 | |||
825 | /* Fire! */ | ||
826 | outb(inb(VIARMisc) | (BIT2 + BIT3), VIAWMisc); | ||
827 | } | ||
828 | } | ||
829 | |||
830 | static void load_lcd_patch_regs(int set_hres, int set_vres, | ||
831 | int panel_id, int set_iga) | ||
832 | { | ||
833 | int vmode_index; | ||
834 | |||
835 | if (viaparinfo->lvds_setting_info->iga_path == IGA2) | ||
836 | vmode_index = viafb_get_mode_index(set_hres, set_vres, 1); | ||
837 | else | ||
838 | vmode_index = viafb_get_mode_index(set_hres, set_vres, 0); | ||
839 | |||
840 | viafb_unlock_crt(); | ||
841 | |||
842 | /* Patch for simultaneous & Expansion */ | ||
843 | if ((set_iga == IGA1_IGA2) && | ||
844 | (viaparinfo->lvds_setting_info->display_method == | ||
845 | LCD_EXPANDSION)) { | ||
846 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
847 | case UNICHROME_CLE266: | ||
848 | case UNICHROME_K400: | ||
849 | load_lcd_k400_patch_tbl(set_hres, set_vres, panel_id); | ||
850 | break; | ||
851 | case UNICHROME_K800: | ||
852 | break; | ||
853 | case UNICHROME_PM800: | ||
854 | case UNICHROME_CN700: | ||
855 | case UNICHROME_CX700: | ||
856 | load_lcd_p880_patch_tbl(set_hres, set_vres, panel_id); | ||
857 | } | ||
858 | } | ||
859 | |||
860 | viafb_lock_crt(); | ||
861 | } | ||
862 | |||
863 | static void via_pitch_alignment_patch_lcd( | ||
864 | struct lvds_setting_information *plvds_setting_info, | ||
865 | struct lvds_chip_information | ||
866 | *plvds_chip_info) | ||
867 | { | ||
868 | unsigned char cr13, cr35, cr65, cr66, cr67; | ||
869 | unsigned long dwScreenPitch = 0; | ||
870 | unsigned long dwPitch; | ||
871 | |||
872 | dwPitch = plvds_setting_info->h_active * (plvds_setting_info->bpp >> 3); | ||
873 | if (dwPitch & 0x1F) { | ||
874 | dwScreenPitch = ((dwPitch + 31) & ~31) >> 3; | ||
875 | if (plvds_setting_info->iga_path == IGA2) { | ||
876 | if (plvds_setting_info->bpp > 8) { | ||
877 | cr66 = (unsigned char)(dwScreenPitch & 0xFF); | ||
878 | viafb_write_reg(CR66, VIACR, cr66); | ||
879 | cr67 = viafb_read_reg(VIACR, CR67) & 0xFC; | ||
880 | cr67 |= | ||
881 | (unsigned | ||
882 | char)((dwScreenPitch & 0x300) >> 8); | ||
883 | viafb_write_reg(CR67, VIACR, cr67); | ||
884 | } | ||
885 | |||
886 | /* Fetch Count */ | ||
887 | cr67 = viafb_read_reg(VIACR, CR67) & 0xF3; | ||
888 | cr67 |= (unsigned char)((dwScreenPitch & 0x600) >> 7); | ||
889 | viafb_write_reg(CR67, VIACR, cr67); | ||
890 | cr65 = (unsigned char)((dwScreenPitch >> 1) & 0xFF); | ||
891 | cr65 += 2; | ||
892 | viafb_write_reg(CR65, VIACR, cr65); | ||
893 | } else { | ||
894 | if (plvds_setting_info->bpp > 8) { | ||
895 | cr13 = (unsigned char)(dwScreenPitch & 0xFF); | ||
896 | viafb_write_reg(CR13, VIACR, cr13); | ||
897 | cr35 = viafb_read_reg(VIACR, CR35) & 0x1F; | ||
898 | cr35 |= | ||
899 | (unsigned | ||
900 | char)((dwScreenPitch & 0x700) >> 3); | ||
901 | viafb_write_reg(CR35, VIACR, cr35); | ||
902 | } | ||
903 | } | ||
904 | } | ||
905 | } | ||
906 | static void lcd_patch_skew_dvp0(struct lvds_setting_information | ||
907 | *plvds_setting_info, | ||
908 | struct lvds_chip_information *plvds_chip_info) | ||
909 | { | ||
910 | if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) { | ||
911 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
912 | case UNICHROME_P4M900: | ||
913 | viafb_vt1636_patch_skew_on_vt3364(plvds_setting_info, | ||
914 | plvds_chip_info); | ||
915 | break; | ||
916 | case UNICHROME_P4M890: | ||
917 | viafb_vt1636_patch_skew_on_vt3327(plvds_setting_info, | ||
918 | plvds_chip_info); | ||
919 | break; | ||
920 | } | ||
921 | } | ||
922 | } | ||
923 | static void lcd_patch_skew_dvp1(struct lvds_setting_information | ||
924 | *plvds_setting_info, | ||
925 | struct lvds_chip_information *plvds_chip_info) | ||
926 | { | ||
927 | if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) { | ||
928 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
929 | case UNICHROME_CX700: | ||
930 | viafb_vt1636_patch_skew_on_vt3324(plvds_setting_info, | ||
931 | plvds_chip_info); | ||
932 | break; | ||
933 | } | ||
934 | } | ||
935 | } | ||
936 | static void lcd_patch_skew(struct lvds_setting_information | ||
937 | *plvds_setting_info, struct lvds_chip_information *plvds_chip_info) | ||
938 | { | ||
939 | DEBUG_MSG(KERN_INFO "lcd_patch_skew\n"); | ||
940 | switch (plvds_chip_info->output_interface) { | ||
941 | case INTERFACE_DVP0: | ||
942 | lcd_patch_skew_dvp0(plvds_setting_info, plvds_chip_info); | ||
943 | break; | ||
944 | case INTERFACE_DVP1: | ||
945 | lcd_patch_skew_dvp1(plvds_setting_info, plvds_chip_info); | ||
946 | break; | ||
947 | case INTERFACE_DFP_LOW: | ||
948 | if (UNICHROME_P4M900 == viaparinfo->chip_info->gfx_chip_name) { | ||
949 | viafb_write_reg_mask(CR99, VIACR, 0x08, | ||
950 | BIT0 + BIT1 + BIT2 + BIT3); | ||
951 | } | ||
952 | break; | ||
953 | } | ||
954 | } | ||
955 | |||
956 | /* LCD Set Mode */ | ||
957 | void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, | ||
958 | struct lvds_setting_information *plvds_setting_info, | ||
959 | struct lvds_chip_information *plvds_chip_info) | ||
960 | { | ||
961 | int video_index = plvds_setting_info->lcd_panel_size; | ||
962 | int set_iga = plvds_setting_info->iga_path; | ||
963 | int mode_bpp = plvds_setting_info->bpp; | ||
964 | int viafb_load_reg_num = 0; | ||
965 | int reg_value = 0; | ||
966 | int set_hres, set_vres; | ||
967 | int panel_hres, panel_vres; | ||
968 | u32 pll_D_N; | ||
969 | int offset; | ||
970 | struct io_register *reg = NULL; | ||
971 | struct display_timing mode_crt_reg, panel_crt_reg; | ||
972 | struct crt_mode_table *panel_crt_table = NULL; | ||
973 | struct VideoModeTable *vmode_tbl = NULL; | ||
974 | |||
975 | DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n"); | ||
976 | /* Get mode table */ | ||
977 | mode_crt_reg = mode_crt_table->crtc; | ||
978 | /* Get panel table Pointer */ | ||
979 | vmode_tbl = viafb_get_modetbl_pointer(video_index); | ||
980 | panel_crt_table = vmode_tbl->crtc; | ||
981 | panel_crt_reg = panel_crt_table->crtc; | ||
982 | DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n"); | ||
983 | set_hres = plvds_setting_info->h_active; | ||
984 | set_vres = plvds_setting_info->v_active; | ||
985 | panel_hres = plvds_setting_info->lcd_panel_hres; | ||
986 | panel_vres = plvds_setting_info->lcd_panel_vres; | ||
987 | if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) | ||
988 | viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info); | ||
989 | plvds_setting_info->vclk = panel_crt_table->clk; | ||
990 | if (set_iga == IGA1) { | ||
991 | /* IGA1 doesn't have LCD scaling, so set it as centering. */ | ||
992 | viafb_load_crtc_timing(lcd_centering_timging | ||
993 | (mode_crt_reg, panel_crt_reg), IGA1); | ||
994 | } else { | ||
995 | /* Expansion */ | ||
996 | if ((plvds_setting_info->display_method == | ||
997 | LCD_EXPANDSION) & ((set_hres != panel_hres) | ||
998 | || (set_vres != panel_vres))) { | ||
999 | /* expansion timing IGA2 loaded panel set timing*/ | ||
1000 | viafb_load_crtc_timing(panel_crt_reg, IGA2); | ||
1001 | DEBUG_MSG(KERN_INFO "viafb_load_crtc_timing!!\n"); | ||
1002 | load_lcd_scaling(set_hres, set_vres, panel_hres, | ||
1003 | panel_vres); | ||
1004 | DEBUG_MSG(KERN_INFO "load_lcd_scaling!!\n"); | ||
1005 | } else { /* Centering */ | ||
1006 | /* centering timing IGA2 always loaded panel | ||
1007 | and mode releative timing */ | ||
1008 | viafb_load_crtc_timing(lcd_centering_timging | ||
1009 | (mode_crt_reg, panel_crt_reg), IGA2); | ||
1010 | viafb_write_reg_mask(CR79, VIACR, 0x00, | ||
1011 | BIT0 + BIT1 + BIT2); | ||
1012 | /* LCD scaling disabled */ | ||
1013 | } | ||
1014 | } | ||
1015 | |||
1016 | if (set_iga == IGA1_IGA2) { | ||
1017 | load_crtc_shadow_timing(mode_crt_reg, panel_crt_reg); | ||
1018 | /* Fill shadow registers */ | ||
1019 | |||
1020 | switch (plvds_setting_info->lcd_panel_id) { | ||
1021 | case LCD_PANEL_ID0_640X480: | ||
1022 | offset = 80; | ||
1023 | break; | ||
1024 | case LCD_PANEL_ID1_800X600: | ||
1025 | case LCD_PANEL_IDA_800X480: | ||
1026 | offset = 110; | ||
1027 | break; | ||
1028 | case LCD_PANEL_ID2_1024X768: | ||
1029 | offset = 150; | ||
1030 | break; | ||
1031 | case LCD_PANEL_ID3_1280X768: | ||
1032 | case LCD_PANEL_ID4_1280X1024: | ||
1033 | case LCD_PANEL_ID5_1400X1050: | ||
1034 | case LCD_PANEL_ID9_1280X800: | ||
1035 | offset = 190; | ||
1036 | break; | ||
1037 | case LCD_PANEL_ID6_1600X1200: | ||
1038 | offset = 250; | ||
1039 | break; | ||
1040 | case LCD_PANEL_ID7_1366X768: | ||
1041 | case LCD_PANEL_IDB_1360X768: | ||
1042 | offset = 212; | ||
1043 | break; | ||
1044 | default: | ||
1045 | offset = 140; | ||
1046 | break; | ||
1047 | } | ||
1048 | |||
1049 | /* Offset for simultaneous */ | ||
1050 | reg_value = offset; | ||
1051 | viafb_load_reg_num = offset_reg.iga2_offset_reg.reg_num; | ||
1052 | reg = offset_reg.iga2_offset_reg.reg; | ||
1053 | viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR); | ||
1054 | DEBUG_MSG(KERN_INFO "viafb_load_reg!!\n"); | ||
1055 | viafb_load_fetch_count_reg(set_hres, 4, IGA2); | ||
1056 | /* Fetch count for simultaneous */ | ||
1057 | } else { /* SAMM */ | ||
1058 | /* Offset for IGA2 only */ | ||
1059 | viafb_load_offset_reg(set_hres, mode_bpp / 8, set_iga); | ||
1060 | /* Fetch count for IGA2 only */ | ||
1061 | viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga); | ||
1062 | |||
1063 | if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266) | ||
1064 | && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)) | ||
1065 | viafb_load_FIFO_reg(set_iga, set_hres, set_vres); | ||
1066 | |||
1067 | viafb_set_color_depth(mode_bpp / 8, set_iga); | ||
1068 | } | ||
1069 | |||
1070 | fill_lcd_format(); | ||
1071 | |||
1072 | pll_D_N = viafb_get_clk_value(panel_crt_table[0].clk); | ||
1073 | DEBUG_MSG(KERN_INFO "PLL=0x%x", pll_D_N); | ||
1074 | viafb_set_vclock(pll_D_N, set_iga); | ||
1075 | |||
1076 | viafb_set_output_path(DEVICE_LCD, set_iga, | ||
1077 | plvds_chip_info->output_interface); | ||
1078 | lcd_patch_skew(plvds_setting_info, plvds_chip_info); | ||
1079 | |||
1080 | /* If K8M800, enable LCD Prefetch Mode. */ | ||
1081 | if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) | ||
1082 | || (UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name)) | ||
1083 | viafb_write_reg_mask(CR6A, VIACR, 0x01, BIT0); | ||
1084 | |||
1085 | load_lcd_patch_regs(set_hres, set_vres, | ||
1086 | plvds_setting_info->lcd_panel_id, set_iga); | ||
1087 | |||
1088 | DEBUG_MSG(KERN_INFO "load_lcd_patch_regs!!\n"); | ||
1089 | |||
1090 | /* Patch for non 32bit alignment mode */ | ||
1091 | via_pitch_alignment_patch_lcd(plvds_setting_info, plvds_chip_info); | ||
1092 | } | ||
1093 | |||
1094 | static void integrated_lvds_disable(struct lvds_setting_information | ||
1095 | *plvds_setting_info, | ||
1096 | struct lvds_chip_information *plvds_chip_info) | ||
1097 | { | ||
1098 | bool turn_off_first_powersequence = false; | ||
1099 | bool turn_off_second_powersequence = false; | ||
1100 | if (INTERFACE_LVDS0LVDS1 == plvds_chip_info->output_interface) | ||
1101 | turn_off_first_powersequence = true; | ||
1102 | if (INTERFACE_LVDS0 == plvds_chip_info->output_interface) | ||
1103 | turn_off_first_powersequence = true; | ||
1104 | if (INTERFACE_LVDS1 == plvds_chip_info->output_interface) | ||
1105 | turn_off_second_powersequence = true; | ||
1106 | if (turn_off_second_powersequence) { | ||
1107 | /* Use second power sequence control: */ | ||
1108 | |||
1109 | /* Turn off power sequence. */ | ||
1110 | viafb_write_reg_mask(CRD4, VIACR, 0, BIT1); | ||
1111 | |||
1112 | /* Turn off back light. */ | ||
1113 | viafb_write_reg_mask(CRD3, VIACR, 0xC0, BIT6 + BIT7); | ||
1114 | } | ||
1115 | if (turn_off_first_powersequence) { | ||
1116 | /* Use first power sequence control: */ | ||
1117 | |||
1118 | /* Turn off power sequence. */ | ||
1119 | viafb_write_reg_mask(CR6A, VIACR, 0, BIT3); | ||
1120 | |||
1121 | /* Turn off back light. */ | ||
1122 | viafb_write_reg_mask(CR91, VIACR, 0xC0, BIT6 + BIT7); | ||
1123 | } | ||
1124 | |||
1125 | /* Turn DFP High/Low Pad off. */ | ||
1126 | viafb_write_reg_mask(SR2A, VIASR, 0, BIT0 + BIT1 + BIT2 + BIT3); | ||
1127 | |||
1128 | /* Power off LVDS channel. */ | ||
1129 | switch (plvds_chip_info->output_interface) { | ||
1130 | case INTERFACE_LVDS0: | ||
1131 | { | ||
1132 | viafb_write_reg_mask(CRD2, VIACR, 0x80, BIT7); | ||
1133 | break; | ||
1134 | } | ||
1135 | |||
1136 | case INTERFACE_LVDS1: | ||
1137 | { | ||
1138 | viafb_write_reg_mask(CRD2, VIACR, 0x40, BIT6); | ||
1139 | break; | ||
1140 | } | ||
1141 | |||
1142 | case INTERFACE_LVDS0LVDS1: | ||
1143 | { | ||
1144 | viafb_write_reg_mask(CRD2, VIACR, 0xC0, BIT6 + BIT7); | ||
1145 | break; | ||
1146 | } | ||
1147 | } | ||
1148 | } | ||
1149 | |||
1150 | static void integrated_lvds_enable(struct lvds_setting_information | ||
1151 | *plvds_setting_info, | ||
1152 | struct lvds_chip_information *plvds_chip_info) | ||
1153 | { | ||
1154 | bool turn_on_first_powersequence = false; | ||
1155 | bool turn_on_second_powersequence = false; | ||
1156 | |||
1157 | DEBUG_MSG(KERN_INFO "integrated_lvds_enable, out_interface:%d\n", | ||
1158 | plvds_chip_info->output_interface); | ||
1159 | if (plvds_setting_info->lcd_mode == LCD_SPWG) | ||
1160 | viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT0 + BIT1); | ||
1161 | else | ||
1162 | viafb_write_reg_mask(CRD2, VIACR, 0x03, BIT0 + BIT1); | ||
1163 | if (INTERFACE_LVDS0LVDS1 == plvds_chip_info->output_interface) | ||
1164 | turn_on_first_powersequence = true; | ||
1165 | if (INTERFACE_LVDS0 == plvds_chip_info->output_interface) | ||
1166 | turn_on_first_powersequence = true; | ||
1167 | if (INTERFACE_LVDS1 == plvds_chip_info->output_interface) | ||
1168 | turn_on_second_powersequence = true; | ||
1169 | |||
1170 | if (turn_on_second_powersequence) { | ||
1171 | /* Use second power sequence control: */ | ||
1172 | |||
1173 | /* Use hardware control power sequence. */ | ||
1174 | viafb_write_reg_mask(CRD3, VIACR, 0, BIT0); | ||
1175 | |||
1176 | /* Turn on back light. */ | ||
1177 | viafb_write_reg_mask(CRD3, VIACR, 0, BIT6 + BIT7); | ||
1178 | |||
1179 | /* Turn on hardware power sequence. */ | ||
1180 | viafb_write_reg_mask(CRD4, VIACR, 0x02, BIT1); | ||
1181 | } | ||
1182 | if (turn_on_first_powersequence) { | ||
1183 | /* Use first power sequence control: */ | ||
1184 | |||
1185 | /* Use hardware control power sequence. */ | ||
1186 | viafb_write_reg_mask(CR91, VIACR, 0, BIT0); | ||
1187 | |||
1188 | /* Turn on back light. */ | ||
1189 | viafb_write_reg_mask(CR91, VIACR, 0, BIT6 + BIT7); | ||
1190 | |||
1191 | /* Turn on hardware power sequence. */ | ||
1192 | viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3); | ||
1193 | } | ||
1194 | |||
1195 | /* Turn DFP High/Low pad on. */ | ||
1196 | viafb_write_reg_mask(SR2A, VIASR, 0x0F, BIT0 + BIT1 + BIT2 + BIT3); | ||
1197 | |||
1198 | /* Power on LVDS channel. */ | ||
1199 | switch (plvds_chip_info->output_interface) { | ||
1200 | case INTERFACE_LVDS0: | ||
1201 | { | ||
1202 | viafb_write_reg_mask(CRD2, VIACR, 0, BIT7); | ||
1203 | break; | ||
1204 | } | ||
1205 | |||
1206 | case INTERFACE_LVDS1: | ||
1207 | { | ||
1208 | viafb_write_reg_mask(CRD2, VIACR, 0, BIT6); | ||
1209 | break; | ||
1210 | } | ||
1211 | |||
1212 | case INTERFACE_LVDS0LVDS1: | ||
1213 | { | ||
1214 | viafb_write_reg_mask(CRD2, VIACR, 0, BIT6 + BIT7); | ||
1215 | break; | ||
1216 | } | ||
1217 | } | ||
1218 | } | ||
1219 | |||
1220 | void viafb_lcd_disable(void) | ||
1221 | { | ||
1222 | |||
1223 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) { | ||
1224 | lcd_powersequence_off(); | ||
1225 | /* DI1 pad off */ | ||
1226 | viafb_write_reg_mask(SR1E, VIASR, 0x00, 0x30); | ||
1227 | } else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) { | ||
1228 | if (viafb_LCD2_ON | ||
1229 | && (INTEGRATED_LVDS == | ||
1230 | viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name)) | ||
1231 | integrated_lvds_disable(viaparinfo->lvds_setting_info, | ||
1232 | &viaparinfo->chip_info->lvds_chip_info2); | ||
1233 | if (INTEGRATED_LVDS == | ||
1234 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) | ||
1235 | integrated_lvds_disable(viaparinfo->lvds_setting_info, | ||
1236 | &viaparinfo->chip_info->lvds_chip_info); | ||
1237 | if (VT1636_LVDS == viaparinfo->chip_info-> | ||
1238 | lvds_chip_info.lvds_chip_name) | ||
1239 | viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info, | ||
1240 | &viaparinfo->chip_info->lvds_chip_info); | ||
1241 | } else if (VT1636_LVDS == | ||
1242 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) { | ||
1243 | viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info, | ||
1244 | &viaparinfo->chip_info->lvds_chip_info); | ||
1245 | } else { | ||
1246 | /* DFP-HL pad off */ | ||
1247 | viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x0F); | ||
1248 | /* Backlight off */ | ||
1249 | viafb_write_reg_mask(SR3D, VIASR, 0x00, 0x20); | ||
1250 | /* 24 bit DI data paht off */ | ||
1251 | viafb_write_reg_mask(CR91, VIACR, 0x80, 0x80); | ||
1252 | /* Simultaneout disabled */ | ||
1253 | viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08); | ||
1254 | } | ||
1255 | |||
1256 | /* Disable expansion bit */ | ||
1257 | viafb_write_reg_mask(CR79, VIACR, 0x00, 0x01); | ||
1258 | /* CRT path set to IGA1 */ | ||
1259 | viafb_write_reg_mask(SR16, VIASR, 0x00, 0x40); | ||
1260 | /* Simultaneout disabled */ | ||
1261 | viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08); | ||
1262 | /* IGA2 path disabled */ | ||
1263 | viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x80); | ||
1264 | |||
1265 | } | ||
1266 | |||
1267 | void viafb_lcd_enable(void) | ||
1268 | { | ||
1269 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) { | ||
1270 | /* DI1 pad on */ | ||
1271 | viafb_write_reg_mask(SR1E, VIASR, 0x30, 0x30); | ||
1272 | lcd_powersequence_on(); | ||
1273 | } else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) { | ||
1274 | if (viafb_LCD2_ON && (INTEGRATED_LVDS == | ||
1275 | viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name)) | ||
1276 | integrated_lvds_enable(viaparinfo->lvds_setting_info2, \ | ||
1277 | &viaparinfo->chip_info->lvds_chip_info2); | ||
1278 | if (INTEGRATED_LVDS == | ||
1279 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) | ||
1280 | integrated_lvds_enable(viaparinfo->lvds_setting_info, | ||
1281 | &viaparinfo->chip_info->lvds_chip_info); | ||
1282 | if (VT1636_LVDS == viaparinfo->chip_info-> | ||
1283 | lvds_chip_info.lvds_chip_name) | ||
1284 | viafb_enable_lvds_vt1636(viaparinfo-> | ||
1285 | lvds_setting_info, &viaparinfo->chip_info-> | ||
1286 | lvds_chip_info); | ||
1287 | } else if (VT1636_LVDS == | ||
1288 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) { | ||
1289 | viafb_enable_lvds_vt1636(viaparinfo->lvds_setting_info, | ||
1290 | &viaparinfo->chip_info->lvds_chip_info); | ||
1291 | } else { | ||
1292 | /* DFP-HL pad on */ | ||
1293 | viafb_write_reg_mask(SR2A, VIASR, 0x0F, 0x0F); | ||
1294 | /* Backlight on */ | ||
1295 | viafb_write_reg_mask(SR3D, VIASR, 0x20, 0x20); | ||
1296 | /* 24 bit DI data paht on */ | ||
1297 | viafb_write_reg_mask(CR91, VIACR, 0x00, 0x80); | ||
1298 | |||
1299 | /* Set data source selection bit by iga path */ | ||
1300 | if (viaparinfo->lvds_setting_info->iga_path == IGA1) { | ||
1301 | /* DFP-H set to IGA1 */ | ||
1302 | viafb_write_reg_mask(CR97, VIACR, 0x00, 0x10); | ||
1303 | /* DFP-L set to IGA1 */ | ||
1304 | viafb_write_reg_mask(CR99, VIACR, 0x00, 0x10); | ||
1305 | } else { | ||
1306 | /* DFP-H set to IGA2 */ | ||
1307 | viafb_write_reg_mask(CR97, VIACR, 0x10, 0x10); | ||
1308 | /* DFP-L set to IGA2 */ | ||
1309 | viafb_write_reg_mask(CR99, VIACR, 0x10, 0x10); | ||
1310 | } | ||
1311 | /* LCD enabled */ | ||
1312 | viafb_write_reg_mask(CR6A, VIACR, 0x48, 0x48); | ||
1313 | } | ||
1314 | |||
1315 | if ((viaparinfo->lvds_setting_info->iga_path == IGA1) | ||
1316 | || (viaparinfo->lvds_setting_info->iga_path == IGA1_IGA2)) { | ||
1317 | /* CRT path set to IGA2 */ | ||
1318 | viafb_write_reg_mask(SR16, VIASR, 0x40, 0x40); | ||
1319 | /* IGA2 path disabled */ | ||
1320 | viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x80); | ||
1321 | /* IGA2 path enabled */ | ||
1322 | } else { /* IGA2 */ | ||
1323 | viafb_write_reg_mask(CR6A, VIACR, 0x80, 0x80); | ||
1324 | } | ||
1325 | |||
1326 | } | ||
1327 | |||
1328 | static void lcd_powersequence_off(void) | ||
1329 | { | ||
1330 | int i, mask, data; | ||
1331 | |||
1332 | /* Software control power sequence */ | ||
1333 | viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11); | ||
1334 | |||
1335 | for (i = 0; i < 3; i++) { | ||
1336 | mask = PowerSequenceOff[0][i]; | ||
1337 | data = PowerSequenceOff[1][i] & mask; | ||
1338 | viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask); | ||
1339 | udelay(PowerSequenceOff[2][i]); | ||
1340 | } | ||
1341 | |||
1342 | /* Disable LCD */ | ||
1343 | viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x08); | ||
1344 | } | ||
1345 | |||
1346 | static void lcd_powersequence_on(void) | ||
1347 | { | ||
1348 | int i, mask, data; | ||
1349 | |||
1350 | /* Software control power sequence */ | ||
1351 | viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11); | ||
1352 | |||
1353 | /* Enable LCD */ | ||
1354 | viafb_write_reg_mask(CR6A, VIACR, 0x08, 0x08); | ||
1355 | |||
1356 | for (i = 0; i < 3; i++) { | ||
1357 | mask = PowerSequenceOn[0][i]; | ||
1358 | data = PowerSequenceOn[1][i] & mask; | ||
1359 | viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask); | ||
1360 | udelay(PowerSequenceOn[2][i]); | ||
1361 | } | ||
1362 | |||
1363 | udelay(1); | ||
1364 | } | ||
1365 | |||
1366 | static void fill_lcd_format(void) | ||
1367 | { | ||
1368 | u8 bdithering = 0, bdual = 0; | ||
1369 | |||
1370 | if (viaparinfo->lvds_setting_info->device_lcd_dualedge) | ||
1371 | bdual = BIT4; | ||
1372 | if (viaparinfo->lvds_setting_info->LCDDithering) | ||
1373 | bdithering = BIT0; | ||
1374 | /* Dual & Dithering */ | ||
1375 | viafb_write_reg_mask(CR88, VIACR, (bdithering | bdual), BIT4 + BIT0); | ||
1376 | } | ||
1377 | |||
1378 | static void check_diport_of_integrated_lvds( | ||
1379 | struct lvds_chip_information *plvds_chip_info, | ||
1380 | struct lvds_setting_information | ||
1381 | *plvds_setting_info) | ||
1382 | { | ||
1383 | /* Determine LCD DI Port by hardware layout. */ | ||
1384 | switch (viafb_display_hardware_layout) { | ||
1385 | case HW_LAYOUT_LCD_ONLY: | ||
1386 | { | ||
1387 | if (plvds_setting_info->device_lcd_dualedge) { | ||
1388 | plvds_chip_info->output_interface = | ||
1389 | INTERFACE_LVDS0LVDS1; | ||
1390 | } else { | ||
1391 | plvds_chip_info->output_interface = | ||
1392 | INTERFACE_LVDS0; | ||
1393 | } | ||
1394 | |||
1395 | break; | ||
1396 | } | ||
1397 | |||
1398 | case HW_LAYOUT_DVI_ONLY: | ||
1399 | { | ||
1400 | plvds_chip_info->output_interface = INTERFACE_NONE; | ||
1401 | break; | ||
1402 | } | ||
1403 | |||
1404 | case HW_LAYOUT_LCD1_LCD2: | ||
1405 | case HW_LAYOUT_LCD_EXTERNAL_LCD2: | ||
1406 | { | ||
1407 | plvds_chip_info->output_interface = | ||
1408 | INTERFACE_LVDS0LVDS1; | ||
1409 | break; | ||
1410 | } | ||
1411 | |||
1412 | case HW_LAYOUT_LCD_DVI: | ||
1413 | { | ||
1414 | plvds_chip_info->output_interface = INTERFACE_LVDS1; | ||
1415 | break; | ||
1416 | } | ||
1417 | |||
1418 | default: | ||
1419 | { | ||
1420 | plvds_chip_info->output_interface = INTERFACE_LVDS1; | ||
1421 | break; | ||
1422 | } | ||
1423 | } | ||
1424 | |||
1425 | DEBUG_MSG(KERN_INFO | ||
1426 | "Display Hardware Layout: 0x%x, LCD DI Port: 0x%x\n", | ||
1427 | viafb_display_hardware_layout, | ||
1428 | plvds_chip_info->output_interface); | ||
1429 | } | ||
1430 | |||
1431 | void viafb_init_lvds_output_interface(struct lvds_chip_information | ||
1432 | *plvds_chip_info, | ||
1433 | struct lvds_setting_information | ||
1434 | *plvds_setting_info) | ||
1435 | { | ||
1436 | if (INTERFACE_NONE != plvds_chip_info->output_interface) { | ||
1437 | /*Do nothing, lcd port is specified by module parameter */ | ||
1438 | return; | ||
1439 | } | ||
1440 | |||
1441 | switch (plvds_chip_info->lvds_chip_name) { | ||
1442 | |||
1443 | case VT1636_LVDS: | ||
1444 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
1445 | case UNICHROME_CX700: | ||
1446 | plvds_chip_info->output_interface = INTERFACE_DVP1; | ||
1447 | break; | ||
1448 | case UNICHROME_CN700: | ||
1449 | plvds_chip_info->output_interface = INTERFACE_DFP_LOW; | ||
1450 | break; | ||
1451 | default: | ||
1452 | plvds_chip_info->output_interface = INTERFACE_DVP0; | ||
1453 | break; | ||
1454 | } | ||
1455 | break; | ||
1456 | |||
1457 | case INTEGRATED_LVDS: | ||
1458 | check_diport_of_integrated_lvds(plvds_chip_info, | ||
1459 | plvds_setting_info); | ||
1460 | break; | ||
1461 | |||
1462 | default: | ||
1463 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
1464 | case UNICHROME_K8M890: | ||
1465 | case UNICHROME_P4M900: | ||
1466 | case UNICHROME_P4M890: | ||
1467 | plvds_chip_info->output_interface = INTERFACE_DFP_LOW; | ||
1468 | break; | ||
1469 | default: | ||
1470 | plvds_chip_info->output_interface = INTERFACE_DFP; | ||
1471 | break; | ||
1472 | } | ||
1473 | break; | ||
1474 | } | ||
1475 | } | ||
1476 | |||
1477 | static struct display_timing lcd_centering_timging(struct display_timing | ||
1478 | mode_crt_reg, | ||
1479 | struct display_timing panel_crt_reg) | ||
1480 | { | ||
1481 | struct display_timing crt_reg; | ||
1482 | |||
1483 | crt_reg.hor_total = panel_crt_reg.hor_total; | ||
1484 | crt_reg.hor_addr = mode_crt_reg.hor_addr; | ||
1485 | crt_reg.hor_blank_start = | ||
1486 | (panel_crt_reg.hor_addr - mode_crt_reg.hor_addr) / 2 + | ||
1487 | crt_reg.hor_addr; | ||
1488 | crt_reg.hor_blank_end = panel_crt_reg.hor_blank_end; | ||
1489 | crt_reg.hor_sync_start = | ||
1490 | (panel_crt_reg.hor_sync_start - | ||
1491 | panel_crt_reg.hor_blank_start) + crt_reg.hor_blank_start; | ||
1492 | crt_reg.hor_sync_end = panel_crt_reg.hor_sync_end; | ||
1493 | |||
1494 | crt_reg.ver_total = panel_crt_reg.ver_total; | ||
1495 | crt_reg.ver_addr = mode_crt_reg.ver_addr; | ||
1496 | crt_reg.ver_blank_start = | ||
1497 | (panel_crt_reg.ver_addr - mode_crt_reg.ver_addr) / 2 + | ||
1498 | crt_reg.ver_addr; | ||
1499 | crt_reg.ver_blank_end = panel_crt_reg.ver_blank_end; | ||
1500 | crt_reg.ver_sync_start = | ||
1501 | (panel_crt_reg.ver_sync_start - | ||
1502 | panel_crt_reg.ver_blank_start) + crt_reg.ver_blank_start; | ||
1503 | crt_reg.ver_sync_end = panel_crt_reg.ver_sync_end; | ||
1504 | |||
1505 | return crt_reg; | ||
1506 | } | ||
1507 | |||
1508 | static void load_crtc_shadow_timing(struct display_timing mode_timing, | ||
1509 | struct display_timing panel_timing) | ||
1510 | { | ||
1511 | struct io_register *reg = NULL; | ||
1512 | int i; | ||
1513 | int viafb_load_reg_Num = 0; | ||
1514 | int reg_value = 0; | ||
1515 | |||
1516 | if (viaparinfo->lvds_setting_info->display_method == LCD_EXPANDSION) { | ||
1517 | /* Expansion */ | ||
1518 | for (i = 12; i < 20; i++) { | ||
1519 | switch (i) { | ||
1520 | case H_TOTAL_SHADOW_INDEX: | ||
1521 | reg_value = | ||
1522 | IGA2_HOR_TOTAL_SHADOW_FORMULA | ||
1523 | (panel_timing.hor_total); | ||
1524 | viafb_load_reg_Num = | ||
1525 | iga2_shadow_crtc_reg.hor_total_shadow. | ||
1526 | reg_num; | ||
1527 | reg = iga2_shadow_crtc_reg.hor_total_shadow.reg; | ||
1528 | break; | ||
1529 | case H_BLANK_END_SHADOW_INDEX: | ||
1530 | reg_value = | ||
1531 | IGA2_HOR_BLANK_END_SHADOW_FORMULA | ||
1532 | (panel_timing.hor_blank_start, | ||
1533 | panel_timing.hor_blank_end); | ||
1534 | viafb_load_reg_Num = | ||
1535 | iga2_shadow_crtc_reg. | ||
1536 | hor_blank_end_shadow.reg_num; | ||
1537 | reg = | ||
1538 | iga2_shadow_crtc_reg. | ||
1539 | hor_blank_end_shadow.reg; | ||
1540 | break; | ||
1541 | case V_TOTAL_SHADOW_INDEX: | ||
1542 | reg_value = | ||
1543 | IGA2_VER_TOTAL_SHADOW_FORMULA | ||
1544 | (panel_timing.ver_total); | ||
1545 | viafb_load_reg_Num = | ||
1546 | iga2_shadow_crtc_reg.ver_total_shadow. | ||
1547 | reg_num; | ||
1548 | reg = iga2_shadow_crtc_reg.ver_total_shadow.reg; | ||
1549 | break; | ||
1550 | case V_ADDR_SHADOW_INDEX: | ||
1551 | reg_value = | ||
1552 | IGA2_VER_ADDR_SHADOW_FORMULA | ||
1553 | (panel_timing.ver_addr); | ||
1554 | viafb_load_reg_Num = | ||
1555 | iga2_shadow_crtc_reg.ver_addr_shadow. | ||
1556 | reg_num; | ||
1557 | reg = iga2_shadow_crtc_reg.ver_addr_shadow.reg; | ||
1558 | break; | ||
1559 | case V_BLANK_SATRT_SHADOW_INDEX: | ||
1560 | reg_value = | ||
1561 | IGA2_VER_BLANK_START_SHADOW_FORMULA | ||
1562 | (panel_timing.ver_blank_start); | ||
1563 | viafb_load_reg_Num = | ||
1564 | iga2_shadow_crtc_reg. | ||
1565 | ver_blank_start_shadow.reg_num; | ||
1566 | reg = | ||
1567 | iga2_shadow_crtc_reg. | ||
1568 | ver_blank_start_shadow.reg; | ||
1569 | break; | ||
1570 | case V_BLANK_END_SHADOW_INDEX: | ||
1571 | reg_value = | ||
1572 | IGA2_VER_BLANK_END_SHADOW_FORMULA | ||
1573 | (panel_timing.ver_blank_start, | ||
1574 | panel_timing.ver_blank_end); | ||
1575 | viafb_load_reg_Num = | ||
1576 | iga2_shadow_crtc_reg. | ||
1577 | ver_blank_end_shadow.reg_num; | ||
1578 | reg = | ||
1579 | iga2_shadow_crtc_reg. | ||
1580 | ver_blank_end_shadow.reg; | ||
1581 | break; | ||
1582 | case V_SYNC_SATRT_SHADOW_INDEX: | ||
1583 | reg_value = | ||
1584 | IGA2_VER_SYNC_START_SHADOW_FORMULA | ||
1585 | (panel_timing.ver_sync_start); | ||
1586 | viafb_load_reg_Num = | ||
1587 | iga2_shadow_crtc_reg. | ||
1588 | ver_sync_start_shadow.reg_num; | ||
1589 | reg = | ||
1590 | iga2_shadow_crtc_reg. | ||
1591 | ver_sync_start_shadow.reg; | ||
1592 | break; | ||
1593 | case V_SYNC_END_SHADOW_INDEX: | ||
1594 | reg_value = | ||
1595 | IGA2_VER_SYNC_END_SHADOW_FORMULA | ||
1596 | (panel_timing.ver_sync_start, | ||
1597 | panel_timing.ver_sync_end); | ||
1598 | viafb_load_reg_Num = | ||
1599 | iga2_shadow_crtc_reg. | ||
1600 | ver_sync_end_shadow.reg_num; | ||
1601 | reg = | ||
1602 | iga2_shadow_crtc_reg. | ||
1603 | ver_sync_end_shadow.reg; | ||
1604 | break; | ||
1605 | } | ||
1606 | viafb_load_reg(reg_value, | ||
1607 | viafb_load_reg_Num, reg, VIACR); | ||
1608 | } | ||
1609 | } else { /* Centering */ | ||
1610 | for (i = 12; i < 20; i++) { | ||
1611 | switch (i) { | ||
1612 | case H_TOTAL_SHADOW_INDEX: | ||
1613 | reg_value = | ||
1614 | IGA2_HOR_TOTAL_SHADOW_FORMULA | ||
1615 | (panel_timing.hor_total); | ||
1616 | viafb_load_reg_Num = | ||
1617 | iga2_shadow_crtc_reg.hor_total_shadow. | ||
1618 | reg_num; | ||
1619 | reg = iga2_shadow_crtc_reg.hor_total_shadow.reg; | ||
1620 | break; | ||
1621 | case H_BLANK_END_SHADOW_INDEX: | ||
1622 | reg_value = | ||
1623 | IGA2_HOR_BLANK_END_SHADOW_FORMULA | ||
1624 | (panel_timing.hor_blank_start, | ||
1625 | panel_timing.hor_blank_end); | ||
1626 | viafb_load_reg_Num = | ||
1627 | iga2_shadow_crtc_reg. | ||
1628 | hor_blank_end_shadow.reg_num; | ||
1629 | reg = | ||
1630 | iga2_shadow_crtc_reg. | ||
1631 | hor_blank_end_shadow.reg; | ||
1632 | break; | ||
1633 | case V_TOTAL_SHADOW_INDEX: | ||
1634 | reg_value = | ||
1635 | IGA2_VER_TOTAL_SHADOW_FORMULA | ||
1636 | (panel_timing.ver_total); | ||
1637 | viafb_load_reg_Num = | ||
1638 | iga2_shadow_crtc_reg.ver_total_shadow. | ||
1639 | reg_num; | ||
1640 | reg = iga2_shadow_crtc_reg.ver_total_shadow.reg; | ||
1641 | break; | ||
1642 | case V_ADDR_SHADOW_INDEX: | ||
1643 | reg_value = | ||
1644 | IGA2_VER_ADDR_SHADOW_FORMULA | ||
1645 | (mode_timing.ver_addr); | ||
1646 | viafb_load_reg_Num = | ||
1647 | iga2_shadow_crtc_reg.ver_addr_shadow. | ||
1648 | reg_num; | ||
1649 | reg = iga2_shadow_crtc_reg.ver_addr_shadow.reg; | ||
1650 | break; | ||
1651 | case V_BLANK_SATRT_SHADOW_INDEX: | ||
1652 | reg_value = | ||
1653 | IGA2_VER_BLANK_START_SHADOW_FORMULA | ||
1654 | (mode_timing.ver_blank_start); | ||
1655 | viafb_load_reg_Num = | ||
1656 | iga2_shadow_crtc_reg. | ||
1657 | ver_blank_start_shadow.reg_num; | ||
1658 | reg = | ||
1659 | iga2_shadow_crtc_reg. | ||
1660 | ver_blank_start_shadow.reg; | ||
1661 | break; | ||
1662 | case V_BLANK_END_SHADOW_INDEX: | ||
1663 | reg_value = | ||
1664 | IGA2_VER_BLANK_END_SHADOW_FORMULA | ||
1665 | (panel_timing.ver_blank_start, | ||
1666 | panel_timing.ver_blank_end); | ||
1667 | viafb_load_reg_Num = | ||
1668 | iga2_shadow_crtc_reg. | ||
1669 | ver_blank_end_shadow.reg_num; | ||
1670 | reg = | ||
1671 | iga2_shadow_crtc_reg. | ||
1672 | ver_blank_end_shadow.reg; | ||
1673 | break; | ||
1674 | case V_SYNC_SATRT_SHADOW_INDEX: | ||
1675 | reg_value = | ||
1676 | IGA2_VER_SYNC_START_SHADOW_FORMULA( | ||
1677 | (panel_timing.ver_sync_start - | ||
1678 | panel_timing.ver_blank_start) + | ||
1679 | (panel_timing.ver_addr - | ||
1680 | mode_timing.ver_addr) / 2 + | ||
1681 | mode_timing.ver_addr); | ||
1682 | viafb_load_reg_Num = | ||
1683 | iga2_shadow_crtc_reg.ver_sync_start_shadow. | ||
1684 | reg_num; | ||
1685 | reg = | ||
1686 | iga2_shadow_crtc_reg.ver_sync_start_shadow. | ||
1687 | reg; | ||
1688 | break; | ||
1689 | case V_SYNC_END_SHADOW_INDEX: | ||
1690 | reg_value = | ||
1691 | IGA2_VER_SYNC_END_SHADOW_FORMULA( | ||
1692 | (panel_timing.ver_sync_start - | ||
1693 | panel_timing.ver_blank_start) + | ||
1694 | (panel_timing.ver_addr - | ||
1695 | mode_timing.ver_addr) / 2 + | ||
1696 | mode_timing.ver_addr, | ||
1697 | panel_timing.ver_sync_end); | ||
1698 | viafb_load_reg_Num = | ||
1699 | iga2_shadow_crtc_reg.ver_sync_end_shadow. | ||
1700 | reg_num; | ||
1701 | reg = | ||
1702 | iga2_shadow_crtc_reg.ver_sync_end_shadow. | ||
1703 | reg; | ||
1704 | break; | ||
1705 | } | ||
1706 | viafb_load_reg(reg_value, | ||
1707 | viafb_load_reg_Num, reg, VIACR); | ||
1708 | } | ||
1709 | } | ||
1710 | } | ||
1711 | |||
1712 | bool viafb_lcd_get_mobile_state(bool *mobile) | ||
1713 | { | ||
1714 | unsigned char *romptr, *tableptr; | ||
1715 | u8 core_base; | ||
1716 | unsigned char *biosptr; | ||
1717 | /* Rom address */ | ||
1718 | u32 romaddr = 0x000C0000; | ||
1719 | u16 start_pattern = 0; | ||
1720 | |||
1721 | biosptr = ioremap(romaddr, 0x10000); | ||
1722 | |||
1723 | memcpy(&start_pattern, biosptr, 2); | ||
1724 | /* Compare pattern */ | ||
1725 | if (start_pattern == 0xAA55) { | ||
1726 | /* Get the start of Table */ | ||
1727 | /* 0x1B means BIOS offset position */ | ||
1728 | romptr = biosptr + 0x1B; | ||
1729 | tableptr = biosptr + *((u16 *) romptr); | ||
1730 | |||
1731 | /* Get the start of biosver structure */ | ||
1732 | /* 18 means BIOS version position. */ | ||
1733 | romptr = tableptr + 18; | ||
1734 | romptr = biosptr + *((u16 *) romptr); | ||
1735 | |||
1736 | /* The offset should be 44, but the | ||
1737 | actual image is less three char. */ | ||
1738 | /* pRom += 44; */ | ||
1739 | romptr += 41; | ||
1740 | |||
1741 | core_base = *romptr++; | ||
1742 | |||
1743 | if (core_base & 0x8) | ||
1744 | *mobile = false; | ||
1745 | else | ||
1746 | *mobile = true; | ||
1747 | /* release memory */ | ||
1748 | iounmap(biosptr); | ||
1749 | |||
1750 | return true; | ||
1751 | } else { | ||
1752 | iounmap(biosptr); | ||
1753 | return false; | ||
1754 | } | ||
1755 | } | ||
1756 | |||
1757 | static void viafb_load_scaling_factor_for_p4m900(int set_hres, | ||
1758 | int set_vres, int panel_hres, int panel_vres) | ||
1759 | { | ||
1760 | int h_scaling_factor; | ||
1761 | int v_scaling_factor; | ||
1762 | u8 cra2 = 0; | ||
1763 | u8 cr77 = 0; | ||
1764 | u8 cr78 = 0; | ||
1765 | u8 cr79 = 0; | ||
1766 | u8 cr9f = 0; | ||
1767 | /* Check if expansion for horizontal */ | ||
1768 | if (set_hres < panel_hres) { | ||
1769 | /* Load Horizontal Scaling Factor */ | ||
1770 | |||
1771 | /* For VIA_K8M800 or later chipsets. */ | ||
1772 | h_scaling_factor = | ||
1773 | K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres); | ||
1774 | /* HSCaleFactor[1:0] at CR9F[1:0] */ | ||
1775 | cr9f = h_scaling_factor & 0x0003; | ||
1776 | /* HSCaleFactor[9:2] at CR77[7:0] */ | ||
1777 | cr77 = (h_scaling_factor & 0x03FC) >> 2; | ||
1778 | /* HSCaleFactor[11:10] at CR79[5:4] */ | ||
1779 | cr79 = (h_scaling_factor & 0x0C00) >> 10; | ||
1780 | cr79 <<= 4; | ||
1781 | |||
1782 | /* Horizontal scaling enabled */ | ||
1783 | cra2 = 0xC0; | ||
1784 | |||
1785 | DEBUG_MSG(KERN_INFO "Horizontal Scaling value = %d\n", | ||
1786 | h_scaling_factor); | ||
1787 | } else { | ||
1788 | /* Horizontal scaling disabled */ | ||
1789 | cra2 = 0x00; | ||
1790 | } | ||
1791 | |||
1792 | /* Check if expansion for vertical */ | ||
1793 | if (set_vres < panel_vres) { | ||
1794 | /* Load Vertical Scaling Factor */ | ||
1795 | |||
1796 | /* For VIA_K8M800 or later chipsets. */ | ||
1797 | v_scaling_factor = | ||
1798 | K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres); | ||
1799 | |||
1800 | /* Vertical scaling enabled */ | ||
1801 | cra2 |= 0x08; | ||
1802 | /* VSCaleFactor[0] at CR79[3] */ | ||
1803 | cr79 |= ((v_scaling_factor & 0x0001) << 3); | ||
1804 | /* VSCaleFactor[8:1] at CR78[7:0] */ | ||
1805 | cr78 |= (v_scaling_factor & 0x01FE) >> 1; | ||
1806 | /* VSCaleFactor[10:9] at CR79[7:6] */ | ||
1807 | cr79 |= ((v_scaling_factor & 0x0600) >> 9) << 6; | ||
1808 | |||
1809 | DEBUG_MSG(KERN_INFO "Vertical Scaling value = %d\n", | ||
1810 | v_scaling_factor); | ||
1811 | } else { | ||
1812 | /* Vertical scaling disabled */ | ||
1813 | cra2 |= 0x00; | ||
1814 | } | ||
1815 | |||
1816 | viafb_write_reg_mask(CRA2, VIACR, cra2, BIT3 + BIT6 + BIT7); | ||
1817 | viafb_write_reg_mask(CR77, VIACR, cr77, 0xFF); | ||
1818 | viafb_write_reg_mask(CR78, VIACR, cr78, 0xFF); | ||
1819 | viafb_write_reg_mask(CR79, VIACR, cr79, 0xF8); | ||
1820 | viafb_write_reg_mask(CR9F, VIACR, cr9f, BIT0 + BIT1); | ||
1821 | } | ||
diff --git a/drivers/video/via/lcd.h b/drivers/video/via/lcd.h new file mode 100644 index 000000000000..071f47cf5be1 --- /dev/null +++ b/drivers/video/via/lcd.h | |||
@@ -0,0 +1,94 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | #ifndef __LCD_H__ | ||
22 | #define __LCD_H__ | ||
23 | |||
24 | /*Definition TMDS Device ID register*/ | ||
25 | #define VT1631_DEVICE_ID_REG 0x02 | ||
26 | #define VT1631_DEVICE_ID 0x92 | ||
27 | |||
28 | #define VT3271_DEVICE_ID_REG 0x02 | ||
29 | #define VT3271_DEVICE_ID 0x71 | ||
30 | |||
31 | #define GET_LCD_SIZE_BY_SYSTEM_BIOS 0x01 | ||
32 | #define GET_LCD_SIZE_BY_VGA_BIOS 0x02 | ||
33 | #define GET_LCD_SZIE_BY_HW_STRAPPING 0x03 | ||
34 | #define GET_LCD_SIZE_BY_USER_SETTING 0x04 | ||
35 | |||
36 | /* Definition DVI Panel ID*/ | ||
37 | /* Resolution: 640x480, Channel: single, Dithering: Enable */ | ||
38 | #define LCD_PANEL_ID0_640X480 0x00 | ||
39 | /* Resolution: 800x600, Channel: single, Dithering: Enable */ | ||
40 | #define LCD_PANEL_ID1_800X600 0x01 | ||
41 | /* Resolution: 1024x768, Channel: single, Dithering: Enable */ | ||
42 | #define LCD_PANEL_ID2_1024X768 0x02 | ||
43 | /* Resolution: 1280x768, Channel: single, Dithering: Enable */ | ||
44 | #define LCD_PANEL_ID3_1280X768 0x03 | ||
45 | /* Resolution: 1280x1024, Channel: dual, Dithering: Enable */ | ||
46 | #define LCD_PANEL_ID4_1280X1024 0x04 | ||
47 | /* Resolution: 1400x1050, Channel: dual, Dithering: Enable */ | ||
48 | #define LCD_PANEL_ID5_1400X1050 0x05 | ||
49 | /* Resolution: 1600x1200, Channel: dual, Dithering: Enable */ | ||
50 | #define LCD_PANEL_ID6_1600X1200 0x06 | ||
51 | /* Resolution: 1366x768, Channel: single, Dithering: Disable */ | ||
52 | #define LCD_PANEL_ID7_1366X768 0x07 | ||
53 | /* Resolution: 1024x600, Channel: single, Dithering: Enable*/ | ||
54 | #define LCD_PANEL_ID8_1024X600 0x08 | ||
55 | /* Resolution: 1280x800, Channel: single, Dithering: Enable*/ | ||
56 | #define LCD_PANEL_ID9_1280X800 0x09 | ||
57 | /* Resolution: 800x480, Channel: single, Dithering: Enable*/ | ||
58 | #define LCD_PANEL_IDA_800X480 0x0A | ||
59 | /* Resolution: 1360x768, Channel: single, Dithering: Disable*/ | ||
60 | #define LCD_PANEL_IDB_1360X768 0x0B | ||
61 | /* Resolution: 480x640, Channel: single, Dithering: Enable */ | ||
62 | #define LCD_PANEL_IDC_480X640 0x0C | ||
63 | |||
64 | |||
65 | extern int viafb_LCD2_ON; | ||
66 | extern int viafb_LCD_ON; | ||
67 | extern int viafb_DVI_ON; | ||
68 | |||
69 | void viafb_disable_lvds_vt1636(struct lvds_setting_information | ||
70 | *plvds_setting_info, | ||
71 | struct lvds_chip_information *plvds_chip_info); | ||
72 | void viafb_enable_lvds_vt1636(struct lvds_setting_information | ||
73 | *plvds_setting_info, | ||
74 | struct lvds_chip_information *plvds_chip_info); | ||
75 | void viafb_lcd_disable(void); | ||
76 | void viafb_lcd_enable(void); | ||
77 | void viafb_init_lcd_size(void); | ||
78 | void viafb_init_lvds_output_interface(struct lvds_chip_information | ||
79 | *plvds_chip_info, | ||
80 | struct lvds_setting_information | ||
81 | *plvds_setting_info); | ||
82 | void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, | ||
83 | struct lvds_setting_information *plvds_setting_info, | ||
84 | struct lvds_chip_information *plvds_chip_info); | ||
85 | int viafb_lvds_trasmitter_identify(void); | ||
86 | void viafb_init_lvds_output_interface(struct lvds_chip_information | ||
87 | *plvds_chip_info, | ||
88 | struct lvds_setting_information | ||
89 | *plvds_setting_info); | ||
90 | bool viafb_lcd_get_mobile_state(bool *mobile); | ||
91 | void viafb_load_crtc_timing(struct display_timing device_timing, | ||
92 | int set_iga); | ||
93 | |||
94 | #endif /* __LCD_H__ */ | ||
diff --git a/drivers/video/via/lcdtbl.h b/drivers/video/via/lcdtbl.h new file mode 100644 index 000000000000..6f3dd800be59 --- /dev/null +++ b/drivers/video/via/lcdtbl.h | |||
@@ -0,0 +1,591 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | #ifndef __LCDTBL_H__ | ||
22 | #define __LCDTBL_H__ | ||
23 | |||
24 | #include "share.h" | ||
25 | |||
26 | /* CLE266 Software Power Sequence */ | ||
27 | /* {Mask}, {Data}, {Delay} */ | ||
28 | int PowerSequenceOn[3][3] = | ||
29 | { {0x10, 0x08, 0x06}, {0x10, 0x08, 0x06}, {0x19, 0x1FE, 0x01} }; | ||
30 | int PowerSequenceOff[3][3] = | ||
31 | { {0x06, 0x08, 0x10}, {0x00, 0x00, 0x00}, {0xD2, 0x19, 0x01} }; | ||
32 | |||
33 | /* ++++++ P880 ++++++ */ | ||
34 | /* Panel 1600x1200 */ | ||
35 | struct io_reg P880_LCD_RES_6X4_16X12[] = { | ||
36 | /*IGA2 Horizontal Total */ | ||
37 | {VIACR, CR50, 0xFF, 0x73}, {VIACR, CR55, 0x0F, 0x08}, | ||
38 | /*IGA2 Horizontal Blank End */ | ||
39 | {VIACR, CR53, 0xFF, 0x73}, {VIACR, CR54, 0x38, 0x00}, | ||
40 | {VIACR, CR5D, 0x40, 0x40}, | ||
41 | /*IGA2 Horizontal Total Shadow */ | ||
42 | {VIACR, CR6D, 0xFF, 0x5A}, {VIACR, CR71, 0x08, 0x00}, | ||
43 | /*IGA2 Horizontal Blank End Shadow */ | ||
44 | {VIACR, CR6E, 0xFF, 0x5E}, | ||
45 | /*IGA2 Offset */ | ||
46 | {VIACR, CR66, 0xFF, 0xD6}, {VIACR, CR67, 0x03, 0x00}, | ||
47 | /*VCLK*/ {VIASR, SR44, 0xFF, 0x7D}, {VIASR, SR45, 0xFF, 0x8C}, | ||
48 | {VIASR, SR46, 0xFF, 0x02} | ||
49 | |||
50 | }; | ||
51 | |||
52 | #define NUM_TOTAL_P880_LCD_RES_6X4_16X12 ARRAY_SIZE(P880_LCD_RES_6X4_16X12) | ||
53 | |||
54 | struct io_reg P880_LCD_RES_7X4_16X12[] = { | ||
55 | /*IGA2 Horizontal Total */ | ||
56 | {VIACR, CR50, 0xFF, 0x67}, {VIACR, CR55, 0x0F, 0x08}, | ||
57 | /*IGA2 Horizontal Blank End */ | ||
58 | {VIACR, CR53, 0xFF, 0x67}, {VIACR, CR54, 0x38, 0x00}, | ||
59 | {VIACR, CR5D, 0x40, 0x40}, | ||
60 | /*IGA2 Horizontal Total Shadow */ | ||
61 | {VIACR, CR6D, 0xFF, 0x74}, {VIACR, CR71, 0x08, 0x00}, | ||
62 | /*IGA2 Horizontal Blank End Shadow */ | ||
63 | {VIACR, CR6E, 0xFF, 0x78}, | ||
64 | /*IGA2 Offset */ | ||
65 | {VIACR, CR66, 0xFF, 0xF5}, {VIACR, CR67, 0x03, 0x00}, | ||
66 | /*VCLK*/ {VIASR, SR44, 0xFF, 0x78}, {VIASR, SR45, 0xFF, 0x8C}, | ||
67 | {VIASR, SR46, 0xFF, 0x01} | ||
68 | |||
69 | }; | ||
70 | |||
71 | #define NUM_TOTAL_P880_LCD_RES_7X4_16X12 ARRAY_SIZE(P880_LCD_RES_7X4_16X12) | ||
72 | |||
73 | struct io_reg P880_LCD_RES_8X6_16X12[] = { | ||
74 | /*IGA2 Horizontal Total */ | ||
75 | {VIACR, CR50, 0xFF, 0x65}, {VIACR, CR55, 0x0F, 0x08}, | ||
76 | /*IGA2 Horizontal Blank End */ | ||
77 | {VIACR, CR53, 0xFF, 0x65}, {VIACR, CR54, 0x38, 0x00}, | ||
78 | {VIACR, CR5D, 0x40, 0x40}, | ||
79 | /*IGA2 Horizontal Total Shadow */ | ||
80 | {VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x00}, | ||
81 | /*IGA2 Horizontal Blank End Shadow */ | ||
82 | {VIACR, CR6E, 0xFF, 0x83}, | ||
83 | /*IGA2 Offset */ | ||
84 | {VIACR, CR66, 0xFF, 0xE1}, {VIACR, CR67, 0x03, 0x00}, | ||
85 | /*VCLK*/ {VIASR, SR44, 0xFF, 0x6D}, {VIASR, SR45, 0xFF, 0x88}, | ||
86 | {VIASR, SR46, 0xFF, 0x03} | ||
87 | |||
88 | }; | ||
89 | |||
90 | #define NUM_TOTAL_P880_LCD_RES_8X6_16X12 ARRAY_SIZE(P880_LCD_RES_8X6_16X12) | ||
91 | |||
92 | struct io_reg P880_LCD_RES_10X7_16X12[] = { | ||
93 | /*IGA2 Horizontal Total */ | ||
94 | {VIACR, CR50, 0xFF, 0x65}, {VIACR, CR55, 0x0F, 0x08}, | ||
95 | /*IGA2 Horizontal Blank End */ | ||
96 | {VIACR, CR53, 0xFF, 0x65}, {VIACR, CR54, 0x38, 0x00}, | ||
97 | {VIACR, CR5D, 0x40, 0x40}, | ||
98 | /*IGA2 Horizontal Total Shadow */ | ||
99 | {VIACR, CR6D, 0xFF, 0xAB}, {VIACR, CR71, 0x08, 0x00}, | ||
100 | /*IGA2 Horizontal Blank End Shadow */ | ||
101 | {VIACR, CR6E, 0xFF, 0xAF}, | ||
102 | /*IGA2 Offset */ | ||
103 | {VIACR, CR66, 0xFF, 0xF0}, {VIACR, CR67, 0x03, 0x00}, | ||
104 | /*VCLK*/ {VIASR, SR44, 0xFF, 0x92}, {VIASR, SR45, 0xFF, 0x88}, | ||
105 | {VIASR, SR46, 0xFF, 0x03} | ||
106 | |||
107 | }; | ||
108 | |||
109 | #define NUM_TOTAL_P880_LCD_RES_10X7_16X12 ARRAY_SIZE(P880_LCD_RES_10X7_16X12) | ||
110 | |||
111 | struct io_reg P880_LCD_RES_12X10_16X12[] = { | ||
112 | /*IGA2 Horizontal Total */ | ||
113 | {VIACR, CR50, 0xFF, 0x7D}, {VIACR, CR55, 0x0F, 0x08}, | ||
114 | /*IGA2 Horizontal Blank End */ | ||
115 | {VIACR, CR53, 0xFF, 0x7D}, {VIACR, CR54, 0x38, 0x00}, | ||
116 | {VIACR, CR5D, 0x40, 0x40}, | ||
117 | /*IGA2 Horizontal Total Shadow */ | ||
118 | {VIACR, CR6D, 0xFF, 0xD0}, {VIACR, CR71, 0x08, 0x00}, | ||
119 | /*IGA2 Horizontal Blank End Shadow */ | ||
120 | {VIACR, CR6E, 0xFF, 0xD4}, | ||
121 | /*IGA2 Offset */ | ||
122 | {VIACR, CR66, 0xFF, 0xFA}, {VIACR, CR67, 0x03, 0x00}, | ||
123 | /*VCLK*/ {VIASR, SR44, 0xFF, 0xF6}, {VIASR, SR45, 0xFF, 0x88}, | ||
124 | {VIASR, SR46, 0xFF, 0x05} | ||
125 | |||
126 | }; | ||
127 | |||
128 | #define NUM_TOTAL_P880_LCD_RES_12X10_16X12 ARRAY_SIZE(P880_LCD_RES_12X10_16X12) | ||
129 | |||
130 | /* Panel 1400x1050 */ | ||
131 | struct io_reg P880_LCD_RES_6X4_14X10[] = { | ||
132 | /* 640x480 */ | ||
133 | /* IGA2 Horizontal Total */ | ||
134 | {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56}, | ||
135 | /* IGA2 Horizontal Blank End */ | ||
136 | {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75}, | ||
137 | {VIACR, CR5D, 0x40, 0x24}, | ||
138 | /* IGA2 Horizontal Total Shadow */ | ||
139 | {VIACR, CR6D, 0xFF, 0x5F}, {VIACR, CR71, 0x08, 0x44}, | ||
140 | /* IGA2 Horizontal Blank End Shadow */ | ||
141 | {VIACR, CR6E, 0xFF, 0x63}, | ||
142 | /* IGA2 Offset */ | ||
143 | {VIACR, CR66, 0xFF, 0xB4}, {VIACR, CR67, 0x03, 0x00}, | ||
144 | /* VCLK */ | ||
145 | {VIASR, SR44, 0xFF, 0xC6}, {VIASR, SR45, 0xFF, 0x8C}, | ||
146 | {VIASR, SR46, 0xFF, 0x05} | ||
147 | }; | ||
148 | |||
149 | #define NUM_TOTAL_P880_LCD_RES_6X4_14X10 ARRAY_SIZE(P880_LCD_RES_6X4_14X10) | ||
150 | |||
151 | struct io_reg P880_LCD_RES_8X6_14X10[] = { | ||
152 | /* 800x600 */ | ||
153 | /* IGA2 Horizontal Total */ | ||
154 | {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56}, | ||
155 | /* IGA2 Horizontal Blank End */ | ||
156 | {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75}, | ||
157 | {VIACR, CR5D, 0x40, 0x24}, | ||
158 | /* IGA2 Horizontal Total Shadow */ | ||
159 | {VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x44}, | ||
160 | /* IGA2 Horizontal Blank End Shadow */ | ||
161 | {VIACR, CR6E, 0xFF, 0x83}, | ||
162 | /* IGA2 Offset */ | ||
163 | {VIACR, CR66, 0xFF, 0xBE}, {VIACR, CR67, 0x03, 0x00}, | ||
164 | /* VCLK */ | ||
165 | {VIASR, SR44, 0xFF, 0x06}, {VIASR, SR45, 0xFF, 0x8D}, | ||
166 | {VIASR, SR46, 0xFF, 0x05} | ||
167 | }; | ||
168 | |||
169 | #define NUM_TOTAL_P880_LCD_RES_8X6_14X10 ARRAY_SIZE(P880_LCD_RES_8X6_14X10) | ||
170 | |||
171 | /* ++++++ K400 ++++++ */ | ||
172 | /* Panel 1600x1200 */ | ||
173 | struct io_reg K400_LCD_RES_6X4_16X12[] = { | ||
174 | /*IGA2 Horizontal Total */ | ||
175 | {VIACR, CR50, 0xFF, 0x73}, {VIACR, CR55, 0x0F, 0x08}, | ||
176 | /*IGA2 Horizontal Blank End */ | ||
177 | {VIACR, CR53, 0xFF, 0x73}, {VIACR, CR54, 0x38, 0x00}, | ||
178 | {VIACR, CR5D, 0x40, 0x40}, | ||
179 | /*IGA2 Horizontal Total Shadow */ | ||
180 | {VIACR, CR6D, 0xFF, 0x5A}, {VIACR, CR71, 0x08, 0x00}, | ||
181 | /*IGA2 Horizontal Blank End Shadow */ | ||
182 | {VIACR, CR6E, 0xFF, 0x5E}, | ||
183 | /*IGA2 Offset */ | ||
184 | {VIACR, CR66, 0xFF, 0xDA}, {VIACR, CR67, 0x03, 0x00}, | ||
185 | /*VCLK*/ {VIASR, SR46, 0xFF, 0xC4}, {VIASR, SR47, 0xFF, 0x7F} | ||
186 | }; | ||
187 | |||
188 | #define NUM_TOTAL_K400_LCD_RES_6X4_16X12 ARRAY_SIZE(K400_LCD_RES_6X4_16X12) | ||
189 | |||
190 | struct io_reg K400_LCD_RES_7X4_16X12[] = { | ||
191 | /*IGA2 Horizontal Total */ | ||
192 | {VIACR, CR50, 0xFF, 0x67}, {VIACR, CR55, 0x0F, 0x08}, | ||
193 | /*IGA2 Horizontal Blank End */ | ||
194 | {VIACR, CR53, 0xFF, 0x67}, {VIACR, CR54, 0x38, 0x00}, | ||
195 | {VIACR, CR5D, 0x40, 0x40}, | ||
196 | /*IGA2 Horizontal Total Shadow */ | ||
197 | {VIACR, CR6D, 0xFF, 0x74}, {VIACR, CR71, 0x08, 0x00}, | ||
198 | /*IGA2 Horizontal Blank End Shadow */ | ||
199 | {VIACR, CR6E, 0xFF, 0x78}, | ||
200 | /*IGA2 Offset */ | ||
201 | {VIACR, CR66, 0xFF, 0xF5}, {VIACR, CR67, 0x03, 0x00}, | ||
202 | /*VCLK*/ {VIASR, SR46, 0xFF, 0x46}, {VIASR, SR47, 0xFF, 0x3D} | ||
203 | }; | ||
204 | |||
205 | #define NUM_TOTAL_K400_LCD_RES_7X4_16X12 ARRAY_SIZE(K400_LCD_RES_7X4_16X12) | ||
206 | |||
207 | struct io_reg K400_LCD_RES_8X6_16X12[] = { | ||
208 | /*IGA2 Horizontal Total */ | ||
209 | {VIACR, CR50, 0xFF, 0x65}, {VIACR, CR55, 0x0F, 0x08}, | ||
210 | /*IGA2 Horizontal Blank End */ | ||
211 | {VIACR, CR53, 0xFF, 0x65}, {VIACR, CR54, 0x38, 0x00}, | ||
212 | {VIACR, CR5D, 0x40, 0x40}, | ||
213 | /*IGA2 Horizontal Total Shadow */ | ||
214 | {VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x00}, | ||
215 | /*IGA2 Horizontal Blank End Shadow */ | ||
216 | {VIACR, CR6E, 0xFF, 0x83}, | ||
217 | /*IGA2 Offset */ | ||
218 | {VIACR, CR66, 0xFF, 0xE1}, {VIACR, CR67, 0x03, 0x00}, | ||
219 | /*VCLK*/ {VIASR, SR46, 0xFF, 0x85}, {VIASR, SR47, 0xFF, 0x6F} | ||
220 | }; | ||
221 | |||
222 | #define NUM_TOTAL_K400_LCD_RES_8X6_16X12 ARRAY_SIZE(K400_LCD_RES_8X6_16X12) | ||
223 | |||
224 | struct io_reg K400_LCD_RES_10X7_16X12[] = { | ||
225 | /*IGA2 Horizontal Total */ | ||
226 | {VIACR, CR50, 0xFF, 0x65}, {VIACR, CR55, 0x0F, 0x08}, | ||
227 | /*IGA2 Horizontal Blank End */ | ||
228 | {VIACR, CR53, 0xFF, 0x65}, {VIACR, CR54, 0x38, 0x00}, | ||
229 | {VIACR, CR5D, 0x40, 0x40}, | ||
230 | /*IGA2 Horizontal Total Shadow */ | ||
231 | {VIACR, CR6D, 0xFF, 0xAB}, {VIACR, CR71, 0x08, 0x00}, | ||
232 | /*IGA2 Horizontal Blank End Shadow */ | ||
233 | {VIACR, CR6E, 0xFF, 0xAF}, | ||
234 | /*IGA2 Offset */ | ||
235 | {VIACR, CR66, 0xFF, 0xF0}, {VIACR, CR67, 0x03, 0x00}, | ||
236 | /*VCLK*/ {VIASR, SR46, 0xFF, 0x45}, {VIASR, SR47, 0xFF, 0x4A} | ||
237 | }; | ||
238 | |||
239 | #define NUM_TOTAL_K400_LCD_RES_10X7_16X12 ARRAY_SIZE(K400_LCD_RES_10X7_16X12) | ||
240 | |||
241 | struct io_reg K400_LCD_RES_12X10_16X12[] = { | ||
242 | /*IGA2 Horizontal Total */ | ||
243 | {VIACR, CR50, 0xFF, 0x7D}, {VIACR, CR55, 0x0F, 0x08}, | ||
244 | /*IGA2 Horizontal Blank End */ | ||
245 | {VIACR, CR53, 0xFF, 0x7D}, {VIACR, CR54, 0x38, 0x00}, | ||
246 | {VIACR, CR5D, 0x40, 0x40}, | ||
247 | /*IGA2 Horizontal Total Shadow */ | ||
248 | {VIACR, CR6D, 0xFF, 0xD0}, {VIACR, CR71, 0x08, 0x00}, | ||
249 | /*IGA2 Horizontal Blank End Shadow */ | ||
250 | {VIACR, CR6E, 0xFF, 0xD4}, | ||
251 | /*IGA2 Offset */ | ||
252 | {VIACR, CR66, 0xFF, 0xFA}, {VIACR, CR67, 0x03, 0x00}, | ||
253 | /*VCLK*/ {VIASR, SR46, 0xFF, 0x47}, {VIASR, SR47, 0xFF, 0x7C} | ||
254 | }; | ||
255 | |||
256 | #define NUM_TOTAL_K400_LCD_RES_12X10_16X12 ARRAY_SIZE(K400_LCD_RES_12X10_16X12) | ||
257 | |||
258 | /* Panel 1400x1050 */ | ||
259 | struct io_reg K400_LCD_RES_6X4_14X10[] = { | ||
260 | /* 640x400 */ | ||
261 | /* IGA2 Horizontal Total */ | ||
262 | {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56}, | ||
263 | /* IGA2 Horizontal Blank End */ | ||
264 | {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75}, | ||
265 | {VIACR, CR5D, 0x40, 0x24}, | ||
266 | /* IGA2 Horizontal Total Shadow */ | ||
267 | {VIACR, CR6D, 0xFF, 0x5F}, {VIACR, CR71, 0x08, 0x44}, | ||
268 | /* IGA2 Horizontal Blank End Shadow */ | ||
269 | {VIACR, CR6E, 0xFF, 0x63}, | ||
270 | /* IGA2 Offset */ | ||
271 | {VIACR, CR66, 0xFF, 0xB4}, {VIACR, CR67, 0x03, 0x00}, | ||
272 | /* VCLK */ | ||
273 | {VIASR, SR46, 0xFF, 0x07}, {VIASR, SR47, 0xFF, 0x19} | ||
274 | }; | ||
275 | |||
276 | #define NUM_TOTAL_K400_LCD_RES_6X4_14X10 ARRAY_SIZE(K400_LCD_RES_6X4_14X10) | ||
277 | |||
278 | struct io_reg K400_LCD_RES_8X6_14X10[] = { | ||
279 | /* 800x600 */ | ||
280 | /* IGA2 Horizontal Total */ | ||
281 | {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56}, | ||
282 | /* IGA2 Horizontal Blank End */ | ||
283 | {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75}, | ||
284 | {VIACR, CR5D, 0x40, 0x24}, | ||
285 | /* IGA2 Horizontal Total Shadow */ | ||
286 | {VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x44}, | ||
287 | /* IGA2 Horizontal Blank End Shadow */ | ||
288 | {VIACR, CR6E, 0xFF, 0x83}, | ||
289 | /* IGA2 Offset */ | ||
290 | {VIACR, CR66, 0xFF, 0xBE}, {VIACR, CR67, 0x03, 0x00}, | ||
291 | /* VCLK */ | ||
292 | {VIASR, SR46, 0xFF, 0x07}, {VIASR, SR47, 0xFF, 0x21} | ||
293 | }; | ||
294 | |||
295 | #define NUM_TOTAL_K400_LCD_RES_8X6_14X10 ARRAY_SIZE(K400_LCD_RES_8X6_14X10) | ||
296 | |||
297 | struct io_reg K400_LCD_RES_10X7_14X10[] = { | ||
298 | /* 1024x768 */ | ||
299 | /* IGA2 Horizontal Total */ | ||
300 | {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56}, | ||
301 | /* IGA2 Horizontal Blank End */ | ||
302 | {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75}, | ||
303 | {VIACR, CR5D, 0x40, 0x24}, | ||
304 | /* IGA2 Horizontal Total Shadow */ | ||
305 | {VIACR, CR6D, 0xFF, 0xA3}, {VIACR, CR71, 0x08, 0x44}, | ||
306 | /* IGA2 Horizontal Blank End Shadow */ | ||
307 | {VIACR, CR6E, 0xFF, 0xA7}, | ||
308 | /* IGA2 Offset */ | ||
309 | {VIACR, CR66, 0xFF, 0xC3}, {VIACR, CR67, 0x03, 0x04}, | ||
310 | /* VCLK */ | ||
311 | {VIASR, SR46, 0xFF, 0x05}, {VIASR, SR47, 0xFF, 0x1E} | ||
312 | }; | ||
313 | |||
314 | #define NUM_TOTAL_K400_LCD_RES_10X7_14X10 ARRAY_SIZE(K400_LCD_RES_10X7_14X10) | ||
315 | |||
316 | struct io_reg K400_LCD_RES_12X10_14X10[] = { | ||
317 | /* 1280x768, 1280x960, 1280x1024 */ | ||
318 | /* IGA2 Horizontal Total */ | ||
319 | {VIACR, CR50, 0xFF, 0x97}, {VIACR, CR55, 0x0F, 0x56}, | ||
320 | /* IGA2 Horizontal Blank End */ | ||
321 | {VIACR, CR53, 0xFF, 0x97}, {VIACR, CR54, 0x38, 0x75}, | ||
322 | {VIACR, CR5D, 0x40, 0x24}, | ||
323 | /* IGA2 Horizontal Total Shadow */ | ||
324 | {VIACR, CR6D, 0xFF, 0xCE}, {VIACR, CR71, 0x08, 0x44}, | ||
325 | /* IGA2 Horizontal Blank End Shadow */ | ||
326 | {VIACR, CR6E, 0xFF, 0xD2}, | ||
327 | /* IGA2 Offset */ | ||
328 | {VIACR, CR66, 0xFF, 0xC9}, {VIACR, CR67, 0x03, 0x04}, | ||
329 | /* VCLK */ | ||
330 | {VIASR, SR46, 0xFF, 0x84}, {VIASR, SR47, 0xFF, 0x79} | ||
331 | }; | ||
332 | |||
333 | #define NUM_TOTAL_K400_LCD_RES_12X10_14X10 ARRAY_SIZE(K400_LCD_RES_12X10_14X10) | ||
334 | |||
335 | /* ++++++ K400 ++++++ */ | ||
336 | /* Panel 1366x768 */ | ||
337 | struct io_reg K400_LCD_RES_6X4_1366X7[] = { | ||
338 | /* 640x400 */ | ||
339 | /* IGA2 Horizontal Total */ | ||
340 | {VIACR, CR50, 0xFF, 0x47}, {VIACR, CR55, 0x0F, 0x35}, | ||
341 | /* IGA2 Horizontal Blank End */ | ||
342 | {VIACR, CR53, 0xFF, 0x47}, {VIACR, CR54, 0x38, 0x2B}, | ||
343 | {VIACR, CR5D, 0x40, 0x13}, | ||
344 | /* IGA2 Horizontal Total Shadow */ | ||
345 | {VIACR, CR6D, 0xFF, 0x60}, {VIACR, CR71, 0x08, 0x23}, | ||
346 | /* IGA2 Horizontal Blank End Shadow */ | ||
347 | {VIACR, CR6E, 0xFF, 0x64}, | ||
348 | /* IGA2 Offset */ | ||
349 | {VIACR, CR66, 0xFF, 0x8C}, {VIACR, CR67, 0x03, 0x00}, | ||
350 | /* VCLK */ | ||
351 | {VIASR, SR46, 0xFF, 0x87}, {VIASR, SR47, 0xFF, 0x4C} | ||
352 | }; | ||
353 | |||
354 | #define NUM_TOTAL_K400_LCD_RES_6X4_1366X7 ARRAY_SIZE(K400_LCD_RES_6X4_1366X7) | ||
355 | |||
356 | struct io_reg K400_LCD_RES_7X4_1366X7[] = { | ||
357 | /* IGA2 Horizontal Total */ | ||
358 | {VIACR, CR50, 0xFF, 0x3B}, {VIACR, CR55, 0x0F, 0x35}, | ||
359 | /* IGA2 Horizontal Blank End */ | ||
360 | {VIACR, CR53, 0xFF, 0x3B}, {VIACR, CR54, 0x38, 0x2B}, | ||
361 | {VIACR, CR5D, 0x40, 0x13}, | ||
362 | /* IGA2 Horizontal Total Shadow */ | ||
363 | {VIACR, CR6D, 0xFF, 0x71}, {VIACR, CR71, 0x08, 0x23}, | ||
364 | /* IGA2 Horizontal Blank End Shadow */ | ||
365 | {VIACR, CR6E, 0xFF, 0x75}, | ||
366 | /* IGA2 Offset */ | ||
367 | {VIACR, CR66, 0xFF, 0x96}, {VIACR, CR67, 0x03, 0x00}, | ||
368 | /* VCLK */ | ||
369 | {VIASR, SR46, 0xFF, 0x05}, {VIASR, SR47, 0xFF, 0x10} | ||
370 | }; | ||
371 | |||
372 | #define NUM_TOTAL_K400_LCD_RES_7X4_1366X7 ARRAY_SIZE(K400_LCD_RES_7X4_1366X7) | ||
373 | |||
374 | struct io_reg K400_LCD_RES_8X6_1366X7[] = { | ||
375 | /* 800x600 */ | ||
376 | /* IGA2 Horizontal Total */ | ||
377 | {VIACR, CR50, 0xFF, 0x37}, {VIACR, CR55, 0x0F, 0x35}, | ||
378 | /* IGA2 Horizontal Blank End */ | ||
379 | {VIACR, CR53, 0xFF, 0x37}, {VIACR, CR54, 0x38, 0x2B}, | ||
380 | {VIACR, CR5D, 0x40, 0x13}, | ||
381 | /* IGA2 Horizontal Total Shadow */ | ||
382 | {VIACR, CR6D, 0xFF, 0x7E}, {VIACR, CR71, 0x08, 0x23}, | ||
383 | /* IGA2 Horizontal Blank End Shadow */ | ||
384 | {VIACR, CR6E, 0xFF, 0x82}, | ||
385 | /* IGA2 Offset */ | ||
386 | {VIACR, CR66, 0xFF, 0x8C}, {VIACR, CR67, 0x03, 0x00}, | ||
387 | /* VCLK */ | ||
388 | {VIASR, SR46, 0xFF, 0x84}, {VIASR, SR47, 0xFF, 0xB9} | ||
389 | }; | ||
390 | |||
391 | #define NUM_TOTAL_K400_LCD_RES_8X6_1366X7 ARRAY_SIZE(K400_LCD_RES_8X6_1366X7) | ||
392 | |||
393 | struct io_reg K400_LCD_RES_10X7_1366X7[] = { | ||
394 | /* 1024x768 */ | ||
395 | /* IGA2 Horizontal Total */ | ||
396 | {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56}, | ||
397 | /* IGA2 Horizontal Blank End */ | ||
398 | {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75}, | ||
399 | {VIACR, CR5D, 0x40, 0x24}, | ||
400 | /* IGA2 Horizontal Total Shadow */ | ||
401 | {VIACR, CR6D, 0xFF, 0xA3}, {VIACR, CR71, 0x08, 0x44}, | ||
402 | /* IGA2 Horizontal Blank End Shadow */ | ||
403 | {VIACR, CR6E, 0xFF, 0xA7}, | ||
404 | /* IGA2 Offset */ | ||
405 | {VIACR, CR66, 0xFF, 0xC3}, {VIACR, CR67, 0x03, 0x04}, | ||
406 | /* VCLK */ | ||
407 | {VIASR, SR46, 0xFF, 0x05}, {VIASR, SR47, 0xFF, 0x1E} | ||
408 | }; | ||
409 | |||
410 | #define NUM_TOTAL_K400_LCD_RES_10X7_1366X7 ARRAY_SIZE(K400_LCD_RES_10X7_1366X7) | ||
411 | |||
412 | struct io_reg K400_LCD_RES_12X10_1366X7[] = { | ||
413 | /* 1280x768, 1280x960, 1280x1024 */ | ||
414 | /* IGA2 Horizontal Total */ | ||
415 | {VIACR, CR50, 0xFF, 0x97}, {VIACR, CR55, 0x0F, 0x56}, | ||
416 | /* IGA2 Horizontal Blank End */ | ||
417 | {VIACR, CR53, 0xFF, 0x97}, {VIACR, CR54, 0x38, 0x75}, | ||
418 | {VIACR, CR5D, 0x40, 0x24}, | ||
419 | /* IGA2 Horizontal Total Shadow */ | ||
420 | {VIACR, CR6D, 0xFF, 0xCE}, {VIACR, CR71, 0x08, 0x44}, | ||
421 | /* IGA2 Horizontal Blank End Shadow */ | ||
422 | {VIACR, CR6E, 0xFF, 0xD2}, | ||
423 | /* IGA2 Offset */ | ||
424 | {VIACR, CR66, 0xFF, 0xC9}, {VIACR, CR67, 0x03, 0x04}, | ||
425 | /* VCLK */ | ||
426 | {VIASR, SR46, 0xFF, 0x84}, {VIASR, SR47, 0xFF, 0x79} | ||
427 | }; | ||
428 | |||
429 | #define NUM_TOTAL_K400_LCD_RES_12X10_1366X7\ | ||
430 | ARRAY_SIZE(K400_LCD_RES_12X10_1366X7) | ||
431 | |||
432 | /* ++++++ K400 ++++++ */ | ||
433 | /* Panel 1280x1024 */ | ||
434 | struct io_reg K400_LCD_RES_6X4_12X10[] = { | ||
435 | /*IGA2 Horizontal Total */ | ||
436 | {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x46}, | ||
437 | /*IGA2 Horizontal Blank End */ | ||
438 | {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x74}, | ||
439 | {VIACR, CR5D, 0x40, 0x1C}, | ||
440 | /*IGA2 Horizontal Total Shadow */ | ||
441 | {VIACR, CR6D, 0xFF, 0x5F}, {VIACR, CR71, 0x08, 0x34}, | ||
442 | /*IGA2 Horizontal Blank End Shadow */ | ||
443 | {VIACR, CR6E, 0xFF, 0x63}, | ||
444 | /*IGA2 Offset */ | ||
445 | {VIACR, CR66, 0xFF, 0xAA}, {VIACR, CR67, 0x03, 0x00}, | ||
446 | /*VCLK*/ {VIASR, SR46, 0xFF, 0x07}, {VIASR, SR47, 0xFF, 0x19} | ||
447 | }; | ||
448 | |||
449 | #define NUM_TOTAL_K400_LCD_RES_6X4_12X10 ARRAY_SIZE(K400_LCD_RES_6X4_12X10) | ||
450 | |||
451 | struct io_reg K400_LCD_RES_7X4_12X10[] = { | ||
452 | /*IGA2 Horizontal Total */ | ||
453 | {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x46}, | ||
454 | /*IGA2 Horizontal Blank End */ | ||
455 | {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x74}, | ||
456 | {VIACR, CR5D, 0x40, 0x1C}, | ||
457 | /*IGA2 Horizontal Total Shadow */ | ||
458 | {VIACR, CR6D, 0xFF, 0x68}, {VIACR, CR71, 0x08, 0x34}, | ||
459 | /*IGA2 Horizontal Blank End Shadow */ | ||
460 | {VIACR, CR6E, 0xFF, 0x6C}, | ||
461 | /*IGA2 Offset */ | ||
462 | {VIACR, CR66, 0xFF, 0xA8}, {VIACR, CR67, 0x03, 0x00}, | ||
463 | /*VCLK*/ {VIASR, SR46, 0xFF, 0x87}, {VIASR, SR47, 0xFF, 0xED} | ||
464 | }; | ||
465 | |||
466 | #define NUM_TOTAL_K400_LCD_RES_7X4_12X10 ARRAY_SIZE(K400_LCD_RES_7X4_12X10) | ||
467 | |||
468 | struct io_reg K400_LCD_RES_8X6_12X10[] = { | ||
469 | /*IGA2 Horizontal Total */ | ||
470 | {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x46}, | ||
471 | /*IGA2 Horizontal Blank End */ | ||
472 | {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x74}, | ||
473 | {VIACR, CR5D, 0x40, 0x1C}, | ||
474 | /*IGA2 Horizontal Total Shadow */ | ||
475 | {VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x34}, | ||
476 | /*IGA2 Horizontal Blank End Shadow */ | ||
477 | {VIACR, CR6E, 0xFF, 0x83}, | ||
478 | /*IGA2 Offset */ | ||
479 | {VIACR, CR66, 0xFF, 0xBE}, {VIACR, CR67, 0x03, 0x00}, | ||
480 | /*VCLK*/ {VIASR, SR46, 0xFF, 0x07}, {VIASR, SR47, 0xFF, 0x21} | ||
481 | }; | ||
482 | |||
483 | #define NUM_TOTAL_K400_LCD_RES_8X6_12X10 ARRAY_SIZE(K400_LCD_RES_8X6_12X10) | ||
484 | |||
485 | struct io_reg K400_LCD_RES_10X7_12X10[] = { | ||
486 | /*IGA2 Horizontal Total */ | ||
487 | {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x46}, | ||
488 | /*IGA2 Horizontal Blank End */ | ||
489 | {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x74}, | ||
490 | {VIACR, CR5D, 0x40, 0x1C}, | ||
491 | /*IGA2 Horizontal Total Shadow */ | ||
492 | {VIACR, CR6D, 0xFF, 0xA3}, {VIACR, CR71, 0x08, 0x34}, | ||
493 | /*IGA2 Horizontal Blank End Shadow */ | ||
494 | {VIACR, CR6E, 0xFF, 0xA7}, | ||
495 | /*IGA2 Offset */ | ||
496 | {VIACR, CR66, 0xFF, 0xBE}, {VIACR, CR67, 0x03, 0x04}, | ||
497 | /*VCLK*/ {VIASR, SR46, 0xFF, 0x05}, {VIASR, SR47, 0xFF, 0x1E} | ||
498 | }; | ||
499 | |||
500 | #define NUM_TOTAL_K400_LCD_RES_10X7_12X10 ARRAY_SIZE(K400_LCD_RES_10X7_12X10) | ||
501 | |||
502 | /* ++++++ K400 ++++++ */ | ||
503 | /* Panel 1024x768 */ | ||
504 | struct io_reg K400_LCD_RES_6X4_10X7[] = { | ||
505 | /*IGA2 Horizontal Total */ | ||
506 | {VIACR, CR50, 0xFF, 0x47}, {VIACR, CR55, 0x0F, 0x35}, | ||
507 | /*IGA2 Horizontal Blank End */ | ||
508 | {VIACR, CR53, 0xFF, 0x47}, {VIACR, CR54, 0x38, 0x2B}, | ||
509 | {VIACR, CR5D, 0x40, 0x13}, | ||
510 | /*IGA2 Horizontal Total Shadow */ | ||
511 | {VIACR, CR6D, 0xFF, 0x60}, {VIACR, CR71, 0x08, 0x23}, | ||
512 | /*IGA2 Horizontal Blank End Shadow */ | ||
513 | {VIACR, CR6E, 0xFF, 0x64}, | ||
514 | /*IGA2 Offset */ | ||
515 | {VIACR, CR66, 0xFF, 0x8C}, {VIACR, CR67, 0x03, 0x00}, | ||
516 | /*VCLK*/ {VIASR, SR46, 0xFF, 0x87}, {VIASR, SR47, 0xFF, 0x4C} | ||
517 | }; | ||
518 | |||
519 | #define NUM_TOTAL_K400_LCD_RES_6X4_10X7 ARRAY_SIZE(K400_LCD_RES_6X4_10X7) | ||
520 | |||
521 | struct io_reg K400_LCD_RES_7X4_10X7[] = { | ||
522 | /*IGA2 Horizontal Total */ | ||
523 | {VIACR, CR50, 0xFF, 0x3B}, {VIACR, CR55, 0x0F, 0x35}, | ||
524 | /*IGA2 Horizontal Blank End */ | ||
525 | {VIACR, CR53, 0xFF, 0x3B}, {VIACR, CR54, 0x38, 0x2B}, | ||
526 | {VIACR, CR5D, 0x40, 0x13}, | ||
527 | /*IGA2 Horizontal Total Shadow */ | ||
528 | {VIACR, CR6D, 0xFF, 0x71}, {VIACR, CR71, 0x08, 0x23}, | ||
529 | /*IGA2 Horizontal Blank End Shadow */ | ||
530 | {VIACR, CR6E, 0xFF, 0x75}, | ||
531 | /*IGA2 Offset */ | ||
532 | {VIACR, CR66, 0xFF, 0x96}, {VIACR, CR67, 0x03, 0x00}, | ||
533 | /*VCLK*/ {VIASR, SR46, 0xFF, 0x05}, {VIASR, SR47, 0xFF, 0x10} | ||
534 | }; | ||
535 | |||
536 | #define NUM_TOTAL_K400_LCD_RES_7X4_10X7 ARRAY_SIZE(K400_LCD_RES_7X4_10X7) | ||
537 | |||
538 | struct io_reg K400_LCD_RES_8X6_10X7[] = { | ||
539 | /*IGA2 Horizontal Total */ | ||
540 | {VIACR, CR50, 0xFF, 0x37}, {VIACR, CR55, 0x0F, 0x35}, | ||
541 | /*IGA2 Horizontal Blank End */ | ||
542 | {VIACR, CR53, 0xFF, 0x37}, {VIACR, CR54, 0x38, 0x2B}, | ||
543 | {VIACR, CR5D, 0x40, 0x13}, | ||
544 | /*IGA2 Horizontal Total Shadow */ | ||
545 | {VIACR, CR6D, 0xFF, 0x7E}, {VIACR, CR71, 0x08, 0x23}, | ||
546 | /*IGA2 Horizontal Blank End Shadow */ | ||
547 | {VIACR, CR6E, 0xFF, 0x82}, | ||
548 | /*IGA2 Offset */ | ||
549 | {VIACR, CR66, 0xFF, 0x8C}, {VIACR, CR67, 0x03, 0x00}, | ||
550 | /*VCLK*/ {VIASR, SR46, 0xFF, 0x84}, {VIASR, SR47, 0xFF, 0xB9} | ||
551 | }; | ||
552 | |||
553 | #define NUM_TOTAL_K400_LCD_RES_8X6_10X7 ARRAY_SIZE(K400_LCD_RES_8X6_10X7) | ||
554 | |||
555 | /* ++++++ K400 ++++++ */ | ||
556 | /* Panel 800x600 */ | ||
557 | struct io_reg K400_LCD_RES_6X4_8X6[] = { | ||
558 | /*IGA2 Horizontal Total */ | ||
559 | {VIACR, CR50, 0xFF, 0x1A}, {VIACR, CR55, 0x0F, 0x34}, | ||
560 | /*IGA2 Horizontal Blank End */ | ||
561 | {VIACR, CR53, 0xFF, 0x1A}, {VIACR, CR54, 0x38, 0xE3}, | ||
562 | {VIACR, CR5D, 0x40, 0x12}, | ||
563 | /*IGA2 Horizontal Total Shadow */ | ||
564 | {VIACR, CR6D, 0xFF, 0x5F}, {VIACR, CR71, 0x08, 0x22}, | ||
565 | /*IGA2 Horizontal Blank End Shadow */ | ||
566 | {VIACR, CR6E, 0xFF, 0x63}, | ||
567 | /*IGA2 Offset */ | ||
568 | {VIACR, CR66, 0xFF, 0x6E}, {VIACR, CR67, 0x03, 0x00}, | ||
569 | /*VCLK*/ {VIASR, SR46, 0xFF, 0x86}, {VIASR, SR47, 0xFF, 0xB3} | ||
570 | }; | ||
571 | |||
572 | #define NUM_TOTAL_K400_LCD_RES_6X4_8X6 ARRAY_SIZE(K400_LCD_RES_6X4_8X6) | ||
573 | |||
574 | struct io_reg K400_LCD_RES_7X4_8X6[] = { | ||
575 | /*IGA2 Horizontal Total */ | ||
576 | {VIACR, CR50, 0xFF, 0x1F}, {VIACR, CR55, 0x0F, 0x34}, | ||
577 | /*IGA2 Horizontal Blank End */ | ||
578 | {VIACR, CR53, 0xFF, 0x1F}, {VIACR, CR54, 0x38, 0xE3}, | ||
579 | {VIACR, CR5D, 0x40, 0x12}, | ||
580 | /*IGA2 Horizontal Total Shadow */ | ||
581 | {VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x22}, | ||
582 | /*IGA2 Horizontal Blank End Shadow */ | ||
583 | {VIACR, CR6E, 0xFF, 0x83}, | ||
584 | /*IGA2 Offset */ | ||
585 | {VIACR, CR66, 0xFF, 0x78}, {VIACR, CR67, 0x03, 0x00}, | ||
586 | /*VCLK*/ {VIASR, SR46, 0xFF, 0xC4}, {VIASR, SR47, 0xFF, 0x59} | ||
587 | }; | ||
588 | |||
589 | #define NUM_TOTAL_K400_LCD_RES_7X4_8X6 ARRAY_SIZE(K400_LCD_RES_7X4_8X6) | ||
590 | |||
591 | #endif /* __LCDTBL_H__ */ | ||
diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h new file mode 100644 index 000000000000..2e1254da9c8c --- /dev/null +++ b/drivers/video/via/share.h | |||
@@ -0,0 +1,1105 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef __SHARE_H__ | ||
23 | #define __SHARE_H__ | ||
24 | |||
25 | /* Define Return Value */ | ||
26 | #define FAIL -1 | ||
27 | #define OK 1 | ||
28 | |||
29 | #ifndef NULL | ||
30 | #define NULL 0 | ||
31 | #endif | ||
32 | |||
33 | /* Define Bit Field */ | ||
34 | #define BIT0 0x01 | ||
35 | #define BIT1 0x02 | ||
36 | #define BIT2 0x04 | ||
37 | #define BIT3 0x08 | ||
38 | #define BIT4 0x10 | ||
39 | #define BIT5 0x20 | ||
40 | #define BIT6 0x40 | ||
41 | #define BIT7 0x80 | ||
42 | |||
43 | /* Video Memory Size */ | ||
44 | #define VIDEO_MEMORY_SIZE_16M 0x1000000 | ||
45 | |||
46 | /* Definition Mode Index | ||
47 | */ | ||
48 | #define VIA_RES_640X480 0 | ||
49 | #define VIA_RES_800X600 1 | ||
50 | #define VIA_RES_1024X768 2 | ||
51 | #define VIA_RES_1152X864 3 | ||
52 | #define VIA_RES_1280X1024 4 | ||
53 | #define VIA_RES_1600X1200 5 | ||
54 | #define VIA_RES_1440X1050 6 | ||
55 | #define VIA_RES_1280X768 7 | ||
56 | #define VIA_RES_1280X960 8 | ||
57 | #define VIA_RES_1920X1440 9 | ||
58 | #define VIA_RES_848X480 10 | ||
59 | #define VIA_RES_1400X1050 11 | ||
60 | #define VIA_RES_720X480 12 | ||
61 | #define VIA_RES_720X576 13 | ||
62 | #define VIA_RES_1024X512 14 | ||
63 | #define VIA_RES_856X480 15 | ||
64 | #define VIA_RES_1024X576 16 | ||
65 | #define VIA_RES_640X400 17 | ||
66 | #define VIA_RES_1280X720 18 | ||
67 | #define VIA_RES_1920X1080 19 | ||
68 | #define VIA_RES_800X480 20 | ||
69 | #define VIA_RES_1368X768 21 | ||
70 | #define VIA_RES_1024X600 22 | ||
71 | #define VIA_RES_1280X800 23 | ||
72 | #define VIA_RES_1680X1050 24 | ||
73 | #define VIA_RES_960X600 25 | ||
74 | #define VIA_RES_1000X600 26 | ||
75 | #define VIA_RES_1088X612 27 | ||
76 | #define VIA_RES_1152X720 28 | ||
77 | #define VIA_RES_1200X720 29 | ||
78 | #define VIA_RES_1280X600 30 | ||
79 | #define VIA_RES_1360X768 31 | ||
80 | #define VIA_RES_1366X768 32 | ||
81 | #define VIA_RES_1440X900 33 | ||
82 | #define VIA_RES_1600X900 34 | ||
83 | #define VIA_RES_1600X1024 35 | ||
84 | #define VIA_RES_1792X1344 36 | ||
85 | #define VIA_RES_1856X1392 37 | ||
86 | #define VIA_RES_1920X1200 38 | ||
87 | #define VIA_RES_2048X1536 39 | ||
88 | #define VIA_RES_480X640 40 | ||
89 | |||
90 | /*Reduce Blanking*/ | ||
91 | #define VIA_RES_1360X768_RB 131 | ||
92 | #define VIA_RES_1440X900_RB 133 | ||
93 | #define VIA_RES_1400X1050_RB 111 | ||
94 | #define VIA_RES_1600X900_RB 134 | ||
95 | #define VIA_RES_1680X1050_RB 124 | ||
96 | #define VIA_RES_1920X1080_RB 119 | ||
97 | #define VIA_RES_1920X1200_RB 138 | ||
98 | |||
99 | #define VIA_RES_INVALID 255 | ||
100 | |||
101 | /* standard VGA IO port | ||
102 | */ | ||
103 | #define VIARMisc 0x3CC | ||
104 | #define VIAWMisc 0x3C2 | ||
105 | #define VIAStatus 0x3DA | ||
106 | #define VIACR 0x3D4 | ||
107 | #define VIASR 0x3C4 | ||
108 | #define VIAGR 0x3CE | ||
109 | #define VIAAR 0x3C0 | ||
110 | |||
111 | #define StdCR 0x19 | ||
112 | #define StdSR 0x04 | ||
113 | #define StdGR 0x09 | ||
114 | #define StdAR 0x14 | ||
115 | |||
116 | #define PatchCR 11 | ||
117 | |||
118 | /* Display path */ | ||
119 | #define IGA1 1 | ||
120 | #define IGA2 2 | ||
121 | #define IGA1_IGA2 3 | ||
122 | |||
123 | /* Define Color Depth */ | ||
124 | #define MODE_8BPP 1 | ||
125 | #define MODE_16BPP 2 | ||
126 | #define MODE_32BPP 4 | ||
127 | |||
128 | #define GR20 0x20 | ||
129 | #define GR21 0x21 | ||
130 | #define GR22 0x22 | ||
131 | |||
132 | /* Sequencer Registers */ | ||
133 | #define SR01 0x01 | ||
134 | #define SR10 0x10 | ||
135 | #define SR12 0x12 | ||
136 | #define SR15 0x15 | ||
137 | #define SR16 0x16 | ||
138 | #define SR17 0x17 | ||
139 | #define SR18 0x18 | ||
140 | #define SR1B 0x1B | ||
141 | #define SR1A 0x1A | ||
142 | #define SR1C 0x1C | ||
143 | #define SR1D 0x1D | ||
144 | #define SR1E 0x1E | ||
145 | #define SR1F 0x1F | ||
146 | #define SR20 0x20 | ||
147 | #define SR21 0x21 | ||
148 | #define SR22 0x22 | ||
149 | #define SR2A 0x2A | ||
150 | #define SR2D 0x2D | ||
151 | #define SR2E 0x2E | ||
152 | |||
153 | #define SR30 0x30 | ||
154 | #define SR39 0x39 | ||
155 | #define SR3D 0x3D | ||
156 | #define SR3E 0x3E | ||
157 | #define SR3F 0x3F | ||
158 | #define SR40 0x40 | ||
159 | #define SR43 0x43 | ||
160 | #define SR44 0x44 | ||
161 | #define SR45 0x45 | ||
162 | #define SR46 0x46 | ||
163 | #define SR47 0x47 | ||
164 | #define SR48 0x48 | ||
165 | #define SR49 0x49 | ||
166 | #define SR4A 0x4A | ||
167 | #define SR4B 0x4B | ||
168 | #define SR4C 0x4C | ||
169 | #define SR52 0x52 | ||
170 | #define SR5E 0x5E | ||
171 | #define SR65 0x65 | ||
172 | |||
173 | /* CRT Controller Registers */ | ||
174 | #define CR00 0x00 | ||
175 | #define CR01 0x01 | ||
176 | #define CR02 0x02 | ||
177 | #define CR03 0x03 | ||
178 | #define CR04 0x04 | ||
179 | #define CR05 0x05 | ||
180 | #define CR06 0x06 | ||
181 | #define CR07 0x07 | ||
182 | #define CR08 0x08 | ||
183 | #define CR09 0x09 | ||
184 | #define CR0A 0x0A | ||
185 | #define CR0B 0x0B | ||
186 | #define CR0C 0x0C | ||
187 | #define CR0D 0x0D | ||
188 | #define CR0E 0x0E | ||
189 | #define CR0F 0x0F | ||
190 | #define CR10 0x10 | ||
191 | #define CR11 0x11 | ||
192 | #define CR12 0x12 | ||
193 | #define CR13 0x13 | ||
194 | #define CR14 0x14 | ||
195 | #define CR15 0x15 | ||
196 | #define CR16 0x16 | ||
197 | #define CR17 0x17 | ||
198 | #define CR18 0x18 | ||
199 | |||
200 | /* Extend CRT Controller Registers */ | ||
201 | #define CR30 0x30 | ||
202 | #define CR31 0x31 | ||
203 | #define CR32 0x32 | ||
204 | #define CR33 0x33 | ||
205 | #define CR34 0x34 | ||
206 | #define CR35 0x35 | ||
207 | #define CR36 0x36 | ||
208 | #define CR37 0x37 | ||
209 | #define CR38 0x38 | ||
210 | #define CR39 0x39 | ||
211 | #define CR3A 0x3A | ||
212 | #define CR3B 0x3B | ||
213 | #define CR3C 0x3C | ||
214 | #define CR3D 0x3D | ||
215 | #define CR3E 0x3E | ||
216 | #define CR3F 0x3F | ||
217 | #define CR40 0x40 | ||
218 | #define CR41 0x41 | ||
219 | #define CR42 0x42 | ||
220 | #define CR43 0x43 | ||
221 | #define CR44 0x44 | ||
222 | #define CR45 0x45 | ||
223 | #define CR46 0x46 | ||
224 | #define CR47 0x47 | ||
225 | #define CR48 0x48 | ||
226 | #define CR49 0x49 | ||
227 | #define CR4A 0x4A | ||
228 | #define CR4B 0x4B | ||
229 | #define CR4C 0x4C | ||
230 | #define CR4D 0x4D | ||
231 | #define CR4E 0x4E | ||
232 | #define CR4F 0x4F | ||
233 | #define CR50 0x50 | ||
234 | #define CR51 0x51 | ||
235 | #define CR52 0x52 | ||
236 | #define CR53 0x53 | ||
237 | #define CR54 0x54 | ||
238 | #define CR55 0x55 | ||
239 | #define CR56 0x56 | ||
240 | #define CR57 0x57 | ||
241 | #define CR58 0x58 | ||
242 | #define CR59 0x59 | ||
243 | #define CR5A 0x5A | ||
244 | #define CR5B 0x5B | ||
245 | #define CR5C 0x5C | ||
246 | #define CR5D 0x5D | ||
247 | #define CR5E 0x5E | ||
248 | #define CR5F 0x5F | ||
249 | #define CR60 0x60 | ||
250 | #define CR61 0x61 | ||
251 | #define CR62 0x62 | ||
252 | #define CR63 0x63 | ||
253 | #define CR64 0x64 | ||
254 | #define CR65 0x65 | ||
255 | #define CR66 0x66 | ||
256 | #define CR67 0x67 | ||
257 | #define CR68 0x68 | ||
258 | #define CR69 0x69 | ||
259 | #define CR6A 0x6A | ||
260 | #define CR6B 0x6B | ||
261 | #define CR6C 0x6C | ||
262 | #define CR6D 0x6D | ||
263 | #define CR6E 0x6E | ||
264 | #define CR6F 0x6F | ||
265 | #define CR70 0x70 | ||
266 | #define CR71 0x71 | ||
267 | #define CR72 0x72 | ||
268 | #define CR73 0x73 | ||
269 | #define CR74 0x74 | ||
270 | #define CR75 0x75 | ||
271 | #define CR76 0x76 | ||
272 | #define CR77 0x77 | ||
273 | #define CR78 0x78 | ||
274 | #define CR79 0x79 | ||
275 | #define CR7A 0x7A | ||
276 | #define CR7B 0x7B | ||
277 | #define CR7C 0x7C | ||
278 | #define CR7D 0x7D | ||
279 | #define CR7E 0x7E | ||
280 | #define CR7F 0x7F | ||
281 | #define CR80 0x80 | ||
282 | #define CR81 0x81 | ||
283 | #define CR82 0x82 | ||
284 | #define CR83 0x83 | ||
285 | #define CR84 0x84 | ||
286 | #define CR85 0x85 | ||
287 | #define CR86 0x86 | ||
288 | #define CR87 0x87 | ||
289 | #define CR88 0x88 | ||
290 | #define CR89 0x89 | ||
291 | #define CR8A 0x8A | ||
292 | #define CR8B 0x8B | ||
293 | #define CR8C 0x8C | ||
294 | #define CR8D 0x8D | ||
295 | #define CR8E 0x8E | ||
296 | #define CR8F 0x8F | ||
297 | #define CR90 0x90 | ||
298 | #define CR91 0x91 | ||
299 | #define CR92 0x92 | ||
300 | #define CR93 0x93 | ||
301 | #define CR94 0x94 | ||
302 | #define CR95 0x95 | ||
303 | #define CR96 0x96 | ||
304 | #define CR97 0x97 | ||
305 | #define CR98 0x98 | ||
306 | #define CR99 0x99 | ||
307 | #define CR9A 0x9A | ||
308 | #define CR9B 0x9B | ||
309 | #define CR9C 0x9C | ||
310 | #define CR9D 0x9D | ||
311 | #define CR9E 0x9E | ||
312 | #define CR9F 0x9F | ||
313 | #define CRA0 0xA0 | ||
314 | #define CRA1 0xA1 | ||
315 | #define CRA2 0xA2 | ||
316 | #define CRA3 0xA3 | ||
317 | #define CRD2 0xD2 | ||
318 | #define CRD3 0xD3 | ||
319 | #define CRD4 0xD4 | ||
320 | |||
321 | /* LUT Table*/ | ||
322 | #define LUT_DATA 0x3C9 /* DACDATA */ | ||
323 | #define LUT_INDEX_READ 0x3C7 /* DACRX */ | ||
324 | #define LUT_INDEX_WRITE 0x3C8 /* DACWX */ | ||
325 | #define DACMASK 0x3C6 | ||
326 | |||
327 | /* Definition Device */ | ||
328 | #define DEVICE_CRT 0x01 | ||
329 | #define DEVICE_DVI 0x03 | ||
330 | #define DEVICE_LCD 0x04 | ||
331 | |||
332 | /* Device output interface */ | ||
333 | #define INTERFACE_NONE 0x00 | ||
334 | #define INTERFACE_ANALOG_RGB 0x01 | ||
335 | #define INTERFACE_DVP0 0x02 | ||
336 | #define INTERFACE_DVP1 0x03 | ||
337 | #define INTERFACE_DFP_HIGH 0x04 | ||
338 | #define INTERFACE_DFP_LOW 0x05 | ||
339 | #define INTERFACE_DFP 0x06 | ||
340 | #define INTERFACE_LVDS0 0x07 | ||
341 | #define INTERFACE_LVDS1 0x08 | ||
342 | #define INTERFACE_LVDS0LVDS1 0x09 | ||
343 | #define INTERFACE_TMDS 0x0A | ||
344 | |||
345 | #define HW_LAYOUT_LCD_ONLY 0x01 | ||
346 | #define HW_LAYOUT_DVI_ONLY 0x02 | ||
347 | #define HW_LAYOUT_LCD_DVI 0x03 | ||
348 | #define HW_LAYOUT_LCD1_LCD2 0x04 | ||
349 | #define HW_LAYOUT_LCD_EXTERNAL_LCD2 0x10 | ||
350 | |||
351 | /* Definition Refresh Rate */ | ||
352 | #define REFRESH_50 50 | ||
353 | #define REFRESH_60 60 | ||
354 | #define REFRESH_75 75 | ||
355 | #define REFRESH_85 85 | ||
356 | #define REFRESH_100 100 | ||
357 | #define REFRESH_120 120 | ||
358 | |||
359 | /* Definition Sync Polarity*/ | ||
360 | #define NEGATIVE 1 | ||
361 | #define POSITIVE 0 | ||
362 | |||
363 | /*480x640@60 Sync Polarity (GTF) | ||
364 | */ | ||
365 | #define M480X640_R60_HSP NEGATIVE | ||
366 | #define M480X640_R60_VSP POSITIVE | ||
367 | |||
368 | /*640x480@60 Sync Polarity (VESA Mode) | ||
369 | */ | ||
370 | #define M640X480_R60_HSP NEGATIVE | ||
371 | #define M640X480_R60_VSP NEGATIVE | ||
372 | |||
373 | /*640x480@75 Sync Polarity (VESA Mode) | ||
374 | */ | ||
375 | #define M640X480_R75_HSP NEGATIVE | ||
376 | #define M640X480_R75_VSP NEGATIVE | ||
377 | |||
378 | /*640x480@85 Sync Polarity (VESA Mode) | ||
379 | */ | ||
380 | #define M640X480_R85_HSP NEGATIVE | ||
381 | #define M640X480_R85_VSP NEGATIVE | ||
382 | |||
383 | /*640x480@100 Sync Polarity (GTF Mode) | ||
384 | */ | ||
385 | #define M640X480_R100_HSP NEGATIVE | ||
386 | #define M640X480_R100_VSP POSITIVE | ||
387 | |||
388 | /*640x480@120 Sync Polarity (GTF Mode) | ||
389 | */ | ||
390 | #define M640X480_R120_HSP NEGATIVE | ||
391 | #define M640X480_R120_VSP POSITIVE | ||
392 | |||
393 | /*720x480@60 Sync Polarity (GTF Mode) | ||
394 | */ | ||
395 | #define M720X480_R60_HSP NEGATIVE | ||
396 | #define M720X480_R60_VSP POSITIVE | ||
397 | |||
398 | /*720x576@60 Sync Polarity (GTF Mode) | ||
399 | */ | ||
400 | #define M720X576_R60_HSP NEGATIVE | ||
401 | #define M720X576_R60_VSP POSITIVE | ||
402 | |||
403 | /*800x600@60 Sync Polarity (VESA Mode) | ||
404 | */ | ||
405 | #define M800X600_R60_HSP POSITIVE | ||
406 | #define M800X600_R60_VSP POSITIVE | ||
407 | |||
408 | /*800x600@75 Sync Polarity (VESA Mode) | ||
409 | */ | ||
410 | #define M800X600_R75_HSP POSITIVE | ||
411 | #define M800X600_R75_VSP POSITIVE | ||
412 | |||
413 | /*800x600@85 Sync Polarity (VESA Mode) | ||
414 | */ | ||
415 | #define M800X600_R85_HSP POSITIVE | ||
416 | #define M800X600_R85_VSP POSITIVE | ||
417 | |||
418 | /*800x600@100 Sync Polarity (GTF Mode) | ||
419 | */ | ||
420 | #define M800X600_R100_HSP NEGATIVE | ||
421 | #define M800X600_R100_VSP POSITIVE | ||
422 | |||
423 | /*800x600@120 Sync Polarity (GTF Mode) | ||
424 | */ | ||
425 | #define M800X600_R120_HSP NEGATIVE | ||
426 | #define M800X600_R120_VSP POSITIVE | ||
427 | |||
428 | /*800x480@60 Sync Polarity (CVT Mode) | ||
429 | */ | ||
430 | #define M800X480_R60_HSP NEGATIVE | ||
431 | #define M800X480_R60_VSP POSITIVE | ||
432 | |||
433 | /*848x480@60 Sync Polarity (CVT Mode) | ||
434 | */ | ||
435 | #define M848X480_R60_HSP NEGATIVE | ||
436 | #define M848X480_R60_VSP POSITIVE | ||
437 | |||
438 | /*852x480@60 Sync Polarity (GTF Mode) | ||
439 | */ | ||
440 | #define M852X480_R60_HSP NEGATIVE | ||
441 | #define M852X480_R60_VSP POSITIVE | ||
442 | |||
443 | /*1024x512@60 Sync Polarity (GTF Mode) | ||
444 | */ | ||
445 | #define M1024X512_R60_HSP NEGATIVE | ||
446 | #define M1024X512_R60_VSP POSITIVE | ||
447 | |||
448 | /*1024x600@60 Sync Polarity (GTF Mode) | ||
449 | */ | ||
450 | #define M1024X600_R60_HSP NEGATIVE | ||
451 | #define M1024X600_R60_VSP POSITIVE | ||
452 | |||
453 | /*1024x768@60 Sync Polarity (VESA Mode) | ||
454 | */ | ||
455 | #define M1024X768_R60_HSP NEGATIVE | ||
456 | #define M1024X768_R60_VSP NEGATIVE | ||
457 | |||
458 | /*1024x768@75 Sync Polarity (VESA Mode) | ||
459 | */ | ||
460 | #define M1024X768_R75_HSP POSITIVE | ||
461 | #define M1024X768_R75_VSP POSITIVE | ||
462 | |||
463 | /*1024x768@85 Sync Polarity (VESA Mode) | ||
464 | */ | ||
465 | #define M1024X768_R85_HSP POSITIVE | ||
466 | #define M1024X768_R85_VSP POSITIVE | ||
467 | |||
468 | /*1024x768@100 Sync Polarity (GTF Mode) | ||
469 | */ | ||
470 | #define M1024X768_R100_HSP NEGATIVE | ||
471 | #define M1024X768_R100_VSP POSITIVE | ||
472 | |||
473 | /*1152x864@75 Sync Polarity (VESA Mode) | ||
474 | */ | ||
475 | #define M1152X864_R75_HSP POSITIVE | ||
476 | #define M1152X864_R75_VSP POSITIVE | ||
477 | |||
478 | /*1280x720@60 Sync Polarity (GTF Mode) | ||
479 | */ | ||
480 | #define M1280X720_R60_HSP NEGATIVE | ||
481 | #define M1280X720_R60_VSP POSITIVE | ||
482 | |||
483 | /* 1280x768@50 Sync Polarity (GTF Mode) */ | ||
484 | #define M1280X768_R50_HSP NEGATIVE | ||
485 | #define M1280X768_R50_VSP POSITIVE | ||
486 | |||
487 | /*1280x768@60 Sync Polarity (GTF Mode) | ||
488 | */ | ||
489 | #define M1280X768_R60_HSP NEGATIVE | ||
490 | #define M1280X768_R60_VSP POSITIVE | ||
491 | |||
492 | /*1280x800@60 Sync Polarity (CVT Mode) | ||
493 | */ | ||
494 | #define M1280X800_R60_HSP NEGATIVE | ||
495 | #define M1280X800_R60_VSP POSITIVE | ||
496 | |||
497 | /*1280x960@60 Sync Polarity (VESA Mode) | ||
498 | */ | ||
499 | #define M1280X960_R60_HSP POSITIVE | ||
500 | #define M1280X960_R60_VSP POSITIVE | ||
501 | |||
502 | /*1280x1024@60 Sync Polarity (VESA Mode) | ||
503 | */ | ||
504 | #define M1280X1024_R60_HSP POSITIVE | ||
505 | #define M1280X1024_R60_VSP POSITIVE | ||
506 | |||
507 | /* 1360x768@60 Sync Polarity (CVT Mode) */ | ||
508 | #define M1360X768_R60_HSP POSITIVE | ||
509 | #define M1360X768_R60_VSP POSITIVE | ||
510 | |||
511 | /* 1360x768@60 Sync Polarity (CVT Reduce Blanking Mode) */ | ||
512 | #define M1360X768_RB_R60_HSP POSITIVE | ||
513 | #define M1360X768_RB_R60_VSP NEGATIVE | ||
514 | |||
515 | /* 1368x768@50 Sync Polarity (GTF Mode) */ | ||
516 | #define M1368X768_R50_HSP NEGATIVE | ||
517 | #define M1368X768_R50_VSP POSITIVE | ||
518 | |||
519 | /* 1368x768@60 Sync Polarity (VESA Mode) */ | ||
520 | #define M1368X768_R60_HSP NEGATIVE | ||
521 | #define M1368X768_R60_VSP POSITIVE | ||
522 | |||
523 | /*1280x1024@75 Sync Polarity (VESA Mode) | ||
524 | */ | ||
525 | #define M1280X1024_R75_HSP POSITIVE | ||
526 | #define M1280X1024_R75_VSP POSITIVE | ||
527 | |||
528 | /*1280x1024@85 Sync Polarity (VESA Mode) | ||
529 | */ | ||
530 | #define M1280X1024_R85_HSP POSITIVE | ||
531 | #define M1280X1024_R85_VSP POSITIVE | ||
532 | |||
533 | /*1440x1050@60 Sync Polarity (GTF Mode) | ||
534 | */ | ||
535 | #define M1440X1050_R60_HSP NEGATIVE | ||
536 | #define M1440X1050_R60_VSP POSITIVE | ||
537 | |||
538 | /*1600x1200@60 Sync Polarity (VESA Mode) | ||
539 | */ | ||
540 | #define M1600X1200_R60_HSP POSITIVE | ||
541 | #define M1600X1200_R60_VSP POSITIVE | ||
542 | |||
543 | /*1600x1200@75 Sync Polarity (VESA Mode) | ||
544 | */ | ||
545 | #define M1600X1200_R75_HSP POSITIVE | ||
546 | #define M1600X1200_R75_VSP POSITIVE | ||
547 | |||
548 | /* 1680x1050@60 Sync Polarity (CVT Mode) */ | ||
549 | #define M1680x1050_R60_HSP NEGATIVE | ||
550 | #define M1680x1050_R60_VSP NEGATIVE | ||
551 | |||
552 | /* 1680x1050@60 Sync Polarity (CVT Reduce Blanking Mode) */ | ||
553 | #define M1680x1050_RB_R60_HSP POSITIVE | ||
554 | #define M1680x1050_RB_R60_VSP NEGATIVE | ||
555 | |||
556 | /* 1680x1050@75 Sync Polarity (CVT Mode) */ | ||
557 | #define M1680x1050_R75_HSP NEGATIVE | ||
558 | #define M1680x1050_R75_VSP POSITIVE | ||
559 | |||
560 | /*1920x1080@60 Sync Polarity (CVT Mode) | ||
561 | */ | ||
562 | #define M1920X1080_R60_HSP NEGATIVE | ||
563 | #define M1920X1080_R60_VSP POSITIVE | ||
564 | |||
565 | /* 1920x1080@60 Sync Polarity (CVT Reduce Blanking Mode) */ | ||
566 | #define M1920X1080_RB_R60_HSP POSITIVE | ||
567 | #define M1920X1080_RB_R60_VSP NEGATIVE | ||
568 | |||
569 | /*1920x1440@60 Sync Polarity (VESA Mode) | ||
570 | */ | ||
571 | #define M1920X1440_R60_HSP NEGATIVE | ||
572 | #define M1920X1440_R60_VSP POSITIVE | ||
573 | |||
574 | /*1920x1440@75 Sync Polarity (VESA Mode) | ||
575 | */ | ||
576 | #define M1920X1440_R75_HSP NEGATIVE | ||
577 | #define M1920X1440_R75_VSP POSITIVE | ||
578 | |||
579 | #if 0 | ||
580 | /* 1400x1050@60 Sync Polarity (VESA Mode) */ | ||
581 | #define M1400X1050_R60_HSP NEGATIVE | ||
582 | #define M1400X1050_R60_VSP NEGATIVE | ||
583 | #endif | ||
584 | |||
585 | /* 1400x1050@60 Sync Polarity (CVT Mode) */ | ||
586 | #define M1400X1050_R60_HSP NEGATIVE | ||
587 | #define M1400X1050_R60_VSP POSITIVE | ||
588 | |||
589 | /* 1400x1050@60 Sync Polarity (CVT Reduce Blanking Mode) */ | ||
590 | #define M1400X1050_RB_R60_HSP POSITIVE | ||
591 | #define M1400X1050_RB_R60_VSP NEGATIVE | ||
592 | |||
593 | /* 1400x1050@75 Sync Polarity (CVT Mode) */ | ||
594 | #define M1400X1050_R75_HSP NEGATIVE | ||
595 | #define M1400X1050_R75_VSP POSITIVE | ||
596 | |||
597 | /* 960x600@60 Sync Polarity (CVT Mode) */ | ||
598 | #define M960X600_R60_HSP NEGATIVE | ||
599 | #define M960X600_R60_VSP POSITIVE | ||
600 | |||
601 | /* 1000x600@60 Sync Polarity (GTF Mode) */ | ||
602 | #define M1000X600_R60_HSP NEGATIVE | ||
603 | #define M1000X600_R60_VSP POSITIVE | ||
604 | |||
605 | /* 1024x576@60 Sync Polarity (GTF Mode) */ | ||
606 | #define M1024X576_R60_HSP NEGATIVE | ||
607 | #define M1024X576_R60_VSP POSITIVE | ||
608 | |||
609 | /*1024x600@60 Sync Polarity (GTF Mode)*/ | ||
610 | #define M1024X600_R60_HSP NEGATIVE | ||
611 | #define M1024X600_R60_VSP POSITIVE | ||
612 | |||
613 | /* 1088x612@60 Sync Polarity (CVT Mode) */ | ||
614 | #define M1088X612_R60_HSP NEGATIVE | ||
615 | #define M1088X612_R60_VSP POSITIVE | ||
616 | |||
617 | /* 1152x720@60 Sync Polarity (CVT Mode) */ | ||
618 | #define M1152X720_R60_HSP NEGATIVE | ||
619 | #define M1152X720_R60_VSP POSITIVE | ||
620 | |||
621 | /* 1200x720@60 Sync Polarity (GTF Mode) */ | ||
622 | #define M1200X720_R60_HSP NEGATIVE | ||
623 | #define M1200X720_R60_VSP POSITIVE | ||
624 | |||
625 | /* 1280x600@60 Sync Polarity (GTF Mode) */ | ||
626 | #define M1280x600_R60_HSP NEGATIVE | ||
627 | #define M1280x600_R60_VSP POSITIVE | ||
628 | |||
629 | /* 1280x720@50 Sync Polarity (GTF Mode) */ | ||
630 | #define M1280X720_R50_HSP NEGATIVE | ||
631 | #define M1280X720_R50_VSP POSITIVE | ||
632 | |||
633 | /* 1280x720@60 Sync Polarity (CEA Mode) */ | ||
634 | #define M1280X720_CEA_R60_HSP POSITIVE | ||
635 | #define M1280X720_CEA_R60_VSP POSITIVE | ||
636 | |||
637 | /* 1440x900@60 Sync Polarity (CVT Mode) */ | ||
638 | #define M1440X900_R60_HSP NEGATIVE | ||
639 | #define M1440X900_R60_VSP POSITIVE | ||
640 | |||
641 | /* 1440x900@75 Sync Polarity (CVT Mode) */ | ||
642 | #define M1440X900_R75_HSP NEGATIVE | ||
643 | #define M1440X900_R75_VSP POSITIVE | ||
644 | |||
645 | /* 1440x900@60 Sync Polarity (CVT Reduce Blanking Mode) */ | ||
646 | #define M1440X900_RB_R60_HSP POSITIVE | ||
647 | #define M1440X900_RB_R60_VSP NEGATIVE | ||
648 | |||
649 | /* 1600x900@60 Sync Polarity (CVT Mode) */ | ||
650 | #define M1600X900_R60_HSP NEGATIVE | ||
651 | #define M1600X900_R60_VSP POSITIVE | ||
652 | |||
653 | /* 1600x900@60 Sync Polarity (CVT Reduce Blanking Mode) */ | ||
654 | #define M1600X900_RB_R60_HSP POSITIVE | ||
655 | #define M1600X900_RB_R60_VSP NEGATIVE | ||
656 | |||
657 | /* 1600x1024@60 Sync Polarity (GTF Mode) */ | ||
658 | #define M1600X1024_R60_HSP NEGATIVE | ||
659 | #define M1600X1024_R60_VSP POSITIVE | ||
660 | |||
661 | /* 1792x1344@60 Sync Polarity (DMT Mode) */ | ||
662 | #define M1792x1344_R60_HSP NEGATIVE | ||
663 | #define M1792x1344_R60_VSP POSITIVE | ||
664 | |||
665 | /* 1856x1392@60 Sync Polarity (DMT Mode) */ | ||
666 | #define M1856x1392_R60_HSP NEGATIVE | ||
667 | #define M1856x1392_R60_VSP POSITIVE | ||
668 | |||
669 | /* 1920x1200@60 Sync Polarity (CVT Mode) */ | ||
670 | #define M1920X1200_R60_HSP NEGATIVE | ||
671 | #define M1920X1200_R60_VSP POSITIVE | ||
672 | |||
673 | /* 1920x1200@60 Sync Polarity (CVT Reduce Blanking Mode) */ | ||
674 | #define M1920X1200_RB_R60_HSP POSITIVE | ||
675 | #define M1920X1200_RB_R60_VSP NEGATIVE | ||
676 | |||
677 | /* 1920x1080@60 Sync Polarity (CEA Mode) */ | ||
678 | #define M1920X1080_CEA_R60_HSP POSITIVE | ||
679 | #define M1920X1080_CEA_R60_VSP POSITIVE | ||
680 | |||
681 | /* 2048x1536@60 Sync Polarity (CVT Mode) */ | ||
682 | #define M2048x1536_R60_HSP NEGATIVE | ||
683 | #define M2048x1536_R60_VSP POSITIVE | ||
684 | |||
685 | /* define PLL index: */ | ||
686 | #define CLK_25_175M 25175000 | ||
687 | #define CLK_26_880M 26880000 | ||
688 | #define CLK_29_581M 29581000 | ||
689 | #define CLK_31_490M 31490000 | ||
690 | #define CLK_31_500M 31500000 | ||
691 | #define CLK_31_728M 31728000 | ||
692 | #define CLK_32_668M 32688000 | ||
693 | #define CLK_36_000M 36000000 | ||
694 | #define CLK_40_000M 40000000 | ||
695 | #define CLK_41_291M 41291000 | ||
696 | #define CLK_43_163M 43163000 | ||
697 | #define CLK_45_250M 45250000 /* 45.46MHz */ | ||
698 | #define CLK_46_000M 46000000 | ||
699 | #define CLK_46_996M 46996000 | ||
700 | #define CLK_48_000M 48000000 | ||
701 | #define CLK_48_875M 48875000 | ||
702 | #define CLK_49_500M 49500000 | ||
703 | #define CLK_52_406M 52406000 | ||
704 | #define CLK_52_977M 52977000 | ||
705 | #define CLK_56_250M 56250000 | ||
706 | #define CLK_60_466M 60466000 | ||
707 | #define CLK_61_500M 61500000 | ||
708 | #define CLK_65_000M 65000000 | ||
709 | #define CLK_65_178M 65178000 | ||
710 | #define CLK_66_750M 66750000 /* 67.116MHz */ | ||
711 | #define CLK_68_179M 68179000 | ||
712 | #define CLK_69_924M 69924000 | ||
713 | #define CLK_70_159M 70159000 | ||
714 | #define CLK_72_000M 72000000 | ||
715 | #define CLK_74_270M 74270000 | ||
716 | #define CLK_78_750M 78750000 | ||
717 | #define CLK_80_136M 80136000 | ||
718 | #define CLK_83_375M 83375000 | ||
719 | #define CLK_83_950M 83950000 | ||
720 | #define CLK_84_750M 84750000 /* 84.537Mhz */ | ||
721 | #define CLK_85_860M 85860000 | ||
722 | #define CLK_88_750M 88750000 | ||
723 | #define CLK_94_500M 94500000 | ||
724 | #define CLK_97_750M 97750000 | ||
725 | #define CLK_101_000M 101000000 | ||
726 | #define CLK_106_500M 106500000 | ||
727 | #define CLK_108_000M 108000000 | ||
728 | #define CLK_113_309M 113309000 | ||
729 | #define CLK_118_840M 118840000 | ||
730 | #define CLK_119_000M 119000000 | ||
731 | #define CLK_121_750M 121750000 /* 121.704MHz */ | ||
732 | #define CLK_125_104M 125104000 | ||
733 | #define CLK_133_308M 133308000 | ||
734 | #define CLK_135_000M 135000000 | ||
735 | #define CLK_136_700M 136700000 | ||
736 | #define CLK_138_400M 138400000 | ||
737 | #define CLK_146_760M 146760000 | ||
738 | #define CLK_148_500M 148500000 | ||
739 | |||
740 | #define CLK_153_920M 153920000 | ||
741 | #define CLK_156_000M 156000000 | ||
742 | #define CLK_157_500M 157500000 | ||
743 | #define CLK_162_000M 162000000 | ||
744 | #define CLK_187_000M 187000000 | ||
745 | #define CLK_193_295M 193295000 | ||
746 | #define CLK_202_500M 202500000 | ||
747 | #define CLK_204_000M 204000000 | ||
748 | #define CLK_218_500M 218500000 | ||
749 | #define CLK_234_000M 234000000 | ||
750 | #define CLK_267_250M 267250000 | ||
751 | #define CLK_297_500M 297500000 | ||
752 | #define CLK_74_481M 74481000 | ||
753 | #define CLK_172_798M 172798000 | ||
754 | #define CLK_122_614M 122614000 | ||
755 | |||
756 | /* CLE266 PLL value | ||
757 | */ | ||
758 | #define CLE266_PLL_25_175M 0x0000C763 | ||
759 | #define CLE266_PLL_26_880M 0x0000440F | ||
760 | #define CLE266_PLL_29_581M 0x00008421 | ||
761 | #define CLE266_PLL_31_490M 0x00004721 | ||
762 | #define CLE266_PLL_31_500M 0x0000C3B5 | ||
763 | #define CLE266_PLL_31_728M 0x0000471F | ||
764 | #define CLE266_PLL_32_668M 0x0000C449 | ||
765 | #define CLE266_PLL_36_000M 0x0000C5E5 | ||
766 | #define CLE266_PLL_40_000M 0x0000C459 | ||
767 | #define CLE266_PLL_41_291M 0x00004417 | ||
768 | #define CLE266_PLL_43_163M 0x0000C579 | ||
769 | #define CLE266_PLL_45_250M 0x0000C57F /* 45.46MHz */ | ||
770 | #define CLE266_PLL_46_000M 0x0000875A | ||
771 | #define CLE266_PLL_46_996M 0x0000C4E9 | ||
772 | #define CLE266_PLL_48_000M 0x00001443 | ||
773 | #define CLE266_PLL_48_875M 0x00001D63 | ||
774 | #define CLE266_PLL_49_500M 0x00008653 | ||
775 | #define CLE266_PLL_52_406M 0x0000C475 | ||
776 | #define CLE266_PLL_52_977M 0x00004525 | ||
777 | #define CLE266_PLL_56_250M 0x000047B7 | ||
778 | #define CLE266_PLL_60_466M 0x0000494C | ||
779 | #define CLE266_PLL_61_500M 0x00001456 | ||
780 | #define CLE266_PLL_65_000M 0x000086ED | ||
781 | #define CLE266_PLL_65_178M 0x0000855B | ||
782 | #define CLE266_PLL_66_750M 0x0000844B /* 67.116MHz */ | ||
783 | #define CLE266_PLL_68_179M 0x00000413 | ||
784 | #define CLE266_PLL_69_924M 0x00001153 | ||
785 | #define CLE266_PLL_70_159M 0x00001462 | ||
786 | #define CLE266_PLL_72_000M 0x00001879 | ||
787 | #define CLE266_PLL_74_270M 0x00004853 | ||
788 | #define CLE266_PLL_78_750M 0x00004321 | ||
789 | #define CLE266_PLL_80_136M 0x0000051C | ||
790 | #define CLE266_PLL_83_375M 0x0000C25D | ||
791 | #define CLE266_PLL_83_950M 0x00000729 | ||
792 | #define CLE266_PLL_84_750M 0x00008576 /* 84.537MHz */ | ||
793 | #define CLE266_PLL_85_860M 0x00004754 | ||
794 | #define CLE266_PLL_88_750M 0x0000051F | ||
795 | #define CLE266_PLL_94_500M 0x00000521 | ||
796 | #define CLE266_PLL_97_750M 0x00004652 | ||
797 | #define CLE266_PLL_101_000M 0x0000497F | ||
798 | #define CLE266_PLL_106_500M 0x00008477 /* 106.491463 MHz */ | ||
799 | #define CLE266_PLL_108_000M 0x00008479 | ||
800 | #define CLE266_PLL_113_309M 0x00000C5F | ||
801 | #define CLE266_PLL_118_840M 0x00004553 | ||
802 | #define CLE266_PLL_119_000M 0x00000D6C | ||
803 | #define CLE266_PLL_121_750M 0x00004555 /* 121.704MHz */ | ||
804 | #define CLE266_PLL_125_104M 0x000006B5 | ||
805 | #define CLE266_PLL_133_308M 0x0000465F | ||
806 | #define CLE266_PLL_135_000M 0x0000455E | ||
807 | #define CLE266_PLL_136_700M 0x00000C73 | ||
808 | #define CLE266_PLL_138_400M 0x00000957 | ||
809 | #define CLE266_PLL_146_760M 0x00004567 | ||
810 | #define CLE266_PLL_148_500M 0x00000853 | ||
811 | #define CLE266_PLL_153_920M 0x00000856 | ||
812 | #define CLE266_PLL_156_000M 0x0000456D | ||
813 | #define CLE266_PLL_157_500M 0x000005B7 | ||
814 | #define CLE266_PLL_162_000M 0x00004571 | ||
815 | #define CLE266_PLL_187_000M 0x00000976 | ||
816 | #define CLE266_PLL_193_295M 0x0000086C | ||
817 | #define CLE266_PLL_202_500M 0x00000763 | ||
818 | #define CLE266_PLL_204_000M 0x00000764 | ||
819 | #define CLE266_PLL_218_500M 0x0000065C | ||
820 | #define CLE266_PLL_234_000M 0x00000662 | ||
821 | #define CLE266_PLL_267_250M 0x00000670 | ||
822 | #define CLE266_PLL_297_500M 0x000005E6 | ||
823 | #define CLE266_PLL_74_481M 0x0000051A | ||
824 | #define CLE266_PLL_172_798M 0x00004579 | ||
825 | #define CLE266_PLL_122_614M 0x0000073C | ||
826 | |||
827 | /* K800 PLL value | ||
828 | */ | ||
829 | #define K800_PLL_25_175M 0x00539001 | ||
830 | #define K800_PLL_26_880M 0x001C8C80 | ||
831 | #define K800_PLL_29_581M 0x00409080 | ||
832 | #define K800_PLL_31_490M 0x006F9001 | ||
833 | #define K800_PLL_31_500M 0x008B9002 | ||
834 | #define K800_PLL_31_728M 0x00AF9003 | ||
835 | #define K800_PLL_32_668M 0x00909002 | ||
836 | #define K800_PLL_36_000M 0x009F9002 | ||
837 | #define K800_PLL_40_000M 0x00578C02 | ||
838 | #define K800_PLL_41_291M 0x00438C01 | ||
839 | #define K800_PLL_43_163M 0x00778C03 | ||
840 | #define K800_PLL_45_250M 0x007D8C83 /* 45.46MHz */ | ||
841 | #define K800_PLL_46_000M 0x00658C02 | ||
842 | #define K800_PLL_46_996M 0x00818C83 | ||
843 | #define K800_PLL_48_000M 0x00848C83 | ||
844 | #define K800_PLL_48_875M 0x00508C81 | ||
845 | #define K800_PLL_49_500M 0x00518C01 | ||
846 | #define K800_PLL_52_406M 0x00738C02 | ||
847 | #define K800_PLL_52_977M 0x00928C83 | ||
848 | #define K800_PLL_56_250M 0x007C8C02 | ||
849 | #define K800_PLL_60_466M 0x00A78C83 | ||
850 | #define K800_PLL_61_500M 0x00AA8C83 | ||
851 | #define K800_PLL_65_000M 0x006B8C01 | ||
852 | #define K800_PLL_65_178M 0x00B48C83 | ||
853 | #define K800_PLL_66_750M 0x00948C82 /* 67.116MHz */ | ||
854 | #define K800_PLL_68_179M 0x00708C01 | ||
855 | #define K800_PLL_69_924M 0x00C18C83 | ||
856 | #define K800_PLL_70_159M 0x00C28C83 | ||
857 | #define K800_PLL_72_000M 0x009F8C82 | ||
858 | #define K800_PLL_74_270M 0x00ce0c03 | ||
859 | #define K800_PLL_78_750M 0x00408801 | ||
860 | #define K800_PLL_80_136M 0x00428801 | ||
861 | #define K800_PLL_83_375M 0x005B0882 | ||
862 | #define K800_PLL_83_950M 0x00738803 | ||
863 | #define K800_PLL_84_750M 0x00748883 /* 84.477MHz */ | ||
864 | #define K800_PLL_85_860M 0x00768883 | ||
865 | #define K800_PLL_88_750M 0x007A8883 | ||
866 | #define K800_PLL_94_500M 0x00828803 | ||
867 | #define K800_PLL_97_750M 0x00878883 | ||
868 | #define K800_PLL_101_000M 0x008B8883 | ||
869 | #define K800_PLL_106_500M 0x00758882 /* 106.491463 MHz */ | ||
870 | #define K800_PLL_108_000M 0x00778882 | ||
871 | #define K800_PLL_113_309M 0x005D8881 | ||
872 | #define K800_PLL_118_840M 0x00A48883 | ||
873 | #define K800_PLL_119_000M 0x00838882 | ||
874 | #define K800_PLL_121_750M 0x00A88883 /* 121.704MHz */ | ||
875 | #define K800_PLL_125_104M 0x00688801 | ||
876 | #define K800_PLL_133_308M 0x005D8801 | ||
877 | #define K800_PLL_135_000M 0x001A4081 | ||
878 | #define K800_PLL_136_700M 0x00BD8883 | ||
879 | #define K800_PLL_138_400M 0x00728881 | ||
880 | #define K800_PLL_146_760M 0x00CC8883 | ||
881 | #define K800_PLL_148_500M 0x00ce0803 | ||
882 | #define K800_PLL_153_920M 0x00548482 | ||
883 | #define K800_PLL_156_000M 0x006B8483 | ||
884 | #define K800_PLL_157_500M 0x00142080 | ||
885 | #define K800_PLL_162_000M 0x006F8483 | ||
886 | #define K800_PLL_187_000M 0x00818483 | ||
887 | #define K800_PLL_193_295M 0x004F8481 | ||
888 | #define K800_PLL_202_500M 0x00538481 | ||
889 | #define K800_PLL_204_000M 0x008D8483 | ||
890 | #define K800_PLL_218_500M 0x00978483 | ||
891 | #define K800_PLL_234_000M 0x00608401 | ||
892 | #define K800_PLL_267_250M 0x006E8481 | ||
893 | #define K800_PLL_297_500M 0x00A48402 | ||
894 | #define K800_PLL_74_481M 0x007B8C81 | ||
895 | #define K800_PLL_172_798M 0x00778483 | ||
896 | #define K800_PLL_122_614M 0x00878882 | ||
897 | |||
898 | /* PLL for VT3324 */ | ||
899 | #define CX700_25_175M 0x008B1003 | ||
900 | #define CX700_26_719M 0x00931003 | ||
901 | #define CX700_26_880M 0x00941003 | ||
902 | #define CX700_29_581M 0x00A49003 | ||
903 | #define CX700_31_490M 0x00AE1003 | ||
904 | #define CX700_31_500M 0x00AE1003 | ||
905 | #define CX700_31_728M 0x00AF1003 | ||
906 | #define CX700_32_668M 0x00B51003 | ||
907 | #define CX700_36_000M 0x00C81003 | ||
908 | #define CX700_40_000M 0x006E0C03 | ||
909 | #define CX700_41_291M 0x00710C03 | ||
910 | #define CX700_43_163M 0x00770C03 | ||
911 | #define CX700_45_250M 0x007D0C03 /* 45.46MHz */ | ||
912 | #define CX700_46_000M 0x007F0C03 | ||
913 | #define CX700_46_996M 0x00818C83 | ||
914 | #define CX700_48_000M 0x00840C03 | ||
915 | #define CX700_48_875M 0x00508C81 | ||
916 | #define CX700_49_500M 0x00880C03 | ||
917 | #define CX700_52_406M 0x00730C02 | ||
918 | #define CX700_52_977M 0x00920C03 | ||
919 | #define CX700_56_250M 0x009B0C03 | ||
920 | #define CX700_60_466M 0x00460C00 | ||
921 | #define CX700_61_500M 0x00AA0C03 | ||
922 | #define CX700_65_000M 0x006B0C01 | ||
923 | #define CX700_65_178M 0x006B0C01 | ||
924 | #define CX700_66_750M 0x00940C02 /*67.116MHz */ | ||
925 | #define CX700_68_179M 0x00BC0C03 | ||
926 | #define CX700_69_924M 0x00C10C03 | ||
927 | #define CX700_70_159M 0x00C20C03 | ||
928 | #define CX700_72_000M 0x009F0C02 | ||
929 | #define CX700_74_270M 0x00CE0C03 | ||
930 | #define CX700_74_481M 0x00CE0C03 | ||
931 | #define CX700_78_750M 0x006C0803 | ||
932 | #define CX700_80_136M 0x006E0803 | ||
933 | #define CX700_83_375M 0x005B0882 | ||
934 | #define CX700_83_950M 0x00730803 | ||
935 | #define CX700_84_750M 0x00740803 /* 84.537Mhz */ | ||
936 | #define CX700_85_860M 0x00760803 | ||
937 | #define CX700_88_750M 0x00AC8885 | ||
938 | #define CX700_94_500M 0x00820803 | ||
939 | #define CX700_97_750M 0x00870803 | ||
940 | #define CX700_101_000M 0x008B0803 | ||
941 | #define CX700_106_500M 0x00750802 | ||
942 | #define CX700_108_000M 0x00950803 | ||
943 | #define CX700_113_309M 0x005D0801 | ||
944 | #define CX700_118_840M 0x00A40803 | ||
945 | #define CX700_119_000M 0x00830802 | ||
946 | #define CX700_121_750M 0x00420800 /* 121.704MHz */ | ||
947 | #define CX700_125_104M 0x00AD0803 | ||
948 | #define CX700_133_308M 0x00930802 | ||
949 | #define CX700_135_000M 0x00950802 | ||
950 | #define CX700_136_700M 0x00BD0803 | ||
951 | #define CX700_138_400M 0x00720801 | ||
952 | #define CX700_146_760M 0x00CC0803 | ||
953 | #define CX700_148_500M 0x00a40802 | ||
954 | #define CX700_153_920M 0x00540402 | ||
955 | #define CX700_156_000M 0x006B0403 | ||
956 | #define CX700_157_500M 0x006C0403 | ||
957 | #define CX700_162_000M 0x006F0403 | ||
958 | #define CX700_172_798M 0x00770403 | ||
959 | #define CX700_187_000M 0x00810403 | ||
960 | #define CX700_193_295M 0x00850403 | ||
961 | #define CX700_202_500M 0x008C0403 | ||
962 | #define CX700_204_000M 0x008D0403 | ||
963 | #define CX700_218_500M 0x00970403 | ||
964 | #define CX700_234_000M 0x00600401 | ||
965 | #define CX700_267_250M 0x00B90403 | ||
966 | #define CX700_297_500M 0x00CE0403 | ||
967 | #define CX700_122_614M 0x00870802 | ||
968 | |||
969 | /* Definition CRTC Timing Index */ | ||
970 | #define H_TOTAL_INDEX 0 | ||
971 | #define H_ADDR_INDEX 1 | ||
972 | #define H_BLANK_START_INDEX 2 | ||
973 | #define H_BLANK_END_INDEX 3 | ||
974 | #define H_SYNC_START_INDEX 4 | ||
975 | #define H_SYNC_END_INDEX 5 | ||
976 | #define V_TOTAL_INDEX 6 | ||
977 | #define V_ADDR_INDEX 7 | ||
978 | #define V_BLANK_START_INDEX 8 | ||
979 | #define V_BLANK_END_INDEX 9 | ||
980 | #define V_SYNC_START_INDEX 10 | ||
981 | #define V_SYNC_END_INDEX 11 | ||
982 | #define H_TOTAL_SHADOW_INDEX 12 | ||
983 | #define H_BLANK_END_SHADOW_INDEX 13 | ||
984 | #define V_TOTAL_SHADOW_INDEX 14 | ||
985 | #define V_ADDR_SHADOW_INDEX 15 | ||
986 | #define V_BLANK_SATRT_SHADOW_INDEX 16 | ||
987 | #define V_BLANK_END_SHADOW_INDEX 17 | ||
988 | #define V_SYNC_SATRT_SHADOW_INDEX 18 | ||
989 | #define V_SYNC_END_SHADOW_INDEX 19 | ||
990 | |||
991 | /* Definition Video Mode Pixel Clock (picoseconds) | ||
992 | */ | ||
993 | #define RES_480X640_60HZ_PIXCLOCK 39722 | ||
994 | #define RES_640X480_60HZ_PIXCLOCK 39722 | ||
995 | #define RES_640X480_75HZ_PIXCLOCK 31747 | ||
996 | #define RES_640X480_85HZ_PIXCLOCK 27777 | ||
997 | #define RES_640X480_100HZ_PIXCLOCK 23168 | ||
998 | #define RES_640X480_120HZ_PIXCLOCK 19081 | ||
999 | #define RES_720X480_60HZ_PIXCLOCK 37020 | ||
1000 | #define RES_720X576_60HZ_PIXCLOCK 30611 | ||
1001 | #define RES_800X600_60HZ_PIXCLOCK 25000 | ||
1002 | #define RES_800X600_75HZ_PIXCLOCK 20203 | ||
1003 | #define RES_800X600_85HZ_PIXCLOCK 17777 | ||
1004 | #define RES_800X600_100HZ_PIXCLOCK 14667 | ||
1005 | #define RES_800X600_120HZ_PIXCLOCK 11912 | ||
1006 | #define RES_800X480_60HZ_PIXCLOCK 33805 | ||
1007 | #define RES_848X480_60HZ_PIXCLOCK 31756 | ||
1008 | #define RES_856X480_60HZ_PIXCLOCK 31518 | ||
1009 | #define RES_1024X512_60HZ_PIXCLOCK 24218 | ||
1010 | #define RES_1024X600_60HZ_PIXCLOCK 20460 | ||
1011 | #define RES_1024X768_60HZ_PIXCLOCK 15385 | ||
1012 | #define RES_1024X768_75HZ_PIXCLOCK 12699 | ||
1013 | #define RES_1024X768_85HZ_PIXCLOCK 10582 | ||
1014 | #define RES_1024X768_100HZ_PIXCLOCK 8825 | ||
1015 | #define RES_1152X864_75HZ_PIXCLOCK 9259 | ||
1016 | #define RES_1280X768_60HZ_PIXCLOCK 12480 | ||
1017 | #define RES_1280X800_60HZ_PIXCLOCK 11994 | ||
1018 | #define RES_1280X960_60HZ_PIXCLOCK 9259 | ||
1019 | #define RES_1280X1024_60HZ_PIXCLOCK 9260 | ||
1020 | #define RES_1280X1024_75HZ_PIXCLOCK 7408 | ||
1021 | #define RES_1280X768_85HZ_PIXCLOCK 6349 | ||
1022 | #define RES_1440X1050_60HZ_PIXCLOCK 7993 | ||
1023 | #define RES_1600X1200_60HZ_PIXCLOCK 6172 | ||
1024 | #define RES_1600X1200_75HZ_PIXCLOCK 4938 | ||
1025 | #define RES_1280X720_60HZ_PIXCLOCK 13426 | ||
1026 | #define RES_1920X1080_60HZ_PIXCLOCK 5787 | ||
1027 | #define RES_1400X1050_60HZ_PIXCLOCK 8214 | ||
1028 | #define RES_1400X1050_75HZ_PIXCLOCK 6410 | ||
1029 | #define RES_1368X768_60HZ_PIXCLOCK 11647 | ||
1030 | #define RES_960X600_60HZ_PIXCLOCK 22099 | ||
1031 | #define RES_1000X600_60HZ_PIXCLOCK 20834 | ||
1032 | #define RES_1024X576_60HZ_PIXCLOCK 21278 | ||
1033 | #define RES_1088X612_60HZ_PIXCLOCK 18877 | ||
1034 | #define RES_1152X720_60HZ_PIXCLOCK 14981 | ||
1035 | #define RES_1200X720_60HZ_PIXCLOCK 14253 | ||
1036 | #define RES_1280X600_60HZ_PIXCLOCK 16260 | ||
1037 | #define RES_1280X720_50HZ_PIXCLOCK 16538 | ||
1038 | #define RES_1280X768_50HZ_PIXCLOCK 15342 | ||
1039 | #define RES_1366X768_50HZ_PIXCLOCK 14301 | ||
1040 | #define RES_1366X768_60HZ_PIXCLOCK 11646 | ||
1041 | #define RES_1360X768_60HZ_PIXCLOCK 11799 | ||
1042 | #define RES_1440X900_60HZ_PIXCLOCK 9390 | ||
1043 | #define RES_1440X900_75HZ_PIXCLOCK 7315 | ||
1044 | #define RES_1600X900_60HZ_PIXCLOCK 8415 | ||
1045 | #define RES_1600X1024_60HZ_PIXCLOCK 7315 | ||
1046 | #define RES_1680X1050_60HZ_PIXCLOCK 6814 | ||
1047 | #define RES_1680X1050_75HZ_PIXCLOCK 5348 | ||
1048 | #define RES_1792X1344_60HZ_PIXCLOCK 4902 | ||
1049 | #define RES_1856X1392_60HZ_PIXCLOCK 4577 | ||
1050 | #define RES_1920X1200_60HZ_PIXCLOCK 5173 | ||
1051 | #define RES_1920X1440_60HZ_PIXCLOCK 4274 | ||
1052 | #define RES_1920X1440_75HZ_PIXCLOCK 3367 | ||
1053 | #define RES_2048X1536_60HZ_PIXCLOCK 3742 | ||
1054 | |||
1055 | #define RES_1360X768_RB_60HZ_PIXCLOCK 13889 | ||
1056 | #define RES_1400X1050_RB_60HZ_PIXCLOCK 9901 | ||
1057 | #define RES_1440X900_RB_60HZ_PIXCLOCK 11268 | ||
1058 | #define RES_1600X900_RB_60HZ_PIXCLOCK 10230 | ||
1059 | #define RES_1680X1050_RB_60HZ_PIXCLOCK 8403 | ||
1060 | #define RES_1920X1080_RB_60HZ_PIXCLOCK 7225 | ||
1061 | #define RES_1920X1200_RB_60HZ_PIXCLOCK 6497 | ||
1062 | |||
1063 | /* LCD display method | ||
1064 | */ | ||
1065 | #define LCD_EXPANDSION 0x00 | ||
1066 | #define LCD_CENTERING 0x01 | ||
1067 | |||
1068 | /* LCD mode | ||
1069 | */ | ||
1070 | #define LCD_OPENLDI 0x00 | ||
1071 | #define LCD_SPWG 0x01 | ||
1072 | |||
1073 | /* Define display timing | ||
1074 | */ | ||
1075 | struct display_timing { | ||
1076 | u16 hor_total; | ||
1077 | u16 hor_addr; | ||
1078 | u16 hor_blank_start; | ||
1079 | u16 hor_blank_end; | ||
1080 | u16 hor_sync_start; | ||
1081 | u16 hor_sync_end; | ||
1082 | u16 ver_total; | ||
1083 | u16 ver_addr; | ||
1084 | u16 ver_blank_start; | ||
1085 | u16 ver_blank_end; | ||
1086 | u16 ver_sync_start; | ||
1087 | u16 ver_sync_end; | ||
1088 | }; | ||
1089 | |||
1090 | struct crt_mode_table { | ||
1091 | int refresh_rate; | ||
1092 | unsigned long clk; | ||
1093 | int h_sync_polarity; | ||
1094 | int v_sync_polarity; | ||
1095 | struct display_timing crtc; | ||
1096 | }; | ||
1097 | |||
1098 | struct io_reg { | ||
1099 | int port; | ||
1100 | u8 index; | ||
1101 | u8 mask; | ||
1102 | u8 value; | ||
1103 | }; | ||
1104 | |||
1105 | #endif /* __SHARE_H__ */ | ||
diff --git a/drivers/video/via/tbl1636.c b/drivers/video/via/tbl1636.c new file mode 100644 index 000000000000..2d8453429d4a --- /dev/null +++ b/drivers/video/via/tbl1636.c | |||
@@ -0,0 +1,71 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #include "global.h" | ||
23 | struct IODATA COMMON_INIT_TBL_VT1636[] = { | ||
24 | /* Index, Mask, Value */ | ||
25 | /* Set panel power sequence timing */ | ||
26 | {0x10, 0xC0, 0x00}, | ||
27 | /* T1: VDD on - Data on. Each increment is 1 ms. (50ms = 031h) */ | ||
28 | {0x0B, 0xFF, 0x40}, | ||
29 | /* T2: Data on - Backlight on. Each increment is 2 ms. (210ms = 068h) */ | ||
30 | {0x0C, 0xFF, 0x31}, | ||
31 | /* T3: Backlight off -Data off. Each increment is 2 ms. (210ms = 068h)*/ | ||
32 | {0x0D, 0xFF, 0x31}, | ||
33 | /* T4: Data off - VDD off. Each increment is 1 ms. (50ms = 031h) */ | ||
34 | {0x0E, 0xFF, 0x68}, | ||
35 | /* T5: VDD off - VDD on. Each increment is 100 ms. (500ms = 04h) */ | ||
36 | {0x0F, 0xFF, 0x68}, | ||
37 | /* LVDS output power up */ | ||
38 | {0x09, 0xA0, 0xA0}, | ||
39 | /* turn on back light */ | ||
40 | {0x10, 0x33, 0x13} | ||
41 | }; | ||
42 | |||
43 | struct IODATA DUAL_CHANNEL_ENABLE_TBL_VT1636[] = { | ||
44 | /* Index, Mask, Value */ | ||
45 | {0x08, 0xF0, 0xE0} /* Input Data Mode Select */ | ||
46 | }; | ||
47 | |||
48 | struct IODATA SINGLE_CHANNEL_ENABLE_TBL_VT1636[] = { | ||
49 | /* Index, Mask, Value */ | ||
50 | {0x08, 0xF0, 0x00} /* Input Data Mode Select */ | ||
51 | }; | ||
52 | |||
53 | struct IODATA DITHERING_ENABLE_TBL_VT1636[] = { | ||
54 | /* Index, Mask, Value */ | ||
55 | {0x0A, 0x70, 0x50} | ||
56 | }; | ||
57 | |||
58 | struct IODATA DITHERING_DISABLE_TBL_VT1636[] = { | ||
59 | /* Index, Mask, Value */ | ||
60 | {0x0A, 0x70, 0x00} | ||
61 | }; | ||
62 | |||
63 | struct IODATA VDD_ON_TBL_VT1636[] = { | ||
64 | /* Index, Mask, Value */ | ||
65 | {0x10, 0x20, 0x20} | ||
66 | }; | ||
67 | |||
68 | struct IODATA VDD_OFF_TBL_VT1636[] = { | ||
69 | /* Index, Mask, Value */ | ||
70 | {0x10, 0x20, 0x00} | ||
71 | }; | ||
diff --git a/drivers/video/via/tbl1636.h b/drivers/video/via/tbl1636.h new file mode 100644 index 000000000000..d906055f1511 --- /dev/null +++ b/drivers/video/via/tbl1636.h | |||
@@ -0,0 +1,34 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef _TBL1636_H_ | ||
23 | #define _TBL1636_H_ | ||
24 | #include "hw.h" | ||
25 | |||
26 | extern struct IODATA COMMON_INIT_TBL_VT1636[8]; | ||
27 | extern struct IODATA DUAL_CHANNEL_ENABLE_TBL_VT1636[1]; | ||
28 | extern struct IODATA SINGLE_CHANNEL_ENABLE_TBL_VT1636[1]; | ||
29 | extern struct IODATA DITHERING_ENABLE_TBL_VT1636[1]; | ||
30 | extern struct IODATA DITHERING_DISABLE_TBL_VT1636[1]; | ||
31 | extern struct IODATA VDD_ON_TBL_VT1636[1]; | ||
32 | extern struct IODATA VDD_OFF_TBL_VT1636[1]; | ||
33 | |||
34 | #endif /* _VIA_TBL1636_H_ */ | ||
diff --git a/drivers/video/via/tblDPASetting.c b/drivers/video/via/tblDPASetting.c new file mode 100644 index 000000000000..0c4c8cc712f4 --- /dev/null +++ b/drivers/video/via/tblDPASetting.c | |||
@@ -0,0 +1,109 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #include "global.h" | ||
23 | /* For VT3324: */ | ||
24 | struct VT1636_DPA_SETTING VT1636_DPA_SETTING_TBL_VT3324[] = { | ||
25 | /* Panel ID, CLK_SEL_ST1[09], CLK_SEL_ST2[08] */ | ||
26 | {LCD_PANEL_ID0_640X480, 0x00, 0x00}, /* For 640x480 */ | ||
27 | {LCD_PANEL_ID1_800X600, 0x00, 0x00}, /* For 800x600 */ | ||
28 | {LCD_PANEL_ID2_1024X768, 0x00, 0x00}, /* For 1024x768 */ | ||
29 | {LCD_PANEL_ID3_1280X768, 0x00, 0x00}, /* For 1280x768 */ | ||
30 | {LCD_PANEL_ID4_1280X1024, 0x00, 0x00}, /* For 1280x1024 */ | ||
31 | {LCD_PANEL_ID5_1400X1050, 0x00, 0x00}, /* For 1400x1050 */ | ||
32 | {LCD_PANEL_ID6_1600X1200, 0x0B, 0x03} /* For 1600x1200 */ | ||
33 | }; | ||
34 | |||
35 | struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3324[] = { | ||
36 | /* ClkRange, DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1, | ||
37 | DVP1Driving, DFPHigh, DFPLow */ | ||
38 | /* CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], CR9B, | ||
39 | SR65, CR97, CR99 */ | ||
40 | /* LCK/VCK < 30000000 will use this value */ | ||
41 | {DPA_CLK_RANGE_30M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, | ||
42 | 0x00}, | ||
43 | /* 30000000 < LCK/VCK < 50000000 will use this value */ | ||
44 | {DPA_CLK_RANGE_30_50M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, | ||
45 | 0x00}, | ||
46 | /* 50000000 < LCK/VCK < 70000000 will use this value */ | ||
47 | {DPA_CLK_RANGE_50_70M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, | ||
48 | 0x00}, | ||
49 | /* 70000000 < LCK/VCK < 100000000 will use this value */ | ||
50 | {DPA_CLK_RANGE_70_100M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, | ||
51 | 0x00}, | ||
52 | /* 100000000 < LCK/VCK < 15000000 will use this value */ | ||
53 | {DPA_CLK_RANGE_100_150M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, | ||
54 | 0x00}, | ||
55 | /* 15000000 < LCK/VCK will use this value */ | ||
56 | {DPA_CLK_RANGE_150M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0E, 0x00, | ||
57 | 0x00}, | ||
58 | }; | ||
59 | |||
60 | /* For VT3327: */ | ||
61 | struct VT1636_DPA_SETTING VT1636_DPA_SETTING_TBL_VT3327[] = { | ||
62 | /* Panel ID, CLK_SEL_ST1[09], CLK_SEL_ST2[08] */ | ||
63 | {LCD_PANEL_ID0_640X480, 0x00, 0x00}, /* For 640x480 */ | ||
64 | {LCD_PANEL_ID1_800X600, 0x00, 0x00}, /* For 800x600 */ | ||
65 | {LCD_PANEL_ID2_1024X768, 0x00, 0x00}, /* For 1024x768 */ | ||
66 | {LCD_PANEL_ID3_1280X768, 0x00, 0x00}, /* For 1280x768 */ | ||
67 | {LCD_PANEL_ID4_1280X1024, 0x00, 0x00}, /* For 1280x1024 */ | ||
68 | {LCD_PANEL_ID5_1400X1050, 0x00, 0x00}, /* For 1400x1050 */ | ||
69 | {LCD_PANEL_ID6_1600X1200, 0x00, 0x00} /* For 1600x1200 */ | ||
70 | }; | ||
71 | |||
72 | struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3327[] = { | ||
73 | /* ClkRange,DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1, | ||
74 | DVP1Driving, DFPHigh, DFPLow */ | ||
75 | /* CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], CR9B, | ||
76 | SR65, CR97, CR99 */ | ||
77 | /* LCK/VCK < 30000000 will use this value */ | ||
78 | {DPA_CLK_RANGE_30M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x01}, | ||
79 | /* 30000000 < LCK/VCK < 50000000 will use this value */ | ||
80 | {DPA_CLK_RANGE_30_50M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x01}, | ||
81 | /* 50000000 < LCK/VCK < 70000000 will use this value */ | ||
82 | {DPA_CLK_RANGE_50_70M, 0x06, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x01}, | ||
83 | /* 70000000 < LCK/VCK < 100000000 will use this value */ | ||
84 | {DPA_CLK_RANGE_70_100M, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x03}, | ||
85 | /* 100000000 < LCK/VCK < 15000000 will use this value */ | ||
86 | {DPA_CLK_RANGE_100_150M, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x02}, | ||
87 | /* 15000000 < LCK/VCK will use this value */ | ||
88 | {DPA_CLK_RANGE_150M, 0x00, 0x20, 0x00, 0x10, 0x00, 0x03, 0x00, 0x0D, 0x03}, | ||
89 | }; | ||
90 | |||
91 | /* For VT3364: */ | ||
92 | struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3364[] = { | ||
93 | /* ClkRange,DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1, | ||
94 | DVP1Driving, DFPHigh, DFPLow */ | ||
95 | /* CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], CR9B, | ||
96 | SR65, CR97, CR99 */ | ||
97 | /* LCK/VCK < 30000000 will use this value */ | ||
98 | {DPA_CLK_RANGE_30M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08}, | ||
99 | /* 30000000 < LCK/VCK < 50000000 will use this value */ | ||
100 | {DPA_CLK_RANGE_30_50M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08}, | ||
101 | /* 50000000 < LCK/VCK < 70000000 will use this value */ | ||
102 | {DPA_CLK_RANGE_50_70M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08}, | ||
103 | /* 70000000 < LCK/VCK < 100000000 will use this value */ | ||
104 | {DPA_CLK_RANGE_70_100M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08}, | ||
105 | /* 100000000 < LCK/VCK < 15000000 will use this value */ | ||
106 | {DPA_CLK_RANGE_100_150M, 0x03, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08}, | ||
107 | /* 15000000 < LCK/VCK will use this value */ | ||
108 | {DPA_CLK_RANGE_150M, 0x01, 0x00, 0x02, 0x10, 0x00, 0x03, 0x00, 0x00, 0x08}, | ||
109 | }; | ||
diff --git a/drivers/video/via/tblDPASetting.h b/drivers/video/via/tblDPASetting.h new file mode 100644 index 000000000000..b065a83481d3 --- /dev/null +++ b/drivers/video/via/tblDPASetting.h | |||
@@ -0,0 +1,47 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef _TBLDPASETTING_H_ | ||
23 | #define _TBLDPASETTING_H_ | ||
24 | #include "global.h" | ||
25 | |||
26 | #define DPA_CLK_30M 30000000 | ||
27 | #define DPA_CLK_50M 50000000 | ||
28 | #define DPA_CLK_70M 70000000 | ||
29 | #define DPA_CLK_100M 100000000 | ||
30 | #define DPA_CLK_150M 150000000 | ||
31 | |||
32 | enum DPA_RANGE { | ||
33 | DPA_CLK_RANGE_30M, | ||
34 | DPA_CLK_RANGE_30_50M, | ||
35 | DPA_CLK_RANGE_50_70M, | ||
36 | DPA_CLK_RANGE_70_100M, | ||
37 | DPA_CLK_RANGE_100_150M, | ||
38 | DPA_CLK_RANGE_150M | ||
39 | }; | ||
40 | |||
41 | extern struct VT1636_DPA_SETTING VT1636_DPA_SETTING_TBL_VT3324[7]; | ||
42 | extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3324[6]; | ||
43 | extern struct VT1636_DPA_SETTING VT1636_DPA_SETTING_TBL_VT3327[7]; | ||
44 | extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3327[]; | ||
45 | extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3364[6]; | ||
46 | |||
47 | #endif | ||
diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c new file mode 100644 index 000000000000..0f3ed4eb236d --- /dev/null +++ b/drivers/video/via/via_i2c.c | |||
@@ -0,0 +1,177 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #include "global.h" | ||
23 | |||
24 | static void via_i2c_setscl(void *data, int state) | ||
25 | { | ||
26 | u8 val; | ||
27 | struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data; | ||
28 | |||
29 | val = viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0xF0; | ||
30 | if (state) | ||
31 | val |= 0x20; | ||
32 | else | ||
33 | val &= ~0x20; | ||
34 | switch (via_i2c_chan->i2c_port) { | ||
35 | case I2CPORTINDEX: | ||
36 | val |= 0x01; | ||
37 | break; | ||
38 | case GPIOPORTINDEX: | ||
39 | val |= 0x80; | ||
40 | break; | ||
41 | default: | ||
42 | DEBUG_MSG("via_i2c: specify wrong i2c port.\n"); | ||
43 | } | ||
44 | viafb_write_reg(via_i2c_chan->i2c_port, VIASR, val); | ||
45 | } | ||
46 | |||
47 | static int via_i2c_getscl(void *data) | ||
48 | { | ||
49 | struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data; | ||
50 | |||
51 | if (viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0x08) | ||
52 | return 1; | ||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | static int via_i2c_getsda(void *data) | ||
57 | { | ||
58 | struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data; | ||
59 | |||
60 | if (viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0x04) | ||
61 | return 1; | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static void via_i2c_setsda(void *data, int state) | ||
66 | { | ||
67 | u8 val; | ||
68 | struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data; | ||
69 | |||
70 | val = viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0xF0; | ||
71 | if (state) | ||
72 | val |= 0x10; | ||
73 | else | ||
74 | val &= ~0x10; | ||
75 | switch (via_i2c_chan->i2c_port) { | ||
76 | case I2CPORTINDEX: | ||
77 | val |= 0x01; | ||
78 | break; | ||
79 | case GPIOPORTINDEX: | ||
80 | val |= 0x40; | ||
81 | break; | ||
82 | default: | ||
83 | DEBUG_MSG("via_i2c: specify wrong i2c port.\n"); | ||
84 | } | ||
85 | viafb_write_reg(via_i2c_chan->i2c_port, VIASR, val); | ||
86 | } | ||
87 | |||
88 | int viafb_i2c_readbyte(u8 slave_addr, u8 index, u8 *pdata) | ||
89 | { | ||
90 | u8 mm1[] = {0x00}; | ||
91 | struct i2c_msg msgs[2]; | ||
92 | |||
93 | *pdata = 0; | ||
94 | msgs[0].flags = 0; | ||
95 | msgs[1].flags = I2C_M_RD; | ||
96 | msgs[0].addr = msgs[1].addr = slave_addr / 2; | ||
97 | mm1[0] = index; | ||
98 | msgs[0].len = 1; msgs[1].len = 1; | ||
99 | msgs[0].buf = mm1; msgs[1].buf = pdata; | ||
100 | i2c_transfer(&viaparinfo->i2c_stuff.adapter, msgs, 2); | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | int viafb_i2c_writebyte(u8 slave_addr, u8 index, u8 data) | ||
106 | { | ||
107 | u8 msg[2] = { index, data }; | ||
108 | struct i2c_msg msgs; | ||
109 | |||
110 | msgs.flags = 0; | ||
111 | msgs.addr = slave_addr / 2; | ||
112 | msgs.len = 2; | ||
113 | msgs.buf = msg; | ||
114 | return i2c_transfer(&viaparinfo->i2c_stuff.adapter, &msgs, 1); | ||
115 | } | ||
116 | |||
117 | int viafb_i2c_readbytes(u8 slave_addr, u8 index, u8 *buff, int buff_len) | ||
118 | { | ||
119 | u8 mm1[] = {0x00}; | ||
120 | struct i2c_msg msgs[2]; | ||
121 | |||
122 | msgs[0].flags = 0; | ||
123 | msgs[1].flags = I2C_M_RD; | ||
124 | msgs[0].addr = msgs[1].addr = slave_addr / 2; | ||
125 | mm1[0] = index; | ||
126 | msgs[0].len = 1; msgs[1].len = buff_len; | ||
127 | msgs[0].buf = mm1; msgs[1].buf = buff; | ||
128 | i2c_transfer(&viaparinfo->i2c_stuff.adapter, msgs, 2); | ||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | int viafb_create_i2c_bus(void *viapar) | ||
133 | { | ||
134 | int ret; | ||
135 | struct viafb_par *par = (struct viafb_par *)viapar; | ||
136 | |||
137 | strcpy(par->i2c_stuff.adapter.name, "via_i2c"); | ||
138 | par->i2c_stuff.i2c_port = 0x0; | ||
139 | par->i2c_stuff.adapter.owner = THIS_MODULE; | ||
140 | par->i2c_stuff.adapter.id = 0x01FFFF; | ||
141 | par->i2c_stuff.adapter.class = 0; | ||
142 | par->i2c_stuff.adapter.algo_data = &par->i2c_stuff.algo; | ||
143 | par->i2c_stuff.adapter.dev.parent = NULL; | ||
144 | par->i2c_stuff.algo.setsda = via_i2c_setsda; | ||
145 | par->i2c_stuff.algo.setscl = via_i2c_setscl; | ||
146 | par->i2c_stuff.algo.getsda = via_i2c_getsda; | ||
147 | par->i2c_stuff.algo.getscl = via_i2c_getscl; | ||
148 | par->i2c_stuff.algo.udelay = 40; | ||
149 | par->i2c_stuff.algo.timeout = 20; | ||
150 | par->i2c_stuff.algo.data = &par->i2c_stuff; | ||
151 | |||
152 | i2c_set_adapdata(&par->i2c_stuff.adapter, &par->i2c_stuff); | ||
153 | |||
154 | /* Raise SCL and SDA */ | ||
155 | par->i2c_stuff.i2c_port = I2CPORTINDEX; | ||
156 | via_i2c_setsda(&par->i2c_stuff, 1); | ||
157 | via_i2c_setscl(&par->i2c_stuff, 1); | ||
158 | |||
159 | par->i2c_stuff.i2c_port = GPIOPORTINDEX; | ||
160 | via_i2c_setsda(&par->i2c_stuff, 1); | ||
161 | via_i2c_setscl(&par->i2c_stuff, 1); | ||
162 | udelay(20); | ||
163 | |||
164 | ret = i2c_bit_add_bus(&par->i2c_stuff.adapter); | ||
165 | if (ret == 0) | ||
166 | DEBUG_MSG("I2C bus %s registered.\n", | ||
167 | par->i2c_stuff.adapter.name); | ||
168 | else | ||
169 | DEBUG_MSG("Failed to register I2C bus %s.\n", | ||
170 | par->i2c_stuff.adapter.name); | ||
171 | return ret; | ||
172 | } | ||
173 | |||
174 | void viafb_delete_i2c_buss(void *par) | ||
175 | { | ||
176 | i2c_del_adapter(&((struct viafb_par *)par)->i2c_stuff.adapter); | ||
177 | } | ||
diff --git a/drivers/video/via/via_i2c.h b/drivers/video/via/via_i2c.h new file mode 100644 index 000000000000..3a13242a3152 --- /dev/null +++ b/drivers/video/via/via_i2c.h | |||
@@ -0,0 +1,46 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | #ifndef __VIA_I2C_H__ | ||
22 | #define __VIA_I2C_H__ | ||
23 | |||
24 | #include <linux/i2c.h> | ||
25 | #include <linux/i2c-algo-bit.h> | ||
26 | |||
27 | struct via_i2c_stuff { | ||
28 | u16 i2c_port; /* GPIO or I2C port */ | ||
29 | struct i2c_adapter adapter; | ||
30 | struct i2c_algo_bit_data algo; | ||
31 | }; | ||
32 | |||
33 | #define I2CPORT 0x3c4 | ||
34 | #define I2CPORTINDEX 0x31 | ||
35 | #define GPIOPORT 0x3C4 | ||
36 | #define GPIOPORTINDEX 0x2C | ||
37 | #define I2C_BUS 1 | ||
38 | #define GPIO_BUS 2 | ||
39 | #define DELAYPORT 0x3C3 | ||
40 | |||
41 | int viafb_i2c_readbyte(u8 slave_addr, u8 index, u8 *pdata); | ||
42 | int viafb_i2c_writebyte(u8 slave_addr, u8 index, u8 data); | ||
43 | int viafb_i2c_readbytes(u8 slave_addr, u8 index, u8 *buff, int buff_len); | ||
44 | int viafb_create_i2c_bus(void *par); | ||
45 | void viafb_delete_i2c_buss(void *par); | ||
46 | #endif /* __VIA_I2C_H__ */ | ||
diff --git a/drivers/video/via/via_utility.c b/drivers/video/via/via_utility.c new file mode 100644 index 000000000000..d53c3d54ed8e --- /dev/null +++ b/drivers/video/via/via_utility.c | |||
@@ -0,0 +1,253 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #include "global.h" | ||
23 | |||
24 | void viafb_get_device_support_state(u32 *support_state) | ||
25 | { | ||
26 | *support_state = CRT_Device; | ||
27 | |||
28 | if (viaparinfo->chip_info->tmds_chip_info.tmds_chip_name == VT1632_TMDS) | ||
29 | *support_state |= DVI_Device; | ||
30 | |||
31 | if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name == VT1631_LVDS) | ||
32 | *support_state |= LCD_Device; | ||
33 | } | ||
34 | |||
35 | void viafb_get_device_connect_state(u32 *connect_state) | ||
36 | { | ||
37 | bool mobile = false; | ||
38 | |||
39 | *connect_state = CRT_Device; | ||
40 | |||
41 | if (viafb_dvi_sense()) | ||
42 | *connect_state |= DVI_Device; | ||
43 | |||
44 | viafb_lcd_get_mobile_state(&mobile); | ||
45 | if (mobile) | ||
46 | *connect_state |= LCD_Device; | ||
47 | } | ||
48 | |||
49 | bool viafb_lcd_get_support_expand_state(u32 xres, u32 yres) | ||
50 | { | ||
51 | unsigned int support_state = 0; | ||
52 | |||
53 | switch (viafb_lcd_panel_id) { | ||
54 | case LCD_PANEL_ID0_640X480: | ||
55 | if ((xres < 640) && (yres < 480)) | ||
56 | support_state = true; | ||
57 | break; | ||
58 | |||
59 | case LCD_PANEL_ID1_800X600: | ||
60 | if ((xres < 800) && (yres < 600)) | ||
61 | support_state = true; | ||
62 | break; | ||
63 | |||
64 | case LCD_PANEL_ID2_1024X768: | ||
65 | if ((xres < 1024) && (yres < 768)) | ||
66 | support_state = true; | ||
67 | break; | ||
68 | |||
69 | case LCD_PANEL_ID3_1280X768: | ||
70 | if ((xres < 1280) && (yres < 768)) | ||
71 | support_state = true; | ||
72 | break; | ||
73 | |||
74 | case LCD_PANEL_ID4_1280X1024: | ||
75 | if ((xres < 1280) && (yres < 1024)) | ||
76 | support_state = true; | ||
77 | break; | ||
78 | |||
79 | case LCD_PANEL_ID5_1400X1050: | ||
80 | if ((xres < 1400) && (yres < 1050)) | ||
81 | support_state = true; | ||
82 | break; | ||
83 | |||
84 | case LCD_PANEL_ID6_1600X1200: | ||
85 | if ((xres < 1600) && (yres < 1200)) | ||
86 | support_state = true; | ||
87 | break; | ||
88 | |||
89 | case LCD_PANEL_ID7_1366X768: | ||
90 | if ((xres < 1366) && (yres < 768)) | ||
91 | support_state = true; | ||
92 | break; | ||
93 | |||
94 | case LCD_PANEL_ID8_1024X600: | ||
95 | if ((xres < 1024) && (yres < 600)) | ||
96 | support_state = true; | ||
97 | break; | ||
98 | |||
99 | case LCD_PANEL_ID9_1280X800: | ||
100 | if ((xres < 1280) && (yres < 800)) | ||
101 | support_state = true; | ||
102 | break; | ||
103 | |||
104 | case LCD_PANEL_IDA_800X480: | ||
105 | if ((xres < 800) && (yres < 480)) | ||
106 | support_state = true; | ||
107 | break; | ||
108 | |||
109 | case LCD_PANEL_IDB_1360X768: | ||
110 | if ((xres < 1360) && (yres < 768)) | ||
111 | support_state = true; | ||
112 | break; | ||
113 | |||
114 | case LCD_PANEL_IDC_480X640: | ||
115 | if ((xres < 480) && (yres < 640)) | ||
116 | support_state = true; | ||
117 | break; | ||
118 | |||
119 | default: | ||
120 | support_state = false; | ||
121 | break; | ||
122 | } | ||
123 | |||
124 | return support_state; | ||
125 | } | ||
126 | |||
127 | /*====================================================================*/ | ||
128 | /* Gamma Function Implementation*/ | ||
129 | /*====================================================================*/ | ||
130 | |||
131 | void viafb_set_gamma_table(int bpp, unsigned int *gamma_table) | ||
132 | { | ||
133 | int i, sr1a; | ||
134 | int active_device_amount = 0; | ||
135 | int device_status = viafb_DeviceStatus; | ||
136 | |||
137 | for (i = 0; i < sizeof(viafb_DeviceStatus) * 8; i++) { | ||
138 | if (device_status & 1) | ||
139 | active_device_amount++; | ||
140 | device_status >>= 1; | ||
141 | } | ||
142 | |||
143 | /* 8 bpp mode can't adjust gamma */ | ||
144 | if (bpp == 8) | ||
145 | return ; | ||
146 | |||
147 | /* Enable Gamma */ | ||
148 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
149 | case UNICHROME_CLE266: | ||
150 | case UNICHROME_K400: | ||
151 | viafb_write_reg_mask(SR16, VIASR, 0x80, BIT7); | ||
152 | break; | ||
153 | |||
154 | case UNICHROME_K800: | ||
155 | case UNICHROME_PM800: | ||
156 | case UNICHROME_CN700: | ||
157 | case UNICHROME_CX700: | ||
158 | case UNICHROME_K8M890: | ||
159 | case UNICHROME_P4M890: | ||
160 | case UNICHROME_P4M900: | ||
161 | viafb_write_reg_mask(CR33, VIACR, 0x80, BIT7); | ||
162 | break; | ||
163 | } | ||
164 | sr1a = (unsigned int)viafb_read_reg(VIASR, SR1A); | ||
165 | viafb_write_reg_mask(SR1A, VIASR, 0x0, BIT0); | ||
166 | |||
167 | /* Fill IGA1 Gamma Table */ | ||
168 | outb(0, LUT_INDEX_WRITE); | ||
169 | for (i = 0; i < 256; i++) { | ||
170 | outb(gamma_table[i] >> 16, LUT_DATA); | ||
171 | outb(gamma_table[i] >> 8 & 0xFF, LUT_DATA); | ||
172 | outb(gamma_table[i] & 0xFF, LUT_DATA); | ||
173 | } | ||
174 | |||
175 | /* If adjust Gamma value in SAMM, fill IGA1, | ||
176 | IGA2 Gamma table simultanous. */ | ||
177 | /* Switch to IGA2 Gamma Table */ | ||
178 | if ((active_device_amount > 1) && | ||
179 | !((viaparinfo->chip_info->gfx_chip_name == | ||
180 | UNICHROME_CLE266) && | ||
181 | (viaparinfo->chip_info->gfx_chip_revision < 15))) { | ||
182 | viafb_write_reg_mask(SR1A, VIASR, 0x01, BIT0); | ||
183 | viafb_write_reg_mask(CR6A, VIACR, 0x02, BIT1); | ||
184 | |||
185 | /* Fill IGA2 Gamma Table */ | ||
186 | outb(0, LUT_INDEX_WRITE); | ||
187 | for (i = 0; i < 256; i++) { | ||
188 | outb(gamma_table[i] >> 16, LUT_DATA); | ||
189 | outb(gamma_table[i] >> 8 & 0xFF, LUT_DATA); | ||
190 | outb(gamma_table[i] & 0xFF, LUT_DATA); | ||
191 | } | ||
192 | } | ||
193 | viafb_write_reg(SR1A, VIASR, sr1a); | ||
194 | } | ||
195 | |||
196 | void viafb_get_gamma_table(unsigned int *gamma_table) | ||
197 | { | ||
198 | unsigned char color_r, color_g, color_b; | ||
199 | unsigned char sr1a = 0; | ||
200 | int i; | ||
201 | |||
202 | /* Enable Gamma */ | ||
203 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
204 | case UNICHROME_CLE266: | ||
205 | case UNICHROME_K400: | ||
206 | viafb_write_reg_mask(SR16, VIASR, 0x80, BIT7); | ||
207 | break; | ||
208 | |||
209 | case UNICHROME_K800: | ||
210 | case UNICHROME_PM800: | ||
211 | case UNICHROME_CN700: | ||
212 | case UNICHROME_CX700: | ||
213 | case UNICHROME_K8M890: | ||
214 | case UNICHROME_P4M890: | ||
215 | case UNICHROME_P4M900: | ||
216 | viafb_write_reg_mask(CR33, VIACR, 0x80, BIT7); | ||
217 | break; | ||
218 | } | ||
219 | sr1a = viafb_read_reg(VIASR, SR1A); | ||
220 | viafb_write_reg_mask(SR1A, VIASR, 0x0, BIT0); | ||
221 | |||
222 | /* Reading gamma table to get color value */ | ||
223 | outb(0, LUT_INDEX_READ); | ||
224 | for (i = 0; i < 256; i++) { | ||
225 | color_r = inb(LUT_DATA); | ||
226 | color_g = inb(LUT_DATA); | ||
227 | color_b = inb(LUT_DATA); | ||
228 | gamma_table[i] = | ||
229 | ((((u32) color_r) << 16) | | ||
230 | (((u16) color_g) << 8)) | color_b; | ||
231 | } | ||
232 | viafb_write_reg(SR1A, VIASR, sr1a); | ||
233 | } | ||
234 | |||
235 | void viafb_get_gamma_support_state(int bpp, unsigned int *support_state) | ||
236 | { | ||
237 | if (bpp == 8) | ||
238 | *support_state = None_Device; | ||
239 | else | ||
240 | *support_state = CRT_Device | DVI_Device | LCD_Device; | ||
241 | } | ||
242 | |||
243 | int viafb_input_parameter_converter(int parameter_value) | ||
244 | { | ||
245 | int result; | ||
246 | |||
247 | if (parameter_value >= 1 && parameter_value <= 9) | ||
248 | result = 1 << (parameter_value - 1); | ||
249 | else | ||
250 | result = 1; | ||
251 | |||
252 | return result; | ||
253 | } | ||
diff --git a/drivers/video/via/via_utility.h b/drivers/video/via/via_utility.h new file mode 100644 index 000000000000..2fd455202ebd --- /dev/null +++ b/drivers/video/via/via_utility.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | #ifndef __VIAUTILITY_H__ | ||
22 | #define __VIAUTILITY_H__ | ||
23 | |||
24 | /* These functions are used to get infomation about device's state */ | ||
25 | void viafb_get_device_support_state(u32 *support_state); | ||
26 | void viafb_get_device_connect_state(u32 *connect_state); | ||
27 | bool viafb_lcd_get_support_expand_state(u32 xres, u32 yres); | ||
28 | |||
29 | /* These function are used to access gamma table */ | ||
30 | void viafb_set_gamma_table(int bpp, unsigned int *gamma_table); | ||
31 | void viafb_get_gamma_table(unsigned int *gamma_table); | ||
32 | void viafb_get_gamma_support_state(int bpp, unsigned int *support_state); | ||
33 | int viafb_input_parameter_converter(int parameter_value); | ||
34 | |||
35 | #endif /* __VIAUTILITY_H__ */ | ||
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c new file mode 100644 index 000000000000..0132eae06f55 --- /dev/null +++ b/drivers/video/via/viafbdev.c | |||
@@ -0,0 +1,2571 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #define _MASTER_FILE | ||
24 | |||
25 | #include "global.h" | ||
26 | |||
27 | static int MAX_CURS = 32; | ||
28 | static struct fb_var_screeninfo default_var; | ||
29 | static char *viafb_name = "Via"; | ||
30 | static u32 pseudo_pal[17]; | ||
31 | |||
32 | /* video mode */ | ||
33 | static char *viafb_mode = "640x480"; | ||
34 | static char *viafb_mode1 = "640x480"; | ||
35 | static int viafb_resMode = VIA_RES_640X480; | ||
36 | |||
37 | /* Added for specifying active devices.*/ | ||
38 | char *viafb_active_dev = ""; | ||
39 | |||
40 | /* Added for specifying video on devices.*/ | ||
41 | char *viafb_video_dev = ""; | ||
42 | |||
43 | /*Added for specify lcd output port*/ | ||
44 | char *viafb_lcd_port = ""; | ||
45 | char *viafb_dvi_port = ""; | ||
46 | |||
47 | static void viafb_set_device(struct device_t active_dev); | ||
48 | static int apply_device_setting(struct viafb_ioctl_setting setting_info, | ||
49 | struct fb_info *info); | ||
50 | static void apply_second_mode_setting(struct fb_var_screeninfo | ||
51 | *sec_var); | ||
52 | static void retrieve_device_setting(struct viafb_ioctl_setting | ||
53 | *setting_info); | ||
54 | static void viafb_set_video_device(u32 video_dev_info); | ||
55 | static void viafb_get_video_device(u32 *video_dev_info); | ||
56 | |||
57 | /* Mode information */ | ||
58 | static const struct viafb_modeinfo viafb_modentry[] = { | ||
59 | {480, 640, VIA_RES_480X640, "480x640"}, | ||
60 | {640, 480, VIA_RES_640X480, "640x480"}, | ||
61 | {800, 480, VIA_RES_800X480, "800x480"}, | ||
62 | {800, 600, VIA_RES_800X600, "800x600"}, | ||
63 | {1024, 768, VIA_RES_1024X768, "1024x768"}, | ||
64 | {1152, 864, VIA_RES_1152X864, "1152x864"}, | ||
65 | {1280, 1024, VIA_RES_1280X1024, "1280x1024"}, | ||
66 | {1600, 1200, VIA_RES_1600X1200, "1600x1200"}, | ||
67 | {1440, 1050, VIA_RES_1440X1050, "1440x1050"}, | ||
68 | {1280, 768, VIA_RES_1280X768, "1280x768"}, | ||
69 | {1280, 800, VIA_RES_1280X800, "1280x800"}, | ||
70 | {1280, 960, VIA_RES_1280X960, "1280x960"}, | ||
71 | {1920, 1440, VIA_RES_1920X1440, "1920x1440"}, | ||
72 | {848, 480, VIA_RES_848X480, "848x480"}, | ||
73 | {1400, 1050, VIA_RES_1400X1050, "1400x1050"}, | ||
74 | {720, 480, VIA_RES_720X480, "720x480"}, | ||
75 | {720, 576, VIA_RES_720X576, "720x576"}, | ||
76 | {1024, 512, VIA_RES_1024X512, "1024x512"}, | ||
77 | {1024, 576, VIA_RES_1024X576, "1024x576"}, | ||
78 | {1024, 600, VIA_RES_1024X600, "1024x600"}, | ||
79 | {1280, 720, VIA_RES_1280X720, "1280x720"}, | ||
80 | {1920, 1080, VIA_RES_1920X1080, "1920x1080"}, | ||
81 | {1366, 768, VIA_RES_1368X768, "1368x768"}, | ||
82 | {1680, 1050, VIA_RES_1680X1050, "1680x1050"}, | ||
83 | {960, 600, VIA_RES_960X600, "960x600"}, | ||
84 | {1000, 600, VIA_RES_1000X600, "1000x600"}, | ||
85 | {1024, 576, VIA_RES_1024X576, "1024x576"}, | ||
86 | {1024, 600, VIA_RES_1024X600, "1024x600"}, | ||
87 | {1088, 612, VIA_RES_1088X612, "1088x612"}, | ||
88 | {1152, 720, VIA_RES_1152X720, "1152x720"}, | ||
89 | {1200, 720, VIA_RES_1200X720, "1200x720"}, | ||
90 | {1280, 600, VIA_RES_1280X600, "1280x600"}, | ||
91 | {1360, 768, VIA_RES_1360X768, "1360x768"}, | ||
92 | {1440, 900, VIA_RES_1440X900, "1440x900"}, | ||
93 | {1600, 900, VIA_RES_1600X900, "1600x900"}, | ||
94 | {1600, 1024, VIA_RES_1600X1024, "1600x1024"}, | ||
95 | {1792, 1344, VIA_RES_1792X1344, "1792x1344"}, | ||
96 | {1856, 1392, VIA_RES_1856X1392, "1856x1392"}, | ||
97 | {1920, 1200, VIA_RES_1920X1200, "1920x1200"}, | ||
98 | {2048, 1536, VIA_RES_2048X1536, "2048x1536"}, | ||
99 | {0, 0, VIA_RES_INVALID, "640x480"} | ||
100 | }; | ||
101 | |||
102 | static struct fb_ops viafb_ops; | ||
103 | |||
104 | static int viafb_update_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) | ||
105 | { | ||
106 | struct viafb_par *ppar; | ||
107 | ppar = info->par; | ||
108 | |||
109 | DEBUG_MSG(KERN_INFO "viafb_update_fix!\n"); | ||
110 | |||
111 | fix->visual = | ||
112 | ppar->bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; | ||
113 | fix->line_length = ppar->linelength; | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | |||
119 | static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix, | ||
120 | struct viafb_par *viaparinfo) | ||
121 | { | ||
122 | memset(fix, 0, sizeof(struct fb_fix_screeninfo)); | ||
123 | strcpy(fix->id, viafb_name); | ||
124 | |||
125 | fix->smem_start = viaparinfo->fbmem; | ||
126 | fix->smem_len = viaparinfo->fbmem_free; | ||
127 | fix->mmio_start = viaparinfo->mmio_base; | ||
128 | fix->mmio_len = viaparinfo->mmio_len; | ||
129 | |||
130 | fix->type = FB_TYPE_PACKED_PIXELS; | ||
131 | fix->type_aux = 0; | ||
132 | |||
133 | fix->xpanstep = fix->ywrapstep = 0; | ||
134 | fix->ypanstep = 1; | ||
135 | |||
136 | /* Just tell the accel name */ | ||
137 | viafbinfo->fix.accel = FB_ACCEL_VIA_UNICHROME; | ||
138 | } | ||
139 | static int viafb_open(struct fb_info *info, int user) | ||
140 | { | ||
141 | DEBUG_MSG(KERN_INFO "viafb_open!\n"); | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | static int viafb_release(struct fb_info *info, int user) | ||
146 | { | ||
147 | DEBUG_MSG(KERN_INFO "viafb_release!\n"); | ||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | static void viafb_update_viafb_par(struct fb_info *info) | ||
152 | { | ||
153 | struct viafb_par *ppar; | ||
154 | |||
155 | ppar = info->par; | ||
156 | ppar->bpp = info->var.bits_per_pixel; | ||
157 | ppar->linelength = ((info->var.xres_virtual + 7) & ~7) * ppar->bpp / 8; | ||
158 | ppar->hres = info->var.xres; | ||
159 | ppar->vres = info->var.yres; | ||
160 | ppar->xoffset = info->var.xoffset; | ||
161 | ppar->yoffset = info->var.yoffset; | ||
162 | } | ||
163 | |||
164 | static int viafb_check_var(struct fb_var_screeninfo *var, | ||
165 | struct fb_info *info) | ||
166 | { | ||
167 | int vmode_index, htotal, vtotal; | ||
168 | struct viafb_par *ppar; | ||
169 | u32 long_refresh; | ||
170 | struct viafb_par *p_viafb_par; | ||
171 | ppar = info->par; | ||
172 | |||
173 | |||
174 | DEBUG_MSG(KERN_INFO "viafb_check_var!\n"); | ||
175 | /* Sanity check */ | ||
176 | /* HW neither support interlacte nor double-scaned mode */ | ||
177 | if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE) | ||
178 | return -EINVAL; | ||
179 | |||
180 | vmode_index = viafb_get_mode_index(var->xres, var->yres, 0); | ||
181 | if (vmode_index == VIA_RES_INVALID) { | ||
182 | DEBUG_MSG(KERN_INFO | ||
183 | "viafb: Mode %dx%dx%d not supported!!\n", | ||
184 | var->xres, var->yres, var->bits_per_pixel); | ||
185 | return -EINVAL; | ||
186 | } | ||
187 | |||
188 | if (24 == var->bits_per_pixel) | ||
189 | var->bits_per_pixel = 32; | ||
190 | |||
191 | if (var->bits_per_pixel != 8 && var->bits_per_pixel != 16 && | ||
192 | var->bits_per_pixel != 32) | ||
193 | return -EINVAL; | ||
194 | |||
195 | if ((var->xres_virtual * (var->bits_per_pixel >> 3)) & 0x1F) | ||
196 | /*32 pixel alignment */ | ||
197 | var->xres_virtual = (var->xres_virtual + 31) & ~31; | ||
198 | if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 > | ||
199 | ppar->memsize) | ||
200 | return -EINVAL; | ||
201 | |||
202 | /* Based on var passed in to calculate the refresh, | ||
203 | * because our driver use some modes special. | ||
204 | */ | ||
205 | htotal = var->xres + var->left_margin + | ||
206 | var->right_margin + var->hsync_len; | ||
207 | vtotal = var->yres + var->upper_margin + | ||
208 | var->lower_margin + var->vsync_len; | ||
209 | long_refresh = 1000000000UL / var->pixclock * 1000; | ||
210 | long_refresh /= (htotal * vtotal); | ||
211 | |||
212 | viafb_refresh = viafb_get_refresh(var->xres, var->yres, long_refresh); | ||
213 | |||
214 | /* Adjust var according to our driver's own table */ | ||
215 | viafb_fill_var_timing_info(var, viafb_refresh, vmode_index); | ||
216 | |||
217 | /* This is indeed a patch for VT3353 */ | ||
218 | if (!info->par) | ||
219 | return -1; | ||
220 | p_viafb_par = (struct viafb_par *)info->par; | ||
221 | if (p_viafb_par->chip_info->gfx_chip_name == UNICHROME_VX800) | ||
222 | var->accel_flags = 0; | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static int viafb_set_par(struct fb_info *info) | ||
228 | { | ||
229 | int vmode_index; | ||
230 | int vmode_index1 = 0; | ||
231 | DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); | ||
232 | |||
233 | viafb_update_device_setting(info->var.xres, info->var.yres, | ||
234 | info->var.bits_per_pixel, viafb_refresh, 0); | ||
235 | |||
236 | vmode_index = viafb_get_mode_index(info->var.xres, info->var.yres, 0); | ||
237 | |||
238 | if (viafb_SAMM_ON == 1) { | ||
239 | DEBUG_MSG(KERN_INFO | ||
240 | "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n", | ||
241 | viafb_second_xres, viafb_second_yres, viafb_bpp1); | ||
242 | vmode_index1 = viafb_get_mode_index(viafb_second_xres, | ||
243 | viafb_second_yres, 1); | ||
244 | DEBUG_MSG(KERN_INFO "->viafb_SAMM_ON: index=%d\n", | ||
245 | vmode_index1); | ||
246 | |||
247 | viafb_update_device_setting(viafb_second_xres, | ||
248 | viafb_second_yres, viafb_bpp1, viafb_refresh1, 1); | ||
249 | } | ||
250 | |||
251 | if (vmode_index != VIA_RES_INVALID) { | ||
252 | viafb_setmode(vmode_index, info->var.xres, info->var.yres, | ||
253 | info->var.bits_per_pixel, vmode_index1, | ||
254 | viafb_second_xres, viafb_second_yres, viafb_bpp1); | ||
255 | |||
256 | /*We should set memory offset according virtual_x */ | ||
257 | /*Fix me:put this function into viafb_setmode */ | ||
258 | viafb_memory_pitch_patch(info); | ||
259 | |||
260 | /* Update ***fb_par information */ | ||
261 | viafb_update_viafb_par(info); | ||
262 | |||
263 | /* Update other fixed information */ | ||
264 | viafb_update_fix(&info->fix, info); | ||
265 | viafb_bpp = info->var.bits_per_pixel; | ||
266 | /* Update viafb_accel, it is necessary to our 2D accelerate */ | ||
267 | viafb_accel = info->var.accel_flags; | ||
268 | |||
269 | if (viafb_accel) | ||
270 | viafb_set_2d_color_depth(info->var.bits_per_pixel); | ||
271 | } | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | /* Set one color register */ | ||
277 | static int viafb_setcolreg(unsigned regno, unsigned red, unsigned green, | ||
278 | unsigned blue, unsigned transp, struct fb_info *info) | ||
279 | { | ||
280 | u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10; | ||
281 | unsigned cmap_entries = (info->var.bits_per_pixel == 8) ? 256 : 16; | ||
282 | DEBUG_MSG(KERN_INFO "viafb_setcolreg!\n"); | ||
283 | if (regno >= cmap_entries) | ||
284 | return 1; | ||
285 | if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) { | ||
286 | /* | ||
287 | * Read PCI bus 0,dev 0,function 0,index 0xF6 to get chip rev. | ||
288 | */ | ||
289 | outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8); | ||
290 | rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff; | ||
291 | } | ||
292 | switch (info->var.bits_per_pixel) { | ||
293 | case 8: | ||
294 | outb(0x1A, 0x3C4); | ||
295 | sr1a = inb(0x3C5); | ||
296 | outb(0x1B, 0x3C4); | ||
297 | sr1b = inb(0x3C5); | ||
298 | outb(0x67, 0x3D4); | ||
299 | cr67 = inb(0x3D5); | ||
300 | outb(0x6A, 0x3D4); | ||
301 | cr6a = inb(0x3D5); | ||
302 | |||
303 | /* Map the 3C6/7/8/9 to the IGA2 */ | ||
304 | outb(0x1A, 0x3C4); | ||
305 | outb(sr1a | 0x01, 0x3C5); | ||
306 | /* Second Display Engine colck always on */ | ||
307 | outb(0x1B, 0x3C4); | ||
308 | outb(sr1b | 0x80, 0x3C5); | ||
309 | /* Second Display Color Depth 8 */ | ||
310 | outb(0x67, 0x3D4); | ||
311 | outb(cr67 & 0x3F, 0x3D5); | ||
312 | outb(0x6A, 0x3D4); | ||
313 | /* Second Display Channel Reset CR6A[6]) */ | ||
314 | outb(cr6a & 0xBF, 0x3D5); | ||
315 | /* Second Display Channel Enable CR6A[7] */ | ||
316 | outb(cr6a | 0x80, 0x3D5); | ||
317 | /* Second Display Channel stop reset) */ | ||
318 | outb(cr6a | 0x40, 0x3D5); | ||
319 | |||
320 | /* Bit mask of palette */ | ||
321 | outb(0xFF, 0x3c6); | ||
322 | /* Write one register of IGA2 */ | ||
323 | outb(regno, 0x3C8); | ||
324 | if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name && | ||
325 | rev >= 15) { | ||
326 | shift = 8; | ||
327 | viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5); | ||
328 | viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7); | ||
329 | } else { | ||
330 | shift = 10; | ||
331 | viafb_write_reg_mask(CR6A, VIACR, 0, BIT5); | ||
332 | viafb_write_reg_mask(SR15, VIASR, 0, BIT7); | ||
333 | } | ||
334 | outb(red >> shift, 0x3C9); | ||
335 | outb(green >> shift, 0x3C9); | ||
336 | outb(blue >> shift, 0x3C9); | ||
337 | |||
338 | /* Map the 3C6/7/8/9 to the IGA1 */ | ||
339 | outb(0x1A, 0x3C4); | ||
340 | outb(sr1a & 0xFE, 0x3C5); | ||
341 | /* Bit mask of palette */ | ||
342 | outb(0xFF, 0x3c6); | ||
343 | /* Write one register of IGA1 */ | ||
344 | outb(regno, 0x3C8); | ||
345 | outb(red >> shift, 0x3C9); | ||
346 | outb(green >> shift, 0x3C9); | ||
347 | outb(blue >> shift, 0x3C9); | ||
348 | |||
349 | outb(0x1A, 0x3C4); | ||
350 | outb(sr1a, 0x3C5); | ||
351 | outb(0x1B, 0x3C4); | ||
352 | outb(sr1b, 0x3C5); | ||
353 | outb(0x67, 0x3D4); | ||
354 | outb(cr67, 0x3D5); | ||
355 | outb(0x6A, 0x3D4); | ||
356 | outb(cr6a, 0x3D5); | ||
357 | break; | ||
358 | case 16: | ||
359 | ((u32 *) info->pseudo_palette)[regno] = (red & 0xF800) | | ||
360 | ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11); | ||
361 | break; | ||
362 | case 32: | ||
363 | ((u32 *) info->pseudo_palette)[regno] = | ||
364 | ((transp & 0xFF00) << 16) | | ||
365 | ((red & 0xFF00) << 8) | | ||
366 | ((green & 0xFF00)) | ((blue & 0xFF00) >> 8); | ||
367 | break; | ||
368 | } | ||
369 | |||
370 | return 0; | ||
371 | |||
372 | } | ||
373 | |||
374 | /*CALLED BY: fb_set_cmap */ | ||
375 | /* fb_set_var, pass 256 colors */ | ||
376 | /*CALLED BY: fb_set_cmap */ | ||
377 | /* fbcon_set_palette, pass 16 colors */ | ||
378 | static int viafb_setcmap(struct fb_cmap *cmap, struct fb_info *info) | ||
379 | { | ||
380 | u32 len = cmap->len; | ||
381 | u32 i; | ||
382 | u16 *pred = cmap->red; | ||
383 | u16 *pgreen = cmap->green; | ||
384 | u16 *pblue = cmap->blue; | ||
385 | u16 *ptransp = cmap->transp; | ||
386 | u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10; | ||
387 | if (len > 256) | ||
388 | return 1; | ||
389 | if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) { | ||
390 | /* | ||
391 | * Read PCI bus 0, dev 0, function 0, index 0xF6 to get chip | ||
392 | * rev. | ||
393 | */ | ||
394 | outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8); | ||
395 | rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff; | ||
396 | } | ||
397 | switch (info->var.bits_per_pixel) { | ||
398 | case 8: | ||
399 | outb(0x1A, 0x3C4); | ||
400 | sr1a = inb(0x3C5); | ||
401 | outb(0x1B, 0x3C4); | ||
402 | sr1b = inb(0x3C5); | ||
403 | outb(0x67, 0x3D4); | ||
404 | cr67 = inb(0x3D5); | ||
405 | outb(0x6A, 0x3D4); | ||
406 | cr6a = inb(0x3D5); | ||
407 | /* Map the 3C6/7/8/9 to the IGA2 */ | ||
408 | outb(0x1A, 0x3C4); | ||
409 | outb(sr1a | 0x01, 0x3C5); | ||
410 | outb(0x1B, 0x3C4); | ||
411 | /* Second Display Engine colck always on */ | ||
412 | outb(sr1b | 0x80, 0x3C5); | ||
413 | outb(0x67, 0x3D4); | ||
414 | /* Second Display Color Depth 8 */ | ||
415 | outb(cr67 & 0x3F, 0x3D5); | ||
416 | outb(0x6A, 0x3D4); | ||
417 | /* Second Display Channel Reset CR6A[6]) */ | ||
418 | outb(cr6a & 0xBF, 0x3D5); | ||
419 | /* Second Display Channel Enable CR6A[7] */ | ||
420 | outb(cr6a | 0x80, 0x3D5); | ||
421 | /* Second Display Channel stop reset) */ | ||
422 | outb(cr6a | 0xC0, 0x3D5); | ||
423 | |||
424 | /* Bit mask of palette */ | ||
425 | outb(0xFF, 0x3c6); | ||
426 | outb(0x00, 0x3C8); | ||
427 | if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name && | ||
428 | rev >= 15) { | ||
429 | shift = 8; | ||
430 | viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5); | ||
431 | viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7); | ||
432 | } else { | ||
433 | shift = 10; | ||
434 | viafb_write_reg_mask(CR6A, VIACR, 0, BIT5); | ||
435 | viafb_write_reg_mask(SR15, VIASR, 0, BIT7); | ||
436 | } | ||
437 | for (i = 0; i < len; i++) { | ||
438 | outb((*(pred + i)) >> shift, 0x3C9); | ||
439 | outb((*(pgreen + i)) >> shift, 0x3C9); | ||
440 | outb((*(pblue + i)) >> shift, 0x3C9); | ||
441 | } | ||
442 | |||
443 | outb(0x1A, 0x3C4); | ||
444 | /* Map the 3C6/7/8/9 to the IGA1 */ | ||
445 | outb(sr1a & 0xFE, 0x3C5); | ||
446 | /* Bit mask of palette */ | ||
447 | outb(0xFF, 0x3c6); | ||
448 | outb(0x00, 0x3C8); | ||
449 | for (i = 0; i < len; i++) { | ||
450 | outb((*(pred + i)) >> shift, 0x3C9); | ||
451 | outb((*(pgreen + i)) >> shift, 0x3C9); | ||
452 | outb((*(pblue + i)) >> shift, 0x3C9); | ||
453 | } | ||
454 | |||
455 | outb(0x1A, 0x3C4); | ||
456 | outb(sr1a, 0x3C5); | ||
457 | outb(0x1B, 0x3C4); | ||
458 | outb(sr1b, 0x3C5); | ||
459 | outb(0x67, 0x3D4); | ||
460 | outb(cr67, 0x3D5); | ||
461 | outb(0x6A, 0x3D4); | ||
462 | outb(cr6a, 0x3D5); | ||
463 | break; | ||
464 | case 16: | ||
465 | if (len > 17) | ||
466 | return 0; /* Because static u32 pseudo_pal[17]; */ | ||
467 | for (i = 0; i < len; i++) | ||
468 | ((u32 *) info->pseudo_palette)[i] = | ||
469 | (*(pred + i) & 0xF800) | | ||
470 | ((*(pgreen + i) & 0xFC00) >> 5) | | ||
471 | ((*(pblue + i) & 0xF800) >> 11); | ||
472 | break; | ||
473 | case 32: | ||
474 | if (len > 17) | ||
475 | return 0; | ||
476 | if (ptransp) { | ||
477 | for (i = 0; i < len; i++) | ||
478 | ((u32 *) info->pseudo_palette)[i] = | ||
479 | ((*(ptransp + i) & 0xFF00) << 16) | | ||
480 | ((*(pred + i) & 0xFF00) << 8) | | ||
481 | ((*(pgreen + i) & 0xFF00)) | | ||
482 | ((*(pblue + i) & 0xFF00) >> 8); | ||
483 | } else { | ||
484 | for (i = 0; i < len; i++) | ||
485 | ((u32 *) info->pseudo_palette)[i] = | ||
486 | 0x00000000 | | ||
487 | ((*(pred + i) & 0xFF00) << 8) | | ||
488 | ((*(pgreen + i) & 0xFF00)) | | ||
489 | ((*(pblue + i) & 0xFF00) >> 8); | ||
490 | } | ||
491 | break; | ||
492 | } | ||
493 | return 0; | ||
494 | } | ||
495 | |||
496 | static int viafb_pan_display(struct fb_var_screeninfo *var, | ||
497 | struct fb_info *info) | ||
498 | { | ||
499 | unsigned int offset; | ||
500 | |||
501 | DEBUG_MSG(KERN_INFO "viafb_pan_display!\n"); | ||
502 | |||
503 | offset = (var->xoffset + (var->yoffset * var->xres_virtual)) * | ||
504 | var->bits_per_pixel / 16; | ||
505 | |||
506 | DEBUG_MSG(KERN_INFO "\nviafb_pan_display,offset =%d ", offset); | ||
507 | |||
508 | viafb_write_reg_mask(0x48, 0x3d4, ((offset >> 24) & 0x3), 0x3); | ||
509 | viafb_write_reg_mask(0x34, 0x3d4, ((offset >> 16) & 0xff), 0xff); | ||
510 | viafb_write_reg_mask(0x0c, 0x3d4, ((offset >> 8) & 0xff), 0xff); | ||
511 | viafb_write_reg_mask(0x0d, 0x3d4, (offset & 0xff), 0xff); | ||
512 | |||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | static int viafb_blank(int blank_mode, struct fb_info *info) | ||
517 | { | ||
518 | DEBUG_MSG(KERN_INFO "viafb_blank!\n"); | ||
519 | /* clear DPMS setting */ | ||
520 | |||
521 | switch (blank_mode) { | ||
522 | case FB_BLANK_UNBLANK: | ||
523 | /* Screen: On, HSync: On, VSync: On */ | ||
524 | /* control CRT monitor power management */ | ||
525 | viafb_write_reg_mask(CR36, VIACR, 0x00, BIT4 + BIT5); | ||
526 | break; | ||
527 | case FB_BLANK_HSYNC_SUSPEND: | ||
528 | /* Screen: Off, HSync: Off, VSync: On */ | ||
529 | /* control CRT monitor power management */ | ||
530 | viafb_write_reg_mask(CR36, VIACR, 0x10, BIT4 + BIT5); | ||
531 | break; | ||
532 | case FB_BLANK_VSYNC_SUSPEND: | ||
533 | /* Screen: Off, HSync: On, VSync: Off */ | ||
534 | /* control CRT monitor power management */ | ||
535 | viafb_write_reg_mask(CR36, VIACR, 0x20, BIT4 + BIT5); | ||
536 | break; | ||
537 | case FB_BLANK_POWERDOWN: | ||
538 | /* Screen: Off, HSync: Off, VSync: Off */ | ||
539 | /* control CRT monitor power management */ | ||
540 | viafb_write_reg_mask(CR36, VIACR, 0x30, BIT4 + BIT5); | ||
541 | break; | ||
542 | } | ||
543 | |||
544 | return 0; | ||
545 | } | ||
546 | |||
547 | static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) | ||
548 | { | ||
549 | struct viafb_ioctl_mode viamode; | ||
550 | struct viafb_ioctl_samm viasamm; | ||
551 | struct viafb_driver_version driver_version; | ||
552 | struct fb_var_screeninfo sec_var; | ||
553 | struct _panel_size_pos_info panel_pos_size_para; | ||
554 | u32 state_info = 0; | ||
555 | u32 viainfo_size = sizeof(struct viafb_ioctl_info); | ||
556 | u32 *viafb_gamma_table; | ||
557 | char driver_name[] = "viafb"; | ||
558 | |||
559 | u32 __user *argp = (u32 __user *) arg; | ||
560 | u32 gpu32; | ||
561 | u32 video_dev_info = 0; | ||
562 | struct viafb_ioctl_setting viafb_setting = {}; | ||
563 | struct device_t active_dev = {}; | ||
564 | |||
565 | DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd); | ||
566 | |||
567 | switch (cmd) { | ||
568 | case VIAFB_GET_CHIP_INFO: | ||
569 | if (copy_to_user(argp, viaparinfo->chip_info, | ||
570 | sizeof(struct chip_information))) | ||
571 | return -EFAULT; | ||
572 | break; | ||
573 | case VIAFB_GET_INFO_SIZE: | ||
574 | return put_user(viainfo_size, argp); | ||
575 | case VIAFB_GET_INFO: | ||
576 | return viafb_ioctl_get_viafb_info(arg); | ||
577 | case VIAFB_HOTPLUG: | ||
578 | return put_user(viafb_ioctl_hotplug(info->var.xres, | ||
579 | info->var.yres, | ||
580 | info->var.bits_per_pixel), argp); | ||
581 | case VIAFB_SET_HOTPLUG_FLAG: | ||
582 | if (copy_from_user(&gpu32, argp, sizeof(gpu32))) | ||
583 | return -EFAULT; | ||
584 | viafb_hotplug = (gpu32) ? 1 : 0; | ||
585 | break; | ||
586 | case VIAFB_GET_RESOLUTION: | ||
587 | viamode.xres = (u32) viafb_hotplug_Xres; | ||
588 | viamode.yres = (u32) viafb_hotplug_Yres; | ||
589 | viamode.refresh = (u32) viafb_hotplug_refresh; | ||
590 | viamode.bpp = (u32) viafb_hotplug_bpp; | ||
591 | if (viafb_SAMM_ON == 1) { | ||
592 | viamode.xres_sec = viafb_second_xres; | ||
593 | viamode.yres_sec = viafb_second_yres; | ||
594 | viamode.virtual_xres_sec = viafb_second_virtual_xres; | ||
595 | viamode.virtual_yres_sec = viafb_second_virtual_yres; | ||
596 | viamode.refresh_sec = viafb_refresh1; | ||
597 | viamode.bpp_sec = viafb_bpp1; | ||
598 | } else { | ||
599 | viamode.xres_sec = 0; | ||
600 | viamode.yres_sec = 0; | ||
601 | viamode.virtual_xres_sec = 0; | ||
602 | viamode.virtual_yres_sec = 0; | ||
603 | viamode.refresh_sec = 0; | ||
604 | viamode.bpp_sec = 0; | ||
605 | } | ||
606 | if (copy_to_user(argp, &viamode, sizeof(viamode))) | ||
607 | return -EFAULT; | ||
608 | break; | ||
609 | case VIAFB_GET_SAMM_INFO: | ||
610 | viasamm.samm_status = viafb_SAMM_ON; | ||
611 | |||
612 | if (viafb_SAMM_ON == 1) { | ||
613 | if (viafb_dual_fb) { | ||
614 | viasamm.size_prim = viaparinfo->fbmem_free; | ||
615 | viasamm.size_sec = viaparinfo1->fbmem_free; | ||
616 | } else { | ||
617 | if (viafb_second_size) { | ||
618 | viasamm.size_prim = | ||
619 | viaparinfo->fbmem_free - | ||
620 | viafb_second_size * 1024 * 1024; | ||
621 | viasamm.size_sec = | ||
622 | viafb_second_size * 1024 * 1024; | ||
623 | } else { | ||
624 | viasamm.size_prim = | ||
625 | viaparinfo->fbmem_free >> 1; | ||
626 | viasamm.size_sec = | ||
627 | (viaparinfo->fbmem_free >> 1); | ||
628 | } | ||
629 | } | ||
630 | viasamm.mem_base = viaparinfo->fbmem; | ||
631 | viasamm.offset_sec = viafb_second_offset; | ||
632 | } else { | ||
633 | viasamm.size_prim = | ||
634 | viaparinfo->memsize - viaparinfo->fbmem_used; | ||
635 | viasamm.size_sec = 0; | ||
636 | viasamm.mem_base = viaparinfo->fbmem; | ||
637 | viasamm.offset_sec = 0; | ||
638 | } | ||
639 | |||
640 | if (copy_to_user(argp, &viasamm, sizeof(viasamm))) | ||
641 | return -EFAULT; | ||
642 | |||
643 | break; | ||
644 | case VIAFB_TURN_ON_OUTPUT_DEVICE: | ||
645 | if (copy_from_user(&gpu32, argp, sizeof(gpu32))) | ||
646 | return -EFAULT; | ||
647 | if (gpu32 & CRT_Device) | ||
648 | viafb_crt_enable(); | ||
649 | if (gpu32 & DVI_Device) | ||
650 | viafb_dvi_enable(); | ||
651 | if (gpu32 & LCD_Device) | ||
652 | viafb_lcd_enable(); | ||
653 | break; | ||
654 | case VIAFB_TURN_OFF_OUTPUT_DEVICE: | ||
655 | if (copy_from_user(&gpu32, argp, sizeof(gpu32))) | ||
656 | return -EFAULT; | ||
657 | if (gpu32 & CRT_Device) | ||
658 | viafb_crt_disable(); | ||
659 | if (gpu32 & DVI_Device) | ||
660 | viafb_dvi_disable(); | ||
661 | if (gpu32 & LCD_Device) | ||
662 | viafb_lcd_disable(); | ||
663 | break; | ||
664 | case VIAFB_SET_DEVICE: | ||
665 | if (copy_from_user(&active_dev, (void *)argp, | ||
666 | sizeof(active_dev))) | ||
667 | return -EFAULT; | ||
668 | viafb_set_device(active_dev); | ||
669 | viafb_set_par(info); | ||
670 | break; | ||
671 | case VIAFB_GET_DEVICE: | ||
672 | active_dev.crt = viafb_CRT_ON; | ||
673 | active_dev.dvi = viafb_DVI_ON; | ||
674 | active_dev.lcd = viafb_LCD_ON; | ||
675 | active_dev.samm = viafb_SAMM_ON; | ||
676 | active_dev.primary_dev = viafb_primary_dev; | ||
677 | |||
678 | active_dev.lcd_dsp_cent = viafb_lcd_dsp_method; | ||
679 | active_dev.lcd_panel_id = viafb_lcd_panel_id; | ||
680 | active_dev.lcd_mode = viafb_lcd_mode; | ||
681 | |||
682 | active_dev.xres = viafb_hotplug_Xres; | ||
683 | active_dev.yres = viafb_hotplug_Yres; | ||
684 | |||
685 | active_dev.xres1 = viafb_second_xres; | ||
686 | active_dev.yres1 = viafb_second_yres; | ||
687 | |||
688 | active_dev.bpp = viafb_bpp; | ||
689 | active_dev.bpp1 = viafb_bpp1; | ||
690 | active_dev.refresh = viafb_refresh; | ||
691 | active_dev.refresh1 = viafb_refresh1; | ||
692 | |||
693 | active_dev.epia_dvi = viafb_platform_epia_dvi; | ||
694 | active_dev.lcd_dual_edge = viafb_device_lcd_dualedge; | ||
695 | active_dev.bus_width = viafb_bus_width; | ||
696 | |||
697 | if (copy_to_user(argp, &active_dev, sizeof(active_dev))) | ||
698 | return -EFAULT; | ||
699 | break; | ||
700 | |||
701 | case VIAFB_GET_DRIVER_VERSION: | ||
702 | driver_version.iMajorNum = VERSION_MAJOR; | ||
703 | driver_version.iKernelNum = VERSION_KERNEL; | ||
704 | driver_version.iOSNum = VERSION_OS; | ||
705 | driver_version.iMinorNum = VERSION_MINOR; | ||
706 | |||
707 | if (copy_to_user(argp, &driver_version, | ||
708 | sizeof(driver_version))) | ||
709 | return -EFAULT; | ||
710 | |||
711 | break; | ||
712 | |||
713 | case VIAFB_SET_DEVICE_INFO: | ||
714 | if (copy_from_user(&viafb_setting, | ||
715 | argp, sizeof(viafb_setting))) | ||
716 | return -EFAULT; | ||
717 | if (apply_device_setting(viafb_setting, info) < 0) | ||
718 | return -EINVAL; | ||
719 | |||
720 | break; | ||
721 | |||
722 | case VIAFB_SET_SECOND_MODE: | ||
723 | if (copy_from_user(&sec_var, argp, sizeof(sec_var))) | ||
724 | return -EFAULT; | ||
725 | apply_second_mode_setting(&sec_var); | ||
726 | break; | ||
727 | |||
728 | case VIAFB_GET_DEVICE_INFO: | ||
729 | |||
730 | retrieve_device_setting(&viafb_setting); | ||
731 | |||
732 | if (copy_to_user(argp, &viafb_setting, sizeof(viafb_setting))) | ||
733 | return -EFAULT; | ||
734 | |||
735 | break; | ||
736 | |||
737 | case VIAFB_GET_DEVICE_SUPPORT: | ||
738 | viafb_get_device_support_state(&state_info); | ||
739 | if (put_user(state_info, argp)) | ||
740 | return -EFAULT; | ||
741 | break; | ||
742 | |||
743 | case VIAFB_GET_DEVICE_CONNECT: | ||
744 | viafb_get_device_connect_state(&state_info); | ||
745 | if (put_user(state_info, argp)) | ||
746 | return -EFAULT; | ||
747 | break; | ||
748 | |||
749 | case VIAFB_GET_PANEL_SUPPORT_EXPAND: | ||
750 | state_info = | ||
751 | viafb_lcd_get_support_expand_state(info->var.xres, | ||
752 | info->var.yres); | ||
753 | if (put_user(state_info, argp)) | ||
754 | return -EFAULT; | ||
755 | break; | ||
756 | |||
757 | case VIAFB_GET_DRIVER_NAME: | ||
758 | if (copy_to_user(argp, driver_name, sizeof(driver_name))) | ||
759 | return -EFAULT; | ||
760 | break; | ||
761 | |||
762 | case VIAFB_SET_GAMMA_LUT: | ||
763 | viafb_gamma_table = kmalloc(256 * sizeof(u32), GFP_KERNEL); | ||
764 | if (!viafb_gamma_table) | ||
765 | return -ENOMEM; | ||
766 | if (copy_from_user(viafb_gamma_table, argp, | ||
767 | sizeof(viafb_gamma_table))) { | ||
768 | kfree(viafb_gamma_table); | ||
769 | return -EFAULT; | ||
770 | } | ||
771 | viafb_set_gamma_table(viafb_bpp, viafb_gamma_table); | ||
772 | kfree(viafb_gamma_table); | ||
773 | break; | ||
774 | |||
775 | case VIAFB_GET_GAMMA_LUT: | ||
776 | viafb_gamma_table = kmalloc(256 * sizeof(u32), GFP_KERNEL); | ||
777 | if (!viafb_gamma_table) | ||
778 | return -ENOMEM; | ||
779 | viafb_get_gamma_table(viafb_gamma_table); | ||
780 | if (copy_to_user(argp, viafb_gamma_table, | ||
781 | sizeof(viafb_gamma_table))) { | ||
782 | kfree(viafb_gamma_table); | ||
783 | return -EFAULT; | ||
784 | } | ||
785 | kfree(viafb_gamma_table); | ||
786 | break; | ||
787 | |||
788 | case VIAFB_GET_GAMMA_SUPPORT_STATE: | ||
789 | viafb_get_gamma_support_state(viafb_bpp, &state_info); | ||
790 | if (put_user(state_info, argp)) | ||
791 | return -EFAULT; | ||
792 | break; | ||
793 | case VIAFB_SET_VIDEO_DEVICE: | ||
794 | get_user(video_dev_info, argp); | ||
795 | viafb_set_video_device(video_dev_info); | ||
796 | break; | ||
797 | case VIAFB_GET_VIDEO_DEVICE: | ||
798 | viafb_get_video_device(&video_dev_info); | ||
799 | if (put_user(video_dev_info, argp)) | ||
800 | return -EFAULT; | ||
801 | break; | ||
802 | case VIAFB_SYNC_SURFACE: | ||
803 | DEBUG_MSG(KERN_INFO "lobo VIAFB_SYNC_SURFACE\n"); | ||
804 | break; | ||
805 | case VIAFB_GET_DRIVER_CAPS: | ||
806 | break; | ||
807 | |||
808 | case VIAFB_GET_PANEL_MAX_SIZE: | ||
809 | if (copy_from_user | ||
810 | (&panel_pos_size_para, argp, sizeof(panel_pos_size_para))) | ||
811 | return -EFAULT; | ||
812 | panel_pos_size_para.x = panel_pos_size_para.y = 0; | ||
813 | if (copy_to_user(argp, &panel_pos_size_para, | ||
814 | sizeof(panel_pos_size_para))) | ||
815 | return -EFAULT; | ||
816 | break; | ||
817 | case VIAFB_GET_PANEL_MAX_POSITION: | ||
818 | if (copy_from_user | ||
819 | (&panel_pos_size_para, argp, sizeof(panel_pos_size_para))) | ||
820 | return -EFAULT; | ||
821 | panel_pos_size_para.x = panel_pos_size_para.y = 0; | ||
822 | if (copy_to_user(argp, &panel_pos_size_para, | ||
823 | sizeof(panel_pos_size_para))) | ||
824 | return -EFAULT; | ||
825 | break; | ||
826 | |||
827 | case VIAFB_GET_PANEL_POSITION: | ||
828 | if (copy_from_user | ||
829 | (&panel_pos_size_para, argp, sizeof(panel_pos_size_para))) | ||
830 | return -EFAULT; | ||
831 | panel_pos_size_para.x = panel_pos_size_para.y = 0; | ||
832 | if (copy_to_user(argp, &panel_pos_size_para, | ||
833 | sizeof(panel_pos_size_para))) | ||
834 | return -EFAULT; | ||
835 | break; | ||
836 | case VIAFB_GET_PANEL_SIZE: | ||
837 | if (copy_from_user | ||
838 | (&panel_pos_size_para, argp, sizeof(panel_pos_size_para))) | ||
839 | return -EFAULT; | ||
840 | panel_pos_size_para.x = panel_pos_size_para.y = 0; | ||
841 | if (copy_to_user(argp, &panel_pos_size_para, | ||
842 | sizeof(panel_pos_size_para))) | ||
843 | return -EFAULT; | ||
844 | break; | ||
845 | |||
846 | case VIAFB_SET_PANEL_POSITION: | ||
847 | if (copy_from_user | ||
848 | (&panel_pos_size_para, argp, sizeof(panel_pos_size_para))) | ||
849 | return -EFAULT; | ||
850 | break; | ||
851 | case VIAFB_SET_PANEL_SIZE: | ||
852 | if (copy_from_user | ||
853 | (&panel_pos_size_para, argp, sizeof(panel_pos_size_para))) | ||
854 | return -EFAULT; | ||
855 | break; | ||
856 | |||
857 | default: | ||
858 | return -EINVAL; | ||
859 | } | ||
860 | |||
861 | return 0; | ||
862 | } | ||
863 | |||
864 | static void viafb_fillrect(struct fb_info *info, | ||
865 | const struct fb_fillrect *rect) | ||
866 | { | ||
867 | u32 col = 0, rop = 0; | ||
868 | int pitch; | ||
869 | |||
870 | if (!viafb_accel) | ||
871 | return cfb_fillrect(info, rect); | ||
872 | |||
873 | if (!rect->width || !rect->height) | ||
874 | return; | ||
875 | |||
876 | switch (rect->rop) { | ||
877 | case ROP_XOR: | ||
878 | rop = 0x5A; | ||
879 | break; | ||
880 | case ROP_COPY: | ||
881 | default: | ||
882 | rop = 0xF0; | ||
883 | break; | ||
884 | } | ||
885 | |||
886 | switch (info->var.bits_per_pixel) { | ||
887 | case 8: | ||
888 | col = rect->color; | ||
889 | break; | ||
890 | case 16: | ||
891 | col = ((u32 *) (info->pseudo_palette))[rect->color]; | ||
892 | break; | ||
893 | case 32: | ||
894 | col = ((u32 *) (info->pseudo_palette))[rect->color]; | ||
895 | break; | ||
896 | } | ||
897 | |||
898 | /* BitBlt Source Address */ | ||
899 | writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS); | ||
900 | /* Source Base Address */ | ||
901 | writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE); | ||
902 | /* Destination Base Address */ | ||
903 | writel(((unsigned long) (info->screen_base) - | ||
904 | (unsigned long) viafb_FB_MM) >> 3, | ||
905 | viaparinfo->io_virt + VIA_REG_DSTBASE); | ||
906 | /* Pitch */ | ||
907 | pitch = (info->var.xres_virtual + 7) & ~7; | ||
908 | writel(VIA_PITCH_ENABLE | | ||
909 | (((pitch * | ||
910 | info->var.bits_per_pixel >> 3) >> 3) | | ||
911 | (((pitch * info-> | ||
912 | var.bits_per_pixel >> 3) >> 3) << 16)), | ||
913 | viaparinfo->io_virt + VIA_REG_PITCH); | ||
914 | /* BitBlt Destination Address */ | ||
915 | writel(((rect->dy << 16) | rect->dx), | ||
916 | viaparinfo->io_virt + VIA_REG_DSTPOS); | ||
917 | /* Dimension: width & height */ | ||
918 | writel((((rect->height - 1) << 16) | (rect->width - 1)), | ||
919 | viaparinfo->io_virt + VIA_REG_DIMENSION); | ||
920 | /* Forground color or Destination color */ | ||
921 | writel(col, viaparinfo->io_virt + VIA_REG_FGCOLOR); | ||
922 | /* GE Command */ | ||
923 | writel((0x01 | 0x2000 | (rop << 24)), | ||
924 | viaparinfo->io_virt + VIA_REG_GECMD); | ||
925 | |||
926 | } | ||
927 | |||
928 | static void viafb_copyarea(struct fb_info *info, | ||
929 | const struct fb_copyarea *area) | ||
930 | { | ||
931 | u32 dy = area->dy, sy = area->sy, direction = 0x0; | ||
932 | u32 sx = area->sx, dx = area->dx, width = area->width; | ||
933 | int pitch; | ||
934 | |||
935 | DEBUG_MSG(KERN_INFO "viafb_copyarea!!\n"); | ||
936 | |||
937 | if (!viafb_accel) | ||
938 | return cfb_copyarea(info, area); | ||
939 | |||
940 | if (!area->width || !area->height) | ||
941 | return; | ||
942 | |||
943 | if (sy < dy) { | ||
944 | dy += area->height - 1; | ||
945 | sy += area->height - 1; | ||
946 | direction |= 0x4000; | ||
947 | } | ||
948 | |||
949 | if (sx < dx) { | ||
950 | dx += width - 1; | ||
951 | sx += width - 1; | ||
952 | direction |= 0x8000; | ||
953 | } | ||
954 | |||
955 | /* Source Base Address */ | ||
956 | writel(((unsigned long) (info->screen_base) - | ||
957 | (unsigned long) viafb_FB_MM) >> 3, | ||
958 | viaparinfo->io_virt + VIA_REG_SRCBASE); | ||
959 | /* Destination Base Address */ | ||
960 | writel(((unsigned long) (info->screen_base) - | ||
961 | (unsigned long) viafb_FB_MM) >> 3, | ||
962 | viaparinfo->io_virt + VIA_REG_DSTBASE); | ||
963 | /* Pitch */ | ||
964 | pitch = (info->var.xres_virtual + 7) & ~7; | ||
965 | /* VIA_PITCH_ENABLE can be omitted now. */ | ||
966 | writel(VIA_PITCH_ENABLE | | ||
967 | (((pitch * | ||
968 | info->var.bits_per_pixel >> 3) >> 3) | (((pitch * | ||
969 | info->var. | ||
970 | bits_per_pixel | ||
971 | >> 3) >> 3) | ||
972 | << 16)), | ||
973 | viaparinfo->io_virt + VIA_REG_PITCH); | ||
974 | /* BitBlt Source Address */ | ||
975 | writel(((sy << 16) | sx), viaparinfo->io_virt + VIA_REG_SRCPOS); | ||
976 | /* BitBlt Destination Address */ | ||
977 | writel(((dy << 16) | dx), viaparinfo->io_virt + VIA_REG_DSTPOS); | ||
978 | /* Dimension: width & height */ | ||
979 | writel((((area->height - 1) << 16) | (area->width - 1)), | ||
980 | viaparinfo->io_virt + VIA_REG_DIMENSION); | ||
981 | /* GE Command */ | ||
982 | writel((0x01 | direction | (0xCC << 24)), | ||
983 | viaparinfo->io_virt + VIA_REG_GECMD); | ||
984 | |||
985 | } | ||
986 | |||
987 | static void viafb_imageblit(struct fb_info *info, | ||
988 | const struct fb_image *image) | ||
989 | { | ||
990 | u32 size, bg_col = 0, fg_col = 0, *udata; | ||
991 | int i; | ||
992 | int pitch; | ||
993 | |||
994 | if (!viafb_accel) | ||
995 | return cfb_imageblit(info, image); | ||
996 | |||
997 | udata = (u32 *) image->data; | ||
998 | |||
999 | switch (info->var.bits_per_pixel) { | ||
1000 | case 8: | ||
1001 | bg_col = image->bg_color; | ||
1002 | fg_col = image->fg_color; | ||
1003 | break; | ||
1004 | case 16: | ||
1005 | bg_col = ((u32 *) (info->pseudo_palette))[image->bg_color]; | ||
1006 | fg_col = ((u32 *) (info->pseudo_palette))[image->fg_color]; | ||
1007 | break; | ||
1008 | case 32: | ||
1009 | bg_col = ((u32 *) (info->pseudo_palette))[image->bg_color]; | ||
1010 | fg_col = ((u32 *) (info->pseudo_palette))[image->fg_color]; | ||
1011 | break; | ||
1012 | } | ||
1013 | size = image->width * image->height; | ||
1014 | |||
1015 | /* Source Base Address */ | ||
1016 | writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE); | ||
1017 | /* Destination Base Address */ | ||
1018 | writel(((unsigned long) (info->screen_base) - | ||
1019 | (unsigned long) viafb_FB_MM) >> 3, | ||
1020 | viaparinfo->io_virt + VIA_REG_DSTBASE); | ||
1021 | /* Pitch */ | ||
1022 | pitch = (info->var.xres_virtual + 7) & ~7; | ||
1023 | writel(VIA_PITCH_ENABLE | | ||
1024 | (((pitch * | ||
1025 | info->var.bits_per_pixel >> 3) >> 3) | (((pitch * | ||
1026 | info->var. | ||
1027 | bits_per_pixel | ||
1028 | >> 3) >> 3) | ||
1029 | << 16)), | ||
1030 | viaparinfo->io_virt + VIA_REG_PITCH); | ||
1031 | /* BitBlt Source Address */ | ||
1032 | writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS); | ||
1033 | /* BitBlt Destination Address */ | ||
1034 | writel(((image->dy << 16) | image->dx), | ||
1035 | viaparinfo->io_virt + VIA_REG_DSTPOS); | ||
1036 | /* Dimension: width & height */ | ||
1037 | writel((((image->height - 1) << 16) | (image->width - 1)), | ||
1038 | viaparinfo->io_virt + VIA_REG_DIMENSION); | ||
1039 | /* fb color */ | ||
1040 | writel(fg_col, viaparinfo->io_virt + VIA_REG_FGCOLOR); | ||
1041 | /* bg color */ | ||
1042 | writel(bg_col, viaparinfo->io_virt + VIA_REG_BGCOLOR); | ||
1043 | /* GE Command */ | ||
1044 | writel(0xCC020142, viaparinfo->io_virt + VIA_REG_GECMD); | ||
1045 | |||
1046 | for (i = 0; i < size / 4; i++) { | ||
1047 | writel(*udata, viaparinfo->io_virt + VIA_MMIO_BLTBASE); | ||
1048 | udata++; | ||
1049 | } | ||
1050 | |||
1051 | } | ||
1052 | |||
1053 | static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) | ||
1054 | { | ||
1055 | u8 data[CURSOR_SIZE / 8]; | ||
1056 | u32 data_bak[CURSOR_SIZE / 32]; | ||
1057 | u32 temp, xx, yy, bg_col = 0, fg_col = 0; | ||
1058 | int size, i, j = 0; | ||
1059 | static int hw_cursor; | ||
1060 | struct viafb_par *p_viafb_par; | ||
1061 | |||
1062 | if (viafb_accel) | ||
1063 | hw_cursor = 1; | ||
1064 | |||
1065 | if (!viafb_accel) { | ||
1066 | if (hw_cursor) { | ||
1067 | viafb_show_hw_cursor(info, HW_Cursor_OFF); | ||
1068 | hw_cursor = 0; | ||
1069 | } | ||
1070 | return -ENODEV; | ||
1071 | } | ||
1072 | |||
1073 | if ((((struct viafb_par *)(info->par))->iga_path == IGA2) | ||
1074 | && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)) | ||
1075 | return -ENODEV; | ||
1076 | |||
1077 | /* When duoview and using lcd , use soft cursor */ | ||
1078 | if (viafb_LCD_ON || ((struct viafb_par *)(info->par))->duoview) | ||
1079 | return -ENODEV; | ||
1080 | |||
1081 | viafb_show_hw_cursor(info, HW_Cursor_OFF); | ||
1082 | viacursor = *cursor; | ||
1083 | |||
1084 | if (cursor->set & FB_CUR_SETHOT) { | ||
1085 | viacursor.hot = cursor->hot; | ||
1086 | temp = ((viacursor.hot.x) << 16) + viacursor.hot.y; | ||
1087 | writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_ORG); | ||
1088 | } | ||
1089 | |||
1090 | if (cursor->set & FB_CUR_SETPOS) { | ||
1091 | viacursor.image.dx = cursor->image.dx; | ||
1092 | viacursor.image.dy = cursor->image.dy; | ||
1093 | yy = cursor->image.dy - info->var.yoffset; | ||
1094 | xx = cursor->image.dx - info->var.xoffset; | ||
1095 | temp = yy & 0xFFFF; | ||
1096 | temp |= (xx << 16); | ||
1097 | writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_POS); | ||
1098 | } | ||
1099 | |||
1100 | if (cursor->set & FB_CUR_SETSIZE) { | ||
1101 | temp = readl(viaparinfo->io_virt + VIA_REG_CURSOR_MODE); | ||
1102 | |||
1103 | if ((cursor->image.width <= 32) | ||
1104 | && (cursor->image.height <= 32)) { | ||
1105 | MAX_CURS = 32; | ||
1106 | temp |= 0x2; | ||
1107 | } else if ((cursor->image.width <= 64) | ||
1108 | && (cursor->image.height <= 64)) { | ||
1109 | MAX_CURS = 64; | ||
1110 | temp &= 0xFFFFFFFD; | ||
1111 | } else { | ||
1112 | DEBUG_MSG(KERN_INFO | ||
1113 | "The cursor image is biger than 64x64 bits...\n"); | ||
1114 | return -ENXIO; | ||
1115 | } | ||
1116 | writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_MODE); | ||
1117 | |||
1118 | viacursor.image.height = cursor->image.height; | ||
1119 | viacursor.image.width = cursor->image.width; | ||
1120 | } | ||
1121 | |||
1122 | if (cursor->set & FB_CUR_SETCMAP) { | ||
1123 | viacursor.image.fg_color = cursor->image.fg_color; | ||
1124 | viacursor.image.bg_color = cursor->image.bg_color; | ||
1125 | |||
1126 | switch (info->var.bits_per_pixel) { | ||
1127 | case 8: | ||
1128 | case 16: | ||
1129 | case 32: | ||
1130 | bg_col = | ||
1131 | (0xFF << 24) | | ||
1132 | (((info->cmap.red)[viacursor.image.bg_color] & | ||
1133 | 0xFF00) << 8) | | ||
1134 | ((info->cmap.green)[viacursor.image.bg_color] & | ||
1135 | 0xFF00) | | ||
1136 | (((info->cmap.blue)[viacursor.image.bg_color] & | ||
1137 | 0xFF00) >> 8); | ||
1138 | fg_col = | ||
1139 | (0xFF << 24) | | ||
1140 | (((info->cmap.red)[viacursor.image.fg_color] & | ||
1141 | 0xFF00) << 8) | | ||
1142 | ((info->cmap.green)[viacursor.image.fg_color] & | ||
1143 | 0xFF00) | | ||
1144 | (((info->cmap.blue)[viacursor.image.fg_color] & | ||
1145 | 0xFF00) >> 8); | ||
1146 | break; | ||
1147 | default: | ||
1148 | return 0; | ||
1149 | } | ||
1150 | |||
1151 | /* This is indeed a patch for VT3324/VT3353 */ | ||
1152 | if (!info->par) | ||
1153 | return 0; | ||
1154 | p_viafb_par = (struct viafb_par *)info->par; | ||
1155 | |||
1156 | if ((p_viafb_par->chip_info->gfx_chip_name == | ||
1157 | UNICHROME_CX700) || | ||
1158 | ((p_viafb_par->chip_info->gfx_chip_name == | ||
1159 | UNICHROME_VX800))) { | ||
1160 | bg_col = | ||
1161 | (((info->cmap.red)[viacursor.image.bg_color] & | ||
1162 | 0xFFC0) << 14) | | ||
1163 | (((info->cmap.green)[viacursor.image.bg_color] & | ||
1164 | 0xFFC0) << 4) | | ||
1165 | (((info->cmap.blue)[viacursor.image.bg_color] & | ||
1166 | 0xFFC0) >> 6); | ||
1167 | fg_col = | ||
1168 | (((info->cmap.red)[viacursor.image.fg_color] & | ||
1169 | 0xFFC0) << 14) | | ||
1170 | (((info->cmap.green)[viacursor.image.fg_color] & | ||
1171 | 0xFFC0) << 4) | | ||
1172 | (((info->cmap.blue)[viacursor.image.fg_color] & | ||
1173 | 0xFFC0) >> 6); | ||
1174 | } | ||
1175 | |||
1176 | writel(bg_col, viaparinfo->io_virt + VIA_REG_CURSOR_BG); | ||
1177 | writel(fg_col, viaparinfo->io_virt + VIA_REG_CURSOR_FG); | ||
1178 | } | ||
1179 | |||
1180 | if (cursor->set & FB_CUR_SETSHAPE) { | ||
1181 | size = | ||
1182 | ((viacursor.image.width + 7) >> 3) * | ||
1183 | viacursor.image.height; | ||
1184 | |||
1185 | if (MAX_CURS == 32) { | ||
1186 | for (i = 0; i < (CURSOR_SIZE / 32); i++) { | ||
1187 | data_bak[i] = 0x0; | ||
1188 | data_bak[i + 1] = 0xFFFFFFFF; | ||
1189 | i += 1; | ||
1190 | } | ||
1191 | } else if (MAX_CURS == 64) { | ||
1192 | for (i = 0; i < (CURSOR_SIZE / 32); i++) { | ||
1193 | data_bak[i] = 0x0; | ||
1194 | data_bak[i + 1] = 0x0; | ||
1195 | data_bak[i + 2] = 0xFFFFFFFF; | ||
1196 | data_bak[i + 3] = 0xFFFFFFFF; | ||
1197 | i += 3; | ||
1198 | } | ||
1199 | } | ||
1200 | |||
1201 | switch (viacursor.rop) { | ||
1202 | case ROP_XOR: | ||
1203 | for (i = 0; i < size; i++) | ||
1204 | data[i] = viacursor.mask[i]; | ||
1205 | break; | ||
1206 | case ROP_COPY: | ||
1207 | |||
1208 | for (i = 0; i < size; i++) | ||
1209 | data[i] = viacursor.mask[i]; | ||
1210 | break; | ||
1211 | default: | ||
1212 | break; | ||
1213 | } | ||
1214 | |||
1215 | if (MAX_CURS == 32) { | ||
1216 | for (i = 0; i < size; i++) { | ||
1217 | data_bak[j] = (u32) data[i]; | ||
1218 | data_bak[j + 1] = ~data_bak[j]; | ||
1219 | j += 2; | ||
1220 | } | ||
1221 | } else if (MAX_CURS == 64) { | ||
1222 | for (i = 0; i < size; i++) { | ||
1223 | data_bak[j] = (u32) data[i]; | ||
1224 | data_bak[j + 1] = 0x0; | ||
1225 | data_bak[j + 2] = ~data_bak[j]; | ||
1226 | data_bak[j + 3] = ~data_bak[j + 1]; | ||
1227 | j += 4; | ||
1228 | } | ||
1229 | } | ||
1230 | |||
1231 | memcpy(((struct viafb_par *)(info->par))->fbmem_virt + | ||
1232 | ((struct viafb_par *)(info->par))->cursor_start, | ||
1233 | data_bak, CURSOR_SIZE); | ||
1234 | } | ||
1235 | |||
1236 | if (viacursor.enable) | ||
1237 | viafb_show_hw_cursor(info, HW_Cursor_ON); | ||
1238 | |||
1239 | return 0; | ||
1240 | } | ||
1241 | |||
1242 | static int viafb_sync(struct fb_info *info) | ||
1243 | { | ||
1244 | if (viafb_accel) | ||
1245 | viafb_wait_engine_idle(); | ||
1246 | return 0; | ||
1247 | } | ||
1248 | |||
1249 | int viafb_get_mode_index(int hres, int vres, int flag) | ||
1250 | { | ||
1251 | u32 i; | ||
1252 | DEBUG_MSG(KERN_INFO "viafb_get_mode_index!\n"); | ||
1253 | |||
1254 | for (i = 0; viafb_modentry[i].mode_index != VIA_RES_INVALID; i++) | ||
1255 | if (viafb_modentry[i].xres == hres && | ||
1256 | viafb_modentry[i].yres == vres) | ||
1257 | break; | ||
1258 | |||
1259 | viafb_resMode = viafb_modentry[i].mode_index; | ||
1260 | if (flag) | ||
1261 | viafb_mode1 = viafb_modentry[i].mode_res; | ||
1262 | else | ||
1263 | viafb_mode = viafb_modentry[i].mode_res; | ||
1264 | |||
1265 | return viafb_resMode; | ||
1266 | } | ||
1267 | |||
1268 | static void check_available_device_to_enable(int device_id) | ||
1269 | { | ||
1270 | int device_num = 0; | ||
1271 | |||
1272 | /* Initialize: */ | ||
1273 | viafb_CRT_ON = STATE_OFF; | ||
1274 | viafb_DVI_ON = STATE_OFF; | ||
1275 | viafb_LCD_ON = STATE_OFF; | ||
1276 | viafb_LCD2_ON = STATE_OFF; | ||
1277 | viafb_DeviceStatus = None_Device; | ||
1278 | |||
1279 | if ((device_id & CRT_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) { | ||
1280 | viafb_CRT_ON = STATE_ON; | ||
1281 | device_num++; | ||
1282 | viafb_DeviceStatus |= CRT_Device; | ||
1283 | } | ||
1284 | |||
1285 | if ((device_id & DVI_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) { | ||
1286 | viafb_DVI_ON = STATE_ON; | ||
1287 | device_num++; | ||
1288 | viafb_DeviceStatus |= DVI_Device; | ||
1289 | } | ||
1290 | |||
1291 | if ((device_id & LCD_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) { | ||
1292 | viafb_LCD_ON = STATE_ON; | ||
1293 | device_num++; | ||
1294 | viafb_DeviceStatus |= LCD_Device; | ||
1295 | } | ||
1296 | |||
1297 | if ((device_id & LCD2_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) { | ||
1298 | viafb_LCD2_ON = STATE_ON; | ||
1299 | device_num++; | ||
1300 | viafb_DeviceStatus |= LCD2_Device; | ||
1301 | } | ||
1302 | |||
1303 | if (viafb_DeviceStatus == None_Device) { | ||
1304 | /* Use CRT as default active device: */ | ||
1305 | viafb_CRT_ON = STATE_ON; | ||
1306 | viafb_DeviceStatus = CRT_Device; | ||
1307 | } | ||
1308 | DEBUG_MSG(KERN_INFO "Device Status:%x", viafb_DeviceStatus); | ||
1309 | } | ||
1310 | |||
1311 | static void viafb_set_device(struct device_t active_dev) | ||
1312 | { | ||
1313 | /* Check available device to enable: */ | ||
1314 | int device_id = None_Device; | ||
1315 | if (active_dev.crt) | ||
1316 | device_id |= CRT_Device; | ||
1317 | if (active_dev.dvi) | ||
1318 | device_id |= DVI_Device; | ||
1319 | if (active_dev.lcd) | ||
1320 | device_id |= LCD_Device; | ||
1321 | |||
1322 | check_available_device_to_enable(device_id); | ||
1323 | |||
1324 | /* Check property of LCD: */ | ||
1325 | if (viafb_LCD_ON) { | ||
1326 | if (active_dev.lcd_dsp_cent) { | ||
1327 | viaparinfo->lvds_setting_info->display_method = | ||
1328 | viafb_lcd_dsp_method = LCD_CENTERING; | ||
1329 | } else { | ||
1330 | viaparinfo->lvds_setting_info->display_method = | ||
1331 | viafb_lcd_dsp_method = LCD_EXPANDSION; | ||
1332 | } | ||
1333 | |||
1334 | if (active_dev.lcd_mode == LCD_SPWG) { | ||
1335 | viaparinfo->lvds_setting_info->lcd_mode = | ||
1336 | viafb_lcd_mode = LCD_SPWG; | ||
1337 | } else { | ||
1338 | viaparinfo->lvds_setting_info->lcd_mode = | ||
1339 | viafb_lcd_mode = LCD_OPENLDI; | ||
1340 | } | ||
1341 | |||
1342 | if (active_dev.lcd_panel_id <= LCD_PANEL_ID_MAXIMUM) { | ||
1343 | viafb_lcd_panel_id = active_dev.lcd_panel_id; | ||
1344 | viafb_init_lcd_size(); | ||
1345 | } | ||
1346 | } | ||
1347 | |||
1348 | /* Check property of mode: */ | ||
1349 | if (!active_dev.xres1) | ||
1350 | viafb_second_xres = 640; | ||
1351 | else | ||
1352 | viafb_second_xres = active_dev.xres1; | ||
1353 | if (!active_dev.yres1) | ||
1354 | viafb_second_yres = 480; | ||
1355 | else | ||
1356 | viafb_second_yres = active_dev.yres1; | ||
1357 | if (active_dev.bpp != 0) | ||
1358 | viafb_bpp = active_dev.bpp; | ||
1359 | if (active_dev.bpp1 != 0) | ||
1360 | viafb_bpp1 = active_dev.bpp1; | ||
1361 | if (active_dev.refresh != 0) | ||
1362 | viafb_refresh = active_dev.refresh; | ||
1363 | if (active_dev.refresh1 != 0) | ||
1364 | viafb_refresh1 = active_dev.refresh1; | ||
1365 | if ((active_dev.samm == STATE_OFF) || (active_dev.samm == STATE_ON)) | ||
1366 | viafb_SAMM_ON = active_dev.samm; | ||
1367 | viafb_primary_dev = active_dev.primary_dev; | ||
1368 | |||
1369 | viafb_set_start_addr(); | ||
1370 | viafb_set_iga_path(); | ||
1371 | } | ||
1372 | |||
1373 | static void viafb_set_video_device(u32 video_dev_info) | ||
1374 | { | ||
1375 | viaparinfo->video_on_crt = STATE_OFF; | ||
1376 | viaparinfo->video_on_dvi = STATE_OFF; | ||
1377 | viaparinfo->video_on_lcd = STATE_OFF; | ||
1378 | |||
1379 | /* Check available device to enable: */ | ||
1380 | if ((video_dev_info & CRT_Device) == CRT_Device) | ||
1381 | viaparinfo->video_on_crt = STATE_ON; | ||
1382 | else if ((video_dev_info & DVI_Device) == DVI_Device) | ||
1383 | viaparinfo->video_on_dvi = STATE_ON; | ||
1384 | else if ((video_dev_info & LCD_Device) == LCD_Device) | ||
1385 | viaparinfo->video_on_lcd = STATE_ON; | ||
1386 | } | ||
1387 | |||
1388 | static void viafb_get_video_device(u32 *video_dev_info) | ||
1389 | { | ||
1390 | *video_dev_info = None_Device; | ||
1391 | if (viaparinfo->video_on_crt == STATE_ON) | ||
1392 | *video_dev_info |= CRT_Device; | ||
1393 | else if (viaparinfo->video_on_dvi == STATE_ON) | ||
1394 | *video_dev_info |= DVI_Device; | ||
1395 | else if (viaparinfo->video_on_lcd == STATE_ON) | ||
1396 | *video_dev_info |= LCD_Device; | ||
1397 | } | ||
1398 | |||
1399 | static int get_primary_device(void) | ||
1400 | { | ||
1401 | int primary_device = 0; | ||
1402 | /* Rule: device on iga1 path are the primary device. */ | ||
1403 | if (viafb_SAMM_ON) { | ||
1404 | if (viafb_CRT_ON) { | ||
1405 | if (viaparinfo->crt_setting_info->iga_path == IGA1) { | ||
1406 | DEBUG_MSG(KERN_INFO "CRT IGA Path:%d\n", | ||
1407 | viaparinfo-> | ||
1408 | crt_setting_info->iga_path); | ||
1409 | primary_device = CRT_Device; | ||
1410 | } | ||
1411 | } | ||
1412 | if (viafb_DVI_ON) { | ||
1413 | if (viaparinfo->tmds_setting_info->iga_path == IGA1) { | ||
1414 | DEBUG_MSG(KERN_INFO "DVI IGA Path:%d\n", | ||
1415 | viaparinfo-> | ||
1416 | tmds_setting_info->iga_path); | ||
1417 | primary_device = DVI_Device; | ||
1418 | } | ||
1419 | } | ||
1420 | if (viafb_LCD_ON) { | ||
1421 | if (viaparinfo->lvds_setting_info->iga_path == IGA1) { | ||
1422 | DEBUG_MSG(KERN_INFO "LCD IGA Path:%d\n", | ||
1423 | viaparinfo-> | ||
1424 | lvds_setting_info->iga_path); | ||
1425 | primary_device = LCD_Device; | ||
1426 | } | ||
1427 | } | ||
1428 | if (viafb_LCD2_ON) { | ||
1429 | if (viaparinfo->lvds_setting_info2->iga_path == IGA1) { | ||
1430 | DEBUG_MSG(KERN_INFO "LCD2 IGA Path:%d\n", | ||
1431 | viaparinfo-> | ||
1432 | lvds_setting_info2->iga_path); | ||
1433 | primary_device = LCD2_Device; | ||
1434 | } | ||
1435 | } | ||
1436 | } | ||
1437 | return primary_device; | ||
1438 | } | ||
1439 | |||
1440 | static u8 is_duoview(void) | ||
1441 | { | ||
1442 | if (0 == viafb_SAMM_ON) { | ||
1443 | if (viafb_LCD_ON + viafb_LCD2_ON + | ||
1444 | viafb_DVI_ON + viafb_CRT_ON == 2) | ||
1445 | return true; | ||
1446 | return false; | ||
1447 | } else { | ||
1448 | return false; | ||
1449 | } | ||
1450 | } | ||
1451 | |||
1452 | static void apply_second_mode_setting(struct fb_var_screeninfo | ||
1453 | *sec_var) | ||
1454 | { | ||
1455 | u32 htotal, vtotal, long_refresh; | ||
1456 | |||
1457 | htotal = sec_var->xres + sec_var->left_margin + | ||
1458 | sec_var->right_margin + sec_var->hsync_len; | ||
1459 | vtotal = sec_var->yres + sec_var->upper_margin + | ||
1460 | sec_var->lower_margin + sec_var->vsync_len; | ||
1461 | if ((sec_var->xres_virtual * (sec_var->bits_per_pixel >> 3)) & 0x1F) { | ||
1462 | /*Is 32 bytes alignment? */ | ||
1463 | /*32 pixel alignment */ | ||
1464 | sec_var->xres_virtual = (sec_var->xres_virtual + 31) & ~31; | ||
1465 | } | ||
1466 | |||
1467 | htotal = sec_var->xres + sec_var->left_margin + | ||
1468 | sec_var->right_margin + sec_var->hsync_len; | ||
1469 | vtotal = sec_var->yres + sec_var->upper_margin + | ||
1470 | sec_var->lower_margin + sec_var->vsync_len; | ||
1471 | long_refresh = 1000000000UL / sec_var->pixclock * 1000; | ||
1472 | long_refresh /= (htotal * vtotal); | ||
1473 | |||
1474 | viafb_second_xres = sec_var->xres; | ||
1475 | viafb_second_yres = sec_var->yres; | ||
1476 | viafb_second_virtual_xres = sec_var->xres_virtual; | ||
1477 | viafb_second_virtual_yres = sec_var->yres_virtual; | ||
1478 | viafb_bpp1 = sec_var->bits_per_pixel; | ||
1479 | viafb_refresh1 = viafb_get_refresh(sec_var->xres, sec_var->yres, | ||
1480 | long_refresh); | ||
1481 | } | ||
1482 | |||
1483 | static int apply_device_setting(struct viafb_ioctl_setting setting_info, | ||
1484 | struct fb_info *info) | ||
1485 | { | ||
1486 | int need_set_mode = 0; | ||
1487 | DEBUG_MSG(KERN_INFO "apply_device_setting\n"); | ||
1488 | |||
1489 | if (setting_info.device_flag) { | ||
1490 | need_set_mode = 1; | ||
1491 | check_available_device_to_enable(setting_info.device_status); | ||
1492 | } | ||
1493 | |||
1494 | /* Unlock LCD's operation according to LCD flag | ||
1495 | and check if the setting value is valid. */ | ||
1496 | /* If the value is valid, apply the new setting value to the device. */ | ||
1497 | if (viafb_LCD_ON) { | ||
1498 | if (setting_info.lcd_operation_flag & OP_LCD_CENTERING) { | ||
1499 | need_set_mode = 1; | ||
1500 | if (setting_info.lcd_attributes.display_center) { | ||
1501 | /* Centering */ | ||
1502 | viaparinfo->lvds_setting_info->display_method = | ||
1503 | LCD_CENTERING; | ||
1504 | viafb_lcd_dsp_method = LCD_CENTERING; | ||
1505 | viaparinfo->lvds_setting_info2->display_method = | ||
1506 | viafb_lcd_dsp_method = LCD_CENTERING; | ||
1507 | } else { | ||
1508 | /* expandsion */ | ||
1509 | viaparinfo->lvds_setting_info->display_method = | ||
1510 | LCD_EXPANDSION; | ||
1511 | viafb_lcd_dsp_method = LCD_EXPANDSION; | ||
1512 | viaparinfo->lvds_setting_info2->display_method = | ||
1513 | LCD_EXPANDSION; | ||
1514 | viafb_lcd_dsp_method = LCD_EXPANDSION; | ||
1515 | } | ||
1516 | } | ||
1517 | |||
1518 | if (setting_info.lcd_operation_flag & OP_LCD_MODE) { | ||
1519 | need_set_mode = 1; | ||
1520 | if (setting_info.lcd_attributes.lcd_mode == | ||
1521 | LCD_SPWG) { | ||
1522 | viaparinfo->lvds_setting_info->lcd_mode = | ||
1523 | viafb_lcd_mode = LCD_SPWG; | ||
1524 | } else { | ||
1525 | viaparinfo->lvds_setting_info->lcd_mode = | ||
1526 | viafb_lcd_mode = LCD_OPENLDI; | ||
1527 | } | ||
1528 | viaparinfo->lvds_setting_info2->lcd_mode = | ||
1529 | viaparinfo->lvds_setting_info->lcd_mode; | ||
1530 | } | ||
1531 | |||
1532 | if (setting_info.lcd_operation_flag & OP_LCD_PANEL_ID) { | ||
1533 | need_set_mode = 1; | ||
1534 | if (setting_info.lcd_attributes.panel_id <= | ||
1535 | LCD_PANEL_ID_MAXIMUM) { | ||
1536 | viafb_lcd_panel_id = | ||
1537 | setting_info.lcd_attributes.panel_id; | ||
1538 | viafb_init_lcd_size(); | ||
1539 | } | ||
1540 | } | ||
1541 | } | ||
1542 | |||
1543 | if (0 != (setting_info.samm_status & OP_SAMM)) { | ||
1544 | setting_info.samm_status = | ||
1545 | setting_info.samm_status & (~OP_SAMM); | ||
1546 | if (setting_info.samm_status == 0 | ||
1547 | || setting_info.samm_status == 1) { | ||
1548 | viafb_SAMM_ON = setting_info.samm_status; | ||
1549 | |||
1550 | if (viafb_SAMM_ON) | ||
1551 | viafb_primary_dev = setting_info.primary_device; | ||
1552 | |||
1553 | viafb_set_start_addr(); | ||
1554 | viafb_set_iga_path(); | ||
1555 | } | ||
1556 | need_set_mode = 1; | ||
1557 | } | ||
1558 | |||
1559 | viaparinfo->duoview = is_duoview(); | ||
1560 | |||
1561 | if (!need_set_mode) { | ||
1562 | ; | ||
1563 | } else { | ||
1564 | viafb_set_iga_path(); | ||
1565 | viafb_set_par(info); | ||
1566 | } | ||
1567 | return true; | ||
1568 | } | ||
1569 | |||
1570 | static void retrieve_device_setting(struct viafb_ioctl_setting | ||
1571 | *setting_info) | ||
1572 | { | ||
1573 | |||
1574 | /* get device status */ | ||
1575 | if (viafb_CRT_ON == 1) | ||
1576 | setting_info->device_status = CRT_Device; | ||
1577 | if (viafb_DVI_ON == 1) | ||
1578 | setting_info->device_status |= DVI_Device; | ||
1579 | if (viafb_LCD_ON == 1) | ||
1580 | setting_info->device_status |= LCD_Device; | ||
1581 | if (viafb_LCD2_ON == 1) | ||
1582 | setting_info->device_status |= LCD2_Device; | ||
1583 | if ((viaparinfo->video_on_crt == 1) && (viafb_CRT_ON == 1)) { | ||
1584 | setting_info->video_device_status = | ||
1585 | viaparinfo->crt_setting_info->iga_path; | ||
1586 | } else if ((viaparinfo->video_on_dvi == 1) && (viafb_DVI_ON == 1)) { | ||
1587 | setting_info->video_device_status = | ||
1588 | viaparinfo->tmds_setting_info->iga_path; | ||
1589 | } else if ((viaparinfo->video_on_lcd == 1) && (viafb_LCD_ON == 1)) { | ||
1590 | setting_info->video_device_status = | ||
1591 | viaparinfo->lvds_setting_info->iga_path; | ||
1592 | } else { | ||
1593 | setting_info->video_device_status = 0; | ||
1594 | } | ||
1595 | |||
1596 | setting_info->samm_status = viafb_SAMM_ON; | ||
1597 | setting_info->primary_device = get_primary_device(); | ||
1598 | |||
1599 | setting_info->first_dev_bpp = viafb_bpp; | ||
1600 | setting_info->second_dev_bpp = viafb_bpp1; | ||
1601 | |||
1602 | setting_info->first_dev_refresh = viafb_refresh; | ||
1603 | setting_info->second_dev_refresh = viafb_refresh1; | ||
1604 | |||
1605 | setting_info->first_dev_hor_res = viafb_hotplug_Xres; | ||
1606 | setting_info->first_dev_ver_res = viafb_hotplug_Yres; | ||
1607 | setting_info->second_dev_hor_res = viafb_second_xres; | ||
1608 | setting_info->second_dev_ver_res = viafb_second_yres; | ||
1609 | |||
1610 | /* Get lcd attributes */ | ||
1611 | setting_info->lcd_attributes.display_center = viafb_lcd_dsp_method; | ||
1612 | setting_info->lcd_attributes.panel_id = viafb_lcd_panel_id; | ||
1613 | setting_info->lcd_attributes.lcd_mode = viafb_lcd_mode; | ||
1614 | } | ||
1615 | |||
1616 | static void parse_active_dev(void) | ||
1617 | { | ||
1618 | viafb_CRT_ON = STATE_OFF; | ||
1619 | viafb_DVI_ON = STATE_OFF; | ||
1620 | viafb_LCD_ON = STATE_OFF; | ||
1621 | viafb_LCD2_ON = STATE_OFF; | ||
1622 | /* 1. Modify the active status of devices. */ | ||
1623 | /* 2. Keep the order of devices, so we can set corresponding | ||
1624 | IGA path to devices in SAMM case. */ | ||
1625 | /* Note: The previous of active_dev is primary device, | ||
1626 | and the following is secondary device. */ | ||
1627 | if (!strncmp(viafb_active_dev, "CRT+DVI", 7)) { | ||
1628 | /* CRT+DVI */ | ||
1629 | viafb_CRT_ON = STATE_ON; | ||
1630 | viafb_DVI_ON = STATE_ON; | ||
1631 | viafb_primary_dev = CRT_Device; | ||
1632 | } else if (!strncmp(viafb_active_dev, "DVI+CRT", 7)) { | ||
1633 | /* DVI+CRT */ | ||
1634 | viafb_CRT_ON = STATE_ON; | ||
1635 | viafb_DVI_ON = STATE_ON; | ||
1636 | viafb_primary_dev = DVI_Device; | ||
1637 | } else if (!strncmp(viafb_active_dev, "CRT+LCD", 7)) { | ||
1638 | /* CRT+LCD */ | ||
1639 | viafb_CRT_ON = STATE_ON; | ||
1640 | viafb_LCD_ON = STATE_ON; | ||
1641 | viafb_primary_dev = CRT_Device; | ||
1642 | } else if (!strncmp(viafb_active_dev, "LCD+CRT", 7)) { | ||
1643 | /* LCD+CRT */ | ||
1644 | viafb_CRT_ON = STATE_ON; | ||
1645 | viafb_LCD_ON = STATE_ON; | ||
1646 | viafb_primary_dev = LCD_Device; | ||
1647 | } else if (!strncmp(viafb_active_dev, "DVI+LCD", 7)) { | ||
1648 | /* DVI+LCD */ | ||
1649 | viafb_DVI_ON = STATE_ON; | ||
1650 | viafb_LCD_ON = STATE_ON; | ||
1651 | viafb_primary_dev = DVI_Device; | ||
1652 | } else if (!strncmp(viafb_active_dev, "LCD+DVI", 7)) { | ||
1653 | /* LCD+DVI */ | ||
1654 | viafb_DVI_ON = STATE_ON; | ||
1655 | viafb_LCD_ON = STATE_ON; | ||
1656 | viafb_primary_dev = LCD_Device; | ||
1657 | } else if (!strncmp(viafb_active_dev, "LCD+LCD2", 8)) { | ||
1658 | viafb_LCD_ON = STATE_ON; | ||
1659 | viafb_LCD2_ON = STATE_ON; | ||
1660 | viafb_primary_dev = LCD_Device; | ||
1661 | } else if (!strncmp(viafb_active_dev, "LCD2+LCD", 8)) { | ||
1662 | viafb_LCD_ON = STATE_ON; | ||
1663 | viafb_LCD2_ON = STATE_ON; | ||
1664 | viafb_primary_dev = LCD2_Device; | ||
1665 | } else if (!strncmp(viafb_active_dev, "CRT", 3)) { | ||
1666 | /* CRT only */ | ||
1667 | viafb_CRT_ON = STATE_ON; | ||
1668 | viafb_SAMM_ON = STATE_OFF; | ||
1669 | } else if (!strncmp(viafb_active_dev, "DVI", 3)) { | ||
1670 | /* DVI only */ | ||
1671 | viafb_DVI_ON = STATE_ON; | ||
1672 | viafb_SAMM_ON = STATE_OFF; | ||
1673 | } else if (!strncmp(viafb_active_dev, "LCD", 3)) { | ||
1674 | /* LCD only */ | ||
1675 | viafb_LCD_ON = STATE_ON; | ||
1676 | viafb_SAMM_ON = STATE_OFF; | ||
1677 | } else { | ||
1678 | viafb_CRT_ON = STATE_ON; | ||
1679 | viafb_SAMM_ON = STATE_OFF; | ||
1680 | } | ||
1681 | viaparinfo->duoview = is_duoview(); | ||
1682 | } | ||
1683 | |||
1684 | static void parse_video_dev(void) | ||
1685 | { | ||
1686 | viaparinfo->video_on_crt = STATE_OFF; | ||
1687 | viaparinfo->video_on_dvi = STATE_OFF; | ||
1688 | viaparinfo->video_on_lcd = STATE_OFF; | ||
1689 | |||
1690 | if (!strncmp(viafb_video_dev, "CRT", 3)) { | ||
1691 | /* Video on CRT */ | ||
1692 | viaparinfo->video_on_crt = STATE_ON; | ||
1693 | } else if (!strncmp(viafb_video_dev, "DVI", 3)) { | ||
1694 | /* Video on DVI */ | ||
1695 | viaparinfo->video_on_dvi = STATE_ON; | ||
1696 | } else if (!strncmp(viafb_video_dev, "LCD", 3)) { | ||
1697 | /* Video on LCD */ | ||
1698 | viaparinfo->video_on_lcd = STATE_ON; | ||
1699 | } | ||
1700 | } | ||
1701 | |||
1702 | static int parse_port(char *opt_str, int *output_interface) | ||
1703 | { | ||
1704 | if (!strncmp(opt_str, "DVP0", 4)) | ||
1705 | *output_interface = INTERFACE_DVP0; | ||
1706 | else if (!strncmp(opt_str, "DVP1", 4)) | ||
1707 | *output_interface = INTERFACE_DVP1; | ||
1708 | else if (!strncmp(opt_str, "DFP_HIGHLOW", 11)) | ||
1709 | *output_interface = INTERFACE_DFP; | ||
1710 | else if (!strncmp(opt_str, "DFP_HIGH", 8)) | ||
1711 | *output_interface = INTERFACE_DFP_HIGH; | ||
1712 | else if (!strncmp(opt_str, "DFP_LOW", 7)) | ||
1713 | *output_interface = INTERFACE_DFP_LOW; | ||
1714 | else | ||
1715 | *output_interface = INTERFACE_NONE; | ||
1716 | return 0; | ||
1717 | } | ||
1718 | |||
1719 | static void parse_lcd_port(void) | ||
1720 | { | ||
1721 | parse_port(viafb_lcd_port, &viaparinfo->chip_info->lvds_chip_info. | ||
1722 | output_interface); | ||
1723 | /*Initialize to avoid unexpected behavior */ | ||
1724 | viaparinfo->chip_info->lvds_chip_info2.output_interface = | ||
1725 | INTERFACE_NONE; | ||
1726 | |||
1727 | DEBUG_MSG(KERN_INFO "parse_lcd_port: viafb_lcd_port:%s,interface:%d\n", | ||
1728 | viafb_lcd_port, viaparinfo->chip_info->lvds_chip_info. | ||
1729 | output_interface); | ||
1730 | } | ||
1731 | |||
1732 | static void parse_dvi_port(void) | ||
1733 | { | ||
1734 | parse_port(viafb_dvi_port, &viaparinfo->chip_info->tmds_chip_info. | ||
1735 | output_interface); | ||
1736 | |||
1737 | DEBUG_MSG(KERN_INFO "parse_dvi_port: viafb_dvi_port:%s,interface:%d\n", | ||
1738 | viafb_dvi_port, viaparinfo->chip_info->tmds_chip_info. | ||
1739 | output_interface); | ||
1740 | } | ||
1741 | |||
1742 | /* | ||
1743 | * The proc filesystem read/write function, a simple proc implement to | ||
1744 | * get/set the value of DPA DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1, | ||
1745 | * DVP1Driving, DFPHigh, DFPLow CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], | ||
1746 | * CR9B, SR65, CR97, CR99 | ||
1747 | */ | ||
1748 | static int viafb_dvp0_proc_read(char *buf, char **start, off_t offset, | ||
1749 | int count, int *eof, void *data) | ||
1750 | { | ||
1751 | int len = 0; | ||
1752 | u8 dvp0_data_dri = 0, dvp0_clk_dri = 0, dvp0 = 0; | ||
1753 | dvp0_data_dri = | ||
1754 | (viafb_read_reg(VIASR, SR2A) & BIT5) >> 4 | | ||
1755 | (viafb_read_reg(VIASR, SR1B) & BIT1) >> 1; | ||
1756 | dvp0_clk_dri = | ||
1757 | (viafb_read_reg(VIASR, SR2A) & BIT4) >> 3 | | ||
1758 | (viafb_read_reg(VIASR, SR1E) & BIT2) >> 2; | ||
1759 | dvp0 = viafb_read_reg(VIACR, CR96) & 0x0f; | ||
1760 | len += | ||
1761 | sprintf(buf + len, "%x %x %x\n", dvp0, dvp0_data_dri, dvp0_clk_dri); | ||
1762 | *eof = 1; /*Inform kernel end of data */ | ||
1763 | return len; | ||
1764 | } | ||
1765 | static int viafb_dvp0_proc_write(struct file *file, | ||
1766 | const char __user *buffer, unsigned long count, void *data) | ||
1767 | { | ||
1768 | char buf[20], *value, *pbuf; | ||
1769 | u8 reg_val = 0; | ||
1770 | unsigned long length, i; | ||
1771 | if (count < 1) | ||
1772 | return -EINVAL; | ||
1773 | length = count > 20 ? 20 : count; | ||
1774 | if (copy_from_user(&buf[0], buffer, length)) | ||
1775 | return -EFAULT; | ||
1776 | buf[length - 1] = '\0'; /*Ensure end string */ | ||
1777 | pbuf = &buf[0]; | ||
1778 | for (i = 0; i < 3; i++) { | ||
1779 | value = strsep(&pbuf, " "); | ||
1780 | if (value != NULL) { | ||
1781 | strict_strtoul(value, 0, (unsigned long *)®_val); | ||
1782 | DEBUG_MSG(KERN_INFO "DVP0:reg_val[%l]=:%x\n", i, | ||
1783 | reg_val); | ||
1784 | switch (i) { | ||
1785 | case 0: | ||
1786 | viafb_write_reg_mask(CR96, VIACR, | ||
1787 | reg_val, 0x0f); | ||
1788 | break; | ||
1789 | case 1: | ||
1790 | viafb_write_reg_mask(SR2A, VIASR, | ||
1791 | reg_val << 4, BIT5); | ||
1792 | viafb_write_reg_mask(SR1B, VIASR, | ||
1793 | reg_val << 1, BIT1); | ||
1794 | break; | ||
1795 | case 2: | ||
1796 | viafb_write_reg_mask(SR2A, VIASR, | ||
1797 | reg_val << 3, BIT4); | ||
1798 | viafb_write_reg_mask(SR1E, VIASR, | ||
1799 | reg_val << 2, BIT2); | ||
1800 | break; | ||
1801 | default: | ||
1802 | break; | ||
1803 | } | ||
1804 | } else { | ||
1805 | break; | ||
1806 | } | ||
1807 | } | ||
1808 | return count; | ||
1809 | } | ||
1810 | static int viafb_dvp1_proc_read(char *buf, char **start, off_t offset, | ||
1811 | int count, int *eof, void *data) | ||
1812 | { | ||
1813 | int len = 0; | ||
1814 | u8 dvp1 = 0, dvp1_data_dri = 0, dvp1_clk_dri = 0; | ||
1815 | dvp1 = viafb_read_reg(VIACR, CR9B) & 0x0f; | ||
1816 | dvp1_data_dri = (viafb_read_reg(VIASR, SR65) & 0x0c) >> 2; | ||
1817 | dvp1_clk_dri = viafb_read_reg(VIASR, SR65) & 0x03; | ||
1818 | len += | ||
1819 | sprintf(buf + len, "%x %x %x\n", dvp1, dvp1_data_dri, dvp1_clk_dri); | ||
1820 | *eof = 1; /*Inform kernel end of data */ | ||
1821 | return len; | ||
1822 | } | ||
1823 | static int viafb_dvp1_proc_write(struct file *file, | ||
1824 | const char __user *buffer, unsigned long count, void *data) | ||
1825 | { | ||
1826 | char buf[20], *value, *pbuf; | ||
1827 | u8 reg_val = 0; | ||
1828 | unsigned long length, i; | ||
1829 | if (count < 1) | ||
1830 | return -EINVAL; | ||
1831 | length = count > 20 ? 20 : count; | ||
1832 | if (copy_from_user(&buf[0], buffer, length)) | ||
1833 | return -EFAULT; | ||
1834 | buf[length - 1] = '\0'; /*Ensure end string */ | ||
1835 | pbuf = &buf[0]; | ||
1836 | for (i = 0; i < 3; i++) { | ||
1837 | value = strsep(&pbuf, " "); | ||
1838 | if (value != NULL) { | ||
1839 | strict_strtoul(value, 0, (unsigned long *)®_val); | ||
1840 | switch (i) { | ||
1841 | case 0: | ||
1842 | viafb_write_reg_mask(CR9B, VIACR, | ||
1843 | reg_val, 0x0f); | ||
1844 | break; | ||
1845 | case 1: | ||
1846 | viafb_write_reg_mask(SR65, VIASR, | ||
1847 | reg_val << 2, 0x0c); | ||
1848 | break; | ||
1849 | case 2: | ||
1850 | viafb_write_reg_mask(SR65, VIASR, | ||
1851 | reg_val, 0x03); | ||
1852 | break; | ||
1853 | default: | ||
1854 | break; | ||
1855 | } | ||
1856 | } else { | ||
1857 | break; | ||
1858 | } | ||
1859 | } | ||
1860 | return count; | ||
1861 | } | ||
1862 | |||
1863 | static int viafb_dfph_proc_read(char *buf, char **start, off_t offset, | ||
1864 | int count, int *eof, void *data) | ||
1865 | { | ||
1866 | int len = 0; | ||
1867 | u8 dfp_high = 0; | ||
1868 | dfp_high = viafb_read_reg(VIACR, CR97) & 0x0f; | ||
1869 | len += sprintf(buf + len, "%x\n", dfp_high); | ||
1870 | *eof = 1; /*Inform kernel end of data */ | ||
1871 | return len; | ||
1872 | } | ||
1873 | static int viafb_dfph_proc_write(struct file *file, | ||
1874 | const char __user *buffer, unsigned long count, void *data) | ||
1875 | { | ||
1876 | char buf[20]; | ||
1877 | u8 reg_val = 0; | ||
1878 | unsigned long length; | ||
1879 | if (count < 1) | ||
1880 | return -EINVAL; | ||
1881 | length = count > 20 ? 20 : count; | ||
1882 | if (copy_from_user(&buf[0], buffer, length)) | ||
1883 | return -EFAULT; | ||
1884 | buf[length - 1] = '\0'; /*Ensure end string */ | ||
1885 | strict_strtoul(&buf[0], 0, (unsigned long *)®_val); | ||
1886 | viafb_write_reg_mask(CR97, VIACR, reg_val, 0x0f); | ||
1887 | return count; | ||
1888 | } | ||
1889 | static int viafb_dfpl_proc_read(char *buf, char **start, off_t offset, | ||
1890 | int count, int *eof, void *data) | ||
1891 | { | ||
1892 | int len = 0; | ||
1893 | u8 dfp_low = 0; | ||
1894 | dfp_low = viafb_read_reg(VIACR, CR99) & 0x0f; | ||
1895 | len += sprintf(buf + len, "%x\n", dfp_low); | ||
1896 | *eof = 1; /*Inform kernel end of data */ | ||
1897 | return len; | ||
1898 | } | ||
1899 | static int viafb_dfpl_proc_write(struct file *file, | ||
1900 | const char __user *buffer, unsigned long count, void *data) | ||
1901 | { | ||
1902 | char buf[20]; | ||
1903 | u8 reg_val = 0; | ||
1904 | unsigned long length; | ||
1905 | if (count < 1) | ||
1906 | return -EINVAL; | ||
1907 | length = count > 20 ? 20 : count; | ||
1908 | if (copy_from_user(&buf[0], buffer, length)) | ||
1909 | return -EFAULT; | ||
1910 | buf[length - 1] = '\0'; /*Ensure end string */ | ||
1911 | strict_strtoul(&buf[0], 0, (unsigned long *)®_val); | ||
1912 | viafb_write_reg_mask(CR99, VIACR, reg_val, 0x0f); | ||
1913 | return count; | ||
1914 | } | ||
1915 | static int viafb_vt1636_proc_read(char *buf, char **start, | ||
1916 | off_t offset, int count, int *eof, void *data) | ||
1917 | { | ||
1918 | int len = 0; | ||
1919 | u8 vt1636_08 = 0, vt1636_09 = 0; | ||
1920 | switch (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) { | ||
1921 | case VT1636_LVDS: | ||
1922 | vt1636_08 = | ||
1923 | viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info, | ||
1924 | &viaparinfo->chip_info->lvds_chip_info, 0x08) & 0x0f; | ||
1925 | vt1636_09 = | ||
1926 | viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info, | ||
1927 | &viaparinfo->chip_info->lvds_chip_info, 0x09) & 0x1f; | ||
1928 | len += sprintf(buf + len, "%x %x\n", vt1636_08, vt1636_09); | ||
1929 | break; | ||
1930 | default: | ||
1931 | break; | ||
1932 | } | ||
1933 | switch (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) { | ||
1934 | case VT1636_LVDS: | ||
1935 | vt1636_08 = | ||
1936 | viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info2, | ||
1937 | &viaparinfo->chip_info->lvds_chip_info2, 0x08) & 0x0f; | ||
1938 | vt1636_09 = | ||
1939 | viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info2, | ||
1940 | &viaparinfo->chip_info->lvds_chip_info2, 0x09) & 0x1f; | ||
1941 | len += sprintf(buf + len, " %x %x\n", vt1636_08, vt1636_09); | ||
1942 | break; | ||
1943 | default: | ||
1944 | break; | ||
1945 | } | ||
1946 | *eof = 1; /*Inform kernel end of data */ | ||
1947 | return len; | ||
1948 | } | ||
1949 | static int viafb_vt1636_proc_write(struct file *file, | ||
1950 | const char __user *buffer, unsigned long count, void *data) | ||
1951 | { | ||
1952 | char buf[30], *value, *pbuf; | ||
1953 | struct IODATA reg_val; | ||
1954 | unsigned long length, i; | ||
1955 | if (count < 1) | ||
1956 | return -EINVAL; | ||
1957 | length = count > 30 ? 30 : count; | ||
1958 | if (copy_from_user(&buf[0], buffer, length)) | ||
1959 | return -EFAULT; | ||
1960 | buf[length - 1] = '\0'; /*Ensure end string */ | ||
1961 | pbuf = &buf[0]; | ||
1962 | switch (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) { | ||
1963 | case VT1636_LVDS: | ||
1964 | for (i = 0; i < 2; i++) { | ||
1965 | value = strsep(&pbuf, " "); | ||
1966 | if (value != NULL) { | ||
1967 | strict_strtoul(value, 0, | ||
1968 | (unsigned long *)®_val.Data); | ||
1969 | switch (i) { | ||
1970 | case 0: | ||
1971 | reg_val.Index = 0x08; | ||
1972 | reg_val.Mask = 0x0f; | ||
1973 | viafb_gpio_i2c_write_mask_lvds | ||
1974 | (viaparinfo->lvds_setting_info, | ||
1975 | &viaparinfo-> | ||
1976 | chip_info->lvds_chip_info, | ||
1977 | reg_val); | ||
1978 | break; | ||
1979 | case 1: | ||
1980 | reg_val.Index = 0x09; | ||
1981 | reg_val.Mask = 0x1f; | ||
1982 | viafb_gpio_i2c_write_mask_lvds | ||
1983 | (viaparinfo->lvds_setting_info, | ||
1984 | &viaparinfo-> | ||
1985 | chip_info->lvds_chip_info, | ||
1986 | reg_val); | ||
1987 | break; | ||
1988 | default: | ||
1989 | break; | ||
1990 | } | ||
1991 | } else { | ||
1992 | break; | ||
1993 | } | ||
1994 | } | ||
1995 | break; | ||
1996 | default: | ||
1997 | break; | ||
1998 | } | ||
1999 | switch (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) { | ||
2000 | case VT1636_LVDS: | ||
2001 | for (i = 0; i < 2; i++) { | ||
2002 | value = strsep(&pbuf, " "); | ||
2003 | if (value != NULL) { | ||
2004 | strict_strtoul(value, 0, | ||
2005 | (unsigned long *)®_val.Data); | ||
2006 | switch (i) { | ||
2007 | case 0: | ||
2008 | reg_val.Index = 0x08; | ||
2009 | reg_val.Mask = 0x0f; | ||
2010 | viafb_gpio_i2c_write_mask_lvds | ||
2011 | (viaparinfo->lvds_setting_info2, | ||
2012 | &viaparinfo-> | ||
2013 | chip_info->lvds_chip_info2, | ||
2014 | reg_val); | ||
2015 | break; | ||
2016 | case 1: | ||
2017 | reg_val.Index = 0x09; | ||
2018 | reg_val.Mask = 0x1f; | ||
2019 | viafb_gpio_i2c_write_mask_lvds | ||
2020 | (viaparinfo->lvds_setting_info2, | ||
2021 | &viaparinfo-> | ||
2022 | chip_info->lvds_chip_info2, | ||
2023 | reg_val); | ||
2024 | break; | ||
2025 | default: | ||
2026 | break; | ||
2027 | } | ||
2028 | } else { | ||
2029 | break; | ||
2030 | } | ||
2031 | } | ||
2032 | break; | ||
2033 | default: | ||
2034 | break; | ||
2035 | } | ||
2036 | return count; | ||
2037 | } | ||
2038 | |||
2039 | static void viafb_init_proc(struct proc_dir_entry *viafb_entry) | ||
2040 | { | ||
2041 | struct proc_dir_entry *entry; | ||
2042 | viafb_entry = proc_mkdir("viafb", NULL); | ||
2043 | if (viafb_entry) { | ||
2044 | entry = create_proc_entry("dvp0", 0, viafb_entry); | ||
2045 | if (entry) { | ||
2046 | entry->owner = THIS_MODULE; | ||
2047 | entry->read_proc = viafb_dvp0_proc_read; | ||
2048 | entry->write_proc = viafb_dvp0_proc_write; | ||
2049 | } | ||
2050 | entry = create_proc_entry("dvp1", 0, viafb_entry); | ||
2051 | if (entry) { | ||
2052 | entry->owner = THIS_MODULE; | ||
2053 | entry->read_proc = viafb_dvp1_proc_read; | ||
2054 | entry->write_proc = viafb_dvp1_proc_write; | ||
2055 | } | ||
2056 | entry = create_proc_entry("dfph", 0, viafb_entry); | ||
2057 | if (entry) { | ||
2058 | entry->owner = THIS_MODULE; | ||
2059 | entry->read_proc = viafb_dfph_proc_read; | ||
2060 | entry->write_proc = viafb_dfph_proc_write; | ||
2061 | } | ||
2062 | entry = create_proc_entry("dfpl", 0, viafb_entry); | ||
2063 | if (entry) { | ||
2064 | entry->owner = THIS_MODULE; | ||
2065 | entry->read_proc = viafb_dfpl_proc_read; | ||
2066 | entry->write_proc = viafb_dfpl_proc_write; | ||
2067 | } | ||
2068 | if (VT1636_LVDS == viaparinfo->chip_info->lvds_chip_info. | ||
2069 | lvds_chip_name || VT1636_LVDS == | ||
2070 | viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) { | ||
2071 | entry = create_proc_entry("vt1636", 0, viafb_entry); | ||
2072 | if (entry) { | ||
2073 | entry->owner = THIS_MODULE; | ||
2074 | entry->read_proc = viafb_vt1636_proc_read; | ||
2075 | entry->write_proc = viafb_vt1636_proc_write; | ||
2076 | } | ||
2077 | } | ||
2078 | |||
2079 | } | ||
2080 | } | ||
2081 | static void viafb_remove_proc(struct proc_dir_entry *viafb_entry) | ||
2082 | { | ||
2083 | /* no problem if it was not registered */ | ||
2084 | remove_proc_entry("dvp0", viafb_entry);/* parent dir */ | ||
2085 | remove_proc_entry("dvp1", viafb_entry); | ||
2086 | remove_proc_entry("dfph", viafb_entry); | ||
2087 | remove_proc_entry("dfpl", viafb_entry); | ||
2088 | remove_proc_entry("vt1636", viafb_entry); | ||
2089 | remove_proc_entry("vt1625", viafb_entry); | ||
2090 | } | ||
2091 | |||
2092 | static int __devinit via_pci_probe(void) | ||
2093 | { | ||
2094 | unsigned int default_xres, default_yres; | ||
2095 | char *tmpc, *tmpm; | ||
2096 | char *tmpc_sec, *tmpm_sec; | ||
2097 | int vmode_index; | ||
2098 | u32 tmds_length, lvds_length, crt_length, chip_length, viafb_par_length; | ||
2099 | |||
2100 | DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n"); | ||
2101 | |||
2102 | viafb_par_length = ALIGN(sizeof(struct viafb_par), BITS_PER_LONG/8); | ||
2103 | tmds_length = ALIGN(sizeof(struct tmds_setting_information), | ||
2104 | BITS_PER_LONG/8); | ||
2105 | lvds_length = ALIGN(sizeof(struct lvds_setting_information), | ||
2106 | BITS_PER_LONG/8); | ||
2107 | crt_length = ALIGN(sizeof(struct lvds_setting_information), | ||
2108 | BITS_PER_LONG/8); | ||
2109 | chip_length = ALIGN(sizeof(struct chip_information), BITS_PER_LONG/8); | ||
2110 | |||
2111 | /* Allocate fb_info and ***_par here, also including some other needed | ||
2112 | * variables | ||
2113 | */ | ||
2114 | viafbinfo = framebuffer_alloc(viafb_par_length + 2 * lvds_length + | ||
2115 | tmds_length + crt_length + chip_length, NULL); | ||
2116 | if (!viafbinfo) { | ||
2117 | printk(KERN_ERR"Could not allocate memory for viafb_info.\n"); | ||
2118 | return -ENODEV; | ||
2119 | } | ||
2120 | |||
2121 | viaparinfo = (struct viafb_par *)viafbinfo->par; | ||
2122 | viaparinfo->tmds_setting_info = (struct tmds_setting_information *) | ||
2123 | ((unsigned long)viaparinfo + viafb_par_length); | ||
2124 | viaparinfo->lvds_setting_info = (struct lvds_setting_information *) | ||
2125 | ((unsigned long)viaparinfo->tmds_setting_info + tmds_length); | ||
2126 | viaparinfo->lvds_setting_info2 = (struct lvds_setting_information *) | ||
2127 | ((unsigned long)viaparinfo->lvds_setting_info + lvds_length); | ||
2128 | viaparinfo->crt_setting_info = (struct crt_setting_information *) | ||
2129 | ((unsigned long)viaparinfo->lvds_setting_info2 + lvds_length); | ||
2130 | viaparinfo->chip_info = (struct chip_information *) | ||
2131 | ((unsigned long)viaparinfo->crt_setting_info + crt_length); | ||
2132 | |||
2133 | if (viafb_dual_fb) | ||
2134 | viafb_SAMM_ON = 1; | ||
2135 | parse_active_dev(); | ||
2136 | parse_video_dev(); | ||
2137 | parse_lcd_port(); | ||
2138 | parse_dvi_port(); | ||
2139 | |||
2140 | /* for dual-fb must viafb_SAMM_ON=1 and viafb_dual_fb=1 */ | ||
2141 | if (!viafb_SAMM_ON) | ||
2142 | viafb_dual_fb = 0; | ||
2143 | |||
2144 | /* Set up I2C bus stuff */ | ||
2145 | viafb_create_i2c_bus(viaparinfo); | ||
2146 | |||
2147 | viafb_init_chip_info(); | ||
2148 | viafb_get_fb_info(&viaparinfo->fbmem, &viaparinfo->memsize); | ||
2149 | viaparinfo->fbmem_free = viaparinfo->memsize; | ||
2150 | viaparinfo->fbmem_used = 0; | ||
2151 | viaparinfo->fbmem_virt = ioremap_nocache(viaparinfo->fbmem, | ||
2152 | viaparinfo->memsize); | ||
2153 | viafbinfo->screen_base = (char *)viaparinfo->fbmem_virt; | ||
2154 | |||
2155 | if (!viaparinfo->fbmem_virt) { | ||
2156 | printk(KERN_INFO "ioremap failed\n"); | ||
2157 | return -1; | ||
2158 | } | ||
2159 | |||
2160 | viafb_get_mmio_info(&viaparinfo->mmio_base, &viaparinfo->mmio_len); | ||
2161 | viaparinfo->io_virt = ioremap_nocache(viaparinfo->mmio_base, | ||
2162 | viaparinfo->mmio_len); | ||
2163 | |||
2164 | viafbinfo->node = 0; | ||
2165 | viafbinfo->fbops = &viafb_ops; | ||
2166 | viafbinfo->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; | ||
2167 | |||
2168 | viafbinfo->pseudo_palette = pseudo_pal; | ||
2169 | if (viafb_accel) { | ||
2170 | viafb_init_accel(); | ||
2171 | viafb_init_2d_engine(); | ||
2172 | viafb_hw_cursor_init(); | ||
2173 | } | ||
2174 | |||
2175 | if (viafb_second_size && (viafb_second_size < 8)) { | ||
2176 | viafb_second_offset = viaparinfo->fbmem_free - | ||
2177 | viafb_second_size * 1024 * 1024; | ||
2178 | } else { | ||
2179 | viafb_second_size = 8; | ||
2180 | viafb_second_offset = viaparinfo->fbmem_free - | ||
2181 | viafb_second_size * 1024 * 1024; | ||
2182 | } | ||
2183 | |||
2184 | viafb_FB_MM = viaparinfo->fbmem_virt; | ||
2185 | tmpm = viafb_mode; | ||
2186 | tmpc = strsep(&tmpm, "x"); | ||
2187 | strict_strtoul(tmpc, 0, (unsigned long *)&default_xres); | ||
2188 | strict_strtoul(tmpm, 0, (unsigned long *)&default_yres); | ||
2189 | |||
2190 | vmode_index = viafb_get_mode_index(default_xres, default_yres, 0); | ||
2191 | DEBUG_MSG(KERN_INFO "0->index=%d\n", vmode_index); | ||
2192 | |||
2193 | if (viafb_SAMM_ON == 1) { | ||
2194 | if (strcmp(viafb_mode, viafb_mode1)) { | ||
2195 | tmpm_sec = viafb_mode1; | ||
2196 | tmpc_sec = strsep(&tmpm_sec, "x"); | ||
2197 | strict_strtoul(tmpc_sec, 0, | ||
2198 | (unsigned long *)&viafb_second_xres); | ||
2199 | strict_strtoul(tmpm_sec, 0, | ||
2200 | (unsigned long *)&viafb_second_yres); | ||
2201 | } else { | ||
2202 | viafb_second_xres = default_xres; | ||
2203 | viafb_second_yres = default_yres; | ||
2204 | } | ||
2205 | if (0 == viafb_second_virtual_xres) { | ||
2206 | switch (viafb_second_xres) { | ||
2207 | case 1400: | ||
2208 | viafb_second_virtual_xres = 1408; | ||
2209 | break; | ||
2210 | default: | ||
2211 | viafb_second_virtual_xres = viafb_second_xres; | ||
2212 | break; | ||
2213 | } | ||
2214 | } | ||
2215 | if (0 == viafb_second_virtual_yres) | ||
2216 | viafb_second_virtual_yres = viafb_second_yres; | ||
2217 | } | ||
2218 | |||
2219 | switch (viafb_bpp) { | ||
2220 | case 0 ... 8: | ||
2221 | viafb_bpp = 8; | ||
2222 | break; | ||
2223 | case 9 ... 16: | ||
2224 | viafb_bpp = 16; | ||
2225 | break; | ||
2226 | case 17 ... 32: | ||
2227 | viafb_bpp = 32; | ||
2228 | break; | ||
2229 | default: | ||
2230 | viafb_bpp = 8; | ||
2231 | } | ||
2232 | default_var.xres = default_xres; | ||
2233 | default_var.yres = default_yres; | ||
2234 | switch (default_xres) { | ||
2235 | case 1400: | ||
2236 | default_var.xres_virtual = 1408; | ||
2237 | break; | ||
2238 | default: | ||
2239 | default_var.xres_virtual = default_xres; | ||
2240 | break; | ||
2241 | } | ||
2242 | default_var.yres_virtual = default_yres; | ||
2243 | default_var.bits_per_pixel = viafb_bpp; | ||
2244 | if (default_var.bits_per_pixel == 15) | ||
2245 | default_var.bits_per_pixel = 16; | ||
2246 | default_var.pixclock = | ||
2247 | viafb_get_pixclock(default_xres, default_yres, viafb_refresh); | ||
2248 | default_var.left_margin = (default_xres >> 3) & 0xf8; | ||
2249 | default_var.right_margin = 32; | ||
2250 | default_var.upper_margin = 16; | ||
2251 | default_var.lower_margin = 4; | ||
2252 | default_var.hsync_len = default_var.left_margin; | ||
2253 | default_var.vsync_len = 4; | ||
2254 | default_var.accel_flags = 0; | ||
2255 | |||
2256 | if (viafb_accel) { | ||
2257 | viafbinfo->flags |= | ||
2258 | (FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT | | ||
2259 | FBINFO_HWACCEL_IMAGEBLIT); | ||
2260 | default_var.accel_flags |= FB_ACCELF_TEXT; | ||
2261 | } else | ||
2262 | viafbinfo->flags |= FBINFO_HWACCEL_DISABLED; | ||
2263 | |||
2264 | if (viafb_dual_fb) { | ||
2265 | viafbinfo1 = framebuffer_alloc(viafb_par_length, NULL); | ||
2266 | if (!viafbinfo1) { | ||
2267 | printk(KERN_ERR | ||
2268 | "allocate the second framebuffer struct error\n"); | ||
2269 | framebuffer_release(viafbinfo); | ||
2270 | return -ENOMEM; | ||
2271 | } | ||
2272 | viaparinfo1 = viafbinfo1->par; | ||
2273 | memcpy(viaparinfo1, viaparinfo, viafb_par_length); | ||
2274 | viaparinfo1->memsize = viaparinfo->memsize - | ||
2275 | viafb_second_offset; | ||
2276 | viaparinfo->memsize = viafb_second_offset; | ||
2277 | viaparinfo1->fbmem_virt = viaparinfo->fbmem_virt + | ||
2278 | viafb_second_offset; | ||
2279 | viaparinfo1->fbmem = viaparinfo->fbmem + viafb_second_offset; | ||
2280 | |||
2281 | viaparinfo1->fbmem_used = viaparinfo->fbmem_used; | ||
2282 | viaparinfo1->fbmem_free = viaparinfo1->memsize - | ||
2283 | viaparinfo1->fbmem_used; | ||
2284 | viaparinfo->fbmem_free = viaparinfo->memsize; | ||
2285 | viaparinfo->fbmem_used = 0; | ||
2286 | if (viafb_accel) { | ||
2287 | viaparinfo1->cursor_start = | ||
2288 | viaparinfo->cursor_start - viafb_second_offset; | ||
2289 | viaparinfo1->VQ_start = viaparinfo->VQ_start - | ||
2290 | viafb_second_offset; | ||
2291 | viaparinfo1->VQ_end = viaparinfo->VQ_end - | ||
2292 | viafb_second_offset; | ||
2293 | } | ||
2294 | |||
2295 | memcpy(viafbinfo1, viafbinfo, sizeof(struct fb_info)); | ||
2296 | viafbinfo1->screen_base = viafbinfo->screen_base + | ||
2297 | viafb_second_offset; | ||
2298 | viafbinfo1->fix.smem_start = viaparinfo1->fbmem; | ||
2299 | viafbinfo1->fix.smem_len = viaparinfo1->fbmem_free; | ||
2300 | |||
2301 | default_var.xres = viafb_second_xres; | ||
2302 | default_var.yres = viafb_second_yres; | ||
2303 | default_var.xres_virtual = viafb_second_virtual_xres; | ||
2304 | default_var.yres_virtual = viafb_second_virtual_yres; | ||
2305 | if (viafb_bpp1 != viafb_bpp) | ||
2306 | viafb_bpp1 = viafb_bpp; | ||
2307 | default_var.bits_per_pixel = viafb_bpp1; | ||
2308 | default_var.pixclock = | ||
2309 | viafb_get_pixclock(viafb_second_xres, viafb_second_yres, | ||
2310 | viafb_refresh); | ||
2311 | default_var.left_margin = (viafb_second_xres >> 3) & 0xf8; | ||
2312 | default_var.right_margin = 32; | ||
2313 | default_var.upper_margin = 16; | ||
2314 | default_var.lower_margin = 4; | ||
2315 | default_var.hsync_len = default_var.left_margin; | ||
2316 | default_var.vsync_len = 4; | ||
2317 | |||
2318 | viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1); | ||
2319 | viafb_check_var(&default_var, viafbinfo1); | ||
2320 | viafbinfo1->var = default_var; | ||
2321 | viafb_update_viafb_par(viafbinfo); | ||
2322 | viafb_update_fix(&viafbinfo1->fix, viafbinfo1); | ||
2323 | } | ||
2324 | |||
2325 | viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo); | ||
2326 | viafb_check_var(&default_var, viafbinfo); | ||
2327 | viafbinfo->var = default_var; | ||
2328 | viafb_update_viafb_par(viafbinfo); | ||
2329 | viafb_update_fix(&viafbinfo->fix, viafbinfo); | ||
2330 | default_var.activate = FB_ACTIVATE_NOW; | ||
2331 | fb_alloc_cmap(&viafbinfo->cmap, 256, 0); | ||
2332 | |||
2333 | if (viafb_dual_fb && (viafb_primary_dev == LCD_Device) | ||
2334 | && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)) { | ||
2335 | if (register_framebuffer(viafbinfo1) < 0) | ||
2336 | return -EINVAL; | ||
2337 | } | ||
2338 | if (register_framebuffer(viafbinfo) < 0) | ||
2339 | return -EINVAL; | ||
2340 | |||
2341 | if (viafb_dual_fb && ((viafb_primary_dev != LCD_Device) | ||
2342 | || (viaparinfo->chip_info->gfx_chip_name != | ||
2343 | UNICHROME_CLE266))) { | ||
2344 | if (register_framebuffer(viafbinfo1) < 0) | ||
2345 | return -EINVAL; | ||
2346 | } | ||
2347 | DEBUG_MSG(KERN_INFO "fb%d: %s frame buffer device %dx%d-%dbpp\n", | ||
2348 | viafbinfo->node, viafbinfo->fix.id, default_var.xres, | ||
2349 | default_var.yres, default_var.bits_per_pixel); | ||
2350 | |||
2351 | viafb_init_proc(viaparinfo->proc_entry); | ||
2352 | viafb_init_dac(IGA2); | ||
2353 | return 0; | ||
2354 | } | ||
2355 | |||
2356 | static void __devexit via_pci_remove(void) | ||
2357 | { | ||
2358 | DEBUG_MSG(KERN_INFO "via_pci_remove!\n"); | ||
2359 | fb_dealloc_cmap(&viafbinfo->cmap); | ||
2360 | unregister_framebuffer(viafbinfo); | ||
2361 | if (viafb_dual_fb) | ||
2362 | unregister_framebuffer(viafbinfo1); | ||
2363 | iounmap((void *)viaparinfo->fbmem_virt); | ||
2364 | iounmap(viaparinfo->io_virt); | ||
2365 | |||
2366 | viafb_delete_i2c_buss(viaparinfo); | ||
2367 | |||
2368 | framebuffer_release(viafbinfo); | ||
2369 | if (viafb_dual_fb) | ||
2370 | framebuffer_release(viafbinfo1); | ||
2371 | |||
2372 | viafb_remove_proc(viaparinfo->proc_entry); | ||
2373 | } | ||
2374 | |||
2375 | #ifndef MODULE | ||
2376 | static int __init viafb_setup(char *options) | ||
2377 | { | ||
2378 | char *this_opt; | ||
2379 | DEBUG_MSG(KERN_INFO "viafb_setup!\n"); | ||
2380 | |||
2381 | if (!options || !*options) | ||
2382 | return 0; | ||
2383 | |||
2384 | while ((this_opt = strsep(&options, ",")) != NULL) { | ||
2385 | if (!*this_opt) | ||
2386 | continue; | ||
2387 | |||
2388 | if (!strncmp(this_opt, "viafb_mode1=", 12)) | ||
2389 | viafb_mode1 = kstrdup(this_opt + 12, GFP_KERNEL); | ||
2390 | else if (!strncmp(this_opt, "viafb_mode=", 11)) | ||
2391 | viafb_mode = kstrdup(this_opt + 11, GFP_KERNEL); | ||
2392 | else if (!strncmp(this_opt, "viafb_bpp1=", 11)) | ||
2393 | strict_strtoul(this_opt + 11, 0, | ||
2394 | (unsigned long *)&viafb_bpp1); | ||
2395 | else if (!strncmp(this_opt, "viafb_bpp=", 10)) | ||
2396 | strict_strtoul(this_opt + 10, 0, | ||
2397 | (unsigned long *)&viafb_bpp); | ||
2398 | else if (!strncmp(this_opt, "viafb_refresh1=", 15)) | ||
2399 | strict_strtoul(this_opt + 15, 0, | ||
2400 | (unsigned long *)&viafb_refresh1); | ||
2401 | else if (!strncmp(this_opt, "viafb_refresh=", 14)) | ||
2402 | strict_strtoul(this_opt + 14, 0, | ||
2403 | (unsigned long *)&viafb_refresh); | ||
2404 | else if (!strncmp(this_opt, "viafb_lcd_dsp_method=", 21)) | ||
2405 | strict_strtoul(this_opt + 21, 0, | ||
2406 | (unsigned long *)&viafb_lcd_dsp_method); | ||
2407 | else if (!strncmp(this_opt, "viafb_lcd_panel_id=", 19)) | ||
2408 | strict_strtoul(this_opt + 19, 0, | ||
2409 | (unsigned long *)&viafb_lcd_panel_id); | ||
2410 | else if (!strncmp(this_opt, "viafb_accel=", 12)) | ||
2411 | strict_strtoul(this_opt + 12, 0, | ||
2412 | (unsigned long *)&viafb_accel); | ||
2413 | else if (!strncmp(this_opt, "viafb_SAMM_ON=", 14)) | ||
2414 | strict_strtoul(this_opt + 14, 0, | ||
2415 | (unsigned long *)&viafb_SAMM_ON); | ||
2416 | else if (!strncmp(this_opt, "viafb_active_dev=", 17)) | ||
2417 | viafb_active_dev = kstrdup(this_opt + 17, GFP_KERNEL); | ||
2418 | else if (!strncmp(this_opt, | ||
2419 | "viafb_display_hardware_layout=", 30)) | ||
2420 | strict_strtoul(this_opt + 30, 0, | ||
2421 | (unsigned long *)&viafb_display_hardware_layout); | ||
2422 | else if (!strncmp(this_opt, "viafb_second_size=", 18)) | ||
2423 | strict_strtoul(this_opt + 18, 0, | ||
2424 | (unsigned long *)&viafb_second_size); | ||
2425 | else if (!strncmp(this_opt, | ||
2426 | "viafb_platform_epia_dvi=", 24)) | ||
2427 | strict_strtoul(this_opt + 24, 0, | ||
2428 | (unsigned long *)&viafb_platform_epia_dvi); | ||
2429 | else if (!strncmp(this_opt, | ||
2430 | "viafb_device_lcd_dualedge=", 26)) | ||
2431 | strict_strtoul(this_opt + 26, 0, | ||
2432 | (unsigned long *)&viafb_device_lcd_dualedge); | ||
2433 | else if (!strncmp(this_opt, "viafb_bus_width=", 16)) | ||
2434 | strict_strtoul(this_opt + 16, 0, | ||
2435 | (unsigned long *)&viafb_bus_width); | ||
2436 | else if (!strncmp(this_opt, "viafb_lcd_mode=", 15)) | ||
2437 | strict_strtoul(this_opt + 15, 0, | ||
2438 | (unsigned long *)&viafb_lcd_mode); | ||
2439 | else if (!strncmp(this_opt, "viafb_video_dev=", 16)) | ||
2440 | viafb_video_dev = kstrdup(this_opt + 16, GFP_KERNEL); | ||
2441 | else if (!strncmp(this_opt, "viafb_lcd_port=", 15)) | ||
2442 | viafb_lcd_port = kstrdup(this_opt + 15, GFP_KERNEL); | ||
2443 | else if (!strncmp(this_opt, "viafb_dvi_port=", 15)) | ||
2444 | viafb_dvi_port = kstrdup(this_opt + 15, GFP_KERNEL); | ||
2445 | } | ||
2446 | return 0; | ||
2447 | } | ||
2448 | #endif | ||
2449 | |||
2450 | static int __init viafb_init(void) | ||
2451 | { | ||
2452 | #ifndef MODULE | ||
2453 | char *option = NULL; | ||
2454 | if (fb_get_options("viafb", &option)) | ||
2455 | return -ENODEV; | ||
2456 | viafb_setup(option); | ||
2457 | #endif | ||
2458 | printk(KERN_INFO | ||
2459 | "VIA Graphics Intergration Chipset framebuffer %d.%d initializing\n", | ||
2460 | VERSION_MAJOR, VERSION_MINOR); | ||
2461 | return via_pci_probe(); | ||
2462 | } | ||
2463 | |||
2464 | static void __exit viafb_exit(void) | ||
2465 | { | ||
2466 | DEBUG_MSG(KERN_INFO "viafb_exit!\n"); | ||
2467 | via_pci_remove(); | ||
2468 | } | ||
2469 | |||
2470 | static struct fb_ops viafb_ops = { | ||
2471 | .owner = THIS_MODULE, | ||
2472 | .fb_open = viafb_open, | ||
2473 | .fb_release = viafb_release, | ||
2474 | .fb_check_var = viafb_check_var, | ||
2475 | .fb_set_par = viafb_set_par, | ||
2476 | .fb_setcolreg = viafb_setcolreg, | ||
2477 | .fb_pan_display = viafb_pan_display, | ||
2478 | .fb_blank = viafb_blank, | ||
2479 | .fb_fillrect = viafb_fillrect, | ||
2480 | .fb_copyarea = viafb_copyarea, | ||
2481 | .fb_imageblit = viafb_imageblit, | ||
2482 | .fb_cursor = viafb_cursor, | ||
2483 | .fb_ioctl = viafb_ioctl, | ||
2484 | .fb_sync = viafb_sync, | ||
2485 | .fb_setcmap = viafb_setcmap, | ||
2486 | }; | ||
2487 | |||
2488 | module_init(viafb_init); | ||
2489 | module_exit(viafb_exit); | ||
2490 | |||
2491 | #ifdef MODULE | ||
2492 | module_param(viafb_memsize, int, 0); | ||
2493 | |||
2494 | module_param(viafb_mode, charp, 0); | ||
2495 | MODULE_PARM_DESC(viafb_mode, "Set resolution (default=640x480)"); | ||
2496 | |||
2497 | module_param(viafb_mode1, charp, 0); | ||
2498 | MODULE_PARM_DESC(viafb_mode1, "Set resolution (default=640x480)"); | ||
2499 | |||
2500 | module_param(viafb_bpp, int, 0); | ||
2501 | MODULE_PARM_DESC(viafb_bpp, "Set color depth (default=32bpp)"); | ||
2502 | |||
2503 | module_param(viafb_bpp1, int, 0); | ||
2504 | MODULE_PARM_DESC(viafb_bpp1, "Set color depth (default=32bpp)"); | ||
2505 | |||
2506 | module_param(viafb_refresh, int, 0); | ||
2507 | MODULE_PARM_DESC(viafb_refresh, | ||
2508 | "Set CRT viafb_refresh rate (default = 60)"); | ||
2509 | |||
2510 | module_param(viafb_refresh1, int, 0); | ||
2511 | MODULE_PARM_DESC(viafb_refresh1, | ||
2512 | "Set CRT refresh rate (default = 60)"); | ||
2513 | |||
2514 | module_param(viafb_lcd_panel_id, int, 0); | ||
2515 | MODULE_PARM_DESC(viafb_lcd_panel_id, | ||
2516 | "Set Flat Panel type(Default=1024x768)"); | ||
2517 | |||
2518 | module_param(viafb_lcd_dsp_method, int, 0); | ||
2519 | MODULE_PARM_DESC(viafb_lcd_dsp_method, | ||
2520 | "Set Flat Panel display scaling method.(Default=Expandsion)"); | ||
2521 | |||
2522 | module_param(viafb_SAMM_ON, int, 0); | ||
2523 | MODULE_PARM_DESC(viafb_SAMM_ON, | ||
2524 | "Turn on/off flag of SAMM(Default=OFF)"); | ||
2525 | |||
2526 | module_param(viafb_accel, int, 0); | ||
2527 | MODULE_PARM_DESC(viafb_accel, | ||
2528 | "Set 2D Hardware Acceleration.(Default = OFF)"); | ||
2529 | |||
2530 | module_param(viafb_active_dev, charp, 0); | ||
2531 | MODULE_PARM_DESC(viafb_active_dev, "Specify active devices."); | ||
2532 | |||
2533 | module_param(viafb_display_hardware_layout, int, 0); | ||
2534 | MODULE_PARM_DESC(viafb_display_hardware_layout, | ||
2535 | "Display Hardware Layout (LCD Only, DVI Only...,etc)"); | ||
2536 | |||
2537 | module_param(viafb_second_size, int, 0); | ||
2538 | MODULE_PARM_DESC(viafb_second_size, | ||
2539 | "Set secondary device memory size"); | ||
2540 | |||
2541 | module_param(viafb_dual_fb, int, 0); | ||
2542 | MODULE_PARM_DESC(viafb_dual_fb, | ||
2543 | "Turn on/off flag of dual framebuffer devices.(Default = OFF)"); | ||
2544 | |||
2545 | module_param(viafb_platform_epia_dvi, int, 0); | ||
2546 | MODULE_PARM_DESC(viafb_platform_epia_dvi, | ||
2547 | "Turn on/off flag of DVI devices on EPIA board.(Default = OFF)"); | ||
2548 | |||
2549 | module_param(viafb_device_lcd_dualedge, int, 0); | ||
2550 | MODULE_PARM_DESC(viafb_device_lcd_dualedge, | ||
2551 | "Turn on/off flag of dual edge panel.(Default = OFF)"); | ||
2552 | |||
2553 | module_param(viafb_bus_width, int, 0); | ||
2554 | MODULE_PARM_DESC(viafb_bus_width, | ||
2555 | "Set bus width of panel.(Default = 12)"); | ||
2556 | |||
2557 | module_param(viafb_lcd_mode, int, 0); | ||
2558 | MODULE_PARM_DESC(viafb_lcd_mode, | ||
2559 | "Set Flat Panel mode(Default=OPENLDI)"); | ||
2560 | |||
2561 | module_param(viafb_video_dev, charp, 0); | ||
2562 | MODULE_PARM_DESC(viafb_video_dev, "Specify video devices."); | ||
2563 | |||
2564 | module_param(viafb_lcd_port, charp, 0); | ||
2565 | MODULE_PARM_DESC(viafb_lcd_port, "Specify LCD output port."); | ||
2566 | |||
2567 | module_param(viafb_dvi_port, charp, 0); | ||
2568 | MODULE_PARM_DESC(viafb_dvi_port, "Specify DVI output port."); | ||
2569 | |||
2570 | MODULE_LICENSE("GPL"); | ||
2571 | #endif | ||
diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h new file mode 100644 index 000000000000..a4158e872878 --- /dev/null +++ b/drivers/video/via/viafbdev.h | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef __VIAFBDEV_H__ | ||
23 | #define __VIAFBDEV_H__ | ||
24 | |||
25 | #include <linux/proc_fs.h> | ||
26 | #include <linux/fb.h> | ||
27 | |||
28 | #include "ioctl.h" | ||
29 | #include "share.h" | ||
30 | #include "chip.h" | ||
31 | #include "hw.h" | ||
32 | #include "via_i2c.h" | ||
33 | |||
34 | #define VERSION_MAJOR 2 | ||
35 | #define VERSION_KERNEL 6 /* For kernel 2.6 */ | ||
36 | |||
37 | #define VERSION_OS 0 /* 0: for 32 bits OS, 1: for 64 bits OS */ | ||
38 | #define VERSION_MINOR 4 | ||
39 | |||
40 | struct viafb_par { | ||
41 | int bpp; | ||
42 | int hres; | ||
43 | int vres; | ||
44 | int linelength; | ||
45 | u32 xoffset; | ||
46 | u32 yoffset; | ||
47 | |||
48 | void __iomem *fbmem_virt; /*framebuffer virtual memory address */ | ||
49 | void __iomem *io_virt; /*iospace virtual memory address */ | ||
50 | unsigned int fbmem; /*framebuffer physical memory address */ | ||
51 | unsigned int memsize; /*size of fbmem */ | ||
52 | unsigned int io; /*io space address */ | ||
53 | unsigned long mmio_base; /*mmio base address */ | ||
54 | unsigned long mmio_len; /*mmio base length */ | ||
55 | u32 fbmem_free; /* Free FB memory */ | ||
56 | u32 fbmem_used; /* Use FB memory size */ | ||
57 | u32 cursor_start; /* Cursor Start Address */ | ||
58 | u32 VQ_start; /* Virtual Queue Start Address */ | ||
59 | u32 VQ_end; /* Virtual Queue End Address */ | ||
60 | u32 iga_path; | ||
61 | struct proc_dir_entry *proc_entry; /*viafb proc entry */ | ||
62 | u8 duoview; /*Is working in duoview mode? */ | ||
63 | |||
64 | /* I2C stuff */ | ||
65 | struct via_i2c_stuff i2c_stuff; | ||
66 | |||
67 | /* All the information will be needed to set engine */ | ||
68 | struct tmds_setting_information *tmds_setting_info; | ||
69 | struct crt_setting_information *crt_setting_info; | ||
70 | struct lvds_setting_information *lvds_setting_info; | ||
71 | struct lvds_setting_information *lvds_setting_info2; | ||
72 | struct chip_information *chip_info; | ||
73 | |||
74 | /* some information related to video playing */ | ||
75 | int video_on_crt; | ||
76 | int video_on_dvi; | ||
77 | int video_on_lcd; | ||
78 | |||
79 | }; | ||
80 | struct viafb_modeinfo { | ||
81 | u32 xres; | ||
82 | u32 yres; | ||
83 | int mode_index; | ||
84 | char *mode_res; | ||
85 | }; | ||
86 | extern unsigned int viafb_second_virtual_yres; | ||
87 | extern unsigned int viafb_second_virtual_xres; | ||
88 | extern unsigned int viafb_second_offset; | ||
89 | extern int viafb_second_size; | ||
90 | extern int viafb_SAMM_ON; | ||
91 | extern int viafb_dual_fb; | ||
92 | extern int viafb_LCD2_ON; | ||
93 | extern int viafb_LCD_ON; | ||
94 | extern int viafb_DVI_ON; | ||
95 | extern int viafb_accel; | ||
96 | extern int viafb_hotplug; | ||
97 | extern int viafb_memsize; | ||
98 | |||
99 | extern int strict_strtoul(const char *cp, unsigned int base, | ||
100 | unsigned long *res); | ||
101 | |||
102 | void viafb_memory_pitch_patch(struct fb_info *info); | ||
103 | void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, | ||
104 | int mode_index); | ||
105 | int viafb_get_mode_index(int hres, int vres, int flag); | ||
106 | u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information | ||
107 | *plvds_setting_info, struct lvds_chip_information | ||
108 | *plvds_chip_info, u8 index); | ||
109 | void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information | ||
110 | *plvds_setting_info, struct lvds_chip_information | ||
111 | *plvds_chip_info, struct IODATA io_data); | ||
112 | #endif /* __VIAFBDEV_H__ */ | ||
diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c new file mode 100644 index 000000000000..6dcf583a837d --- /dev/null +++ b/drivers/video/via/viamode.c | |||
@@ -0,0 +1,1086 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #include "global.h" | ||
23 | struct res_map_refresh res_map_refresh_tbl[] = { | ||
24 | /*hres, vres, vclock, vmode_refresh*/ | ||
25 | {480, 640, RES_480X640_60HZ_PIXCLOCK, 60}, | ||
26 | {640, 480, RES_640X480_60HZ_PIXCLOCK, 60}, | ||
27 | {640, 480, RES_640X480_75HZ_PIXCLOCK, 75}, | ||
28 | {640, 480, RES_640X480_85HZ_PIXCLOCK, 85}, | ||
29 | {640, 480, RES_640X480_100HZ_PIXCLOCK, 100}, | ||
30 | {640, 480, RES_640X480_120HZ_PIXCLOCK, 120}, | ||
31 | {720, 480, RES_720X480_60HZ_PIXCLOCK, 60}, | ||
32 | {720, 576, RES_720X576_60HZ_PIXCLOCK, 60}, | ||
33 | {800, 480, RES_800X480_60HZ_PIXCLOCK, 60}, | ||
34 | {800, 600, RES_800X600_60HZ_PIXCLOCK, 60}, | ||
35 | {800, 600, RES_800X600_75HZ_PIXCLOCK, 75}, | ||
36 | {800, 600, RES_800X600_85HZ_PIXCLOCK, 85}, | ||
37 | {800, 600, RES_800X600_100HZ_PIXCLOCK, 100}, | ||
38 | {800, 600, RES_800X600_120HZ_PIXCLOCK, 120}, | ||
39 | {848, 480, RES_848X480_60HZ_PIXCLOCK, 60}, | ||
40 | {856, 480, RES_856X480_60HZ_PIXCLOCK, 60}, | ||
41 | {1024, 512, RES_1024X512_60HZ_PIXCLOCK, 60}, | ||
42 | {1024, 600, RES_1024X600_60HZ_PIXCLOCK, 60}, | ||
43 | {1024, 768, RES_1024X768_60HZ_PIXCLOCK, 60}, | ||
44 | {1024, 768, RES_1024X768_75HZ_PIXCLOCK, 75}, | ||
45 | {1024, 768, RES_1024X768_85HZ_PIXCLOCK, 85}, | ||
46 | {1024, 768, RES_1024X768_100HZ_PIXCLOCK, 100}, | ||
47 | /* {1152,864, RES_1152X864_70HZ_PIXCLOCK, 70},*/ | ||
48 | {1152, 864, RES_1152X864_75HZ_PIXCLOCK, 75}, | ||
49 | {1280, 768, RES_1280X768_60HZ_PIXCLOCK, 60}, | ||
50 | {1280, 800, RES_1280X800_60HZ_PIXCLOCK, 60}, | ||
51 | {1280, 960, RES_1280X960_60HZ_PIXCLOCK, 60}, | ||
52 | {1280, 1024, RES_1280X1024_60HZ_PIXCLOCK, 60}, | ||
53 | {1280, 1024, RES_1280X1024_75HZ_PIXCLOCK, 75}, | ||
54 | {1280, 1024, RES_1280X768_85HZ_PIXCLOCK, 85}, | ||
55 | {1440, 1050, RES_1440X1050_60HZ_PIXCLOCK, 60}, | ||
56 | {1600, 1200, RES_1600X1200_60HZ_PIXCLOCK, 60}, | ||
57 | {1600, 1200, RES_1600X1200_75HZ_PIXCLOCK, 75}, | ||
58 | {1280, 720, RES_1280X720_60HZ_PIXCLOCK, 60}, | ||
59 | {1920, 1080, RES_1920X1080_60HZ_PIXCLOCK, 60}, | ||
60 | {1400, 1050, RES_1400X1050_60HZ_PIXCLOCK, 60}, | ||
61 | {1400, 1050, RES_1400X1050_75HZ_PIXCLOCK, 75}, | ||
62 | {1368, 768, RES_1368X768_60HZ_PIXCLOCK, 60}, | ||
63 | {960, 600, RES_960X600_60HZ_PIXCLOCK, 60}, | ||
64 | {1000, 600, RES_1000X600_60HZ_PIXCLOCK, 60}, | ||
65 | {1024, 576, RES_1024X576_60HZ_PIXCLOCK, 60}, | ||
66 | {1088, 612, RES_1088X612_60HZ_PIXCLOCK, 60}, | ||
67 | {1152, 720, RES_1152X720_60HZ_PIXCLOCK, 60}, | ||
68 | {1200, 720, RES_1200X720_60HZ_PIXCLOCK, 60}, | ||
69 | {1280, 600, RES_1280X600_60HZ_PIXCLOCK, 60}, | ||
70 | {1280, 720, RES_1280X720_50HZ_PIXCLOCK, 50}, | ||
71 | {1280, 768, RES_1280X768_50HZ_PIXCLOCK, 50}, | ||
72 | {1360, 768, RES_1360X768_60HZ_PIXCLOCK, 60}, | ||
73 | {1366, 768, RES_1366X768_50HZ_PIXCLOCK, 50}, | ||
74 | {1366, 768, RES_1366X768_60HZ_PIXCLOCK, 60}, | ||
75 | {1440, 900, RES_1440X900_60HZ_PIXCLOCK, 60}, | ||
76 | {1440, 900, RES_1440X900_75HZ_PIXCLOCK, 75}, | ||
77 | {1600, 900, RES_1600X900_60HZ_PIXCLOCK, 60}, | ||
78 | {1600, 1024, RES_1600X1024_60HZ_PIXCLOCK, 60}, | ||
79 | {1680, 1050, RES_1680X1050_60HZ_PIXCLOCK, 60}, | ||
80 | {1680, 1050, RES_1680X1050_75HZ_PIXCLOCK, 75}, | ||
81 | {1792, 1344, RES_1792X1344_60HZ_PIXCLOCK, 60}, | ||
82 | {1856, 1392, RES_1856X1392_60HZ_PIXCLOCK, 60}, | ||
83 | {1920, 1200, RES_1920X1200_60HZ_PIXCLOCK, 60}, | ||
84 | {1920, 1440, RES_1920X1440_60HZ_PIXCLOCK, 60}, | ||
85 | {1920, 1440, RES_1920X1440_75HZ_PIXCLOCK, 75}, | ||
86 | {2048, 1536, RES_2048X1536_60HZ_PIXCLOCK, 60} | ||
87 | }; | ||
88 | |||
89 | struct io_reg CN400_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01}, | ||
90 | {VIASR, SR15, 0x02, 0x02}, | ||
91 | {VIASR, SR16, 0xBF, 0x08}, | ||
92 | {VIASR, SR17, 0xFF, 0x1F}, | ||
93 | {VIASR, SR18, 0xFF, 0x4E}, | ||
94 | {VIASR, SR1A, 0xFB, 0x08}, | ||
95 | {VIASR, SR1E, 0x0F, 0x01}, | ||
96 | {VIASR, SR2A, 0xFF, 0x00}, | ||
97 | {VIACR, CR0A, 0xFF, 0x1E}, /* Cursor Start */ | ||
98 | {VIACR, CR0B, 0xFF, 0x00}, /* Cursor End */ | ||
99 | {VIACR, CR0E, 0xFF, 0x00}, /* Cursor Location High */ | ||
100 | {VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */ | ||
101 | {VIACR, CR32, 0xFF, 0x00}, | ||
102 | {VIACR, CR33, 0xFF, 0x00}, | ||
103 | {VIACR, CR34, 0xFF, 0x00}, | ||
104 | {VIACR, CR35, 0xFF, 0x00}, | ||
105 | {VIACR, CR36, 0x08, 0x00}, | ||
106 | {VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */ | ||
107 | {VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */ | ||
108 | {VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */ | ||
109 | {VIACR, CR69, 0xFF, 0x00}, | ||
110 | {VIACR, CR6A, 0xFF, 0x40}, | ||
111 | {VIACR, CR6B, 0xFF, 0x00}, | ||
112 | {VIACR, CR6C, 0xFF, 0x00}, | ||
113 | {VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */ | ||
114 | {VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */ | ||
115 | {VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */ | ||
116 | {VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */ | ||
117 | {VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */ | ||
118 | {VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */ | ||
119 | {VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */ | ||
120 | {VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */ | ||
121 | {VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */ | ||
122 | {VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */ | ||
123 | {VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */ | ||
124 | {VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */ | ||
125 | {VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */ | ||
126 | {VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */ | ||
127 | {VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */ | ||
128 | {VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */ | ||
129 | {VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */ | ||
130 | {VIACR, CR8B, 0xFF, 0x69}, /* LCD Power Sequence Control 0 */ | ||
131 | {VIACR, CR8C, 0xFF, 0x57}, /* LCD Power Sequence Control 1 */ | ||
132 | {VIACR, CR8D, 0xFF, 0x00}, /* LCD Power Sequence Control 2 */ | ||
133 | {VIACR, CR8E, 0xFF, 0x7B}, /* LCD Power Sequence Control 3 */ | ||
134 | {VIACR, CR8F, 0xFF, 0x03}, /* LCD Power Sequence Control 4 */ | ||
135 | {VIACR, CR90, 0xFF, 0x30}, /* LCD Power Sequence Control 5 */ | ||
136 | {VIACR, CR91, 0xFF, 0xA0}, /* 24/12 bit LVDS Data off */ | ||
137 | {VIACR, CR96, 0xFF, 0x00}, | ||
138 | {VIACR, CR97, 0xFF, 0x00}, | ||
139 | {VIACR, CR99, 0xFF, 0x00}, | ||
140 | {VIACR, CR9B, 0xFF, 0x00} | ||
141 | }; | ||
142 | |||
143 | /* Video Mode Table for VT3314 chipset*/ | ||
144 | /* Common Setting for Video Mode */ | ||
145 | struct io_reg CN700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01}, | ||
146 | {VIASR, SR15, 0x02, 0x02}, | ||
147 | {VIASR, SR16, 0xBF, 0x08}, | ||
148 | {VIASR, SR17, 0xFF, 0x1F}, | ||
149 | {VIASR, SR18, 0xFF, 0x4E}, | ||
150 | {VIASR, SR1A, 0xFB, 0x82}, | ||
151 | {VIASR, SR1B, 0xFF, 0xF0}, | ||
152 | {VIASR, SR1F, 0xFF, 0x00}, | ||
153 | {VIASR, SR1E, 0xFF, 0x01}, | ||
154 | {VIASR, SR22, 0xFF, 0x1F}, | ||
155 | {VIASR, SR2A, 0x0F, 0x00}, | ||
156 | {VIASR, SR2E, 0xFF, 0xFF}, | ||
157 | {VIASR, SR3F, 0xFF, 0xFF}, | ||
158 | {VIASR, SR40, 0xF7, 0x00}, | ||
159 | {VIASR, CR30, 0xFF, 0x04}, | ||
160 | {VIACR, CR32, 0xFF, 0x00}, | ||
161 | {VIACR, CR33, 0x7F, 0x00}, | ||
162 | {VIACR, CR34, 0xFF, 0x00}, | ||
163 | {VIACR, CR35, 0xFF, 0x00}, | ||
164 | {VIACR, CR36, 0xFF, 0x31}, | ||
165 | {VIACR, CR41, 0xFF, 0x80}, | ||
166 | {VIACR, CR42, 0xFF, 0x00}, | ||
167 | {VIACR, CR55, 0x80, 0x00}, | ||
168 | {VIACR, CR5D, 0x80, 0x00}, /*Horizontal Retrace Start bit[11] should be 0*/ | ||
169 | {VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */ | ||
170 | {VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */ | ||
171 | {VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */ | ||
172 | {VIACR, CR68, 0xFF, 0x67}, /* Default FIFO For IGA2 */ | ||
173 | {VIACR, CR69, 0xFF, 0x00}, | ||
174 | {VIACR, CR6A, 0xFD, 0x40}, | ||
175 | {VIACR, CR6B, 0xFF, 0x00}, | ||
176 | {VIACR, CR6C, 0xFF, 0x00}, | ||
177 | {VIACR, CR77, 0xFF, 0x00}, /* LCD scaling Factor */ | ||
178 | {VIACR, CR78, 0xFF, 0x00}, /* LCD scaling Factor */ | ||
179 | {VIACR, CR79, 0xFF, 0x00}, /* LCD scaling Factor */ | ||
180 | {VIACR, CR9F, 0x03, 0x00}, /* LCD scaling Factor */ | ||
181 | {VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */ | ||
182 | {VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */ | ||
183 | {VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */ | ||
184 | {VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */ | ||
185 | {VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */ | ||
186 | {VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */ | ||
187 | {VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */ | ||
188 | {VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */ | ||
189 | {VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */ | ||
190 | {VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */ | ||
191 | {VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */ | ||
192 | {VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */ | ||
193 | {VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */ | ||
194 | {VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */ | ||
195 | {VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */ | ||
196 | {VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */ | ||
197 | {VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */ | ||
198 | {VIACR, CR8B, 0xFF, 0x5D}, /* LCD Power Sequence Control 0 */ | ||
199 | {VIACR, CR8C, 0xFF, 0x2B}, /* LCD Power Sequence Control 1 */ | ||
200 | {VIACR, CR8D, 0xFF, 0x6F}, /* LCD Power Sequence Control 2 */ | ||
201 | {VIACR, CR8E, 0xFF, 0x2B}, /* LCD Power Sequence Control 3 */ | ||
202 | {VIACR, CR8F, 0xFF, 0x01}, /* LCD Power Sequence Control 4 */ | ||
203 | {VIACR, CR90, 0xFF, 0x01}, /* LCD Power Sequence Control 5 */ | ||
204 | {VIACR, CR91, 0xFF, 0xA0}, /* 24/12 bit LVDS Data off */ | ||
205 | {VIACR, CR96, 0xFF, 0x00}, | ||
206 | {VIACR, CR97, 0xFF, 0x00}, | ||
207 | {VIACR, CR99, 0xFF, 0x00}, | ||
208 | {VIACR, CR9B, 0xFF, 0x00}, | ||
209 | {VIACR, CR9D, 0xFF, 0x80}, | ||
210 | {VIACR, CR9E, 0xFF, 0x80} | ||
211 | }; | ||
212 | |||
213 | struct io_reg KM400_ModeXregs[] = { | ||
214 | {VIASR, SR10, 0xFF, 0x01}, /* Unlock Register */ | ||
215 | {VIASR, SR16, 0xFF, 0x08}, /* Display FIFO threshold Control */ | ||
216 | {VIASR, SR17, 0xFF, 0x1F}, /* Display FIFO Control */ | ||
217 | {VIASR, SR18, 0xFF, 0x4E}, /* GFX PREQ threshold */ | ||
218 | {VIASR, SR1A, 0xFF, 0x0a}, /* GFX PREQ threshold */ | ||
219 | {VIASR, SR1F, 0xFF, 0x00}, /* Memory Control 0 */ | ||
220 | {VIASR, SR1B, 0xFF, 0xF0}, /* Power Management Control 0 */ | ||
221 | {VIASR, SR1E, 0xFF, 0x01}, /* Power Management Control */ | ||
222 | {VIASR, SR20, 0xFF, 0x00}, /* Sequencer Arbiter Control 0 */ | ||
223 | {VIASR, SR21, 0xFF, 0x00}, /* Sequencer Arbiter Control 1 */ | ||
224 | {VIASR, SR22, 0xFF, 0x1F}, /* Display Arbiter Control 1 */ | ||
225 | {VIASR, SR2A, 0xFF, 0x00}, /* Power Management Control 5 */ | ||
226 | {VIASR, SR2D, 0xFF, 0xFF}, /* Power Management Control 1 */ | ||
227 | {VIASR, SR2E, 0xFF, 0xFF}, /* Power Management Control 2 */ | ||
228 | {VIACR, CR0A, 0xFF, 0x1E}, /* Cursor Start */ | ||
229 | {VIACR, CR0B, 0xFF, 0x00}, /* Cursor End */ | ||
230 | {VIACR, CR0E, 0xFF, 0x00}, /* Cursor Location High */ | ||
231 | {VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */ | ||
232 | {VIACR, CR33, 0xFF, 0x00}, | ||
233 | {VIACR, CR55, 0x80, 0x00}, | ||
234 | {VIACR, CR5D, 0x80, 0x00}, | ||
235 | {VIACR, CR36, 0xFF, 0x01}, /* Power Mangement 3 */ | ||
236 | {VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */ | ||
237 | {VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */ | ||
238 | {VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */ | ||
239 | {VIACR, CR68, 0xFF, 0x67}, /* Default FIFO For IGA2 */ | ||
240 | {VIACR, CR6A, 0x20, 0x20}, /* Extended FIFO On */ | ||
241 | {VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */ | ||
242 | {VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */ | ||
243 | {VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */ | ||
244 | {VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */ | ||
245 | {VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */ | ||
246 | {VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */ | ||
247 | {VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */ | ||
248 | {VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */ | ||
249 | {VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */ | ||
250 | {VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */ | ||
251 | {VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */ | ||
252 | {VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */ | ||
253 | {VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */ | ||
254 | {VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */ | ||
255 | {VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */ | ||
256 | {VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */ | ||
257 | {VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */ | ||
258 | {VIACR, CR8B, 0xFF, 0x2D}, /* LCD Power Sequence Control 0 */ | ||
259 | {VIACR, CR8C, 0xFF, 0x2D}, /* LCD Power Sequence Control 1 */ | ||
260 | {VIACR, CR8D, 0xFF, 0xC8}, /* LCD Power Sequence Control 2 */ | ||
261 | {VIACR, CR8E, 0xFF, 0x36}, /* LCD Power Sequence Control 3 */ | ||
262 | {VIACR, CR8F, 0xFF, 0x00}, /* LCD Power Sequence Control 4 */ | ||
263 | {VIACR, CR90, 0xFF, 0x10}, /* LCD Power Sequence Control 5 */ | ||
264 | {VIACR, CR91, 0xFF, 0xA0}, /* 24/12 bit LVDS Data off */ | ||
265 | {VIACR, CR96, 0xFF, 0x03}, /* DVP0 ; DVP0 Clock Skew */ | ||
266 | {VIACR, CR97, 0xFF, 0x03}, /* DFP high ; DFPH Clock Skew */ | ||
267 | {VIACR, CR99, 0xFF, 0x03}, /* DFP low ; DFPL Clock Skew*/ | ||
268 | {VIACR, CR9B, 0xFF, 0x07} /* DVI on DVP1 ; DVP1 Clock Skew*/ | ||
269 | }; | ||
270 | |||
271 | /* For VT3324: Common Setting for Video Mode */ | ||
272 | struct io_reg CX700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01}, | ||
273 | {VIASR, SR15, 0x02, 0x02}, | ||
274 | {VIASR, SR16, 0xBF, 0x08}, | ||
275 | {VIASR, SR17, 0xFF, 0x1F}, | ||
276 | {VIASR, SR18, 0xFF, 0x4E}, | ||
277 | {VIASR, SR1A, 0xFB, 0x08}, | ||
278 | {VIASR, SR1B, 0xFF, 0xF0}, | ||
279 | {VIASR, SR1E, 0xFF, 0x01}, | ||
280 | {VIASR, SR2A, 0xFF, 0x00}, | ||
281 | {VIASR, SR2D, 0xFF, 0xFF}, /* VCK and LCK PLL power on. */ | ||
282 | {VIACR, CR0A, 0xFF, 0x1E}, /* Cursor Start */ | ||
283 | {VIACR, CR0B, 0xFF, 0x00}, /* Cursor End */ | ||
284 | {VIACR, CR0E, 0xFF, 0x00}, /* Cursor Location High */ | ||
285 | {VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */ | ||
286 | {VIACR, CR32, 0xFF, 0x00}, | ||
287 | {VIACR, CR33, 0xFF, 0x00}, | ||
288 | {VIACR, CR34, 0xFF, 0x00}, | ||
289 | {VIACR, CR35, 0xFF, 0x00}, | ||
290 | {VIACR, CR36, 0x08, 0x00}, | ||
291 | {VIACR, CR47, 0xC8, 0x00}, /* Clear VCK Plus. */ | ||
292 | {VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */ | ||
293 | {VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */ | ||
294 | {VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */ | ||
295 | {VIACR, CRA3, 0xFF, 0x00}, /* Secondary Display Starting Address */ | ||
296 | {VIACR, CR69, 0xFF, 0x00}, | ||
297 | {VIACR, CR6A, 0xFF, 0x40}, | ||
298 | {VIACR, CR6B, 0xFF, 0x00}, | ||
299 | {VIACR, CR6C, 0xFF, 0x00}, | ||
300 | {VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */ | ||
301 | {VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */ | ||
302 | {VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */ | ||
303 | {VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */ | ||
304 | {VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */ | ||
305 | {VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */ | ||
306 | {VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */ | ||
307 | {VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */ | ||
308 | {VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */ | ||
309 | {VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */ | ||
310 | {VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */ | ||
311 | {VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */ | ||
312 | {VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */ | ||
313 | {VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */ | ||
314 | {VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */ | ||
315 | {VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */ | ||
316 | {VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */ | ||
317 | {VIACR, CRD4, 0xFF, 0x81}, /* Second power sequence control */ | ||
318 | {VIACR, CR8B, 0xFF, 0x5D}, /* LCD Power Sequence Control 0 */ | ||
319 | {VIACR, CR8C, 0xFF, 0x2B}, /* LCD Power Sequence Control 1 */ | ||
320 | {VIACR, CR8D, 0xFF, 0x6F}, /* LCD Power Sequence Control 2 */ | ||
321 | {VIACR, CR8E, 0xFF, 0x2B}, /* LCD Power Sequence Control 3 */ | ||
322 | {VIACR, CR8F, 0xFF, 0x01}, /* LCD Power Sequence Control 4 */ | ||
323 | {VIACR, CR90, 0xFF, 0x01}, /* LCD Power Sequence Control 5 */ | ||
324 | {VIACR, CR91, 0xFF, 0x80}, /* 24/12 bit LVDS Data off */ | ||
325 | {VIACR, CR96, 0xFF, 0x00}, | ||
326 | {VIACR, CR97, 0xFF, 0x00}, | ||
327 | {VIACR, CR99, 0xFF, 0x00}, | ||
328 | {VIACR, CR9B, 0xFF, 0x00}, | ||
329 | {VIACR, CRD2, 0xFF, 0xFF} /* TMDS/LVDS control register. */ | ||
330 | }; | ||
331 | |||
332 | /* For VT3353: Common Setting for Video Mode */ | ||
333 | struct io_reg VX800_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01}, | ||
334 | {VIASR, SR15, 0x02, 0x02}, | ||
335 | {VIASR, SR16, 0xBF, 0x08}, | ||
336 | {VIASR, SR17, 0xFF, 0x1F}, | ||
337 | {VIASR, SR18, 0xFF, 0x4E}, | ||
338 | {VIASR, SR1A, 0xFB, 0x08}, | ||
339 | {VIASR, SR1B, 0xFF, 0xF0}, | ||
340 | {VIASR, SR1E, 0xFF, 0x01}, | ||
341 | {VIASR, SR2A, 0xFF, 0x00}, | ||
342 | {VIASR, SR2D, 0xFF, 0xFF}, /* VCK and LCK PLL power on. */ | ||
343 | {VIACR, CR0A, 0xFF, 0x1E}, /* Cursor Start */ | ||
344 | {VIACR, CR0B, 0xFF, 0x00}, /* Cursor End */ | ||
345 | {VIACR, CR0E, 0xFF, 0x00}, /* Cursor Location High */ | ||
346 | {VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */ | ||
347 | {VIACR, CR32, 0xFF, 0x00}, | ||
348 | {VIACR, CR33, 0xFF, 0x00}, | ||
349 | {VIACR, CR34, 0xFF, 0x00}, | ||
350 | {VIACR, CR35, 0xFF, 0x00}, | ||
351 | {VIACR, CR36, 0x08, 0x00}, | ||
352 | {VIACR, CR47, 0xC8, 0x00}, /* Clear VCK Plus. */ | ||
353 | {VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */ | ||
354 | {VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */ | ||
355 | {VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */ | ||
356 | {VIACR, CRA3, 0xFF, 0x00}, /* Secondary Display Starting Address */ | ||
357 | {VIACR, CR69, 0xFF, 0x00}, | ||
358 | {VIACR, CR6A, 0xFF, 0x40}, | ||
359 | {VIACR, CR6B, 0xFF, 0x00}, | ||
360 | {VIACR, CR6C, 0xFF, 0x00}, | ||
361 | {VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */ | ||
362 | {VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */ | ||
363 | {VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */ | ||
364 | {VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */ | ||
365 | {VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */ | ||
366 | {VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */ | ||
367 | {VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */ | ||
368 | {VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */ | ||
369 | {VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */ | ||
370 | {VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */ | ||
371 | {VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */ | ||
372 | {VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */ | ||
373 | {VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */ | ||
374 | {VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */ | ||
375 | {VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */ | ||
376 | {VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */ | ||
377 | {VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */ | ||
378 | {VIACR, CRD4, 0xFF, 0x81}, /* Second power sequence control */ | ||
379 | {VIACR, CR8B, 0xFF, 0x5D}, /* LCD Power Sequence Control 0 */ | ||
380 | {VIACR, CR8C, 0xFF, 0x2B}, /* LCD Power Sequence Control 1 */ | ||
381 | {VIACR, CR8D, 0xFF, 0x6F}, /* LCD Power Sequence Control 2 */ | ||
382 | {VIACR, CR8E, 0xFF, 0x2B}, /* LCD Power Sequence Control 3 */ | ||
383 | {VIACR, CR8F, 0xFF, 0x01}, /* LCD Power Sequence Control 4 */ | ||
384 | {VIACR, CR90, 0xFF, 0x01}, /* LCD Power Sequence Control 5 */ | ||
385 | {VIACR, CR91, 0xFF, 0x80}, /* 24/12 bit LVDS Data off */ | ||
386 | {VIACR, CR96, 0xFF, 0x00}, | ||
387 | {VIACR, CR97, 0xFF, 0x00}, | ||
388 | {VIACR, CR99, 0xFF, 0x00}, | ||
389 | {VIACR, CR9B, 0xFF, 0x00}, | ||
390 | {VIACR, CRD2, 0xFF, 0xFF} /* TMDS/LVDS control register. */ | ||
391 | }; | ||
392 | |||
393 | /* Video Mode Table */ | ||
394 | /* Common Setting for Video Mode */ | ||
395 | struct io_reg CLE266_ModeXregs[] = { {VIASR, SR1E, 0xF0, 0x00}, | ||
396 | {VIASR, SR2A, 0x0F, 0x00}, | ||
397 | {VIASR, SR15, 0x02, 0x02}, | ||
398 | {VIASR, SR16, 0xBF, 0x08}, | ||
399 | {VIASR, SR17, 0xFF, 0x1F}, | ||
400 | {VIASR, SR18, 0xFF, 0x4E}, | ||
401 | {VIASR, SR1A, 0xFB, 0x08}, | ||
402 | |||
403 | {VIACR, CR32, 0xFF, 0x00}, | ||
404 | {VIACR, CR34, 0xFF, 0x00}, | ||
405 | {VIACR, CR35, 0xFF, 0x00}, | ||
406 | {VIACR, CR36, 0x08, 0x00}, | ||
407 | {VIACR, CR6A, 0xFF, 0x80}, | ||
408 | {VIACR, CR6A, 0xFF, 0xC0}, | ||
409 | |||
410 | {VIACR, CR55, 0x80, 0x00}, | ||
411 | {VIACR, CR5D, 0x80, 0x00}, | ||
412 | |||
413 | {VIAGR, GR20, 0xFF, 0x00}, | ||
414 | {VIAGR, GR21, 0xFF, 0x00}, | ||
415 | {VIAGR, GR22, 0xFF, 0x00}, | ||
416 | /* LCD Parameters */ | ||
417 | {VIACR, CR7A, 0xFF, 0x01}, /* LCD Parameter 1 */ | ||
418 | {VIACR, CR7B, 0xFF, 0x02}, /* LCD Parameter 2 */ | ||
419 | {VIACR, CR7C, 0xFF, 0x03}, /* LCD Parameter 3 */ | ||
420 | {VIACR, CR7D, 0xFF, 0x04}, /* LCD Parameter 4 */ | ||
421 | {VIACR, CR7E, 0xFF, 0x07}, /* LCD Parameter 5 */ | ||
422 | {VIACR, CR7F, 0xFF, 0x0A}, /* LCD Parameter 6 */ | ||
423 | {VIACR, CR80, 0xFF, 0x0D}, /* LCD Parameter 7 */ | ||
424 | {VIACR, CR81, 0xFF, 0x13}, /* LCD Parameter 8 */ | ||
425 | {VIACR, CR82, 0xFF, 0x16}, /* LCD Parameter 9 */ | ||
426 | {VIACR, CR83, 0xFF, 0x19}, /* LCD Parameter 10 */ | ||
427 | {VIACR, CR84, 0xFF, 0x1C}, /* LCD Parameter 11 */ | ||
428 | {VIACR, CR85, 0xFF, 0x1D}, /* LCD Parameter 12 */ | ||
429 | {VIACR, CR86, 0xFF, 0x1E}, /* LCD Parameter 13 */ | ||
430 | {VIACR, CR87, 0xFF, 0x1F}, /* LCD Parameter 14 */ | ||
431 | |||
432 | }; | ||
433 | |||
434 | /* Mode:1024X768 */ | ||
435 | struct io_reg PM1024x768[] = { {VIASR, 0x16, 0xBF, 0x0C}, | ||
436 | {VIASR, 0x18, 0xFF, 0x4C} | ||
437 | }; | ||
438 | |||
439 | struct patch_table res_patch_table[] = { | ||
440 | {VIA_RES_1024X768, ARRAY_SIZE(PM1024x768), PM1024x768} | ||
441 | }; | ||
442 | |||
443 | /* struct VPITTable { | ||
444 | unsigned char Misc; | ||
445 | unsigned char SR[StdSR]; | ||
446 | unsigned char CR[StdCR]; | ||
447 | unsigned char GR[StdGR]; | ||
448 | unsigned char AR[StdAR]; | ||
449 | };*/ | ||
450 | |||
451 | struct VPITTable VPIT = { | ||
452 | /* Msic */ | ||
453 | 0xC7, | ||
454 | /* Sequencer */ | ||
455 | {0x01, 0x0F, 0x00, 0x0E}, | ||
456 | /* Graphic Controller */ | ||
457 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF}, | ||
458 | /* Attribute Controller */ | ||
459 | {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, | ||
460 | 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, | ||
461 | 0x01, 0x00, 0x0F, 0x00} | ||
462 | }; | ||
463 | |||
464 | /********************/ | ||
465 | /* Mode Table */ | ||
466 | /********************/ | ||
467 | |||
468 | /* 480x640 */ | ||
469 | struct crt_mode_table CRTM480x640[] = { | ||
470 | /* r_rate, vclk, hsp, vsp */ | ||
471 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
472 | {REFRESH_60, CLK_25_175M, M480X640_R60_HSP, M480X640_R60_VSP, | ||
473 | {624, 480, 480, 144, 504, 48, 663, 640, 640, 23, 641, 3} } /* GTF*/ | ||
474 | }; | ||
475 | |||
476 | /* 640x480*/ | ||
477 | struct crt_mode_table CRTM640x480[] = { | ||
478 | /*r_rate,vclk,hsp,vsp */ | ||
479 | /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
480 | {REFRESH_60, CLK_25_175M, M640X480_R60_HSP, M640X480_R60_VSP, | ||
481 | {800, 640, 648, 144, 656, 96, 525, 480, 480, 45, 490, 2} }, | ||
482 | {REFRESH_75, CLK_31_500M, M640X480_R75_HSP, M640X480_R75_VSP, | ||
483 | {840, 640, 640, 200, 656, 64, 500, 480, 480, 20, 481, 3} }, | ||
484 | {REFRESH_85, CLK_36_000M, M640X480_R85_HSP, M640X480_R85_VSP, | ||
485 | {832, 640, 640, 192, 696, 56, 509, 480, 480, 29, 481, 3} }, | ||
486 | {REFRESH_100, CLK_43_163M, M640X480_R100_HSP, M640X480_R100_VSP, | ||
487 | {848, 640, 640, 208, 680, 64, 509, 480, 480, 29, 481, 3} }, /*GTF*/ | ||
488 | {REFRESH_120, CLK_52_406M, M640X480_R120_HSP, | ||
489 | M640X480_R120_VSP, | ||
490 | {848, 640, 640, 208, 680, 64, 515, 480, 480, 35, 481, | ||
491 | 3} } /*GTF*/ | ||
492 | }; | ||
493 | |||
494 | /*720x480 (GTF)*/ | ||
495 | struct crt_mode_table CRTM720x480[] = { | ||
496 | /*r_rate,vclk,hsp,vsp */ | ||
497 | /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
498 | {REFRESH_60, CLK_26_880M, M720X480_R60_HSP, M720X480_R60_VSP, | ||
499 | {896, 720, 720, 176, 736, 72, 497, 480, 480, 17, 481, 3} } | ||
500 | |||
501 | }; | ||
502 | |||
503 | /*720x576 (GTF)*/ | ||
504 | struct crt_mode_table CRTM720x576[] = { | ||
505 | /*r_rate,vclk,hsp,vsp */ | ||
506 | /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
507 | {REFRESH_60, CLK_32_668M, M720X576_R60_HSP, M720X576_R60_VSP, | ||
508 | {912, 720, 720, 192, 744, 72, 597, 576, 576, 21, 577, 3} } | ||
509 | }; | ||
510 | |||
511 | /* 800x480 (CVT) */ | ||
512 | struct crt_mode_table CRTM800x480[] = { | ||
513 | /* r_rate, vclk, hsp, vsp */ | ||
514 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
515 | {REFRESH_60, CLK_29_581M, M800X480_R60_HSP, M800X480_R60_VSP, | ||
516 | {992, 800, 800, 192, 824, 72, 500, 480, 480, 20, 483, 7} } | ||
517 | }; | ||
518 | |||
519 | /* 800x600*/ | ||
520 | struct crt_mode_table CRTM800x600[] = { | ||
521 | /*r_rate,vclk,hsp,vsp */ | ||
522 | /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
523 | {REFRESH_60, CLK_40_000M, M800X600_R60_HSP, M800X600_R60_VSP, | ||
524 | {1056, 800, 800, 256, 840, 128, 628, 600, 600, 28, 601, 4} }, | ||
525 | {REFRESH_75, CLK_49_500M, M800X600_R75_HSP, M800X600_R75_VSP, | ||
526 | {1056, 800, 800, 256, 816, 80, 625, 600, 600, 25, 601, 3} }, | ||
527 | {REFRESH_85, CLK_56_250M, M800X600_R85_HSP, M800X600_R85_VSP, | ||
528 | {1048, 800, 800, 248, 832, 64, 631, 600, 600, 31, 601, 3} }, | ||
529 | {REFRESH_100, CLK_68_179M, M800X600_R100_HSP, M800X600_R100_VSP, | ||
530 | {1072, 800, 800, 272, 848, 88, 636, 600, 600, 36, 601, 3} }, | ||
531 | {REFRESH_120, CLK_83_950M, M800X600_R120_HSP, | ||
532 | M800X600_R120_VSP, | ||
533 | {1088, 800, 800, 288, 856, 88, 643, 600, 600, 43, 601, | ||
534 | 3} } | ||
535 | }; | ||
536 | |||
537 | /* 848x480 (CVT) */ | ||
538 | struct crt_mode_table CRTM848x480[] = { | ||
539 | /* r_rate, vclk, hsp, vsp */ | ||
540 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
541 | {REFRESH_60, CLK_31_500M, M848X480_R60_HSP, M848X480_R60_VSP, | ||
542 | {1056, 848, 848, 208, 872, 80, 500, 480, 480, 20, 483, 5} } | ||
543 | }; | ||
544 | |||
545 | /*856x480 (GTF) convert to 852x480*/ | ||
546 | struct crt_mode_table CRTM852x480[] = { | ||
547 | /*r_rate,vclk,hsp,vsp */ | ||
548 | /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
549 | {REFRESH_60, CLK_31_728M, M852X480_R60_HSP, M852X480_R60_VSP, | ||
550 | {1064, 856, 856, 208, 872, 88, 497, 480, 480, 17, 481, 3} } | ||
551 | }; | ||
552 | |||
553 | /*1024x512 (GTF)*/ | ||
554 | struct crt_mode_table CRTM1024x512[] = { | ||
555 | /*r_rate,vclk,hsp,vsp */ | ||
556 | /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
557 | {REFRESH_60, CLK_41_291M, M1024X512_R60_HSP, M1024X512_R60_VSP, | ||
558 | {1296, 1024, 1024, 272, 1056, 104, 531, 512, 512, 19, 513, 3} } | ||
559 | |||
560 | }; | ||
561 | |||
562 | /* 1024x600*/ | ||
563 | struct crt_mode_table CRTM1024x600[] = { | ||
564 | /*r_rate,vclk,hsp,vsp */ | ||
565 | /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
566 | {REFRESH_60, CLK_48_875M, M1024X600_R60_HSP, M1024X600_R60_VSP, | ||
567 | {1312, 1024, 1024, 288, 1064, 104, 622, 600, 600, 22, 601, 3} }, | ||
568 | }; | ||
569 | |||
570 | /* 1024x768*/ | ||
571 | struct crt_mode_table CRTM1024x768[] = { | ||
572 | /*r_rate,vclk,hsp,vsp */ | ||
573 | /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
574 | {REFRESH_60, CLK_65_000M, M1024X768_R60_HSP, M1024X768_R60_VSP, | ||
575 | {1344, 1024, 1024, 320, 1048, 136, 806, 768, 768, 38, 771, 6} }, | ||
576 | {REFRESH_75, CLK_78_750M, M1024X768_R75_HSP, M1024X768_R75_VSP, | ||
577 | {1312, 1024, 1024, 288, 1040, 96, 800, 768, 768, 32, 769, 3} }, | ||
578 | {REFRESH_85, CLK_94_500M, M1024X768_R85_HSP, M1024X768_R85_VSP, | ||
579 | {1376, 1024, 1024, 352, 1072, 96, 808, 768, 768, 40, 769, 3} }, | ||
580 | {REFRESH_100, CLK_113_309M, M1024X768_R100_HSP, M1024X768_R100_VSP, | ||
581 | {1392, 1024, 1024, 368, 1096, 112, 814, 768, 768, 46, 769, 3} } | ||
582 | }; | ||
583 | |||
584 | /* 1152x864*/ | ||
585 | struct crt_mode_table CRTM1152x864[] = { | ||
586 | /*r_rate,vclk,hsp,vsp */ | ||
587 | /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
588 | {REFRESH_75, CLK_108_000M, M1152X864_R75_HSP, M1152X864_R75_VSP, | ||
589 | {1600, 1152, 1152, 448, 1216, 128, 900, 864, 864, 36, 865, 3} } | ||
590 | |||
591 | }; | ||
592 | |||
593 | /* 1280x720 (HDMI 720P)*/ | ||
594 | struct crt_mode_table CRTM1280x720[] = { | ||
595 | /*r_rate,vclk,hsp,vsp */ | ||
596 | /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
597 | {REFRESH_60, CLK_74_481M, M1280X720_R60_HSP, M1280X720_R60_VSP, | ||
598 | {1648, 1280, 1280, 368, 1392, 40, 750, 720, 720, 30, 725, 5} }, | ||
599 | {REFRESH_50, CLK_60_466M, M1280X720_R50_HSP, M1280X720_R50_VSP, | ||
600 | {1632, 1280, 1280, 352, 1328, 128, 741, 720, 720, 21, 721, 3} } | ||
601 | }; | ||
602 | |||
603 | /*1280x768 (GTF)*/ | ||
604 | struct crt_mode_table CRTM1280x768[] = { | ||
605 | /*r_rate,vclk,hsp,vsp */ | ||
606 | /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
607 | {REFRESH_60, CLK_80_136M, M1280X768_R60_HSP, M1280X768_R60_VSP, | ||
608 | {1680, 1280, 1280, 400, 1344, 136, 795, 768, 768, 27, 769, 3} }, | ||
609 | {REFRESH_50, CLK_65_178M, M1280X768_R50_HSP, M1280X768_R50_VSP, | ||
610 | {1648, 1280, 1280, 368, 1336, 128, 791, 768, 768, 23, 769, 3} } | ||
611 | }; | ||
612 | |||
613 | /* 1280x800 (CVT) */ | ||
614 | struct crt_mode_table CRTM1280x800[] = { | ||
615 | /* r_rate, vclk, hsp, vsp */ | ||
616 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
617 | {REFRESH_60, CLK_83_375M, M1280X800_R60_HSP, M1280X800_R60_VSP, | ||
618 | {1680, 1280, 1280, 400, 1352, 128, 831, 800, 800, 31, 803, 6} } | ||
619 | }; | ||
620 | |||
621 | /*1280x960*/ | ||
622 | struct crt_mode_table CRTM1280x960[] = { | ||
623 | /*r_rate,vclk,hsp,vsp */ | ||
624 | /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
625 | {REFRESH_60, CLK_108_000M, M1280X960_R60_HSP, M1280X960_R60_VSP, | ||
626 | {1800, 1280, 1280, 520, 1376, 112, 1000, 960, 960, 40, 961, 3} } | ||
627 | }; | ||
628 | |||
629 | /* 1280x1024*/ | ||
630 | struct crt_mode_table CRTM1280x1024[] = { | ||
631 | /*r_rate,vclk,,hsp,vsp */ | ||
632 | /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
633 | {REFRESH_60, CLK_108_000M, M1280X1024_R60_HSP, M1280X1024_R60_VSP, | ||
634 | {1688, 1280, 1280, 408, 1328, 112, 1066, 1024, 1024, 42, 1025, | ||
635 | 3} }, | ||
636 | {REFRESH_75, CLK_135_000M, M1280X1024_R75_HSP, M1280X1024_R75_VSP, | ||
637 | {1688, 1280, 1280, 408, 1296, 144, 1066, 1024, 1024, 42, 1025, | ||
638 | 3} }, | ||
639 | {REFRESH_85, CLK_157_500M, M1280X1024_R85_HSP, M1280X1024_R85_VSP, | ||
640 | {1728, 1280, 1280, 448, 1344, 160, 1072, 1024, 1024, 48, 1025, 3} } | ||
641 | }; | ||
642 | |||
643 | /* 1368x768 (GTF) */ | ||
644 | struct crt_mode_table CRTM1368x768[] = { | ||
645 | /* r_rate, vclk, hsp, vsp */ | ||
646 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
647 | {REFRESH_60, CLK_85_860M, M1368X768_R60_HSP, M1368X768_R60_VSP, | ||
648 | {1800, 1368, 1368, 432, 1440, 144, 795, 768, 768, 27, 769, 3} } | ||
649 | }; | ||
650 | |||
651 | /*1440x1050 (GTF)*/ | ||
652 | struct crt_mode_table CRTM1440x1050[] = { | ||
653 | /*r_rate,vclk,hsp,vsp */ | ||
654 | /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
655 | {REFRESH_60, CLK_125_104M, M1440X1050_R60_HSP, M1440X1050_R60_VSP, | ||
656 | {1936, 1440, 1440, 496, 1536, 152, 1077, 1040, 1040, 37, 1041, 3} } | ||
657 | }; | ||
658 | |||
659 | /* 1600x1200*/ | ||
660 | struct crt_mode_table CRTM1600x1200[] = { | ||
661 | /*r_rate,vclk,hsp,vsp */ | ||
662 | /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
663 | {REFRESH_60, CLK_162_000M, M1600X1200_R60_HSP, M1600X1200_R60_VSP, | ||
664 | {2160, 1600, 1600, 560, 1664, 192, 1250, 1200, 1200, 50, 1201, | ||
665 | 3} }, | ||
666 | {REFRESH_75, CLK_202_500M, M1600X1200_R75_HSP, M1600X1200_R75_VSP, | ||
667 | {2160, 1600, 1600, 560, 1664, 192, 1250, 1200, 1200, 50, 1201, 3} } | ||
668 | |||
669 | }; | ||
670 | |||
671 | /* 1680x1050 (CVT) */ | ||
672 | struct crt_mode_table CRTM1680x1050[] = { | ||
673 | /* r_rate, vclk, hsp, vsp */ | ||
674 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
675 | {REFRESH_60, CLK_146_760M, M1680x1050_R60_HSP, M1680x1050_R60_VSP, | ||
676 | {2240, 1680, 1680, 560, 1784, 176, 1089, 1050, 1050, 39, 1053, | ||
677 | 6} }, | ||
678 | {REFRESH_75, CLK_187_000M, M1680x1050_R75_HSP, M1680x1050_R75_VSP, | ||
679 | {2272, 1680, 1680, 592, 1800, 176, 1099, 1050, 1050, 49, 1053, 6} } | ||
680 | }; | ||
681 | |||
682 | /* 1680x1050 (CVT Reduce Blanking) */ | ||
683 | struct crt_mode_table CRTM1680x1050_RB[] = { | ||
684 | /* r_rate, vclk, hsp, vsp */ | ||
685 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
686 | {REFRESH_60, CLK_119_000M, M1680x1050_RB_R60_HSP, | ||
687 | M1680x1050_RB_R60_VSP, | ||
688 | {1840, 1680, 1680, 160, 1728, 32, 1080, 1050, 1050, 30, 1053, 6} } | ||
689 | }; | ||
690 | |||
691 | /* 1920x1080 (CVT)*/ | ||
692 | struct crt_mode_table CRTM1920x1080[] = { | ||
693 | /*r_rate,vclk,hsp,vsp */ | ||
694 | /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
695 | {REFRESH_60, CLK_172_798M, M1920X1080_R60_HSP, M1920X1080_R60_VSP, | ||
696 | {2576, 1920, 1920, 656, 2048, 200, 1120, 1080, 1080, 40, 1083, 5} } | ||
697 | }; | ||
698 | |||
699 | /* 1920x1080 (CVT with Reduce Blanking) */ | ||
700 | struct crt_mode_table CRTM1920x1080_RB[] = { | ||
701 | /* r_rate, vclk, hsp, vsp */ | ||
702 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
703 | {REFRESH_60, CLK_138_400M, M1920X1080_RB_R60_HSP, | ||
704 | M1920X1080_RB_R60_VSP, | ||
705 | {2080, 1920, 1920, 160, 1968, 32, 1111, 1080, 1080, 31, 1083, 5} } | ||
706 | }; | ||
707 | |||
708 | /* 1920x1440*/ | ||
709 | struct crt_mode_table CRTM1920x1440[] = { | ||
710 | /*r_rate,vclk,hsp,vsp */ | ||
711 | /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
712 | {REFRESH_60, CLK_234_000M, M1920X1440_R60_HSP, M1920X1440_R60_VSP, | ||
713 | {2600, 1920, 1920, 680, 2048, 208, 1500, 1440, 1440, 60, 1441, | ||
714 | 3} }, | ||
715 | {REFRESH_75, CLK_297_500M, M1920X1440_R75_HSP, M1920X1440_R75_VSP, | ||
716 | {2640, 1920, 1920, 720, 2064, 224, 1500, 1440, 1440, 60, 1441, 3} } | ||
717 | }; | ||
718 | |||
719 | /* 1400x1050 (CVT) */ | ||
720 | struct crt_mode_table CRTM1400x1050[] = { | ||
721 | /* r_rate, vclk, hsp, vsp */ | ||
722 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
723 | {REFRESH_60, CLK_121_750M, M1400X1050_R60_HSP, M1400X1050_R60_VSP, | ||
724 | {1864, 1400, 1400, 464, 1488, 144, 1089, 1050, 1050, 39, 1053, | ||
725 | 4} }, | ||
726 | {REFRESH_75, CLK_156_000M, M1400X1050_R75_HSP, M1400X1050_R75_VSP, | ||
727 | {1896, 1400, 1400, 496, 1504, 144, 1099, 1050, 1050, 49, 1053, 4} } | ||
728 | }; | ||
729 | |||
730 | /* 1400x1050 (CVT Reduce Blanking) */ | ||
731 | struct crt_mode_table CRTM1400x1050_RB[] = { | ||
732 | /* r_rate, vclk, hsp, vsp */ | ||
733 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
734 | {REFRESH_60, CLK_101_000M, M1400X1050_RB_R60_HSP, | ||
735 | M1400X1050_RB_R60_VSP, | ||
736 | {1560, 1400, 1400, 160, 1448, 32, 1080, 1050, 1050, 30, 1053, 4} } | ||
737 | }; | ||
738 | |||
739 | /* 960x600 (CVT) */ | ||
740 | struct crt_mode_table CRTM960x600[] = { | ||
741 | /* r_rate, vclk, hsp, vsp */ | ||
742 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
743 | {REFRESH_60, CLK_45_250M, M960X600_R60_HSP, M960X600_R60_VSP, | ||
744 | {1216, 960, 960, 256, 992, 96, 624, 600, 600, 24, 603, 6} } | ||
745 | }; | ||
746 | |||
747 | /* 1000x600 (GTF) */ | ||
748 | struct crt_mode_table CRTM1000x600[] = { | ||
749 | /* r_rate, vclk, hsp, vsp */ | ||
750 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
751 | {REFRESH_60, CLK_48_000M, M1000X600_R60_HSP, M1000X600_R60_VSP, | ||
752 | {1288, 1000, 1000, 288, 1040, 104, 622, 600, 600, 22, 601, 3} } | ||
753 | }; | ||
754 | |||
755 | /* 1024x576 (GTF) */ | ||
756 | struct crt_mode_table CRTM1024x576[] = { | ||
757 | /* r_rate, vclk, hsp, vsp */ | ||
758 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
759 | {REFRESH_60, CLK_46_996M, M1024X576_R60_HSP, M1024X576_R60_VSP, | ||
760 | {1312, 1024, 1024, 288, 1064, 104, 597, 576, 576, 21, 577, 3} } | ||
761 | }; | ||
762 | |||
763 | /* 1088x612 (CVT) */ | ||
764 | struct crt_mode_table CRTM1088x612[] = { | ||
765 | /* r_rate, vclk, hsp, vsp */ | ||
766 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
767 | {REFRESH_60, CLK_52_977M, M1088X612_R60_HSP, M1088X612_R60_VSP, | ||
768 | {1392, 1088, 1088, 304, 1136, 104, 636, 612, 612, 24, 615, 5} } | ||
769 | }; | ||
770 | |||
771 | /* 1152x720 (CVT) */ | ||
772 | struct crt_mode_table CRTM1152x720[] = { | ||
773 | /* r_rate, vclk, hsp, vsp */ | ||
774 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
775 | {REFRESH_60, CLK_66_750M, M1152X720_R60_HSP, M1152X720_R60_VSP, | ||
776 | {1488, 1152, 1152, 336, 1208, 112, 748, 720, 720, 28, 723, 6} } | ||
777 | }; | ||
778 | |||
779 | /* 1200x720 (GTF) */ | ||
780 | struct crt_mode_table CRTM1200x720[] = { | ||
781 | /* r_rate, vclk, hsp, vsp */ | ||
782 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
783 | {REFRESH_60, CLK_70_159M, M1200X720_R60_HSP, M1200X720_R60_VSP, | ||
784 | {1568, 1200, 1200, 368, 1256, 128, 746, 720, 720, 26, 721, 3} } | ||
785 | }; | ||
786 | |||
787 | /* 1280x600 (GTF) */ | ||
788 | struct crt_mode_table CRTM1280x600[] = { | ||
789 | /* r_rate, vclk, hsp, vsp */ | ||
790 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
791 | {REFRESH_60, CLK_61_500M, M1280x600_R60_HSP, M1280x600_R60_VSP, | ||
792 | {1648, 1280, 1280, 368, 1336, 128, 622, 600, 600, 22, 601, 3} } | ||
793 | }; | ||
794 | |||
795 | /* 1360x768 (CVT) */ | ||
796 | struct crt_mode_table CRTM1360x768[] = { | ||
797 | /* r_rate, vclk, hsp, vsp */ | ||
798 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
799 | {REFRESH_60, CLK_84_750M, M1360X768_R60_HSP, M1360X768_R60_VSP, | ||
800 | {1776, 1360, 1360, 416, 1432, 136, 798, 768, 768, 30, 771, 5} } | ||
801 | }; | ||
802 | |||
803 | /* 1360x768 (CVT Reduce Blanking) */ | ||
804 | struct crt_mode_table CRTM1360x768_RB[] = { | ||
805 | /* r_rate, vclk, hsp, vsp */ | ||
806 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
807 | {REFRESH_60, CLK_72_000M, M1360X768_RB_R60_HSP, | ||
808 | M1360X768_RB_R60_VSP, | ||
809 | {1520, 1360, 1360, 160, 1408, 32, 790, 768, 768, 22, 771, 5} } | ||
810 | }; | ||
811 | |||
812 | /* 1366x768 (GTF) */ | ||
813 | struct crt_mode_table CRTM1366x768[] = { | ||
814 | /* r_rate, vclk, hsp, vsp */ | ||
815 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
816 | {REFRESH_60, CLK_85_860M, M1368X768_R60_HSP, M1368X768_R60_VSP, | ||
817 | {1800, 1368, 1368, 432, 1440, 144, 795, 768, 768, 27, 769, 3} }, | ||
818 | {REFRESH_50, CLK_69_924M, M1368X768_R50_HSP, M1368X768_R50_VSP, | ||
819 | {1768, 1368, 1368, 400, 1424, 144, 791, 768, 768, 23, 769, 3} } | ||
820 | }; | ||
821 | |||
822 | /* 1440x900 (CVT) */ | ||
823 | struct crt_mode_table CRTM1440x900[] = { | ||
824 | /* r_rate, vclk, hsp, vsp */ | ||
825 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
826 | {REFRESH_60, CLK_106_500M, M1440X900_R60_HSP, M1440X900_R60_VSP, | ||
827 | {1904, 1440, 1440, 464, 1520, 152, 934, 900, 900, 34, 903, 6} }, | ||
828 | {REFRESH_75, CLK_136_700M, M1440X900_R75_HSP, M1440X900_R75_VSP, | ||
829 | {1936, 1440, 1440, 496, 1536, 152, 942, 900, 900, 42, 903, 6} } | ||
830 | }; | ||
831 | |||
832 | /* 1440x900 (CVT Reduce Blanking) */ | ||
833 | struct crt_mode_table CRTM1440x900_RB[] = { | ||
834 | /* r_rate, vclk, hsp, vsp */ | ||
835 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
836 | {REFRESH_60, CLK_88_750M, M1440X900_RB_R60_HSP, | ||
837 | M1440X900_RB_R60_VSP, | ||
838 | {1600, 1440, 1440, 160, 1488, 32, 926, 900, 900, 26, 903, 6} } | ||
839 | }; | ||
840 | |||
841 | /* 1600x900 (CVT) */ | ||
842 | struct crt_mode_table CRTM1600x900[] = { | ||
843 | /* r_rate, vclk, hsp, vsp */ | ||
844 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
845 | {REFRESH_60, CLK_118_840M, M1600X900_R60_HSP, M1600X900_R60_VSP, | ||
846 | {2112, 1600, 1600, 512, 1688, 168, 934, 900, 900, 34, 903, 5} } | ||
847 | }; | ||
848 | |||
849 | /* 1600x900 (CVT Reduce Blanking) */ | ||
850 | struct crt_mode_table CRTM1600x900_RB[] = { | ||
851 | /* r_rate, vclk, hsp, vsp */ | ||
852 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
853 | {REFRESH_60, CLK_97_750M, M1600X900_RB_R60_HSP, | ||
854 | M1600X900_RB_R60_VSP, | ||
855 | {1760, 1600, 1600, 160, 1648, 32, 926, 900, 900, 26, 903, 5} } | ||
856 | }; | ||
857 | |||
858 | /* 1600x1024 (GTF) */ | ||
859 | struct crt_mode_table CRTM1600x1024[] = { | ||
860 | /* r_rate, vclk, hsp, vsp */ | ||
861 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
862 | {REFRESH_60, CLK_136_700M, M1600X1024_R60_HSP, M1600X1024_R60_VSP, | ||
863 | {2144, 1600, 1600, 544, 1704, 168, 1060, 1024, 1024, 36, 1025, 3} } | ||
864 | }; | ||
865 | |||
866 | /* 1792x1344 (DMT) */ | ||
867 | struct crt_mode_table CRTM1792x1344[] = { | ||
868 | /* r_rate, vclk, hsp, vsp */ | ||
869 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
870 | {REFRESH_60, CLK_204_000M, M1792x1344_R60_HSP, M1792x1344_R60_VSP, | ||
871 | {2448, 1792, 1792, 656, 1920, 200, 1394, 1344, 1344, 50, 1345, 3} } | ||
872 | }; | ||
873 | |||
874 | /* 1856x1392 (DMT) */ | ||
875 | struct crt_mode_table CRTM1856x1392[] = { | ||
876 | /* r_rate, vclk, hsp, vsp */ | ||
877 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
878 | {REFRESH_60, CLK_218_500M, M1856x1392_R60_HSP, M1856x1392_R60_VSP, | ||
879 | {2528, 1856, 1856, 672, 1952, 224, 1439, 1392, 1392, 47, 1393, 3} } | ||
880 | }; | ||
881 | |||
882 | /* 1920x1200 (CVT) */ | ||
883 | struct crt_mode_table CRTM1920x1200[] = { | ||
884 | /* r_rate, vclk, hsp, vsp */ | ||
885 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
886 | {REFRESH_60, CLK_193_295M, M1920X1200_R60_HSP, M1920X1200_R60_VSP, | ||
887 | {2592, 1920, 1920, 672, 2056, 200, 1245, 1200, 1200, 45, 1203, 6} } | ||
888 | }; | ||
889 | |||
890 | /* 1920x1200 (CVT with Reduce Blanking) */ | ||
891 | struct crt_mode_table CRTM1920x1200_RB[] = { | ||
892 | /* r_rate, vclk, hsp, vsp */ | ||
893 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
894 | {REFRESH_60, CLK_153_920M, M1920X1200_RB_R60_HSP, | ||
895 | M1920X1200_RB_R60_VSP, | ||
896 | {2080, 1920, 1920, 160, 1968, 32, 1235, 1200, 1200, 35, 1203, 6} } | ||
897 | }; | ||
898 | |||
899 | /* 2048x1536 (CVT) */ | ||
900 | struct crt_mode_table CRTM2048x1536[] = { | ||
901 | /* r_rate, vclk, hsp, vsp */ | ||
902 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
903 | {REFRESH_60, CLK_267_250M, M2048x1536_R60_HSP, M2048x1536_R60_VSP, | ||
904 | {2800, 2048, 2048, 752, 2200, 224, 1592, 1536, 1536, 56, 1539, 4} } | ||
905 | }; | ||
906 | |||
907 | /* Video Mode Table */ | ||
908 | /* struct VideoModeTable {*/ | ||
909 | /* int ModeIndex;*/ | ||
910 | /* struct crt_mode_table *crtc;*/ | ||
911 | /* int mode_array;*/ | ||
912 | /* };*/ | ||
913 | struct VideoModeTable CLE266Modes[] = { | ||
914 | /* Display : 480x640 (GTF) */ | ||
915 | {VIA_RES_480X640, CRTM480x640, ARRAY_SIZE(CRTM480x640)}, | ||
916 | |||
917 | /* Display : 640x480 */ | ||
918 | {VIA_RES_640X480, CRTM640x480, ARRAY_SIZE(CRTM640x480)}, | ||
919 | |||
920 | /* Display : 720x480 (GTF) */ | ||
921 | {VIA_RES_720X480, CRTM720x480, ARRAY_SIZE(CRTM720x480)}, | ||
922 | |||
923 | /* Display : 720x576 (GTF) */ | ||
924 | {VIA_RES_720X576, CRTM720x576, ARRAY_SIZE(CRTM720x576)}, | ||
925 | |||
926 | /* Display : 800x600 */ | ||
927 | {VIA_RES_800X600, CRTM800x600, ARRAY_SIZE(CRTM800x600)}, | ||
928 | |||
929 | /* Display : 800x480 (CVT) */ | ||
930 | {VIA_RES_800X480, CRTM800x480, ARRAY_SIZE(CRTM800x480)}, | ||
931 | |||
932 | /* Display : 848x480 (CVT) */ | ||
933 | {VIA_RES_848X480, CRTM848x480, ARRAY_SIZE(CRTM848x480)}, | ||
934 | |||
935 | /* Display : 852x480 (GTF) */ | ||
936 | {VIA_RES_856X480, CRTM852x480, ARRAY_SIZE(CRTM852x480)}, | ||
937 | |||
938 | /* Display : 1024x512 (GTF) */ | ||
939 | {VIA_RES_1024X512, CRTM1024x512, ARRAY_SIZE(CRTM1024x512)}, | ||
940 | |||
941 | /* Display : 1024x600 */ | ||
942 | {VIA_RES_1024X600, CRTM1024x600, ARRAY_SIZE(CRTM1024x600)}, | ||
943 | |||
944 | /* Display : 1024x576 (GTF) */ | ||
945 | /*{ VIA_RES_1024X576, CRTM1024x576, ARRAY_SIZE(CRTM1024x576)}, */ | ||
946 | |||
947 | /* Display : 1024x768 */ | ||
948 | {VIA_RES_1024X768, CRTM1024x768, ARRAY_SIZE(CRTM1024x768)}, | ||
949 | |||
950 | /* Display : 1152x864 */ | ||
951 | {VIA_RES_1152X864, CRTM1152x864, ARRAY_SIZE(CRTM1152x864)}, | ||
952 | |||
953 | /* Display : 1280x768 (GTF) */ | ||
954 | {VIA_RES_1280X768, CRTM1280x768, ARRAY_SIZE(CRTM1280x768)}, | ||
955 | |||
956 | /* Display : 960x600 (CVT) */ | ||
957 | {VIA_RES_960X600, CRTM960x600, ARRAY_SIZE(CRTM960x600)}, | ||
958 | |||
959 | /* Display : 1000x600 (GTF) */ | ||
960 | {VIA_RES_1000X600, CRTM1000x600, ARRAY_SIZE(CRTM1000x600)}, | ||
961 | |||
962 | /* Display : 1024x576 (GTF) */ | ||
963 | {VIA_RES_1024X576, CRTM1024x576, ARRAY_SIZE(CRTM1024x576)}, | ||
964 | |||
965 | /* Display : 1088x612 (GTF) */ | ||
966 | {VIA_RES_1088X612, CRTM1088x612, ARRAY_SIZE(CRTM1088x612)}, | ||
967 | |||
968 | /* Display : 1152x720 (CVT) */ | ||
969 | {VIA_RES_1152X720, CRTM1152x720, ARRAY_SIZE(CRTM1152x720)}, | ||
970 | |||
971 | /* Display : 1200x720 (GTF) */ | ||
972 | {VIA_RES_1200X720, CRTM1200x720, ARRAY_SIZE(CRTM1200x720)}, | ||
973 | |||
974 | /* Display : 1280x600 (GTF) */ | ||
975 | {VIA_RES_1280X600, CRTM1280x600, ARRAY_SIZE(CRTM1280x600)}, | ||
976 | |||
977 | /* Display : 1280x800 (CVT) */ | ||
978 | {VIA_RES_1280X800, CRTM1280x800, ARRAY_SIZE(CRTM1280x800)}, | ||
979 | |||
980 | /* Display : 1280x800 (GTF) */ | ||
981 | /*{ M1280x800, CRTM1280x800, ARRAY_SIZE(CRTM1280x800)}, */ | ||
982 | |||
983 | /* Display : 1280x960 */ | ||
984 | {VIA_RES_1280X960, CRTM1280x960, ARRAY_SIZE(CRTM1280x960)}, | ||
985 | |||
986 | /* Display : 1280x1024 */ | ||
987 | {VIA_RES_1280X1024, CRTM1280x1024, ARRAY_SIZE(CRTM1280x1024)}, | ||
988 | |||
989 | /* Display : 1360x768 (CVT) */ | ||
990 | {VIA_RES_1360X768, CRTM1360x768, ARRAY_SIZE(CRTM1360x768)}, | ||
991 | |||
992 | /* Display : 1360x768 (CVT Reduce Blanking) */ | ||
993 | {VIA_RES_1360X768_RB, CRTM1360x768_RB, | ||
994 | ARRAY_SIZE(CRTM1360x768_RB)}, | ||
995 | |||
996 | /* Display : 1366x768 */ | ||
997 | {VIA_RES_1366X768, CRTM1366x768, ARRAY_SIZE(CRTM1366x768)}, | ||
998 | |||
999 | /* Display : 1368x768 (GTF) */ | ||
1000 | /*{ M1368x768,CRTM1368x768,ARRAY_SIZE(CRTM1368x768)}, */ | ||
1001 | /* Display : 1368x768 (GTF) */ | ||
1002 | {VIA_RES_1368X768, CRTM1368x768, ARRAY_SIZE(CRTM1368x768)}, | ||
1003 | |||
1004 | /* Display : 1440x900 (CVT) */ | ||
1005 | {VIA_RES_1440X900, CRTM1440x900, ARRAY_SIZE(CRTM1440x900)}, | ||
1006 | |||
1007 | /* Display : 1440x900 (CVT Reduce Blanking) */ | ||
1008 | {VIA_RES_1440X900_RB, CRTM1440x900_RB, | ||
1009 | ARRAY_SIZE(CRTM1440x900_RB)}, | ||
1010 | |||
1011 | /* Display : 1440x1050 (GTF) */ | ||
1012 | {VIA_RES_1440X1050, CRTM1440x1050, ARRAY_SIZE(CRTM1440x1050)}, | ||
1013 | |||
1014 | /* Display : 1400x1050 (CVT Reduce Blanking) */ | ||
1015 | {VIA_RES_1400X1050_RB, CRTM1400x1050_RB, | ||
1016 | ARRAY_SIZE(CRTM1400x1050_RB)}, | ||
1017 | |||
1018 | /* Display : 1600x900 (CVT) */ | ||
1019 | {VIA_RES_1600X900, CRTM1600x900, ARRAY_SIZE(CRTM1600x900)}, | ||
1020 | |||
1021 | /* Display : 1600x900 (CVT Reduce Blanking) */ | ||
1022 | {VIA_RES_1600X900_RB, CRTM1600x900_RB, | ||
1023 | ARRAY_SIZE(CRTM1600x900_RB)}, | ||
1024 | |||
1025 | /* Display : 1600x1024 (GTF) */ | ||
1026 | {VIA_RES_1600X1024, CRTM1600x1024, ARRAY_SIZE(CRTM1600x1024)}, | ||
1027 | |||
1028 | /* Display : 1600x1200 */ | ||
1029 | {VIA_RES_1600X1200, CRTM1600x1200, ARRAY_SIZE(CRTM1600x1200)}, | ||
1030 | |||
1031 | /* Display : 1680x1050 (CVT) */ | ||
1032 | {VIA_RES_1680X1050, CRTM1680x1050, ARRAY_SIZE(CRTM1680x1050)}, | ||
1033 | |||
1034 | /* Display : 1680x1050 (CVT Reduce Blanking) */ | ||
1035 | {VIA_RES_1680X1050_RB, CRTM1680x1050_RB, | ||
1036 | ARRAY_SIZE(CRTM1680x1050_RB)}, | ||
1037 | |||
1038 | /* Display : 1792x1344 (DMT) */ | ||
1039 | {VIA_RES_1792X1344, CRTM1792x1344, ARRAY_SIZE(CRTM1792x1344)}, | ||
1040 | |||
1041 | /* Display : 1856x1392 (DMT) */ | ||
1042 | {VIA_RES_1856X1392, CRTM1856x1392, ARRAY_SIZE(CRTM1856x1392)}, | ||
1043 | |||
1044 | /* Display : 1920x1440 */ | ||
1045 | {VIA_RES_1920X1440, CRTM1920x1440, ARRAY_SIZE(CRTM1920x1440)}, | ||
1046 | |||
1047 | /* Display : 2048x1536 */ | ||
1048 | {VIA_RES_2048X1536, CRTM2048x1536, ARRAY_SIZE(CRTM2048x1536)}, | ||
1049 | |||
1050 | /* Display : 1280x720 */ | ||
1051 | {VIA_RES_1280X720, CRTM1280x720, ARRAY_SIZE(CRTM1280x720)}, | ||
1052 | |||
1053 | /* Display : 1920x1080 (CVT) */ | ||
1054 | {VIA_RES_1920X1080, CRTM1920x1080, ARRAY_SIZE(CRTM1920x1080)}, | ||
1055 | |||
1056 | /* Display : 1920x1080 (CVT Reduce Blanking) */ | ||
1057 | {VIA_RES_1920X1080_RB, CRTM1920x1080_RB, | ||
1058 | ARRAY_SIZE(CRTM1920x1080_RB)}, | ||
1059 | |||
1060 | /* Display : 1920x1200 (CVT) */ | ||
1061 | {VIA_RES_1920X1200, CRTM1920x1200, ARRAY_SIZE(CRTM1920x1200)}, | ||
1062 | |||
1063 | /* Display : 1920x1200 (CVT Reduce Blanking) */ | ||
1064 | {VIA_RES_1920X1200_RB, CRTM1920x1200_RB, | ||
1065 | ARRAY_SIZE(CRTM1920x1200_RB)}, | ||
1066 | |||
1067 | /* Display : 1400x1050 (CVT) */ | ||
1068 | {VIA_RES_1400X1050, CRTM1400x1050, ARRAY_SIZE(CRTM1400x1050)} | ||
1069 | }; | ||
1070 | struct crt_mode_table CEAM1280x720[] = { | ||
1071 | {REFRESH_60, CLK_74_270M, M1280X720_CEA_R60_HSP, | ||
1072 | M1280X720_CEA_R60_VSP, | ||
1073 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
1074 | {1650, 1280, 1280, 370, 1390, 40, 750, 720, 720, 30, 725, 5} } | ||
1075 | }; | ||
1076 | struct crt_mode_table CEAM1920x1080[] = { | ||
1077 | {REFRESH_60, CLK_148_500M, M1920X1080_CEA_R60_HSP, | ||
1078 | M1920X1080_CEA_R60_VSP, | ||
1079 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
1080 | {2200, 1920, 1920, 300, 2008, 44, 1125, 1080, 1080, 45, 1084, 5} } | ||
1081 | }; | ||
1082 | struct VideoModeTable CEA_HDMI_Modes[] = { | ||
1083 | /* Display : 1280x720 */ | ||
1084 | {VIA_RES_1280X720, CEAM1280x720, ARRAY_SIZE(CEAM1280x720)}, | ||
1085 | {VIA_RES_1920X1080, CEAM1920x1080, ARRAY_SIZE(CEAM1920x1080)} | ||
1086 | }; | ||
diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h new file mode 100644 index 000000000000..1a5de50a23a2 --- /dev/null +++ b/drivers/video/via/viamode.h | |||
@@ -0,0 +1,177 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef __VIAMODE_H__ | ||
23 | #define __VIAMODE_H__ | ||
24 | |||
25 | #include "global.h" | ||
26 | |||
27 | struct VPITTable { | ||
28 | unsigned char Misc; | ||
29 | unsigned char SR[StdSR]; | ||
30 | unsigned char GR[StdGR]; | ||
31 | unsigned char AR[StdAR]; | ||
32 | }; | ||
33 | |||
34 | struct VideoModeTable { | ||
35 | int ModeIndex; | ||
36 | struct crt_mode_table *crtc; | ||
37 | int mode_array; | ||
38 | }; | ||
39 | |||
40 | struct patch_table { | ||
41 | int mode_index; | ||
42 | int table_length; | ||
43 | struct io_reg *io_reg_table; | ||
44 | }; | ||
45 | |||
46 | struct res_map_refresh { | ||
47 | int hres; | ||
48 | int vres; | ||
49 | int pixclock; | ||
50 | int vmode_refresh; | ||
51 | }; | ||
52 | |||
53 | #define NUM_TOTAL_RES_MAP_REFRESH ARRAY_SIZE(res_map_refresh_tbl) | ||
54 | #define NUM_TOTAL_CEA_MODES ARRAY_SIZE(CEA_HDMI_Modes) | ||
55 | #define NUM_TOTAL_CN400_ModeXregs ARRAY_SIZE(CN400_ModeXregs) | ||
56 | #define NUM_TOTAL_CN700_ModeXregs ARRAY_SIZE(CN700_ModeXregs) | ||
57 | #define NUM_TOTAL_KM400_ModeXregs ARRAY_SIZE(KM400_ModeXregs) | ||
58 | #define NUM_TOTAL_CX700_ModeXregs ARRAY_SIZE(CX700_ModeXregs) | ||
59 | #define NUM_TOTAL_VX800_ModeXregs ARRAY_SIZE(VX800_ModeXregs) | ||
60 | #define NUM_TOTAL_CLE266_ModeXregs ARRAY_SIZE(CLE266_ModeXregs) | ||
61 | #define NUM_TOTAL_PATCH_MODE ARRAY_SIZE(res_patch_table) | ||
62 | #define NUM_TOTAL_MODETABLE ARRAY_SIZE(CLE266Modes) | ||
63 | |||
64 | /********************/ | ||
65 | /* Mode Table */ | ||
66 | /********************/ | ||
67 | |||
68 | /* 480x640 */ | ||
69 | extern struct crt_mode_table CRTM480x640[1]; | ||
70 | /* 640x480*/ | ||
71 | extern struct crt_mode_table CRTM640x480[5]; | ||
72 | /*720x480 (GTF)*/ | ||
73 | extern struct crt_mode_table CRTM720x480[1]; | ||
74 | /*720x576 (GTF)*/ | ||
75 | extern struct crt_mode_table CRTM720x576[1]; | ||
76 | /* 800x480 (CVT) */ | ||
77 | extern struct crt_mode_table CRTM800x480[1]; | ||
78 | /* 800x600*/ | ||
79 | extern struct crt_mode_table CRTM800x600[5]; | ||
80 | /* 848x480 (CVT) */ | ||
81 | extern struct crt_mode_table CRTM848x480[1]; | ||
82 | /*856x480 (GTF) convert to 852x480*/ | ||
83 | extern struct crt_mode_table CRTM852x480[1]; | ||
84 | /*1024x512 (GTF)*/ | ||
85 | extern struct crt_mode_table CRTM1024x512[1]; | ||
86 | /* 1024x600*/ | ||
87 | extern struct crt_mode_table CRTM1024x600[1]; | ||
88 | /* 1024x768*/ | ||
89 | extern struct crt_mode_table CRTM1024x768[4]; | ||
90 | /* 1152x864*/ | ||
91 | extern struct crt_mode_table CRTM1152x864[1]; | ||
92 | /* 1280x720 (HDMI 720P)*/ | ||
93 | extern struct crt_mode_table CRTM1280x720[2]; | ||
94 | /*1280x768 (GTF)*/ | ||
95 | extern struct crt_mode_table CRTM1280x768[2]; | ||
96 | /* 1280x800 (CVT) */ | ||
97 | extern struct crt_mode_table CRTM1280x800[1]; | ||
98 | /*1280x960*/ | ||
99 | extern struct crt_mode_table CRTM1280x960[1]; | ||
100 | /* 1280x1024*/ | ||
101 | extern struct crt_mode_table CRTM1280x1024[3]; | ||
102 | /* 1368x768 (GTF) */ | ||
103 | extern struct crt_mode_table CRTM1368x768[1]; | ||
104 | /*1440x1050 (GTF)*/ | ||
105 | extern struct crt_mode_table CRTM1440x1050[1]; | ||
106 | /* 1600x1200*/ | ||
107 | extern struct crt_mode_table CRTM1600x1200[2]; | ||
108 | /* 1680x1050 (CVT) */ | ||
109 | extern struct crt_mode_table CRTM1680x1050[2]; | ||
110 | /* 1680x1050 (CVT Reduce Blanking) */ | ||
111 | extern struct crt_mode_table CRTM1680x1050_RB[1]; | ||
112 | /* 1920x1080 (CVT)*/ | ||
113 | extern struct crt_mode_table CRTM1920x1080[1]; | ||
114 | /* 1920x1080 (CVT with Reduce Blanking) */ | ||
115 | extern struct crt_mode_table CRTM1920x1080_RB[1]; | ||
116 | /* 1920x1440*/ | ||
117 | extern struct crt_mode_table CRTM1920x1440[2]; | ||
118 | /* 1400x1050 (CVT) */ | ||
119 | extern struct crt_mode_table CRTM1400x1050[2]; | ||
120 | /* 1400x1050 (CVT Reduce Blanking) */ | ||
121 | extern struct crt_mode_table CRTM1400x1050_RB[1]; | ||
122 | /* 960x600 (CVT) */ | ||
123 | extern struct crt_mode_table CRTM960x600[1]; | ||
124 | /* 1000x600 (GTF) */ | ||
125 | extern struct crt_mode_table CRTM1000x600[1]; | ||
126 | /* 1024x576 (GTF) */ | ||
127 | extern struct crt_mode_table CRTM1024x576[1]; | ||
128 | /* 1088x612 (CVT) */ | ||
129 | extern struct crt_mode_table CRTM1088x612[1]; | ||
130 | /* 1152x720 (CVT) */ | ||
131 | extern struct crt_mode_table CRTM1152x720[1]; | ||
132 | /* 1200x720 (GTF) */ | ||
133 | extern struct crt_mode_table CRTM1200x720[1]; | ||
134 | /* 1280x600 (GTF) */ | ||
135 | extern struct crt_mode_table CRTM1280x600[1]; | ||
136 | /* 1360x768 (CVT) */ | ||
137 | extern struct crt_mode_table CRTM1360x768[1]; | ||
138 | /* 1360x768 (CVT Reduce Blanking) */ | ||
139 | extern struct crt_mode_table CRTM1360x768_RB[1]; | ||
140 | /* 1366x768 (GTF) */ | ||
141 | extern struct crt_mode_table CRTM1366x768[2]; | ||
142 | /* 1440x900 (CVT) */ | ||
143 | extern struct crt_mode_table CRTM1440x900[2]; | ||
144 | /* 1440x900 (CVT Reduce Blanking) */ | ||
145 | extern struct crt_mode_table CRTM1440x900_RB[1]; | ||
146 | /* 1600x900 (CVT) */ | ||
147 | extern struct crt_mode_table CRTM1600x900[1]; | ||
148 | /* 1600x900 (CVT Reduce Blanking) */ | ||
149 | extern struct crt_mode_table CRTM1600x900_RB[1]; | ||
150 | /* 1600x1024 (GTF) */ | ||
151 | extern struct crt_mode_table CRTM1600x1024[1]; | ||
152 | /* 1792x1344 (DMT) */ | ||
153 | extern struct crt_mode_table CRTM1792x1344[1]; | ||
154 | /* 1856x1392 (DMT) */ | ||
155 | extern struct crt_mode_table CRTM1856x1392[1]; | ||
156 | /* 1920x1200 (CVT) */ | ||
157 | extern struct crt_mode_table CRTM1920x1200[1]; | ||
158 | /* 1920x1200 (CVT with Reduce Blanking) */ | ||
159 | extern struct crt_mode_table CRTM1920x1200_RB[1]; | ||
160 | /* 2048x1536 (CVT) */ | ||
161 | extern struct crt_mode_table CRTM2048x1536[1]; | ||
162 | extern struct VideoModeTable CLE266Modes[47]; | ||
163 | extern struct crt_mode_table CEAM1280x720[1]; | ||
164 | extern struct crt_mode_table CEAM1920x1080[1]; | ||
165 | extern struct VideoModeTable CEA_HDMI_Modes[2]; | ||
166 | |||
167 | extern struct res_map_refresh res_map_refresh_tbl[61]; | ||
168 | extern struct io_reg CN400_ModeXregs[52]; | ||
169 | extern struct io_reg CN700_ModeXregs[66]; | ||
170 | extern struct io_reg KM400_ModeXregs[55]; | ||
171 | extern struct io_reg CX700_ModeXregs[58]; | ||
172 | extern struct io_reg VX800_ModeXregs[58]; | ||
173 | extern struct io_reg CLE266_ModeXregs[32]; | ||
174 | extern struct io_reg PM1024x768[2]; | ||
175 | extern struct patch_table res_patch_table[1]; | ||
176 | extern struct VPITTable VPIT; | ||
177 | #endif /* __VIAMODE_H__ */ | ||
diff --git a/drivers/video/via/vt1636.c b/drivers/video/via/vt1636.c new file mode 100644 index 000000000000..322a9f993550 --- /dev/null +++ b/drivers/video/via/vt1636.c | |||
@@ -0,0 +1,306 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #include "global.h" | ||
23 | |||
24 | u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information | ||
25 | *plvds_setting_info, struct lvds_chip_information *plvds_chip_info, | ||
26 | u8 index) | ||
27 | { | ||
28 | u8 data; | ||
29 | |||
30 | viaparinfo->i2c_stuff.i2c_port = plvds_chip_info->i2c_port; | ||
31 | viafb_i2c_readbyte(plvds_chip_info->lvds_chip_slave_addr, index, &data); | ||
32 | |||
33 | return data; | ||
34 | } | ||
35 | |||
36 | void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information | ||
37 | *plvds_setting_info, struct lvds_chip_information | ||
38 | *plvds_chip_info, struct IODATA io_data) | ||
39 | { | ||
40 | int index, data; | ||
41 | |||
42 | viaparinfo->i2c_stuff.i2c_port = plvds_chip_info->i2c_port; | ||
43 | |||
44 | index = io_data.Index; | ||
45 | data = viafb_gpio_i2c_read_lvds(plvds_setting_info, plvds_chip_info, | ||
46 | index); | ||
47 | data = (data & (~io_data.Mask)) | io_data.Data; | ||
48 | |||
49 | viafb_i2c_writebyte(plvds_chip_info->lvds_chip_slave_addr, index, data); | ||
50 | } | ||
51 | |||
52 | void viafb_init_lvds_vt1636(struct lvds_setting_information | ||
53 | *plvds_setting_info, struct lvds_chip_information *plvds_chip_info) | ||
54 | { | ||
55 | int reg_num, i; | ||
56 | |||
57 | /* Common settings: */ | ||
58 | reg_num = ARRAY_SIZE(COMMON_INIT_TBL_VT1636); | ||
59 | |||
60 | for (i = 0; i < reg_num; i++) { | ||
61 | viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, | ||
62 | plvds_chip_info, | ||
63 | COMMON_INIT_TBL_VT1636[i]); | ||
64 | } | ||
65 | |||
66 | /* Input Data Mode Select */ | ||
67 | if (plvds_setting_info->device_lcd_dualedge) { | ||
68 | viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, | ||
69 | plvds_chip_info, | ||
70 | DUAL_CHANNEL_ENABLE_TBL_VT1636[0]); | ||
71 | } else { | ||
72 | viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, | ||
73 | plvds_chip_info, | ||
74 | SINGLE_CHANNEL_ENABLE_TBL_VT1636[0]); | ||
75 | } | ||
76 | |||
77 | if (plvds_setting_info->LCDDithering) { | ||
78 | viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, | ||
79 | plvds_chip_info, | ||
80 | DITHERING_ENABLE_TBL_VT1636[0]); | ||
81 | } else { | ||
82 | viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, | ||
83 | plvds_chip_info, | ||
84 | DITHERING_DISABLE_TBL_VT1636[0]); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | void viafb_enable_lvds_vt1636(struct lvds_setting_information | ||
89 | *plvds_setting_info, | ||
90 | struct lvds_chip_information *plvds_chip_info) | ||
91 | { | ||
92 | |||
93 | viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info, | ||
94 | VDD_ON_TBL_VT1636[0]); | ||
95 | |||
96 | /* Pad on: */ | ||
97 | switch (plvds_chip_info->output_interface) { | ||
98 | case INTERFACE_DVP0: | ||
99 | { | ||
100 | viafb_write_reg_mask(SR1E, VIASR, 0xC0, 0xC0); | ||
101 | break; | ||
102 | } | ||
103 | |||
104 | case INTERFACE_DVP1: | ||
105 | { | ||
106 | viafb_write_reg_mask(SR1E, VIASR, 0x30, 0x30); | ||
107 | break; | ||
108 | } | ||
109 | |||
110 | case INTERFACE_DFP_LOW: | ||
111 | { | ||
112 | viafb_write_reg_mask(SR2A, VIASR, 0x03, 0x03); | ||
113 | break; | ||
114 | } | ||
115 | |||
116 | case INTERFACE_DFP_HIGH: | ||
117 | { | ||
118 | viafb_write_reg_mask(SR2A, VIASR, 0x03, 0x0C); | ||
119 | break; | ||
120 | } | ||
121 | |||
122 | } | ||
123 | } | ||
124 | |||
125 | void viafb_disable_lvds_vt1636(struct lvds_setting_information | ||
126 | *plvds_setting_info, | ||
127 | struct lvds_chip_information *plvds_chip_info) | ||
128 | { | ||
129 | |||
130 | viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info, | ||
131 | VDD_OFF_TBL_VT1636[0]); | ||
132 | |||
133 | /* Pad off: */ | ||
134 | switch (plvds_chip_info->output_interface) { | ||
135 | case INTERFACE_DVP0: | ||
136 | { | ||
137 | viafb_write_reg_mask(SR1E, VIASR, 0x00, 0xC0); | ||
138 | break; | ||
139 | } | ||
140 | |||
141 | case INTERFACE_DVP1: | ||
142 | { | ||
143 | viafb_write_reg_mask(SR1E, VIASR, 0x00, 0x30); | ||
144 | break; | ||
145 | } | ||
146 | |||
147 | case INTERFACE_DFP_LOW: | ||
148 | { | ||
149 | viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x03); | ||
150 | break; | ||
151 | } | ||
152 | |||
153 | case INTERFACE_DFP_HIGH: | ||
154 | { | ||
155 | viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x0C); | ||
156 | break; | ||
157 | } | ||
158 | |||
159 | } | ||
160 | } | ||
161 | |||
162 | bool viafb_lvds_identify_vt1636(void) | ||
163 | { | ||
164 | u8 Buffer[2]; | ||
165 | |||
166 | DEBUG_MSG(KERN_INFO "viafb_lvds_identify_vt1636.\n"); | ||
167 | |||
168 | /* Sense VT1636 LVDS Transmiter */ | ||
169 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr = | ||
170 | VT1636_LVDS_I2C_ADDR; | ||
171 | |||
172 | /* Check vendor ID first: */ | ||
173 | viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info. | ||
174 | lvds_chip_slave_addr, | ||
175 | 0x00, &Buffer[0]); | ||
176 | viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info. | ||
177 | lvds_chip_slave_addr, | ||
178 | 0x01, &Buffer[1]); | ||
179 | |||
180 | if (!((Buffer[0] == 0x06) && (Buffer[1] == 0x11))) | ||
181 | return false; | ||
182 | |||
183 | /* Check Chip ID: */ | ||
184 | viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info. | ||
185 | lvds_chip_slave_addr, | ||
186 | 0x02, &Buffer[0]); | ||
187 | viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info. | ||
188 | lvds_chip_slave_addr, | ||
189 | 0x03, &Buffer[1]); | ||
190 | if ((Buffer[0] == 0x45) && (Buffer[1] == 0x33)) { | ||
191 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = | ||
192 | VT1636_LVDS; | ||
193 | return true; | ||
194 | } | ||
195 | |||
196 | return false; | ||
197 | } | ||
198 | |||
199 | static int get_clk_range_index(u32 Clk) | ||
200 | { | ||
201 | if (Clk < DPA_CLK_30M) | ||
202 | return DPA_CLK_RANGE_30M; | ||
203 | else if (Clk < DPA_CLK_50M) | ||
204 | return DPA_CLK_RANGE_30_50M; | ||
205 | else if (Clk < DPA_CLK_70M) | ||
206 | return DPA_CLK_RANGE_50_70M; | ||
207 | else if (Clk < DPA_CLK_100M) | ||
208 | return DPA_CLK_RANGE_70_100M; | ||
209 | else if (Clk < DPA_CLK_150M) | ||
210 | return DPA_CLK_RANGE_100_150M; | ||
211 | else | ||
212 | return DPA_CLK_RANGE_150M; | ||
213 | } | ||
214 | |||
215 | static int get_lvds_dpa_setting_index(int panel_size_id, | ||
216 | struct VT1636_DPA_SETTING *p_vt1636_dpasetting_tbl, | ||
217 | int tbl_size) | ||
218 | { | ||
219 | int i; | ||
220 | |||
221 | for (i = 0; i < tbl_size; i++) { | ||
222 | if (panel_size_id == p_vt1636_dpasetting_tbl->PanelSizeID) | ||
223 | return i; | ||
224 | |||
225 | p_vt1636_dpasetting_tbl++; | ||
226 | } | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static void set_dpa_vt1636(struct lvds_setting_information | ||
232 | *plvds_setting_info, struct lvds_chip_information *plvds_chip_info, | ||
233 | struct VT1636_DPA_SETTING *p_vt1636_dpa_setting) | ||
234 | { | ||
235 | struct IODATA io_data; | ||
236 | |||
237 | io_data.Index = 0x09; | ||
238 | io_data.Mask = 0x1F; | ||
239 | io_data.Data = p_vt1636_dpa_setting->CLK_SEL_ST1; | ||
240 | viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, | ||
241 | plvds_chip_info, io_data); | ||
242 | |||
243 | io_data.Index = 0x08; | ||
244 | io_data.Mask = 0x0F; | ||
245 | io_data.Data = p_vt1636_dpa_setting->CLK_SEL_ST2; | ||
246 | viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info, | ||
247 | io_data); | ||
248 | } | ||
249 | |||
250 | void viafb_vt1636_patch_skew_on_vt3324( | ||
251 | struct lvds_setting_information *plvds_setting_info, | ||
252 | struct lvds_chip_information *plvds_chip_info) | ||
253 | { | ||
254 | int index, size; | ||
255 | |||
256 | DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3324.\n"); | ||
257 | |||
258 | /* Graphics DPA settings: */ | ||
259 | index = get_clk_range_index(plvds_setting_info->vclk); | ||
260 | viafb_set_dpa_gfx(plvds_chip_info->output_interface, | ||
261 | &GFX_DPA_SETTING_TBL_VT3324[index]); | ||
262 | |||
263 | /* LVDS Transmitter DPA settings: */ | ||
264 | size = ARRAY_SIZE(VT1636_DPA_SETTING_TBL_VT3324); | ||
265 | index = | ||
266 | get_lvds_dpa_setting_index(plvds_setting_info->lcd_panel_id, | ||
267 | VT1636_DPA_SETTING_TBL_VT3324, size); | ||
268 | set_dpa_vt1636(plvds_setting_info, plvds_chip_info, | ||
269 | &VT1636_DPA_SETTING_TBL_VT3324[index]); | ||
270 | } | ||
271 | |||
272 | void viafb_vt1636_patch_skew_on_vt3327( | ||
273 | struct lvds_setting_information *plvds_setting_info, | ||
274 | struct lvds_chip_information *plvds_chip_info) | ||
275 | { | ||
276 | int index, size; | ||
277 | |||
278 | DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3327.\n"); | ||
279 | |||
280 | /* Graphics DPA settings: */ | ||
281 | index = get_clk_range_index(plvds_setting_info->vclk); | ||
282 | viafb_set_dpa_gfx(plvds_chip_info->output_interface, | ||
283 | &GFX_DPA_SETTING_TBL_VT3327[index]); | ||
284 | |||
285 | /* LVDS Transmitter DPA settings: */ | ||
286 | size = ARRAY_SIZE(VT1636_DPA_SETTING_TBL_VT3327); | ||
287 | index = | ||
288 | get_lvds_dpa_setting_index(plvds_setting_info->lcd_panel_id, | ||
289 | VT1636_DPA_SETTING_TBL_VT3327, size); | ||
290 | set_dpa_vt1636(plvds_setting_info, plvds_chip_info, | ||
291 | &VT1636_DPA_SETTING_TBL_VT3327[index]); | ||
292 | } | ||
293 | |||
294 | void viafb_vt1636_patch_skew_on_vt3364( | ||
295 | struct lvds_setting_information *plvds_setting_info, | ||
296 | struct lvds_chip_information *plvds_chip_info) | ||
297 | { | ||
298 | int index; | ||
299 | |||
300 | DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3364.\n"); | ||
301 | |||
302 | /* Graphics DPA settings: */ | ||
303 | index = get_clk_range_index(plvds_setting_info->vclk); | ||
304 | viafb_set_dpa_gfx(plvds_chip_info->output_interface, | ||
305 | &GFX_DPA_SETTING_TBL_VT3364[index]); | ||
306 | } | ||
diff --git a/drivers/video/via/vt1636.h b/drivers/video/via/vt1636.h new file mode 100644 index 000000000000..2a150c58c7ed --- /dev/null +++ b/drivers/video/via/vt1636.h | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
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 | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef _VT1636_H_ | ||
23 | #define _VT1636_H_ | ||
24 | #include "chip.h" | ||
25 | bool viafb_lvds_identify_vt1636(void); | ||
26 | void viafb_init_lvds_vt1636(struct lvds_setting_information | ||
27 | *plvds_setting_info, struct lvds_chip_information *plvds_chip_info); | ||
28 | void viafb_enable_lvds_vt1636(struct lvds_setting_information | ||
29 | *plvds_setting_info, | ||
30 | struct lvds_chip_information *plvds_chip_info); | ||
31 | void viafb_disable_lvds_vt1636(struct lvds_setting_information | ||
32 | *plvds_setting_info, | ||
33 | struct lvds_chip_information *plvds_chip_info); | ||
34 | void viafb_vt1636_patch_skew_on_vt3324( | ||
35 | struct lvds_setting_information *plvds_setting_info, | ||
36 | struct lvds_chip_information *plvds_chip_info); | ||
37 | void viafb_vt1636_patch_skew_on_vt3327( | ||
38 | struct lvds_setting_information *plvds_setting_info, | ||
39 | struct lvds_chip_information *plvds_chip_info); | ||
40 | void viafb_vt1636_patch_skew_on_vt3364( | ||
41 | struct lvds_setting_information *plvds_setting_info, | ||
42 | struct lvds_chip_information *plvds_chip_info); | ||
43 | |||
44 | #endif | ||
diff --git a/drivers/w1/masters/ds1wm.c b/drivers/w1/masters/ds1wm.c index 10211e493001..29e144f81cbe 100644 --- a/drivers/w1/masters/ds1wm.c +++ b/drivers/w1/masters/ds1wm.c | |||
@@ -160,8 +160,10 @@ static int ds1wm_reset(struct ds1wm_data *ds1wm_data) | |||
160 | * 625 us - 60 us - 240 us - 100 ns = 324.9 us | 160 | * 625 us - 60 us - 240 us - 100 ns = 324.9 us |
161 | * | 161 | * |
162 | * We'll wait a bit longer just to be sure. | 162 | * We'll wait a bit longer just to be sure. |
163 | * Was udelay(500), but if it is going to busywait the cpu that long, | ||
164 | * might as well come back later. | ||
163 | */ | 165 | */ |
164 | udelay(500); | 166 | msleep(1); |
165 | 167 | ||
166 | ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, | 168 | ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, |
167 | DS1WM_INTEN_ERBF | DS1WM_INTEN_ETMT | DS1WM_INTEN_EPD | | 169 | DS1WM_INTEN_ERBF | DS1WM_INTEN_ETMT | DS1WM_INTEN_EPD | |
@@ -274,8 +276,8 @@ static u8 ds1wm_reset_bus(void *data) | |||
274 | return 0; | 276 | return 0; |
275 | } | 277 | } |
276 | 278 | ||
277 | static void ds1wm_search(void *data, u8 search_type, | 279 | static void ds1wm_search(void *data, struct w1_master *master_dev, |
278 | w1_slave_found_callback slave_found) | 280 | u8 search_type, w1_slave_found_callback slave_found) |
279 | { | 281 | { |
280 | struct ds1wm_data *ds1wm_data = data; | 282 | struct ds1wm_data *ds1wm_data = data; |
281 | int i; | 283 | int i; |
@@ -313,7 +315,7 @@ static void ds1wm_search(void *data, u8 search_type, | |||
313 | ds1wm_write_register(ds1wm_data, DS1WM_CMD, ~DS1WM_CMD_SRA); | 315 | ds1wm_write_register(ds1wm_data, DS1WM_CMD, ~DS1WM_CMD_SRA); |
314 | ds1wm_reset(ds1wm_data); | 316 | ds1wm_reset(ds1wm_data); |
315 | 317 | ||
316 | slave_found(ds1wm_data, rom_id); | 318 | slave_found(master_dev, rom_id); |
317 | } | 319 | } |
318 | 320 | ||
319 | /* --------------------------------------------------------------------- */ | 321 | /* --------------------------------------------------------------------- */ |
diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c index b63b5e044a4c..59ad6e95af8f 100644 --- a/drivers/w1/masters/ds2490.c +++ b/drivers/w1/masters/ds2490.c | |||
@@ -88,7 +88,7 @@ | |||
88 | #define COMM_DT 0x2000 | 88 | #define COMM_DT 0x2000 |
89 | #define COMM_SPU 0x1000 | 89 | #define COMM_SPU 0x1000 |
90 | #define COMM_F 0x0800 | 90 | #define COMM_F 0x0800 |
91 | #define COMM_NTP 0x0400 | 91 | #define COMM_NTF 0x0400 |
92 | #define COMM_ICP 0x0200 | 92 | #define COMM_ICP 0x0200 |
93 | #define COMM_RST 0x0100 | 93 | #define COMM_RST 0x0100 |
94 | 94 | ||
@@ -98,11 +98,6 @@ | |||
98 | #define BRANCH_MAIN 0xCC | 98 | #define BRANCH_MAIN 0xCC |
99 | #define BRANCH_AUX 0x33 | 99 | #define BRANCH_AUX 0x33 |
100 | 100 | ||
101 | /* | ||
102 | * Duration of the strong pull-up pulse in milliseconds. | ||
103 | */ | ||
104 | #define PULLUP_PULSE_DURATION 750 | ||
105 | |||
106 | /* Status flags */ | 101 | /* Status flags */ |
107 | #define ST_SPUA 0x01 /* Strong Pull-up is active */ | 102 | #define ST_SPUA 0x01 /* Strong Pull-up is active */ |
108 | #define ST_PRGA 0x02 /* 12V programming pulse is being generated */ | 103 | #define ST_PRGA 0x02 /* 12V programming pulse is being generated */ |
@@ -112,6 +107,17 @@ | |||
112 | #define ST_IDLE 0x20 /* DS2490 is currently idle */ | 107 | #define ST_IDLE 0x20 /* DS2490 is currently idle */ |
113 | #define ST_EPOF 0x80 | 108 | #define ST_EPOF 0x80 |
114 | 109 | ||
110 | /* Result Register flags */ | ||
111 | #define RR_DETECT 0xA5 /* New device detected */ | ||
112 | #define RR_NRS 0x01 /* Reset no presence or ... */ | ||
113 | #define RR_SH 0x02 /* short on reset or set path */ | ||
114 | #define RR_APP 0x04 /* alarming presence on reset */ | ||
115 | #define RR_VPP 0x08 /* 12V expected not seen */ | ||
116 | #define RR_CMP 0x10 /* compare error */ | ||
117 | #define RR_CRC 0x20 /* CRC error detected */ | ||
118 | #define RR_RDP 0x40 /* redirected page */ | ||
119 | #define RR_EOS 0x80 /* end of search error */ | ||
120 | |||
115 | #define SPEED_NORMAL 0x00 | 121 | #define SPEED_NORMAL 0x00 |
116 | #define SPEED_FLEXIBLE 0x01 | 122 | #define SPEED_FLEXIBLE 0x01 |
117 | #define SPEED_OVERDRIVE 0x02 | 123 | #define SPEED_OVERDRIVE 0x02 |
@@ -131,6 +137,15 @@ struct ds_device | |||
131 | 137 | ||
132 | int ep[NUM_EP]; | 138 | int ep[NUM_EP]; |
133 | 139 | ||
140 | /* Strong PullUp | ||
141 | * 0: pullup not active, else duration in milliseconds | ||
142 | */ | ||
143 | int spu_sleep; | ||
144 | /* spu_bit contains COMM_SPU or 0 depending on if the strong pullup | ||
145 | * should be active or not for writes. | ||
146 | */ | ||
147 | u16 spu_bit; | ||
148 | |||
134 | struct w1_bus_master master; | 149 | struct w1_bus_master master; |
135 | }; | 150 | }; |
136 | 151 | ||
@@ -164,7 +179,6 @@ MODULE_DEVICE_TABLE(usb, ds_id_table); | |||
164 | static int ds_probe(struct usb_interface *, const struct usb_device_id *); | 179 | static int ds_probe(struct usb_interface *, const struct usb_device_id *); |
165 | static void ds_disconnect(struct usb_interface *); | 180 | static void ds_disconnect(struct usb_interface *); |
166 | 181 | ||
167 | static inline void ds_dump_status(unsigned char *, unsigned char *, int); | ||
168 | static int ds_send_control(struct ds_device *, u16, u16); | 182 | static int ds_send_control(struct ds_device *, u16, u16); |
169 | static int ds_send_control_cmd(struct ds_device *, u16, u16); | 183 | static int ds_send_control_cmd(struct ds_device *, u16, u16); |
170 | 184 | ||
@@ -192,7 +206,7 @@ static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index) | |||
192 | 206 | ||
193 | return err; | 207 | return err; |
194 | } | 208 | } |
195 | #if 0 | 209 | |
196 | static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index) | 210 | static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index) |
197 | { | 211 | { |
198 | int err; | 212 | int err; |
@@ -207,7 +221,7 @@ static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index) | |||
207 | 221 | ||
208 | return err; | 222 | return err; |
209 | } | 223 | } |
210 | #endif | 224 | |
211 | static int ds_send_control(struct ds_device *dev, u16 value, u16 index) | 225 | static int ds_send_control(struct ds_device *dev, u16 value, u16 index) |
212 | { | 226 | { |
213 | int err; | 227 | int err; |
@@ -223,11 +237,6 @@ static int ds_send_control(struct ds_device *dev, u16 value, u16 index) | |||
223 | return err; | 237 | return err; |
224 | } | 238 | } |
225 | 239 | ||
226 | static inline void ds_dump_status(unsigned char *buf, unsigned char *str, int off) | ||
227 | { | ||
228 | printk("%45s: %8x\n", str, buf[off]); | ||
229 | } | ||
230 | |||
231 | static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st, | 240 | static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st, |
232 | unsigned char *buf, int size) | 241 | unsigned char *buf, int size) |
233 | { | 242 | { |
@@ -248,62 +257,81 @@ static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st, | |||
248 | return count; | 257 | return count; |
249 | } | 258 | } |
250 | 259 | ||
251 | static int ds_recv_status(struct ds_device *dev, struct ds_status *st) | 260 | static inline void ds_print_msg(unsigned char *buf, unsigned char *str, int off) |
252 | { | 261 | { |
253 | unsigned char buf[64]; | 262 | printk(KERN_INFO "%45s: %8x\n", str, buf[off]); |
254 | int count, err = 0, i; | 263 | } |
255 | |||
256 | memcpy(st, buf, sizeof(*st)); | ||
257 | 264 | ||
258 | count = ds_recv_status_nodump(dev, st, buf, sizeof(buf)); | 265 | static void ds_dump_status(struct ds_device *dev, unsigned char *buf, int count) |
259 | if (count < 0) | 266 | { |
260 | return err; | 267 | int i; |
261 | 268 | ||
262 | printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], count); | 269 | printk(KERN_INFO "0x%x: count=%d, status: ", dev->ep[EP_STATUS], count); |
263 | for (i=0; i<count; ++i) | 270 | for (i=0; i<count; ++i) |
264 | printk("%02x ", buf[i]); | 271 | printk("%02x ", buf[i]); |
265 | printk("\n"); | 272 | printk(KERN_INFO "\n"); |
266 | 273 | ||
267 | if (count >= 16) { | 274 | if (count >= 16) { |
268 | ds_dump_status(buf, "enable flag", 0); | 275 | ds_print_msg(buf, "enable flag", 0); |
269 | ds_dump_status(buf, "1-wire speed", 1); | 276 | ds_print_msg(buf, "1-wire speed", 1); |
270 | ds_dump_status(buf, "strong pullup duration", 2); | 277 | ds_print_msg(buf, "strong pullup duration", 2); |
271 | ds_dump_status(buf, "programming pulse duration", 3); | 278 | ds_print_msg(buf, "programming pulse duration", 3); |
272 | ds_dump_status(buf, "pulldown slew rate control", 4); | 279 | ds_print_msg(buf, "pulldown slew rate control", 4); |
273 | ds_dump_status(buf, "write-1 low time", 5); | 280 | ds_print_msg(buf, "write-1 low time", 5); |
274 | ds_dump_status(buf, "data sample offset/write-0 recovery time", 6); | 281 | ds_print_msg(buf, "data sample offset/write-0 recovery time", |
275 | ds_dump_status(buf, "reserved (test register)", 7); | 282 | 6); |
276 | ds_dump_status(buf, "device status flags", 8); | 283 | ds_print_msg(buf, "reserved (test register)", 7); |
277 | ds_dump_status(buf, "communication command byte 1", 9); | 284 | ds_print_msg(buf, "device status flags", 8); |
278 | ds_dump_status(buf, "communication command byte 2", 10); | 285 | ds_print_msg(buf, "communication command byte 1", 9); |
279 | ds_dump_status(buf, "communication command buffer status", 11); | 286 | ds_print_msg(buf, "communication command byte 2", 10); |
280 | ds_dump_status(buf, "1-wire data output buffer status", 12); | 287 | ds_print_msg(buf, "communication command buffer status", 11); |
281 | ds_dump_status(buf, "1-wire data input buffer status", 13); | 288 | ds_print_msg(buf, "1-wire data output buffer status", 12); |
282 | ds_dump_status(buf, "reserved", 14); | 289 | ds_print_msg(buf, "1-wire data input buffer status", 13); |
283 | ds_dump_status(buf, "reserved", 15); | 290 | ds_print_msg(buf, "reserved", 14); |
291 | ds_print_msg(buf, "reserved", 15); | ||
284 | } | 292 | } |
285 | 293 | for (i = 16; i < count; ++i) { | |
286 | memcpy(st, buf, sizeof(*st)); | 294 | if (buf[i] == RR_DETECT) { |
287 | 295 | ds_print_msg(buf, "new device detect", i); | |
288 | if (st->status & ST_EPOF) { | 296 | continue; |
289 | printk(KERN_INFO "Resetting device after ST_EPOF.\n"); | 297 | } |
290 | err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); | 298 | ds_print_msg(buf, "Result Register Value: ", i); |
291 | if (err) | 299 | if (buf[i] & RR_NRS) |
292 | return err; | 300 | printk(KERN_INFO "NRS: Reset no presence or ...\n"); |
293 | count = ds_recv_status_nodump(dev, st, buf, sizeof(buf)); | 301 | if (buf[i] & RR_SH) |
294 | if (count < 0) | 302 | printk(KERN_INFO "SH: short on reset or set path\n"); |
295 | return err; | 303 | if (buf[i] & RR_APP) |
296 | } | 304 | printk(KERN_INFO "APP: alarming presence on reset\n"); |
297 | #if 0 | 305 | if (buf[i] & RR_VPP) |
298 | if (st->status & ST_IDLE) { | 306 | printk(KERN_INFO "VPP: 12V expected not seen\n"); |
299 | printk(KERN_INFO "Resetting pulse after ST_IDLE.\n"); | 307 | if (buf[i] & RR_CMP) |
300 | err = ds_start_pulse(dev, PULLUP_PULSE_DURATION); | 308 | printk(KERN_INFO "CMP: compare error\n"); |
301 | if (err) | 309 | if (buf[i] & RR_CRC) |
302 | return err; | 310 | printk(KERN_INFO "CRC: CRC error detected\n"); |
311 | if (buf[i] & RR_RDP) | ||
312 | printk(KERN_INFO "RDP: redirected page\n"); | ||
313 | if (buf[i] & RR_EOS) | ||
314 | printk(KERN_INFO "EOS: end of search error\n"); | ||
303 | } | 315 | } |
304 | #endif | 316 | } |
305 | 317 | ||
306 | return err; | 318 | static void ds_reset_device(struct ds_device *dev) |
319 | { | ||
320 | ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); | ||
321 | /* Always allow strong pullup which allow individual writes to use | ||
322 | * the strong pullup. | ||
323 | */ | ||
324 | if (ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE)) | ||
325 | printk(KERN_ERR "ds_reset_device: " | ||
326 | "Error allowing strong pullup\n"); | ||
327 | /* Chip strong pullup time was cleared. */ | ||
328 | if (dev->spu_sleep) { | ||
329 | /* lower 4 bits are 0, see ds_set_pullup */ | ||
330 | u8 del = dev->spu_sleep>>4; | ||
331 | if (ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del)) | ||
332 | printk(KERN_ERR "ds_reset_device: " | ||
333 | "Error setting duration\n"); | ||
334 | } | ||
307 | } | 335 | } |
308 | 336 | ||
309 | static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size) | 337 | static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size) |
@@ -311,13 +339,27 @@ static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size) | |||
311 | int count, err; | 339 | int count, err; |
312 | struct ds_status st; | 340 | struct ds_status st; |
313 | 341 | ||
342 | /* Careful on size. If size is less than what is available in | ||
343 | * the input buffer, the device fails the bulk transfer and | ||
344 | * clears the input buffer. It could read the maximum size of | ||
345 | * the data buffer, but then do you return the first, last, or | ||
346 | * some set of the middle size bytes? As long as the rest of | ||
347 | * the code is correct there will be size bytes waiting. A | ||
348 | * call to ds_wait_status will wait until the device is idle | ||
349 | * and any data to be received would have been available. | ||
350 | */ | ||
314 | count = 0; | 351 | count = 0; |
315 | err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]), | 352 | err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]), |
316 | buf, size, &count, 1000); | 353 | buf, size, &count, 1000); |
317 | if (err < 0) { | 354 | if (err < 0) { |
355 | u8 buf[0x20]; | ||
356 | int count; | ||
357 | |||
318 | printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]); | 358 | printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]); |
319 | usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN])); | 359 | usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN])); |
320 | ds_recv_status(dev, &st); | 360 | |
361 | count = ds_recv_status_nodump(dev, &st, buf, sizeof(buf)); | ||
362 | ds_dump_status(dev, buf, count); | ||
321 | return err; | 363 | return err; |
322 | } | 364 | } |
323 | 365 | ||
@@ -341,7 +383,8 @@ static int ds_send_data(struct ds_device *dev, unsigned char *buf, int len) | |||
341 | count = 0; | 383 | count = 0; |
342 | err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000); | 384 | err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000); |
343 | if (err < 0) { | 385 | if (err < 0) { |
344 | printk(KERN_ERR "Failed to read 1-wire data from 0x02: err=%d.\n", err); | 386 | printk(KERN_ERR "Failed to write 1-wire data to ep0x%x: " |
387 | "err=%d.\n", dev->ep[EP_DATA_OUT], err); | ||
345 | return err; | 388 | return err; |
346 | } | 389 | } |
347 | 390 | ||
@@ -397,7 +440,7 @@ int ds_detect(struct ds_device *dev, struct ds_status *st) | |||
397 | if (err) | 440 | if (err) |
398 | return err; | 441 | return err; |
399 | 442 | ||
400 | err = ds_recv_status(dev, st); | 443 | err = ds_dump_status(dev, st); |
401 | 444 | ||
402 | return err; | 445 | return err; |
403 | } | 446 | } |
@@ -420,33 +463,49 @@ static int ds_wait_status(struct ds_device *dev, struct ds_status *st) | |||
420 | printk("\n"); | 463 | printk("\n"); |
421 | } | 464 | } |
422 | #endif | 465 | #endif |
423 | } while(!(buf[0x08] & 0x20) && !(err < 0) && ++count < 100); | 466 | } while (!(buf[0x08] & ST_IDLE) && !(err < 0) && ++count < 100); |
467 | |||
468 | if (err >= 16 && st->status & ST_EPOF) { | ||
469 | printk(KERN_INFO "Resetting device after ST_EPOF.\n"); | ||
470 | ds_reset_device(dev); | ||
471 | /* Always dump the device status. */ | ||
472 | count = 101; | ||
473 | } | ||
424 | 474 | ||
475 | /* Dump the status for errors or if there is extended return data. | ||
476 | * The extended status includes new device detection (maybe someone | ||
477 | * can do something with it). | ||
478 | */ | ||
479 | if (err > 16 || count >= 100 || err < 0) | ||
480 | ds_dump_status(dev, buf, err); | ||
425 | 481 | ||
426 | if (((err > 16) && (buf[0x10] & 0x01)) || count >= 100 || err < 0) { | 482 | /* Extended data isn't an error. Well, a short is, but the dump |
427 | ds_recv_status(dev, st); | 483 | * would have already told the user that and we can't do anything |
484 | * about it in software anyway. | ||
485 | */ | ||
486 | if (count >= 100 || err < 0) | ||
428 | return -1; | 487 | return -1; |
429 | } else | 488 | else |
430 | return 0; | 489 | return 0; |
431 | } | 490 | } |
432 | 491 | ||
433 | static int ds_reset(struct ds_device *dev, struct ds_status *st) | 492 | static int ds_reset(struct ds_device *dev) |
434 | { | 493 | { |
435 | int err; | 494 | int err; |
436 | 495 | ||
437 | //err = ds_send_control(dev, COMM_1_WIRE_RESET | COMM_F | COMM_IM | COMM_SE, SPEED_FLEXIBLE); | 496 | /* Other potentionally interesting flags for reset. |
438 | err = ds_send_control(dev, 0x43, SPEED_NORMAL); | 497 | * |
498 | * COMM_NTF: Return result register feedback. This could be used to | ||
499 | * detect some conditions such as short, alarming presence, or | ||
500 | * detect if a new device was detected. | ||
501 | * | ||
502 | * COMM_SE which allows SPEED_NORMAL, SPEED_FLEXIBLE, SPEED_OVERDRIVE: | ||
503 | * Select the data transfer rate. | ||
504 | */ | ||
505 | err = ds_send_control(dev, COMM_1_WIRE_RESET | COMM_IM, SPEED_NORMAL); | ||
439 | if (err) | 506 | if (err) |
440 | return err; | 507 | return err; |
441 | 508 | ||
442 | ds_wait_status(dev, st); | ||
443 | #if 0 | ||
444 | if (st->command_buffer_status) { | ||
445 | printk(KERN_INFO "Short circuit.\n"); | ||
446 | return -EIO; | ||
447 | } | ||
448 | #endif | ||
449 | |||
450 | return 0; | 509 | return 0; |
451 | } | 510 | } |
452 | 511 | ||
@@ -471,60 +530,43 @@ static int ds_set_speed(struct ds_device *dev, int speed) | |||
471 | } | 530 | } |
472 | #endif /* 0 */ | 531 | #endif /* 0 */ |
473 | 532 | ||
474 | static int ds_start_pulse(struct ds_device *dev, int delay) | 533 | static int ds_set_pullup(struct ds_device *dev, int delay) |
475 | { | 534 | { |
476 | int err; | 535 | int err = 0; |
477 | u8 del = 1 + (u8)(delay >> 4); | 536 | u8 del = 1 + (u8)(delay >> 4); |
478 | struct ds_status st; | 537 | /* Just storing delay would not get the trunication and roundup. */ |
479 | 538 | int ms = del<<4; | |
480 | #if 0 | 539 | |
481 | err = ds_stop_pulse(dev, 10); | 540 | /* Enable spu_bit if a delay is set. */ |
482 | if (err) | 541 | dev->spu_bit = delay ? COMM_SPU : 0; |
542 | /* If delay is zero, it has already been disabled, if the time is | ||
543 | * the same as the hardware was last programmed to, there is also | ||
544 | * nothing more to do. Compare with the recalculated value ms | ||
545 | * rather than del or delay which can have a different value. | ||
546 | */ | ||
547 | if (delay == 0 || ms == dev->spu_sleep) | ||
483 | return err; | 548 | return err; |
484 | 549 | ||
485 | err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE); | ||
486 | if (err) | ||
487 | return err; | ||
488 | #endif | ||
489 | err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del); | 550 | err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del); |
490 | if (err) | 551 | if (err) |
491 | return err; | 552 | return err; |
492 | 553 | ||
493 | err = ds_send_control(dev, COMM_PULSE | COMM_IM | COMM_F, 0); | 554 | dev->spu_sleep = ms; |
494 | if (err) | ||
495 | return err; | ||
496 | |||
497 | mdelay(delay); | ||
498 | |||
499 | ds_wait_status(dev, &st); | ||
500 | 555 | ||
501 | return err; | 556 | return err; |
502 | } | 557 | } |
503 | 558 | ||
504 | static int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit) | 559 | static int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit) |
505 | { | 560 | { |
506 | int err, count; | 561 | int err; |
507 | struct ds_status st; | 562 | struct ds_status st; |
508 | u16 value = (COMM_BIT_IO | COMM_IM) | ((bit) ? COMM_D : 0); | ||
509 | u16 cmd; | ||
510 | 563 | ||
511 | err = ds_send_control(dev, value, 0); | 564 | err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | (bit ? COMM_D : 0), |
565 | 0); | ||
512 | if (err) | 566 | if (err) |
513 | return err; | 567 | return err; |
514 | 568 | ||
515 | count = 0; | 569 | ds_wait_status(dev, &st); |
516 | do { | ||
517 | err = ds_wait_status(dev, &st); | ||
518 | if (err) | ||
519 | return err; | ||
520 | |||
521 | cmd = st.command0 | (st.command1 << 8); | ||
522 | } while (cmd != value && ++count < 10); | ||
523 | |||
524 | if (err < 0 || count >= 10) { | ||
525 | printk(KERN_ERR "Failed to obtain status.\n"); | ||
526 | return -EINVAL; | ||
527 | } | ||
528 | 570 | ||
529 | err = ds_recv_data(dev, tbit, sizeof(*tbit)); | 571 | err = ds_recv_data(dev, tbit, sizeof(*tbit)); |
530 | if (err < 0) | 572 | if (err < 0) |
@@ -533,12 +575,18 @@ static int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit) | |||
533 | return 0; | 575 | return 0; |
534 | } | 576 | } |
535 | 577 | ||
578 | #if 0 | ||
536 | static int ds_write_bit(struct ds_device *dev, u8 bit) | 579 | static int ds_write_bit(struct ds_device *dev, u8 bit) |
537 | { | 580 | { |
538 | int err; | 581 | int err; |
539 | struct ds_status st; | 582 | struct ds_status st; |
540 | 583 | ||
541 | err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | (bit) ? COMM_D : 0, 0); | 584 | /* Set COMM_ICP to write without a readback. Note, this will |
585 | * produce one time slot, a down followed by an up with COMM_D | ||
586 | * only determing the timing. | ||
587 | */ | ||
588 | err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | COMM_ICP | | ||
589 | (bit ? COMM_D : 0), 0); | ||
542 | if (err) | 590 | if (err) |
543 | return err; | 591 | return err; |
544 | 592 | ||
@@ -546,6 +594,7 @@ static int ds_write_bit(struct ds_device *dev, u8 bit) | |||
546 | 594 | ||
547 | return 0; | 595 | return 0; |
548 | } | 596 | } |
597 | #endif | ||
549 | 598 | ||
550 | static int ds_write_byte(struct ds_device *dev, u8 byte) | 599 | static int ds_write_byte(struct ds_device *dev, u8 byte) |
551 | { | 600 | { |
@@ -553,10 +602,13 @@ static int ds_write_byte(struct ds_device *dev, u8 byte) | |||
553 | struct ds_status st; | 602 | struct ds_status st; |
554 | u8 rbyte; | 603 | u8 rbyte; |
555 | 604 | ||
556 | err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte); | 605 | err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | dev->spu_bit, byte); |
557 | if (err) | 606 | if (err) |
558 | return err; | 607 | return err; |
559 | 608 | ||
609 | if (dev->spu_bit) | ||
610 | msleep(dev->spu_sleep); | ||
611 | |||
560 | err = ds_wait_status(dev, &st); | 612 | err = ds_wait_status(dev, &st); |
561 | if (err) | 613 | if (err) |
562 | return err; | 614 | return err; |
@@ -565,8 +617,6 @@ static int ds_write_byte(struct ds_device *dev, u8 byte) | |||
565 | if (err < 0) | 617 | if (err < 0) |
566 | return err; | 618 | return err; |
567 | 619 | ||
568 | ds_start_pulse(dev, PULLUP_PULSE_DURATION); | ||
569 | |||
570 | return !(byte == rbyte); | 620 | return !(byte == rbyte); |
571 | } | 621 | } |
572 | 622 | ||
@@ -602,7 +652,7 @@ static int ds_read_block(struct ds_device *dev, u8 *buf, int len) | |||
602 | if (err < 0) | 652 | if (err < 0) |
603 | return err; | 653 | return err; |
604 | 654 | ||
605 | err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len); | 655 | err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM, len); |
606 | if (err) | 656 | if (err) |
607 | return err; | 657 | return err; |
608 | 658 | ||
@@ -623,20 +673,19 @@ static int ds_write_block(struct ds_device *dev, u8 *buf, int len) | |||
623 | if (err < 0) | 673 | if (err < 0) |
624 | return err; | 674 | return err; |
625 | 675 | ||
626 | ds_wait_status(dev, &st); | 676 | err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | dev->spu_bit, len); |
627 | |||
628 | err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len); | ||
629 | if (err) | 677 | if (err) |
630 | return err; | 678 | return err; |
631 | 679 | ||
680 | if (dev->spu_bit) | ||
681 | msleep(dev->spu_sleep); | ||
682 | |||
632 | ds_wait_status(dev, &st); | 683 | ds_wait_status(dev, &st); |
633 | 684 | ||
634 | err = ds_recv_data(dev, buf, len); | 685 | err = ds_recv_data(dev, buf, len); |
635 | if (err < 0) | 686 | if (err < 0) |
636 | return err; | 687 | return err; |
637 | 688 | ||
638 | ds_start_pulse(dev, PULLUP_PULSE_DURATION); | ||
639 | |||
640 | return !(err == len); | 689 | return !(err == len); |
641 | } | 690 | } |
642 | 691 | ||
@@ -728,6 +777,7 @@ static u8 ds9490r_touch_bit(void *data, u8 bit) | |||
728 | return ret; | 777 | return ret; |
729 | } | 778 | } |
730 | 779 | ||
780 | #if 0 | ||
731 | static void ds9490r_write_bit(void *data, u8 bit) | 781 | static void ds9490r_write_bit(void *data, u8 bit) |
732 | { | 782 | { |
733 | struct ds_device *dev = data; | 783 | struct ds_device *dev = data; |
@@ -735,13 +785,6 @@ static void ds9490r_write_bit(void *data, u8 bit) | |||
735 | ds_write_bit(dev, bit); | 785 | ds_write_bit(dev, bit); |
736 | } | 786 | } |
737 | 787 | ||
738 | static void ds9490r_write_byte(void *data, u8 byte) | ||
739 | { | ||
740 | struct ds_device *dev = data; | ||
741 | |||
742 | ds_write_byte(dev, byte); | ||
743 | } | ||
744 | |||
745 | static u8 ds9490r_read_bit(void *data) | 788 | static u8 ds9490r_read_bit(void *data) |
746 | { | 789 | { |
747 | struct ds_device *dev = data; | 790 | struct ds_device *dev = data; |
@@ -754,6 +797,14 @@ static u8 ds9490r_read_bit(void *data) | |||
754 | 797 | ||
755 | return bit & 1; | 798 | return bit & 1; |
756 | } | 799 | } |
800 | #endif | ||
801 | |||
802 | static void ds9490r_write_byte(void *data, u8 byte) | ||
803 | { | ||
804 | struct ds_device *dev = data; | ||
805 | |||
806 | ds_write_byte(dev, byte); | ||
807 | } | ||
757 | 808 | ||
758 | static u8 ds9490r_read_byte(void *data) | 809 | static u8 ds9490r_read_byte(void *data) |
759 | { | 810 | { |
@@ -790,31 +841,58 @@ static u8 ds9490r_read_block(void *data, u8 *buf, int len) | |||
790 | static u8 ds9490r_reset(void *data) | 841 | static u8 ds9490r_reset(void *data) |
791 | { | 842 | { |
792 | struct ds_device *dev = data; | 843 | struct ds_device *dev = data; |
793 | struct ds_status st; | ||
794 | int err; | 844 | int err; |
795 | 845 | ||
796 | memset(&st, 0, sizeof(st)); | 846 | err = ds_reset(dev); |
797 | |||
798 | err = ds_reset(dev, &st); | ||
799 | if (err) | 847 | if (err) |
800 | return 1; | 848 | return 1; |
801 | 849 | ||
802 | return 0; | 850 | return 0; |
803 | } | 851 | } |
804 | 852 | ||
853 | static u8 ds9490r_set_pullup(void *data, int delay) | ||
854 | { | ||
855 | struct ds_device *dev = data; | ||
856 | |||
857 | if (ds_set_pullup(dev, delay)) | ||
858 | return 1; | ||
859 | |||
860 | return 0; | ||
861 | } | ||
862 | |||
805 | static int ds_w1_init(struct ds_device *dev) | 863 | static int ds_w1_init(struct ds_device *dev) |
806 | { | 864 | { |
807 | memset(&dev->master, 0, sizeof(struct w1_bus_master)); | 865 | memset(&dev->master, 0, sizeof(struct w1_bus_master)); |
808 | 866 | ||
867 | /* Reset the device as it can be in a bad state. | ||
868 | * This is necessary because a block write will wait for data | ||
869 | * to be placed in the output buffer and block any later | ||
870 | * commands which will keep accumulating and the device will | ||
871 | * not be idle. Another case is removing the ds2490 module | ||
872 | * while a bus search is in progress, somehow a few commands | ||
873 | * get through, but the input transfers fail leaving data in | ||
874 | * the input buffer. This will cause the next read to fail | ||
875 | * see the note in ds_recv_data. | ||
876 | */ | ||
877 | ds_reset_device(dev); | ||
878 | |||
809 | dev->master.data = dev; | 879 | dev->master.data = dev; |
810 | dev->master.touch_bit = &ds9490r_touch_bit; | 880 | dev->master.touch_bit = &ds9490r_touch_bit; |
881 | /* read_bit and write_bit in w1_bus_master are expected to set and | ||
882 | * sample the line level. For write_bit that means it is expected to | ||
883 | * set it to that value and leave it there. ds2490 only supports an | ||
884 | * individual time slot at the lowest level. The requirement from | ||
885 | * pulling the bus state down to reading the state is 15us, something | ||
886 | * that isn't realistic on the USB bus anyway. | ||
811 | dev->master.read_bit = &ds9490r_read_bit; | 887 | dev->master.read_bit = &ds9490r_read_bit; |
812 | dev->master.write_bit = &ds9490r_write_bit; | 888 | dev->master.write_bit = &ds9490r_write_bit; |
889 | */ | ||
813 | dev->master.read_byte = &ds9490r_read_byte; | 890 | dev->master.read_byte = &ds9490r_read_byte; |
814 | dev->master.write_byte = &ds9490r_write_byte; | 891 | dev->master.write_byte = &ds9490r_write_byte; |
815 | dev->master.read_block = &ds9490r_read_block; | 892 | dev->master.read_block = &ds9490r_read_block; |
816 | dev->master.write_block = &ds9490r_write_block; | 893 | dev->master.write_block = &ds9490r_write_block; |
817 | dev->master.reset_bus = &ds9490r_reset; | 894 | dev->master.reset_bus = &ds9490r_reset; |
895 | dev->master.set_pullup = &ds9490r_set_pullup; | ||
818 | 896 | ||
819 | return w1_add_master_device(&dev->master); | 897 | return w1_add_master_device(&dev->master); |
820 | } | 898 | } |
@@ -838,6 +916,8 @@ static int ds_probe(struct usb_interface *intf, | |||
838 | printk(KERN_INFO "Failed to allocate new DS9490R structure.\n"); | 916 | printk(KERN_INFO "Failed to allocate new DS9490R structure.\n"); |
839 | return -ENOMEM; | 917 | return -ENOMEM; |
840 | } | 918 | } |
919 | dev->spu_sleep = 0; | ||
920 | dev->spu_bit = 0; | ||
841 | dev->udev = usb_get_dev(udev); | 921 | dev->udev = usb_get_dev(udev); |
842 | if (!dev->udev) { | 922 | if (!dev->udev) { |
843 | err = -ENOMEM; | 923 | err = -ENOMEM; |
diff --git a/drivers/w1/slaves/w1_ds2431.c b/drivers/w1/slaves/w1_ds2431.c new file mode 100644 index 000000000000..2c6c0cf6a20f --- /dev/null +++ b/drivers/w1/slaves/w1_ds2431.c | |||
@@ -0,0 +1,312 @@ | |||
1 | /* | ||
2 | * w1_ds2431.c - w1 family 2d (DS2431) driver | ||
3 | * | ||
4 | * Copyright (c) 2008 Bernhard Weirich <bernhard.weirich@riedel.net> | ||
5 | * | ||
6 | * Heavily inspired by w1_DS2433 driver from Ben Gardner <bgardner@wabtec.com> | ||
7 | * | ||
8 | * This source code is licensed under the GNU General Public License, | ||
9 | * Version 2. See the file COPYING for more details. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/moduleparam.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/types.h> | ||
17 | #include <linux/delay.h> | ||
18 | |||
19 | #include "../w1.h" | ||
20 | #include "../w1_int.h" | ||
21 | #include "../w1_family.h" | ||
22 | |||
23 | #define W1_F2D_EEPROM_SIZE 128 | ||
24 | #define W1_F2D_PAGE_COUNT 4 | ||
25 | #define W1_F2D_PAGE_BITS 5 | ||
26 | #define W1_F2D_PAGE_SIZE (1<<W1_F2D_PAGE_BITS) | ||
27 | #define W1_F2D_PAGE_MASK 0x1F | ||
28 | |||
29 | #define W1_F2D_SCRATCH_BITS 3 | ||
30 | #define W1_F2D_SCRATCH_SIZE (1<<W1_F2D_SCRATCH_BITS) | ||
31 | #define W1_F2D_SCRATCH_MASK (W1_F2D_SCRATCH_SIZE-1) | ||
32 | |||
33 | #define W1_F2D_READ_EEPROM 0xF0 | ||
34 | #define W1_F2D_WRITE_SCRATCH 0x0F | ||
35 | #define W1_F2D_READ_SCRATCH 0xAA | ||
36 | #define W1_F2D_COPY_SCRATCH 0x55 | ||
37 | |||
38 | |||
39 | #define W1_F2D_TPROG_MS 11 | ||
40 | |||
41 | #define W1_F2D_READ_RETRIES 10 | ||
42 | #define W1_F2D_READ_MAXLEN 8 | ||
43 | |||
44 | /* | ||
45 | * Check the file size bounds and adjusts count as needed. | ||
46 | * This would not be needed if the file size didn't reset to 0 after a write. | ||
47 | */ | ||
48 | static inline size_t w1_f2d_fix_count(loff_t off, size_t count, size_t size) | ||
49 | { | ||
50 | if (off > size) | ||
51 | return 0; | ||
52 | |||
53 | if ((off + count) > size) | ||
54 | return size - off; | ||
55 | |||
56 | return count; | ||
57 | } | ||
58 | |||
59 | /* | ||
60 | * Read a block from W1 ROM two times and compares the results. | ||
61 | * If they are equal they are returned, otherwise the read | ||
62 | * is repeated W1_F2D_READ_RETRIES times. | ||
63 | * | ||
64 | * count must not exceed W1_F2D_READ_MAXLEN. | ||
65 | */ | ||
66 | static int w1_f2d_readblock(struct w1_slave *sl, int off, int count, char *buf) | ||
67 | { | ||
68 | u8 wrbuf[3]; | ||
69 | u8 cmp[W1_F2D_READ_MAXLEN]; | ||
70 | int tries = W1_F2D_READ_RETRIES; | ||
71 | |||
72 | do { | ||
73 | wrbuf[0] = W1_F2D_READ_EEPROM; | ||
74 | wrbuf[1] = off & 0xff; | ||
75 | wrbuf[2] = off >> 8; | ||
76 | |||
77 | if (w1_reset_select_slave(sl)) | ||
78 | return -1; | ||
79 | |||
80 | w1_write_block(sl->master, wrbuf, 3); | ||
81 | w1_read_block(sl->master, buf, count); | ||
82 | |||
83 | if (w1_reset_select_slave(sl)) | ||
84 | return -1; | ||
85 | |||
86 | w1_write_block(sl->master, wrbuf, 3); | ||
87 | w1_read_block(sl->master, cmp, count); | ||
88 | |||
89 | if (!memcmp(cmp, buf, count)) | ||
90 | return 0; | ||
91 | } while (--tries); | ||
92 | |||
93 | dev_err(&sl->dev, "proof reading failed %d times\n", | ||
94 | W1_F2D_READ_RETRIES); | ||
95 | |||
96 | return -1; | ||
97 | } | ||
98 | |||
99 | static ssize_t w1_f2d_read_bin(struct kobject *kobj, | ||
100 | struct bin_attribute *bin_attr, | ||
101 | char *buf, loff_t off, size_t count) | ||
102 | { | ||
103 | struct w1_slave *sl = kobj_to_w1_slave(kobj); | ||
104 | int todo = count; | ||
105 | |||
106 | count = w1_f2d_fix_count(off, count, W1_F2D_EEPROM_SIZE); | ||
107 | if (count == 0) | ||
108 | return 0; | ||
109 | |||
110 | mutex_lock(&sl->master->mutex); | ||
111 | |||
112 | /* read directly from the EEPROM in chunks of W1_F2D_READ_MAXLEN */ | ||
113 | while (todo > 0) { | ||
114 | int block_read; | ||
115 | |||
116 | if (todo >= W1_F2D_READ_MAXLEN) | ||
117 | block_read = W1_F2D_READ_MAXLEN; | ||
118 | else | ||
119 | block_read = todo; | ||
120 | |||
121 | if (w1_f2d_readblock(sl, off, block_read, buf) < 0) | ||
122 | count = -EIO; | ||
123 | |||
124 | todo -= W1_F2D_READ_MAXLEN; | ||
125 | buf += W1_F2D_READ_MAXLEN; | ||
126 | off += W1_F2D_READ_MAXLEN; | ||
127 | } | ||
128 | |||
129 | mutex_unlock(&sl->master->mutex); | ||
130 | |||
131 | return count; | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | * Writes to the scratchpad and reads it back for verification. | ||
136 | * Then copies the scratchpad to EEPROM. | ||
137 | * The data must be aligned at W1_F2D_SCRATCH_SIZE bytes and | ||
138 | * must be W1_F2D_SCRATCH_SIZE bytes long. | ||
139 | * The master must be locked. | ||
140 | * | ||
141 | * @param sl The slave structure | ||
142 | * @param addr Address for the write | ||
143 | * @param len length must be <= (W1_F2D_PAGE_SIZE - (addr & W1_F2D_PAGE_MASK)) | ||
144 | * @param data The data to write | ||
145 | * @return 0=Success -1=failure | ||
146 | */ | ||
147 | static int w1_f2d_write(struct w1_slave *sl, int addr, int len, const u8 *data) | ||
148 | { | ||
149 | int tries = W1_F2D_READ_RETRIES; | ||
150 | u8 wrbuf[4]; | ||
151 | u8 rdbuf[W1_F2D_SCRATCH_SIZE + 3]; | ||
152 | u8 es = (addr + len - 1) % W1_F2D_SCRATCH_SIZE; | ||
153 | |||
154 | retry: | ||
155 | |||
156 | /* Write the data to the scratchpad */ | ||
157 | if (w1_reset_select_slave(sl)) | ||
158 | return -1; | ||
159 | |||
160 | wrbuf[0] = W1_F2D_WRITE_SCRATCH; | ||
161 | wrbuf[1] = addr & 0xff; | ||
162 | wrbuf[2] = addr >> 8; | ||
163 | |||
164 | w1_write_block(sl->master, wrbuf, 3); | ||
165 | w1_write_block(sl->master, data, len); | ||
166 | |||
167 | /* Read the scratchpad and verify */ | ||
168 | if (w1_reset_select_slave(sl)) | ||
169 | return -1; | ||
170 | |||
171 | w1_write_8(sl->master, W1_F2D_READ_SCRATCH); | ||
172 | w1_read_block(sl->master, rdbuf, len + 3); | ||
173 | |||
174 | /* Compare what was read against the data written */ | ||
175 | if ((rdbuf[0] != wrbuf[1]) || (rdbuf[1] != wrbuf[2]) || | ||
176 | (rdbuf[2] != es) || (memcmp(data, &rdbuf[3], len) != 0)) { | ||
177 | |||
178 | if (--tries) | ||
179 | goto retry; | ||
180 | |||
181 | dev_err(&sl->dev, | ||
182 | "could not write to eeprom, scratchpad compare failed %d times\n", | ||
183 | W1_F2D_READ_RETRIES); | ||
184 | |||
185 | return -1; | ||
186 | } | ||
187 | |||
188 | /* Copy the scratchpad to EEPROM */ | ||
189 | if (w1_reset_select_slave(sl)) | ||
190 | return -1; | ||
191 | |||
192 | wrbuf[0] = W1_F2D_COPY_SCRATCH; | ||
193 | wrbuf[3] = es; | ||
194 | w1_write_block(sl->master, wrbuf, 4); | ||
195 | |||
196 | /* Sleep for tprog ms to wait for the write to complete */ | ||
197 | msleep(W1_F2D_TPROG_MS); | ||
198 | |||
199 | /* Reset the bus to wake up the EEPROM */ | ||
200 | w1_reset_bus(sl->master); | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | static ssize_t w1_f2d_write_bin(struct kobject *kobj, | ||
206 | struct bin_attribute *bin_attr, | ||
207 | char *buf, loff_t off, size_t count) | ||
208 | { | ||
209 | struct w1_slave *sl = kobj_to_w1_slave(kobj); | ||
210 | int addr, len; | ||
211 | int copy; | ||
212 | |||
213 | count = w1_f2d_fix_count(off, count, W1_F2D_EEPROM_SIZE); | ||
214 | if (count == 0) | ||
215 | return 0; | ||
216 | |||
217 | mutex_lock(&sl->master->mutex); | ||
218 | |||
219 | /* Can only write data in blocks of the size of the scratchpad */ | ||
220 | addr = off; | ||
221 | len = count; | ||
222 | while (len > 0) { | ||
223 | |||
224 | /* if len too short or addr not aligned */ | ||
225 | if (len < W1_F2D_SCRATCH_SIZE || addr & W1_F2D_SCRATCH_MASK) { | ||
226 | char tmp[W1_F2D_SCRATCH_SIZE]; | ||
227 | |||
228 | /* read the block and update the parts to be written */ | ||
229 | if (w1_f2d_readblock(sl, addr & ~W1_F2D_SCRATCH_MASK, | ||
230 | W1_F2D_SCRATCH_SIZE, tmp)) { | ||
231 | count = -EIO; | ||
232 | goto out_up; | ||
233 | } | ||
234 | |||
235 | /* copy at most to the boundary of the PAGE or len */ | ||
236 | copy = W1_F2D_SCRATCH_SIZE - | ||
237 | (addr & W1_F2D_SCRATCH_MASK); | ||
238 | |||
239 | if (copy > len) | ||
240 | copy = len; | ||
241 | |||
242 | memcpy(&tmp[addr & W1_F2D_SCRATCH_MASK], buf, copy); | ||
243 | if (w1_f2d_write(sl, addr & ~W1_F2D_SCRATCH_MASK, | ||
244 | W1_F2D_SCRATCH_SIZE, tmp) < 0) { | ||
245 | count = -EIO; | ||
246 | goto out_up; | ||
247 | } | ||
248 | } else { | ||
249 | |||
250 | copy = W1_F2D_SCRATCH_SIZE; | ||
251 | if (w1_f2d_write(sl, addr, copy, buf) < 0) { | ||
252 | count = -EIO; | ||
253 | goto out_up; | ||
254 | } | ||
255 | } | ||
256 | buf += copy; | ||
257 | addr += copy; | ||
258 | len -= copy; | ||
259 | } | ||
260 | |||
261 | out_up: | ||
262 | mutex_unlock(&sl->master->mutex); | ||
263 | |||
264 | return count; | ||
265 | } | ||
266 | |||
267 | static struct bin_attribute w1_f2d_bin_attr = { | ||
268 | .attr = { | ||
269 | .name = "eeprom", | ||
270 | .mode = S_IRUGO | S_IWUSR, | ||
271 | }, | ||
272 | .size = W1_F2D_EEPROM_SIZE, | ||
273 | .read = w1_f2d_read_bin, | ||
274 | .write = w1_f2d_write_bin, | ||
275 | }; | ||
276 | |||
277 | static int w1_f2d_add_slave(struct w1_slave *sl) | ||
278 | { | ||
279 | return sysfs_create_bin_file(&sl->dev.kobj, &w1_f2d_bin_attr); | ||
280 | } | ||
281 | |||
282 | static void w1_f2d_remove_slave(struct w1_slave *sl) | ||
283 | { | ||
284 | sysfs_remove_bin_file(&sl->dev.kobj, &w1_f2d_bin_attr); | ||
285 | } | ||
286 | |||
287 | static struct w1_family_ops w1_f2d_fops = { | ||
288 | .add_slave = w1_f2d_add_slave, | ||
289 | .remove_slave = w1_f2d_remove_slave, | ||
290 | }; | ||
291 | |||
292 | static struct w1_family w1_family_2d = { | ||
293 | .fid = W1_EEPROM_DS2431, | ||
294 | .fops = &w1_f2d_fops, | ||
295 | }; | ||
296 | |||
297 | static int __init w1_f2d_init(void) | ||
298 | { | ||
299 | return w1_register_family(&w1_family_2d); | ||
300 | } | ||
301 | |||
302 | static void __exit w1_f2d_fini(void) | ||
303 | { | ||
304 | w1_unregister_family(&w1_family_2d); | ||
305 | } | ||
306 | |||
307 | module_init(w1_f2d_init); | ||
308 | module_exit(w1_f2d_fini); | ||
309 | |||
310 | MODULE_LICENSE("GPL"); | ||
311 | MODULE_AUTHOR("Bernhard Weirich <bernhard.weirich@riedel.net>"); | ||
312 | MODULE_DESCRIPTION("w1 family 2d driver for DS2431, 1kb EEPROM"); | ||
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c index fb28acaeed6c..2c8dff9f77da 100644 --- a/drivers/w1/slaves/w1_therm.c +++ b/drivers/w1/slaves/w1_therm.c | |||
@@ -37,31 +37,33 @@ MODULE_LICENSE("GPL"); | |||
37 | MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>"); | 37 | MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>"); |
38 | MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, temperature family."); | 38 | MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, temperature family."); |
39 | 39 | ||
40 | /* Allow the strong pullup to be disabled, but default to enabled. | ||
41 | * If it was disabled a parasite powered device might not get the require | ||
42 | * current to do a temperature conversion. If it is enabled parasite powered | ||
43 | * devices have a better chance of getting the current required. | ||
44 | */ | ||
45 | static int w1_strong_pullup = 1; | ||
46 | module_param_named(strong_pullup, w1_strong_pullup, int, 0); | ||
47 | |||
40 | static u8 bad_roms[][9] = { | 48 | static u8 bad_roms[][9] = { |
41 | {0xaa, 0x00, 0x4b, 0x46, 0xff, 0xff, 0x0c, 0x10, 0x87}, | 49 | {0xaa, 0x00, 0x4b, 0x46, 0xff, 0xff, 0x0c, 0x10, 0x87}, |
42 | {} | 50 | {} |
43 | }; | 51 | }; |
44 | 52 | ||
45 | static ssize_t w1_therm_read_bin(struct kobject *, struct bin_attribute *, | 53 | static ssize_t w1_therm_read(struct device *device, |
46 | char *, loff_t, size_t); | 54 | struct device_attribute *attr, char *buf); |
47 | 55 | ||
48 | static struct bin_attribute w1_therm_bin_attr = { | 56 | static struct device_attribute w1_therm_attr = |
49 | .attr = { | 57 | __ATTR(w1_slave, S_IRUGO, w1_therm_read, NULL); |
50 | .name = "w1_slave", | ||
51 | .mode = S_IRUGO, | ||
52 | }, | ||
53 | .size = W1_SLAVE_DATA_SIZE, | ||
54 | .read = w1_therm_read_bin, | ||
55 | }; | ||
56 | 58 | ||
57 | static int w1_therm_add_slave(struct w1_slave *sl) | 59 | static int w1_therm_add_slave(struct w1_slave *sl) |
58 | { | 60 | { |
59 | return sysfs_create_bin_file(&sl->dev.kobj, &w1_therm_bin_attr); | 61 | return device_create_file(&sl->dev, &w1_therm_attr); |
60 | } | 62 | } |
61 | 63 | ||
62 | static void w1_therm_remove_slave(struct w1_slave *sl) | 64 | static void w1_therm_remove_slave(struct w1_slave *sl) |
63 | { | 65 | { |
64 | sysfs_remove_bin_file(&sl->dev.kobj, &w1_therm_bin_attr); | 66 | device_remove_file(&sl->dev, &w1_therm_attr); |
65 | } | 67 | } |
66 | 68 | ||
67 | static struct w1_family_ops w1_therm_fops = { | 69 | static struct w1_family_ops w1_therm_fops = { |
@@ -160,30 +162,19 @@ static int w1_therm_check_rom(u8 rom[9]) | |||
160 | return 0; | 162 | return 0; |
161 | } | 163 | } |
162 | 164 | ||
163 | static ssize_t w1_therm_read_bin(struct kobject *kobj, | 165 | static ssize_t w1_therm_read(struct device *device, |
164 | struct bin_attribute *bin_attr, | 166 | struct device_attribute *attr, char *buf) |
165 | char *buf, loff_t off, size_t count) | ||
166 | { | 167 | { |
167 | struct w1_slave *sl = kobj_to_w1_slave(kobj); | 168 | struct w1_slave *sl = dev_to_w1_slave(device); |
168 | struct w1_master *dev = sl->master; | 169 | struct w1_master *dev = sl->master; |
169 | u8 rom[9], crc, verdict; | 170 | u8 rom[9], crc, verdict; |
170 | int i, max_trying = 10; | 171 | int i, max_trying = 10; |
172 | ssize_t c = PAGE_SIZE; | ||
171 | 173 | ||
172 | mutex_lock(&sl->master->mutex); | 174 | mutex_lock(&dev->mutex); |
173 | 175 | ||
174 | if (off > W1_SLAVE_DATA_SIZE) { | ||
175 | count = 0; | ||
176 | goto out; | ||
177 | } | ||
178 | if (off + count > W1_SLAVE_DATA_SIZE) { | ||
179 | count = 0; | ||
180 | goto out; | ||
181 | } | ||
182 | |||
183 | memset(buf, 0, count); | ||
184 | memset(rom, 0, sizeof(rom)); | 176 | memset(rom, 0, sizeof(rom)); |
185 | 177 | ||
186 | count = 0; | ||
187 | verdict = 0; | 178 | verdict = 0; |
188 | crc = 0; | 179 | crc = 0; |
189 | 180 | ||
@@ -192,15 +183,20 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, | |||
192 | int count = 0; | 183 | int count = 0; |
193 | unsigned int tm = 750; | 184 | unsigned int tm = 750; |
194 | 185 | ||
186 | /* 750ms strong pullup (or delay) after the convert */ | ||
187 | if (w1_strong_pullup) | ||
188 | w1_next_pullup(dev, tm); | ||
195 | w1_write_8(dev, W1_CONVERT_TEMP); | 189 | w1_write_8(dev, W1_CONVERT_TEMP); |
196 | 190 | if (!w1_strong_pullup) | |
197 | msleep(tm); | 191 | msleep(tm); |
198 | 192 | ||
199 | if (!w1_reset_select_slave(sl)) { | 193 | if (!w1_reset_select_slave(sl)) { |
200 | 194 | ||
201 | w1_write_8(dev, W1_READ_SCRATCHPAD); | 195 | w1_write_8(dev, W1_READ_SCRATCHPAD); |
202 | if ((count = w1_read_block(dev, rom, 9)) != 9) { | 196 | if ((count = w1_read_block(dev, rom, 9)) != 9) { |
203 | dev_warn(&dev->dev, "w1_read_block() returned %d instead of 9.\n", count); | 197 | dev_warn(device, "w1_read_block() " |
198 | "returned %u instead of 9.\n", | ||
199 | count); | ||
204 | } | 200 | } |
205 | 201 | ||
206 | crc = w1_calc_crc8(rom, 8); | 202 | crc = w1_calc_crc8(rom, 8); |
@@ -215,22 +211,22 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, | |||
215 | } | 211 | } |
216 | 212 | ||
217 | for (i = 0; i < 9; ++i) | 213 | for (i = 0; i < 9; ++i) |
218 | count += sprintf(buf + count, "%02x ", rom[i]); | 214 | c -= snprintf(buf + PAGE_SIZE - c, c, "%02x ", rom[i]); |
219 | count += sprintf(buf + count, ": crc=%02x %s\n", | 215 | c -= snprintf(buf + PAGE_SIZE - c, c, ": crc=%02x %s\n", |
220 | crc, (verdict) ? "YES" : "NO"); | 216 | crc, (verdict) ? "YES" : "NO"); |
221 | if (verdict) | 217 | if (verdict) |
222 | memcpy(sl->rom, rom, sizeof(sl->rom)); | 218 | memcpy(sl->rom, rom, sizeof(sl->rom)); |
223 | else | 219 | else |
224 | dev_warn(&dev->dev, "18S20 doesn't respond to CONVERT_TEMP.\n"); | 220 | dev_warn(device, "18S20 doesn't respond to CONVERT_TEMP.\n"); |
225 | 221 | ||
226 | for (i = 0; i < 9; ++i) | 222 | for (i = 0; i < 9; ++i) |
227 | count += sprintf(buf + count, "%02x ", sl->rom[i]); | 223 | c -= snprintf(buf + PAGE_SIZE - c, c, "%02x ", sl->rom[i]); |
228 | 224 | ||
229 | count += sprintf(buf + count, "t=%d\n", w1_convert_temp(rom, sl->family->fid)); | 225 | c -= snprintf(buf + PAGE_SIZE - c, c, "t=%d\n", |
230 | out: | 226 | w1_convert_temp(rom, sl->family->fid)); |
231 | mutex_unlock(&dev->mutex); | 227 | mutex_unlock(&dev->mutex); |
232 | 228 | ||
233 | return count; | 229 | return PAGE_SIZE - c; |
234 | } | 230 | } |
235 | 231 | ||
236 | static int __init w1_therm_init(void) | 232 | static int __init w1_therm_init(void) |
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 7293c9b11f91..3b615d4022ee 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c | |||
@@ -46,19 +46,17 @@ MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>"); | |||
46 | MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol."); | 46 | MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol."); |
47 | 47 | ||
48 | static int w1_timeout = 10; | 48 | static int w1_timeout = 10; |
49 | static int w1_control_timeout = 1; | ||
50 | int w1_max_slave_count = 10; | 49 | int w1_max_slave_count = 10; |
51 | int w1_max_slave_ttl = 10; | 50 | int w1_max_slave_ttl = 10; |
52 | 51 | ||
53 | module_param_named(timeout, w1_timeout, int, 0); | 52 | module_param_named(timeout, w1_timeout, int, 0); |
54 | module_param_named(control_timeout, w1_control_timeout, int, 0); | ||
55 | module_param_named(max_slave_count, w1_max_slave_count, int, 0); | 53 | module_param_named(max_slave_count, w1_max_slave_count, int, 0); |
56 | module_param_named(slave_ttl, w1_max_slave_ttl, int, 0); | 54 | module_param_named(slave_ttl, w1_max_slave_ttl, int, 0); |
57 | 55 | ||
58 | DEFINE_MUTEX(w1_mlock); | 56 | DEFINE_MUTEX(w1_mlock); |
59 | LIST_HEAD(w1_masters); | 57 | LIST_HEAD(w1_masters); |
60 | 58 | ||
61 | static struct task_struct *w1_control_thread; | 59 | static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn); |
62 | 60 | ||
63 | static int w1_master_match(struct device *dev, struct device_driver *drv) | 61 | static int w1_master_match(struct device *dev, struct device_driver *drv) |
64 | { | 62 | { |
@@ -83,10 +81,10 @@ static void w1_slave_release(struct device *dev) | |||
83 | { | 81 | { |
84 | struct w1_slave *sl = dev_to_w1_slave(dev); | 82 | struct w1_slave *sl = dev_to_w1_slave(dev); |
85 | 83 | ||
86 | printk("%s: Releasing %s.\n", __func__, sl->name); | 84 | dev_dbg(dev, "%s: Releasing %s.\n", __func__, sl->name); |
87 | 85 | ||
88 | while (atomic_read(&sl->refcnt)) { | 86 | while (atomic_read(&sl->refcnt)) { |
89 | printk("Waiting for %s to become free: refcnt=%d.\n", | 87 | dev_dbg(dev, "Waiting for %s to become free: refcnt=%d.\n", |
90 | sl->name, atomic_read(&sl->refcnt)); | 88 | sl->name, atomic_read(&sl->refcnt)); |
91 | if (msleep_interruptible(1000)) | 89 | if (msleep_interruptible(1000)) |
92 | flush_signals(current); | 90 | flush_signals(current); |
@@ -105,35 +103,20 @@ static ssize_t w1_slave_read_name(struct device *dev, struct device_attribute *a | |||
105 | return sprintf(buf, "%s\n", sl->name); | 103 | return sprintf(buf, "%s\n", sl->name); |
106 | } | 104 | } |
107 | 105 | ||
108 | static ssize_t w1_slave_read_id(struct kobject *kobj, | 106 | static ssize_t w1_slave_read_id(struct device *dev, |
109 | struct bin_attribute *bin_attr, | 107 | struct device_attribute *attr, char *buf) |
110 | char *buf, loff_t off, size_t count) | ||
111 | { | 108 | { |
112 | struct w1_slave *sl = kobj_to_w1_slave(kobj); | 109 | struct w1_slave *sl = dev_to_w1_slave(dev); |
113 | 110 | ssize_t count = sizeof(sl->reg_num); | |
114 | if (off > 8) { | ||
115 | count = 0; | ||
116 | } else { | ||
117 | if (off + count > 8) | ||
118 | count = 8 - off; | ||
119 | |||
120 | memcpy(buf, (u8 *)&sl->reg_num, count); | ||
121 | } | ||
122 | 111 | ||
112 | memcpy(buf, (u8 *)&sl->reg_num, count); | ||
123 | return count; | 113 | return count; |
124 | } | 114 | } |
125 | 115 | ||
126 | static struct device_attribute w1_slave_attr_name = | 116 | static struct device_attribute w1_slave_attr_name = |
127 | __ATTR(name, S_IRUGO, w1_slave_read_name, NULL); | 117 | __ATTR(name, S_IRUGO, w1_slave_read_name, NULL); |
128 | 118 | static struct device_attribute w1_slave_attr_id = | |
129 | static struct bin_attribute w1_slave_attr_bin_id = { | 119 | __ATTR(id, S_IRUGO, w1_slave_read_id, NULL); |
130 | .attr = { | ||
131 | .name = "id", | ||
132 | .mode = S_IRUGO, | ||
133 | }, | ||
134 | .size = 8, | ||
135 | .read = w1_slave_read_id, | ||
136 | }; | ||
137 | 120 | ||
138 | /* Default family */ | 121 | /* Default family */ |
139 | 122 | ||
@@ -250,11 +233,16 @@ static ssize_t w1_master_attribute_store_search(struct device * dev, | |||
250 | struct device_attribute *attr, | 233 | struct device_attribute *attr, |
251 | const char * buf, size_t count) | 234 | const char * buf, size_t count) |
252 | { | 235 | { |
236 | long tmp; | ||
253 | struct w1_master *md = dev_to_w1_master(dev); | 237 | struct w1_master *md = dev_to_w1_master(dev); |
254 | 238 | ||
239 | if (strict_strtol(buf, 0, &tmp) == -EINVAL) | ||
240 | return -EINVAL; | ||
241 | |||
255 | mutex_lock(&md->mutex); | 242 | mutex_lock(&md->mutex); |
256 | md->search_count = simple_strtol(buf, NULL, 0); | 243 | md->search_count = tmp; |
257 | mutex_unlock(&md->mutex); | 244 | mutex_unlock(&md->mutex); |
245 | wake_up_process(md->thread); | ||
258 | 246 | ||
259 | return count; | 247 | return count; |
260 | } | 248 | } |
@@ -273,6 +261,38 @@ static ssize_t w1_master_attribute_show_search(struct device *dev, | |||
273 | return count; | 261 | return count; |
274 | } | 262 | } |
275 | 263 | ||
264 | static ssize_t w1_master_attribute_store_pullup(struct device *dev, | ||
265 | struct device_attribute *attr, | ||
266 | const char *buf, size_t count) | ||
267 | { | ||
268 | long tmp; | ||
269 | struct w1_master *md = dev_to_w1_master(dev); | ||
270 | |||
271 | if (strict_strtol(buf, 0, &tmp) == -EINVAL) | ||
272 | return -EINVAL; | ||
273 | |||
274 | mutex_lock(&md->mutex); | ||
275 | md->enable_pullup = tmp; | ||
276 | mutex_unlock(&md->mutex); | ||
277 | wake_up_process(md->thread); | ||
278 | |||
279 | return count; | ||
280 | } | ||
281 | |||
282 | static ssize_t w1_master_attribute_show_pullup(struct device *dev, | ||
283 | struct device_attribute *attr, | ||
284 | char *buf) | ||
285 | { | ||
286 | struct w1_master *md = dev_to_w1_master(dev); | ||
287 | ssize_t count; | ||
288 | |||
289 | mutex_lock(&md->mutex); | ||
290 | count = sprintf(buf, "%d\n", md->enable_pullup); | ||
291 | mutex_unlock(&md->mutex); | ||
292 | |||
293 | return count; | ||
294 | } | ||
295 | |||
276 | static ssize_t w1_master_attribute_show_pointer(struct device *dev, struct device_attribute *attr, char *buf) | 296 | static ssize_t w1_master_attribute_show_pointer(struct device *dev, struct device_attribute *attr, char *buf) |
277 | { | 297 | { |
278 | struct w1_master *md = dev_to_w1_master(dev); | 298 | struct w1_master *md = dev_to_w1_master(dev); |
@@ -324,7 +344,8 @@ static ssize_t w1_master_attribute_show_slave_count(struct device *dev, struct d | |||
324 | return count; | 344 | return count; |
325 | } | 345 | } |
326 | 346 | ||
327 | static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device_attribute *attr, char *buf) | 347 | static ssize_t w1_master_attribute_show_slaves(struct device *dev, |
348 | struct device_attribute *attr, char *buf) | ||
328 | { | 349 | { |
329 | struct w1_master *md = dev_to_w1_master(dev); | 350 | struct w1_master *md = dev_to_w1_master(dev); |
330 | int c = PAGE_SIZE; | 351 | int c = PAGE_SIZE; |
@@ -349,6 +370,135 @@ static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device | |||
349 | return PAGE_SIZE - c; | 370 | return PAGE_SIZE - c; |
350 | } | 371 | } |
351 | 372 | ||
373 | static ssize_t w1_master_attribute_show_add(struct device *dev, | ||
374 | struct device_attribute *attr, char *buf) | ||
375 | { | ||
376 | int c = PAGE_SIZE; | ||
377 | c -= snprintf(buf+PAGE_SIZE - c, c, | ||
378 | "write device id xx-xxxxxxxxxxxx to add slave\n"); | ||
379 | return PAGE_SIZE - c; | ||
380 | } | ||
381 | |||
382 | static int w1_atoreg_num(struct device *dev, const char *buf, size_t count, | ||
383 | struct w1_reg_num *rn) | ||
384 | { | ||
385 | unsigned int family; | ||
386 | unsigned long long id; | ||
387 | int i; | ||
388 | u64 rn64_le; | ||
389 | |||
390 | /* The CRC value isn't read from the user because the sysfs directory | ||
391 | * doesn't include it and most messages from the bus search don't | ||
392 | * print it either. It would be unreasonable for the user to then | ||
393 | * provide it. | ||
394 | */ | ||
395 | const char *error_msg = "bad slave string format, expecting " | ||
396 | "ff-dddddddddddd\n"; | ||
397 | |||
398 | if (buf[2] != '-') { | ||
399 | dev_err(dev, "%s", error_msg); | ||
400 | return -EINVAL; | ||
401 | } | ||
402 | i = sscanf(buf, "%02x-%012llx", &family, &id); | ||
403 | if (i != 2) { | ||
404 | dev_err(dev, "%s", error_msg); | ||
405 | return -EINVAL; | ||
406 | } | ||
407 | rn->family = family; | ||
408 | rn->id = id; | ||
409 | |||
410 | rn64_le = cpu_to_le64(*(u64 *)rn); | ||
411 | rn->crc = w1_calc_crc8((u8 *)&rn64_le, 7); | ||
412 | |||
413 | #if 0 | ||
414 | dev_info(dev, "With CRC device is %02x.%012llx.%02x.\n", | ||
415 | rn->family, (unsigned long long)rn->id, rn->crc); | ||
416 | #endif | ||
417 | |||
418 | return 0; | ||
419 | } | ||
420 | |||
421 | /* Searches the slaves in the w1_master and returns a pointer or NULL. | ||
422 | * Note: must hold the mutex | ||
423 | */ | ||
424 | static struct w1_slave *w1_slave_search_device(struct w1_master *dev, | ||
425 | struct w1_reg_num *rn) | ||
426 | { | ||
427 | struct w1_slave *sl; | ||
428 | list_for_each_entry(sl, &dev->slist, w1_slave_entry) { | ||
429 | if (sl->reg_num.family == rn->family && | ||
430 | sl->reg_num.id == rn->id && | ||
431 | sl->reg_num.crc == rn->crc) { | ||
432 | return sl; | ||
433 | } | ||
434 | } | ||
435 | return NULL; | ||
436 | } | ||
437 | |||
438 | static ssize_t w1_master_attribute_store_add(struct device *dev, | ||
439 | struct device_attribute *attr, | ||
440 | const char *buf, size_t count) | ||
441 | { | ||
442 | struct w1_master *md = dev_to_w1_master(dev); | ||
443 | struct w1_reg_num rn; | ||
444 | struct w1_slave *sl; | ||
445 | ssize_t result = count; | ||
446 | |||
447 | if (w1_atoreg_num(dev, buf, count, &rn)) | ||
448 | return -EINVAL; | ||
449 | |||
450 | mutex_lock(&md->mutex); | ||
451 | sl = w1_slave_search_device(md, &rn); | ||
452 | /* It would be nice to do a targeted search one the one-wire bus | ||
453 | * for the new device to see if it is out there or not. But the | ||
454 | * current search doesn't support that. | ||
455 | */ | ||
456 | if (sl) { | ||
457 | dev_info(dev, "Device %s already exists\n", sl->name); | ||
458 | result = -EINVAL; | ||
459 | } else { | ||
460 | w1_attach_slave_device(md, &rn); | ||
461 | } | ||
462 | mutex_unlock(&md->mutex); | ||
463 | |||
464 | return result; | ||
465 | } | ||
466 | |||
467 | static ssize_t w1_master_attribute_show_remove(struct device *dev, | ||
468 | struct device_attribute *attr, char *buf) | ||
469 | { | ||
470 | int c = PAGE_SIZE; | ||
471 | c -= snprintf(buf+PAGE_SIZE - c, c, | ||
472 | "write device id xx-xxxxxxxxxxxx to remove slave\n"); | ||
473 | return PAGE_SIZE - c; | ||
474 | } | ||
475 | |||
476 | static ssize_t w1_master_attribute_store_remove(struct device *dev, | ||
477 | struct device_attribute *attr, | ||
478 | const char *buf, size_t count) | ||
479 | { | ||
480 | struct w1_master *md = dev_to_w1_master(dev); | ||
481 | struct w1_reg_num rn; | ||
482 | struct w1_slave *sl; | ||
483 | ssize_t result = count; | ||
484 | |||
485 | if (w1_atoreg_num(dev, buf, count, &rn)) | ||
486 | return -EINVAL; | ||
487 | |||
488 | mutex_lock(&md->mutex); | ||
489 | sl = w1_slave_search_device(md, &rn); | ||
490 | if (sl) { | ||
491 | w1_slave_detach(sl); | ||
492 | } else { | ||
493 | dev_info(dev, "Device %02x-%012llx doesn't exists\n", rn.family, | ||
494 | (unsigned long long)rn.id); | ||
495 | result = -EINVAL; | ||
496 | } | ||
497 | mutex_unlock(&md->mutex); | ||
498 | |||
499 | return result; | ||
500 | } | ||
501 | |||
352 | #define W1_MASTER_ATTR_RO(_name, _mode) \ | 502 | #define W1_MASTER_ATTR_RO(_name, _mode) \ |
353 | struct device_attribute w1_master_attribute_##_name = \ | 503 | struct device_attribute w1_master_attribute_##_name = \ |
354 | __ATTR(w1_master_##_name, _mode, \ | 504 | __ATTR(w1_master_##_name, _mode, \ |
@@ -368,6 +518,9 @@ static W1_MASTER_ATTR_RO(attempts, S_IRUGO); | |||
368 | static W1_MASTER_ATTR_RO(timeout, S_IRUGO); | 518 | static W1_MASTER_ATTR_RO(timeout, S_IRUGO); |
369 | static W1_MASTER_ATTR_RO(pointer, S_IRUGO); | 519 | static W1_MASTER_ATTR_RO(pointer, S_IRUGO); |
370 | static W1_MASTER_ATTR_RW(search, S_IRUGO | S_IWUGO); | 520 | static W1_MASTER_ATTR_RW(search, S_IRUGO | S_IWUGO); |
521 | static W1_MASTER_ATTR_RW(pullup, S_IRUGO | S_IWUGO); | ||
522 | static W1_MASTER_ATTR_RW(add, S_IRUGO | S_IWUGO); | ||
523 | static W1_MASTER_ATTR_RW(remove, S_IRUGO | S_IWUGO); | ||
371 | 524 | ||
372 | static struct attribute *w1_master_default_attrs[] = { | 525 | static struct attribute *w1_master_default_attrs[] = { |
373 | &w1_master_attribute_name.attr, | 526 | &w1_master_attribute_name.attr, |
@@ -378,6 +531,9 @@ static struct attribute *w1_master_default_attrs[] = { | |||
378 | &w1_master_attribute_timeout.attr, | 531 | &w1_master_attribute_timeout.attr, |
379 | &w1_master_attribute_pointer.attr, | 532 | &w1_master_attribute_pointer.attr, |
380 | &w1_master_attribute_search.attr, | 533 | &w1_master_attribute_search.attr, |
534 | &w1_master_attribute_pullup.attr, | ||
535 | &w1_master_attribute_add.attr, | ||
536 | &w1_master_attribute_remove.attr, | ||
381 | NULL | 537 | NULL |
382 | }; | 538 | }; |
383 | 539 | ||
@@ -390,7 +546,7 @@ int w1_create_master_attributes(struct w1_master *master) | |||
390 | return sysfs_create_group(&master->dev.kobj, &w1_master_defattr_group); | 546 | return sysfs_create_group(&master->dev.kobj, &w1_master_defattr_group); |
391 | } | 547 | } |
392 | 548 | ||
393 | static void w1_destroy_master_attributes(struct w1_master *master) | 549 | void w1_destroy_master_attributes(struct w1_master *master) |
394 | { | 550 | { |
395 | sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group); | 551 | sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group); |
396 | } | 552 | } |
@@ -479,7 +635,7 @@ static int __w1_attach_slave_device(struct w1_slave *sl) | |||
479 | } | 635 | } |
480 | 636 | ||
481 | /* Create "id" entry */ | 637 | /* Create "id" entry */ |
482 | err = sysfs_create_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id); | 638 | err = device_create_file(&sl->dev, &w1_slave_attr_id); |
483 | if (err < 0) { | 639 | if (err < 0) { |
484 | dev_err(&sl->dev, | 640 | dev_err(&sl->dev, |
485 | "sysfs file creation for [%s] failed. err=%d\n", | 641 | "sysfs file creation for [%s] failed. err=%d\n", |
@@ -501,7 +657,7 @@ static int __w1_attach_slave_device(struct w1_slave *sl) | |||
501 | return 0; | 657 | return 0; |
502 | 658 | ||
503 | out_rem2: | 659 | out_rem2: |
504 | sysfs_remove_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id); | 660 | device_remove_file(&sl->dev, &w1_slave_attr_id); |
505 | out_rem1: | 661 | out_rem1: |
506 | device_remove_file(&sl->dev, &w1_slave_attr_name); | 662 | device_remove_file(&sl->dev, &w1_slave_attr_name); |
507 | out_unreg: | 663 | out_unreg: |
@@ -567,7 +723,7 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn) | |||
567 | return 0; | 723 | return 0; |
568 | } | 724 | } |
569 | 725 | ||
570 | static void w1_slave_detach(struct w1_slave *sl) | 726 | void w1_slave_detach(struct w1_slave *sl) |
571 | { | 727 | { |
572 | struct w1_netlink_msg msg; | 728 | struct w1_netlink_msg msg; |
573 | 729 | ||
@@ -583,7 +739,7 @@ static void w1_slave_detach(struct w1_slave *sl) | |||
583 | msg.type = W1_SLAVE_REMOVE; | 739 | msg.type = W1_SLAVE_REMOVE; |
584 | w1_netlink_send(sl->master, &msg); | 740 | w1_netlink_send(sl->master, &msg); |
585 | 741 | ||
586 | sysfs_remove_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id); | 742 | device_remove_file(&sl->dev, &w1_slave_attr_id); |
587 | device_remove_file(&sl->dev, &w1_slave_attr_name); | 743 | device_remove_file(&sl->dev, &w1_slave_attr_name); |
588 | device_unregister(&sl->dev); | 744 | device_unregister(&sl->dev); |
589 | 745 | ||
@@ -591,24 +747,6 @@ static void w1_slave_detach(struct w1_slave *sl) | |||
591 | kfree(sl); | 747 | kfree(sl); |
592 | } | 748 | } |
593 | 749 | ||
594 | static struct w1_master *w1_search_master(void *data) | ||
595 | { | ||
596 | struct w1_master *dev; | ||
597 | int found = 0; | ||
598 | |||
599 | mutex_lock(&w1_mlock); | ||
600 | list_for_each_entry(dev, &w1_masters, w1_master_entry) { | ||
601 | if (dev->bus_master->data == data) { | ||
602 | found = 1; | ||
603 | atomic_inc(&dev->refcnt); | ||
604 | break; | ||
605 | } | ||
606 | } | ||
607 | mutex_unlock(&w1_mlock); | ||
608 | |||
609 | return (found)?dev:NULL; | ||
610 | } | ||
611 | |||
612 | struct w1_master *w1_search_master_id(u32 id) | 750 | struct w1_master *w1_search_master_id(u32 id) |
613 | { | 751 | { |
614 | struct w1_master *dev; | 752 | struct w1_master *dev; |
@@ -656,55 +794,56 @@ struct w1_slave *w1_search_slave(struct w1_reg_num *id) | |||
656 | return (found)?sl:NULL; | 794 | return (found)?sl:NULL; |
657 | } | 795 | } |
658 | 796 | ||
659 | void w1_reconnect_slaves(struct w1_family *f) | 797 | void w1_reconnect_slaves(struct w1_family *f, int attach) |
660 | { | 798 | { |
799 | struct w1_slave *sl, *sln; | ||
661 | struct w1_master *dev; | 800 | struct w1_master *dev; |
662 | 801 | ||
663 | mutex_lock(&w1_mlock); | 802 | mutex_lock(&w1_mlock); |
664 | list_for_each_entry(dev, &w1_masters, w1_master_entry) { | 803 | list_for_each_entry(dev, &w1_masters, w1_master_entry) { |
665 | dev_dbg(&dev->dev, "Reconnecting slaves in %s into new family %02x.\n", | 804 | dev_dbg(&dev->dev, "Reconnecting slaves in device %s " |
666 | dev->name, f->fid); | 805 | "for family %02x.\n", dev->name, f->fid); |
667 | set_bit(W1_MASTER_NEED_RECONNECT, &dev->flags); | 806 | mutex_lock(&dev->mutex); |
807 | list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { | ||
808 | /* If it is a new family, slaves with the default | ||
809 | * family driver and are that family will be | ||
810 | * connected. If the family is going away, devices | ||
811 | * matching that family are reconneced. | ||
812 | */ | ||
813 | if ((attach && sl->family->fid == W1_FAMILY_DEFAULT | ||
814 | && sl->reg_num.family == f->fid) || | ||
815 | (!attach && sl->family->fid == f->fid)) { | ||
816 | struct w1_reg_num rn; | ||
817 | |||
818 | memcpy(&rn, &sl->reg_num, sizeof(rn)); | ||
819 | w1_slave_detach(sl); | ||
820 | |||
821 | w1_attach_slave_device(dev, &rn); | ||
822 | } | ||
823 | } | ||
824 | dev_dbg(&dev->dev, "Reconnecting slaves in device %s " | ||
825 | "has been finished.\n", dev->name); | ||
826 | mutex_unlock(&dev->mutex); | ||
668 | } | 827 | } |
669 | mutex_unlock(&w1_mlock); | 828 | mutex_unlock(&w1_mlock); |
670 | } | 829 | } |
671 | 830 | ||
672 | static void w1_slave_found(void *data, u64 rn) | 831 | static void w1_slave_found(struct w1_master *dev, u64 rn) |
673 | { | 832 | { |
674 | int slave_count; | ||
675 | struct w1_slave *sl; | 833 | struct w1_slave *sl; |
676 | struct list_head *ent; | ||
677 | struct w1_reg_num *tmp; | 834 | struct w1_reg_num *tmp; |
678 | struct w1_master *dev; | ||
679 | u64 rn_le = cpu_to_le64(rn); | 835 | u64 rn_le = cpu_to_le64(rn); |
680 | 836 | ||
681 | dev = w1_search_master(data); | 837 | atomic_inc(&dev->refcnt); |
682 | if (!dev) { | ||
683 | printk(KERN_ERR "Failed to find w1 master device for data %p, " | ||
684 | "it is impossible.\n", data); | ||
685 | return; | ||
686 | } | ||
687 | 838 | ||
688 | tmp = (struct w1_reg_num *) &rn; | 839 | tmp = (struct w1_reg_num *) &rn; |
689 | 840 | ||
690 | slave_count = 0; | 841 | sl = w1_slave_search_device(dev, tmp); |
691 | list_for_each(ent, &dev->slist) { | 842 | if (sl) { |
692 | 843 | set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags); | |
693 | sl = list_entry(ent, struct w1_slave, w1_slave_entry); | 844 | } else { |
694 | 845 | if (rn && tmp->crc == w1_calc_crc8((u8 *)&rn_le, 7)) | |
695 | if (sl->reg_num.family == tmp->family && | 846 | w1_attach_slave_device(dev, tmp); |
696 | sl->reg_num.id == tmp->id && | ||
697 | sl->reg_num.crc == tmp->crc) { | ||
698 | set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags); | ||
699 | break; | ||
700 | } | ||
701 | |||
702 | slave_count++; | ||
703 | } | ||
704 | |||
705 | if (slave_count == dev->slave_count && | ||
706 | rn && ((rn >> 56) & 0xff) == w1_calc_crc8((u8 *)&rn_le, 7)) { | ||
707 | w1_attach_slave_device(dev, tmp); | ||
708 | } | 847 | } |
709 | 848 | ||
710 | atomic_dec(&dev->refcnt); | 849 | atomic_dec(&dev->refcnt); |
@@ -779,80 +918,20 @@ void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb | |||
779 | /* extract the direction taken & update the device number */ | 918 | /* extract the direction taken & update the device number */ |
780 | tmp64 = (triplet_ret >> 2); | 919 | tmp64 = (triplet_ret >> 2); |
781 | rn |= (tmp64 << i); | 920 | rn |= (tmp64 << i); |
921 | |||
922 | if (kthread_should_stop()) { | ||
923 | dev_dbg(&dev->dev, "Abort w1_search\n"); | ||
924 | return; | ||
925 | } | ||
782 | } | 926 | } |
783 | 927 | ||
784 | if ( (triplet_ret & 0x03) != 0x03 ) { | 928 | if ( (triplet_ret & 0x03) != 0x03 ) { |
785 | if ( (desc_bit == last_zero) || (last_zero < 0)) | 929 | if ( (desc_bit == last_zero) || (last_zero < 0)) |
786 | last_device = 1; | 930 | last_device = 1; |
787 | desc_bit = last_zero; | 931 | desc_bit = last_zero; |
788 | cb(dev->bus_master->data, rn); | 932 | cb(dev, rn); |
789 | } | ||
790 | } | ||
791 | } | ||
792 | |||
793 | static int w1_control(void *data) | ||
794 | { | ||
795 | struct w1_slave *sl, *sln; | ||
796 | struct w1_master *dev, *n; | ||
797 | int have_to_wait = 0; | ||
798 | |||
799 | set_freezable(); | ||
800 | while (!kthread_should_stop() || have_to_wait) { | ||
801 | have_to_wait = 0; | ||
802 | |||
803 | try_to_freeze(); | ||
804 | msleep_interruptible(w1_control_timeout * 1000); | ||
805 | |||
806 | list_for_each_entry_safe(dev, n, &w1_masters, w1_master_entry) { | ||
807 | if (!kthread_should_stop() && !dev->flags) | ||
808 | continue; | ||
809 | /* | ||
810 | * Little race: we can create thread but not set the flag. | ||
811 | * Get a chance for external process to set flag up. | ||
812 | */ | ||
813 | if (!dev->initialized) { | ||
814 | have_to_wait = 1; | ||
815 | continue; | ||
816 | } | ||
817 | |||
818 | if (kthread_should_stop() || test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) { | ||
819 | set_bit(W1_MASTER_NEED_EXIT, &dev->flags); | ||
820 | |||
821 | mutex_lock(&w1_mlock); | ||
822 | list_del(&dev->w1_master_entry); | ||
823 | mutex_unlock(&w1_mlock); | ||
824 | |||
825 | mutex_lock(&dev->mutex); | ||
826 | list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { | ||
827 | w1_slave_detach(sl); | ||
828 | } | ||
829 | w1_destroy_master_attributes(dev); | ||
830 | mutex_unlock(&dev->mutex); | ||
831 | atomic_dec(&dev->refcnt); | ||
832 | continue; | ||
833 | } | ||
834 | |||
835 | if (test_bit(W1_MASTER_NEED_RECONNECT, &dev->flags)) { | ||
836 | dev_dbg(&dev->dev, "Reconnecting slaves in device %s.\n", dev->name); | ||
837 | mutex_lock(&dev->mutex); | ||
838 | list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { | ||
839 | if (sl->family->fid == W1_FAMILY_DEFAULT) { | ||
840 | struct w1_reg_num rn; | ||
841 | |||
842 | memcpy(&rn, &sl->reg_num, sizeof(rn)); | ||
843 | w1_slave_detach(sl); | ||
844 | |||
845 | w1_attach_slave_device(dev, &rn); | ||
846 | } | ||
847 | } | ||
848 | dev_dbg(&dev->dev, "Reconnecting slaves in device %s has been finished.\n", dev->name); | ||
849 | clear_bit(W1_MASTER_NEED_RECONNECT, &dev->flags); | ||
850 | mutex_unlock(&dev->mutex); | ||
851 | } | ||
852 | } | 933 | } |
853 | } | 934 | } |
854 | |||
855 | return 0; | ||
856 | } | 935 | } |
857 | 936 | ||
858 | void w1_search_process(struct w1_master *dev, u8 search_type) | 937 | void w1_search_process(struct w1_master *dev, u8 search_type) |
@@ -878,23 +957,29 @@ void w1_search_process(struct w1_master *dev, u8 search_type) | |||
878 | int w1_process(void *data) | 957 | int w1_process(void *data) |
879 | { | 958 | { |
880 | struct w1_master *dev = (struct w1_master *) data; | 959 | struct w1_master *dev = (struct w1_master *) data; |
960 | /* As long as w1_timeout is only set by a module parameter the sleep | ||
961 | * time can be calculated in jiffies once. | ||
962 | */ | ||
963 | const unsigned long jtime = msecs_to_jiffies(w1_timeout * 1000); | ||
964 | |||
965 | while (!kthread_should_stop()) { | ||
966 | if (dev->search_count) { | ||
967 | mutex_lock(&dev->mutex); | ||
968 | w1_search_process(dev, W1_SEARCH); | ||
969 | mutex_unlock(&dev->mutex); | ||
970 | } | ||
881 | 971 | ||
882 | while (!kthread_should_stop() && !test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) { | ||
883 | try_to_freeze(); | 972 | try_to_freeze(); |
884 | msleep_interruptible(w1_timeout * 1000); | 973 | __set_current_state(TASK_INTERRUPTIBLE); |
885 | 974 | ||
886 | if (kthread_should_stop() || test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) | 975 | if (kthread_should_stop()) |
887 | break; | 976 | break; |
888 | 977 | ||
889 | if (!dev->initialized) | 978 | /* Only sleep when the search is active. */ |
890 | continue; | 979 | if (dev->search_count) |
891 | 980 | schedule_timeout(jtime); | |
892 | if (dev->search_count == 0) | 981 | else |
893 | continue; | 982 | schedule(); |
894 | |||
895 | mutex_lock(&dev->mutex); | ||
896 | w1_search_process(dev, W1_SEARCH); | ||
897 | mutex_unlock(&dev->mutex); | ||
898 | } | 983 | } |
899 | 984 | ||
900 | atomic_dec(&dev->refcnt); | 985 | atomic_dec(&dev->refcnt); |
@@ -932,18 +1017,13 @@ static int w1_init(void) | |||
932 | goto err_out_master_unregister; | 1017 | goto err_out_master_unregister; |
933 | } | 1018 | } |
934 | 1019 | ||
935 | w1_control_thread = kthread_run(w1_control, NULL, "w1_control"); | ||
936 | if (IS_ERR(w1_control_thread)) { | ||
937 | retval = PTR_ERR(w1_control_thread); | ||
938 | printk(KERN_ERR "Failed to create control thread. err=%d\n", | ||
939 | retval); | ||
940 | goto err_out_slave_unregister; | ||
941 | } | ||
942 | |||
943 | return 0; | 1020 | return 0; |
944 | 1021 | ||
1022 | #if 0 | ||
1023 | /* For undoing the slave register if there was a step after it. */ | ||
945 | err_out_slave_unregister: | 1024 | err_out_slave_unregister: |
946 | driver_unregister(&w1_slave_driver); | 1025 | driver_unregister(&w1_slave_driver); |
1026 | #endif | ||
947 | 1027 | ||
948 | err_out_master_unregister: | 1028 | err_out_master_unregister: |
949 | driver_unregister(&w1_master_driver); | 1029 | driver_unregister(&w1_master_driver); |
@@ -959,13 +1039,12 @@ static void w1_fini(void) | |||
959 | { | 1039 | { |
960 | struct w1_master *dev; | 1040 | struct w1_master *dev; |
961 | 1041 | ||
1042 | /* Set netlink removal messages and some cleanup */ | ||
962 | list_for_each_entry(dev, &w1_masters, w1_master_entry) | 1043 | list_for_each_entry(dev, &w1_masters, w1_master_entry) |
963 | __w1_remove_master_device(dev); | 1044 | __w1_remove_master_device(dev); |
964 | 1045 | ||
965 | w1_fini_netlink(); | 1046 | w1_fini_netlink(); |
966 | 1047 | ||
967 | kthread_stop(w1_control_thread); | ||
968 | |||
969 | driver_unregister(&w1_slave_driver); | 1048 | driver_unregister(&w1_slave_driver); |
970 | driver_unregister(&w1_master_driver); | 1049 | driver_unregister(&w1_master_driver); |
971 | bus_unregister(&w1_bus_type); | 1050 | bus_unregister(&w1_bus_type); |
diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h index f1df5343f4ad..cdaa6fffbfc7 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h | |||
@@ -46,7 +46,6 @@ struct w1_reg_num | |||
46 | #include "w1_family.h" | 46 | #include "w1_family.h" |
47 | 47 | ||
48 | #define W1_MAXNAMELEN 32 | 48 | #define W1_MAXNAMELEN 32 |
49 | #define W1_SLAVE_DATA_SIZE 128 | ||
50 | 49 | ||
51 | #define W1_SEARCH 0xF0 | 50 | #define W1_SEARCH 0xF0 |
52 | #define W1_ALARM_SEARCH 0xEC | 51 | #define W1_ALARM_SEARCH 0xEC |
@@ -77,7 +76,7 @@ struct w1_slave | |||
77 | struct completion released; | 76 | struct completion released; |
78 | }; | 77 | }; |
79 | 78 | ||
80 | typedef void (* w1_slave_found_callback)(void *, u64); | 79 | typedef void (*w1_slave_found_callback)(struct w1_master *, u64); |
81 | 80 | ||
82 | 81 | ||
83 | /** | 82 | /** |
@@ -142,12 +141,18 @@ struct w1_bus_master | |||
142 | */ | 141 | */ |
143 | u8 (*reset_bus)(void *); | 142 | u8 (*reset_bus)(void *); |
144 | 143 | ||
145 | /** Really nice hardware can handles the different types of ROM search */ | 144 | /** |
146 | void (*search)(void *, u8, w1_slave_found_callback); | 145 | * Put out a strong pull-up pulse of the specified duration. |
147 | }; | 146 | * @return -1=Error, 0=completed |
147 | */ | ||
148 | u8 (*set_pullup)(void *, int); | ||
148 | 149 | ||
149 | #define W1_MASTER_NEED_EXIT 0 | 150 | /** Really nice hardware can handles the different types of ROM search |
150 | #define W1_MASTER_NEED_RECONNECT 1 | 151 | * w1_master* is passed to the slave found callback. |
152 | */ | ||
153 | void (*search)(void *, struct w1_master *, | ||
154 | u8, w1_slave_found_callback); | ||
155 | }; | ||
151 | 156 | ||
152 | struct w1_master | 157 | struct w1_master |
153 | { | 158 | { |
@@ -167,7 +172,10 @@ struct w1_master | |||
167 | void *priv; | 172 | void *priv; |
168 | int priv_size; | 173 | int priv_size; |
169 | 174 | ||
170 | long flags; | 175 | /** 5V strong pullup enabled flag, 1 enabled, zero disabled. */ |
176 | int enable_pullup; | ||
177 | /** 5V strong pullup duration in milliseconds, zero disabled. */ | ||
178 | int pullup_duration; | ||
171 | 179 | ||
172 | struct task_struct *thread; | 180 | struct task_struct *thread; |
173 | struct mutex mutex; | 181 | struct mutex mutex; |
@@ -181,12 +189,21 @@ struct w1_master | |||
181 | }; | 189 | }; |
182 | 190 | ||
183 | int w1_create_master_attributes(struct w1_master *); | 191 | int w1_create_master_attributes(struct w1_master *); |
192 | void w1_destroy_master_attributes(struct w1_master *master); | ||
184 | void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb); | 193 | void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb); |
185 | void w1_search_devices(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb); | 194 | void w1_search_devices(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb); |
186 | struct w1_slave *w1_search_slave(struct w1_reg_num *id); | 195 | struct w1_slave *w1_search_slave(struct w1_reg_num *id); |
187 | void w1_search_process(struct w1_master *dev, u8 search_type); | 196 | void w1_search_process(struct w1_master *dev, u8 search_type); |
188 | struct w1_master *w1_search_master_id(u32 id); | 197 | struct w1_master *w1_search_master_id(u32 id); |
189 | 198 | ||
199 | /* Disconnect and reconnect devices in the given family. Used for finding | ||
200 | * unclaimed devices after a family has been registered or releasing devices | ||
201 | * after a family has been unregistered. Set attach to 1 when a new family | ||
202 | * has just been registered, to 0 when it has been unregistered. | ||
203 | */ | ||
204 | void w1_reconnect_slaves(struct w1_family *f, int attach); | ||
205 | void w1_slave_detach(struct w1_slave *sl); | ||
206 | |||
190 | u8 w1_triplet(struct w1_master *dev, int bdir); | 207 | u8 w1_triplet(struct w1_master *dev, int bdir); |
191 | void w1_write_8(struct w1_master *, u8); | 208 | void w1_write_8(struct w1_master *, u8); |
192 | int w1_reset_bus(struct w1_master *); | 209 | int w1_reset_bus(struct w1_master *); |
@@ -194,6 +211,7 @@ u8 w1_calc_crc8(u8 *, int); | |||
194 | void w1_write_block(struct w1_master *, const u8 *, int); | 211 | void w1_write_block(struct w1_master *, const u8 *, int); |
195 | u8 w1_read_block(struct w1_master *, u8 *, int); | 212 | u8 w1_read_block(struct w1_master *, u8 *, int); |
196 | int w1_reset_select_slave(struct w1_slave *sl); | 213 | int w1_reset_select_slave(struct w1_slave *sl); |
214 | void w1_next_pullup(struct w1_master *, int); | ||
197 | 215 | ||
198 | static inline struct w1_slave* dev_to_w1_slave(struct device *dev) | 216 | static inline struct w1_slave* dev_to_w1_slave(struct device *dev) |
199 | { | 217 | { |
diff --git a/drivers/w1/w1_family.c b/drivers/w1/w1_family.c index a3c95bd6890a..4a099041f28a 100644 --- a/drivers/w1/w1_family.c +++ b/drivers/w1/w1_family.c | |||
@@ -48,12 +48,12 @@ int w1_register_family(struct w1_family *newf) | |||
48 | 48 | ||
49 | if (!ret) { | 49 | if (!ret) { |
50 | atomic_set(&newf->refcnt, 0); | 50 | atomic_set(&newf->refcnt, 0); |
51 | newf->need_exit = 0; | ||
52 | list_add_tail(&newf->family_entry, &w1_families); | 51 | list_add_tail(&newf->family_entry, &w1_families); |
53 | } | 52 | } |
54 | spin_unlock(&w1_flock); | 53 | spin_unlock(&w1_flock); |
55 | 54 | ||
56 | w1_reconnect_slaves(newf); | 55 | /* check default devices against the new set of drivers */ |
56 | w1_reconnect_slaves(newf, 1); | ||
57 | 57 | ||
58 | return ret; | 58 | return ret; |
59 | } | 59 | } |
@@ -72,11 +72,11 @@ void w1_unregister_family(struct w1_family *fent) | |||
72 | break; | 72 | break; |
73 | } | 73 | } |
74 | } | 74 | } |
75 | |||
76 | fent->need_exit = 1; | ||
77 | |||
78 | spin_unlock(&w1_flock); | 75 | spin_unlock(&w1_flock); |
79 | 76 | ||
77 | /* deatch devices using this family code */ | ||
78 | w1_reconnect_slaves(fent, 0); | ||
79 | |||
80 | while (atomic_read(&fent->refcnt)) { | 80 | while (atomic_read(&fent->refcnt)) { |
81 | printk(KERN_INFO "Waiting for family %u to become free: refcnt=%d.\n", | 81 | printk(KERN_INFO "Waiting for family %u to become free: refcnt=%d.\n", |
82 | fent->fid, atomic_read(&fent->refcnt)); | 82 | fent->fid, atomic_read(&fent->refcnt)); |
@@ -109,8 +109,7 @@ struct w1_family * w1_family_registered(u8 fid) | |||
109 | 109 | ||
110 | static void __w1_family_put(struct w1_family *f) | 110 | static void __w1_family_put(struct w1_family *f) |
111 | { | 111 | { |
112 | if (atomic_dec_and_test(&f->refcnt)) | 112 | atomic_dec(&f->refcnt); |
113 | f->need_exit = 1; | ||
114 | } | 113 | } |
115 | 114 | ||
116 | void w1_family_put(struct w1_family *f) | 115 | void w1_family_put(struct w1_family *f) |
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h index ef1e1dafa19a..3ca1b9298f21 100644 --- a/drivers/w1/w1_family.h +++ b/drivers/w1/w1_family.h | |||
@@ -33,6 +33,7 @@ | |||
33 | #define W1_THERM_DS1822 0x22 | 33 | #define W1_THERM_DS1822 0x22 |
34 | #define W1_EEPROM_DS2433 0x23 | 34 | #define W1_EEPROM_DS2433 0x23 |
35 | #define W1_THERM_DS18B20 0x28 | 35 | #define W1_THERM_DS18B20 0x28 |
36 | #define W1_EEPROM_DS2431 0x2D | ||
36 | #define W1_FAMILY_DS2760 0x30 | 37 | #define W1_FAMILY_DS2760 0x30 |
37 | 38 | ||
38 | #define MAXNAMELEN 32 | 39 | #define MAXNAMELEN 32 |
@@ -53,7 +54,6 @@ struct w1_family | |||
53 | struct w1_family_ops *fops; | 54 | struct w1_family_ops *fops; |
54 | 55 | ||
55 | atomic_t refcnt; | 56 | atomic_t refcnt; |
56 | u8 need_exit; | ||
57 | }; | 57 | }; |
58 | 58 | ||
59 | extern spinlock_t w1_flock; | 59 | extern spinlock_t w1_flock; |
@@ -63,6 +63,5 @@ void __w1_family_get(struct w1_family *); | |||
63 | struct w1_family * w1_family_registered(u8); | 63 | struct w1_family * w1_family_registered(u8); |
64 | void w1_unregister_family(struct w1_family *); | 64 | void w1_unregister_family(struct w1_family *); |
65 | int w1_register_family(struct w1_family *); | 65 | int w1_register_family(struct w1_family *); |
66 | void w1_reconnect_slaves(struct w1_family *f); | ||
67 | 66 | ||
68 | #endif /* __W1_FAMILY_H */ | 67 | #endif /* __W1_FAMILY_H */ |
diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c index 6840dfebe4d4..a3a54567bfba 100644 --- a/drivers/w1/w1_int.c +++ b/drivers/w1/w1_int.c | |||
@@ -29,7 +29,11 @@ | |||
29 | #include "w1_netlink.h" | 29 | #include "w1_netlink.h" |
30 | #include "w1_int.h" | 30 | #include "w1_int.h" |
31 | 31 | ||
32 | static u32 w1_ids = 1; | 32 | static int w1_search_count = -1; /* Default is continual scan */ |
33 | module_param_named(search_count, w1_search_count, int, 0); | ||
34 | |||
35 | static int w1_enable_pullup = 1; | ||
36 | module_param_named(enable_pullup, w1_enable_pullup, int, 0); | ||
33 | 37 | ||
34 | static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl, | 38 | static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl, |
35 | struct device_driver *driver, | 39 | struct device_driver *driver, |
@@ -59,8 +63,12 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl, | |||
59 | dev->initialized = 0; | 63 | dev->initialized = 0; |
60 | dev->id = id; | 64 | dev->id = id; |
61 | dev->slave_ttl = slave_ttl; | 65 | dev->slave_ttl = slave_ttl; |
62 | dev->search_count = -1; /* continual scan */ | 66 | dev->search_count = w1_search_count; |
67 | dev->enable_pullup = w1_enable_pullup; | ||
63 | 68 | ||
69 | /* 1 for w1_process to decrement | ||
70 | * 1 for __w1_remove_master_device to decrement | ||
71 | */ | ||
64 | atomic_set(&dev->refcnt, 2); | 72 | atomic_set(&dev->refcnt, 2); |
65 | 73 | ||
66 | INIT_LIST_HEAD(&dev->slist); | 74 | INIT_LIST_HEAD(&dev->slist); |
@@ -93,9 +101,10 @@ static void w1_free_dev(struct w1_master *dev) | |||
93 | 101 | ||
94 | int w1_add_master_device(struct w1_bus_master *master) | 102 | int w1_add_master_device(struct w1_bus_master *master) |
95 | { | 103 | { |
96 | struct w1_master *dev; | 104 | struct w1_master *dev, *entry; |
97 | int retval = 0; | 105 | int retval = 0; |
98 | struct w1_netlink_msg msg; | 106 | struct w1_netlink_msg msg; |
107 | int id, found; | ||
99 | 108 | ||
100 | /* validate minimum functionality */ | 109 | /* validate minimum functionality */ |
101 | if (!(master->touch_bit && master->reset_bus) && | 110 | if (!(master->touch_bit && master->reset_bus) && |
@@ -104,10 +113,50 @@ int w1_add_master_device(struct w1_bus_master *master) | |||
104 | printk(KERN_ERR "w1_add_master_device: invalid function set\n"); | 113 | printk(KERN_ERR "w1_add_master_device: invalid function set\n"); |
105 | return(-EINVAL); | 114 | return(-EINVAL); |
106 | } | 115 | } |
116 | /* While it would be electrically possible to make a device that | ||
117 | * generated a strong pullup in bit bang mode, only hardare that | ||
118 | * controls 1-wire time frames are even expected to support a strong | ||
119 | * pullup. w1_io.c would need to support calling set_pullup before | ||
120 | * the last write_bit operation of a w1_write_8 which it currently | ||
121 | * doesn't. | ||
122 | */ | ||
123 | if (!master->write_byte && !master->touch_bit && master->set_pullup) { | ||
124 | printk(KERN_ERR "w1_add_master_device: set_pullup requires " | ||
125 | "write_byte or touch_bit, disabling\n"); | ||
126 | master->set_pullup = NULL; | ||
127 | } | ||
128 | |||
129 | /* Lock until the device is added (or not) to w1_masters. */ | ||
130 | mutex_lock(&w1_mlock); | ||
131 | /* Search for the first available id (starting at 1). */ | ||
132 | id = 0; | ||
133 | do { | ||
134 | ++id; | ||
135 | found = 0; | ||
136 | list_for_each_entry(entry, &w1_masters, w1_master_entry) { | ||
137 | if (entry->id == id) { | ||
138 | found = 1; | ||
139 | break; | ||
140 | } | ||
141 | } | ||
142 | } while (found); | ||
107 | 143 | ||
108 | dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, w1_max_slave_ttl, &w1_master_driver, &w1_master_device); | 144 | dev = w1_alloc_dev(id, w1_max_slave_count, w1_max_slave_ttl, |
109 | if (!dev) | 145 | &w1_master_driver, &w1_master_device); |
146 | if (!dev) { | ||
147 | mutex_unlock(&w1_mlock); | ||
110 | return -ENOMEM; | 148 | return -ENOMEM; |
149 | } | ||
150 | |||
151 | retval = w1_create_master_attributes(dev); | ||
152 | if (retval) { | ||
153 | mutex_unlock(&w1_mlock); | ||
154 | goto err_out_free_dev; | ||
155 | } | ||
156 | |||
157 | memcpy(dev->bus_master, master, sizeof(struct w1_bus_master)); | ||
158 | |||
159 | dev->initialized = 1; | ||
111 | 160 | ||
112 | dev->thread = kthread_run(&w1_process, dev, "%s", dev->name); | 161 | dev->thread = kthread_run(&w1_process, dev, "%s", dev->name); |
113 | if (IS_ERR(dev->thread)) { | 162 | if (IS_ERR(dev->thread)) { |
@@ -115,18 +164,10 @@ int w1_add_master_device(struct w1_bus_master *master) | |||
115 | dev_err(&dev->dev, | 164 | dev_err(&dev->dev, |
116 | "Failed to create new kernel thread. err=%d\n", | 165 | "Failed to create new kernel thread. err=%d\n", |
117 | retval); | 166 | retval); |
118 | goto err_out_free_dev; | 167 | mutex_unlock(&w1_mlock); |
168 | goto err_out_rm_attr; | ||
119 | } | 169 | } |
120 | 170 | ||
121 | retval = w1_create_master_attributes(dev); | ||
122 | if (retval) | ||
123 | goto err_out_kill_thread; | ||
124 | |||
125 | memcpy(dev->bus_master, master, sizeof(struct w1_bus_master)); | ||
126 | |||
127 | dev->initialized = 1; | ||
128 | |||
129 | mutex_lock(&w1_mlock); | ||
130 | list_add(&dev->w1_master_entry, &w1_masters); | 171 | list_add(&dev->w1_master_entry, &w1_masters); |
131 | mutex_unlock(&w1_mlock); | 172 | mutex_unlock(&w1_mlock); |
132 | 173 | ||
@@ -137,8 +178,12 @@ int w1_add_master_device(struct w1_bus_master *master) | |||
137 | 178 | ||
138 | return 0; | 179 | return 0; |
139 | 180 | ||
181 | #if 0 /* Thread cleanup code, not required currently. */ | ||
140 | err_out_kill_thread: | 182 | err_out_kill_thread: |
141 | kthread_stop(dev->thread); | 183 | kthread_stop(dev->thread); |
184 | #endif | ||
185 | err_out_rm_attr: | ||
186 | w1_destroy_master_attributes(dev); | ||
142 | err_out_free_dev: | 187 | err_out_free_dev: |
143 | w1_free_dev(dev); | 188 | w1_free_dev(dev); |
144 | 189 | ||
@@ -148,10 +193,21 @@ err_out_free_dev: | |||
148 | void __w1_remove_master_device(struct w1_master *dev) | 193 | void __w1_remove_master_device(struct w1_master *dev) |
149 | { | 194 | { |
150 | struct w1_netlink_msg msg; | 195 | struct w1_netlink_msg msg; |
196 | struct w1_slave *sl, *sln; | ||
151 | 197 | ||
152 | set_bit(W1_MASTER_NEED_EXIT, &dev->flags); | ||
153 | kthread_stop(dev->thread); | 198 | kthread_stop(dev->thread); |
154 | 199 | ||
200 | mutex_lock(&w1_mlock); | ||
201 | list_del(&dev->w1_master_entry); | ||
202 | mutex_unlock(&w1_mlock); | ||
203 | |||
204 | mutex_lock(&dev->mutex); | ||
205 | list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) | ||
206 | w1_slave_detach(sl); | ||
207 | w1_destroy_master_attributes(dev); | ||
208 | mutex_unlock(&dev->mutex); | ||
209 | atomic_dec(&dev->refcnt); | ||
210 | |||
155 | while (atomic_read(&dev->refcnt)) { | 211 | while (atomic_read(&dev->refcnt)) { |
156 | dev_info(&dev->dev, "Waiting for %s to become free: refcnt=%d.\n", | 212 | dev_info(&dev->dev, "Waiting for %s to become free: refcnt=%d.\n", |
157 | dev->name, atomic_read(&dev->refcnt)); | 213 | dev->name, atomic_read(&dev->refcnt)); |
diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c index 30b6fbf83bd4..f4f82f1f486e 100644 --- a/drivers/w1/w1_io.c +++ b/drivers/w1/w1_io.c | |||
@@ -93,6 +93,40 @@ static void w1_write_bit(struct w1_master *dev, int bit) | |||
93 | } | 93 | } |
94 | 94 | ||
95 | /** | 95 | /** |
96 | * Pre-write operation, currently only supporting strong pullups. | ||
97 | * Program the hardware for a strong pullup, if one has been requested and | ||
98 | * the hardware supports it. | ||
99 | * | ||
100 | * @param dev the master device | ||
101 | */ | ||
102 | static void w1_pre_write(struct w1_master *dev) | ||
103 | { | ||
104 | if (dev->pullup_duration && | ||
105 | dev->enable_pullup && dev->bus_master->set_pullup) { | ||
106 | dev->bus_master->set_pullup(dev->bus_master->data, | ||
107 | dev->pullup_duration); | ||
108 | } | ||
109 | } | ||
110 | |||
111 | /** | ||
112 | * Post-write operation, currently only supporting strong pullups. | ||
113 | * If a strong pullup was requested, clear it if the hardware supports | ||
114 | * them, or execute the delay otherwise, in either case clear the request. | ||
115 | * | ||
116 | * @param dev the master device | ||
117 | */ | ||
118 | static void w1_post_write(struct w1_master *dev) | ||
119 | { | ||
120 | if (dev->pullup_duration) { | ||
121 | if (dev->enable_pullup && dev->bus_master->set_pullup) | ||
122 | dev->bus_master->set_pullup(dev->bus_master->data, 0); | ||
123 | else | ||
124 | msleep(dev->pullup_duration); | ||
125 | dev->pullup_duration = 0; | ||
126 | } | ||
127 | } | ||
128 | |||
129 | /** | ||
96 | * Writes 8 bits. | 130 | * Writes 8 bits. |
97 | * | 131 | * |
98 | * @param dev the master device | 132 | * @param dev the master device |
@@ -102,11 +136,17 @@ void w1_write_8(struct w1_master *dev, u8 byte) | |||
102 | { | 136 | { |
103 | int i; | 137 | int i; |
104 | 138 | ||
105 | if (dev->bus_master->write_byte) | 139 | if (dev->bus_master->write_byte) { |
140 | w1_pre_write(dev); | ||
106 | dev->bus_master->write_byte(dev->bus_master->data, byte); | 141 | dev->bus_master->write_byte(dev->bus_master->data, byte); |
142 | } | ||
107 | else | 143 | else |
108 | for (i = 0; i < 8; ++i) | 144 | for (i = 0; i < 8; ++i) { |
145 | if (i == 7) | ||
146 | w1_pre_write(dev); | ||
109 | w1_touch_bit(dev, (byte >> i) & 0x1); | 147 | w1_touch_bit(dev, (byte >> i) & 0x1); |
148 | } | ||
149 | w1_post_write(dev); | ||
110 | } | 150 | } |
111 | EXPORT_SYMBOL_GPL(w1_write_8); | 151 | EXPORT_SYMBOL_GPL(w1_write_8); |
112 | 152 | ||
@@ -203,11 +243,14 @@ void w1_write_block(struct w1_master *dev, const u8 *buf, int len) | |||
203 | { | 243 | { |
204 | int i; | 244 | int i; |
205 | 245 | ||
206 | if (dev->bus_master->write_block) | 246 | if (dev->bus_master->write_block) { |
247 | w1_pre_write(dev); | ||
207 | dev->bus_master->write_block(dev->bus_master->data, buf, len); | 248 | dev->bus_master->write_block(dev->bus_master->data, buf, len); |
249 | } | ||
208 | else | 250 | else |
209 | for (i = 0; i < len; ++i) | 251 | for (i = 0; i < len; ++i) |
210 | w1_write_8(dev, buf[i]); | 252 | w1_write_8(dev, buf[i]); /* calls w1_pre_write */ |
253 | w1_post_write(dev); | ||
211 | } | 254 | } |
212 | EXPORT_SYMBOL_GPL(w1_write_block); | 255 | EXPORT_SYMBOL_GPL(w1_write_block); |
213 | 256 | ||
@@ -250,12 +293,24 @@ int w1_reset_bus(struct w1_master *dev) | |||
250 | result = dev->bus_master->reset_bus(dev->bus_master->data) & 0x1; | 293 | result = dev->bus_master->reset_bus(dev->bus_master->data) & 0x1; |
251 | else { | 294 | else { |
252 | dev->bus_master->write_bit(dev->bus_master->data, 0); | 295 | dev->bus_master->write_bit(dev->bus_master->data, 0); |
296 | /* minimum 480, max ? us | ||
297 | * be nice and sleep, except 18b20 spec lists 960us maximum, | ||
298 | * so until we can sleep with microsecond accuracy, spin. | ||
299 | * Feel free to come up with some other way to give up the | ||
300 | * cpu for such a short amount of time AND get it back in | ||
301 | * the maximum amount of time. | ||
302 | */ | ||
253 | w1_delay(480); | 303 | w1_delay(480); |
254 | dev->bus_master->write_bit(dev->bus_master->data, 1); | 304 | dev->bus_master->write_bit(dev->bus_master->data, 1); |
255 | w1_delay(70); | 305 | w1_delay(70); |
256 | 306 | ||
257 | result = dev->bus_master->read_bit(dev->bus_master->data) & 0x1; | 307 | result = dev->bus_master->read_bit(dev->bus_master->data) & 0x1; |
258 | w1_delay(410); | 308 | /* minmum 70 (above) + 410 = 480 us |
309 | * There aren't any timing requirements between a reset and | ||
310 | * the following transactions. Sleeping is safe here. | ||
311 | */ | ||
312 | /* w1_delay(410); min required time */ | ||
313 | msleep(1); | ||
259 | } | 314 | } |
260 | 315 | ||
261 | return result; | 316 | return result; |
@@ -277,7 +332,8 @@ void w1_search_devices(struct w1_master *dev, u8 search_type, w1_slave_found_cal | |||
277 | { | 332 | { |
278 | dev->attempts++; | 333 | dev->attempts++; |
279 | if (dev->bus_master->search) | 334 | if (dev->bus_master->search) |
280 | dev->bus_master->search(dev->bus_master->data, search_type, cb); | 335 | dev->bus_master->search(dev->bus_master->data, dev, |
336 | search_type, cb); | ||
281 | else | 337 | else |
282 | w1_search(dev, search_type, cb); | 338 | w1_search(dev, search_type, cb); |
283 | } | 339 | } |
@@ -305,3 +361,20 @@ int w1_reset_select_slave(struct w1_slave *sl) | |||
305 | return 0; | 361 | return 0; |
306 | } | 362 | } |
307 | EXPORT_SYMBOL_GPL(w1_reset_select_slave); | 363 | EXPORT_SYMBOL_GPL(w1_reset_select_slave); |
364 | |||
365 | /** | ||
366 | * Put out a strong pull-up of the specified duration after the next write | ||
367 | * operation. Not all hardware supports strong pullups. Hardware that | ||
368 | * doesn't support strong pullups will sleep for the given time after the | ||
369 | * write operation without a strong pullup. This is a one shot request for | ||
370 | * the next write, specifying zero will clear a previous request. | ||
371 | * The w1 master lock must be held. | ||
372 | * | ||
373 | * @param delay time in milliseconds | ||
374 | * @return 0=success, anything else=error | ||
375 | */ | ||
376 | void w1_next_pullup(struct w1_master *dev, int delay) | ||
377 | { | ||
378 | dev->pullup_duration = delay; | ||
379 | } | ||
380 | EXPORT_SYMBOL_GPL(w1_next_pullup); | ||